Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 09ee82d

Browse files
Michel Boudreaulgalfaso
Michel Boudreau
authored andcommitted
feat(ng-jq): adds the ability to force jqLite or a specific jQuery version
Adds the ability to specify that jqLite should be used or to use a specific jQuery version
1 parent c1cf053 commit 09ee82d

File tree

3 files changed

+150
-1
lines changed

3 files changed

+150
-1
lines changed

src/Angular.js

+61-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
shallowCopy: true,
5959
equals: true,
6060
csp: true,
61+
jq: true,
6162
concat: true,
6263
sliceArgs: true,
6364
bind: true,
@@ -901,7 +902,61 @@ var csp = function() {
901902
return (csp.isActive_ = active);
902903
};
903904

905+
/**
906+
* @ngdoc directive
907+
* @module ng
908+
* @name ngJq
909+
*
910+
* @element ANY
911+
* @param {string=} the name of the library available under `window`
912+
* to be used for angular.element
913+
* @description
914+
* Use this directive to force the angular.element library. This should be
915+
* used to force either jqLite by leaving ng-jq blank or setting the name of
916+
* the jquery variable under window (eg. jQuery).
917+
*
918+
* Since this directive is global for the angular library, it is recommended
919+
* that it's added to the same element as ng-app or the HTML element, but it is not mandatory.
920+
* It needs to be noted that only the first instance of `ng-jq` will be used and all others
921+
* ignored.
922+
*
923+
* @example
924+
* This example shows how to force jqLite using the `ngJq` directive to the `html` tag.
925+
```html
926+
<!doctype html>
927+
<html ng-app ng-jq>
928+
...
929+
...
930+
</html>
931+
```
932+
* @example
933+
* This example shows how to use a jQuery based library of a different name.
934+
* The library name must be available at the top most 'window'.
935+
```html
936+
<!doctype html>
937+
<html ng-app ng-jq="jQueryLib">
938+
...
939+
...
940+
</html>
941+
```
942+
*/
943+
var jq = function() {
944+
if (isDefined(jq.name_)) return jq.name_;
945+
var el;
946+
var i, ii = ngAttrPrefixes.length;
947+
for (i = 0; i < ii; ++i) {
948+
if (el = document.querySelector('[' + ngAttrPrefixes[i].replace(':', '\\:') + 'jq]')) {
949+
break;
950+
}
951+
}
904952

953+
var name;
954+
if (el) {
955+
name = getNgAttribute(el, "jq");
956+
}
957+
958+
return (jq.name_ = name);
959+
};
905960

906961
function concat(array1, array2, index) {
907962
return array1.concat(slice.call(array2, index));
@@ -1474,7 +1529,12 @@ function bindJQuery() {
14741529
}
14751530

14761531
// bind to jQuery if present;
1477-
jQuery = window.jQuery;
1532+
var jqName = jq();
1533+
jQuery = window.jQuery; // use default jQuery.
1534+
if (isDefined(jqName)) { // `ngJq` present
1535+
jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`.
1536+
}
1537+
14781538
// Use jQuery if it exists with proper functionality, otherwise default to us.
14791539
// Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
14801540
// Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older

test/.jshintrc

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"shallowCopy": false,
6161
"equals": false,
6262
"csp": false,
63+
"jq": false,
6364
"concat": false,
6465
"sliceArgs": false,
6566
"bind": false,

test/AngularSpec.js

+88
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,94 @@ describe('angular', function() {
615615
});
616616

617617

618+
describe('jq', function() {
619+
var element;
620+
621+
beforeEach(function() {
622+
element = document.createElement('html');
623+
});
624+
625+
afterEach(function() {
626+
delete jq.name_;
627+
});
628+
629+
it('should return undefined when jq is not set, no jQuery found (the default)', function() {
630+
expect(jq()).toBe(undefined);
631+
});
632+
633+
it('should return empty string when jq is enabled manually via [ng-jq] with empty string', function() {
634+
element.setAttribute('ng-jq', '');
635+
spyOn(document, 'querySelector').andCallFake(function(selector) {
636+
if (selector === '[ng-jq]') return element;
637+
});
638+
expect(jq()).toBe('');
639+
});
640+
641+
it('should return empty string when jq is enabled manually via [data-ng-jq] with empty string', function() {
642+
element.setAttribute('data-ng-jq', '');
643+
spyOn(document, 'querySelector').andCallFake(function(selector) {
644+
if (selector === '[data-ng-jq]') return element;
645+
});
646+
expect(jq()).toBe('');
647+
expect(document.querySelector).toHaveBeenCalledWith('[data-ng-jq]');
648+
});
649+
650+
it('should return empty string when jq is enabled manually via [x-ng-jq] with empty string', function() {
651+
element.setAttribute('x-ng-jq', '');
652+
spyOn(document, 'querySelector').andCallFake(function(selector) {
653+
if (selector === '[x-ng-jq]') return element;
654+
});
655+
expect(jq()).toBe('');
656+
expect(document.querySelector).toHaveBeenCalledWith('[x-ng-jq]');
657+
});
658+
659+
it('should return empty string when jq is enabled manually via [ng:jq] with empty string', function() {
660+
element.setAttribute('ng:jq', '');
661+
spyOn(document, 'querySelector').andCallFake(function(selector) {
662+
if (selector === '[ng\\:jq]') return element;
663+
});
664+
expect(jq()).toBe('');
665+
expect(document.querySelector).toHaveBeenCalledWith('[ng\\:jq]');
666+
});
667+
668+
it('should return "jQuery" when jq is enabled manually via [ng-jq] with value "jQuery"', function() {
669+
element.setAttribute('ng-jq', 'jQuery');
670+
spyOn(document, 'querySelector').andCallFake(function(selector) {
671+
if (selector === '[ng-jq]') return element;
672+
});
673+
expect(jq()).toBe('jQuery');
674+
expect(document.querySelector).toHaveBeenCalledWith('[ng-jq]');
675+
});
676+
677+
it('should return "jQuery" when jq is enabled manually via [data-ng-jq] with value "jQuery"', function() {
678+
element.setAttribute('data-ng-jq', 'jQuery');
679+
spyOn(document, 'querySelector').andCallFake(function(selector) {
680+
if (selector === '[data-ng-jq]') return element;
681+
});
682+
expect(jq()).toBe('jQuery');
683+
expect(document.querySelector).toHaveBeenCalledWith('[data-ng-jq]');
684+
});
685+
686+
it('should return "jQuery" when jq is enabled manually via [x-ng-jq] with value "jQuery"', function() {
687+
element.setAttribute('x-ng-jq', 'jQuery');
688+
spyOn(document, 'querySelector').andCallFake(function(selector) {
689+
if (selector === '[x-ng-jq]') return element;
690+
});
691+
expect(jq()).toBe('jQuery');
692+
expect(document.querySelector).toHaveBeenCalledWith('[x-ng-jq]');
693+
});
694+
695+
it('should return "jQuery" when jq is enabled manually via [ng:jq] with value "jQuery"', function() {
696+
element.setAttribute('ng:jq', 'jQuery');
697+
spyOn(document, 'querySelector').andCallFake(function(selector) {
698+
if (selector === '[ng\\:jq]') return element;
699+
});
700+
expect(jq()).toBe('jQuery');
701+
expect(document.querySelector).toHaveBeenCalledWith('[ng\\:jq]');
702+
});
703+
});
704+
705+
618706
describe('parseKeyValue', function() {
619707
it('should parse a string into key-value pairs', function() {
620708
expect(parseKeyValue('')).toEqual({});

0 commit comments

Comments
 (0)