diff --git a/src/Angular.js b/src/Angular.js index 678c6fe12484..bf541d39f459 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -931,7 +931,19 @@ var csp = function() { return (csp.isActive_ = active); }; +var jq = function() { + if (isDefined(jq.name_)) return jq.name_; + var el = document.querySelector('[ng-jq]') || + document.querySelector('[data-ng-jq]'); + var name = null; + + 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)); @@ -1448,7 +1460,7 @@ function bindJQuery() { } // bind to jQuery if present; - jQuery = window.jQuery; + jQuery = jq() !== null ? window[jq()] : window.jQuery; // Use jQuery if it exists with proper functionality, otherwise default to us. // Angular 1.2+ requires jQuery 1.7+ for on()/off() support. // Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older @@ -1467,7 +1479,7 @@ function bindJQuery() { // are passed through jQuery.cleanData. Monkey-patch this method to fire // the $destroy event on all removed nodes. originalCleanData = jQuery.cleanData; - jQuery.cleanData = function(elems) { + jQuery.cleanData = function (elems) { if (!skipDestroyOnNextJQueryCleanData) { for (var i = 0, elem; (elem = elems[i]) != null; i++) { jQuery(elem).triggerHandler('$destroy'); diff --git a/test/AngularSpec.js b/test/AngularSpec.js index 878eb9567d63..6c97456a25d3 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -454,6 +454,57 @@ describe('angular', function() { }); }); + describe('jq', function() { + + var element; + + beforeEach(function() { + element = document.createElement('html'); + }); + + afterEach(function() { + delete jq.name_; + }); + + it('should return null when jq is not set (the default)', function() { + expect(jq()).toBe(null); + }); + + 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() {