diff options
| -rw-r--r-- | src/Angular.js | 21 | ||||
| -rw-r--r-- | src/Compiler.js | 17 | ||||
| -rw-r--r-- | src/Scope.js | 192 | ||||
| -rw-r--r-- | src/directives.js | 120 | ||||
| -rw-r--r-- | src/widgets2.js | 2 | ||||
| -rw-r--r-- | test/directivesSpec.js | 96 | ||||
| -rw-r--r-- | test/markupSpec.js | 17 | ||||
| -rw-r--r-- | test/widgetsSpec.js | 96 |
8 files changed, 347 insertions, 214 deletions
diff --git a/src/Angular.js b/src/Angular.js index 0c6d081e..0cb89bbe 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -208,27 +208,6 @@ function bind(_this, _function) { }; } -function bindTry(_this, _function) { - var args = arguments, - last = args.length - 1, - curryArgs = slice.call(args, 2, last), - exceptionHandler = args[last]; - return function() { - try { - return _function.apply(_this, curryArgs.concat(slice.call(arguments, 0, arguments.length))); - } catch (e) { - if (e = exceptionHandler(e)) throw e; - } - }; -} - -function errorHandlerFor(element) { - return function(error){ - element.attr('ng-error', angular.toJson(error)); - element.addClass('ng-exception'); - }; -} - function outerHTML(node) { var temp = document.createElement('div'); temp.appendChild(node); diff --git a/src/Compiler.js b/src/Compiler.js index 47ab0c14..3b492ebe 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -14,7 +14,7 @@ Template.prototype = { init: function(element, scope) { element = jqLite(element); foreach(this.inits, function(fn) { - scope.apply(fn, element); + scope.$tryEval(fn, element, element); }); var i, @@ -92,14 +92,11 @@ Compiler.prototype = { rawElement = jqLite(rawElement); var template = this.templatize(rawElement) || new Template(); return function(element, parentScope){ - var scope = new Scope(parentScope); - scope.element = element; - // todo return should be a scope with everything already set on it as element - return { - scope: scope, - element:element, - init: bind(template, template.init, element, scope) - }; + var model = scope(parentScope); + return extend(model, { + $element:element, + $init: bind(template, template.init, element, model) + }); }; }, @@ -144,7 +141,7 @@ Compiler.prototype = { exclusive = true; directiveQueue = []; } - directiveQueue.push(bindTry(selfApi, directive, value, element, errorHandlerFor(element))); + directiveQueue.push(bind(selfApi, directive, value, element)); } }); diff --git a/src/Scope.js b/src/Scope.js index 5f1cfdda..ccf55077 100644 --- a/src/Scope.js +++ b/src/Scope.js @@ -53,6 +53,21 @@ Scope.getter = function(instance, path) { return instance; }; +Scope.setter = function(instance, path, value){ + var element = path.split('.'); + for ( var i = 0; element.length > 1; i++) { + var key = element.shift(); + var newInstance = instance[key]; + if (!newInstance) { + newInstance = {}; + instance[key] = newInstance; + } + instance = newInstance; + } + instance[element.shift()] = value; + return value; +}; + Scope.prototype = { // TODO: rename to update? or eval? updateView: function() { @@ -98,19 +113,8 @@ Scope.prototype = { set: function(path, value) { // log('SCOPE.set', path, value); - var element = path.split('.'); var instance = this.state; - for ( var i = 0; element.length > 1; i++) { - var key = element.shift(); - var newInstance = instance[key]; - if (!newInstance) { - newInstance = {}; - instance[key] = newInstance; - } - instance = newInstance; - } - instance[element.shift()] = value; - return value; + return Scope.setter(instance, path, value); }, setEval: function(expressionText, value) { @@ -134,9 +138,9 @@ Scope.prototype = { }; }, - eval: function(expressionText, context) { + eval: function(exp, context) { // log('Scope.eval', expressionText); - return this.compile(expressionText)(context); + return this.compile(exp)(context); }, //TODO: Refactor. This function needs to be an execution closure for widgets @@ -241,3 +245,163 @@ Scope.prototype = { fn.apply(this.state, slice.call(arguments, 1, arguments.length)); } }; + +////////////////////////////// + +function getter(instance, path) { + if (!path) return instance; + var element = path.split('.'); + var key; + var lastInstance = instance; + var len = element.length; + for ( var i = 0; i < len; i++) { + key = element[i]; + if (!key.match(/^[\$\w][\$\w\d]*$/)) + throw "Expression '" + path + "' is not a valid expression for accesing variables."; + if (instance) { + lastInstance = instance; + instance = instance[key]; + } + if (_.isUndefined(instance) && key.charAt(0) == '$') { + var type = angular['Global']['typeOf'](lastInstance); + type = angular[type.charAt(0).toUpperCase()+type.substring(1)]; + var fn = type ? type[[key.substring(1)]] : undefined; + if (fn) { + instance = _.bind(fn, lastInstance, lastInstance); + return instance; + } + } + } + if (typeof instance === 'function' && !instance['$$factory']) { + return bind(lastInstance, instance); + } + return instance; +}; + +function setter(instance, path, value){ + var element = path.split('.'); + for ( var i = 0; element.length > 1; i++) { + var key = element.shift(); + var newInstance = instance[key]; + if (!newInstance) { + newInstance = {}; + instance[key] = newInstance; + } + instance = newInstance; + } + instance[element.shift()] = value; + return value; +}; + +var compileCache = {}; +function expressionCompile(exp){ + if (isFunction(exp)) return exp; + var expFn = compileCache[exp]; + if (!expFn) { + var parser = new Parser(exp); + expFn = parser.statements(); + parser.assertAllConsumed(); + compileCache[exp] = expFn; + } + // return expFn + // TODO(remove this hack) + return function(){ + return expFn({ + scope: { + set: this.$set, + get: this.$get + } + }); + }; +}; + +var NON_RENDERABLE_ELEMENTS = { + '#text': 1, '#comment':1, 'TR':1, 'TH':1 +}; + +function isRenderableElement(element){ + return element && element[0] && !NON_RENDERABLE_ELEMENTS[element[0].nodeName]; +} + +function rethrow(e) { throw e; } +function errorHandlerFor(element) { + while (!isRenderableElement(element)) { + element = element.parent() || jqLite(document.body); + } + return function(error) { + element.attr('ng-error', angular.toJson(error)); + element.addClass('ng-exception'); + }; +} + +function scope(parent, Class) { + function Parent(){} + function API(){} + function Behavior(){} + + var instance, behavior, api, watchList = [], evalList = []; + + Class = Class || noop; + parent = Parent.prototype = parent || {}; + api = API.prototype = new Parent(); + behavior = Behavior.prototype = extend(new API(), Class.prototype); + instance = new Behavior(); + + extend(api, { + $parent: parent, + $bind: bind(instance, bind, instance), + $get: bind(instance, getter, instance), + $set: bind(instance, setter, instance), + + $eval: function(exp) { + if (isDefined(exp)) { + return expressionCompile(exp).apply(instance, slice.call(arguments, 1, arguments.length)); + } else { + foreach(evalList, function(eval) { + instance.$tryEval(eval.fn, eval.handler); + }); + foreach(watchList, function(watch) { + var value = instance.$tryEval(watch.watch, watch.handler); + if (watch.last !== value) { + instance.$tryEval(watch.listener, watch.handler, value, watch.last); + watch.last = value; + } + }); + } + }, + + $tryEval: function (expression, exceptionHandler) { + try { + return expressionCompile(expression).apply(instance, slice.call(arguments, 2, arguments.length)); + } catch (e) { + error(e); + if (isFunction(exceptionHandler)) { + exceptionHandler(e); + } else if (exceptionHandler) { + errorHandlerFor(exceptionHandler)(e); + } + } + }, + + $watch: function(watchExp, listener, exceptionHandler) { + var watch = expressionCompile(watchExp); + watchList.push({ + watch: watch, + last: watch.call(instance), + handler: exceptionHandler, + listener:expressionCompile(listener) + }); + }, + + $onEval: function(expr, exceptionHandler){ + evalList.push({ + fn: expressionCompile(expr), + handler: exceptionHandler + }); + } + }); + + Class.apply(instance, slice.call(arguments, 2, arguments.length)); + + return instance; +} diff --git a/src/directives.js b/src/directives.js index 747da3f5..10476c77 100644 --- a/src/directives.js +++ b/src/directives.js @@ -1,12 +1,12 @@ angularDirective("ng-init", function(expression){ - return function(){ - this.$eval(expression); + return function(element){ + this.$tryEval(expression, element); }; }); angularDirective("ng-eval", function(expression){ - return function(){ - this.$addEval(expression); + return function(element){ + this.$onEval(expression, element); }; }); @@ -14,7 +14,7 @@ angularDirective("ng-bind", function(expression){ return function(element) { this.$watch(expression, function(value){ element.text(value); - }); + }, element); }; }); @@ -45,23 +45,23 @@ angularDirective("ng-bind-template", function(expression){ var templateFn = compileBindTemplate(expression); return function(element) { var lastValue; - this.$addEval(function() { + this.$onEval(function() { var value = templateFn.call(this); if (value != lastValue) { element.text(value); lastValue = value; } - }); + }, element); }; }); angularDirective("ng-bind-attr", function(expression){ return function(element){ - this.$addEval(function(){ + this.$onEval(function(){ foreach(this.$eval(expression), function(value, key){ element.attr(key, compileBindTemplate(value).call(this)); }, this); - }); + }, element); }; }); @@ -70,76 +70,73 @@ angularDirective("ng-non-bindable", function(){ }); angularDirective("ng-repeat", function(expression, element){ - var reference = this.comment("ng-repeat: " + expression), - r = element.removeAttr('ng-repeat'), - template = this.compile(element), - match = expression.match(/^\s*(.+)\s+in\s+(.*)\s*$/), - lhs, rhs, valueIdent, keyIdent; - if (! match) { - throw "Expected ng-repeat in form of 'item in collection' but got '" + + element.removeAttr('ng-repeat'); + element.replaceWith(this.comment("ng-repeat: " + expression)); + var template = this.compile(element); + return function(reference){ + var match = expression.match(/^\s*(.+)\s+in\s+(.*)\s*$/), + lhs, rhs, valueIdent, keyIdent; + if (! match) { + throw "Expected ng-repeat in form of 'item in collection' but got '" + expression + "'."; - } - lhs = match[1]; - rhs = match[2]; - match = lhs.match(/^([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\)$/); - if (!match) { - throw "'item' in 'item in collection' should be identifier or (key, value) but got '" + + } + lhs = match[1]; + rhs = match[2]; + match = lhs.match(/^([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\)$/); + if (!match) { + throw "'item' in 'item in collection' should be identifier or (key, value) but got '" + keyValue + "'."; - } - valueIdent = match[3] || match[1]; - keyIdent = match[2]; + } + valueIdent = match[3] || match[1]; + keyIdent = match[2]; - var parent = element.parent(); - element.replaceWith(reference); - return function(){ - var children = [], - currentScope = this; - this.$addEval(rhs, function(items){ + var children = [], currentScope = this; + this.$onEval(function(){ var index = 0, childCount = children.length, childScope, lastElement = reference; - foreach(items || [], function(value, key){ + foreach(this.$tryEval(rhs, reference), function(value, key){ if (index < childCount) { // reuse existing child childScope = children[index]; } else { // grow children childScope = template(element.clone(), currentScope); - childScope.init(); - childScope.scope.set('$index', index); - childScope.element.attr('ng-index', index); - lastElement.after(childScope.element); + lastElement.after(childScope.$element); + childScope.$index = index; + childScope.$element.attr('ng-index', index); + childScope.$init(); children.push(childScope); } - childScope.scope.set(valueIdent, value); - if (keyIdent) childScope.scope.set(keyIdent, key); - childScope.scope.updateView(); - lastElement = childScope.element; + childScope[valueIdent] = value; + if (keyIdent) childScope[keyIdent] = key; + childScope.$eval(); + lastElement = childScope.$element; index ++; }); // shrink children while(children.length > index) { - children.pop().element.remove(); + children.pop().$element.remove(); } - }); + }, reference); }; }, {exclusive: true}); angularDirective("ng-action", function(expression, element){ - return function(){ + return function(element){ var self = this; element.click(function(){ - self.$eval(expression); + self.$tryEval(expression, element); }); }; }); angularDirective("ng-watch", function(expression, element){ var match = expression.match(/^([^.]*):(.*)$/); - if (!match) { - throw "Expecting watch expression 'ident_to_watch: watch_statement' got '" - + expression + "'"; - } - return function(){ - this.$watch(match[1], match[2]); + return function(element){ + if (!match) { + throw "Expecting watch expression 'ident_to_watch: watch_statement' got '" + + expression + "'"; + } + this.$watch(match[1], match[2], element); }; }); @@ -147,12 +144,13 @@ function ngClass(selector) { return function(expression, element){ var existing = element[0].className + ' '; return function(element){ - this.$addEval(expression, function(value){ + this.$onEval(function(){ + var value = this.$eval(expression); if (selector(this.$index)) { if (isArray(value)) value = value.join(' '); element[0].className = (existing + value).replace(/\s\s+/g, ' '); } - }); + }, element); }; }; } @@ -163,25 +161,25 @@ angularDirective("ng-class-even", ngClass(function(i){return i % 2 == 0;})); angularDirective("ng-show", function(expression, element){ return function(element){ - this.$addEval(expression, function(value){ - element.css('display', toBoolean(value) ? '' : 'none'); - }); + this.$onEval(function(){ + element.css('display', toBoolean(this.$eval(expression)) ? '' : 'none'); + }, element); }; }); angularDirective("ng-hide", function(expression, element){ return function(element){ - this.$addEval(expression, function(value){ - element.css('display', toBoolean(value) ? 'none' : ''); - }); + this.$onEval(function(){ + element.css('display', toBoolean(this.$eval(expression)) ? 'none' : ''); + }, element); }; }); angularDirective("ng-style", function(expression, element){ return function(element){ - this.$addEval(expression, function(value){ - element.css(value); - }); + this.$onEval(function(){ + element.css(this.$eval(expression)); + }, element); }; }); diff --git a/src/widgets2.js b/src/widgets2.js index c4b39bc1..21da3986 100644 --- a/src/widgets2.js +++ b/src/widgets2.js @@ -96,7 +96,7 @@ var NG_ERROR = 'ng-error', 'radio': inputWidget('click', modelAccessor, radioAccessor, undefined), 'select-one': inputWidget('click', modelAccessor, valueAccessor, null), 'select-multiple': inputWidget('click', modelAccessor, optionsAccessor, []) -// 'file': [{}, 'click'] +// 'file': fileWidget??? }; function inputWidget(events, modelAccessor, viewAccessor, initValue) { diff --git a/test/directivesSpec.js b/test/directivesSpec.js index 83a270c1..4ef57dce 100644 --- a/test/directivesSpec.js +++ b/test/directivesSpec.js @@ -1,49 +1,49 @@ describe("directives", function(){ - var compile, element; + var compile, model, element; beforeEach(function() { var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget); compile = function(html) { element = jqLite(html); - var view = compiler.compile(element)(element); - view.init(); - return view.scope; + model = compiler.compile(element)(element); + model.$init(); + return model; }; }); afterEach(function() { - element.remove(); + model.$element.remove(); expect(_(jqCache).size()).toEqual(0); }); it("should ng-init", function() { var scope = compile('<div ng-init="a=123"></div>'); - expect(scope.get('a')).toEqual(123); + expect(scope.a).toEqual(123); }); it("should ng-eval", function() { var scope = compile('<div ng-init="a=0" ng-eval="a = a + 1"></div>'); - expect(scope.get('a')).toEqual(0); - scope.updateView(); - expect(scope.get('a')).toEqual(1); - scope.updateView(); - expect(scope.get('a')).toEqual(2); + expect(scope.a).toEqual(0); + scope.$eval(); + expect(scope.a).toEqual(1); + scope.$eval(); + expect(scope.a).toEqual(2); }); it('should ng-bind', function() { var scope = compile('<div ng-bind="a"></div>'); expect(element.text()).toEqual(''); - scope.set('a', 'misko'); - scope.updateView(); + scope.a = 'misko'; + scope.$eval(); expect(element.text()).toEqual('misko'); }); it('should ng-bind-template', function() { var scope = compile('<div ng-bind-template="Hello {{name}}!"></div>'); expect(element.text()).toEqual(''); - scope.set('name', 'Misko'); - scope.updateView(); + scope.$set('name', 'Misko'); + scope.$eval(); expect(element.text()).toEqual('Hello Misko!'); }); @@ -51,75 +51,73 @@ describe("directives", function(){ var scope = compile('<img ng-bind-attr="{src:\'mysrc\', alt:\'myalt\'}"/>'); expect(element.attr('src')).toEqual(null); expect(element.attr('alt')).toEqual(null); - scope.updateView(); + scope.$eval(); expect(element.attr('src')).toEqual('mysrc'); expect(element.attr('alt')).toEqual('myalt'); }); it('should ng-non-bindable', function(){ var scope = compile('<div ng-non-bindable><span ng-bind="name"></span></div>'); - scope.set('name', 'misko'); - scope.updateView(); + scope.$set('name', 'misko'); + scope.$eval(); expect(element.text()).toEqual(''); }); it('should ng-repeat over array', function(){ var scope = compile('<ul><li ng-repeat="item in items" ng-init="suffix = \';\'" ng-bind="item + suffix"></li></ul>'); - scope.set('items', ['misko', 'shyam']); - scope.updateView(); + scope.$set('items', ['misko', 'shyam']); + scope.$eval(); expect(element.text()).toEqual('misko;shyam;'); - scope.set('items', ['adam', 'kai', 'brad']); - scope.updateView(); + scope.$set('items', ['adam', 'kai', 'brad']); + scope.$eval(); expect(element.text()).toEqual('adam;kai;brad;'); - scope.set('items', ['brad']); - scope.updateView(); + scope.$set('items', ['brad']); + scope.$eval(); expect(element.text()).toEqual('brad;'); }); it('should ng-repeat over object', function(){ var scope = compile('<ul><li ng-repeat="(key, value) in items" ng-bind="key + \':\' + value + \';\' "></li></ul>'); - scope.set('items', {misko:'swe', shyam:'set'}); - scope.updateView(); + scope.$set('items', {misko:'swe', shyam:'set'}); + scope.$eval(); expect(element.text()).toEqual('misko:swe;shyam:set;'); }); it('should error on wrong parsing of ng-repeat', function(){ var scope = compile('<ul><li ng-repeat="i dont parse"></li></ul>'); var log = ""; - eachNode(element, function(li){ - log += li.attr('ng-error') + ';'; - log += li.hasClass('ng-exception') + ';'; - }); + log += element.attr('ng-error') + ';'; + log += element.hasClass('ng-exception') + ';'; expect(log).toEqual("\"Expected ng-repeat in form of 'item in collection' but got 'i dont parse'.\";true;"); }); it('should ng-watch', function(){ var scope = compile('<div ng-watch="i: count = count + 1" ng-init="count = 0">'); - scope.updateView(); - scope.updateView(); - expect(scope.get('count')).toEqual(0); + scope.$eval(); + scope.$eval(); + expect(scope.$get('count')).toEqual(0); - scope.set('i', 0); - scope.updateView(); - scope.updateView(); - expect(scope.get('count')).toEqual(1); + scope.$set('i', 0); + scope.$eval(); + scope.$eval(); + expect(scope.$get('count')).toEqual(1); }); it('should ng-action', function(){ var scope = compile('<div ng-action="clicked = true"></div>'); - scope.updateView(); - expect(scope.get('clicked')).toBeFalsy(); + scope.$eval(); + expect(scope.$get('clicked')).toBeFalsy(); element.click(); - expect(scope.get('clicked')).toEqual(true); + expect(scope.$get('clicked')).toEqual(true); }); it('should ng-class', function(){ var scope = compile('<div class="existing" ng-class="[\'A\', \'B\']"></div>'); - scope.updateView(); + scope.$eval(); expect(element.hasClass('existing')).toBeTruthy(); expect(element.hasClass('A')).toBeTruthy(); expect(element.hasClass('B')).toBeTruthy(); @@ -127,7 +125,7 @@ describe("directives", function(){ it('should ng-class odd/even', function(){ var scope = compile('<ul><li ng-repeat="i in [0,1]" class="existing" ng-class-odd="\'odd\'" ng-class-even="\'even\'"></li><ul>'); - scope.updateView(); + scope.$eval(); var e1 = jQuery(element.parent()[0]).find('li:first'); var e2 = jQuery(element.parent()[0]).find('li:last'); expect(e1.hasClass('existing')).toBeTruthy(); @@ -138,25 +136,25 @@ describe("directives", function(){ it('should ng-style', function(){ var scope = compile('<div ng-style="{color:\'red\'}"></div>'); - scope.updateView(); + scope.$eval(); expect(element.css('color')).toEqual('red'); }); it('should ng-show', function(){ var scope = compile('<div ng-hide="hide"></div>'); - scope.updateView(); + scope.$eval(); expect(element.css('display')).toEqual(''); - scope.set('hide', true); - scope.updateView(); + scope.$set('hide', true); + scope.$eval(); expect(element.css('display')).toEqual('none'); }); it('should ng-hide', function(){ var scope = compile('<div ng-show="show"></div>'); - scope.updateView(); + scope.$eval(); expect(element.css('display')).toEqual('none'); - scope.set('show', true); - scope.updateView(); + scope.$set('show', true); + scope.$eval(); expect(element.css('display')).toEqual(''); }); }); diff --git a/test/markupSpec.js b/test/markupSpec.js index 8ea88f08..c83f27ff 100644 --- a/test/markupSpec.js +++ b/test/markupSpec.js @@ -8,9 +8,8 @@ describe("markups", function(){ var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget); compile = function(html) { element = jqLite(html); - var view = compiler.compile(element)(element); - view.init(); - scope = view.scope; + scope = compiler.compile(element)(element); + scope.$init(); }; }); @@ -24,16 +23,16 @@ describe("markups", function(){ it('should translate {{}} in text', function(){ compile('<div>hello {{name}}!</div>'); expect(element.html()).toEqual('hello <span ng-bind="name"></span>!'); - scope.set('name', 'Misko'); - scope.updateView(); + scope.$set('name', 'Misko'); + scope.$eval(); expect(element.html()).toEqual('hello <span ng-bind="name">Misko</span>!'); }); it('should translate {{}} in terminal nodes', function(){ compile('<select name="x"><option value="">Greet {{name}}!</option></select>'); expect(element.html()).toEqual('<option ng-bind-template="Greet {{name}}!" value=""></option>'); - scope.set('name', 'Misko'); - scope.updateView(); + scope.$set('name', 'Misko'); + scope.$eval(); expect(element.html()).toEqual('<option ng-bind-template="Greet {{name}}!" value="">Greet Misko!</option>'); }); @@ -41,8 +40,8 @@ describe("markups", function(){ compile('<img src="http://server/{{path}}.png"/>'); expect(element.attr('src')).toEqual(); expect(element.attr('ng-bind-attr')).toEqual('{"src":"http://server/{{path}}.png"}'); - scope.set('path', 'a/b'); - scope.updateView(); + scope.$set('path', 'a/b'); + scope.$eval(); expect(element.attr('src')).toEqual("http://server/a/b.png"); }); diff --git a/test/widgetsSpec.js b/test/widgetsSpec.js index 0f416278..7c9ea04a 100644 --- a/test/widgetsSpec.js +++ b/test/widgetsSpec.js @@ -1,6 +1,6 @@ describe("input widget", function(){ - var compile, element, scope, model; + var compile, element, scope; beforeEach(function() { scope = null; @@ -8,10 +8,8 @@ describe("input widget", function(){ var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget); compile = function(html) { element = jqLite(html); - var view = compiler.compile(element)(element); - view.init(); - scope = view.scope; - model = scope.state; + scope = compiler.compile(element)(element); + scope.$init(); }; }); @@ -22,35 +20,35 @@ describe("input widget", function(){ it('should input-text auto init and handle keyup/change events', function(){ compile('<input type="Text" name="name" value="Misko" ng-action="count = count + 1" ng-init="count=0"/>'); - expect(scope.get('name')).toEqual("Misko"); - expect(scope.get('count')).toEqual(0); + expect(scope.$get('name')).toEqual("Misko"); + expect(scope.$get('count')).toEqual(0); - scope.set('name', 'Adam'); - scope.updateView(); + scope.$set('name', 'Adam'); + scope.$eval(); expect(element.val()).toEqual("Adam"); element.val('Shyam'); element.trigger('keyup'); - expect(scope.get('name')).toEqual('Shyam'); - expect(scope.get('count')).toEqual(1); + expect(scope.$get('name')).toEqual('Shyam'); + expect(scope.$get('count')).toEqual(1); element.val('Kai'); element.trigger('change'); - expect(scope.get('name')).toEqual('Kai'); - expect(scope.get('count')).toEqual(2); + expect(scope.$get('name')).toEqual('Kai'); + expect(scope.$get('count')).toEqual(2); }); it("should process ng-format", function(){ compile('<input type="Text" name="list" value="a,b,c" ng-format="list"/>'); - expect(scope.get('list')).toEqual(['a', 'b', 'c']); + expect(scope.$get('list')).toEqual(['a', 'b', 'c']); - scope.set('list', ['x', 'y', 'z']); - scope.updateView(); + scope.$set('list', ['x', 'y', 'z']); + scope.$eval(); expect(element.val()).toEqual("x, y, z"); element.val('1, 2, 3'); element.trigger('keyup'); - expect(scope.get('list')).toEqual(['1', '2', '3']); + expect(scope.$get('list')).toEqual(['1', '2', '3']); }); it("should process ng-validation", function(){ @@ -58,8 +56,8 @@ describe("input widget", function(){ expect(element.hasClass('ng-validation-error')).toBeTruthy(); expect(element.attr('ng-error')).toEqual('Not a number'); - scope.set('price', '123'); - scope.updateView(); + scope.$set('price', '123'); + scope.$eval(); expect(element.hasClass('ng-validation-error')).toBeFalsy(); expect(element.attr('ng-error')).toBeFalsy(); @@ -74,8 +72,8 @@ describe("input widget", function(){ expect(element.hasClass('ng-validation-error')).toBeTruthy(); expect(element.attr('ng-error')).toEqual('Required'); - scope.set('price', 'xxx'); - scope.updateView(); + scope.$set('price', 'xxx'); + scope.$eval(); expect(element.hasClass('ng-validation-error')).toBeFalsy(); expect(element.attr('ng-error')).toBeFalsy(); @@ -87,41 +85,41 @@ describe("input widget", function(){ it("should process ng-required", function() { compile('<textarea name="name">Misko</textarea>'); - expect(scope.get('name')).toEqual("Misko"); + expect(scope.$get('name')).toEqual("Misko"); - scope.set('name', 'Adam'); - scope.updateView(); + scope.$set('name', 'Adam'); + scope.$eval(); expect(element.val()).toEqual("Adam"); element.val('Shyam'); element.trigger('keyup'); - expect(scope.get('name')).toEqual('Shyam'); + expect(scope.$get('name')).toEqual('Shyam'); element.val('Kai'); element.trigger('change'); - expect(scope.get('name')).toEqual('Kai'); + expect(scope.$get('name')).toEqual('Kai'); }); it('should call ng-action on button click', function(){ compile('<input type="button" value="Click Me" ng-action="clicked = true"/>'); element.click(); - expect(scope.get('clicked')).toEqual(true); + expect(scope.$get('clicked')).toEqual(true); }); it('should support button alias', function(){ compile('<button ng-action="clicked = true">Click Me</button>'); element.click(); - expect(scope.get('clicked')).toEqual(true); + expect(scope.$get('clicked')).toEqual(true); }); it('should type="checkbox"', function(){ compile('<input type="checkbox" name="checkbox" checked ng-action="action = true"/>'); - expect(scope.get('checkbox')).toEqual(true); + expect(scope.$get('checkbox')).toEqual(true); element.click(); - expect(scope.get('checkbox')).toEqual(false); - expect(scope.get('action')).toEqual(true); + expect(scope.$get('checkbox')).toEqual(false); + expect(scope.$get('action')).toEqual(true); element.click(); - expect(scope.get('checkbox')).toEqual(true); + expect(scope.$get('checkbox')).toEqual(true); }); it('should type="radio"', function(){ @@ -131,21 +129,21 @@ describe("input widget", function(){ '</div>'); var a = element[0].childNodes[0]; var b = element[0].childNodes[1]; - expect(model.chose).toEqual('B'); - expect(model.clicked).not.toBeDefined(); - model.chose = 'A'; - model.$updateView(); + expect(scope.chose).toEqual('B'); + expect(scope.clicked).not.toBeDefined(); + scope.chose = 'A'; + scope.$eval(); expect(a.checked).toEqual(true); - model.chose = 'B'; - model.$updateView(); + scope.chose = 'B'; + scope.$eval(); expect(a.checked).toEqual(false); expect(b.checked).toEqual(true); - expect(model.clicked).not.toBeDefined(); + expect(scope.clicked).not.toBeDefined(); jqLite(a).click(); - expect(model.chose).toEqual('A'); - expect(model.clicked).toEqual(1); + expect(scope.chose).toEqual('A'); + expect(scope.clicked).toEqual(1); }); it('should type="select-one"', function(){ @@ -154,10 +152,10 @@ describe("input widget", function(){ '<option>A</option>' + '<option selected>B</option>' + '</select>'); - expect(model.selection).toEqual('B'); - model.selection = 'A'; - model.$updateView(); - expect(model.selection).toEqual('A'); + expect(scope.selection).toEqual('B'); + scope.selection = 'A'; + scope.$eval(); + expect(scope.selection).toEqual('A'); expect(element[0].childNodes[0].selected).toEqual(true); }); @@ -167,14 +165,14 @@ describe("input widget", function(){ '<option>A</option>' + '<option selected>B</option>' + '</select>'); - expect(model.selection).toEqual(['B']); - model.selection = ['A']; - model.$updateView(); + expect(scope.selection).toEqual(['B']); + scope.selection = ['A']; + scope.$eval(); expect(element[0].childNodes[0].selected).toEqual(true); }); it('should report error on missing field', function(){ - + //compile('<input type="text"/>'); }); it('should report error on assignment error', function(){ |
