upgrading angular to 0.9.12 thought-implanter
[angular-drzb] / test / lib / angular / angular-scenario.js
index bc31661..09de50e 100644 (file)
@@ -6295,12 +6295,14 @@ var uppercase = function (string){ return isString(string) ? string.toUpperCase(
 
 
 var manualLowercase = function (s) {
-  return isString(s) ? s.replace(/[A-Z]/g,
-      function (ch) {return fromCharCode(ch.charCodeAt(0) | 32); }) : s;
+  return isString(s)
+      ? s.replace(/[A-Z]/g, function (ch) {return fromCharCode(ch.charCodeAt(0) | 32); })
+      : s;
 };
 var manualUppercase = function (s) {
-  return isString(s) ? s.replace(/[a-z]/g,
-      function (ch) {return fromCharCode(ch.charCodeAt(0) & ~32); }) : s;
+  return isString(s)
+      ? s.replace(/[a-z]/g, function (ch) {return fromCharCode(ch.charCodeAt(0) & ~32); })
+      : s;
 };
 
 
@@ -6348,17 +6350,18 @@ var _undefined        = undefined,
     PRIORITY_LAST     =  99999,
     PRIORITY          = {'FIRST': PRIORITY_FIRST, 'LAST': PRIORITY_LAST, 'WATCH':PRIORITY_WATCH},
     Error             = window.Error,
-    jQuery            = window['jQuery'] || window['$'], // weirdness to make IE happy
-    _                 = window['_'],
     /** holds major version number for IE or NaN for real browsers */
     msie              = parseInt((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1], 10),
-    jqLite            = jQuery || jqLiteWrap,
+    jqLite,           // delay binding since jQuery could be loaded after us.
+    jQuery,           // delay binding
     slice             = Array.prototype.slice,
     push              = Array.prototype.push,
-    error             = window[$console] ? bind(window[$console], window[$console]['error'] || noop) : noop,
+    error             = window[$console]
+                           ? bind(window[$console], window[$console]['error'] || noop)
+                           : noop,
 
     /** @name angular */
-    angular           = window[$angular]    || (window[$angular] = {}),
+    angular           = window[$angular] || (window[$angular] = {}),
     /** @name angular.markup */
     angularTextMarkup = extensionMap(angular, 'markup'),
     /** @name angular.attrMarkup */
@@ -6460,7 +6463,7 @@ function formatError(arg) {
  * @function
  *
  * @description
- * Extends the destination object `dst` by copying all of the properties from the `src` objects to
+ * Extends the destination object `dst` by copying all of the properties from the `src` object(s) to
  * `dst`. You can specify multiple `src` objects.
  *
  * @param {Object} dst The destination object.
@@ -6534,21 +6537,6 @@ function extensionMap(angular, name, transform) {
   });
 }
 
-function jqLiteWrap(element) {
-  // for some reasons the parentNode of an orphan looks like _null but its typeof is object.
-  if (element) {
-    if (isString(element)) {
-      var div = document.createElement('div');
-      div.innerHTML = element;
-      element = new JQLite(div.childNodes);
-    } else if (!(element instanceof JQLite)) {
-      element =  new JQLite(element);
-    }
-  }
-  return element;
-}
-
-
 /**
  * @workInProgress
  * @ngdoc function
@@ -6685,7 +6673,9 @@ function isBoolean(value) { return typeof value == $boolean;}
 function isTextNode(node) { return nodeName_(node) == '#text'; }
 function trim(value) { return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; }
 function isElement(node) {
-  return node && (node.nodeName || node instanceof JQLite || (jQuery && node instanceof jQuery));
+  return node &&
+    (node.nodeName  // we are a direct element
+    || (node.bind && node.find));  // we have a bind and find method part of jQuery API
 }
 
 /**
@@ -6696,13 +6686,13 @@ function isElement(node) {
  */
 function HTML(html, option) {
   this.html = html;
-  this.get = lowercase(option) == 'unsafe' ?
-    valueFn(html) :
-    function htmlSanitize() {
-      var buf = [];
-      htmlParser(html, htmlSanitizeWriter(buf));
-      return buf.join('');
-    };
+  this.get = lowercase(option) == 'unsafe'
+    ? valueFn(html)
+    function htmlSanitize() {
+        var buf = [];
+        htmlParser(html, htmlSanitizeWriter(buf));
+        return buf.join('');
+      };
 }
 
 if (msie) {
@@ -6716,10 +6706,6 @@ if (msie) {
   };
 }
 
-function quickClone(element) {
-  return jqLite(element[0].cloneNode(true));
-}
-
 function isVisible(element) {
   var rect = element[0].getBoundingClientRect(),
       width = (rect.width || (rect.right||0 - rect.left||0)),
@@ -6841,14 +6827,14 @@ function isLeafNode (node) {
  *  </doc:source>
  *  <doc:scenario>
    it('should print that initialy the form object is NOT equal to master', function() {
-     expect(element('.doc-example input[name=master.salutation]').val()).toBe('Hello');
-     expect(element('.doc-example input[name=master.name]').val()).toBe('world');
-     expect(element('.doc-example span').css('display')).toBe('inline');
+     expect(element('.doc-example-live input[name=master.salutation]').val()).toBe('Hello');
+     expect(element('.doc-example-live input[name=master.name]').val()).toBe('world');
+     expect(element('.doc-example-live span').css('display')).toBe('inline');
    });
 
    it('should make form and master equal when the copy button is clicked', function() {
-     element('.doc-example button').click();
-     expect(element('.doc-example span').css('display')).toBe('none');
+     element('.doc-example-live button').click();
+     expect(element('.doc-example-live span').css('display')).toBe('none');
    });
  *  </doc:scenario>
  * </doc:example>
@@ -6922,14 +6908,14 @@ function copy(source, destination){
  *  </doc:source>
  *  <doc:scenario>
      it('should print that initialy greeting is equal to the hardcoded value object', function() {
-       expect(element('.doc-example input[name=greeting.salutation]').val()).toBe('Hello');
-       expect(element('.doc-example input[name=greeting.name]').val()).toBe('world');
-       expect(element('.doc-example span').css('display')).toBe('none');
+       expect(element('.doc-example-live input[name=greeting.salutation]').val()).toBe('Hello');
+       expect(element('.doc-example-live input[name=greeting.name]').val()).toBe('world');
+       expect(element('.doc-example-live span').css('display')).toBe('none');
      });
 
      it('should say that the objects are not equal when the form is modified', function() {
        input('greeting.name').enter('kitty');
-       expect(element('.doc-example span').css('display')).toBe('inline');
+       expect(element('.doc-example-live span').css('display')).toBe('inline');
      });
  *  </doc:scenario>
  * </doc:example>
@@ -7006,11 +6992,11 @@ function concat(array1, array2, index) {
  * @function
  *
  * @description
- * Returns function which calls function `fn` bound to `self` (`self` becomes the `this` for `fn`).
+ * Returns function which calls function `fn` bound to `self` (`self` becomes the `this` for `fn`).
  * Optional `args` can be supplied which are prebound to the function, also known as
  * [function currying](http://en.wikipedia.org/wiki/Currying).
  *
- * @param {Object} self Context in which `fn` should be evaluated in.
+ * @param {Object} self Context which `fn` should be evaluated in.
  * @param {function()} fn Function to be bound.
  * @param {...*} args Optional arguments to be prebound to the `fn` function call.
  * @returns {function()} Function that wraps the `fn` with all the specified bindings.
@@ -7053,30 +7039,10 @@ function merge(src, dst) {
 }
 
 
-/**
- * @workInProgress
- * @ngdoc function
- * @name angular.compile
- * @function
- *
- * @description
- * Compiles a piece of HTML or DOM into a {@link angular.scope scope} object.
-   <pre>
-    var scope1 = angular.compile(window.document);
-    scope1.$init();
-
-    var scope2 = angular.compile('<div ng:click="clicked = true">click me</div>');
-    scope2.$init();
-   </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.
- */
-function compile(element, parentScope) {
-  var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget),
-      $element = jqLite(element);
-  return compiler.compile($element)($element, parentScope);
+/** @name angular.compile */
+function compile(element) {
+  return new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget)
+    .compile(element);
 }
 /////////////////////////////////////////////////
 
@@ -7104,6 +7070,23 @@ function toKeyValue(obj) {
   return parts.length ? parts.join('&') : '';
 }
 
+
+/**
+ * we need our custom mehtod because encodeURIComponent is too agressive and doesn't follow
+ * http://www.ietf.org/rfc/rfc2396.txt with regards to the character set (pchar) allowed in path
+ * segments
+ */
+function encodeUriSegment(val) {
+  return encodeURIComponent(val).
+             replace(/%40/gi, '@').
+             replace(/%3A/gi, ':').
+             replace(/%26/gi, '&').
+             replace(/%3D/gi, '=').
+             replace(/%2B/gi, '+').
+             replace(/%24/g, '$').
+             replace(/%2C/gi, ',');
+}
+
 /**
  * @workInProgress
  * @ngdoc directive
@@ -7115,8 +7098,8 @@ function toKeyValue(obj) {
  * @TODO rename to ng:autobind to ng:autoboot
  *
  * @description
- * This section explains how to bootstrap your application with angular using either the angular
- * javascript file.
+ * This section explains how to bootstrap your application with angular, using either the angular
+ * javascript file, or manually.
  *
  *
  * ## The angular distribution
@@ -7211,7 +7194,7 @@ function toKeyValue(obj) {
        (function(window, previousOnLoad){
          window.onload = function(){
           try { (previousOnLoad||angular.noop)(); } catch(e) {}
-          angular.compile(window.document).$init();
+          angular.compile(window.document);
          };
        })(window, window.onload);
       &lt;/script&gt;
@@ -7258,19 +7241,18 @@ 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)(createScope({'$config':config})).scope,
         $browser = scope.$service('$browser');
 
     if (config.css)
       $browser.addCss(config.base_url + config.css);
     else if(msie<8)
       $browser.addJs(config.base_url + config.ie_compat, config.ie_compat_id);
-
-    scope.$init();
   }
 }
 
 function angularJsConfig(document, config) {
+  bindJQuery();
   var scripts = document.getElementsByTagName("script"),
       match;
   config = extend({
@@ -7293,6 +7275,37 @@ function angularJsConfig(document, config) {
   }
   return config;
 }
+
+function bindJQuery(){
+  // bind to jQuery if present;
+  jQuery = window.jQuery;
+  // reset to jQuery or default to us.
+  if (jQuery) {
+    jqLite = jQuery;
+    extend(jQuery.fn, {
+      scope: JQLitePrototype.scope
+    });
+  } else {
+    jqLite = jqLiteWrap;
+  }
+  angular.element = jqLite;
+}
+
+/**
+ * throw error of the argument is falsy.
+ */
+function assertArg(arg, name, reason) {
+  if (!arg) {
+    var error = new Error("Argument '" + (name||'?') + "' is " +
+        (reason || "required"));
+    if (window.console) window.console.log(error.stack);
+    throw error;
+  }
+};
+
+function assertArgFn(arg, name) {
+  assertArg(isFunction(arg, name, 'not a function'));
+};
 var array = [].constructor;
 
 /**
@@ -7464,7 +7477,7 @@ function Template(priority) {
 }
 
 Template.prototype = {
-  init: function(element, scope) {
+  attach: function(element, scope) {
     var inits = {};
     this.collectInits(element, inits, scope);
     forEachSorted(inits, function(queue){
@@ -7477,7 +7490,6 @@ Template.prototype = {
     if (!queue) {
       inits[this.priority] = queue = [];
     }
-    element = jqLite(element);
     if (this.newScope) {
       childScope = createScope(scope);
       scope.$onEval(childScope.$eval);
@@ -7496,7 +7508,7 @@ Template.prototype = {
         paths = this.paths,
         length = paths.length;
     for (i = 0; i < length; i++) {
-      children[i].collectInits(childNodes[paths[i]], inits, childScope);
+      children[i].collectInits(jqLite(childNodes[paths[i]]), inits, childScope);
     }
   },
 
@@ -7520,21 +7532,87 @@ Template.prototype = {
   }
 };
 
-/*
- * Function walks up the element chain looking for the scope associated with the give element.
- */
-function retrieveScope(element) {
-  var scope;
-  element = jqLite(element);
-  while (element && element.length && !(scope = element.data($$scope))) {
-    element = element.parent();
-  }
-  return scope;
-}
-
 ///////////////////////////////////
 //Compiler
 //////////////////////////////////
+
+/**
+ * @workInProgress
+ * @ngdoc function
+ * @name angular.compile
+ * @function
+ *
+ * @description
+ * Compiles a piece of HTML string or DOM into a template and produces a template function, which
+ * can then be used to link {@link angular.scope scope} and the template together.
+ *
+ * The compilation is a process of walking the DOM tree and trying 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 template function which is then returned.
+ *
+ * The template function can then be used once to produce the view or as it is the case with
+ * {@link angular.widget.@ng:repeat repeater} many-times, in which case each call results in a view
+ * that is a DOM clone of the original template.
+ *
+   <pre>
+    //copile the entire window.document and give me the scope bound to this template.
+    var rootSscope = angular.compile(window.document)();
+
+    //compile a piece of html
+    var rootScope2 = angular.compile(''<div ng:click="clicked = true">click me</div>')();
+
+    //compile a piece of html and retain reference to both the dom and scope
+    var template = angular.element('<div ng:click="clicked = true">click me</div>'),
+        scoope = angular.compile(view)();
+    //at this point template was transformed into a view
+   </pre>
+ *
+ *
+ * @param {string|DOMElement} element Element or HTML to compile into a template function.
+ * @returns {function([scope][, cloneAttachFn])} a template function which is used to bind template
+ * (a DOM element/tree) to a scope. Where:
+ *
+ *   * `scope` - A {@link angular.scope scope} to bind to. If none specified, then a new
+ *               root scope is created.
+ *   * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the
+ *               `template` and call the `cloneAttachFn` function allowing the caller to attach the
+ *               cloned elements to the DOM document at the approriate place. The `cloneAttachFn` is
+ *               called as: <br/> `cloneAttachFn(clonedElement, scope)` where:
+ *
+ *     * `clonedElement` - is a clone of the original `element` passed into the compiler.
+ *     * `scope` - is the current scope with which the linking function is working with.
+ *
+ * Calling the template function returns the scope to which the element is bound to. It is either
+ * the same scope as the one passed into the template function, or if none were provided it's the
+ * newly create scope.
+ *
+ * If you need access to the bound view, there are two ways to do it:
+ *
+ * - If you are not asking the linking function to clone the template, create the DOM element(s)
+ *   before you send them to the compiler and keep this reference around.
+ *   <pre>
+ *     var view = angular.element('<p>{{total}}</p>'),
+ *         scope = angular.compile(view)();
+ *   </pre>
+ *
+ * - if on the other hand, you need the element to be cloned, the view reference from the original
+ *   example would not point to the clone, but rather to the original template that was cloned. In
+ *   this case, you can access the clone via the cloneAttachFn:
+ *   <pre>
+ *     var original = angular.element('<p>{{total}}</p>'),
+ *         scope = someParentScope.$new(),
+ *         clone;
+ *
+ *     angular.compile(original)(scope, function(clonedElement, scope) {
+ *       clone = clonedElement;
+ *       //attach the clone to DOM document at the right place
+ *     });
+ *
+ *     //now we have reference to the cloned DOM via `clone`
+ *   </pre>
+ */
 function Compiler(markup, attrMarkup, directives, widgets){
   this.markup = markup;
   this.attrMarkup = attrMarkup;
@@ -7543,34 +7621,33 @@ 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, cloneConnectFn){
+      // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
+      // and sometimes changes the structure of the DOM.
+      var element = cloneConnectFn
+        ? JQLitePrototype.clone.call(templateElement) // IMPORTANT!!!
+        : templateElement;
+        scope = scope || createScope();
       element.data($$scope, scope);
-      return extend(scope, {
-        $element:element,
-        $init: function() {
-          template.init(element, scope);
-          scope.$eval();
-          delete scope.$init;
-          return scope;
-        }
-      });
+      scope.$element = element;
+      (cloneConnectFn||noop)(element, scope);
+      template.attach(element, scope);
+      scope.$eval();
+      return scope;
     };
   },
 
@@ -7638,12 +7715,10 @@ Compiler.prototype = {
         descend = true,
         directives = true,
         elementName = nodeName_(element),
+        elementNamespace = elementName.indexOf(':') > 0 ? lowercase(elementName).replace(':', '-') : '',
         template,
         selfApi = {
           compile: bind(self, self.compile),
-          comment:function(text) {return jqLite(document.createComment(text));},
-          element:function(type) {return jqLite(document.createElement(type));},
-          text:function(text) {return jqLite(document.createTextNode(text));},
           descend: function(value){ if(isDefined(value)) descend = value; return descend;},
           directives: function(value){ if(isDefined(value)) directives = value; return directives;},
           scope: function(value){ if(isDefined(value)) template.newScope = template.newScope || value; return template.newScope;}
@@ -7654,6 +7729,7 @@ Compiler.prototype = {
       // for some reason IE throws error under some weird circumstances. so just assume nothing
       priority = priority || 0;
     }
+    element.addClass(elementNamespace);
     if (isString(priority)) {
       priority = PRIORITY[uppercase(priority)] || parseInt(priority, 10);
     }
@@ -7668,7 +7744,7 @@ Compiler.prototype = {
     });
     if (!widget) {
       if (widget = self.widgets(elementName)) {
-        if (elementName.indexOf(':') > 0)
+        if (elementNamespace)
           element.addClass('ng-widget');
         widget = bind(selfApi, widget, element);
       }
@@ -7866,13 +7942,13 @@ function errorHandlerFor(element, error) {
  * - Scopes can be nested. A scope (prototypically) inherits properties from its parent scope.
  * - Scopes can be attached (bound) to the HTML DOM tree (the view).
  * - A scope {@link angular.scope.$become becomes} `this` for a controller.
- * - Scope's {@link angular.scope.$eval $eval} is used to update its view.
+ * - A scope's {@link angular.scope.$eval $eval} is used to update its view.
  * - Scopes can {@link angular.scope.$watch watch} properties and fire events.
  *
  * # Basic Operations
  * Scopes can be created by calling {@link angular.scope() angular.scope()} or by compiling HTML.
  *
- * {@link angular.widget Widgets} and data bindings register listeners on the current scope to get
+ * {@link angular.widget Widgets} and data bindings register listeners on the current scope to be
  * notified of changes to the scope state. When notified, these listeners push the updated state
  * through to the DOM.
  *
@@ -7919,7 +7995,7 @@ function errorHandlerFor(element, error) {
  *
  * # When scopes are evaluated
  * Anyone can update a scope by calling its {@link angular.scope.$eval $eval()} method. By default
- * angular widgets listen to user change events (e.g. the user enters text into text field), copy
+ * angular widgets listen to user change events (e.g. the user enters text into text field), copy
  * the data from the widget to the scope (the MVC model), and then call the `$eval()` method on the
  * root scope to update dependents. This creates a spreadsheet-like behavior: the bound views update
  * immediately as the user types into the text field.
@@ -7930,7 +8006,7 @@ function errorHandlerFor(element, error) {
  *
  * Because a change in the model that's triggered either by user input or by server response calls
  * `$eval()`, it is unnecessary to call `$eval()` from within your controller. The only time when
- * calling `$eval()` is needed, is when implementing a custom widget or service.
+ * calling `$eval()` is needed is when implementing a custom widget or service.
  *
  * Because scopes are inherited, the child scope `$eval()` overrides the parent `$eval()` method.
  * So to update the whole page you need to call `$eval()` on the root scope as `$root.$eval()`.
@@ -8140,7 +8216,7 @@ function createScope(parent, providers, instanceCache) {
      * {@link angular.scope.$eval()} with expression parameter, but also wraps it in a try/catch
      * block.
      *
-     * If exception is thrown then `exceptionHandler` is used to handle the exception.
+     * If an exception is thrown then `exceptionHandler` is used to handle the exception.
      *
      * # Example
        <pre>
@@ -8195,7 +8271,7 @@ function createScope(parent, providers, instanceCache) {
      *
      * @description
      * Registers `listener` as a callback to be executed every time the `watchExp` changes. Be aware
-     * that callback gets, by default, called upon registration, this can be prevented via the
+     * that the callback gets, by default, called upon registration, this can be prevented via the
      * `initRun` parameter.
      *
      * # Example
@@ -8397,41 +8473,45 @@ function createScope(parent, providers, instanceCache) {
  *
  * @description
  * Creates an inject function that can be used for dependency injection.
+ * (See {@link guide.di dependency injection})
+ *
+ * The inject function can be used for retrieving service instances or for calling any function
+ * which has the $inject property so that the services can be automatically provided. Angular
+ * creates an injection function automatically for the root scope and it is available as
+ * {@link angular.scope.$service $service}.
  *
  * @param {Object=} [providerScope={}] provider's `this`
  * @param {Object.<string, function()>=} [providers=angular.service] Map of provider (factory)
  *     function.
  * @param {Object.<string, function()>=} [cache={}] Place where instances are saved for reuse. Can
  *     also be used to override services speciafied by `providers` (useful in tests).
- * @returns {function()} Injector function.
+ * @returns
+ *   {function()} Injector function: `function(value, scope, args...)`:
+ *
+ *     * `value` - `{string|array|function}`
+ *     * `scope(optional=rootScope)` -  optional function "`this`" when `value` is type `function`.
+ *     * `args(optional)` - optional set of arguments to pass to function after injection arguments.
+ *        (also known as curry arguments or currying).
+ *
+ *   #Return value of `function(value, scope, args...)`
+ *   The injector function return value depended on the type of `value` argument:
+ *
+ *     * `string`: return an instance for the injection key.
+ *     * `array` of keys: returns an array of instances for those keys. (see `string` above.)
+ *     * `function`: look at `$inject` property of function to determine instances to inject
+ *       and then call the function with instances and `scope`. Any additional arguments
+ *       (`args`) are appended to the function arguments.
+ *     * `none`: initialize eager providers.
  *
- * @TODO These docs need a lot of work. Specifically the returned function should be described in
- *     great detail + we need to provide some examples.
  */
 function createInjector(providerScope, providers, cache) {
   providers = providers || angularService;
   cache = cache || {};
   providerScope = providerScope || {};
-  /**
-   * injection function
-   * @param value: string, array, object or function.
-   * @param scope: optional function "this"
-   * @param args: optional arguments to pass to function after injection
-   *              parameters
-   * @returns depends on value:
-   *   string: return an instance for the injection key.
-   *   array of keys: returns an array of instances.
-   *   function: look at $inject property of function to determine instances
-   *             and then call the function with instances and `scope`. Any
-   *             additional arguments (`args`) are appended to the function
-   *             arguments.
-   *   object: initialize eager providers and publish them the ones with publish here.
-   *   none:   same as object but use providerScope as place to publish.
-   */
   return function inject(value, scope, args){
     var returnValue, provider;
     if (isString(value)) {
-      if (!cache.hasOwnProperty(value)) {
+      if (!(value in cache)) {
         provider = providers[value];
         if (!provider) throw "Unknown provider for '"+value+"'.";
         cache[value] = inject(provider, providerScope);
@@ -8443,7 +8523,7 @@ function createInjector(providerScope, providers, cache) {
         returnValue.push(inject(name));
       });
     } else if (isFunction(value)) {
-      returnValue = inject(value.$inject || []);
+      returnValue = inject(injectionArgs(value));
       returnValue = value.apply(scope, concat(returnValue, arguments, 2));
     } else if (isObject(value)) {
       forEach(providers, function(provider, name){
@@ -8468,6 +8548,40 @@ function injectService(services, fn) {
 function injectUpdateView(fn) {
   return injectService(['$updateView'], fn);
 }
+
+function angularServiceInject(name, fn, inject, eager) {
+  angularService(name, fn, {$inject:inject, $eager:eager});
+}
+
+
+/**
+ * @returns the $inject property of function. If not found the
+ * the $inject is computed by looking at the toString of function and
+ * extracting all arguments which start with $ or end with _ as the
+ * injection names.
+ */
+var FN_ARGS = /^function\s*[^\(]*\(([^\)]*)\)/;
+var FN_ARG_SPLIT = /,/;
+var FN_ARG = /^\s*(((\$?).+?)(_?))\s*$/;
+var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
+function injectionArgs(fn) {
+  assertArgFn(fn);
+  if (!fn.$inject) {
+    var args = fn.$inject = [];
+    var fnText = fn.toString().replace(STRIP_COMMENTS, '');
+    var argDecl = fnText.match(FN_ARGS);
+    forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
+      arg.replace(FN_ARG, function(all, name, injectName, $, _){
+        assertArg(args, name, 'after non-injectable arg');
+        if ($ || _)
+          args.push(injectName);
+        else
+          args = null; // once we reach an argument which is not injectable then ignore
+      });
+    });
+  }
+  return fn.$inject;
+};
 var OPERATORS = {
     'null':function(self){return _null;},
     'true':function(self){return true;},
@@ -8577,9 +8691,9 @@ function lex(text, parseStringsForObjects){
   function throwError(error, start, end) {
     end = end || index;
     throw Error("Lexer Error: " + error + " at column" +
-        (isDefined(start) ?
-            "s " + start +  "-" + index + " [" + text.substring(start, end) + "]" :
-            " " + end) +
+        (isDefined(start)
+            ? "s " + start +  "-" + index + " [" + text.substring(start, end) + "]"
+            " " + end) +
         " in expression [" + text + "].");
   }
 
@@ -8669,8 +8783,9 @@ function lex(text, parseStringsForObjects){
         index++;
         tokens.push({index:start, text:rawString, string:string, json:true,
           fn:function(){
-            return (string.length == dateParseLength) ?
-              angular['String']['toDate'](string) : string;
+            return (string.length == dateParseLength)
+              ? angular['String']['toDate'](string)
+              : string;
           }});
         return;
       } else {
@@ -9058,9 +9173,9 @@ function parser(text, json){
       }
       var fnPtr = fn(self) || noop;
       // IE stupidity!
-      return fnPtr.apply ?
-          fnPtr.apply(self, args) :
-            fnPtr(args[0], args[1], args[2], args[3], args[4]);
+      return fnPtr.apply
+          ? fnPtr.apply(self, args)
+          : fnPtr(args[0], args[1], args[2], args[3], args[4]);
     };
   }
 
@@ -9158,19 +9273,20 @@ function Route(template, defaults) {
 
 Route.prototype = {
   url: function(params) {
-    var path = [];
-    var self = this;
-    var url = this.template;
+    var self = this,
+        url = this.template,
+        encodedVal;
+
     params = params || {};
     forEach(this.urlParams, function(_, urlParam){
-      var value = params[urlParam] || self.defaults[urlParam] || "";
-      url = url.replace(new RegExp(":" + urlParam + "(\\W)"), value + "$1");
+      encodedVal = encodeUriSegment(params[urlParam] || self.defaults[urlParam] || "")
+      url = url.replace(new RegExp(":" + urlParam + "(\\W)"), encodedVal + "$1");
     });
     url = url.replace(/\/?#$/, '');
     var query = [];
     forEachSorted(params, function(value, key){
       if (!self.urlParams[key]) {
-        query.push(encodeURI(key) + '=' + encodeURI(value));
+        query.push(encodeUriSegment(key) + '=' + encodeUriSegment(value));
       }
     });
     url = url.replace(/\/*$/, '');
@@ -9509,7 +9625,7 @@ function Browser(window, document, body, XHR, $log) {
    * The listener gets called with either HashChangeEvent object or simple object that also contains
    * `oldURL` and `newURL` properties.
    *
-   * NOTE: this is a api is intended for sole use by $location service. Please use
+   * NOTE: this api is intended for use only by the $location service. Please use the
    * {@link angular.service.$location $location service} to monitor hash changes in angular apps.
    *
    * @param {function(event)} listener Listener function to be called when url hash changes.
@@ -9605,13 +9721,13 @@ function Browser(window, document, body, XHR, $log) {
    * @name angular.service.$browser#defer
    * @methodOf angular.service.$browser
    * @param {function()} fn A function, who's execution should be defered.
-   * @param {int=} [delay=0] of milliseconds to defer the function execution.
+   * @param {number=} [delay=0] of milliseconds to defer the function execution.
    *
    * @description
    * Executes a fn asynchroniously via `setTimeout(fn, delay)`.
    *
    * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using
-   * `setTimeout` in tests, the fns are queued in an array, which can be programaticaly flushed via
+   * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed via
    * `$browser.defer.flush()`.
    *
    */
@@ -9634,7 +9750,7 @@ function Browser(window, document, body, XHR, $log) {
    * @description
    * Set hover listener.
    *
-   * @param {function(Object, boolean)} listener Function that will be called when hover event
+   * @param {function(Object, boolean)} listener Function that will be called when hover event
    *    occurs.
    */
   self.hover = function(listener) { hoverListener = listener; };
@@ -9986,29 +10102,15 @@ function htmlSanitizeWriter(buf){
 var jqCache = {},
     jqName = 'ng-' + new Date().getTime(),
     jqId = 1,
-    addEventListenerFn = (window.document.addEventListener ?
-      function(element, type, fn) {element.addEventListener(type, fn, false);} :
-      function(element, type, fn) {element.attachEvent('on' + type, fn);}),
-    removeEventListenerFn = (window.document.removeEventListener ?
-      function(element, type, fn) {element.removeEventListener(type, fn, false); } :
-      function(element, type, fn) {element.detachEvent('on' + type, fn); });
+    addEventListenerFn = (window.document.addEventListener
+      ? function(element, type, fn) {element.addEventListener(type, fn, false);}
+      function(element, type, fn) {element.attachEvent('on' + type, fn);}),
+    removeEventListenerFn = (window.document.removeEventListener
+      ? function(element, type, fn) {element.removeEventListener(type, fn, false); }
+      function(element, type, fn) {element.detachEvent('on' + type, fn); });
 
 function jqNextId() { return (jqId++); }
 
-function jqClearData(element) {
-  var cacheId = element[jqName],
-      cache = jqCache[cacheId];
-  if (cache) {
-    forEach(cache.bind || {}, function(fn, type){
-      removeEventListenerFn(element, type, fn);
-    });
-    delete jqCache[cacheId];
-    if (msie)
-      element[jqName] = ''; // ie does not allow deletion of attributes on elements.
-    else
-      delete element[jqName];
-  }
-}
 
 function getStyle(element) {
   var current = {}, style = element[0].style, value, name, i;
@@ -10027,47 +10129,120 @@ function getStyle(element) {
   return current;
 }
 
-function JQLite(element) {
-  if (!isElement(element) && isDefined(element.length) && element.item && !isWindow(element)) {
-    for(var i=0; i < element.length; i++) {
-      this[i] = element[i];
+if (msie) {
+  extend(JQLite.prototype, {
+    text: function(value) {
+      var e = this[0];
+      // NodeType == 3 is text node
+      if (e.nodeType == 3) {
+        if (isDefined(value)) e.nodeValue = value;
+        return e.nodeValue;
+      } else {
+        if (isDefined(value)) e.innerText = value;
+        return e.innerText;
+      }
     }
-    this.length = element.length;
+  });
+}
+
+/////////////////////////////////////////////
+function jqLiteWrap(element) {
+  if (isString(element) && element.charAt(0) != '<') {
+    throw new Error('selectors not implemented');
+  }
+  return new JQLite(element);
+}
+
+function JQLite(element) {
+  if (element instanceof JQLite) {
+    return element;
+  } else if (isString(element)) {
+    var div = document.createElement('div');
+    // Read about the NoScope elements here:
+    // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
+    div.innerHTML = '<div>&nbsp;</div>' + element; // IE insanity to make NoScope elements work!
+    div.removeChild(div.firstChild); // remove the superfluous div
+    JQLiteAddNodes(this, div.childNodes);
+    this.remove(); // detach the elements form the temporary DOM div.
   } else {
-    this[0] = element;
-    this.length = 1;
+    JQLiteAddNodes(this, element);
   }
 }
 
-JQLite.prototype = {
-  data: function(key, value) {
-    var element = this[0],
-        cacheId = element[jqName],
-        cache = jqCache[cacheId || -1];
-    if (isDefined(value)) {
-      if (!cache) {
-        element[jqName] = cacheId = jqNextId();
-        cache = jqCache[cacheId] = {};
-      }
-      cache[key] = value;
-    } else {
-      return cache ? cache[key] : _null;
+function JQLiteClone(element) {
+  return element.cloneNode(true);
+}
+
+function JQLiteDealoc(element){
+  JQLiteRemoveData(element);
+  for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
+    JQLiteDealoc(children[i]);
+  }
+}
+
+function JQLiteRemoveData(element) {
+  var cacheId = element[jqName],
+  cache = jqCache[cacheId];
+  if (cache) {
+    forEach(cache.bind || {}, function(fn, type){
+      removeEventListenerFn(element, type, fn);
+    });
+    delete jqCache[cacheId];
+    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.
+  }
+}
+
+function JQLiteData(element, key, value) {
+  var cacheId = element[jqName],
+      cache = jqCache[cacheId || -1];
+  if (isDefined(value)) {
+    if (!cache) {
+      element[jqName] = cacheId = jqNextId();
+      cache = jqCache[cacheId] = {};
     }
-  },
+    cache[key] = value;
+  } else {
+    return cache ? cache[key] : _null;
+  }
+}
 
-  removeData: function(){
-    jqClearData(this[0]);
-  },
+function JQLiteHasClass(element, selector, _) {
+  // the argument '_' is important, since it makes the function have 3 arguments, which
+  // is neede for delegate function to realize the this is a getter.
+  var className = " " + selector + " ";
+  return ((" " + element.className + " ").replace(/[\n\t]/g, " ").indexOf( className ) > -1);
+}
 
-  dealoc: function(){
-    (function dealoc(element){
-      jqClearData(element);
-      for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
-        dealoc(children[i]);
-      }
-    })(this[0]);
-  },
+function JQLiteRemoveClass(element, selector) {
+  element.className = trim(
+      (" " + element.className + " ")
+      .replace(/[\n\t]/g, " ")
+      .replace(" " + selector + " ", "")
+  );
+}
+
+function JQLiteAddClass(element, selector ) {
+  if (!JQLiteHasClass(element, selector)) {
+    element.className = trim(element.className + ' ' + selector);
+  }
+}
+
+function JQLiteAddNodes(root, elements) {
+  if (elements) {
+    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
+      ? elements
+      : [ elements ];
+    for(var i=0; i < elements.length; i++) {
+      if (elements[i].nodeType != 11)
+        root.push(elements[i]);
+    }
+  }
+}
 
+//////////////////////////////////////////
+// Functions which are declared directly.
+//////////////////////////////////////////
+var JQLitePrototype = JQLite.prototype = extend([], {
   ready: function(fn) {
     var fired = false;
 
@@ -10078,15 +10253,138 @@ JQLite.prototype = {
     }
 
     this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9
-    jqLite(window).bind('load', trigger); // fallback to window.onload for others
+    // we can not use jqLite since we are not done loading and jQuery could be loaded later.
+    jqLiteWrap(window).bind('load', trigger); // fallback to window.onload for others
   },
+  toString: function(){
+    var value = [];
+    forEach(this, function(e){ value.push('' + e);});
+    return '[' + value.join(', ') + ']';
+  }
+});
 
-  bind: function(type, fn){
-    var self = this,
-        element = self[0],
-        bind = self.data('bind'),
+//////////////////////////////////////////
+// Functions iterating getter/setters.
+// these functions return self on setter and
+// value on get.
+//////////////////////////////////////////
+forEach({
+  data: JQLiteData,
+
+  scope: function(element) {
+    var scope;
+    while (element && !(scope = jqLite(element).data($$scope))) {
+      element = element.parentNode;
+    }
+    return scope;
+  },
+
+  removeAttr: function(element,name) {
+    element.removeAttribute(name);
+  },
+
+  hasClass: JQLiteHasClass,
+
+  css: function(element, name, value) {
+    if (isDefined(value)) {
+      element.style[name] = value;
+    } else {
+      return element.style[name];
+    }
+  },
+
+  attr: function(element, name, value){
+    if (isDefined(value)) {
+      element.setAttribute(name, value);
+    } else if (element.getAttribute) {
+      // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
+      // some elements (e.g. Document) don't have get attribute, so return undefined
+      return element.getAttribute(name, 2);
+    }
+  },
+
+  text: extend(msie
+      ? function(element, value) {
+        // NodeType == 3 is text node
+        if (element.nodeType == 3) {
+          if (isUndefined(value))
+            return element.nodeValue;
+          element.nodeValue = value;
+        } else {
+          if (isUndefined(value))
+            return element.innerText;
+          element.innerText = value;
+        }
+      }
+      : function(element, value) {
+        if (isUndefined(value)) {
+          return element.textContent;
+        }
+        element.textContent = value;
+      }, {$dv:''}),
+
+  val: function(element, value) {
+    if (isUndefined(value)) {
+      return element.value;
+    }
+    element.value = value;
+  },
+
+  html: function(element, value) {
+    if (isUndefined(value)) {
+      return element.innerHTML;
+    }
+    for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
+      JQLiteDealoc(childNodes[i]);
+    }
+    element.innerHTML = value;
+  }
+}, function(fn, name){
+  /**
+   * Properties: writes return selection, reads return first value
+   */
+  JQLite.prototype[name] = function(arg1, arg2) {
+    if ((fn.length == 2 ? arg1 : arg2) === undefined) {
+      if (isObject(arg1)) {
+        // we are a write, but the object properties are the key/values
+        for(var i=0; i < this.length; i++) {
+          for ( var key in arg1) {
+            fn(this[i], key, arg1[key]);
+          }
+        }
+        // return self for chaining
+        return this;
+      } else {
+        // we are a read, so read the first child.
+        if (this.length)
+          return fn(this[0], arg1, arg2);
+      }
+    } else {
+      // we are a write, so apply to all children
+      for(var i=0; i < this.length; i++) {
+        fn(this[i], arg1, arg2);
+      }
+      // return self for chaining
+      return this;
+    }
+    return fn.$dv;
+  };
+});
+
+//////////////////////////////////////////
+// Functions iterating traversal.
+// These functions chain results into a single
+// selector.
+//////////////////////////////////////////
+forEach({
+  removeData: JQLiteRemoveData,
+
+  dealoc: JQLiteDealoc,
+
+  bind: function(element, type, fn){
+    var bind = JQLiteData(element, 'bind'),
         eventHandler;
-    if (!bind) this.data('bind', bind = {});
+    if (!bind) JQLiteData(element, 'bind', bind = {});
     forEach(type.split(' '), function(type){
       eventHandler = bind[type];
       if (!eventHandler) {
@@ -10102,7 +10400,7 @@ JQLite.prototype = {
             };
           }
           forEach(eventHandler.fns, function(fn){
-            fn.call(self, event);
+            fn.call(element, event);
           });
         };
         eventHandler.fns = [];
@@ -10112,145 +10410,103 @@ JQLite.prototype = {
     });
   },
 
-  replaceWith: function(replaceNode) {
-    this[0].parentNode.replaceChild(jqLite(replaceNode)[0], this[0]);
+  replaceWith: function(element, replaceNode) {
+    var index, parent = element.parentNode;
+    JQLiteDealoc(element);
+    forEach(new JQLite(replaceNode), function(node){
+      if (index) {
+        parent.insertBefore(node, index.nextSibling);
+      } else {
+        parent.replaceChild(node, element);
+      }
+      index = node;
+    });
   },
 
-  children: function() {
-    return new JQLite(this[0].childNodes);
+  children: function(element) {
+    var children = [];
+    forEach(element.childNodes, function(element){
+      if (element.nodeName != '#text')
+        children.push(element);
+    });
+    return children;
   },
 
-  append: function(node) {
-    var self = this[0];
-    node = jqLite(node);
-    forEach(node, function(child){
-      self.appendChild(child);
+  append: function(element, node) {
+    forEach(new JQLite(node), function(child){
+      element.appendChild(child);
     });
   },
 
-  remove: function() {
-    this.dealoc();
-    var parentNode = this[0].parentNode;
-    if (parentNode) parentNode.removeChild(this[0]);
+  remove: function(element) {
+    JQLiteDealoc(element);
+    var parent = element.parentNode;
+    if (parent) parent.removeChild(element);
   },
 
-  removeAttr: function(name) {
-    this[0].removeAttribute(name);
+  after: function(element, newElement) {
+    var index = element, parent = element.parentNode;
+    forEach(new JQLite(newElement), function(node){
+      parent.insertBefore(node, index.nextSibling);
+      index = node;
+    });
   },
 
-  after: function(element) {
-    this[0].parentNode.insertBefore(jqLite(element)[0], this[0].nextSibling);
-  },
+  addClass: JQLiteAddClass,
+  removeClass: JQLiteRemoveClass,
 
-  hasClass: function(selector) {
-    var className = " " + selector + " ";
-    if ( (" " + this[0].className + " ").replace(/[\n\t]/g, " ").indexOf( className ) > -1 ) {
-      return true;
+  toggleClass: function(element, selector, condition) {
+    if (isUndefined(condition)) {
+      condition = !JQLiteHasClass(element, selector);
     }
-    return false;
+    (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);
   },
 
-  removeClass: function(selector) {
-    this[0].className = trim((" " + this[0].className + " ").replace(/[\n\t]/g, " ").replace(" " + selector + " ", ""));
+  parent: function(element) {
+    // in IE it returns undefined, but we need differentiate it from functions which have no return
+    return element.parentNode || null;
   },
 
-  toggleClass: function(selector, condition) {
-   var self = this;
-   (condition ? self.addClass : self.removeClass).call(self, selector);
+  next: function(element) {
+    return element.nextSibling;
   },
 
-  addClass: function( selector ) {
-    if (!this.hasClass(selector)) {
-      this[0].className = trim(this[0].className + ' ' + selector);
-    }
+  find: function(element, selector) {
+    return element.getElementsByTagName(selector);
   },
 
-  css: function(name, value) {
-    var style = this[0].style;
-    if (isString(name)) {
-      if (isDefined(value)) {
-        style[name] = value;
+  clone: JQLiteClone
+}, function(fn, name){
+  /**
+   * chaining functions
+   */
+  JQLite.prototype[name] = function(arg1, arg2) {
+    var value;
+    for(var i=0; i < this.length; i++) {
+      if (value == undefined) {
+        value = fn(this[i], arg1, arg2);
+        if (value !== undefined) {
+          // any function which returns a value needs to be wrapped
+          value = jqLite(value);
+        }
       } else {
-        return style[name];
+        JQLiteAddNodes(value, fn(this[i], arg1, arg2));
       }
-    } else {
-      extend(style, name);
-    }
-  },
-
-  attr: function(name, value){
-    var e = this[0];
-    if (isObject(name)) {
-      forEach(name, function(value, name){
-        e.setAttribute(name, value);
-      });
-    } else if (isDefined(value)) {
-      e.setAttribute(name, value);
-    } else {
-      // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code
-      // some elements (e.g. Document) don't have get attribute, so return undefined
-      if (e.getAttribute) return e.getAttribute(name, 2);
-    }
-  },
-
-  text: function(value) {
-    if (isDefined(value)) {
-      this[0].textContent = value;
-    }
-    return this[0].textContent;
-  },
-
-  val: function(value) {
-    if (isDefined(value)) {
-      this[0].value = value;
     }
-    return this[0].value;
-  },
-
-  html: function(value) {
-    if (isDefined(value)) {
-      var i = 0, childNodes = this[0].childNodes;
-      for ( ; i < childNodes.length; i++) {
-        jqLite(childNodes[i]).dealoc();
-      }
-      this[0].innerHTML = value;
+    return value == undefined ? this : value;
+  };
+});
+var angularGlobal = {
+  'typeOf':function(obj){
+    if (obj === _null) return $null;
+    var type = typeof obj;
+    if (type == $object) {
+      if (obj instanceof Array) return $array;
+      if (isDate(obj)) return $date;
+      if (obj.nodeType == 1) return $element;
     }
-    return this[0].innerHTML;
-  },
-
-  parent: function() {
-    return jqLite(this[0].parentNode);
-  },
-
-  clone: function() { return jqLite(this[0].cloneNode(true)); }
-};
-
-if (msie) {
-  extend(JQLite.prototype, {
-    text: function(value) {
-      var e = this[0];
-      // NodeType == 3 is text node
-      if (e.nodeType == 3) {
-        if (isDefined(value)) e.nodeValue = value;
-        return e.nodeValue;
-      } else {
-        if (isDefined(value)) e.innerText = value;
-        return e.innerText;
-      }
-    }
-  });
-}
-var angularGlobal = {
-  'typeOf':function(obj){
-    if (obj === _null) return $null;
-    var type = typeof obj;
-    if (type == $object) {
-      if (obj instanceof Array) return $array;
-      if (isDate(obj)) return $date;
-      if (obj.nodeType == 1) return $element;
-    }
-    return type;
-  }
+    return type;
+  }
 };
 
 
@@ -10393,7 +10649,7 @@ var angularArray = {
          });
 
          it('should add an entry and recalculate', function() {
-           element('.doc-example a:contains("add item")').click();
+           element('.doc-example-live a:contains("add item")').click();
            using('.doc-example-live tr:nth-child(3)').input('item.qty').enter('20');
            using('.doc-example-live tr:nth-child(3)').input('item.cost').enter('100');
 
@@ -10448,20 +10704,20 @@ var angularArray = {
        </doc:source>
        <doc:scenario>
          it('should initialize the task list with for tasks', function() {
-           expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(4);
-           expect(repeater('.doc-example ul li', 'task in tasks').column('task')).
+           expect(repeater('.doc-example-live ul li', 'task in tasks').count()).toBe(4);
+           expect(repeater('.doc-example-live ul li', 'task in tasks').column('task')).
              toEqual(['Learn Angular', 'Read Documentation', 'Check out demos',
                       'Build cool applications']);
          });
 
          it('should initialize the task list with for tasks', function() {
-           element('.doc-example ul li a:contains("X"):first').click();
-           expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(3);
+           element('.doc-example-live ul li a:contains("X"):first').click();
+           expect(repeater('.doc-example-live ul li', 'task in tasks').count()).toBe(3);
 
-           element('.doc-example ul li a:contains("X"):last').click();
-           expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(2);
+           element('.doc-example-live ul li a:contains("X"):last').click();
+           expect(repeater('.doc-example-live ul li', 'task in tasks').count()).toBe(2);
 
-           expect(repeater('.doc-example ul li', 'task in tasks').column('task')).
+           expect(repeater('.doc-example-live ul li', 'task in tasks').column('task')).
              toEqual(['Read Documentation', 'Check out demos']);
          });
        </doc:scenario>
@@ -10684,23 +10940,23 @@ var angularArray = {
          });
 
          it('should create an empty record when "add empty" is clicked', function() {
-           element('.doc-example a:contains("add empty")').click();
+           element('.doc-example-live a:contains("add empty")').click();
            expect(binding('people')).toBe('people = [{\n  "name":"",\n  "sex":null}]');
          });
 
          it('should create a "John" record when "add \'John\'" is clicked', function() {
-           element('.doc-example a:contains("add \'John\'")').click();
+           element('.doc-example-live a:contains("add \'John\'")').click();
            expect(binding('people')).toBe('people = [{\n  "name":"John",\n  "sex":"male"}]');
          });
 
          it('should create a "Mary" record when "add \'Mary\'" is clicked', function() {
-           element('.doc-example a:contains("add \'Mary\'")').click();
+           element('.doc-example-live a:contains("add \'Mary\'")').click();
            expect(binding('people')).toBe('people = [{\n  "name":"Mary",\n  "sex":"female"}]');
          });
 
          it('should delete a record when "X" is clicked', function() {
-            element('.doc-example a:contains("add empty")').click();
-            element('.doc-example li a:contains("X"):first').click();
+            element('.doc-example-live a:contains("add empty")').click();
+            element('.doc-example-live li a:contains("X"):first').click();
             expect(binding('people')).toBe('people = []');
          });
        </doc:scenario>
@@ -10752,7 +11008,7 @@ var angularArray = {
          });
 
          it('should recalculate when updated', function() {
-           using('.doc-example li:first-child').input('item.points').enter('23');
+           using('.doc-example-live li:first-child').input('item.points').enter('23');
            expect(binding('items.$count(\'points==1\')')).toEqual(1);
            expect(binding('items.$count(\'points>1\')')).toEqual(2);
          });
@@ -10828,23 +11084,23 @@ var angularArray = {
        <doc:scenario>
          it('should be reverse ordered by aged', function() {
            expect(binding('predicate')).toBe('Sorting predicate = -age');
-           expect(repeater('.doc-example table', 'friend in friends').column('friend.age')).
+           expect(repeater('.doc-example-live table', 'friend in friends').column('friend.age')).
              toEqual(['35', '29', '21', '19', '10']);
-           expect(repeater('.doc-example table', 'friend in friends').column('friend.name')).
+           expect(repeater('.doc-example-live table', 'friend in friends').column('friend.name')).
              toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']);
          });
 
          it('should reorder the table when user selects different predicate', function() {
-           element('.doc-example a:contains("Name")').click();
-           expect(repeater('.doc-example table', 'friend in friends').column('friend.name')).
+           element('.doc-example-live a:contains("Name")').click();
+           expect(repeater('.doc-example-live table', 'friend in friends').column('friend.name')).
              toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);
-           expect(repeater('.doc-example table', 'friend in friends').column('friend.age')).
+           expect(repeater('.doc-example-live table', 'friend in friends').column('friend.age')).
              toEqual(['35', '10', '29', '19', '21']);
 
-           element('.doc-example a:contains("Phone")+a:contains("^")').click();
-           expect(repeater('.doc-example table', 'friend in friends').column('friend.phone')).
+           element('.doc-example-live a:contains("Phone")+a:contains("^")').click();
+           expect(repeater('.doc-example-live table', 'friend in friends').column('friend.phone')).
              toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);
-           expect(repeater('.doc-example table', 'friend in friends').column('friend.name')).
+           expect(repeater('.doc-example-live table', 'friend in friends').column('friend.name')).
              toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);
          });
        </doc:scenario>
@@ -10879,8 +11135,9 @@ var angularArray = {
       return 0;
     }
     function reverse(comp, descending) {
-      return toBoolean(descending) ?
-          function(a,b){return comp(b,a);} : comp;
+      return toBoolean(descending)
+          ? function(a,b){return comp(b,a);}
+          : comp;
     }
     function compare(v1, v2){
       var t1 = typeof v1;
@@ -10925,7 +11182,7 @@ var angularArray = {
        </doc:source>
        <doc:scenario>
          it('should limit the numer array to first three items', function() {
-           expect(element('.doc-example input[name=limit]').val()).toBe('3');
+           expect(element('.doc-example-live input[name=limit]').val()).toBe('3');
            expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]');
          });
 
@@ -11675,7 +11932,7 @@ angularFormatter.number = formatter(toString, function(obj){
       it('should format lists', function(){
         expect(binding('value')).toEqual('value=["chair","table"]');
         this.addFutureAction('change to XYZ', function($window, $document, done){
-          $document.elements('.doc-example :input:last').val(',,a,b,').trigger('change');
+          $document.elements('.doc-example-live :input:last').val(',,a,b,').trigger('change');
           done();
         });
         expect(binding('value')).toEqual('value=["a","b"]');
@@ -11717,7 +11974,7 @@ angularFormatter.list = formatter(
         it('should format trim', function(){
           expect(binding('value')).toEqual('value="book"');
           this.addFutureAction('change to XYZ', function($window, $document, done){
-            $document.elements('.doc-example :input:last').val('  text  ').trigger('change');
+            $document.elements('.doc-example-live :input:last').val('  text  ').trigger('change');
             done();
           });
           expect(binding('value')).toEqual('value="text"');
@@ -11816,7 +12073,7 @@ extend(angularValidator, {
       </doc:source>
       <doc:scenario>
         it('should invalidate non ssn', function(){
-         var textBox = element('.doc-example :input');
+         var textBox = element('.doc-example-live :input');
          expect(textBox.attr('className')).not().toMatch(/ng-validation-error/);
          expect(textBox.val()).toEqual('123-45-6789');
          input('ssn').enter('123-45-67890');
@@ -11857,15 +12114,15 @@ extend(angularValidator, {
       </doc:source>
       <doc:scenario>
         it('should invalidate number', function(){
-         var n1 = element('.doc-example :input[name=n1]');
+         var n1 = element('.doc-example-live :input[name=n1]');
          expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
          input('n1').enter('1.x');
          expect(n1.attr('className')).toMatch(/ng-validation-error/);
-         var n2 = element('.doc-example :input[name=n2]');
+         var n2 = element('.doc-example-live :input[name=n2]');
          expect(n2.attr('className')).not().toMatch(/ng-validation-error/);
          input('n2').enter('9');
          expect(n2.attr('className')).toMatch(/ng-validation-error/);
-         var n3 = element('.doc-example :input[name=n3]');
+         var n3 = element('.doc-example-live :input[name=n3]');
          expect(n3.attr('className')).not().toMatch(/ng-validation-error/);
          input('n3').enter('201');
          expect(n3.attr('className')).toMatch(/ng-validation-error/);
@@ -11911,15 +12168,15 @@ extend(angularValidator, {
       </doc:source>
       <doc:scenario>
         it('should invalidate integer', function(){
-         var n1 = element('.doc-example :input[name=n1]');
+         var n1 = element('.doc-example-live :input[name=n1]');
          expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
          input('n1').enter('1.1');
          expect(n1.attr('className')).toMatch(/ng-validation-error/);
-         var n2 = element('.doc-example :input[name=n2]');
+         var n2 = element('.doc-example-live :input[name=n2]');
          expect(n2.attr('className')).not().toMatch(/ng-validation-error/);
          input('n2').enter('10.1');
          expect(n2.attr('className')).toMatch(/ng-validation-error/);
-         var n3 = element('.doc-example :input[name=n3]');
+         var n3 = element('.doc-example-live :input[name=n3]');
          expect(n3.attr('className')).not().toMatch(/ng-validation-error/);
          input('n3').enter('100.1');
          expect(n3.attr('className')).toMatch(/ng-validation-error/);
@@ -11955,7 +12212,7 @@ extend(angularValidator, {
       </doc:source>
       <doc:scenario>
         it('should invalidate date', function(){
-         var n1 = element('.doc-example :input');
+         var n1 = element('.doc-example-live :input');
          expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
          input('text').enter('123/123/123');
          expect(n1.attr('className')).toMatch(/ng-validation-error/);
@@ -11970,8 +12227,9 @@ extend(angularValidator, {
     return (date &&
             date.getFullYear() == fields[3] &&
             date.getMonth() == fields[1]-1 &&
-            date.getDate() == fields[2]) ?
-              _null : "Value is not a date. (Expecting format: 12/31/2009).";
+            date.getDate() == fields[2])
+              ? _null 
+              : "Value is not a date. (Expecting format: 12/31/2009).";
   },
 
   /**
@@ -11992,7 +12250,7 @@ extend(angularValidator, {
       </doc:source>
       <doc:scenario>
         it('should invalidate email', function(){
-         var n1 = element('.doc-example :input');
+         var n1 = element('.doc-example-live :input');
          expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
          input('text').enter('a@b.c');
          expect(n1.attr('className')).toMatch(/ng-validation-error/);
@@ -12026,7 +12284,7 @@ extend(angularValidator, {
       </doc:source>
       <doc:scenario>
         it('should invalidate phone', function(){
-         var n1 = element('.doc-example :input');
+         var n1 = element('.doc-example-live :input');
          expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
          input('text').enter('+12345678');
          expect(n1.attr('className')).toMatch(/ng-validation-error/);
@@ -12063,7 +12321,7 @@ extend(angularValidator, {
       </doc:source>
       <doc:scenario>
         it('should invalidate url', function(){
-         var n1 = element('.doc-example :input');
+         var n1 = element('.doc-example-live :input');
          expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
          input('text').enter('abc://server/path');
          expect(n1.attr('className')).toMatch(/ng-validation-error/);
@@ -12098,7 +12356,7 @@ extend(angularValidator, {
       </doc:source>
       <doc:scenario>
         it('should invalidate json', function(){
-         var n1 = element('.doc-example :input');
+         var n1 = element('.doc-example-live :input');
          expect(n1.attr('className')).not().toMatch(/ng-validation-error/);
          input('json').enter('{name}');
          expect(n1.attr('className')).toMatch(/ng-validation-error/);
@@ -12170,7 +12428,7 @@ extend(angularValidator, {
       </doc:source>
       <doc:scenario>
         it('should change color in delayed way', function(){
-         var textBox = element('.doc-example :input');
+         var textBox = element('.doc-example-live :input');
          expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/);
          expect(textBox.attr('className')).not().toMatch(/ng-validation-error/);
          input('text').enter('X');
@@ -12234,153 +12492,454 @@ extend(angularValidator, {
   }
 
 });
-var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,
-    HASH_MATCH = /^([^\?]*)?(\?([^\?]*))?$/,
-    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp':21},
-    EAGER = true;
-
-function angularServiceInject(name, fn, inject, eager) {
-  angularService(name, fn, {$inject:inject, $eager:eager});
-}
-
 /**
  * @workInProgress
  * @ngdoc service
- * @name angular.service.$window
+ * @name angular.service.$cookieStore
+ * @requires $cookies
  *
  * @description
- * Is reference to the browser's `window` object. While `window`
- * is globally available in JavaScript, it causes testability problems, because
- * it is a global variable. In angular we always refer to it through the
- * `$window` service, so it may be overriden, removed or mocked for testing.
- *
- * All expressions are evaluated with respect to current scope so they don't
- * suffer from window globality.
- *
+ * Provides a key-value (string-object) storage, that is backed by session cookies.
+ * Objects put or retrieved from this storage are automatically serialized or
+ * deserialized by angular's toJson/fromJson.
  * @example
-   <doc:example>
-     <doc:source>
-       <input ng:init="$window = $service('$window'); greeting='Hello World!'" type="text" name="greeting" />
-       <button ng:click="$window.alert(greeting)">ALERT</button>
-     </doc:source>
-     <doc:scenario>
-     </doc:scenario>
-   </doc:example>
  */
-angularServiceInject("$window", bind(window, identity, window), [], EAGER);
+angularServiceInject('$cookieStore', function($store) {
 
-/**
- * @workInProgress
- * @ngdoc service
- * @name angular.service.$document
- * @requires $window
- *
- * @description
- * Reference to the browser window.document, but wrapped into angular.element().
- */
-angularServiceInject("$document", function(window){
-  return jqLite(window.document);
-}, ['$window'], EAGER);
+  return {
+    /**
+     * @workInProgress
+     * @ngdoc method
+     * @name angular.service.$cookieStore#get
+     * @methodOf angular.service.$cookieStore
+     *
+     * @description
+     * Returns the value of given cookie key
+     *
+     * @param {string} key Id to use for lookup.
+     * @returns {Object} Deserialized cookie value.
+     */
+    get: function(key) {
+      return fromJson($store[key]);
+    },
+
+    /**
+     * @workInProgress
+     * @ngdoc method
+     * @name angular.service.$cookieStore#put
+     * @methodOf angular.service.$cookieStore
+     *
+     * @description
+     * Sets a value for given cookie key
+     *
+     * @param {string} key Id for the `value`.
+     * @param {Object} value Value to be stored.
+     */
+    put: function(key, value) {
+      $store[key] = toJson(value);
+    },
+
+    /**
+     * @workInProgress
+     * @ngdoc method
+     * @name angular.service.$cookieStore#remove
+     * @methodOf angular.service.$cookieStore
+     *
+     * @description
+     * Remove given cookie
+     *
+     * @param {string} key Id of the key-value pair to delete.
+     */
+    remove: function(key) {
+      delete $store[key];
+    }
+  };
 
+}, ['$cookies']);
 /**
  * @workInProgress
  * @ngdoc service
- * @name angular.service.$location
+ * @name angular.service.$cookies
  * @requires $browser
  *
- * @property {string} href
- * @property {string} protocol
- * @property {string} host
- * @property {number} port
- * @property {string} path
- * @property {Object.<string|boolean>} search
- * @property {string} hash
- * @property {string} hashPath
- * @property {Object.<string|boolean>} hashSearch
- *
  * @description
- * Parses the browser location url and makes it available to your application.
- * Any changes to the url are reflected into $location service and changes to
- * $location are reflected to url.
- * Notice that using browser's forward/back buttons changes the $location.
+ * Provides read/write access to browser's cookies.
+ *
+ * Only a simple Object is exposed and by adding or removing properties to/from
+ * this object, new cookies are created/deleted at the end of current $eval.
  *
  * @example
-   <doc:example>
-     <doc:source>
-       <a href="#">clear hash</a> |
-       <a href="#myPath?name=misko">test hash</a><br/>
-       <input type='text' name="$location.hash"/>
-       <pre>$location = {{$location}}</pre>
-     </doc:source>
-     <doc:scenario>
-     </doc:scenario>
-    </doc:example>
  */
-angularServiceInject("$location", function($browser) {
-  var scope = this,
-      location = {update:update, updateHash: updateHash},
-      lastLocation = {};
+angularServiceInject('$cookies', function($browser) {
+  var rootScope = this,
+      cookies = {},
+      lastCookies = {},
+      lastBrowserCookies,
+      runEval = false;
 
-  $browser.onHashChange(function() { //register
-    update($browser.getUrl());
-    copy(location, lastLocation);
-    scope.$eval();
-  })(); //initialize
+  //creates a poller fn that copies all cookies from the $browser to service & inits the service
+  $browser.addPollFn(function() {
+    var currentCookies = $browser.cookies();
+    if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
+      lastBrowserCookies = currentCookies;
+      copy(currentCookies, lastCookies);
+      copy(currentCookies, cookies);
+      if (runEval) rootScope.$eval();
+    }
+  })();
 
-  this.$onEval(PRIORITY_FIRST, sync);
-  this.$onEval(PRIORITY_LAST, updateBrowser);
+  runEval = true;
 
-  return location;
+  //at the end of each eval, push cookies
+  //TODO: this should happen before the "delayed" watches fire, because if some cookies are not
+  //      strings or browser refuses to store some cookies, we update the model in the push fn.
+  this.$onEval(PRIORITY_LAST, push);
+
+  return cookies;
 
-  // PUBLIC METHODS
 
   /**
-   * @workInProgress
-   * @ngdoc method
-   * @name angular.service.$location#update
-   * @methodOf angular.service.$location
-   *
-   * @description
-   * Update location object
-   * Does not immediately update the browser
-   * Browser is updated at the end of $eval()
-   *
-   * @example
-    <doc:example>
-      <doc:source>
-        scope.$location.update('http://www.angularjs.org/path#hash?search=x');
-        scope.$location.update({host: 'www.google.com', protocol: 'https'});
-        scope.$location.update({hashPath: '/path', hashSearch: {a: 'b', x: true}});
-      </doc:source>
-      <doc:scenario>
-      </doc:scenario>
-    </doc:example>
-   *
-   * @param {(string|Object)} href Full href as a string or object with properties
+   * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.
    */
-  function update(href) {
-    if (isString(href)) {
-      extend(location, parseHref(href));
-    } else {
-      if (isDefined(href.hash)) {
-        extend(href, isString(href.hash) ? parseHash(href.hash) : href.hash);
-      }
+  function push(){
+    var name,
+        value,
+        browserCookies,
+        updated;
 
-      extend(location, href);
+    //delete any cookies deleted in $cookies
+    for (name in lastCookies) {
+      if (isUndefined(cookies[name])) {
+        $browser.cookies(name, _undefined);
+      }
+    }
 
-      if (isDefined(href.hashPath || href.hashSearch)) {
-        location.hash = composeHash(location);
+    //update all cookies updated in $cookies
+    for(name in cookies) {
+      value = cookies[name];
+      if (!isString(value)) {
+        if (isDefined(lastCookies[name])) {
+          cookies[name] = lastCookies[name];
+        } else {
+          delete cookies[name];
+        }
+      } else if (value !== lastCookies[name]) {
+        $browser.cookies(name, value);
+        updated = true;
       }
+    }
 
-      location.href = composeHref(location);
+    //verify what was actually stored
+    if (updated){
+      updated = false;
+      browserCookies = $browser.cookies();
+
+      for (name in cookies) {
+        if (cookies[name] !== browserCookies[name]) {
+          //delete or reset all cookies that the browser dropped from $cookies
+          if (isUndefined(browserCookies[name])) {
+            delete cookies[name];
+          } else {
+            cookies[name] = browserCookies[name];
+          }
+          updated = true;
+        }
+      }
     }
   }
-
-  /**
-   * @workInProgress
-   * @ngdoc method
-   * @name angular.service.$location#updateHash
-   * @methodOf angular.service.$location
+}, ['$browser']);
+/**
+ * @workInProgress
+ * @ngdoc service
+ * @name angular.service.$defer
+ * @requires $browser
+ * @requires $exceptionHandler
+ * @requires $updateView
+ *
+ * @description
+ * Delegates to {@link angular.service.$browser.defer $browser.defer}, but wraps the `fn` function
+ * into a try/catch block and delegates any exceptions to
+ * {@link angular.services.$exceptionHandler $exceptionHandler} service.
+ *
+ * In tests you can use `$browser.defer.flush()` to flush the queue of deferred functions.
+ *
+ * @param {function()} fn A function, who's execution should be deferred.
+ * @param {number=} [delay=0] of milliseconds to defer the function execution.
+ */
+angularServiceInject('$defer', function($browser, $exceptionHandler, $updateView) {
+  return function(fn, delay) {
+    $browser.defer(function() {
+      try {
+        fn();
+      } catch(e) {
+        $exceptionHandler(e);
+      } finally {
+        $updateView();
+      }
+    }, delay);
+  };
+}, ['$browser', '$exceptionHandler', '$updateView']);
+/**
+ * @workInProgress
+ * @ngdoc service
+ * @name angular.service.$document
+ * @requires $window
+ *
+ * @description
+ * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`
+ * element.
+ */
+angularServiceInject("$document", function(window){
+  return jqLite(window.document);
+}, ['$window']);
+/**
+ * @workInProgress
+ * @ngdoc service
+ * @name angular.service.$exceptionHandler
+ * @requires $log
+ *
+ * @description
+ * Any uncaught exception in angular expressions is delegated to this service.
+ * The default implementation simply delegates to `$log.error` which logs it into
+ * the browser console.
+ *
+ * In unit tests, if `angular-mocks.js` is loaded, this service is overriden by
+ * {@link angular.mock.service.$exceptionHandler mock $exceptionHandler}
+ *
+ * @example
+ */
+var $exceptionHandlerFactory; //reference to be used only in tests
+angularServiceInject('$exceptionHandler', $exceptionHandlerFactory = function($log){
+  return function(e) {
+    $log.error(e);
+  };
+}, ['$log']);
+/**
+ * @workInProgress
+ * @ngdoc service
+ * @name angular.service.$hover
+ * @requires $browser
+ * @requires $document
+ *
+ * @description
+ *
+ * @example
+ */
+angularServiceInject("$hover", function(browser, document) {
+  var tooltip, self = this, error, width = 300, arrowWidth = 10, body = jqLite(document[0].body);
+  browser.hover(function(element, show){
+    if (show && (error = element.attr(NG_EXCEPTION) || element.attr(NG_VALIDATION_ERROR))) {
+      if (!tooltip) {
+        tooltip = {
+            callout: jqLite('<div id="ng-callout"></div>'),
+            arrow: jqLite('<div></div>'),
+            title: jqLite('<div class="ng-title"></div>'),
+            content: jqLite('<div class="ng-content"></div>')
+        };
+        tooltip.callout.append(tooltip.arrow);
+        tooltip.callout.append(tooltip.title);
+        tooltip.callout.append(tooltip.content);
+        body.append(tooltip.callout);
+      }
+      var docRect = body[0].getBoundingClientRect(),
+          elementRect = element[0].getBoundingClientRect(),
+          leftSpace = docRect.right - elementRect.right - arrowWidth;
+      tooltip.title.text(element.hasClass("ng-exception") ? "EXCEPTION:" : "Validation error...");
+      tooltip.content.text(error);
+      if (leftSpace < width) {
+        tooltip.arrow.addClass('ng-arrow-right');
+        tooltip.arrow.css({left: (width + 1)+'px'});
+        tooltip.callout.css({
+          position: 'fixed',
+          left: (elementRect.left - arrowWidth - width - 4) + "px",
+          top: (elementRect.top - 3) + "px",
+          width: width + "px"
+        });
+      } else {
+        tooltip.arrow.addClass('ng-arrow-left');
+        tooltip.callout.css({
+          position: 'fixed',
+          left: (elementRect.right + arrowWidth) + "px",
+          top: (elementRect.top - 3) + "px",
+          width: width + "px"
+        });
+      }
+    } else if (tooltip) {
+      tooltip.callout.remove();
+      tooltip = _null;
+    }
+  });
+}, ['$browser', '$document']);
+/**
+ * @workInProgress
+ * @ngdoc service
+ * @name angular.service.$invalidWidgets
+ *
+ * @description
+ * Keeps references to all invalid widgets found during validation.
+ * Can be queried to find whether there are any invalid widgets currently displayed.
+ *
+ * @example
+ */
+angularServiceInject("$invalidWidgets", function(){
+  var invalidWidgets = [];
+
+
+  /** Remove an element from the array of invalid widgets */
+  invalidWidgets.markValid = function(element){
+    var index = indexOf(invalidWidgets, element);
+    if (index != -1)
+      invalidWidgets.splice(index, 1);
+  };
+
+
+  /** Add an element to the array of invalid widgets */
+  invalidWidgets.markInvalid = function(element){
+    var index = indexOf(invalidWidgets, element);
+    if (index === -1)
+      invalidWidgets.push(element);
+  };
+
+
+  /** Return count of all invalid widgets that are currently visible */
+  invalidWidgets.visible = function() {
+    var count = 0;
+    forEach(invalidWidgets, function(widget){
+      count = count + (isVisible(widget) ? 1 : 0);
+    });
+    return count;
+  };
+
+
+  /* At the end of each eval removes all invalid widgets that are not part of the current DOM. */
+  this.$onEval(PRIORITY_LAST, function() {
+    for(var i = 0; i < invalidWidgets.length;) {
+      var widget = invalidWidgets[i];
+      if (isOrphan(widget[0])) {
+        invalidWidgets.splice(i, 1);
+        if (widget.dealoc) widget.dealoc();
+      } else {
+        i++;
+      }
+    }
+  });
+
+
+  /**
+   * Traverses DOM element's (widget's) parents and considers the element to be an orphant if one of
+   * it's parents isn't the current window.document.
+   */
+  function isOrphan(widget) {
+    if (widget == window.document) return false;
+    var parent = widget.parentNode;
+    return !parent || isOrphan(parent);
+  }
+
+  return invalidWidgets;
+});
+var URL_MATCH = /^(file|ftp|http|https):\/\/(\w+:{0,1}\w*@)?([\w\.-]*)(:([0-9]+))?(\/[^\?#]*)?(\?([^#]*))?(#(.*))?$/,
+    HASH_MATCH = /^([^\?]*)?(\?([^\?]*))?$/,
+    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp':21};
+
+/**
+ * @workInProgress
+ * @ngdoc service
+ * @name angular.service.$location
+ * @requires $browser
+ *
+ * @property {string} href
+ * @property {string} protocol
+ * @property {string} host
+ * @property {number} port
+ * @property {string} path
+ * @property {Object.<string|boolean>} search
+ * @property {string} hash
+ * @property {string} hashPath
+ * @property {Object.<string|boolean>} hashSearch
+ *
+ * @description
+ * Parses the browser location url and makes it available to your application.
+ * Any changes to the url are reflected into $location service and changes to
+ * $location are reflected to url.
+ * Notice that using browser's forward/back buttons changes the $location.
+ *
+ * @example
+   <doc:example>
+     <doc:source>
+       <a href="#">clear hash</a> |
+       <a href="#myPath?name=misko">test hash</a><br/>
+       <input type='text' name="$location.hash"/>
+       <pre>$location = {{$location}}</pre>
+     </doc:source>
+     <doc:scenario>
+     </doc:scenario>
+    </doc:example>
+ */
+angularServiceInject("$location", function($browser) {
+  var scope = this,
+      location = {update:update, updateHash: updateHash},
+      lastLocation = {};
+
+  $browser.onHashChange(function() { //register
+    update($browser.getUrl());
+    copy(location, lastLocation);
+    scope.$eval();
+  })(); //initialize
+
+  this.$onEval(PRIORITY_FIRST, sync);
+  this.$onEval(PRIORITY_LAST, updateBrowser);
+
+  return location;
+
+  // PUBLIC METHODS
+
+  /**
+   * @workInProgress
+   * @ngdoc method
+   * @name angular.service.$location#update
+   * @methodOf angular.service.$location
+   *
+   * @description
+   * Update location object
+   * Does not immediately update the browser
+   * Browser is updated at the end of $eval()
+   *
+   * @example
+    <doc:example>
+      <doc:source>
+        scope.$location.update('http://www.angularjs.org/path#hash?search=x');
+        scope.$location.update({host: 'www.google.com', protocol: 'https'});
+        scope.$location.update({hashPath: '/path', hashSearch: {a: 'b', x: true}});
+      </doc:source>
+      <doc:scenario>
+      </doc:scenario>
+    </doc:example>
+   *
+   * @param {(string|Object)} href Full href as a string or object with properties
+   */
+  function update(href) {
+    if (isString(href)) {
+      extend(location, parseHref(href));
+    } else {
+      if (isDefined(href.hash)) {
+        extend(href, isString(href.hash) ? parseHash(href.hash) : href.hash);
+      }
+
+      extend(location, href);
+
+      if (isDefined(href.hashPath || href.hashSearch)) {
+        location.hash = composeHash(location);
+      }
+
+      location.href = composeHref(location);
+    }
+  }
+
+  /**
+   * @workInProgress
+   * @ngdoc method
+   * @name angular.service.$location#updateHash
+   * @methodOf angular.service.$location
    *
    * @description
    * Update location hash part
@@ -12533,343 +13092,311 @@ angularServiceInject("$location", function($browser) {
     var h = {};
     var match = HASH_MATCH.exec(hash);
 
-    if (match) {
-      h.hash = hash;
-      h.hashPath = unescape(match[1] || '');
-      h.hashSearch = parseKeyValue(match[3]);
-    }
-
-    return h;
-  }
-}, ['$browser']);
-
-
-/**
- * @workInProgress
- * @ngdoc service
- * @name angular.service.$log
- * @requires $window
- *
- * @description
- * Simple service for logging. Default implementation writes the message
- * into the browser's console (if present).
- *
- * The main purpose of this service is to simplify debugging and troubleshooting.
- *
- * @example
-    <doc:example>
-      <doc:source>
-         <p>Reload this page with open console, enter text and hit the log button...</p>
-         Message:
-         <input type="text" name="message" value="Hello World!"/>
-         <button ng:click="$log.log(message)">log</button>
-         <button ng:click="$log.warn(message)">warn</button>
-         <button ng:click="$log.info(message)">info</button>
-         <button ng:click="$log.error(message)">error</button>
-      </doc:source>
-      <doc:scenario>
-      </doc:scenario>
-    </doc:example>
- */
-var $logFactory; //reference to be used only in tests
-angularServiceInject("$log", $logFactory = function($window){
-  return {
-    /**
-     * @workInProgress
-     * @ngdoc method
-     * @name angular.service.$log#log
-     * @methodOf angular.service.$log
-     *
-     * @description
-     * Write a log message
-     */
-    log: consoleLog('log'),
-
-    /**
-     * @workInProgress
-     * @ngdoc method
-     * @name angular.service.$log#warn
-     * @methodOf angular.service.$log
-     *
-     * @description
-     * Write a warning message
-     */
-    warn: consoleLog('warn'),
-
-    /**
-     * @workInProgress
-     * @ngdoc method
-     * @name angular.service.$log#info
-     * @methodOf angular.service.$log
-     *
-     * @description
-     * Write an information message
-     */
-    info: consoleLog('info'),
-
-    /**
-     * @workInProgress
-     * @ngdoc method
-     * @name angular.service.$log#error
-     * @methodOf angular.service.$log
-     *
-     * @description
-     * Write an error message
-     */
-    error: consoleLog('error')
-  };
-
-  function consoleLog(type) {
-    var console = $window.console || {};
-    var logFn = console[type] || console.log || noop;
-    if (logFn.apply) {
-      return function(){
-        var args = [];
-        forEach(arguments, function(arg){
-          args.push(formatError(arg));
-        });
-        return logFn.apply(console, args);
-      };
-    } else {
-      // we are IE, in which case there is nothing we can do
-      return logFn;
-    }
-  }
-}, ['$window'], EAGER);
-
-/**
- * @workInProgress
- * @ngdoc service
- * @name angular.service.$exceptionHandler
- * @requires $log
- *
- * @description
- * Any uncaught exception in angular expressions is delegated to this service.
- * The default implementation simply delegates to `$log.error` which logs it into
- * the browser console.
- *
- * In unit tests, if `angular-mocks.js` is loaded, this service is overriden by
- * {@link angular.mock.service.$exceptionHandler mock $exceptionHandler}
- *
- * @example
- */
-var $exceptionHandlerFactory; //reference to be used only in tests
-angularServiceInject('$exceptionHandler', $exceptionHandlerFactory = function($log){
-  return function(e) {
-    $log.error(e);
-  };
-}, ['$log'], EAGER);
-
-/**
- * @workInProgress
- * @ngdoc service
- * @name angular.service.$updateView
- * @requires $browser
- *
- * @description
- * Calling `$updateView` enqueues the eventual update of the view. (Update the DOM to reflect the
- * model). The update is eventual, since there are often multiple updates to the model which may
- * be deferred. The default update delayed is 25 ms. This means that the view lags the model by
- * that time. (25ms is small enough that it is perceived as instantaneous by the user). The delay
- * can be adjusted by setting the delay property of the service.
- *
- * <pre>angular.service('$updateView').delay = 10</pre>
- *
- * The delay is there so that multiple updates to the model which occur sufficiently close
- * together can be merged into a single update.
- *
- * You don't usually call '$updateView' directly since angular does it for you in most cases,
- * but there are some cases when you need to call it.
- *
- *  - `$updateView()` called automatically by angular:
- *    - Your Application Controllers: Your controller code is called by angular and hence
- *      angular is aware that you may have changed the model.
- *    - Your Services: Your service is usually called by your controller code, hence same rules
- *      apply.
- *  - May need to call `$updateView()` manually:
- *    - Widgets / Directives: If you listen to any DOM events or events on any third party
- *      libraries, then angular is not aware that you may have changed state state of the
- *      model, and hence you need to call '$updateView()' manually.
- *    - 'setTimeout'/'XHR':  If you call 'setTimeout' (instead of {@link angular.service.$defer})
- *      or 'XHR' (instead of {@link angular.service.$xhr}) then you may be changing the model
- *      without angular knowledge and you may need to call '$updateView()' directly.
- *
- * NOTE: if you wish to update the view immediately (without delay), you can do so by calling
- * {@link scope.$eval} at any time from your code:
- * <pre>scope.$root.$eval()</pre>
- *
- * In unit-test mode the update is instantaneous and synchronous to simplify writing tests.
- *
- */
-
-function serviceUpdateViewFactory($browser){
-  var rootScope = this;
-  var scheduled;
-  function update(){
-    scheduled = false;
-    rootScope.$eval();
-  }
-  return $browser.isMock ? update : function(){
-    if (!scheduled) {
-      scheduled = true;
-      $browser.defer(update, serviceUpdateViewFactory.delay);
-    }
-  };
-}
-serviceUpdateViewFactory.delay = 25;
-
-angularServiceInject('$updateView', serviceUpdateViewFactory, ['$browser']);
-
-/**
- * @workInProgress
- * @ngdoc service
- * @name angular.service.$hover
- * @requires $browser
- * @requires $document
- *
- * @description
- *
- * @example
- */
-angularServiceInject("$hover", function(browser, document) {
-  var tooltip, self = this, error, width = 300, arrowWidth = 10, body = jqLite(document[0].body);
-  browser.hover(function(element, show){
-    if (show && (error = element.attr(NG_EXCEPTION) || element.attr(NG_VALIDATION_ERROR))) {
-      if (!tooltip) {
-        tooltip = {
-            callout: jqLite('<div id="ng-callout"></div>'),
-            arrow: jqLite('<div></div>'),
-            title: jqLite('<div class="ng-title"></div>'),
-            content: jqLite('<div class="ng-content"></div>')
-        };
-        tooltip.callout.append(tooltip.arrow);
-        tooltip.callout.append(tooltip.title);
-        tooltip.callout.append(tooltip.content);
-        body.append(tooltip.callout);
-      }
-      var docRect = body[0].getBoundingClientRect(),
-          elementRect = element[0].getBoundingClientRect(),
-          leftSpace = docRect.right - elementRect.right - arrowWidth;
-      tooltip.title.text(element.hasClass("ng-exception") ? "EXCEPTION:" : "Validation error...");
-      tooltip.content.text(error);
-      if (leftSpace < width) {
-        tooltip.arrow.addClass('ng-arrow-right');
-        tooltip.arrow.css({left: (width + 1)+'px'});
-        tooltip.callout.css({
-          position: 'fixed',
-          left: (elementRect.left - arrowWidth - width - 4) + "px",
-          top: (elementRect.top - 3) + "px",
-          width: width + "px"
-        });
-      } else {
-        tooltip.arrow.addClass('ng-arrow-left');
-        tooltip.callout.css({
-          position: 'fixed',
-          left: (elementRect.right + arrowWidth) + "px",
-          top: (elementRect.top - 3) + "px",
-          width: width + "px"
-        });
-      }
-    } else if (tooltip) {
-      tooltip.callout.remove();
-      tooltip = _null;
+    if (match) {
+      h.hash = hash;
+      h.hashPath = unescape(match[1] || '');
+      h.hashSearch = parseKeyValue(match[3]);
     }
-  });
-}, ['$browser', '$document'], EAGER);
 
+    return h;
+  }
+}, ['$browser']);
 /**
  * @workInProgress
  * @ngdoc service
- * @name angular.service.$invalidWidgets
+ * @name angular.service.$log
+ * @requires $window
  *
  * @description
- * Keeps references to all invalid widgets found during validation.
- * Can be queried to find whether there are any invalid widgets currently displayed.
+ * Simple service for logging. Default implementation writes the message
+ * into the browser's console (if present).
+ *
+ * The main purpose of this service is to simplify debugging and troubleshooting.
  *
  * @example
+    <doc:example>
+      <doc:source>
+         <p>Reload this page with open console, enter text and hit the log button...</p>
+         Message:
+         <input type="text" name="message" value="Hello World!"/>
+         <button ng:click="$log.log(message)">log</button>
+         <button ng:click="$log.warn(message)">warn</button>
+         <button ng:click="$log.info(message)">info</button>
+         <button ng:click="$log.error(message)">error</button>
+      </doc:source>
+      <doc:scenario>
+      </doc:scenario>
+    </doc:example>
  */
-angularServiceInject("$invalidWidgets", function(){
-  var invalidWidgets = [];
-
+var $logFactory; //reference to be used only in tests
+angularServiceInject("$log", $logFactory = function($window){
+  return {
+    /**
+     * @workInProgress
+     * @ngdoc method
+     * @name angular.service.$log#log
+     * @methodOf angular.service.$log
+     *
+     * @description
+     * Write a log message
+     */
+    log: consoleLog('log'),
 
-  /** Remove an element from the array of invalid widgets */
-  invalidWidgets.markValid = function(element){
-    var index = indexOf(invalidWidgets, element);
-    if (index != -1)
-      invalidWidgets.splice(index, 1);
-  };
+    /**
+     * @workInProgress
+     * @ngdoc method
+     * @name angular.service.$log#warn
+     * @methodOf angular.service.$log
+     *
+     * @description
+     * Write a warning message
+     */
+    warn: consoleLog('warn'),
 
+    /**
+     * @workInProgress
+     * @ngdoc method
+     * @name angular.service.$log#info
+     * @methodOf angular.service.$log
+     *
+     * @description
+     * Write an information message
+     */
+    info: consoleLog('info'),
 
-  /** Add an element to the array of invalid widgets */
-  invalidWidgets.markInvalid = function(element){
-    var index = indexOf(invalidWidgets, element);
-    if (index === -1)
-      invalidWidgets.push(element);
+    /**
+     * @workInProgress
+     * @ngdoc method
+     * @name angular.service.$log#error
+     * @methodOf angular.service.$log
+     *
+     * @description
+     * Write an error message
+     */
+    error: consoleLog('error')
   };
 
+  function consoleLog(type) {
+    var console = $window.console || {};
+    var logFn = console[type] || console.log || noop;
+    if (logFn.apply) {
+      return function(){
+        var args = [];
+        forEach(arguments, function(arg){
+          args.push(formatError(arg));
+        });
+        return logFn.apply(console, args);
+      };
+    } else {
+      // we are IE, in which case there is nothing we can do
+      return logFn;
+    }
+  }
+}, ['$window']);
+/**
+ * @workInProgress
+ * @ngdoc service
+ * @name angular.service.$resource
+ * @requires $xhr.cache
+ *
+ * @description
+ * A factory which creates a resource object that lets you interact with
+ * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
+ *
+ * The returned resource object has action methods which provide high-level behaviors without
+ * the need to interact with the low level {@link angular.service.$xhr $xhr} service or
+ * raw XMLHttpRequest.
+ *
+ * @param {string} url A parameterized URL template with parameters prefixed by `:` as in
+ *   `/user/:username`.
+ *
+ * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
+ *   `actions` methods.
+ *
+ *   Each key value in the parameter object is first bound to url template if present and then any
+ *   excess keys are appended to the url search query after the `?`.
+ *
+ *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
+ *   URL `/path/greet?salutation=Hello`.
+ *
+ *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from
+ *   the data object (useful for non-GET operations).
+ *
+ * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the
+ *   default set of resource actions. The declaration should be created in the following format:
+ *
+ *       {action1: {method:?, params:?, isArray:?, verifyCache:?},
+ *        action2: {method:?, params:?, isArray:?, verifyCache:?},
+ *        ...}
+ *
+ *   Where:
+ *
+ *   - `action` – {string} – The name of action. This name becomes the name of the method on your
+ *     resource object.
+ *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
+ *     and `JSON` (also known as JSONP).
+ *   - `params` – {object=} – Optional set of pre-bound parameters for this action.
+ *   - isArray – {boolean=} – If true then the returned object for this action is an array, see
+ *     `returns` section.
+ *   - verifyCache – {boolean=} – If true then whenever cache hit occurs, the object is returned and
+ *     an async request will be made to the server and the resources as well as the cache will be
+ *     updated when the response is received.
+ *
+ * @returns {Object} A resource "class" object with methods for the default set of resource actions
+ *   optionally extended with custom `actions`. The default set contains these actions:
+ *
+ *       { 'get':    {method:'GET'},
+ *         'save':   {method:'POST'},
+ *         'query':  {method:'GET', isArray:true},
+ *         'remove': {method:'DELETE'},
+ *         'delete': {method:'DELETE'} };
+ *
+ *   Calling these methods invoke an {@link angular.service.$xhr} with the specified http method,
+ *   destination and parameters. When the data is returned from the server then the object is an
+ *   instance of the resource class `save`, `remove` and `delete` actions are available on it as
+ *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,
+ *   update, delete) on server-side data like this:
+ *   <pre>
+        var User = $resource('/user/:userId', {userId:'@id'});
+        var user = User.get({userId:123}, function(){
+          user.abc = true;
+          user.$save();
+        });
+     </pre>
+ *
+ *   It is important to realize that invoking a $resource object method immediately returns an
+ *   empty reference (object or array depending on `isArray`). Once the data is returned from the
+ *   server the existing reference is populated with the actual data. This is a useful trick since
+ *   usually the resource is assigned to a model which is then rendered by the view. Having an empty
+ *   object results in no rendering, once the data arrives from the server then the object is
+ *   populated with the data and the view automatically re-renders itself showing the new data. This
+ *   means that in most case one never has to write a callback function for the action methods.
+ *
+ *   The action methods on the class object or instance object can be invoked with the following
+ *   parameters:
+ *
+ *   - HTTP GET "class" actions: `Resource.action([parameters], [callback])`
+ *   - non-GET "class" actions: `Resource.action(postData, [parameters], [callback])`
+ *   - non-GET instance actions:  `instance.$action([parameters], [callback])`
+ *
+ *
+ * @example
+ *
+ * # Credit card resource
+ *
+ * <pre>
+     // Define CreditCard class
+     var CreditCard = $resource('/user/:userId/card/:cardId',
+      {userId:123, cardId:'@id'}, {
+       charge: {method:'POST', params:{charge:true}}
+      });
 
-  /** Return count of all invalid widgets that are currently visible */
-  invalidWidgets.visible = function() {
-    var count = 0;
-    forEach(invalidWidgets, function(widget){
-      count = count + (isVisible(widget) ? 1 : 0);
-    });
-    return count;
-  };
-
+     // We can retrieve a collection from the server
+     var cards = CreditCard.query();
+     // GET: /user/123/card
+     // server returns: [ {id:456, number:'1234', name:'Smith'} ];
 
-  /* At the end of each eval removes all invalid widgets that are not part of the current DOM. */
-  this.$onEval(PRIORITY_LAST, function() {
-    for(var i = 0; i < invalidWidgets.length;) {
-      var widget = invalidWidgets[i];
-      if (isOrphan(widget[0])) {
-        invalidWidgets.splice(i, 1);
-        if (widget.dealoc) widget.dealoc();
-      } else {
-        i++;
-      }
-    }
-  });
+     var card = cards[0];
+     // each item is an instance of CreditCard
+     expect(card instanceof CreditCard).toEqual(true);
+     card.name = "J. Smith";
+     // non GET methods are mapped onto the instances
+     card.$save();
+     // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
+     // server returns: {id:456, number:'1234', name: 'J. Smith'};
 
+     // our custom method is mapped as well.
+     card.$charge({amount:9.99});
+     // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
+     // server returns: {id:456, number:'1234', name: 'J. Smith'};
 
-  /**
-   * Traverses DOM element's (widget's) parents and considers the element to be an orphant if one of
-   * it's parents isn't the current window.document.
-   */
-  function isOrphan(widget) {
-    if (widget == window.document) return false;
-    var parent = widget.parentNode;
-    return !parent || isOrphan(parent);
-  }
+     // we can create an instance as well
+     var newCard = new CreditCard({number:'0123'});
+     newCard.name = "Mike Smith";
+     newCard.$save();
+     // POST: /user/123/card {number:'0123', name:'Mike Smith'}
+     // server returns: {id:789, number:'01234', name: 'Mike Smith'};
+     expect(newCard.id).toEqual(789);
+ * </pre>
+ *
+ * The object returned from this function execution is a resource "class" which has "static" method
+ * for each action in the definition.
+ *
+ * Calling these methods invoke `$xhr` on the `url` template with the given `method` and `params`.
+ * When the data is returned from the server then the object is an instance of the resource type and
+ * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
+ * operations (create, read, update, delete) on server-side data.
 
-  return invalidWidgets;
-}, [], EAGER);
+   <pre>
+     var User = $resource('/user/:userId', {userId:'@id'});
+     var user = User.get({userId:123}, function(){
+       user.abc = true;
+       user.$save();
+     });
+   </pre>
+ *
+ *     It's worth noting that the callback for `get`, `query` and other method gets passed in the
+ *     response that came from the server, so one could rewrite the above example as:
+ *
+   <pre>
+     var User = $resource('/user/:userId', {userId:'@id'});
+     User.get({userId:123}, function(u){
+       u.abc = true;
+       u.$save();
+     });
+   </pre>
 
+ * # Buzz client
 
+   Let's look at what a buzz client created with the `$resource` service looks like:
+    <doc:example>
+      <doc:source>
+       <script>
+         function BuzzController($resource) {
+           this.Activity = $resource(
+             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
+             {alt:'json', callback:'JSON_CALLBACK'},
+             {get:{method:'JSON', params:{visibility:'@self'}}, replies: {method:'JSON', params:{visibility:'@self', comments:'@comments'}}}
+           );
+         }
 
-function switchRouteMatcher(on, when, dstName) {
-  var regex = '^' + when.replace(/[\.\\\(\)\^\$]/g, "\$1") + '$',
-      params = [],
-      dst = {};
-  forEach(when.split(/\W/), function(param){
-    if (param) {
-      var paramRegExp = new RegExp(":" + param + "([\\W])");
-      if (regex.match(paramRegExp)) {
-        regex = regex.replace(paramRegExp, "([^\/]*)$1");
-        params.push(param);
-      }
-    }
-  });
-  var match = on.match(new RegExp(regex));
-  if (match) {
-    forEach(params, function(name, index){
-      dst[name] = match[index + 1];
-    });
-    if (dstName) this.$set(dstName, dst);
-  }
-  return match ? dst : _null;
-}
+         BuzzController.prototype = {
+           fetch: function() {
+             this.activities = this.Activity.get({userId:this.userId});
+           },
+           expandReplies: function(activity) {
+             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
+           }
+         };
+         BuzzController.$inject = ['$resource'];
+       </script>
 
+       <div ng:controller="BuzzController">
+         <input name="userId" value="googlebuzz"/>
+         <button ng:click="fetch()">fetch</button>
+         <hr/>
+         <div ng:repeat="item in activities.data.items">
+           <h1 style="font-size: 15px;">
+             <img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
+             <a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
+             <a href ng:click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
+           </h1>
+           {{item.object.content | html}}
+           <div ng:repeat="reply in item.replies.data.items" style="margin-left: 20px;">
+             <img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
+             <a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
+           </div>
+         </div>
+       </div>
+      </doc:source>
+      <doc:scenario>
+      </doc:scenario>
+    </doc:example>
+ */
+angularServiceInject('$resource', function($xhr){
+  var resource = new ResourceFactory($xhr);
+  return bind(resource, resource.route);
+}, ['$xhr.cache']);
 /**
  * @workInProgress
  * @ngdoc service
@@ -13046,6 +13573,32 @@ angularServiceInject('$route', function(location, $updateView) {
           dirty++;
         }
       };
+
+
+  function switchRouteMatcher(on, when, dstName) {
+    var regex = '^' + when.replace(/[\.\\\(\)\^\$]/g, "\$1") + '$',
+        params = [],
+        dst = {};
+    forEach(when.split(/\W/), function(param){
+      if (param) {
+        var paramRegExp = new RegExp(":" + param + "([\\W])");
+        if (regex.match(paramRegExp)) {
+          regex = regex.replace(paramRegExp, "([^\/]*)$1");
+          params.push(param);
+        }
+      }
+    });
+    var match = on.match(new RegExp(regex));
+    if (match) {
+      forEach(params, function(name, index){
+        dst[name] = match[index + 1];
+      });
+      if (dstName) this.$set(dstName, dst);
+    }
+    return match ? dst : _null;
+  }
+
+
   function updateRoute(){
     var childScope, routeParams, pathParams, segmentMatch, key, redir;
 
@@ -13105,153 +13658,95 @@ angularServiceInject('$route', function(location, $updateView) {
     }
   }
 
+
   this.$watch(function(){return dirty + location.hash;}, updateRoute);
 
   return $route;
 }, ['$location', '$updateView']);
-
 /**
  * @workInProgress
  * @ngdoc service
- * @name angular.service.$xhr
- * @function
+ * @name angular.service.$updateView
  * @requires $browser
- * @requires $xhr.error
- * @requires $log
  *
  * @description
- * Generates an XHR request. The $xhr service adds error handling then delegates all requests to
- * {@link angular.service.$browser $browser.xhr()}.
+ * Calling `$updateView` enqueues the eventual update of the view. (Update the DOM to reflect the
+ * model). The update is eventual, since there are often multiple updates to the model which may
+ * be deferred. The default update delayed is 25 ms. This means that the view lags the model by
+ * that time. (25ms is small enough that it is perceived as instantaneous by the user). The delay
+ * can be adjusted by setting the delay property of the service.
  *
- * @param {string} method HTTP method to use. Valid values are: `GET`, `POST`, `PUT`, `DELETE`, and
- *   `JSON`. `JSON` is a special case which causes a
- *   [JSONP](http://en.wikipedia.org/wiki/JSON#JSONP) cross domain request using script tag
- *   insertion.
- * @param {string} url Relative or absolute URL specifying the destination of the request.  For
- *   `JSON` requests, `url` should include `JSON_CALLBACK` string to be replaced with a name of an
- *   angular generated callback function.
- * @param {(string|Object)=} post Request content as either a string or an object to be stringified
- *   as JSON before sent to the server.
- * @param {function(number, (string|Object))} callback A function to be called when the response is
- *   received. The callback will be called with:
+ * <pre>angular.service('$updateView').delay = 10</pre>
  *
- *   - {number} code [HTTP status code](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes) of
- *     the response. This will currently always be 200, since all non-200 responses are routed to
- *     {@link angular.service.$xhr.error} service.
- *   - {string|Object} response Response object as string or an Object if the response was in JSON
- *     format.
+ * The delay is there so that multiple updates to the model which occur sufficiently close
+ * together can be merged into a single update.
+ *
+ * You don't usually call '$updateView' directly since angular does it for you in most cases,
+ * but there are some cases when you need to call it.
+ *
+ *  - `$updateView()` called automatically by angular:
+ *    - Your Application Controllers: Your controller code is called by angular and hence
+ *      angular is aware that you may have changed the model.
+ *    - Your Services: Your service is usually called by your controller code, hence same rules
+ *      apply.
+ *  - May need to call `$updateView()` manually:
+ *    - Widgets / Directives: If you listen to any DOM events or events on any third party
+ *      libraries, then angular is not aware that you may have changed state state of the
+ *      model, and hence you need to call '$updateView()' manually.
+ *    - 'setTimeout'/'XHR':  If you call 'setTimeout' (instead of {@link angular.service.$defer})
+ *      or 'XHR' (instead of {@link angular.service.$xhr}) then you may be changing the model
+ *      without angular knowledge and you may need to call '$updateView()' directly.
+ *
+ * NOTE: if you wish to update the view immediately (without delay), you can do so by calling
+ * {@link scope.$eval} at any time from your code:
+ * <pre>scope.$root.$eval()</pre>
+ *
+ * In unit-test mode the update is instantaneous and synchronous to simplify writing tests.
  *
- * @example
-   <doc:example>
-     <doc:source>
-       <script>
-         function FetchCntl($xhr) {
-           var self = this;
-
-           this.fetch = function() {
-             self.clear();
-             $xhr(self.method, self.url, function(code, response) {
-               self.code = code;
-               self.response = response;
-             });
-           };
-
-           this.clear = function() {
-             self.code = null;
-             self.response = null;
-           };
-         }
-         FetchCntl.$inject = ['$xhr'];
-       </script>
-       <div ng:controller="FetchCntl">
-         <select name="method">
-           <option>GET</option>
-           <option>JSON</option>
-         </select>
-         <input type="text" name="url" value="index.html" size="80"/><br/>
-         <button ng:click="fetch()">fetch</button>
-         <button ng:click="clear()">clear</button>
-         <a href="" ng:click="method='GET'; url='index.html'">sample</a>
-         <a href="" ng:click="method='JSON'; url='https://www.googleapis.com/buzz/v1/activities/googlebuzz/@self?alt=json&callback=JSON_CALLBACK'">buzz</a>
-         <pre>code={{code}}</pre>
-         <pre>response={{response}}</pre>
-       </div>
-     </doc:source>
-   </doc:example>
  */
-angularServiceInject('$xhr', function($browser, $error, $log){
-  var self = this;
-  return function(method, url, post, callback){
-    if (isFunction(post)) {
-      callback = post;
-      post = _null;
-    }
-    if (post && isObject(post)) {
-      post = toJson(post);
+
+function serviceUpdateViewFactory($browser){
+  var rootScope = this;
+  var scheduled;
+  function update(){
+    scheduled = false;
+    rootScope.$eval();
+  }
+  return $browser.isMock ? update : function(){
+    if (!scheduled) {
+      scheduled = true;
+      $browser.defer(update, serviceUpdateViewFactory.delay);
     }
-    $browser.xhr(method, url, post, function(code, response){
-      try {
-        if (isString(response) && /^\s*[\[\{]/.exec(response) && /[\}\]]\s*$/.exec(response)) {
-          response = fromJson(response, true);
-        }
-        if (code == 200) {
-          callback(code, response);
-        } else {
-          $error(
-            {method: method, url:url, data:post, callback:callback},
-            {status: code, body:response});
-        }
-      } catch (e) {
-        $log.error(e);
-      } finally {
-        self.$eval();
-      }
-    });
   };
-}, ['$browser', '$xhr.error', '$log']);
+}
+serviceUpdateViewFactory.delay = 25;
 
+angularServiceInject('$updateView', serviceUpdateViewFactory, ['$browser']);
 /**
  * @workInProgress
  * @ngdoc service
- * @name angular.service.$xhr.error
- * @function
- * @requires $log
+ * @name angular.service.$window
  *
  * @description
- * Error handler for {@link angular.service.$xhr $xhr service}. An application can replaces this
- * service with one specific for the application. The default implementation logs the error to
- * {@link angular.service.$log $log.error}.
- *
- * @param {Object} request Request object.
- *
- *   The object has the following properties
- *
- *   - `method` – `{string}` – The http request method.
- *   - `url` – `{string}` – The request destination.
- *   - `data` – `{(string|Object)=} – An optional request body.
- *   - `callback` – `{function()}` – The callback function
- *
- * @param {Object} response Response object.
- *
- *   The response object has the following properties:
+ * A reference to the browser's `window` object. While `window`
+ * is globally available in JavaScript, it causes testability problems, because
+ * it is a global variable. In angular we always refer to it through the
+ * `$window` service, so it may be overriden, removed or mocked for testing.
  *
- *   - status – {number} – Http status code.
- *   - body – {string|Object} – Body of the response.
+ * All expressions are evaluated with respect to current scope so they don't
+ * suffer from window globality.
  *
  * @example
-    <doc:example>
-      <doc:source>
-        fetch a non-existent file and log an error in the console:
-        <button ng:click="$service('$xhr')('GET', '/DOESNT_EXIST')">fetch</button>
-      </doc:source>
-    </doc:example>
+   <doc:example>
+     <doc:source>
+       <input ng:init="$window = $service('$window'); greeting='Hello World!'" type="text" name="greeting" />
+       <button ng:click="$window.alert(greeting)">ALERT</button>
+     </doc:source>
+     <doc:scenario>
+     </doc:scenario>
+   </doc:example>
  */
-angularServiceInject('$xhr.error', function($log){
-  return function(request, response){
-    $log.error('ERROR: XHR: ' + request.url, request, response);
-  };
-}, ['$log']);
-
+angularServiceInject("$window", bind(window, identity, window));
 /**
  * @workInProgress
  * @ngdoc service
@@ -13313,41 +13808,6 @@ angularServiceInject('$xhr.bulk', function($xhr, $error, $log){
   this.$onEval(PRIORITY_LAST, bulkXHR.flush);
   return bulkXHR;
 }, ['$xhr', '$xhr.error', '$log']);
-
-
-/**
- * @workInProgress
- * @ngdoc service
- * @name angular.service.$defer
- * @requires $browser
- * @requires $log
- *
- * @description
- * Delegates to {@link angular.service.$browser.defer $browser.defer}, but wraps the `fn` function
- * into a try/catch block and delegates any exceptions to
- * {@link angular.services.$exceptionHandler $exceptionHandler} service.
- *
- * In tests you can use `$browser.defer.flush()` to flush the queue of deferred functions.
- *
- * @param {function()} fn A function, who's execution should be deferred.
- */
-angularServiceInject('$defer', function($browser, $exceptionHandler, $updateView) {
-  var scope = this;
-
-  return function(fn) {
-    $browser.defer(function() {
-      try {
-        fn();
-      } catch(e) {
-        $exceptionHandler(e);
-      } finally {
-        $updateView();
-      }
-    });
-  };
-}, ['$browser', '$exceptionHandler', '$updateView']);
-
-
 /**
  * @workInProgress
  * @ngdoc service
@@ -13414,367 +13874,149 @@ angularServiceInject('$xhr.cache', function($xhr, $defer, $log){
   cache.delegate = $xhr;
   return cache;
 }, ['$xhr.bulk', '$defer', '$log']);
-
-
 /**
  * @workInProgress
  * @ngdoc service
- * @name angular.service.$resource
- * @requires $xhr.cache
+ * @name angular.service.$xhr.error
+ * @function
+ * @requires $log
  *
  * @description
- * Is a factory which creates a resource object that lets you interact with
- * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
- *
- * The returned resource object has action methods which provide high-level behaviors without
- * the need to interact with the low level {@link angular.service.$xhr $xhr} service or
- * raw XMLHttpRequest.
- *
- * @param {string} url A parameterized URL template with parameters prefixed by `:` as in
- *   `/user/:username`.
- *
- * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
- *   `actions` methods.
- *
- *   Each key value in the parameter object is first bound to url template if present and then any
- *   excess keys are appended to the url search query after the `?`.
- *
- *   Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
- *   URL `/path/greet?salutation=Hello`.
- *
- *   If the parameter value is prefixed with `@` then the value of that parameter is extracted from
- *   the data object (useful for non-GET operations).
- *
- * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the
- *   default set of resource actions. The declaration should be created in the following format:
- *
- *       {action1: {method:?, params:?, isArray:?, verifyCache:?},
- *        action2: {method:?, params:?, isArray:?, verifyCache:?},
- *        ...}
- *
- *   Where:
- *
- *   - `action` – {string} – The name of action. This name becomes the name of the method on your
- *     resource object.
- *   - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
- *     and `JSON` (also known as JSONP).
- *   - `params` – {object=} – Optional set of pre-bound parameters for this action.
- *   - isArray – {boolean=} – If true then the returned object for this action is an array, see
- *     `returns` section.
- *   - verifyCache – {boolean=} – If true then whenever cache hit occurs, the object is returned and
- *     an async request will be made to the server and the resources as well as the cache will be
- *     updated when the response is received.
- *
- * @returns {Object} A resource "class" object with methods for the default set of resource actions
- *   optionally extended with custom `actions`. The default set contains these actions:
+ * Error handler for {@link angular.service.$xhr $xhr service}. An application can replaces this
+ * service with one specific for the application. The default implementation logs the error to
+ * {@link angular.service.$log $log.error}.
  *
- *       { 'get':    {method:'GET'},
- *         'save':   {method:'POST'},
- *         'query':  {method:'GET', isArray:true},
- *         'remove': {method:'DELETE'},
- *         'delete': {method:'DELETE'} };
+ * @param {Object} request Request object.
  *
- *   Calling these methods invoke an {@link angular.service.$xhr} with the specified http method,
- *   destination and parameters. When the data is returned from the server then the object is an
- *   instance of the resource class `save`, `remove` and `delete` actions are available on it as
- *   methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,
- *   update, delete) on server-side data like this:
- *   <pre>
-        var User = $resource('/user/:userId', {userId:'@id'});
-        var user = User.get({userId:123}, function(){
-          user.abc = true;
-          user.$save();
-        });
-     </pre>
+ *   The object has the following properties
  *
- *   It is important to realize that invoking a $resource object method immediately returns an
- *   empty reference (object or array depending on `isArray`). Once the data is returned from the
- *   server the existing reference is populated with the actual data. This is a useful trick since
- *   usually the resource is assigned to a model which is then rendered by the view. Having an empty
- *   object results in no rendering, once the data arrives from the server then the object is
- *   populated with the data and the view automatically re-renders itself showing the new data. This
- *   means that in most case one never has to write a callback function for the action methods.
+ *   - `method` – `{string}` – The http request method.
+ *   - `url` – `{string}` – The request destination.
+ *   - `data` – `{(string|Object)=} – An optional request body.
+ *   - `callback` – `{function()}` – The callback function
  *
- *   The action methods on the class object or instance object can be invoked with the following
- *   parameters:
+ * @param {Object} response Response object.
  *
- *   - HTTP GET "class" actions: `Resource.action([parameters], [callback])`
- *   - non-GET "class" actions: `Resource.action(postData, [parameters], [callback])`
- *   - non-GET instance actions:  `instance.$action([parameters], [callback])`
+ *   The response object has the following properties:
  *
+ *   - status – {number} – Http status code.
+ *   - body – {string|Object} – Body of the response.
  *
  * @example
- *
- * # Credit card resource
- *
- * <pre>
-     // Define CreditCard class
-     var CreditCard = $resource('/user/:userId/card/:cardId',
-      {userId:123, cardId:'@id'}, {
-       charge: {method:'POST', params:{charge:true}}
-      });
-
-     // We can retrieve a collection from the server
-     var cards = CreditCard.query();
-     // GET: /user/123/card
-     // server returns: [ {id:456, number:'1234', name:'Smith'} ];
-
-     var card = cards[0];
-     // each item is an instance of CreditCard
-     expect(card instanceof CreditCard).toEqual(true);
-     card.name = "J. Smith";
-     // non GET methods are mapped onto the instances
-     card.$save();
-     // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
-     // server returns: {id:456, number:'1234', name: 'J. Smith'};
-
-     // our custom method is mapped as well.
-     card.$charge({amount:9.99});
-     // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
-     // server returns: {id:456, number:'1234', name: 'J. Smith'};
-
-     // we can create an instance as well
-     var newCard = new CreditCard({number:'0123'});
-     newCard.name = "Mike Smith";
-     newCard.$save();
-     // POST: /user/123/card {number:'0123', name:'Mike Smith'}
-     // server returns: {id:789, number:'01234', name: 'Mike Smith'};
-     expect(newCard.id).toEqual(789);
- * </pre>
- *
- * The object returned from this function execution is a resource "class" which has "static" method
- * for each action in the definition.
- *
- * Calling these methods invoke `$xhr` on the `url` template with the given `method` and `params`.
- * When the data is returned from the server then the object is an instance of the resource type and
- * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
- * operations (create, read, update, delete) on server-side data.
-
-   <pre>
-     var User = $resource('/user/:userId', {userId:'@id'});
-     var user = User.get({userId:123}, function(){
-       user.abc = true;
-       user.$save();
-     });
-   </pre>
- *
- *     It's worth noting that the callback for `get`, `query` and other method gets passed in the
- *     response that came from the server, so one could rewrite the above example as:
- *
-   <pre>
-     var User = $resource('/user/:userId', {userId:'@id'});
-     User.get({userId:123}, function(u){
-       u.abc = true;
-       u.$save();
-     });
-   </pre>
-
- * # Buzz client
-
-   Let's look at what a buzz client created with the `$resource` service looks like:
     <doc:example>
       <doc:source>
-       <script>
-         function BuzzController($resource) {
-           this.Activity = $resource(
-             'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
-             {alt:'json', callback:'JSON_CALLBACK'},
-             {get:{method:'JSON', params:{visibility:'@self'}}, replies: {method:'JSON', params:{visibility:'@self', comments:'@comments'}}}
-           );
-         }
-
-         BuzzController.prototype = {
-           fetch: function() {
-             this.activities = this.Activity.get({userId:this.userId});
-           },
-           expandReplies: function(activity) {
-             activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
-           }
-         };
-         BuzzController.$inject = ['$resource'];
-       </script>
-
-       <div ng:controller="BuzzController">
-         <input name="userId" value="googlebuzz"/>
-         <button ng:click="fetch()">fetch</button>
-         <hr/>
-         <div ng:repeat="item in activities.data.items">
-           <h1 style="font-size: 15px;">
-             <img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
-             <a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
-             <a href ng:click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
-           </h1>
-           {{item.object.content | html}}
-           <div ng:repeat="reply in item.replies.data.items" style="margin-left: 20px;">
-             <img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
-             <a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
-           </div>
-         </div>
-       </div>
+        fetch a non-existent file and log an error in the console:
+        <button ng:click="$service('$xhr')('GET', '/DOESNT_EXIST')">fetch</button>
       </doc:source>
-      <doc:scenario>
-      </doc:scenario>
     </doc:example>
  */
-angularServiceInject('$resource', function($xhr){
-  var resource = new ResourceFactory($xhr);
-  return bind(resource, resource.route);
-}, ['$xhr.cache']);
-
+angularServiceInject('$xhr.error', function($log){
+  return function(request, response){
+    $log.error('ERROR: XHR: ' + request.url, request, response);
+  };
+}, ['$log']);
 /**
  * @workInProgress
  * @ngdoc service
- * @name angular.service.$cookies
+ * @name angular.service.$xhr
+ * @function
  * @requires $browser
+ * @requires $xhr.error
+ * @requires $log
  *
  * @description
- * Provides read/write access to browser's cookies.
+ * Generates an XHR request. The $xhr service adds error handling then delegates all requests to
+ * {@link angular.service.$browser $browser.xhr()}.
  *
- * Only a simple Object is exposed and by adding or removing properties to/from
- * this object, new cookies are created/deleted at the end of current $eval.
+ * @param {string} method HTTP method to use. Valid values are: `GET`, `POST`, `PUT`, `DELETE`, and
+ *   `JSON`. `JSON` is a special case which causes a
+ *   [JSONP](http://en.wikipedia.org/wiki/JSON#JSONP) cross domain request using script tag
+ *   insertion.
+ * @param {string} url Relative or absolute URL specifying the destination of the request.  For
+ *   `JSON` requests, `url` should include `JSON_CALLBACK` string to be replaced with a name of an
+ *   angular generated callback function.
+ * @param {(string|Object)=} post Request content as either a string or an object to be stringified
+ *   as JSON before sent to the server.
+ * @param {function(number, (string|Object))} callback A function to be called when the response is
+ *   received. The callback will be called with:
+ *
+ *   - {number} code [HTTP status code](http://en.wikipedia.org/wiki/List_of_HTTP_status_codes) of
+ *     the response. This will currently always be 200, since all non-200 responses are routed to
+ *     {@link angular.service.$xhr.error} service.
+ *   - {string|Object} response Response object as string or an Object if the response was in JSON
+ *     format.
  *
  * @example
- */
-angularServiceInject('$cookies', function($browser) {
-  var rootScope = this,
-      cookies = {},
-      lastCookies = {},
-      lastBrowserCookies;
-
-  //creates a poller fn that copies all cookies from the $browser to service & inits the service
-  $browser.addPollFn(function() {
-    var currentCookies = $browser.cookies();
-    if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl
-      lastBrowserCookies = currentCookies;
-      copy(currentCookies, lastCookies);
-      copy(currentCookies, cookies);
-      rootScope.$eval();
-    }
-  })();
-
-  //at the end of each eval, push cookies
-  //TODO: this should happen before the "delayed" watches fire, because if some cookies are not
-  //      strings or browser refuses to store some cookies, we update the model in the push fn.
-  this.$onEval(PRIORITY_LAST, push);
-
-  return cookies;
-
+   <doc:example>
+     <doc:source>
+       <script>
+         function FetchCntl($xhr) {
+           var self = this;
 
-  /**
-   * Pushes all the cookies from the service to the browser and verifies if all cookies were stored.
-   */
-  function push(){
-    var name,
-        value,
-        browserCookies,
-        updated;
+           this.fetch = function() {
+             self.clear();
+             $xhr(self.method, self.url, function(code, response) {
+               self.code = code;
+               self.response = response;
+             });
+           };
 
-    //delete any cookies deleted in $cookies
-    for (name in lastCookies) {
-      if (isUndefined(cookies[name])) {
-        $browser.cookies(name, _undefined);
-      }
+           this.clear = function() {
+             self.code = null;
+             self.response = null;
+           };
+         }
+         FetchCntl.$inject = ['$xhr'];
+       </script>
+       <div ng:controller="FetchCntl">
+         <select name="method">
+           <option>GET</option>
+           <option>JSON</option>
+         </select>
+         <input type="text" name="url" value="index.html" size="80"/><br/>
+         <button ng:click="fetch()">fetch</button>
+         <button ng:click="clear()">clear</button>
+         <a href="" ng:click="method='GET'; url='index.html'">sample</a>
+         <a href="" ng:click="method='JSON'; url='https://www.googleapis.com/buzz/v1/activities/googlebuzz/@self?alt=json&callback=JSON_CALLBACK'">buzz</a>
+         <pre>code={{code}}</pre>
+         <pre>response={{response}}</pre>
+       </div>
+     </doc:source>
+   </doc:example>
+ */
+angularServiceInject('$xhr', function($browser, $error, $log){
+  var self = this;
+  return function(method, url, post, callback){
+    if (isFunction(post)) {
+      callback = post;
+      post = _null;
     }
-
-    //update all cookies updated in $cookies
-    for(name in cookies) {
-      value = cookies[name];
-      if (!isString(value)) {
-        if (isDefined(lastCookies[name])) {
-          cookies[name] = lastCookies[name];
-        } else {
-          delete cookies[name];
-        }
-      } else if (value !== lastCookies[name]) {
-        $browser.cookies(name, value);
-        updated = true;
-      }
+    if (post && isObject(post)) {
+      post = toJson(post);
     }
-
-    //verify what was actually stored
-    if (updated){
-      updated = false;
-      browserCookies = $browser.cookies();
-
-      for (name in cookies) {
-        if (cookies[name] !== browserCookies[name]) {
-          //delete or reset all cookies that the browser dropped from $cookies
-          if (isUndefined(browserCookies[name])) {
-            delete cookies[name];
-          } else {
-            cookies[name] = browserCookies[name];
+    $browser.xhr(method, url, post, function(code, response){
+      try {
+        if (isString(response)) {
+          if (response.match(/^\)\]\}',\n/)) response=response.substr(6);
+          if (/^\s*[\[\{]/.exec(response) && /[\}\]]\s*$/.exec(response)) {
+            response = fromJson(response, true);
           }
-          updated = true;
         }
+        if (code == 200) {
+          callback(code, response);
+        } else {
+          $error(
+            {method: method, url:url, data:post, callback:callback},
+            {status: code, body:response});
+        }
+      } catch (e) {
+        $log.error(e);
+      } finally {
+        self.$eval();
       }
-    }
-  }
-}, ['$browser']);
-
-/**
- * @workInProgress
- * @ngdoc service
- * @name angular.service.$cookieStore
- * @requires $cookies
- *
- * @description
- * Provides a key-value (string-object) storage, that is backed by session cookies.
- * Objects put or retrieved from this storage are automatically serialized or
- * deserialized by angular's toJson/fromJson.
- * @example
- */
-angularServiceInject('$cookieStore', function($store) {
-
-  return {
-    /**
-     * @workInProgress
-     * @ngdoc method
-     * @name angular.service.$cookieStore#get
-     * @methodOf angular.service.$cookieStore
-     *
-     * @description
-     * Returns the value of given cookie key
-     *
-     * @param {string} key Id to use for lookup.
-     * @returns {Object} Deserialized cookie value.
-     */
-    get: function(key) {
-      return fromJson($store[key]);
-    },
-
-    /**
-     * @workInProgress
-     * @ngdoc method
-     * @name angular.service.$cookieStore#put
-     * @methodOf angular.service.$cookieStore
-     *
-     * @description
-     * Sets a value for given cookie key
-     *
-     * @param {string} key Id for the `value`.
-     * @param {Object} value Value to be stored.
-     */
-    put: function(key, value) {
-      $store[key] = toJson(value);
-    },
-
-    /**
-     * @workInProgress
-     * @ngdoc method
-     * @name angular.service.$cookieStore#remove
-     * @methodOf angular.service.$cookieStore
-     *
-     * @description
-     * Remove given cookie
-     *
-     * @param {string} key Id of the key-value pair to delete.
-     */
-    remove: function(key) {
-      delete $store[key];
-    }
+    });
   };
-
-}, ['$cookies']);
+}, ['$browser', '$xhr.error', '$log']);
 /**
  * @workInProgress
  * @ngdoc directive
@@ -13785,7 +14027,7 @@ angularServiceInject('$cookieStore', function($store) {
  *  before the template enters execution mode during bootstrap.
  *
  * @element ANY
- * @param {expression} expression to eval.
+ * @param {expression} expression {@link guide.expression Expression} to eval.
  *
  * @example
    <doc:example>
@@ -13820,7 +14062,7 @@ angularDirective("ng:init", function(expression){
  * The `ng:controller` directive specifies the MVC controller class
  *
  * @element ANY
- * @param {expression} expression to eval.
+ * @param {expression} expression {@link guide.expression Expression} to eval.
  *
  * @example
  * Here is a simple form for editing the user contact information. Adding, removing clearing and
@@ -13907,7 +14149,7 @@ angularDirective("ng:controller", function(expression){
  * without displaying the result to the user.
  *
  * @element ANY
- * @param {expression} expression to eval.
+ * @param {expression} expression {@link guide.expression Expression} to eval.
  *
  * @example
  * Notice that `{{` `obj.multiplied = obj.a * obj.b` `}}` has a side effect of assigning
@@ -13955,7 +14197,7 @@ angularDirective("ng:eval", function(expression){
  * `<span ng:bind="expression"></span>` at bootstrap time.
  *
  * @element ANY
- * @param {expression} expression to eval.
+ * @param {expression} expression {@link guide.expression Expression} to eval.
  *
  * @example
  * Try it here: enter text in text box and watch the greeting change.
@@ -14020,15 +14262,17 @@ function compileBindTemplate(template){
     var bindings = [];
     forEach(parseBindings(template), function(text){
       var exp = binding(text);
-      bindings.push(exp ? function(element){
-        var error, value = this.$tryEval(exp, function(e){
-          error = toJson(e);
-        });
-        elementError(element, NG_EXCEPTION, error);
-        return error ? error : value;
-      } : function() {
-        return text;
-      });
+      bindings.push(exp
+        ? function(element){
+            var error, value = this.$tryEval(exp, function(e){
+              error = toJson(e);
+            });
+            elementError(element, NG_EXCEPTION, error);
+            return error ? error : value;
+          }
+        : function() {
+            return text;
+          });
     });
     bindTemplateCache[template] = fn = function(element, prettyPrintJson){
       var parts = [], self = this,
@@ -14112,15 +14356,15 @@ var REMOVE_ATTRIBUTES = {
  * @name angular.directive.ng:bind-attr
  *
  * @description
- * The `ng:bind-attr` attribute specifies that the element attributes
- * which should be replaced by the expression in it. Unlike `ng:bind`
- * the `ng:bind-attr` contains a JSON key value pairs representing
- * which attributes need to be changed. You don’t usually write the
- * `ng:bind-attr` in the HTML since embedding
- * <tt ng:non-bindable>{{expression}}</tt> into the
- * attribute directly is the preferred way. The attributes get
- * translated into `<span ng:bind-attr="{attr:expression}"/>` at
- * bootstrap time.
+ * The `ng:bind-attr` attribute specifies that {@link guide.data-binding databindings}  should be
+ * created between element attributes and given expressions. Unlike `ng:bind` the `ng:bind-attr`
+ * contains a JSON key value pairs representing which attributes need to be mapped to which
+ * {@link guide.expression expressions}.
+ *
+ * You don’t usually write the `ng:bind-attr` in the HTML since embedding
+ * <tt ng:non-bindable>{{expression}}</tt> into the attribute directly as the attribute value is
+ * preferred. The attributes get translated into `<span ng:bind-attr="{attr:expression}"/>` at
+ * compile time.
  *
  * This HTML snippet is preferred way of working with `ng:bind-attr`
  * <pre>
@@ -14202,7 +14446,7 @@ angularDirective("ng:bind-attr", function(expression){
  * element is clicked.
  *
  * @element ANY
- * @param {expression} expression to eval upon click.
+ * @param {expression} expression {@link guide.expression Expression} to eval upon click.
  *
  * @example
    <doc:example>
@@ -14253,7 +14497,7 @@ angularDirective("ng:click", function(expression, element){
  * server and reloading the current page).
  *
  * @element form
- * @param {expression} expression to eval.
+ * @param {expression} expression {@link guide.expression Expression} to eval.
  *
  * @example
    <doc:example>
@@ -14291,51 +14535,6 @@ angularDirective("ng:submit", function(expression, element) {
 });
 
 
-/**
- * @workInProgress
- * @ngdoc directive
- * @name angular.directive.ng:watch
- *
- * @description
- * The `ng:watch` allows you watch a variable and then execute
- * an evaluation on variable change.
- *
- * @element ANY
- * @param {expression} expression to eval.
- *
- * @example
- * Notice that the counter is incremented
- * every time you change the text.
-   <doc:example>
-     <doc:source>
-      <div ng:init="counter=0" ng:watch="name: counter = counter+1">
-        <input type="text" name="name" value="hello"><br/>
-        Change counter: {{counter}} Name: {{name}}
-      </div>
-     </doc:source>
-     <doc:scenario>
-       it('should check ng:watch', function(){
-         expect(using('.doc-example-live').binding('counter')).toBe('2');
-         using('.doc-example-live').input('name').enter('abc');
-         expect(using('.doc-example-live').binding('counter')).toBe('3');
-       });
-     </doc:scenario>
-   </doc:example>
- */
-//TODO: delete me, since having watch in UI is logic in UI. (leftover form getangular)
-angularDirective("ng:watch", function(expression, element){
-  return function(element){
-    var self = this;
-    parser(expression).watch()({
-      addListener:function(watch, exp){
-        self.$watch(watch, function(){
-          return exp(self);
-        }, element);
-      }
-    });
-  };
-});
-
 function ngClass(selector) {
   return function(expression, element){
     var existing = element[0].className + ' ';
@@ -14361,7 +14560,7 @@ function ngClass(selector) {
  * conditionally.
  *
  * @element ANY
- * @param {expression} expression to eval.
+ * @param {expression} expression {@link guide.expression Expression} to eval.
  *
  * @example
    <doc:example>
@@ -14402,7 +14601,7 @@ angularDirective("ng:class", ngClass(function(){return true;}));
  * and takes affect only on odd (even) rows.
  *
  * @element ANY
- * @param {expression} expression to eval. Must be inside
+ * @param {expression} expression {@link guide.expression Expression} to eval. Must be inside
  * `ng:repeat`.
  *
  * @example
@@ -14440,7 +14639,7 @@ angularDirective("ng:class-odd", ngClass(function(i){return i % 2 === 0;}));
  * and takes affect only on odd (even) rows.
  *
  * @element ANY
- * @param {expression} expression to eval. Must be inside
+ * @param {expression} expression {@link guide.expression Expression} to eval. Must be inside
  * `ng:repeat`.
  *
  * @example
@@ -14477,8 +14676,8 @@ angularDirective("ng:class-even", ngClass(function(i){return i % 2 === 1;}));
  * of the HTML conditionally.
  *
  * @element ANY
- * @param {expression} expression if truthy then the element is
- * shown or hidden respectively.
+ * @param {expression} expression If the {@link guide.expression expression} is truthy then the element
+ *     is shown or hidden respectively.
  *
  * @example
    <doc:example>
@@ -14518,8 +14717,8 @@ angularDirective("ng:show", function(expression, element){
  * of the HTML conditionally.
  *
  * @element ANY
- * @param {expression} expression if truthy then the element is
- * shown or hidden respectively.
+ * @param {expression} expression If the {@link guide.expression expression} truthy then the element
+ *     is shown or hidden respectively.
  *
  * @example
    <doc:example>
@@ -14558,9 +14757,8 @@ angularDirective("ng:hide", function(expression, element){
  * The ng:style allows you to set CSS style on an HTML element conditionally.
  *
  * @element ANY
- * @param {expression} expression which evals to an object whes key's are
- *        CSS style names and values are coresponding values for those
- *        CSS keys.
+ * @param {expression} expression {@link guide.expression Expression} which evals to an object whose
+ *      keys are CSS style names and values are corresponding values for those CSS keys.
  *
  * @example
    <doc:example>
@@ -14639,10 +14837,10 @@ angularTextMarkup('{{}}', function(text, textNode, parentElement) {
       forEach(parseBindings(text), function(text){
         var exp = binding(text);
         if (exp) {
-          newElement = self.element('span');
+          newElement = jqLite('<span>');
           newElement.attr('ng:bind', exp);
         } else {
-          newElement = self.text(text);
+          newElement = jqLite(document.createTextNode(text));
         }
         if (msie && text.charAt(0) == ' ') {
           newElement = jqLite('<span>&nbsp;</span>');
@@ -15089,9 +15287,9 @@ function valueAccessor(scope, element) {
       invalidWidgets.markValid(element);
     } else {
       var error, validateScope = inherit(scope, {$element:element});
-      error = required && !value ?
-              'Required' :
-              (value ? validator(validateScope, value) : _null);
+      error = required && !value
+              ? 'Required'
+              (value ? validator(validateScope, value) : _null);
       elementError(element, NG_VALIDATION_ERROR, error);
       lastError = error;
       if (error) {
@@ -15313,7 +15511,7 @@ angularWidget('option', function(){
   return function(option) {
     var select = option.parent();
     var isMultiple = select[0].type == 'select-multiple';
-    var scope = retrieveScope(select);
+    var scope = select.scope();
     var model = modelAccessor(scope, select);
 
     //if parent select doesn't have a name, don't bother doing anything any more
@@ -15377,15 +15575,15 @@ angularWidget('option', function(){
       </doc:source>
       <doc:scenario>
         it('should load date filter', function(){
-         expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.date/);
+         expect(element('.doc-example-live ng\\:include').text()).toMatch(/angular\.filter\.date/);
         });
         it('should change to hmtl filter', function(){
          select('url').option('angular.filter.html.html');
-         expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.html/);
+         expect(element('.doc-example-live ng\\:include').text()).toMatch(/angular\.filter\.html/);
         });
         it('should change to blank', function(){
-         select('url').option('(blank)');
-         expect(element('.doc-example ng\\:include').text()).toEqual('');
+         select('url').option('');
+         expect(element('.doc-example-live ng\\:include').text()).toEqual('');
         });
       </doc:scenario>
     </doc:example>
@@ -15428,8 +15626,7 @@ angularWidget('ng:include', function(element){
           xhr('GET', src, function(code, response){
             element.html(response);
             childScope = useScope || createScope(scope);
-            compiler.compile(element)(element, childScope);
-            childScope.$init();
+            compiler.compile(element)(childScope);
             scope.$eval(onloadExp);
           });
         } else {
@@ -15482,19 +15679,20 @@ angularWidget('ng:include', function(element){
       </doc:source>
       <doc:scenario>
         it('should start in settings', function(){
-         expect(element('.doc-example ng\\:switch').text()).toEqual('Settings Div');
+         expect(element('.doc-example-live ng\\:switch').text()).toEqual('Settings Div');
         });
         it('should change to home', function(){
          select('switch').option('home');
-         expect(element('.doc-example ng\\:switch').text()).toEqual('Home Span');
+         expect(element('.doc-example-live ng\\:switch').text()).toEqual('Home Span');
         });
         it('should select deafault', function(){
          select('switch').option('other');
-         expect(element('.doc-example ng\\:switch').text()).toEqual('default');
+         expect(element('.doc-example-live ng\\:switch').text()).toEqual('default');
         });
       </doc:scenario>
     </doc:example>
  */
+//TODO(im): remove all the code related to using and inline equals
 var ngSwitch = angularWidget('ng:switch', function (element){
   var compiler = this,
       watchExpr = element.attr("on"),
@@ -15542,11 +15740,10 @@ var ngSwitch = angularWidget('ng:switch', function (element){
       forEach(cases, function(switchCase){
         if (!found && switchCase.when(childScope, value)) {
           found = true;
-          var caseElement = quickClone(switchCase.element);
-          element.append(caseElement);
           childScope.$tryEval(switchCase.change, element);
-          switchCase.template(caseElement, childScope);
-          childScope.$init();
+          switchCase.template(childScope, function(caseElement){
+            element.append(caseElement);
+          });
         }
       });
     });
@@ -15557,8 +15754,7 @@ var ngSwitch = angularWidget('ng:switch', function (element){
 }, {
   equals: function(on, when) {
     return ''+on == when;
-  },
-  route: switchRouteMatcher
+  }
 });
 
 
@@ -15640,11 +15836,11 @@ angularWidget('a', function() {
       </doc:scenario>
     </doc:example>
  */
-angularWidget("@ng:repeat", function(expression, element){
+angularWidget('@ng:repeat', function(expression, element){
   element.removeAttr('ng:repeat');
-  element.replaceWith(this.comment("ng:repeat: " + expression));
-  var template = this.compile(element);
-  return function(reference){
+  element.replaceWith(jqLite('<!-- ng:repeat: ' + expression + ' --!>'));
+  var linker = this.compile(element);
+  return function(iterStartElement){
     var match = expression.match(/^\s*(.+)\s+in\s+(.*)\s*$/),
         lhs, rhs, valueIdent, keyIdent;
     if (! match) {
@@ -15665,8 +15861,8 @@ angularWidget("@ng:repeat", function(expression, element){
     this.$onEval(function(){
       var index = 0,
           childCount = children.length,
-          lastElement = reference,
-          collection = this.$tryEval(rhs, reference),
+          lastIterElement = iterStartElement,
+          collection = this.$tryEval(rhs, iterStartElement),
           is_array = isArray(collection),
           collectionLength = 0,
           childScope,
@@ -15681,28 +15877,30 @@ angularWidget("@ng:repeat", function(expression, element){
       }
 
       for (key in collection) {
-        if (!is_array || collection.hasOwnProperty(key)) {
+        if (collection.hasOwnProperty(key)) {
           if (index < childCount) {
             // reuse existing child
             childScope = children[index];
             childScope[valueIdent] = collection[key];
             if (keyIdent) childScope[keyIdent] = key;
+            lastIterElement = childScope.$element;
           } else {
             // grow children
-            childScope = template(quickClone(element), createScope(currentScope));
+            childScope = createScope(currentScope);
             childScope[valueIdent] = collection[key];
             if (keyIdent) childScope[keyIdent] = key;
-            lastElement.after(childScope.$element);
             childScope.$index = index;
-            childScope.$position = index == 0 ?
-                                      'first' :
-                                      (index == collectionLength - 1 ? 'last' : 'middle');
-            childScope.$element.attr('ng:repeat-index', index);
-            childScope.$init();
+            childScope.$position = index == 0
+                ? 'first'
+                : (index == collectionLength - 1 ? 'last' : 'middle');
             children.push(childScope);
+            linker(childScope, function(clone){
+              clone.attr('ng:repeat-index', index);
+              lastIterElement.after(clone);
+              lastIterElement = clone;
+            });
           }
           childScope.$eval();
-          lastElement = childScope.$element;
           index ++;
         }
       }
@@ -15710,7 +15908,7 @@ angularWidget("@ng:repeat", function(expression, element){
       while(children.length > index) {
         children.pop().$element.remove();
       }
-    }, reference);
+    }, iterStartElement);
   };
 });
 
@@ -15820,8 +16018,7 @@ angularWidget('ng:view', function(element) {
         if (src) {
           $xhr('GET', src, function(code, response){
             element.html(response);
-            compiler.compile(element)(element, childScope);
-            childScope.$init();
+            compiler.compile(element)(childScope);
           });
         } else {
           element.html('');
@@ -15890,6 +16087,11 @@ extend(angular, {
   'isArray': isArray
 });
 
+//try to bind to jquery now so that one can write angular.element().read()
+//but we will rebind on bootstrap again.
+bindJQuery();
+
+
 
 /**
  * Setup file for the Scenario.
@@ -16148,6 +16350,12 @@ function browserTrigger(element, type) {
         element.checked = !element.checked;
         break;
     }
+    // WTF!!! Error: Unspecified error.
+    // Don't know why, but some elements when detached seem to be in inconsistent state and
+    // calling .fireEvent() on them will result in very unhelpful error (Error: Unspecified error)
+    // forcing the browser to compute the element position (by reading its CSS)
+    // puts the element in consistent state.
+    element.style.posLeft;
     element.fireEvent('on' + type);
     if (lowercase(element.type) == 'submit') {
       while(element) {
@@ -16195,9 +16403,9 @@ function browserTrigger(element, type) {
  */
 _jQuery.fn.bindings = function(name) {
   function contains(text, value) {
-    return value instanceof RegExp ?
-      value.test(text) :
-      text && text.indexOf(value) >= 0;
+    return value instanceof RegExp
+      ? value.test(text)
+      text && text.indexOf(value) >= 0;
   }
   var result = [];
   this.find('.ng-binding:visible').each(function() {
@@ -17843,7 +18051,7 @@ angular.scenario.output('object', function(context, runner) {
 });
   var $scenario = new angular.scenario.Runner(window);
 
-  jqLite(document).ready(function() {
+  jqLiteWrap(document).ready(function() {
     angularScenarioInit($scenario, angularJsConfig(document));
   });