diff options
| author | Misko Hevery | 2010-03-31 17:56:16 -0700 | 
|---|---|---|
| committer | Misko Hevery | 2010-03-31 17:56:16 -0700 | 
| commit | 861bac1d2808b15abb867e761ded8144bf5f7e94 (patch) | |
| tree | c7acd3aba0caeddf14a77c538487cf2baff9d96a /src | |
| parent | 35a91085004e31f786df1e0011bc26ed0142ab4d (diff) | |
| download | angular.js-861bac1d2808b15abb867e761ded8144bf5f7e94.tar.bz2 | |
started to add services
Diffstat (limited to 'src')
| -rw-r--r-- | src/Angular.js | 71 | ||||
| -rw-r--r-- | src/Compiler.js | 1 | ||||
| -rw-r--r-- | src/Parser.js | 4 | ||||
| -rw-r--r-- | src/Scope.js | 55 | ||||
| -rw-r--r-- | src/UrlWatcher.js | 40 | ||||
| -rw-r--r-- | src/services.js | 34 | 
6 files changed, 139 insertions, 66 deletions
diff --git a/src/Angular.js b/src/Angular.js index db177082..8eef6ac0 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -4,6 +4,9 @@ if (typeof document.getAttribute == 'undefined')  if (!window['console']) window['console']={'log':noop, 'error':noop};  var consoleNode, +    PRIORITY_FIRST    = -99999; +    PRIORITY_WATCH    = -1000; +    PRIORITY_LAST     =  99999;      NOOP              = 'noop',      NG_ERROR          = 'ng-error',      NG_EXCEPTION      = 'ng-exception', @@ -21,11 +24,30 @@ var consoleNode,      angularValidator  = extensionMap(angular, 'validator'),      angularFilter     = extensionMap(angular, 'filter'),      angularFormatter  = extensionMap(angular, 'formatter'), +    angularService    = extensionMap(angular, 'service'),      angularCallbacks  = extensionMap(angular, 'callbacks'), -    angularAlert      = angular['alert']     || (angular['alert']     = function(){ -        log(arguments); window.alert.apply(window, arguments); -      }); -angular['copy'] = copy; +    urlWatcher        = new UrlWatcher(window.location); + +function angularAlert(){ +  log(arguments); window.alert.apply(window, arguments); +}; + +extend(angular, { +  'compile': compile, +  'startUrlWatch': bind(urlWatcher, urlWatcher.start), +  'copy': copy, +  'extend': extend, +  'foreach': foreach, +  'noop':noop, +  'identity':identity, +  'isUndefined': isUndefined, +  'isDefined': isDefined, +  'isString': isString, +  'isFunction': isFunction, +  'isNumber': isNumber, +  'isArray': isArray, +  'alert': angularAlert +});  function foreach(obj, iterator, context) {    var key; @@ -43,6 +65,17 @@ function foreach(obj, iterator, context) {    return obj;  } +function foreachSorted(obj, iterator, context) { +  var keys = []; +  for (var key in obj) keys.push(key); +  keys.sort(); +  for ( var i = 0; i < keys.length; i++) { +    iterator.call(context, obj[keys[i]], keys[i]); +  } +  return keys; +} + +  function extend(dst) {    foreach(arguments, function(obj){      if (obj !== dst) { @@ -285,19 +318,21 @@ function merge(src, dst) {    }  } -///////////////////////////////////////////////// - -angular['compile'] = function(element, config) { -  config = extend({ -      'onUpdateView': noop, -      'server': "", -      'location': {'get':noop, 'set':noop, 'listen':noop} -    }, config||{}); - +function compile(element, config) {    var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget);        $element = jqLite(element), -      rootScope = { -        '$window': window -      }; -  return rootScope['$root'] = compiler.compile($element)($element, rootScope); -}; +      rootScope = createScope({ +        $element: $element, +        $config: extend({ +          'onUpdateView': noop, +          'server': "", +          'location': { +            'get':bind(urlWatcher, urlWatcher.get), +            'set':bind(urlWatcher, urlWatcher.set), +            'watch':bind(urlWatcher, urlWatcher.watch) +          } +        }, config || {}) +      }, serviceAdapter(angularService)); +  return compiler.compile($element)($element, rootScope); +} +///////////////////////////////////////////////// diff --git a/src/Compiler.js b/src/Compiler.js index 361d6946..c9039928 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -65,7 +65,6 @@ Compiler.prototype = {        element = jqLite(element);        parentScope = parentScope || {};        var scope = createScope(parentScope); -      parentScope.$root = parentScope.$root || scope;        return extend(scope, {          $element:element,          $init: function() { diff --git a/src/Parser.js b/src/Parser.js index ef1465a0..ec58295a 100644 --- a/src/Parser.js +++ b/src/Parser.js @@ -11,8 +11,8 @@ Lexer.OPERATORS = {      'true':function(self){return true;},      'false':function(self){return false;},      'undefined':noop, -    '+':function(self, a,b){return (a||0)+(b||0);}, -    '-':function(self, a,b){return (a||0)-(b||0);}, +    '+':function(self, a,b){return (isDefined(a)?a:0)+(isDefined(b)?b:0);}, +    '-':function(self, a,b){return (isDefined(a)?a:0)-(isDefined(b)?b:0);},      '*':function(self, a,b){return a*b;},      '/':function(self, a,b){return a/b;},      '%':function(self, a,b){return a%b;}, diff --git a/src/Scope.js b/src/Scope.js index 4144d456..ba86e24f 100644 --- a/src/Scope.js +++ b/src/Scope.js @@ -89,7 +89,11 @@ function createScope(parent, Class) {    function API(){}    function Behavior(){} -  var instance, behavior, api, watchList = [], evalList = []; +  var instance, behavior, api, evalLists = {}; +  if (isFunction(parent)) { +    Class = parent; +    parent = {}; +  }    Class = Class || noop;    parent = Parent.prototype = parent || {}; @@ -107,15 +111,10 @@ function createScope(parent, Class) {        if (isDefined(exp)) {          return expressionCompile(exp).apply(instance, slice.call(arguments, 1, arguments.length));        } else { -        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; -          } -        }); -        foreach(evalList, function(eval) { -          instance.$tryEval(eval.fn, eval.handler); +        foreachSorted(evalLists, function(list) { +          foreach(list, function(eval) { +            instance.$tryEval(eval.fn, eval.handler); +          });          });        }      }, @@ -134,16 +133,24 @@ function createScope(parent, Class) {      },      $watch: function(watchExp, listener, exceptionHandler) { -      var watch = expressionCompile(watchExp); -      watchList.push({ -        watch: watch, -        last: watch.call(instance), -        handler: exceptionHandler, -        listener:expressionCompile(listener) +      var watch = expressionCompile(watchExp), +          last = watch.call(instance); +      instance.$onEval(PRIORITY_WATCH, function(){ +        var value = watch.call(instance); +        if (last !== value) { +          instance.$tryEval(listener, exceptionHandler, value, last); +          last = value; +        }        });      }, -    $onEval: function(expr, exceptionHandler){ +    $onEval: function(priority, expr, exceptionHandler){ +      if (!isNumber(priority)) { +        exceptionHandler = expr; +        expr = priority; +        priority = 0; +      } +      var evalList = evalLists[priority] || (evalLists[priority] = []);        evalList.push({          fn: expressionCompile(expr),          handler: exceptionHandler @@ -151,7 +158,21 @@ function createScope(parent, Class) {      }    }); +  if (isUndefined(instance.$root)) { +    behavior.$root = instance; +    behavior.$parent = instance; +  } +    Class.apply(instance, slice.call(arguments, 2, arguments.length));    return instance;  } + +function serviceAdapter(services) { +  return function(){ +    var self = this; +    foreach(services, function(service, name){ +      self[name] = service.call(self); +    }); +  }; +}; diff --git a/src/UrlWatcher.js b/src/UrlWatcher.js index 0892eb1a..1b2a9cf0 100644 --- a/src/UrlWatcher.js +++ b/src/UrlWatcher.js @@ -9,42 +9,26 @@ function UrlWatcher(location) {    this.setTimeout = function(fn, delay) {      window.setTimeout(fn, delay);    }; -  this.listener = function(url) { -    return url; -  };    this.expectedUrl = location.href; +  this.listeners = [];  }  UrlWatcher.prototype = { -  listen: function(fn){ -    this.listener = fn; +  watch: function(fn){ +    this.listeners.push(fn);    }, -  watch: function() { + +  start: function() {      var self = this; -    var pull = function() { +    (function pull () {        if (self.expectedUrl !== self.location.href) { -        var notify = self.location.hash.match(/^#\$iframe_notify=(.*)$/); -        if (notify) { -          if (!self.expectedUrl.match(/#/)) { -            self.expectedUrl += "#"; -          } -          self.location.href = self.expectedUrl; -          var id = '_iframe_notify_' + notify[1]; -          var notifyFn = angularCallbacks[id]; -          delete angularCallbacks[id]; -          try { -            (notifyFn||noop)(); -          } catch (e) { -            alert(e); -          } -        } else { -          self.listener(self.location.href); -          self.expectedUrl = self.location.href; -        } +        foreach(self.listeners, function(listener){ +          listener(self.location.href); +        }); +        self.expectedUrl = self.location.href;        }        self.setTimeout(pull, self.delay); -    }; -    pull(); +    })();    },    set: function(url) { @@ -57,6 +41,6 @@ UrlWatcher.prototype = {    },    get: function() { -    return window.location.href; +    return this.location.href;    }  }; diff --git a/src/services.js b/src/services.js new file mode 100644 index 00000000..14c71363 --- /dev/null +++ b/src/services.js @@ -0,0 +1,34 @@ +angularService("$window", bind(window, identity, window)); + +angularService("$anchor", function(){ +  var scope = this; +  function anchor(url){ +    if (isDefined(url)) { +      if (url.charAt(0) == '#') url = url.substr(1); +      var pathQuery = url.split('?'); +      anchor.path = decodeURIComponent(pathQuery[0]); +      anchor.param = {}; +      foreach((pathQuery[1] || "").split('&'), function(keyValue){ +        if (keyValue) { +          var parts = keyValue.split('='); +          var key = decodeURIComponent(parts[0]); +          var value = parts[1]; +          if (!value) value = true; +          anchor.param[key] = decodeURIComponent(value); +        } +      }); +    } +    var params = []; +    foreach(anchor.param, function(value, key){ +      params.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); +    }); +    return (anchor.path ? anchor.path : '') + (params.length ? '?' + params.join('&') : ''); +  }; +  this.$config.location.watch(function(url){ +    anchor(url); +  }); +  this.$onEval(PRIORITY_LAST, function(){ +    scope.$config.location.set(anchor()); +  }); +  return anchor; +});  | 
