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

Commit 0d54950

Browse files
Michel Boudreaumboudreau
Michel Boudreau
authored andcommitted
Adding ng-jq functionality, the ability to force jqLite or any other library by name to be used for angular.element
fixing linting and jshint comments, as per @mzgol request fixing weird duplication of docs when merging adding other ng prefixes to be added and test to jq(), fixing documentation error by adding @module ng, changing @element to be any removing tabs, again. removing jq._name = undefined; as not useful anymore adding strict equality for tests Adding better description of ng-jq, fixing tabs/spaces changing the logic behind ngJq to be more robust; removing jQuery = window[jqName] for when jqName is empty string replacing tabs for spaces
1 parent 0d42426 commit 0d54950

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,
@@ -899,7 +900,61 @@ var csp = function() {
899900
return (csp.isActive_ = active);
900901
};
901902

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

951+
var name;
952+
if (el) {
953+
name = getNgAttribute(el, "jq");
954+
}
955+
956+
return (jq.name_ = name);
957+
};
903958

904959
function concat(array1, array2, index) {
905960
return array1.concat(slice.call(array2, index));
@@ -1472,7 +1527,12 @@ function bindJQuery() {
14721527
}
14731528

14741529
// bind to jQuery if present;
1475-
jQuery = window.jQuery;
1530+
var jqName = jq();
1531+
jQuery = window.jQuery; // use default jQuery.
1532+
if (isDefined(jqName)) { // `ngJq` present
1533+
jQuery = jqName === null ? undefined : window[jqName]; // if empty; use jqLite. if not empty, use jQuery specified by `ngJq`.
1534+
}
1535+
14761536
// Use jQuery if it exists with proper functionality, otherwise default to us.
14771537
// Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
14781538
// 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)