diff --git a/docs/content/guide/bootstrap.ngdoc b/docs/content/guide/bootstrap.ngdoc index 2a3c2ebc90e4..423e9bb11937 100644 --- a/docs/content/guide/bootstrap.ngdoc +++ b/docs/content/guide/bootstrap.ngdoc @@ -38,11 +38,7 @@ initialization. - 3. If you require IE7 support add `id="ng-app"` - - - - 4. If you choose to use the old style directive syntax `ng:` then include xml-namespace in `html` + 3. If you choose to use the old style directive syntax `ng:` then include xml-namespace in `html` to make IE happy. (This is here for historical reasons, and we no longer recommend use of `ng:`.) diff --git a/src/Angular.js b/src/Angular.js index eaaf2f37bc75..e0f14c228f8a 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -1301,46 +1301,26 @@ function getNgAttribute(element, ngAttr) { */ function angularInit(element, bootstrap) { - var elements = [element], - appElement, + var appElement, module, - config = {}, - names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'], - options = { - 'boolean': ['strict-di'] - }, - NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/; - - function append(element) { - element && elements.push(element); - } + config = {}; + + // The element `element` has priority over any other element + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + 'app'; - forEach(names, function(name) { - names[name] = true; - append(document.getElementById(name)); - name = name.replace(':', '\\:'); - if (element.querySelectorAll) { - forEach(element.querySelectorAll('.' + name), append); - forEach(element.querySelectorAll('.' + name + '\\:'), append); - forEach(element.querySelectorAll('[' + name + ']'), append); + if (!appElement && element.hasAttribute && element.hasAttribute(name)) { + appElement = element; + module = element.getAttribute(name); } }); + forEach(ngAttrPrefixes, function(prefix) { + var name = prefix + 'app'; + var candidate; - forEach(elements, function(element) { - if (!appElement) { - var className = ' ' + element.className + ' '; - var match = NG_APP_CLASS_REGEXP.exec(className); - if (match) { - appElement = element; - module = (match[2] || '').replace(/\s+/g, ','); - } else { - forEach(element.attributes, function(attr) { - if (!appElement && names[attr.name]) { - appElement = element; - module = attr.value; - } - }); - } + if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) { + appElement = candidate; + module = candidate.getAttribute(name); } }); if (appElement) { diff --git a/test/AngularSpec.js b/test/AngularSpec.js index 6a74c6c615b9..a609aa813c08 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -710,16 +710,14 @@ describe('angular', function() { beforeEach(function() { element = { - getElementById: function (id) { - return element.getElementById[id] || []; + hasAttribute: function (name) { + return !!element[name]; }, - - querySelectorAll: function(arg) { - return element.querySelectorAll[arg] || []; + querySelector: function(arg) { + return element.querySelector[arg] || null; }, - getAttribute: function(name) { return element[name]; } @@ -736,23 +734,7 @@ describe('angular', function() { it('should look for ngApp directive as attr', function() { var appElement = jqLite('
')[0]; - element.querySelectorAll['[ng-app]'] = [appElement]; - angularInit(element, bootstrapSpy); - expect(bootstrapSpy).toHaveBeenCalledOnceWith(appElement, ['ABC'], jasmine.any(Object)); - }); - - - it('should look for ngApp directive in id', function() { - var appElement = jqLite('')[0]; - jqLite(document.body).append(appElement); - angularInit(element, bootstrapSpy); - expect(bootstrapSpy).toHaveBeenCalledOnceWith(appElement, ['ABC'], jasmine.any(Object)); - }); - - - it('should look for ngApp directive in className', function() { - var appElement = jqLite('')[0]; - element.querySelectorAll['.ng\\:app'] = [appElement]; + element.querySelector['[ng-app]'] = appElement; angularInit(element, bootstrapSpy); expect(bootstrapSpy).toHaveBeenCalledOnceWith(appElement, ['ABC'], jasmine.any(Object)); }); @@ -760,36 +742,22 @@ describe('angular', function() { it('should look for ngApp directive using querySelectorAll', function() { var appElement = jqLite('')[0]; - element.querySelectorAll['[ng\\:app]'] = [ appElement ]; + element.querySelector['[x-ng-app]'] = appElement; angularInit(element, bootstrapSpy); expect(bootstrapSpy).toHaveBeenCalledOnceWith(appElement, ['ABC'], jasmine.any(Object)); }); - it('should bootstrap using class name', function() { - var appElement = jqLite('')[0]; - angularInit(jqLite('').append(appElement)[0], bootstrapSpy); - expect(bootstrapSpy).toHaveBeenCalledOnceWith(appElement, ['ABC'], jasmine.any(Object)); - }); - - it('should bootstrap anonymously', function() { var appElement = jqLite('')[0]; - element.querySelectorAll['[x-ng-app]'] = [ appElement ]; + element.querySelector['[x-ng-app]'] = appElement; angularInit(element, bootstrapSpy); expect(bootstrapSpy).toHaveBeenCalledOnceWith(appElement, [], jasmine.any(Object)); }); - it('should bootstrap anonymously using class only', function() { - var appElement = jqLite('')[0]; - angularInit(jqLite('').append(appElement)[0], bootstrapSpy); - expect(bootstrapSpy).toHaveBeenCalledOnceWith(appElement, [], jasmine.any(Object)); - }); - - it('should bootstrap if the annotation is on the root element', function() { - var appElement = jqLite('')[0]; + var appElement = jqLite('')[0]; angularInit(appElement, bootstrapSpy); expect(bootstrapSpy).toHaveBeenCalledOnceWith(appElement, [], jasmine.any(Object)); }); @@ -836,7 +804,7 @@ describe('angular', function() { it('should bootstrap in strict mode when ng-strict-di attribute is specified', function() { bootstrapSpy = spyOn(angular, 'bootstrap').andCallThrough(); - var appElement = jqLite(''); + var appElement = jqLite(''); angularInit(jqLite('').append(appElement[0])[0], bootstrapSpy); expect(bootstrapSpy).toHaveBeenCalledOnce(); expect(bootstrapSpy.mostRecentCall.args[2].strictDi).toBe(true);