diff options
| author | Misko Hevery | 2011-02-12 10:13:28 -0800 | 
|---|---|---|
| committer | Misko Hevery | 2011-02-16 01:03:12 -0500 | 
| commit | ef4bb28be13e99f96c9ace5936cf26a174a0e5f0 (patch) | |
| tree | 833057505e430cac064214ac3d55c687338da2a9 | |
| parent | 496e6bf9016d33a7cf2f4730d06a8655f01ca5cb (diff) | |
| download | angular.js-ef4bb28be13e99f96c9ace5936cf26a174a0e5f0.tar.bz2 | |
Change API angular.compile(element)([scope], [element/true])
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | src/Angular.js | 51 | ||||
| -rw-r--r-- | src/Compiler.js | 22 | ||||
| -rw-r--r-- | src/widgets.js | 8 | ||||
| -rw-r--r-- | test/AngularSpec.js | 725 | ||||
| -rw-r--r-- | test/BinderSpec.js | 110 | ||||
| -rw-r--r-- | test/CompilerSpec.js | 7 | ||||
| -rw-r--r-- | test/ResourceSpec.js | 4 | ||||
| -rw-r--r-- | test/ScenarioSpec.js | 12 | ||||
| -rw-r--r-- | test/ValidatorsSpec.js | 10 | ||||
| -rw-r--r-- | test/directivesSpec.js | 4 | ||||
| -rw-r--r-- | test/markupSpec.js | 3 | ||||
| -rw-r--r-- | test/service/invalidWidgetsSpec.js | 6 | ||||
| -rw-r--r-- | test/service/routeSpec.js | 4 | ||||
| -rw-r--r-- | test/widgetsSpec.js | 18 | 
15 files changed, 524 insertions, 461 deletions
| diff --git a/CHANGELOG.md b/CHANGELOG.md index 979d2435..04d511d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@    recommended way to deal with initializing scope is to put it in the root constructor controller.    To migrate simply remove the call to $init() and move any code you had before $init() to the    root controller. +- Change API angular.compile(..) to angular.compile(element)([scope], [element/true])  <a name="0.9.11"><a/> diff --git a/src/Angular.js b/src/Angular.js index 9b2c7ea6..9eaeb093 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -793,21 +793,50 @@ function merge(src, dst) {   * @function   *   * @description - * Compiles a piece of HTML or DOM into a {@link angular.scope scope} object. + * Compiles a piece of HTML string or DOM into a view and produces a linking function, which can + * then be used to link {@link angular.scope scope} and the template together. The compilation + * process walks the DOM tree and tries to match DOM elements to {@link angular.markup markup}, + * {@link angular.attrMarkup attrMarkup}, {@link angular.widget widgets}, and + * {@link angular.directive directives}. For each match it executes coresponding markup, \ + * attrMarkup, widget or directive template function and collects the instance functions into a + * single linking function which is then returned. The linking function can then be used + * many-times-over on clones of compiled DOM structure, (For example when compiling + * {@link angular.widget.@ng:repeat repeater} the resulting linking function is called once for + * each item in the collection. The `ng:repeat` does this by cloning the template DOM once for + * each item in collection and then calling the linking function to link the cloned template + * with the a new scope for each item in the collection.) + *     <pre> -    var scope1 = angular.compile(window.document); +    var mvc1 = angular.compile(window.document)(); +    mvc1.view; // compiled view elment +    mvc1.scope; // scope bound to the element -    var scope2 = angular.compile('<div ng:click="clicked = true">click me</div>'); +    var mvc2 = angular.compile('<div ng:click="clicked = true">click me</div>')();     </pre>   * - * @param {string|DOMElement} element Element to compile. - * @param {Object=} parentScope Scope to become the parent scope of the newly compiled scope. - * @returns {Object} Compiled scope object. + * @param {string|DOMElement} element Element or HTML to compile into a template function. + * @returns {function([scope][, element])} a template function which is used to bind element + * and scope. Where: + * + *   * `scope` - {@link angular.scope scope} A scope to bind to. If none specified, then a new + *               root scope is created. + *   * `element` - {@link angular.element element} Element to use as the template. If none + *               specified then reuse the element from `angular.compile(element)`. If `true` + *               then clone the `angular.compile(element)`. The element must be either the same + *               element as `angular.compile(element)` or an identical clone to + *               `angular.compile(element)`. Using an element with differnt structure will cause + *               unpredictable behavior. + * + * Calling the template function returns object: `{scope:?, view:?}`, where: + * + *   * `view` - the DOM element which represents the compiled template. Either same or clone of + *           `element` specifed in compile or template function. + *   * `scope` - scope to which the element is bound to. Either a root scope or scope specified + *           in the template function.   */ -function compile(element, parentScope) { -  var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget), -      $element = jqLite(element); -  return compiler.compile($element)($element, parentScope); +function compile(element) { +  return new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget) +    .compile(element);  }  ///////////////////////////////////////////////// @@ -989,7 +1018,7 @@ function toKeyValue(obj) {  function angularInit(config){    if (config.autobind) {      // TODO default to the source of angular.js -    var scope = compile(window.document, _null, {'$config':config}), +    var scope = compile(window.document)(null, createScope({'$config':config})),          $browser = scope.$service('$browser');      if (config.css) diff --git a/src/Compiler.js b/src/Compiler.js index 6aee40b8..890f2510 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -80,30 +80,30 @@ function Compiler(markup, attrMarkup, directives, widgets){  }  Compiler.prototype = { -  compile: function(element) { -    element = jqLite(element); +  compile: function(templateElement) { +    templateElement = jqLite(templateElement);      var index = 0,          template, -        parent = element.parent(); +        parent = templateElement.parent();      if (parent && parent[0]) {        parent = parent[0];        for(var i = 0; i < parent.childNodes.length; i++) { -        if (parent.childNodes[i] == element[0]) { +        if (parent.childNodes[i] == templateElement[0]) {            index = i;          }        }      } -    template = this.templatize(element, index, 0) || new Template(); -    return function(element, parentScope){ -      element = jqLite(element); -      var scope = parentScope && parentScope.$eval -          ? parentScope -          : createScope(parentScope); +    template = this.templatize(templateElement, index, 0) || new Template(); +    return function(scope, element){ +      scope = scope || createScope(); +      element = element === true +        ? templateElement.cloneNode() +        : (jqLite(element) || templateElement);        element.data($$scope, scope);        template.attach(element, scope);        scope.$element = element;        scope.$eval(); -      return scope; +      return {scope:scope, view:element};      };    }, diff --git a/src/widgets.js b/src/widgets.js index 58c22081..14d6fe10 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -676,7 +676,7 @@ angularWidget('ng:include', function(element){            xhr('GET', src, function(code, response){              element.html(response);              childScope = useScope || createScope(scope); -            compiler.compile(element)(element, childScope); +            compiler.compile(element)(childScope);              scope.$eval(onloadExp);            });          } else { @@ -793,7 +793,7 @@ var ngSwitch = angularWidget('ng:switch', function (element){            var caseElement = switchCase.element.cloneNode();            element.append(caseElement);            childScope.$tryEval(switchCase.change, element); -          switchCase.template(caseElement, childScope); +          switchCase.template(childScope, caseElement);          }        });      }); @@ -945,7 +945,7 @@ angularWidget("@ng:repeat", function(expression, element){                    (index == collectionLength - 1 ? 'last' : 'middle');              lastElement.after(cloneElement = element.cloneNode());              cloneElement.attr('ng:repeat-index', index); -            linker(cloneElement, childScope); +            linker(childScope, cloneElement);              children.push(childScope);            }            childScope.$eval(); @@ -1067,7 +1067,7 @@ angularWidget('ng:view', function(element) {          if (src) {            $xhr('GET', src, function(code, response){              element.html(response); -            compiler.compile(element)(element, childScope); +            compiler.compile(element)(childScope);            });          } else {            element.html(''); diff --git a/test/AngularSpec.js b/test/AngularSpec.js index 010dce7c..8ff0631d 100644 --- a/test/AngularSpec.js +++ b/test/AngularSpec.js @@ -1,350 +1,389 @@ -beforeEach(function(){ -  compileCache = {}; -}); - -describe('case', function(){ -  it('should change case', function(){ -    expect(lowercase('ABC90')).toEqual('abc90'); -    expect(manualLowercase('ABC90')).toEqual('abc90'); -    expect(uppercase('abc90')).toEqual('ABC90'); -    expect(manualUppercase('abc90')).toEqual('ABC90'); -  }); -}); - -describe("copy", function(){ -  it("should return same object", function (){ -    var obj = {}; -    var arr = []; -    expect(copy({}, obj)).toBe(obj); -    expect(copy([], arr)).toBe(arr); -  }); - -  it("should copy Date", function(){ -    var date = new Date(123); -    expect(copy(date) instanceof Date).toBeTruthy(); -    expect(copy(date).getTime()).toEqual(123); -    expect(copy(date) === date).toBeFalsy(); -  }); - -  it("should copy array", function(){ -    var src = [1, {name:"value"}]; -    var dst = [{key:"v"}]; -    expect(copy(src, dst)).toBe(dst); -    expect(dst).toEqual([1, {name:"value"}]); -    expect(dst[1]).toEqual({name:"value"}); -    expect(dst[1]).not.toBe(src[1]); -  }); - -  it('should copy empty array', function() { -    var src = []; -    var dst = [{key: "v"}]; -    expect(copy(src, dst)).toEqual([]); -    expect(dst).toEqual([]); -  }); - -  it("should copy object", function(){ -    var src = {a:{name:"value"}}; -    var dst = {b:{key:"v"}}; -    expect(copy(src, dst)).toBe(dst); -    expect(dst).toEqual({a:{name:"value"}}); -    expect(dst.a).toEqual(src.a); -    expect(dst.a).not.toBe(src.a); -  }); - -  it("should copy primitives", function(){ -    expect(copy(null)).toEqual(null); -    expect(copy('')).toBe(''); -    expect(copy('lala')).toBe('lala'); -    expect(copy(123)).toEqual(123); -    expect(copy([{key:null}])).toEqual([{key:null}]); -  }); - -}); - -describe('equals', function(){ -  it('should return true if same object', function(){ -    var o = {}; -    expect(equals(o, o)).toEqual(true); -    expect(equals(1, '1')).toEqual(true); -    expect(equals(1, '2')).toEqual(false); -  }); - -  it('should recurse into object', function(){ -    expect(equals({}, {})).toEqual(true); -    expect(equals({name:'misko'}, {name:'misko'})).toEqual(true); -    expect(equals({name:'misko', age:1}, {name:'misko'})).toEqual(false); -    expect(equals({name:'misko'}, {name:'misko', age:1})).toEqual(false); -    expect(equals({name:'misko'}, {name:'adam'})).toEqual(false); -    expect(equals(['misko'], ['misko'])).toEqual(true); -    expect(equals(['misko'], ['adam'])).toEqual(false); -    expect(equals(['misko'], ['misko', 'adam'])).toEqual(false); -  }); - -  it('should ignore $ member variables', function(){ -    expect(equals({name:'misko', $id:1}, {name:'misko', $id:2})).toEqual(true); -    expect(equals({name:'misko'}, {name:'misko', $id:2})).toEqual(true); -    expect(equals({name:'misko', $id:1}, {name:'misko'})).toEqual(true); -  }); - -  it('should ignore functions', function(){ -    expect(equals({func: function() {}}, {bar: function() {}})).toEqual(true); -  }); - -  it('should work well with nulls', function() { -    expect(equals(null, '123')).toBe(false); -    expect(equals('123', null)).toBe(false); - -    var obj = {foo:'bar'}; -    expect(equals(null, obj)).toBe(false); -    expect(equals(obj, null)).toBe(false); - -    expect(equals(null, null)).toBe(true); -  }); - -  it('should work well with undefined', function() { -    expect(equals(undefined, '123')).toBe(false); -    expect(equals('123', undefined)).toBe(false); - -    var obj = {foo:'bar'}; -    expect(equals(undefined, obj)).toBe(false); -    expect(equals(obj, undefined)).toBe(false); - -    expect(equals(undefined, undefined)).toBe(true); -  }); -}); - -describe('parseKeyValue', function() { -  it('should parse a string into key-value pairs', function() { -    expect(parseKeyValue('')).toEqual({}); -    expect(parseKeyValue('simple=pair')).toEqual({simple: 'pair'}); -    expect(parseKeyValue('first=1&second=2')).toEqual({first: '1', second: '2'}); -    expect(parseKeyValue('escaped%20key=escaped%20value')). +describe('angular', function(){ +  describe('case', function(){ +    it('should change case', function(){ +      expect(lowercase('ABC90')).toEqual('abc90'); +      expect(manualLowercase('ABC90')).toEqual('abc90'); +      expect(uppercase('abc90')).toEqual('ABC90'); +      expect(manualUppercase('abc90')).toEqual('ABC90'); +    }); +  }); + +  describe("copy", function(){ +    it("should return same object", function (){ +      var obj = {}; +      var arr = []; +      expect(copy({}, obj)).toBe(obj); +      expect(copy([], arr)).toBe(arr); +    }); + +    it("should copy Date", function(){ +      var date = new Date(123); +      expect(copy(date) instanceof Date).toBeTruthy(); +      expect(copy(date).getTime()).toEqual(123); +      expect(copy(date) === date).toBeFalsy(); +    }); + +    it("should copy array", function(){ +      var src = [1, {name:"value"}]; +      var dst = [{key:"v"}]; +      expect(copy(src, dst)).toBe(dst); +      expect(dst).toEqual([1, {name:"value"}]); +      expect(dst[1]).toEqual({name:"value"}); +      expect(dst[1]).not.toBe(src[1]); +    }); + +    it('should copy empty array', function() { +      var src = []; +      var dst = [{key: "v"}]; +      expect(copy(src, dst)).toEqual([]); +      expect(dst).toEqual([]); +    }); + +    it("should copy object", function(){ +      var src = {a:{name:"value"}}; +      var dst = {b:{key:"v"}}; +      expect(copy(src, dst)).toBe(dst); +      expect(dst).toEqual({a:{name:"value"}}); +      expect(dst.a).toEqual(src.a); +      expect(dst.a).not.toBe(src.a); +    }); + +    it("should copy primitives", function(){ +      expect(copy(null)).toEqual(null); +      expect(copy('')).toBe(''); +      expect(copy('lala')).toBe('lala'); +      expect(copy(123)).toEqual(123); +      expect(copy([{key:null}])).toEqual([{key:null}]); +    }); + +  }); + +  describe('equals', function(){ +    it('should return true if same object', function(){ +      var o = {}; +      expect(equals(o, o)).toEqual(true); +      expect(equals(1, '1')).toEqual(true); +      expect(equals(1, '2')).toEqual(false); +    }); + +    it('should recurse into object', function(){ +      expect(equals({}, {})).toEqual(true); +      expect(equals({name:'misko'}, {name:'misko'})).toEqual(true); +      expect(equals({name:'misko', age:1}, {name:'misko'})).toEqual(false); +      expect(equals({name:'misko'}, {name:'misko', age:1})).toEqual(false); +      expect(equals({name:'misko'}, {name:'adam'})).toEqual(false); +      expect(equals(['misko'], ['misko'])).toEqual(true); +      expect(equals(['misko'], ['adam'])).toEqual(false); +      expect(equals(['misko'], ['misko', 'adam'])).toEqual(false); +    }); + +    it('should ignore $ member variables', function(){ +      expect(equals({name:'misko', $id:1}, {name:'misko', $id:2})).toEqual(true); +      expect(equals({name:'misko'}, {name:'misko', $id:2})).toEqual(true); +      expect(equals({name:'misko', $id:1}, {name:'misko'})).toEqual(true); +    }); + +    it('should ignore functions', function(){ +      expect(equals({func: function() {}}, {bar: function() {}})).toEqual(true); +    }); + +    it('should work well with nulls', function() { +      expect(equals(null, '123')).toBe(false); +      expect(equals('123', null)).toBe(false); + +      var obj = {foo:'bar'}; +      expect(equals(null, obj)).toBe(false); +      expect(equals(obj, null)).toBe(false); + +      expect(equals(null, null)).toBe(true); +    }); + +    it('should work well with undefined', function() { +      expect(equals(undefined, '123')).toBe(false); +      expect(equals('123', undefined)).toBe(false); + +      var obj = {foo:'bar'}; +      expect(equals(undefined, obj)).toBe(false); +      expect(equals(obj, undefined)).toBe(false); + +      expect(equals(undefined, undefined)).toBe(true); +    }); +  }); + +  describe('parseKeyValue', function() { +    it('should parse a string into key-value pairs', function() { +      expect(parseKeyValue('')).toEqual({}); +      expect(parseKeyValue('simple=pair')).toEqual({simple: 'pair'}); +      expect(parseKeyValue('first=1&second=2')).toEqual({first: '1', second: '2'}); +      expect(parseKeyValue('escaped%20key=escaped%20value')).        toEqual({'escaped key': 'escaped value'}); -    expect(parseKeyValue('emptyKey=')).toEqual({emptyKey: ''}); -    expect(parseKeyValue('flag1&key=value&flag2')). +      expect(parseKeyValue('emptyKey=')).toEqual({emptyKey: ''}); +      expect(parseKeyValue('flag1&key=value&flag2')).        toEqual({flag1: true, key: 'value', flag2: true}); +    });    }); -}); -describe('toKeyValue', function() { -  it('should parse key-value pairs into string', function() { -    expect(toKeyValue({})).toEqual(''); -    expect(toKeyValue({simple: 'pair'})).toEqual('simple=pair'); -    expect(toKeyValue({first: '1', second: '2'})).toEqual('first=1&second=2'); -    expect(toKeyValue({'escaped key': 'escaped value'})). +  describe('toKeyValue', function() { +    it('should parse key-value pairs into string', function() { +      expect(toKeyValue({})).toEqual(''); +      expect(toKeyValue({simple: 'pair'})).toEqual('simple=pair'); +      expect(toKeyValue({first: '1', second: '2'})).toEqual('first=1&second=2'); +      expect(toKeyValue({'escaped key': 'escaped value'})).        toEqual('escaped%20key=escaped%20value'); -    expect(toKeyValue({emptyKey: ''})).toEqual('emptyKey='); -  }); - -  it('should parse true values into flags', function() { -    expect(toKeyValue({flag1: true, key: 'value', flag2: true})).toEqual('flag1&key=value&flag2'); -  }); -}); - - -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 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'}]; -                } -              }; - -    expect(angularJsConfig(doc)).toEqual({base_url: '', -                                          ie_compat: 'angular-ie-compat.js', -                                          ie_compat_id: 'ng-ie-compat'}); -  }); - - -  it('should extract angular config from the ng: attributes', function() { -    var doc = { getElementsByTagName: function(tagName) { -                  expect(lowercase(tagName)).toEqual('script'); -                  return [{nodeName: 'SCRIPT', -                           src: 'angularjs/angular.js', -                           attributes: [{name: 'ng:autobind', value:undefined}, -                                        {name: 'ng:css', value: 'css/my_custom_angular.css'}, -                                        {name: 'ng:ie-compat', value: 'myjs/angular-ie-compat.js'}, -                                        {name: 'ng:ie-compat-id', value: 'ngcompat'}] }]; -               }}; - -    expect(angularJsConfig(doc)).toEqual({base_url: 'angularjs/', -                                          autobind: true, -                                          css: 'css/my_custom_angular.css', -                                          ie_compat: 'myjs/angular-ie-compat.js', -                                          ie_compat_id: 'ngcompat'}); -  }); - - -  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', -                           src: 'angularjs/angular.js#autobind'}]; -               }}; - -    expect(angularJsConfig(doc)).toEqual({base_url: 'angularjs/', -                                          autobind: true, -                                          ie_compat: 'angularjs/angular-ie-compat.js', -                                          ie_compat_id: 'ng-ie-compat'}); -  }); - - -  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', -                           src: 'js/angular-0.9.0.js'}]; -               }}; - -    expect(angularJsConfig(doc)).toEqual({base_url: 'js/', -                                          ie_compat: 'js/angular-ie-compat-0.9.0.js', -                                          ie_compat_id: 'ng-ie-compat'}); -  }); - - -  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/', -                                          ie_compat: 'js/angular-ie-compat-0.9.0-cba23f00.js', -                                          ie_compat_id: 'ng-ie-compat'}); -  }); -}); - - -describe('angular service', function() { -  it('should override services', function() { -    var scope = createScope(); -    angular.service('fake', function() { return 'old'; }); -    angular.service('fake', function() { return 'new'; }); - -    expect(scope.$service('fake')).toEqual('new'); -  }); - -  it('should not preserve properties on override', function() { -    angular.service('fake', {$one: true}, {$two: true}, {three: true}); -    var result = angular.service('fake', {$four: true}); - -    expect(result.$one).toBeUndefined(); -    expect(result.$two).toBeUndefined(); -    expect(result.three).toBeUndefined(); -    expect(result.$four).toBe(true); -  }); - -  it('should not preserve non-angular properties on override', function() { -    angular.service('fake', {one: true}, {two: true}); -    var result = angular.service('fake', {third: true}); - -    expect(result.one).not.toBeDefined(); -    expect(result.two).not.toBeDefined(); -    expect(result.third).toBeTruthy(); -  }); -}); - -describe('isDate', function() { -  it('should return true for Date object', function() { -    expect(isDate(new Date())).toBe(true); -  }); - -  it('should return false for non Date objects', function() { -    expect(isDate([])).toBe(false); -    expect(isDate('')).toBe(false); -    expect(isDate(23)).toBe(false); -    expect(isDate({})).toBe(false); +      expect(toKeyValue({emptyKey: ''})).toEqual('emptyKey='); +    }); + +    it('should parse true values into flags', function() { +      expect(toKeyValue({flag1: true, key: 'value', flag2: true})).toEqual('flag1&key=value&flag2'); +    }); +  }); + + +  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 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'}]; +      } +      }; + +      expect(angularJsConfig(doc)).toEqual({base_url: '', +        ie_compat: 'angular-ie-compat.js', +        ie_compat_id: 'ng-ie-compat'}); +    }); + + +    it('should extract angular config from the ng: attributes', function() { +      var doc = { getElementsByTagName: function(tagName) { +        expect(lowercase(tagName)).toEqual('script'); +        return [{nodeName: 'SCRIPT', +          src: 'angularjs/angular.js', +          attributes: [{name: 'ng:autobind', value:undefined}, +                       {name: 'ng:css', value: 'css/my_custom_angular.css'}, +                       {name: 'ng:ie-compat', value: 'myjs/angular-ie-compat.js'}, +                       {name: 'ng:ie-compat-id', value: 'ngcompat'}] }]; +      }}; + +      expect(angularJsConfig(doc)).toEqual({base_url: 'angularjs/', +        autobind: true, +        css: 'css/my_custom_angular.css', +        ie_compat: 'myjs/angular-ie-compat.js', +        ie_compat_id: 'ngcompat'}); +    }); + + +    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', +          src: 'angularjs/angular.js#autobind'}]; +      }}; + +      expect(angularJsConfig(doc)).toEqual({base_url: 'angularjs/', +        autobind: true, +        ie_compat: 'angularjs/angular-ie-compat.js', +        ie_compat_id: 'ng-ie-compat'}); +    }); + + +    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', +          src: 'js/angular-0.9.0.js'}]; +      }}; + +      expect(angularJsConfig(doc)).toEqual({base_url: 'js/', +        ie_compat: 'js/angular-ie-compat-0.9.0.js', +        ie_compat_id: 'ng-ie-compat'}); +    }); + + +    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/', +        ie_compat: 'js/angular-ie-compat-0.9.0-cba23f00.js', +        ie_compat_id: 'ng-ie-compat'}); +    }); +  }); + + +  describe('angular service', function() { +    it('should override services', function() { +      var scope = createScope(); +      angular.service('fake', function() { return 'old'; }); +      angular.service('fake', function() { return 'new'; }); + +      expect(scope.$service('fake')).toEqual('new'); +    }); + +    it('should not preserve properties on override', function() { +      angular.service('fake', {$one: true}, {$two: true}, {three: true}); +      var result = angular.service('fake', {$four: true}); + +      expect(result.$one).toBeUndefined(); +      expect(result.$two).toBeUndefined(); +      expect(result.three).toBeUndefined(); +      expect(result.$four).toBe(true); +    }); + +    it('should not preserve non-angular properties on override', function() { +      angular.service('fake', {one: true}, {two: true}); +      var result = angular.service('fake', {third: true}); + +      expect(result.one).not.toBeDefined(); +      expect(result.two).not.toBeDefined(); +      expect(result.third).toBeTruthy(); +    }); +  }); + +  describe('isDate', function() { +    it('should return true for Date object', function() { +      expect(isDate(new Date())).toBe(true); +    }); + +    it('should return false for non Date objects', function() { +      expect(isDate([])).toBe(false); +      expect(isDate('')).toBe(false); +      expect(isDate(23)).toBe(false); +      expect(isDate({})).toBe(false); +    }); +  }); + +  describe('compile', function(){ +    var mvc; +    afterEach(function(){ +      dealoc(mvc.view); +    }); + +    it('should link to existing node and create scope', function(){ +      mvc = angular.compile('<div>{{greeting = "hello world"}}</div>')(); +      expect(mvc.view.text()).toEqual('hello world'); +      expect(mvc.scope.greeting).toEqual('hello world'); +    }); + +    it('should link to existing node and given scope', function(){ +      var scope = angular.scope(); +      mvc = angular.compile('<div>{{greeting = "hello world"}}</div>')(scope); +      expect(mvc.view.text()).toEqual('hello world'); +      expect(mvc.scope).toEqual(scope); +    }); + +    it('should link to new node and given scope', function(){ +      var scope = angular.scope(); +      var template = jqLite('<div>{{greeting = "hello world"}}</div>'); +      var templateFn = angular.compile(template); +      var templateClone = template.cloneNode(); +      mvc = templateFn(scope, templateClone); +      expect(template.text()).toEqual(''); +      expect(mvc.view.text()).toEqual('hello world'); +      expect(mvc.view).toEqual(templateClone); +      expect(mvc.scope.greeting).toEqual('hello world'); +    }); + +    it('should link to cloned node and create scope', function(){ +      var scope = angular.scope(); +      var template = jqLite('<div>{{greeting = "hello world"}}</div>'); +      mvc = angular.compile(template)(scope, true); +      expect(template.text()).toEqual(''); +      expect(mvc.view.text()).toEqual('hello world'); +      expect(mvc.scope.greeting).toEqual('hello world'); +    });    });  }); diff --git a/test/BinderSpec.js b/test/BinderSpec.js index c3f90ad7..a1b9be14 100644 --- a/test/BinderSpec.js +++ b/test/BinderSpec.js @@ -4,7 +4,6 @@ describe('Binder', function(){      var self = this;      this.compile = function(html, parent) { -      var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget);        if (self.element) dealoc(self.element);        var element;        if (parent) { @@ -14,11 +13,10 @@ describe('Binder', function(){          element = jqLite(html);        }        self.element = element; -      var scope = compiler.compile(element)(element); -      return {node:element, scope:scope}; +      return angular.compile(element)();      };      this.compileToHtml = function (content) { -      return sortedHtml(this.compile(content).node); +      return sortedHtml(this.compile(content).view);      };    }); @@ -92,7 +90,7 @@ describe('Binder', function(){      var form = this.compile('<div ng:bind="model.a">x</div>');      form.scope.$set('model', {a:123});      form.scope.$eval(); -    assertEquals('123', form.node.text()); +    assertEquals('123', form.view.text());    });    it('ReplaceBindingInTextWithSpan', function(){ @@ -115,7 +113,7 @@ describe('Binder', function(){    it('BindingOfAttributes', function(){      var c = this.compile("<a href='http://s/a{{b}}c' foo='x'></a>"); -    var attrbinding = c.node.attr("ng:bind-attr"); +    var attrbinding = c.view.attr("ng:bind-attr");      var bindings = fromJson(attrbinding);      assertEquals("http://s/a{{b}}c", decodeURI(bindings.href));      assertTrue(!bindings.foo); @@ -123,7 +121,7 @@ describe('Binder', function(){    it('MarkMultipleAttributes', function(){      var c = this.compile('<a href="http://s/a{{b}}c" foo="{{d}}"></a>'); -    var attrbinding = c.node.attr("ng:bind-attr"); +    var attrbinding = c.view.attr("ng:bind-attr");      var bindings = fromJson(attrbinding);      assertEquals(bindings.foo, "{{d}}");      assertEquals(decodeURI(bindings.href), "http://s/a{{b}}c"); @@ -131,23 +129,23 @@ describe('Binder', function(){    it('AttributesNoneBound', function(){      var c = this.compile("<a href='abc' foo='def'></a>"); -    var a = c.node; +    var a = c.view;      assertEquals(a[0].nodeName, "A");      assertTrue(!a.attr("ng:bind-attr"));    });    it('ExistingAttrbindingIsAppended', function(){      var c = this.compile("<a href='http://s/{{abc}}' ng:bind-attr='{\"b\":\"{{def}}\"}'></a>"); -    var a = c.node; +    var a = c.view;      assertEquals('{"b":"{{def}}","href":"http://s/{{abc}}"}', a.attr('ng:bind-attr'));    });    it('AttributesAreEvaluated', function(){      var c = this.compile('<a ng:bind-attr=\'{"a":"a", "b":"a+b={{a+b}}"}\'></a>'); -    var binder = c.binder, form = c.node; +    var binder = c.binder, form = c.view;      c.scope.$eval('a=1;b=2');      c.scope.$eval(); -    var a = c.node; +    var a = c.view;      assertEquals(a.attr('a'), 'a');      assertEquals(a.attr('b'), 'a+b=3');    }); @@ -158,7 +156,7 @@ describe('Binder', function(){      c.scope.$set("person.save", function(){        savedCalled = true;      }); -    browserTrigger(c.node, 'click'); +    browserTrigger(c.view, 'click');      assertTrue(savedCalled);    }); @@ -169,7 +167,7 @@ describe('Binder', function(){        log += 'click;';      });      expect(log).toEqual(''); -    browserTrigger(c.node, 'click'); +    browserTrigger(c.view, 'click');      expect(log).toEqual('click;');    }); @@ -179,13 +177,13 @@ describe('Binder', function(){      c.scope.$set("person.save", function(){        savedCalled = true;      }); -    browserTrigger(c.node, 'click'); +    browserTrigger(c.view, 'click');      assertTrue(savedCalled);    });    it('RepeaterUpdateBindings', function(){      var a = this.compile('<ul><LI ng:repeat="item in model.items" ng:bind="item.a"/></ul>'); -    var form = a.node; +    var form = a.view;      var items = [{a:"A"}, {a:"B"}];      a.scope.$set('model', {items:items}); @@ -225,7 +223,7 @@ describe('Binder', function(){      assertEquals('<ul>' +            '<#comment></#comment>' +            '<li ng:repeat-index="0"><span ng:bind="item.a">A</span></li>' + -          '</ul>', sortedHtml(a.node)); +          '</ul>', sortedHtml(a.view));    });    it('ExpandEntityTag', function(){ @@ -241,11 +239,11 @@ describe('Binder', function(){    it('RepeaterAdd', function(){      var c = this.compile('<div><input type="text" name="item.x" ng:repeat="item in items"></div>'); -    var doc = c.node; +    var doc = c.view;      c.scope.$set('items', [{x:'a'}, {x:'b'}]);      c.scope.$eval(); -    var first = childNode(c.node, 1); -    var second = childNode(c.node, 2); +    var first = childNode(c.view, 1); +    var second = childNode(c.view, 2);      assertEquals('a', first.val());      assertEquals('b', second.val()); @@ -261,20 +259,20 @@ describe('Binder', function(){      c.scope.$set("items", items);      c.scope.$eval(); -    expect(c.node[0].childNodes.length - 1).toEqual(0); +    expect(c.view[0].childNodes.length - 1).toEqual(0);      items.name = "misko";      c.scope.$eval(); -    expect(c.node[0].childNodes.length - 1).toEqual(1); +    expect(c.view[0].childNodes.length - 1).toEqual(1);      delete items.name;      c.scope.$eval(); -    expect(c.node[0].childNodes.length - 1).toEqual(0); +    expect(c.view[0].childNodes.length - 1).toEqual(0);    });    it('IfTextBindingThrowsErrorDecorateTheSpan', function(){      var a = this.compile('<div>{{error.throw()}}</div>'); -    var doc = a.node; +    var doc = a.view;      var errorLogs = a.scope.$service('$log').error.logs;      a.scope.$set('error.throw', function(){throw "ErrorMsg1";}); @@ -303,7 +301,7 @@ describe('Binder', function(){    it('IfAttrBindingThrowsErrorDecorateTheAttribute', function(){      var a = this.compile('<div attr="before {{error.throw()}} after"></div>'); -    var doc = a.node; +    var doc = a.view;      var errorLogs = a.scope.$service('$log').error.logs;      a.scope.$set('error.throw', function(){throw "ErrorMsg";}); @@ -340,7 +338,7 @@ describe('Binder', function(){            '<#comment></#comment>'+            '<ul name="b1" ng:bind-attr="{"name":"{{i}}"}" ng:repeat-index="0"></ul>'+            '<ul name="b2" ng:bind-attr="{"name":"{{i}}"}" ng:repeat-index="1"></ul>'+ -        '</div></div>', sortedHtml(a.node)); +        '</div></div>', sortedHtml(a.view));    });    it('HideBindingExpression', function(){ @@ -349,12 +347,12 @@ describe('Binder', function(){      a.scope.$set('hidden', 3);      a.scope.$eval(); -    assertHidden(a.node); +    assertHidden(a.view);      a.scope.$set('hidden', 2);      a.scope.$eval(); -    assertVisible(a.node); +    assertVisible(a.view);    });    it('HideBinding', function(){ @@ -363,17 +361,17 @@ describe('Binder', function(){      c.scope.$set('hidden', 'true');      c.scope.$eval(); -    assertHidden(c.node); +    assertHidden(c.view);      c.scope.$set('hidden', 'false');      c.scope.$eval(); -    assertVisible(c.node); +    assertVisible(c.view);      c.scope.$set('hidden', '');      c.scope.$eval(); -    assertVisible(c.node); +    assertVisible(c.view);    });    it('ShowBinding', function(){ @@ -382,17 +380,17 @@ describe('Binder', function(){      c.scope.$set('show', 'true');      c.scope.$eval(); -    assertVisible(c.node); +    assertVisible(c.view);      c.scope.$set('show', 'false');      c.scope.$eval(); -    assertHidden(c.node); +    assertHidden(c.view);      c.scope.$set('show', '');      c.scope.$eval(); -    assertHidden(c.node); +    assertHidden(c.view);    });    it('BindClassUndefined', function(){ @@ -401,7 +399,7 @@ describe('Binder', function(){      assertEquals(          '<div class="undefined" ng:class="undefined"></div>', -        sortedHtml(doc.node)); +        sortedHtml(doc.view));    });    it('BindClass', function(){ @@ -410,26 +408,26 @@ describe('Binder', function(){      c.scope.$set('class', 'testClass');      c.scope.$eval(); -    assertEquals('<div class="testClass" ng:class="class"></div>', sortedHtml(c.node)); +    assertEquals('<div class="testClass" ng:class="class"></div>', sortedHtml(c.view));      c.scope.$set('class', ['a', 'b']);      c.scope.$eval(); -    assertEquals('<div class="a b" ng:class="class"></div>', sortedHtml(c.node)); +    assertEquals('<div class="a b" ng:class="class"></div>', sortedHtml(c.view));    });    it('BindClassEvenOdd', function(){      var x = this.compile('<div><div ng:repeat="i in [0,1]" ng:class-even="\'e\'" ng:class-odd="\'o\'"/></div>');      x.scope.$eval(); -    var d1 = jqLite(x.node[0].childNodes[1]); -    var d2 = jqLite(x.node[0].childNodes[2]); +    var d1 = jqLite(x.view[0].childNodes[1]); +    var d2 = jqLite(x.view[0].childNodes[2]);      expect(d1.hasClass('o')).toBeTruthy();      expect(d2.hasClass('e')).toBeTruthy();      assertEquals(          '<div><#comment></#comment>' +          '<div class="o" ng:class-even="\'e\'" ng:class-odd="\'o\'" ng:repeat-index="0"></div>' +          '<div class="e" ng:class-even="\'e\'" ng:class-odd="\'o\'" ng:repeat-index="1"></div></div>', -        sortedHtml(x.node)); +        sortedHtml(x.view));    });    it('BindStyle', function(){ @@ -438,7 +436,7 @@ describe('Binder', function(){      c.scope.$eval('style={color:"red"}');      c.scope.$eval(); -    assertEquals("red", c.node.css('color')); +    assertEquals("red", c.view.css('color'));      c.scope.$eval('style={}');      c.scope.$eval(); @@ -449,7 +447,7 @@ describe('Binder', function(){      c.scope.action = function(){        throw new Error('MyError');      }; -    var input = c.node; +    var input = c.view;      browserTrigger(input, 'click');      var error = input.attr('ng-exception');      assertTrue(!!error.match(/MyError/)); @@ -470,14 +468,14 @@ describe('Binder', function(){          "<div ng:non-bindable='true'>{{c}}</div></div>");      c.scope.$set('a', 123);      c.scope.$eval(); -    assertEquals('123{{a}}{{b}}{{c}}', c.node.text()); +    assertEquals('123{{a}}{{b}}{{c}}', c.view.text());    });    it('OptionShouldUpdateParentToGetProperBinding', function(){      var c = this.compile('<select name="s"><option ng:repeat="i in [0,1]" value="{{i}}" ng:bind="i"></option></select>');      c.scope.$set('s', 1);      c.scope.$eval(); -    assertEquals(1, c.node[0].selectedIndex); +    assertEquals(1, c.view[0].selectedIndex);    });    it('RepeaterShouldBindInputsDefaults', function () { @@ -494,7 +492,7 @@ describe('Binder', function(){      c.scope.$set("name", "World");      c.scope.$eval(); -    assertEquals('<pre ng:bind-template="Hello {{name}}!">Hello World!</pre>', sortedHtml(c.node)); +    assertEquals('<pre ng:bind-template="Hello {{name}}!">Hello World!</pre>', sortedHtml(c.view));    });    it('FillInOptionValueWhenMissing', function(){ @@ -503,9 +501,9 @@ describe('Binder', function(){      c.scope.$set('a', 'A');      c.scope.$set('b', 'B');      c.scope.$eval(); -    var optionA = childNode(c.node, 0); -    var optionB = childNode(c.node, 1); -    var optionC = childNode(c.node, 2); +    var optionA = childNode(c.view, 0); +    var optionB = childNode(c.view, 1); +    var optionC = childNode(c.view, 2);      expect(optionA.attr('value')).toEqual('A');      expect(optionA.text()).toEqual('A'); @@ -565,7 +563,7 @@ describe('Binder', function(){          '<input name="c0" ng:bind-attr="{disabled:\'{{[0]}}\'}"><input name="c1" ng:bind-attr="{disabled:\'{{[]}}\'}"></div>');      c.scope.$eval();      function assertChild(index, disabled) { -      var child = childNode(c.node, index); +      var child = childNode(c.view, index);        assertEquals(sortedHtml(child), disabled, !!child.attr('disabled'));      } @@ -581,8 +579,8 @@ describe('Binder', function(){      var c = this.compile('<div>' +          '<input type="button" ng:click="greeting=\'ABC\'"/>' +          '<input type="button" ng:click=":garbage:"/></div>'); -    var first = jqLite(c.node[0].childNodes[0]); -    var second = jqLite(c.node[0].childNodes[1]); +    var first = jqLite(c.view[0].childNodes[0]); +    var second = jqLite(c.view[0].childNodes[1]);      var errorLogs = c.scope.$service('$log').error.logs;      browserTrigger(first, 'click'); @@ -598,8 +596,8 @@ describe('Binder', function(){      var c = this.compile('<div>' +          '<input type="radio" name="sex" value="female"/>' +          '<input type="radio" name="sex" value="male"/></div>'); -    var female = jqLite(c.node[0].childNodes[0]); -    var male = jqLite(c.node[0].childNodes[1]); +    var female = jqLite(c.view[0].childNodes[0]); +    var male = jqLite(c.view[0].childNodes[1]);      browserTrigger(female);      assertEquals("female", c.scope.sex); @@ -636,7 +634,7 @@ describe('Binder', function(){          '<li ng:bind=\"k + v\" ng:repeat-index="0">a0</li>' +          '<li ng:bind=\"k + v\" ng:repeat-index="1">b1</li>' +          '</ul>', -        sortedHtml(x.node)); +        sortedHtml(x.view));    });    it('ItShouldFireChangeListenersBeforeUpdate', function(){ @@ -648,13 +646,13 @@ describe('Binder', function(){      assertEquals(123, x.scope.$get("name"));      assertEquals(          '<div ng:bind="name">123</div>', -        sortedHtml(x.node)); +        sortedHtml(x.view));    });    it('ItShouldHandleMultilineBindings', function(){      var x = this.compile('<div>{{\n 1 \n + \n 2 \n}}</div>');      x.scope.$eval(); -    assertEquals("3", x.node.text()); +    assertEquals("3", x.view.text());    });    it('ItBindHiddenInputFields', function(){ @@ -667,7 +665,7 @@ describe('Binder', function(){      var x = this.compile('<input name="a" ng:format="list" value="a,b">');      x.scope.$eval();      assertEquals(['a','b'], x.scope.$get('a')); -    var input = x.node; +    var input = x.view;      input[0].value = ' x,,yz';      browserTrigger(input, 'change');      assertEquals(['x','yz'], x.scope.$get('a')); diff --git a/test/CompilerSpec.js b/test/CompilerSpec.js index 647cc366..1a93ac78 100644 --- a/test/CompilerSpec.js +++ b/test/CompilerSpec.js @@ -27,8 +27,7 @@ describe('compiler', function(){      compiler = new Compiler(markup, attrMarkup, directives, widgets);      compile = function(html){        var e = jqLite("<div>" + html + "</div>"); -      var scope = compiler.compile(e)(e); -      return scope; +      return scope = compiler.compile(e)().scope;      };    }); @@ -48,7 +47,7 @@ describe('compiler', function(){      };      var template = compiler.compile(e);      expect(log).toEqual("found"); -    scope = template(e); +    scope = template(angular.scope(), e).scope;      expect(e.hasClass('ng-directive')).toEqual(true);      expect(log).toEqual("found:init");    }); @@ -85,7 +84,7 @@ describe('compiler', function(){        var template = this.compile(element);        return function(marker) {          this.$onEval(function() { -          marker.after(template(element.clone()).$element); +          marker.after(template(angular.scope(), true).view);          });        };      }; diff --git a/test/ResourceSpec.js b/test/ResourceSpec.js index d61282ea..adc93b92 100644 --- a/test/ResourceSpec.js +++ b/test/ResourceSpec.js @@ -169,7 +169,7 @@ describe("resource", function() {    });    it('should excersize full stack', function(){ -    var scope = angular.compile('<div></div>'); +    var scope = angular.compile('<div></div>')().scope;      var $browser = scope.$service('$browser');      var $resource = scope.$service('$resource');      var Person = $resource('/Person/:id'); @@ -181,7 +181,7 @@ describe("resource", function() {    });    it('should return the same object when verifying the cache', function(){ -    var scope = angular.compile('<div></div>'); +    var scope = angular.compile('<div></div>')().scope;      var $browser = scope.$service('$browser');      var $resource = scope.$service('$resource');      var Person = $resource('/Person/:id', null, {query: {method:'GET', isArray: true, verifyCache: true}}); diff --git a/test/ScenarioSpec.js b/test/ScenarioSpec.js index cd1e3115..ce8ce69c 100644 --- a/test/ScenarioSpec.js +++ b/test/ScenarioSpec.js @@ -12,25 +12,25 @@ describe("ScenarioSpec: Compilation", function(){    describe('compilation', function(){      it("should compile dom node and return scope", function(){        var node = jqLite('<div ng:init="a=1">{{b=a+1}}</div>')[0]; -      scope = compile(node); +      scope = angular.compile(node)().scope;        expect(scope.a).toEqual(1);        expect(scope.b).toEqual(2);      });      it("should compile jQuery node and return scope", function(){ -      scope = compile(jqLite('<div>{{a=123}}</div>')); +      scope = compile(jqLite('<div>{{a=123}}</div>'))().scope;        expect(jqLite(scope.$element).text()).toEqual('123');      });      it("should compile text node and return scope", function(){ -      scope = compile('<div>{{a=123}}</div>'); +      scope = angular.compile('<div>{{a=123}}</div>')().scope;        expect(jqLite(scope.$element).text()).toEqual('123');      });    });    describe('scope', function(){      it("should have $set, $get, $eval, $updateView methods", function(){ -      scope = compile('<div>{{a}}</div>'); +      scope = angular.compile('<div>{{a}}</div>')().scope;        scope.$eval("$invalidWidgets.push({})");        expect(scope.$set("a", 2)).toEqual(2);        expect(scope.$get("a")).toEqual(2); @@ -40,7 +40,7 @@ describe("ScenarioSpec: Compilation", function(){      });      it("should have $ objects", function(){ -      scope = compile('<div></div>', {$config: {a:"b"}}); +      scope = angular.compile('<div></div>')(angular.scope({$config: {a:"b"}})).scope;        expect(scope.$service('$location')).toBeDefined();        expect(scope.$get('$eval')).toBeDefined();        expect(scope.$get('$config')).toBeDefined(); @@ -51,7 +51,7 @@ describe("ScenarioSpec: Compilation", function(){    describe("configuration", function(){      it("should take location object", function(){        var url = "http://server/#?book=moby"; -      scope = compile("<div>{{$location}}</div>"); +      scope = angular.compile("<div>{{$location}}</div>")().scope;        var $location = scope.$service('$location');        var $browser = scope.$service('$browser');        expect($location.hashSearch.book).toBeUndefined(); diff --git a/test/ValidatorsSpec.js b/test/ValidatorsSpec.js index 65b93133..2d4fca98 100644 --- a/test/ValidatorsSpec.js +++ b/test/ValidatorsSpec.js @@ -7,7 +7,7 @@ describe('ValidatorTest', function(){        validator.last = last;        validator._this = this;      }; -    var scope = compile('<input name="name" ng:validate="myValidator:\'hevery\'"/>'); +    var scope = compile('<input name="name" ng:validate="myValidator:\'hevery\'"/>')().scope;      scope.name = 'misko';      scope.$eval();      assertEquals('misko', validator.first); @@ -95,7 +95,7 @@ describe('ValidatorTest', function(){      beforeEach(function(){        value = null;        fn = null; -      self = compile('<input />'); +      self = angular.compile('<input />')().scope;        jqLite(document.body).append(self.$element);        self.$element.data('$validate', noop);        self.$root = self; @@ -107,7 +107,8 @@ describe('ValidatorTest', function(){      it('should make a request and show spinner', function(){        var value, fn; -      var scope = compile('<input type="text" name="name" ng:validate="asynchronous:asyncFn"/>'); +      var scope = angular.compile( +          '<input type="text" name="name" ng:validate="asynchronous:asyncFn"/>')().scope;        jqLite(document.body).append(scope.$element);        var input = scope.$element;        scope.asyncFn = function(v,f){ @@ -149,7 +150,8 @@ describe('ValidatorTest', function(){      });      it("should handle update function", function(){ -      var scope = angular.compile('<input name="name" ng:validate="asynchronous:asyncFn:updateFn"/>'); +      var scope = angular.compile( +          '<input name="name" ng:validate="asynchronous:asyncFn:updateFn"/>')().scope;        scope.asyncFn = jasmine.createSpy();        scope.updateFn = jasmine.createSpy();        scope.name = 'misko'; diff --git a/test/directivesSpec.js b/test/directivesSpec.js index 8e5a10ee..2d4703a2 100644 --- a/test/directivesSpec.js +++ b/test/directivesSpec.js @@ -3,11 +3,9 @@ describe("directive", function(){    var compile, model, element;    beforeEach(function() { -    var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget);      compile = function(html) {        element = jqLite(html); -      model = compiler.compile(element)(element); -      return model; +      return model = angular.compile(element)().scope;      };    }); diff --git a/test/markupSpec.js b/test/markupSpec.js index 2462f19e..2c933f09 100644 --- a/test/markupSpec.js +++ b/test/markupSpec.js @@ -5,10 +5,9 @@ describe("markups", function(){    beforeEach(function() {      scope = null;      element = null; -    var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget);      compile = function(html) {        element = jqLite(html); -      scope = compiler.compile(element)(element); +      scope = angular.compile(element)().scope;      };    }); diff --git a/test/service/invalidWidgetsSpec.js b/test/service/invalidWidgetsSpec.js index b6b2da61..4a18dcf8 100644 --- a/test/service/invalidWidgetsSpec.js +++ b/test/service/invalidWidgetsSpec.js @@ -12,9 +12,9 @@ describe('$invalidWidgets', function() {    it("should count number of invalid widgets", function(){ -    scope = compile('<input name="price" ng:required ng:validate="number"></input>'); -    jqLite(document.body).append(scope.$element); -    scope.$init(); +    var element = jqLite('<input name="price" ng:required ng:validate="number"></input>') +    jqLite(document.body).append(element); +    scope = compile(element)().scope;      var $invalidWidgets = scope.$service('$invalidWidgets');      expect($invalidWidgets.length).toEqual(1); diff --git a/test/service/routeSpec.js b/test/service/routeSpec.js index 95258cc8..4dfa546c 100644 --- a/test/service/routeSpec.js +++ b/test/service/routeSpec.js @@ -18,7 +18,7 @@ describe('$route', function() {      function BookChapter() {        this.log = '<init>';      } -    scope = compile('<div></div>').$init(); +    scope = compile('<div></div>')().scope;      $location = scope.$service('$location');      $route = scope.$service('$route');      $route.when('/Book/:book/Chapter/:chapter', {controller: BookChapter, template:'Chapter.html'}); @@ -87,7 +87,7 @@ describe('$route', function() {          $route = scope.$service('$route'),          onChangeSpy = jasmine.createSpy('onChange'); -    function NotFoundCtrl() {this.notFoundProp = 'not found!'} +    function NotFoundCtrl() {this.notFoundProp = 'not found!';}      $route.when('/foo', {template: 'foo.html'});      $route.otherwise({template: '404.html', controller: NotFoundCtrl}); diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js index 606491a9..d4d0e43a 100644 --- a/test/widgetsSpec.js +++ b/test/widgetsSpec.js @@ -4,7 +4,6 @@ describe("widget", function(){    beforeEach(function() {      scope = null;      element = null; -    var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget);      compile = function(html, parent) {        if (parent) {          parent.html(html); @@ -12,8 +11,7 @@ describe("widget", function(){        } else {          element = jqLite(html);        } -      scope = compiler.compile(element)(element); -      return scope; +      return scope = angular.compile(element)().scope;      };    }); @@ -594,7 +592,7 @@ describe("widget", function(){      });      it('should call change on switch', function(){ -      var scope = angular.compile('<ng:switch on="url" change="name=\'works\'"><div ng:switch-when="a">{{name}}</div></ng:switch>'); +      var scope = angular.compile('<ng:switch on="url" change="name=\'works\'"><div ng:switch-when="a">{{name}}</div></ng:switch>')().scope;        scope.url = 'a';        scope.$eval();        expect(scope.name).toEqual(undefined); @@ -606,7 +604,7 @@ describe("widget", function(){    describe('ng:include', function(){      it('should include on external file', function() {        var element = jqLite('<ng:include src="url" scope="childScope"></ng:include>'); -      var scope = angular.compile(element); +      var scope = angular.compile(element)().scope;        scope.childScope = createScope();        scope.childScope.name = 'misko';        scope.url = 'myUrl'; @@ -619,7 +617,7 @@ describe("widget", function(){      it('should remove previously included text if a falsy value is bound to src', function() {        var element = jqLite('<ng:include src="url" scope="childScope"></ng:include>'); -      var scope = angular.compile(element); +      var scope = angular.compile(element)().scope;        scope.childScope = createScope();        scope.childScope.name = 'igor';        scope.url = 'myUrl'; @@ -638,7 +636,7 @@ describe("widget", function(){      it('should allow this for scope', function(){        var element = jqLite('<ng:include src="url" scope="this"></ng:include>'); -      var scope = angular.compile(element); +      var scope = angular.compile(element)().scope;        scope.url = 'myUrl';        scope.$service('$xhr.cache').data.myUrl = {value:'{{c=c+1}}'};        scope.$eval(); @@ -652,7 +650,7 @@ describe("widget", function(){      it('should evaluate onload expression when a partial is loaded', function() {        var element = jqLite('<ng:include src="url" onload="loaded = true"></ng:include>'); -      var scope = angular.compile(element); +      var scope = angular.compile(element)().scope;        expect(scope.loaded).not.toBeDefined(); @@ -791,7 +789,7 @@ describe("widget", function(){      var rootScope, rootScope, $route, $location, $browser;      beforeEach(function() { -      rootScope = angular.compile('<ng:view></ng:view>'); +      rootScope = angular.compile('<ng:view></ng:view>')().scope;        $route = rootScope.$service('$route');        $location = rootScope.$service('$location');        $browser = rootScope.$service('$browser'); @@ -870,7 +868,7 @@ describe("widget", function(){        rootScope = angular.compile(            '<div>' +              'include: <ng:include src="\'includePartial.html\'">' + -          '</ng:include></div>', myApp); +          '</ng:include></div>')(myApp).scope;        $browser.xhr.expectGET('viewPartial.html').respond('content');        $browser.xhr.flush(); | 
