From 9b7b0fc7dbabab41313c17acf8642e69efccce2a Mon Sep 17 00:00:00 2001 From: Michel Boudreau Date: Wed, 14 Jan 2015 22:07:55 +1100 Subject: [PATCH] Adding ng-jq functionality, the ability to choose your angular.element library or force jqLite even if jquery is available. --- src/Angular.js | 32 +++++++++++++++++++++++++++- test/AngularSpec.js | 51 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/Angular.js b/src/Angular.js index b7d77437c070..7e730810275b 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -767,6 +767,36 @@ function equals(o1, o2) { return false; } +/** + * @ngdoc directive + * @name ng.directive:ngJq + * + * @element html + * @param {string} (optional) the name of the library available under `window` to be used for angular.element + * + * @description + * + * Use this directive to force the angular.element library. This should be used to force + * either jqLite by leaving ng-jq blank or setting the name of the jquery variable under window + * (eg. jQuery). + * + * This directive is global for the whole of the angular library, hence the directive can only + * be added to the top-most HTML element. + * + */ +var jq = function () { + if (isDefined(jq.name_)) return jq.name_; + + var el = document.querySelector('[ng-jq]') || document.querySelector('[data-ng-jq]'); + var name = undefined; + + if (el) { + name = el.getAttribute('ng-jq') || el.getAttribute('data-ng-jq') || ''; + } + + return (jq.name_ = name); +}; + function concat(array1, array2, index) { return array1.concat(slice.call(array2, index)); @@ -1147,7 +1177,7 @@ function snake_case(name, separator){ function bindJQuery() { // bind to jQuery if present; - jQuery = window.jQuery; + jQuery = jq() ? window[jq()] : window.jQuery; // reset to jQuery or default to us. if (jQuery) { jqLite = jQuery; diff --git a/test/AngularSpec.js b/test/AngularSpec.js index 62ea31d9f1ab..6e3217c081ab 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -347,6 +347,57 @@ describe('angular', function() { }); }); + describe('jq', function () { + + var element; + + beforeEach(function () { + element = document.createElement('html'); + }); + + afterEach(function () { + jq.name_ = undefined; + delete jq.name_; + }); + + it('should return undefined when jq is not set (the default)', function () { + expect(jq()).toBe(undefined); + }); + + it('should return empty string when jq is enabled manually via [ng-jq] with empty string', function () { + element.setAttribute('ng-jq', ''); + spyOn(document, 'querySelector').andCallFake(function (selector) { + if (selector == '[ng-jq]') return element; + }); + expect(jq()).toBe(''); + }); + + it('should return empty string when jq is enabled manually via [data-ng-jq] with empty string', function () { + element.setAttribute('data-ng-jq', ''); + spyOn(document, 'querySelector').andCallFake(function (selector) { + if (selector == '[data-ng-jq]') return element; + }); + expect(jq()).toBe(''); + expect(document.querySelector).toHaveBeenCalledWith('[data-ng-jq]'); + }); + + it('should return "jquery" when jq is enabled manually via [ng-jq] with value "jquery"', function () { + element.setAttribute('ng-jq', 'jquery'); + spyOn(document, 'querySelector').andCallFake(function (selector) { + if (selector == '[ng-jq]') return element; + }); + expect(jq()).toBe('jquery'); + }); + + it('should return "jquery" when jq is enabled manually via [data-ng-jq] with value "jquery"', function () { + element.setAttribute('data-ng-jq', 'jquery'); + spyOn(document, 'querySelector').andCallFake(function (selector) { + if (selector == '[data-ng-jq]') return element; + }); + expect(jq()).toBe('jquery'); + expect(document.querySelector).toHaveBeenCalledWith('[data-ng-jq]'); + }); + }); describe('parseKeyValue', function() { it('should parse a string into key-value pairs', function() {