From af7c51ee1d010a650e4f524467d5ee7c82cc24b5 Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Tue, 25 Oct 2011 09:09:32 -0700 Subject: [PATCH 1/4] style(Angular.js): various code style fixes --- src/Angular.js | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Angular.js b/src/Angular.js index 256a119c1308..c5a35e4e6119 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -14,7 +14,7 @@ if (typeof document.getAttribute == $undefined) * @param {string} string String to be converted to lowercase. * @returns {string} Lowercased string. */ -var lowercase = function(string){ return isString(string) ? string.toLowerCase() : string; }; +var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;}; /** @@ -26,17 +26,17 @@ var lowercase = function(string){ return isString(string) ? string.toLowerCase() * @param {string} string String to be converted to uppercase. * @returns {string} Uppercased string. */ -var uppercase = function(string){ return isString(string) ? string.toUpperCase() : string; }; +var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;}; var manualLowercase = function(s) { return isString(s) - ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32); }) + ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);}) : s; }; var manualUppercase = function(s) { return isString(s) - ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32); }) + ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);}) : s; }; @@ -49,12 +49,12 @@ if ('i' !== 'I'.toLowerCase()) { uppercase = manualUppercase; } -function fromCharCode(code) { return String.fromCharCode(code); } +function fromCharCode(code) {return String.fromCharCode(code);} /** * Creates the element for IE8 and below to allow styling of widgets - * (http://ejohn.org/blog/html5-shiv/). This hack works only if angular is - * included synchronously at the top of the document before IE sees any + * (http://ejohn.org/blog/html5-shiv/). This hack works only if angular is + * included synchronously at the top of the document before IE sees any * unknown elements. See regression/issue-584.html. * * @param {string} elementName Name of the widget. @@ -295,7 +295,7 @@ function noop() {} function identity($) {return $;} -function valueFn(value) {return function() { return value; };} +function valueFn(value) {return function() {return value;};} function extensionMap(angular, name, transform) { var extPoint; @@ -319,7 +319,7 @@ function extensionMap(angular, name, transform) { * @param {*} value Reference to check. * @returns {boolean} True if `value` is undefined. */ -function isUndefined(value){ return typeof value == $undefined; } +function isUndefined(value){return typeof value == $undefined;} /** @@ -333,7 +333,7 @@ function isUndefined(value){ return typeof value == $undefined; } * @param {*} value Reference to check. * @returns {boolean} True if `value` is defined. */ -function isDefined(value){ return typeof value != $undefined; } +function isDefined(value){return typeof value != $undefined;} /** @@ -348,7 +348,7 @@ function isDefined(value){ return typeof value != $undefined; } * @param {*} value Reference to check. * @returns {boolean} True if `value` is an `Object` but not `null`. */ -function isObject(value){ return value!=null && typeof value == $object;} +function isObject(value){return value!=null && typeof value == $object;} /** @@ -362,7 +362,7 @@ function isObject(value){ return value!=null && typeof value == $object;} * @param {*} value Reference to check. * @returns {boolean} True if `value` is a `String`. */ -function isString(value){ return typeof value == $string;} +function isString(value){return typeof value == $string;} /** @@ -376,7 +376,7 @@ function isString(value){ return typeof value == $string;} * @param {*} value Reference to check. * @returns {boolean} True if `value` is a `Number`. */ -function isNumber(value){ return typeof value == $number;} +function isNumber(value){return typeof value == $number;} /** @@ -390,7 +390,7 @@ function isNumber(value){ return typeof value == $number;} * @param {*} value Reference to check. * @returns {boolean} True if `value` is a `Date`. */ -function isDate(value){ return value instanceof Date; } +function isDate(value){return value instanceof Date;} /** @@ -404,7 +404,7 @@ function isDate(value){ return value instanceof Date; } * @param {*} value Reference to check. * @returns {boolean} True if `value` is an `Array`. */ -function isArray(value) { return value instanceof Array; } +function isArray(value) {return value instanceof Array;} /** @@ -418,7 +418,7 @@ function isArray(value) { return value instanceof Array; } * @param {*} value Reference to check. * @returns {boolean} True if `value` is a `Function`. */ -function isFunction(value){ return typeof value == 'function';} +function isFunction(value){return typeof value == 'function';} /** @@ -432,8 +432,8 @@ function isWindow(obj) { return obj && obj.document && obj.location && obj.alert && obj.setInterval; } -function isBoolean(value) { return typeof value == $boolean; } -function isTextNode(node) { return nodeName_(node) == '#text'; } +function isBoolean(value) {return typeof value == $boolean;} +function isTextNode(node) {return nodeName_(node) == '#text';} function trim(value) { return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; From 578e38e0af7ff49b2ba942301752f0b16c14875a Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Wed, 26 Oct 2011 00:16:21 -0700 Subject: [PATCH 2/4] fix(example): fixes for personalLog e2e tests Looks like this got broken with scope rewrite. --- .../personalLog/scenario/personalLogScenario.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/example/personalLog/scenario/personalLogScenario.js b/example/personalLog/scenario/personalLogScenario.js index fe6388b4e299..355761bd09f2 100644 --- a/example/personalLog/scenario/personalLogScenario.js +++ b/example/personalLog/scenario/personalLogScenario.js @@ -16,7 +16,7 @@ describe('personal log', function() { element('form input[type="submit"]').click(); expect(repeater('ul li').count()).toEqual(1); - expect(repeater('ul li').column('log.msg')).toEqual('my first message'); + expect(repeater('ul li').column('log.msg')).toEqual(['my first message']); //create second msg input('newMsg').enter('my second message'); @@ -38,7 +38,7 @@ describe('personal log', function() { element('ul li a:eq(1)').click(); expect(repeater('ul li').count()).toEqual(1); - expect(repeater('ul li').column('log.msg')).toEqual('my second message'); + expect(repeater('ul li').column('log.msg')).toEqual(['my second message']); element('ul li a:eq(0)').click(); expect(repeater('ul li').count()).toEqual(0); @@ -66,7 +66,7 @@ describe('personal log', function() { browser().reload(); - expect(repeater('ul li').column('log.msg')).toEqual('my persistent message'); + expect(repeater('ul li').column('log.msg')).toEqual(['my persistent message']); expect(repeater('ul li').count()).toEqual(1); }); }); @@ -85,10 +85,11 @@ angular.scenario.dsl('clearCookies', function() { $cookies = rootScope.$service('$cookies'), cookieName; - for (cookieName in $cookies) { - delete $cookies[cookieName]; - } - rootScope.$eval(); + rootScope.$apply(function() { + for (cookieName in $cookies) { + delete $cookies[cookieName]; + } + }); done(); }); From 950d02b4d4b1d574dfbb9bbdd56b8dc430db0a93 Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Tue, 25 Oct 2011 12:02:20 -0700 Subject: [PATCH 3/4] fix(docs): remove unused $browser dependency --- docs/src/templates/docs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/templates/docs.js b/docs/src/templates/docs.js index 78b5a6585206..6ca6bdcf9b4e 100644 --- a/docs/src/templates/docs.js +++ b/docs/src/templates/docs.js @@ -1,5 +1,5 @@ -DocsController.$inject = ['$location', '$browser', '$window', '$cookies']; -function DocsController($location, $browser, $window, $cookies) { +DocsController.$inject = ['$location', '$window', '$cookies']; +function DocsController($location, $window, $cookies) { window.$root = this.$root; var scope = this, From d7ba5bc83ba9a8937384ea677331c5156ed6772d Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Tue, 25 Oct 2011 08:47:02 -0700 Subject: [PATCH 4/4] feat(bootstrap): drop angular.js file name restrictions for autobind The last script element in the dom is always us if the script that contains angular is loaded synchronously. For async loading manual bootstrap needs to be performed. Close #621 --- .../dev_guide.bootstrap.auto_bootstrap.ngdoc | 33 ++-- src/Angular.js | 40 ++--- src/angular-bootstrap.js | 4 +- src/angular.suffix | 4 +- test/AngularSpec.js | 164 +++++------------- 5 files changed, 78 insertions(+), 167 deletions(-) diff --git a/docs/content/guide/dev_guide.bootstrap.auto_bootstrap.ngdoc b/docs/content/guide/dev_guide.bootstrap.auto_bootstrap.ngdoc index 10466d5ec0c4..438b3d3889ad 100644 --- a/docs/content/guide/dev_guide.bootstrap.auto_bootstrap.ngdoc +++ b/docs/content/guide/dev_guide.bootstrap.auto_bootstrap.ngdoc @@ -53,8 +53,7 @@ appending `#autobind` to the ` +
@@ -67,22 +66,24 @@ appending `#autobind` to the ` + + +
+ Hello {{'world'}}! +
+ + + -Optionally, any of the filename formats above can be prepended with a relative or absolute URL that -ends with `/`. ## Global Angular Object diff --git a/src/Angular.js b/src/Angular.js index c5a35e4e6119..ab031049ea9e 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -116,7 +116,6 @@ var _undefined = undefined, angularService = extensionMap(angular, 'service'), angularCallbacks = extensionMap(angular, 'callbacks'), nodeName_, - rngScript = /^(|.*\/)angular(-.*?)?(\.min)?.js(\?[^#]*)?(#(.*))?$/, uid = ['0', '0', '0'], DATE_ISOSTRING_LN = 24; @@ -953,35 +952,30 @@ function angularInit(config, document){ var autobind = config.autobind; if (autobind) { - var element = isString(autobind) ? document.getElementById(autobind) : document, - scope = compile(element)(createScope()), - $browser = scope.$service('$browser'); - - if (config.css) - $browser.addCss(config.base_url + config.css); - scope.$apply(); + var element = isString(autobind) ? document.getElementById(autobind) : document; + compile(element)().$apply(); } } function angularJsConfig(document) { bindJQuery(); - var scripts = document.getElementsByTagName("script"), + var scripts = document.getElementsByTagName('script'), + script = scripts[scripts.length-1], + scriptSrc = script.src, config = {}, - match; - for(var j = 0; j < scripts.length; j++) { - match = (scripts[j].src || "").match(rngScript); - if (match) { - config.base_url = match[1]; - extend(config, parseKeyValue(match[6])); - eachAttribute(jqLite(scripts[j]), function(value, name){ - if (/^ng:/.exec(name)) { - name = name.substring(3).replace(/-/g, '_'); - value = value || true; - config[name] = value; - } - }); + hashPos; + + hashPos = scriptSrc.indexOf('#'); + if (hashPos != -1) extend(config, parseKeyValue(scriptSrc.substr(hashPos+1))); + + eachAttribute(jqLite(script), function(value, name){ + if (/^ng:/.exec(name)) { + name = name.substring(3).replace(/-/g, '_'); + value = value || true; + config[name] = value; } - } + }); + return config; } diff --git a/src/angular-bootstrap.js b/src/angular-bootstrap.js index 7a1752d278b5..fb2acbeb5796 100644 --- a/src/angular-bootstrap.js +++ b/src/angular-bootstrap.js @@ -99,9 +99,7 @@ // empty the cache to prevent mem leaks globalVars = {}; - var config = angularJsConfig(document); - - angularInit(config, document); + angularInit({autobind:true}, document); } if (window.addEventListener) { diff --git a/src/angular.suffix b/src/angular.suffix index e8bb83b7ef93..d38d3130dc35 100644 --- a/src/angular.suffix +++ b/src/angular.suffix @@ -1,6 +1,8 @@ + var config = angularJsConfig(document); + jqLiteWrap(document).ready(function() { - angularInit(angularJsConfig(document), document); + angularInit(config, document); }); })(window, document); diff --git a/test/AngularSpec.js b/test/AngularSpec.js index 5b0a3466c9ee..7831539d215a 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -228,181 +228,97 @@ describe('angular', function() { }); - describe ('rngScript', function() { - it('should match angular.js', function() { - expect('angular.js'.match(rngScript)).not.toBeNull(); - expect('../angular.js'.match(rngScript)).not.toBeNull(); - expect('foo/angular.js'.match(rngScript)).not.toBeNull(); - - expect('foo.js'.match(rngScript)).toBeNull(); - expect('foo/foo.js'.match(rngScript)).toBeNull(); - expect('my-angular-app.js'.match(rngScript)).toBeNull(); - expect('foo/../my-angular-app.js'.match(rngScript)).toBeNull(); - }); - - it('should match angular.min.js', function() { - expect('angular.min.js'.match(rngScript)).not.toBeNull(); - expect('../angular.min.js'.match(rngScript)).not.toBeNull(); - expect('foo/angular.min.js'.match(rngScript)).not.toBeNull(); - - expect('my-angular-app.min.js'.match(rngScript)).toBeNull(); - expect('foo/../my-angular-app.min.js'.match(rngScript)).toBeNull(); - }); - - it('should match angular-bootstrap.js', function() { - expect('angular-bootstrap.js'.match(rngScript)).not.toBeNull(); - expect('../angular-bootstrap.js'.match(rngScript)).not.toBeNull(); - expect('foo/angular-bootstrap.js'.match(rngScript)).not.toBeNull(); - - expect('my-angular-app-bootstrap.js'.match(rngScript)).toBeNull(); - expect('foo/../my-angular-app-bootstrap.js'.match(rngScript)).toBeNull(); - }); - - it('should match angular-0.9.0.js', function() { - expect('angular-0.9.0.js'.match(rngScript)).not.toBeNull(); - expect('../angular-0.9.0.js'.match(rngScript)).not.toBeNull(); - expect('foo/angular-0.9.0.js'.match(rngScript)).not.toBeNull(); - - expect('my-angular-app-0.9.0.js'.match(rngScript)).toBeNull(); - expect('foo/../my-angular-app-0.9.0.js'.match(rngScript)).toBeNull(); - }); - - it('should match angular-0.9.0.min.js', function() { - expect('angular-0.9.0.min.js'.match(rngScript)).not.toBeNull(); - expect('../angular-0.9.0.min.js'.match(rngScript)).not.toBeNull(); - expect('foo/angular-0.9.0.min.js'.match(rngScript)).not.toBeNull(); - - expect('my-angular-app-0.9.0.min.js'.match(rngScript)).toBeNull(); - expect('foo/../my-angular-app-0.9.0.min.js'.match(rngScript)).toBeNull(); - }); - - it('should match angular-0.9.0-de0a8612.js', function() { - expect('angular-0.9.0-de0a8612.js'.match(rngScript)).not.toBeNull(); - expect('../angular-0.9.0-de0a8612.js'.match(rngScript)).not.toBeNull(); - expect('foo/angular-0.9.0-de0a8612.js'.match(rngScript)).not.toBeNull(); - - expect('my-angular-app-0.9.0-de0a8612.js'.match(rngScript)).toBeNull(); - expect('foo/../my-angular-app-0.9.0-de0a8612.js'.match(rngScript)).toBeNull(); - }); - - it('should match angular-0.9.0-de0a8612.min.js', function() { - expect('angular-0.9.0-de0a8612.min.js'.match(rngScript)).not.toBeNull(); - expect('../angular-0.9.0-de0a8612.min.js'.match(rngScript)).not.toBeNull(); - expect('foo/angular-0.9.0-de0a8612.min.js'.match(rngScript)).not.toBeNull(); - - expect('my-angular-app-0.9.0-de0a8612.min.js'.match(rngScript)).toBeNull(); - expect('foo/../my-angular-app-0.9.0-de0a8612.min.js'.match(rngScript)).toBeNull(); - }); - - it('should match angular-scenario.js', function() { - expect('angular-scenario.js'.match(rngScript)).not.toBeNull(); - expect('angular-scenario.min.js'.match(rngScript)).not.toBeNull(); - expect('../angular-scenario.js'.match(rngScript)).not.toBeNull(); - expect('foo/angular-scenario.min.js'.match(rngScript)).not.toBeNull(); - }); - - it('should match angular-scenario-0.9.0(.min).js', function() { - expect('angular-scenario-0.9.0.js'.match(rngScript)).not.toBeNull(); - expect('angular-scenario-0.9.0.min.js'.match(rngScript)).not.toBeNull(); - expect('../angular-scenario-0.9.0.js'.match(rngScript)).not.toBeNull(); - expect('foo/angular-scenario-0.9.0.min.js'.match(rngScript)).not.toBeNull(); - }); - - it('should match angular-scenario-0.9.0-de0a8612(.min).js', function() { - expect('angular-scenario-0.9.0-de0a8612.js'.match(rngScript)).not.toBeNull(); - expect('angular-scenario-0.9.0-de0a8612.min.js'.match(rngScript)).not.toBeNull(); - expect('../angular-scenario-0.9.0-de0a8612.js'.match(rngScript)).not.toBeNull(); - expect('foo/angular-scenario-0.9.0-de0a8612.min.js'.match(rngScript)).not.toBeNull(); - }); - }); + describe('angularJsConfig', function() { + it('should always consider angular.js script tag to be the last script tag', function() { + var doc = { + getElementsByTagName: function(tagName) { + expect(tagName).toEqual('script'); + return [{nodeName: 'SCRIPT', src: 'random.js', + attributes: [{name: 'ng:autobind', value: 'wrong'}]}, + {nodeName: 'SCRIPT', src: 'angular.js', + attributes: [{name: 'ng:autobind', value: 'correct'}]}]; + } + }; + expect(angularJsConfig(doc)).toEqual({autobind: 'correct'}); - describe('angularJsConfig', function() { - it('should find angular.js script tag and config', function() { - var doc = { getElementsByTagName: function(tagName) { - expect(tagName).toEqual('script'); - return [{nodeName: 'SCRIPT', src: 'random.js'}, - {nodeName: 'SCRIPT', src: 'angular.js'}, - {nodeName: 'SCRIPT', src: 'my-angular-app.js'}]; - } + doc = { + getElementsByTagName: function(tagName) { + expect(tagName).toEqual('script'); + return [{nodeName: 'SCRIPT', src: 'angular.js', + attributes: [{name: 'ng:autobind', value: 'wrong'}]}, + {nodeName: 'SCRIPT', src: 'concatinatedAndObfuscadedScriptWithOurScript.js', + attributes: [{name: 'ng:autobind', value: 'correct'}]}]; + } }; - expect(angularJsConfig(doc)).toEqual({base_url: ''}); + expect(angularJsConfig(doc)).toEqual({autobind: 'correct'}); }); - it('should extract angular config from the ng: attributes', - function() { + it('should extract angular config from the ng: attributes', function() { var doc = { getElementsByTagName: function(tagName) { expect(lowercase(tagName)).toEqual('script'); - return [{nodeName: 'SCRIPT', + return [{ + nodeName: 'SCRIPT', src: 'angularjs/angular.js', attributes: [{name: 'ng:autobind', value:'elementIdToCompile'}, {name: 'ng:css', value: 'css/my_custom_angular.css'}] }]; }}; - expect(angularJsConfig(doc)).toEqual({base_url: 'angularjs/', + expect(angularJsConfig(doc)).toEqual({ autobind: 'elementIdToCompile', - css: 'css/my_custom_angular.css'}); + css: 'css/my_custom_angular.css' + }); }); it('should extract angular config and default autobind value to true if present', function() { var doc = { getElementsByTagName: function(tagName) { expect(lowercase(tagName)).toEqual('script'); - return [{nodeName: 'SCRIPT', + return [{ + nodeName: 'SCRIPT', src: 'angularjs/angular.js', attributes: [{name: 'ng:autobind', value:undefined}]}]; }}; - expect(angularJsConfig(doc)).toEqual({autobind: true, - base_url: 'angularjs/'}); + expect(angularJsConfig(doc)).toEqual({autobind: true}); }); it('should extract angular autobind config from the script hashpath attributes', function() { var doc = { getElementsByTagName: function(tagName) { expect(lowercase(tagName)).toEqual('script'); - return [{nodeName: 'SCRIPT', + return [{ + nodeName: 'SCRIPT', src: 'angularjs/angular.js#autobind'}]; }}; - expect(angularJsConfig(doc)).toEqual({base_url: 'angularjs/', - autobind: true}); + expect(angularJsConfig(doc)).toEqual({autobind: true}); }); it('should extract autobind config with element id from the script hashpath', function() { var doc = { getElementsByTagName: function(tagName) { expect(lowercase(tagName)).toEqual('script'); - return [{nodeName: 'SCRIPT', + return [{ + nodeName: 'SCRIPT', src: 'angularjs/angular.js#autobind=foo'}]; }}; - expect(angularJsConfig(doc)).toEqual({base_url: 'angularjs/', - autobind: 'foo'}); + expect(angularJsConfig(doc)).toEqual({autobind: 'foo'}); }); - it("should default to versioned ie-compat file if angular file is versioned", function() { + it('should default to versioned ie-compat file if angular file is versioned', function() { var doc = { getElementsByTagName: function(tagName) { expect(lowercase(tagName)).toEqual('script'); - return [{nodeName: 'SCRIPT', + return [{ + nodeName: 'SCRIPT', src: 'js/angular-0.9.0.js'}]; }}; - expect(angularJsConfig(doc)).toEqual({base_url: 'js/'}); - }); - - - it("should default to versioned ie-compat file if angular file is versioned and minified", function() { - var doc = { getElementsByTagName: function(tagName) { - expect(lowercase(tagName)).toEqual('script'); - return [{nodeName: 'SCRIPT', - src: 'js/angular-0.9.0-cba23f00.min.js'}]; - }}; - - expect(angularJsConfig(doc)).toEqual({base_url: 'js/'}); + expect(angularJsConfig(doc)).toEqual({}); }); });