diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Angular.js | 5 | ||||
| -rw-r--r-- | src/Compiler.js | 13 | ||||
| -rw-r--r-- | src/Scope.js | 27 | ||||
| -rw-r--r-- | src/directives.js | 21 | ||||
| -rw-r--r-- | src/validators.js | 2 | ||||
| -rw-r--r-- | src/widgets.js | 49 | 
6 files changed, 72 insertions, 45 deletions
diff --git a/src/Angular.js b/src/Angular.js index 4d3c360f..97792868 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -53,6 +53,9 @@ function fromCharCode(code) { return String.fromCharCode(code); }  var _undefined        = undefined,      _null             = null,      $$element         = '$element', +    $$update          = '$update', +    $$scope           = '$scope', +    $$validate        = '$validate',      $angular          = 'angular',      $array            = 'array',      $boolean          = 'boolean', @@ -69,6 +72,8 @@ var _undefined        = undefined,      $number           = 'number',      $object           = 'object',      $string           = 'string', +    $value            = 'value', +    $selected         = 'selected',      $undefined        = 'undefined',      NG_EXCEPTION      = 'ng-exception',      NG_VALIDATION_ERROR = 'ng-validation-error', diff --git a/src/Compiler.js b/src/Compiler.js index 10d19ea8..a98bd502 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -30,6 +30,7 @@ Template.prototype = {      if (this.newScope) {        childScope = createScope(scope);        scope.$onEval(childScope.$eval); +      element.data($$scope, childScope);      }      foreach(this.inits, function(fn) {        queue.push(function() { @@ -68,6 +69,17 @@ Template.prototype = {    }  }; +/* + * Function walks up the element chain looking for the scope associated with the give element. + */ +function retrieveScope(element) { +  var scope; +  while (element && !(scope = element.data($$scope))) { +    element = element.parent(); +  } +  return scope; +} +  ///////////////////////////////////  //Compiler  ////////////////////////////////// @@ -97,6 +109,7 @@ Compiler.prototype = {        element = jqLite(element);        var scope = parentScope && parentScope.$eval ?            parentScope : createScope(parentScope); +      element.data($$scope, scope);        return extend(scope, {          $element:element,          $init: function() { diff --git a/src/Scope.js b/src/Scope.js index 09779453..203507a3 100644 --- a/src/Scope.js +++ b/src/Scope.js @@ -243,7 +243,6 @@ function createScope(parent, providers, instanceCache) {    parent = Parent.prototype = (parent || {});    var instance = new Parent();    var evalLists = {sorted:[]}; -  var postList = [], postHash = {}, postId = 0;    extend(instance, {      'this': instance, @@ -371,11 +370,6 @@ function createScope(parent, providers, instanceCache) {              instance.$tryEval(queue[j].fn, queue[j].handler);            }          } -        while(postList.length) { -          fn = postList.shift(); -          delete postHash[fn.$postEvalId]; -          instance.$tryEval(fn); -        }        } else if (type === $function) {          return exp.call(instance);        } else  if (type === 'string') { @@ -552,27 +546,6 @@ function createScope(parent, providers, instanceCache) {      /**       * @workInProgress       * @ngdoc function -     * @name angular.scope.$postEval -     * @function -     */ -    $postEval: function(expr) { -      if (expr) { -        var fn = expressionCompile(expr); -        var id = fn.$postEvalId; -        if (!id) { -          id = '$' + instance.$id + "_" + (postId++); -          fn.$postEvalId = id; -        } -        if (!postHash[id]) { -          postList.push(postHash[id] = fn); -        } -      } -    }, - - -    /** -     * @workInProgress -     * @ngdoc function       * @name angular.scope.$become       * @function       * @deprecated This method will be removed before 1.0 diff --git a/src/directives.js b/src/directives.js index 8a76f17a..d40d6120 100644 --- a/src/directives.js +++ b/src/directives.js @@ -304,7 +304,8 @@ angularDirective("ng:bind-template", function(expression, element){  var REMOVE_ATTRIBUTES = {    'disabled':'disabled',    'readonly':'readOnly', -  'checked':'checked' +  'checked':'checked', +  'selected':'selected'  };  /**   * @workInProgress @@ -359,27 +360,31 @@ var REMOVE_ATTRIBUTES = {  angularDirective("ng:bind-attr", function(expression){    return function(element){      var lastValue = {}; -    var updateFn = element.parent().data('$update'); +    var updateFn = element.data($$update) || noop;      this.$onEval(function(){ -      var values = this.$eval(expression); +      var values = this.$eval(expression), +          dirty = noop;        for(var key in values) {          var value = compileBindTemplate(values[key]).call(this, element),              specialName = REMOVE_ATTRIBUTES[lowercase(key)];          if (lastValue[key] !== value) {            lastValue[key] = value;            if (specialName) { -            if (element[specialName] = toBoolean(value)) { -              element.attr(specialName, value); +            if (toBoolean(value)) { +              element.attr(specialName, specialName); +              element.attr('ng-' + specialName, value);              } else { -              element.removeAttr(key); +              element.removeAttr(specialName); +              element.removeAttr('ng-' + specialName);              } -            (element.data('$validate')||noop)(); +            (element.data($$validate)||noop)();            } else {              element.attr(key, value);            } -          this.$postEval(updateFn); +          dirty = updateFn;          }        } +      dirty();      }, element);    };  }); diff --git a/src/validators.js b/src/validators.js index ea35558e..7318333a 100644 --- a/src/validators.js +++ b/src/validators.js @@ -394,7 +394,7 @@ extend(angularValidator, {            element.removeClass('ng-input-indicator-wait');            scope.$invalidWidgets.markValid(element);          } -        element.data('$validate')(); +        element.data($$validate)();          scope.$root.$eval();        });      } else if (inputState.inFlight) { diff --git a/src/widgets.js b/src/widgets.js index f34ff05c..04353bd5 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -282,7 +282,7 @@ function valueAccessor(scope, element) {      required = requiredExpr === '';    } -  element.data('$validate', validate); +  element.data($$validate, validate);    return {      get: function(){        if (lastError) @@ -391,6 +391,7 @@ var textWidget = inputWidget('keyup change', modelAccessor, valueAccessor, initW  //      'file':            fileWidget???      }; +  function initWidgetValue(initValue) {    return function (model, view) {      var value = view.get(); @@ -461,18 +462,13 @@ function inputWidget(events, modelAccessor, viewAccessor, initFn) {      this.$eval(element.attr('ng:init')||'');      // Don't register a handler if we are a button (noopAccessor) and there is no action      if (action || modelAccessor !== noopAccessor) { -      element.bind(events, function(event){ +      element.bind(events, function (){          model.set(view.get());          lastValue = model.get();          scope.$tryEval(action, element);          scope.$root.$eval();        });      } -    function updateView(){ -      view.set(lastValue = model.get()); -    } -    updateView(); -    element.data('$update', updateView);      scope.$watch(model.get, function(value){        if (lastValue !== value) {          view.set(lastValue = value); @@ -494,15 +490,50 @@ angularWidget('select', function(element){    return inputWidgetSelector.call(this, element);  }); + +/* + * Consider this: + * <select name="selection"> + *   <option ng:repeat="x in [1,2]">{{x}}</option> + * </select> + *  + * The issue is that the select gets evaluated before option is unrolled. + * This means that the selection is undefined, but the browser + * default behavior is to show the top selection in the list.  + * To fix that we register a $update function on the select element + * and the option creation then calls the $update function when it is  + * unrolled. The $update function then calls this update function, which  + * then tries to determine if the model is unassigned, and if so it tries to + * chose one of the options from the list. + */  angularWidget('option', function(){    this.descend(true);    this.directives(true);    return function(element) { -    this.$postEval(element.parent().data('$update')); +    var select = element.parent(); +    var scope = retrieveScope(select); +    var model = modelFormattedAccessor(scope, select); +    var view = valueAccessor(scope, select); +    var option = element; +    var lastValue = option.attr($value); +    var lastSelected = option.attr('ng-' + $selected); +    element.data($$update, function(){ +      var value = option.attr($value); +      var selected = option.attr('ng-' + $selected); +      var modelValue = model.get(); +      if (lastSelected != selected || lastValue != value) { +        lastSelected = selected; +        lastValue = value; +        if (selected || modelValue == _null || modelValue == _undefined)  +          model.set(value); +        if (value == modelValue) { +          view.set(lastValue); +        } +      } +    });    };  }); -  /**   * @workInProgress   * @ngdoc widget  | 
