Bug 1439855 - Tests for multipart tokenizer;r?arai draft
authorDavid Teller <dteller@mozilla.com>
Thu, 12 Apr 2018 15:13:22 +0200
changeset 784322 08e167ebfe0c023ef53bdf9ca3b9abdacca0cbce
parent 784298 4af4ae0aee552a99a995ce4b32198b98294a95f7
child 784323 f3dc352bc86ac6a5039ac8c888e29bfb46d73209
push id106893
push userdteller@mozilla.com
push dateWed, 18 Apr 2018 11:19:13 +0000
reviewersarai
bugs1439855
milestone61.0a1
Bug 1439855 - Tests for multipart tokenizer;r?arai MozReview-Commit-ID: 7V2BWAcpA1D
js/src/jsapi-tests/binast/parser/tester/frameworks/angular-1.2.binjs
js/src/jsapi-tests/binast/parser/tester/frameworks/angular-1.2.js
js/src/jsapi-tests/binast/parser/tester/frameworks/backbone-1.1.binjs
js/src/jsapi-tests/binast/parser/tester/frameworks/backbone-1.1.js
js/src/jsapi-tests/binast/parser/tester/frameworks/benchmark.binjs
js/src/jsapi-tests/binast/parser/tester/frameworks/benchmark.js
js/src/jsapi-tests/binast/parser/tester/frameworks/jquery-1.9.binjs
js/src/jsapi-tests/binast/parser/tester/frameworks/jquery-1.9.js
js/src/jsapi-tests/binast/parser/tester/frameworks/jquery.mobile-1.4.binjs
js/src/jsapi-tests/binast/parser/tester/frameworks/jquery.mobile-1.4.js
js/src/jsapi-tests/binast/parser/tester/frameworks/mootools-1.4.binjs
js/src/jsapi-tests/binast/parser/tester/frameworks/mootools-1.4.js
js/src/jsapi-tests/binast/parser/tester/frameworks/underscore-1.5.binjs
js/src/jsapi-tests/binast/parser/tester/frameworks/underscore-1.5.js
js/src/jsapi-tests/binast/parser/tester/frameworks/yui-3.12.binjs
js/src/jsapi-tests/binast/parser/tester/frameworks/yui-3.12.js
js/src/jsapi-tests/testBinASTReader.cpp
js/src/jsapi-tests/testBinTokenReaderTester.cpp
deleted file mode 100644
index 575fe6b7a6599f26fb3f5705dda41afa18b2ceea..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/js/src/jsapi-tests/binast/parser/tester/frameworks/angular-1.2.js
+++ /dev/null
@@ -1,20369 +0,0 @@
-/**
- * @license AngularJS v1.2.5
- * (c) 2010-2014 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, document, undefined) {'use strict';
-
-/**
- * @description
- *
- * This object provides a utility for producing rich Error messages within
- * Angular. It can be called as follows:
- *
- * var exampleMinErr = minErr('example');
- * throw exampleMinErr('one', 'This {0} is {1}', foo, bar);
- *
- * The above creates an instance of minErr in the example namespace. The
- * resulting error will have a namespaced error code of example.one.  The
- * resulting error will replace {0} with the value of foo, and {1} with the
- * value of bar. The object is not restricted in the number of arguments it can
- * take.
- *
- * If fewer arguments are specified than necessary for interpolation, the extra
- * interpolation markers will be preserved in the final string.
- *
- * Since data will be parsed statically during a build step, some restrictions
- * are applied with respect to how minErr instances are created and called.
- * Instances should have names of the form namespaceMinErr for a minErr created
- * using minErr('namespace') . Error codes, namespaces and template strings
- * should all be static strings, not variables or general expressions.
- *
- * @param {string} module The namespace to use for the new minErr instance.
- * @returns {function(string, string, ...): Error} instance
- */
-
-function minErr(module) {
-  return function () {
-    var code = arguments[0],
-      prefix = '[' + (module ? module + ':' : '') + code + '] ',
-      template = arguments[1],
-      templateArgs = arguments,
-      stringify = function (obj) {
-        if (typeof obj === 'function') {
-          return obj.toString().replace(/ \{[\s\S]*$/, '');
-        } else if (typeof obj === 'undefined') {
-          return 'undefined';
-        } else if (typeof obj !== 'string') {
-          return JSON.stringify(obj);
-        }
-        return obj;
-      },
-      message, i;
-
-    message = prefix + template.replace(/\{\d+\}/g, function (match) {
-      var index = +match.slice(1, -1), arg;
-
-      if (index + 2 < templateArgs.length) {
-        arg = templateArgs[index + 2];
-        if (typeof arg === 'function') {
-          return arg.toString().replace(/ ?\{[\s\S]*$/, '');
-        } else if (typeof arg === 'undefined') {
-          return 'undefined';
-        } else if (typeof arg !== 'string') {
-          return toJson(arg);
-        }
-        return arg;
-      }
-      return match;
-    });
-
-    message = message + '\nhttp://errors.angularjs.org/1.2.5/' +
-      (module ? module + '/' : '') + code;
-    for (i = 2; i < arguments.length; i++) {
-      message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
-        encodeURIComponent(stringify(arguments[i]));
-    }
-
-    return new Error(message);
-  };
-}
-
-/* We need to tell jshint what variables are being exported */
-/* global
-    -angular,
-    -msie,
-    -jqLite,
-    -jQuery,
-    -slice,
-    -push,
-    -toString,
-    -ngMinErr,
-    -_angular,
-    -angularModule,
-    -nodeName_,
-    -uid,
-
-    -lowercase,
-    -uppercase,
-    -manualLowercase,
-    -manualUppercase,
-    -nodeName_,
-    -isArrayLike,
-    -forEach,
-    -sortedKeys,
-    -forEachSorted,
-    -reverseParams,
-    -nextUid,
-    -setHashKey,
-    -extend,
-    -int,
-    -inherit,
-    -noop,
-    -identity,
-    -valueFn,
-    -isUndefined,
-    -isDefined,
-    -isObject,
-    -isString,
-    -isNumber,
-    -isDate,
-    -isArray,
-    -isFunction,
-    -isRegExp,
-    -isWindow,
-    -isScope,
-    -isFile,
-    -isBoolean,
-    -trim,
-    -isElement,
-    -makeMap,
-    -map,
-    -size,
-    -includes,
-    -indexOf,
-    -arrayRemove,
-    -isLeafNode,
-    -copy,
-    -shallowCopy,
-    -equals,
-    -csp,
-    -concat,
-    -sliceArgs,
-    -bind,
-    -toJsonReplacer,
-    -toJson,
-    -fromJson,
-    -toBoolean,
-    -startingTag,
-    -tryDecodeURIComponent,
-    -parseKeyValue,
-    -toKeyValue,
-    -encodeUriSegment,
-    -encodeUriQuery,
-    -angularInit,
-    -bootstrap,
-    -snake_case,
-    -bindJQuery,
-    -assertArg,
-    -assertArgFn,
-    -assertNotHasOwnProperty,
-    -getter,
-    -getBlockElements,
-
-*/
-
-////////////////////////////////////
-
-/**
- * @ngdoc function
- * @name angular.lowercase
- * @function
- *
- * @description Converts the specified string to lowercase.
- * @param {string} string String to be converted to lowercase.
- * @returns {string} Lowercased string.
- */
-var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;};
-
-
-/**
- * @ngdoc function
- * @name angular.uppercase
- * @function
- *
- * @description Converts the specified string to uppercase.
- * @param {string} string String to be converted to uppercase.
- * @returns {string} Uppercased string.
- */
-var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;};
-
-
-var manualLowercase = function(s) {
-  /* jshint bitwise: false */
-  return isString(s)
-      ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);})
-      : s;
-};
-var manualUppercase = function(s) {
-  /* jshint bitwise: false */
-  return isString(s)
-      ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);})
-      : s;
-};
-
-
-// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish
-// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods
-// with correct but slower alternatives.
-if ('i' !== 'I'.toLowerCase()) {
-  lowercase = manualLowercase;
-  uppercase = manualUppercase;
-}
-
-
-var /** holds major version number for IE or NaN for real browsers */
-    msie,
-    jqLite,           // delay binding since jQuery could be loaded after us.
-    jQuery,           // delay binding
-    slice             = [].slice,
-    push              = [].push,
-    toString          = Object.prototype.toString,
-    ngMinErr          = minErr('ng'),
-
-
-    _angular          = window.angular,
-    /** @name angular */
-    angular           = window.angular || (window.angular = {}),
-    angularModule,
-    nodeName_,
-    uid               = ['0', '0', '0'];
-
-/**
- * IE 11 changed the format of the UserAgent string.
- * See http://msdn.microsoft.com/en-us/library/ms537503.aspx
- */
-msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
-if (isNaN(msie)) {
-  msie = int((/trident\/.*; rv:(\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]);
-}
-
-
-/**
- * @private
- * @param {*} obj
- * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
- *                   String ...)
- */
-function isArrayLike(obj) {
-  if (obj == null || isWindow(obj)) {
-    return false;
-  }
-
-  var length = obj.length;
-
-  if (obj.nodeType === 1 && length) {
-    return true;
-  }
-
-  return isString(obj) || isArray(obj) || length === 0 ||
-         typeof length === 'number' && length > 0 && (length - 1) in obj;
-}
-
-/**
- * @ngdoc function
- * @name angular.forEach
- * @function
- *
- * @description
- * Invokes the `iterator` function once for each item in `obj` collection, which can be either an
- * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value`
- * is the value of an object property or an array element and `key` is the object property key or
- * array element index. Specifying a `context` for the function is optional.
- *
- * Note: this function was previously known as `angular.foreach`.
- *
-   <pre>
-     var values = {name: 'misko', gender: 'male'};
-     var log = [];
-     angular.forEach(values, function(value, key){
-       this.push(key + ': ' + value);
-     }, log);
-     expect(log).toEqual(['name: misko', 'gender:male']);
-   </pre>
- *
- * @param {Object|Array} obj Object to iterate over.
- * @param {Function} iterator Iterator function.
- * @param {Object=} context Object to become context (`this`) for the iterator function.
- * @returns {Object|Array} Reference to `obj`.
- */
-function forEach(obj, iterator, context) {
-  var key;
-  if (obj) {
-    if (isFunction(obj)){
-      for (key in obj) {
-        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
-          iterator.call(context, obj[key], key);
-        }
-      }
-    } else if (obj.forEach && obj.forEach !== forEach) {
-      obj.forEach(iterator, context);
-    } else if (isArrayLike(obj)) {
-      for (key = 0; key < obj.length; key++)
-        iterator.call(context, obj[key], key);
-    } else {
-      for (key in obj) {
-        if (obj.hasOwnProperty(key)) {
-          iterator.call(context, obj[key], key);
-        }
-      }
-    }
-  }
-  return obj;
-}
-
-function sortedKeys(obj) {
-  var keys = [];
-  for (var key_1 in obj) {
-    if (obj.hasOwnProperty(key_1)) {
-      keys.push(key_1);
-    }
-  }
-  return keys.sort();
-}
-
-function forEachSorted(obj, iterator, context) {
-  var keys = sortedKeys(obj);
-  for ( var i = 0; i < keys.length; i++) {
-    iterator.call(context, obj[keys[i]], keys[i]);
-  }
-  return keys;
-}
-
-
-/**
- * when using forEach the params are value, key, but it is often useful to have key, value.
- * @param {function(string, *)} iteratorFn
- * @returns {function(*, string)}
- */
-function reverseParams(iteratorFn) {
-  return function(value, key) { iteratorFn(key, value); };
-}
-
-/**
- * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
- * characters such as '012ABC'. The reason why we are not using simply a number counter is that
- * the number string gets longer over time, and it can also overflow, where as the nextId
- * will grow much slower, it is a string, and it will never overflow.
- *
- * @returns an unique alpha-numeric string
- */
-function nextUid() {
-  var index = uid.length;
-  var digit;
-
-  while(index) {
-    index--;
-    digit = uid[index].charCodeAt(0);
-    if (digit == 57 /*'9'*/) {
-      uid[index] = 'A';
-      return uid.join('');
-    }
-    if (digit == 90  /*'Z'*/) {
-      uid[index] = '0';
-    } else {
-      uid[index] = String.fromCharCode(digit + 1);
-      return uid.join('');
-    }
-  }
-  uid.unshift('0');
-  return uid.join('');
-}
-
-
-/**
- * Set or clear the hashkey for an object.
- * @param obj object
- * @param h the hashkey (!truthy to delete the hashkey)
- */
-function setHashKey(obj, h) {
-  if (h) {
-    obj.$$hashKey = h;
-  }
-  else {
-    delete obj.$$hashKey;
-  }
-}
-
-/**
- * @ngdoc function
- * @name angular.extend
- * @function
- *
- * @description
- * 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 Destination object.
- * @param {...Object} src Source object(s).
- * @returns {Object} Reference to `dst`.
- */
-function extend(dst) {
-  var h = dst.$$hashKey;
-  forEach(arguments, function(obj){
-    if (obj !== dst) {
-      forEach(obj, function(value, key){
-        dst[key] = value;
-      });
-    }
-  });
-
-  setHashKey(dst,h);
-  return dst;
-}
-
-function int(str) {
-  return parseInt(str, 10);
-}
-
-
-function inherit(parent, extra) {
-  return extend(new (extend(function() {}, {prototype:parent}))(), extra);
-}
-
-/**
- * @ngdoc function
- * @name angular.noop
- * @function
- *
- * @description
- * A function that performs no operations. This function can be useful when writing code in the
- * functional style.
-   <pre>
-     function foo(callback) {
-       var result = calculateResult();
-       (callback || angular.noop)(result);
-     }
-   </pre>
- */
-function noop() {}
-noop.$inject = [];
-
-
-/**
- * @ngdoc function
- * @name angular.identity
- * @function
- *
- * @description
- * A function that returns its first argument. This function is useful when writing code in the
- * functional style.
- *
-   <pre>
-     function transformer(transformationFn, value) {
-       return (transformationFn || angular.identity)(value);
-     };
-   </pre>
- */
-function identity($) {return $;}
-identity.$inject = [];
-
-
-function valueFn(value) {return function() {return value;};}
-
-/**
- * @ngdoc function
- * @name angular.isUndefined
- * @function
- *
- * @description
- * Determines if a reference is undefined.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is undefined.
- */
-function isUndefined(value){return typeof value === 'undefined';}
-
-
-/**
- * @ngdoc function
- * @name angular.isDefined
- * @function
- *
- * @description
- * Determines if a reference is defined.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is defined.
- */
-function isDefined(value){return typeof value !== 'undefined';}
-
-
-/**
- * @ngdoc function
- * @name angular.isObject
- * @function
- *
- * @description
- * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not
- * considered to be objects.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is an `Object` but not `null`.
- */
-function isObject(value){return value != null && typeof value === 'object';}
-
-
-/**
- * @ngdoc function
- * @name angular.isString
- * @function
- *
- * @description
- * Determines if a reference is a `String`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `String`.
- */
-function isString(value){return typeof value === 'string';}
-
-
-/**
- * @ngdoc function
- * @name angular.isNumber
- * @function
- *
- * @description
- * Determines if a reference is a `Number`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Number`.
- */
-function isNumber(value){return typeof value === 'number';}
-
-
-/**
- * @ngdoc function
- * @name angular.isDate
- * @function
- *
- * @description
- * Determines if a value is a date.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Date`.
- */
-function isDate(value){
-  return toString.call(value) === '[object Date]';
-}
-
-
-/**
- * @ngdoc function
- * @name angular.isArray
- * @function
- *
- * @description
- * Determines if a reference is an `Array`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is an `Array`.
- */
-function isArray(value) {
-  return toString.call(value) === '[object Array]';
-}
-
-
-/**
- * @ngdoc function
- * @name angular.isFunction
- * @function
- *
- * @description
- * Determines if a reference is a `Function`.
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `Function`.
- */
-function isFunction(value){return typeof value === 'function';}
-
-
-/**
- * Determines if a value is a regular expression object.
- *
- * @private
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a `RegExp`.
- */
-function isRegExp(value) {
-  return toString.call(value) === '[object RegExp]';
-}
-
-
-/**
- * Checks if `obj` is a window object.
- *
- * @private
- * @param {*} obj Object to check
- * @returns {boolean} True if `obj` is a window obj.
- */
-function isWindow(obj) {
-  return obj && obj.document && obj.location && obj.alert && obj.setInterval;
-}
-
-
-function isScope(obj) {
-  return obj && obj.$evalAsync && obj.$watch;
-}
-
-
-function isFile(obj) {
-  return toString.call(obj) === '[object File]';
-}
-
-
-function isBoolean(value) {
-  return typeof value === 'boolean';
-}
-
-
-var trim = (function() {
-  // native trim is way faster: http://jsperf.com/angular-trim-test
-  // but IE doesn't have it... :-(
-  // TODO: we should move this into IE/ES5 polyfill
-  if (!String.prototype.trim) {
-    return function(value) {
-      return isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value;
-    };
-  }
-  return function(value) {
-    return isString(value) ? value.trim() : value;
-  };
-})();
-
-
-/**
- * @ngdoc function
- * @name angular.isElement
- * @function
- *
- * @description
- * Determines if a reference is a DOM element (or wrapped jQuery element).
- *
- * @param {*} value Reference to check.
- * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
- */
-function isElement(node) {
-  return !!(node &&
-    (node.nodeName  // we are a direct element
-    || (node.on && node.find)));  // we have an on and find method part of jQuery API
-}
-
-/**
- * @param str 'key1,key2,...'
- * @returns {object} in the form of {key1:true, key2:true, ...}
- */
-function makeMap(str){
-  var obj = {}, items = str.split(","), i;
-  for ( i = 0; i < items.length; i++ )
-    obj[ items[i] ] = true;
-  return obj;
-}
-
-
-if (msie < 9) {
-  nodeName_ = function(element) {
-    element = element.nodeName ? element : element[0];
-    return (element.scopeName && element.scopeName != 'HTML')
-      ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
-  };
-} else {
-  nodeName_ = function(element) {
-    return element.nodeName ? element.nodeName : element[0].nodeName;
-  };
-}
-
-
-function map(obj, iterator, context) {
-  var results = [];
-  forEach(obj, function(value, index, list) {
-    results.push(iterator.call(context, value, index, list));
-  });
-  return results;
-}
-
-
-/**
- * @description
- * Determines the number of elements in an array, the number of properties an object has, or
- * the length of a string.
- *
- * Note: This function is used to augment the Object type in Angular expressions. See
- * {@link angular.Object} for more information about Angular arrays.
- *
- * @param {Object|Array|string} obj Object, array, or string to inspect.
- * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object
- * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array.
- */
-function size(obj, ownPropsOnly) {
-  var count = 0, key;
-
-  if (isArray(obj) || isString(obj)) {
-    return obj.length;
-  } else if (isObject(obj)){
-    for (key in obj)
-      if (!ownPropsOnly || obj.hasOwnProperty(key))
-        count++;
-  }
-
-  return count;
-}
-
-
-function includes(array, obj) {
-  return indexOf(array, obj) != -1;
-}
-
-function indexOf(array, obj) {
-  if (array.indexOf) return array.indexOf(obj);
-
-  for (var i = 0; i < array.length; i++) {
-    if (obj === array[i]) return i;
-  }
-  return -1;
-}
-
-function arrayRemove(array, value) {
-  var index = indexOf(array, value);
-  if (index >=0)
-    array.splice(index, 1);
-  return value;
-}
-
-function isLeafNode (node) {
-  if (node) {
-    switch (node.nodeName) {
-    case "OPTION":
-    case "PRE":
-    case "TITLE":
-      return true;
-    }
-  }
-  return false;
-}
-
-/**
- * @ngdoc function
- * @name angular.copy
- * @function
- *
- * @description
- * Creates a deep copy of `source`, which should be an object or an array.
- *
- * * If no destination is supplied, a copy of the object or array is created.
- * * If a destination is provided, all of its elements (for array) or properties (for objects)
- *   are deleted and then all elements/properties from the source are copied to it.
- * * If `source` is not an object or array (inc. `null` and `undefined`), `source` is returned.
- * * If `source` is identical to 'destination' an exception will be thrown.
- *
- * @param {*} source The source that will be used to make a copy.
- *                   Can be any type, including primitives, `null`, and `undefined`.
- * @param {(Object|Array)=} destination Destination into which the source is copied. If
- *     provided, must be of the same type as `source`.
- * @returns {*} The copy or updated `destination`, if `destination` was specified.
- *
- * @example
- <doc:example>
- <doc:source>
- <div ng-controller="Controller">
- <form novalidate class="simple-form">
- Name: <input type="text" ng-model="user.name" /><br />
- E-mail: <input type="email" ng-model="user.email" /><br />
- Gender: <input type="radio" ng-model="user.gender" value="male" />male
- <input type="radio" ng-model="user.gender" value="female" />female<br />
- <button ng-click="reset()">RESET</button>
- <button ng-click="update(user)">SAVE</button>
- </form>
- <pre>form = {{user | json}}</pre>
- <pre>master = {{master | json}}</pre>
- </div>
-
- <script>
- function Controller($scope) {
-    $scope.master= {};
-
-    $scope.update = function(user) {
-      // Example with 1 argument
-      $scope.master= angular.copy(user);
-    };
-
-    $scope.reset = function() {
-      // Example with 2 arguments
-      angular.copy($scope.master, $scope.user);
-    };
-
-    $scope.reset();
-  }
- </script>
- </doc:source>
- </doc:example>
- */
-function copy(source, destination){
-  if (isWindow(source) || isScope(source)) {
-    throw ngMinErr('cpws',
-      "Can't copy! Making copies of Window or Scope instances is not supported.");
-  }
-
-  if (!destination) {
-    destination = source;
-    if (source) {
-      if (isArray(source)) {
-        destination = copy(source, []);
-      } else if (isDate(source)) {
-        destination = new Date(source.getTime());
-      } else if (isRegExp(source)) {
-        destination = new RegExp(source.source);
-      } else if (isObject(source)) {
-        destination = copy(source, {});
-      }
-    }
-  } else {
-    if (source === destination) throw ngMinErr('cpi',
-      "Can't copy! Source and destination are identical.");
-    if (isArray(source)) {
-      destination.length = 0;
-      for ( var i = 0; i < source.length; i++) {
-        destination.push(copy(source[i]));
-      }
-    } else {
-      var h = destination.$$hashKey;
-      forEach(destination, function(value, key){
-        delete destination[key];
-      });
-      for ( var key_2 in source) {
-        destination[key_2] = copy(source[key_2]);
-      }
-      setHashKey(destination,h);
-    }
-  }
-  return destination;
-}
-
-/**
- * Create a shallow copy of an object
- */
-function shallowCopy(src, dst) {
-  dst = dst || {};
-
-  for(var key_3 in src) {
-    // shallowCopy is only ever called by $compile nodeLinkFn, which has control over src
-    // so we don't need to worry about using our custom hasOwnProperty here
-    if (src.hasOwnProperty(key_3) && key_3.substr(0, 2) !== '$$') {
-      dst[key_3] = src[key_3];
-    }
-  }
-
-  return dst;
-}
-
-
-/**
- * @ngdoc function
- * @name angular.equals
- * @function
- *
- * @description
- * Determines if two objects or two values are equivalent. Supports value types, regular
- * expressions, arrays and objects.
- *
- * Two objects or values are considered equivalent if at least one of the following is true:
- *
- * * Both objects or values pass `===` comparison.
- * * Both objects or values are of the same type and all of their properties are equal by
- *   comparing them with `angular.equals`.
- * * Both values are NaN. (In JavaScript, NaN == NaN => false. But we consider two NaN as equal)
- * * Both values represent the same regular expression (In JavasScript,
- *   /abc/ == /abc/ => false. But we consider two regular expressions as equal when their textual
- *   representation matches).
- *
- * During a property comparison, properties of `function` type and properties with names
- * that begin with `$` are ignored.
- *
- * Scope and DOMWindow objects are being compared only by identify (`===`).
- *
- * @param {*} o1 Object or value to compare.
- * @param {*} o2 Object or value to compare.
- * @returns {boolean} True if arguments are equal.
- */
-function equals(o1, o2) {
-  if (o1 === o2) return true;
-  if (o1 === null || o2 === null) return false;
-  if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN
-  var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
-  if (t1 == t2) {
-    if (t1 == 'object') {
-      if (isArray(o1)) {
-        if (!isArray(o2)) return false;
-        if ((length = o1.length) == o2.length) {
-          for(key=0; key<length; key++) {
-            if (!equals(o1[key], o2[key])) return false;
-          }
-          return true;
-        }
-      } else if (isDate(o1)) {
-        return isDate(o2) && o1.getTime() == o2.getTime();
-      } else if (isRegExp(o1) && isRegExp(o2)) {
-        return o1.toString() == o2.toString();
-      } else {
-        if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || isArray(o2)) return false;
-        keySet = {};
-        for(key in o1) {
-          if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
-          if (!equals(o1[key], o2[key])) return false;
-          keySet[key] = true;
-        }
-        for(key in o2) {
-          if (!keySet.hasOwnProperty(key) &&
-              key.charAt(0) !== '$' &&
-              o2[key] !== undefined &&
-              !isFunction(o2[key])) return false;
-        }
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-
-function csp() {
-  return (document.securityPolicy && document.securityPolicy.isActive) ||
-      (document.querySelector &&
-      !!(document.querySelector('[ng-csp]') || document.querySelector('[data-ng-csp]')));
-}
-
-
-function concat(array1, array2, index) {
-  return array1.concat(slice.call(array2, index));
-}
-
-function sliceArgs(args, startIndex) {
-  return slice.call(args, startIndex || 0);
-}
-
-
-/* jshint -W101 */
-/**
- * @ngdoc function
- * @name angular.bind
- * @function
- *
- * @description
- * Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
- * `fn`). You can supply optional `args` that are prebound to the function. This feature is also
- * known as [partial application](http://en.wikipedia.org/wiki/Partial_application), as
- * distinguished from [function currying](http://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application).
- *
- * @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.
- */
-/* jshint +W101 */
-function bind(self, fn) {
-  var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
-  if (isFunction(fn) && !(fn instanceof RegExp)) {
-    return curryArgs.length
-      ? function() {
-          return arguments.length
-            ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0)))
-            : fn.apply(self, curryArgs);
-        }
-      : function() {
-          return arguments.length
-            ? fn.apply(self, arguments)
-            : fn.call(self);
-        };
-  } else {
-    // in IE, native methods are not functions so they cannot be bound (note: they don't need to be)
-    return fn;
-  }
-}
-
-
-function toJsonReplacer(key, value) {
-  var val = value;
-
-  if (typeof key === 'string' && key.charAt(0) === '$') {
-    val = undefined;
-  } else if (isWindow(value)) {
-    val = '$WINDOW';
-  } else if (value &&  document === value) {
-    val = '$DOCUMENT';
-  } else if (isScope(value)) {
-    val = '$SCOPE';
-  }
-
-  return val;
-}
-
-
-/**
- * @ngdoc function
- * @name angular.toJson
- * @function
- *
- * @description
- * Serializes input into a JSON-formatted string. Properties with leading $ characters will be
- * stripped since angular uses this notation internally.
- *
- * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
- * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
- * @returns {string|undefined} JSON-ified string representing `obj`.
- */
-function toJson(obj, pretty) {
-  if (typeof obj === 'undefined') return undefined;
-  return JSON.stringify(obj, toJsonReplacer, pretty ? '  ' : null);
-}
-
-
-/**
- * @ngdoc function
- * @name angular.fromJson
- * @function
- *
- * @description
- * Deserializes a JSON string.
- *
- * @param {string} json JSON string to deserialize.
- * @returns {Object|Array|Date|string|number} Deserialized thingy.
- */
-function fromJson(json) {
-  return isString(json)
-      ? JSON.parse(json)
-      : json;
-}
-
-
-function toBoolean(value) {
-  if (value && value.length !== 0) {
-    var v = lowercase("" + value);
-    value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
-  } else {
-    value = false;
-  }
-  return value;
-}
-
-/**
- * @returns {string} Returns the string representation of the element.
- */
-function startingTag(element) {
-  element = jqLite(element).clone();
-  try {
-    // turns out IE does not let you set .html() on elements which
-    // are not allowed to have children. So we just ignore it.
-    element.empty();
-  } catch(e) {}
-  // As Per DOM Standards
-  var TEXT_NODE = 3;
-  var elemHtml = jqLite('<div>').append(element).html();
-  try {
-    return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) :
-        elemHtml.
-          match(/^(<[^>]+>)/)[1].
-          replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); });
-  } catch(e) {
-    return lowercase(elemHtml);
-  }
-
-}
-
-
-/////////////////////////////////////////////////
-
-/**
- * Tries to decode the URI component without throwing an exception.
- *
- * @private
- * @param str value potential URI component to check.
- * @returns {boolean} True if `value` can be decoded
- * with the decodeURIComponent function.
- */
-function tryDecodeURIComponent(value) {
-  try {
-    return decodeURIComponent(value);
-  } catch(e) {
-    // Ignore any invalid uri component
-  }
-}
-
-
-/**
- * Parses an escaped url query string into key-value pairs.
- * @returns Object.<(string|boolean)>
- */
-function parseKeyValue(/**string*/keyValue) {
-  var obj = {}, key_value, key;
-  forEach((keyValue || "").split('&'), function(keyValue){
-    if ( keyValue ) {
-      key_value = keyValue.split('=');
-      key = tryDecodeURIComponent(key_value[0]);
-      if ( isDefined(key) ) {
-        var val = isDefined(key_value[1]) ? tryDecodeURIComponent(key_value[1]) : true;
-        if (!obj[key]) {
-          obj[key] = val;
-        } else if(isArray(obj[key])) {
-          obj[key].push(val);
-        } else {
-          obj[key] = [obj[key],val];
-        }
-      }
-    }
-  });
-  return obj;
-}
-
-function toKeyValue(obj) {
-  var parts = [];
-  forEach(obj, function(value, key) {
-    if (isArray(value)) {
-      forEach(value, function(arrayValue) {
-        parts.push(encodeUriQuery(key, true) +
-                   (arrayValue === true ? '' : '=' + encodeUriQuery(arrayValue, true)));
-      });
-    } else {
-    parts.push(encodeUriQuery(key, true) +
-               (value === true ? '' : '=' + encodeUriQuery(value, true)));
-    }
-  });
-  return parts.length ? parts.join('&') : '';
-}
-
-
-/**
- * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
- * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
- * segments:
- *    segment       = *pchar
- *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
- *    pct-encoded   = "%" HEXDIG HEXDIG
- *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
- *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
- *                     / "*" / "+" / "," / ";" / "="
- */
-function encodeUriSegment(val) {
-  return encodeUriQuery(val, true).
-             replace(/%26/gi, '&').
-             replace(/%3D/gi, '=').
-             replace(/%2B/gi, '+');
-}
-
-
-/**
- * This method is intended for encoding *key* or *value* parts of query component. We need a custom
- * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
- * encoded per http://tools.ietf.org/html/rfc3986:
- *    query       = *( pchar / "/" / "?" )
- *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
- *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
- *    pct-encoded   = "%" HEXDIG HEXDIG
- *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
- *                     / "*" / "+" / "," / ";" / "="
- */
-function encodeUriQuery(val, pctEncodeSpaces) {
-  return encodeURIComponent(val).
-             replace(/%40/gi, '@').
-             replace(/%3A/gi, ':').
-             replace(/%24/g, '$').
-             replace(/%2C/gi, ',').
-             replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
-}
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngApp
- *
- * @element ANY
- * @param {angular.Module} ngApp an optional application
- *   {@link angular.module module} name to load.
- *
- * @description
- *
- * Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
- * designates the **root element** of the application and is typically placed near the root element
- * of the page - e.g. on the `<body>` or `<html>` tags.
- *
- * Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
- * found in the document will be used to define the root element to auto-bootstrap as an
- * application. To run multiple applications in an HTML document you must manually bootstrap them using
- * {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
- *
- * You can specify an **AngularJS module** to be used as the root module for the application.  This
- * module will be loaded into the {@link AUTO.$injector} when the application is bootstrapped and
- * should contain the application code needed or have dependencies on other modules that will
- * contain the code. See {@link angular.module} for more information.
- *
- * In the example below if the `ngApp` directive were not placed on the `html` element then the
- * document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
- * would not be resolved to `3`.
- *
- * `ngApp` is the easiest, and most common, way to bootstrap an application.
- *
- <example module="ngAppDemo">
-   <file name="index.html">
-   <div ng-controller="ngAppDemoController">
-     I can add: {{a}} + {{b}} =  {{ a+b }}
-   </file>
-   <file name="script.js">
-   angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
-     $scope.a = 1;
-     $scope.b = 2;
-   });
-   </file>
- </example>
- *
- */
-function angularInit(element, bootstrap) {
-  var elements = [element],
-      appElement,
-      module,
-      names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
-      NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
-
-  function append(element) {
-    element && elements.push(element);
-  }
-
-  forEach(names, function(name) {
-    names[name] = true;
-    append(document.getElementById(name));
-    name = name.replace(':', '\\:');
-    if (element.querySelectorAll) {
-      forEach(element.querySelectorAll('.' + name), append);
-      forEach(element.querySelectorAll('.' + name + '\\:'), append);
-      forEach(element.querySelectorAll('[' + name + ']'), append);
-    }
-  });
-
-  forEach(elements, function(element) {
-    if (!appElement) {
-      var className = ' ' + element.className + ' ';
-      var match = NG_APP_CLASS_REGEXP.exec(className);
-      if (match) {
-        appElement = element;
-        module = (match[2] || '').replace(/\s+/g, ',');
-      } else {
-        forEach(element.attributes, function(attr) {
-          if (!appElement && names[attr.name]) {
-            appElement = element;
-            module = attr.value;
-          }
-        });
-      }
-    }
-  });
-  if (appElement) {
-    bootstrap(appElement, module ? [module] : []);
-  }
-}
-
-/**
- * @ngdoc function
- * @name angular.bootstrap
- * @description
- * Use this function to manually start up angular application.
- *
- * See: {@link guide/bootstrap Bootstrap}
- *
- * Note that ngScenario-based end-to-end tests cannot use this function to bootstrap manually.
- * They must use {@link api/ng.directive:ngApp ngApp}.
- *
- * @param {Element} element DOM element which is the root of angular application.
- * @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
- *     Each item in the array should be the name of a predefined module or a (DI annotated)
- *     function that will be invoked by the injector as a run block.
- *     See: {@link angular.module modules}
- * @returns {AUTO.$injector} Returns the newly created injector for this app.
- */
-function bootstrap(element, modules) {
-  var doBootstrap = function() {
-    element = jqLite(element);
-
-    if (element.injector()) {
-      var tag = (element[0] === document) ? 'document' : startingTag(element);
-      throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag);
-    }
-
-    modules = modules || [];
-    modules.unshift(['$provide', function($provide) {
-      $provide.value('$rootElement', element);
-    }]);
-    modules.unshift('ng');
-    var injector = createInjector(modules);
-    injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',
-       function(scope, element, compile, injector, animate) {
-        scope.$apply(function() {
-          element.data('$injector', injector);
-          compile(element)(scope);
-        });
-      }]
-    );
-    return injector;
-  };
-
-  var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
-
-  if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
-    return doBootstrap();
-  }
-
-  window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
-  angular.resumeBootstrap = function(extraModules) {
-    forEach(extraModules, function(module) {
-      modules.push(module);
-    });
-    doBootstrap();
-  };
-}
-
-var SNAKE_CASE_REGEXP = /[A-Z]/g;
-function snake_case(name, separator){
-  separator = separator || '_';
-  return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) {
-    return (pos ? separator : '') + letter.toLowerCase();
-  });
-}
-
-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,
-      isolateScope: JQLitePrototype.isolateScope,
-      controller: JQLitePrototype.controller,
-      injector: JQLitePrototype.injector,
-      inheritedData: JQLitePrototype.inheritedData
-    });
-    // Method signature:
-    //     jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments)
-    jqLitePatchJQueryRemove('remove', true, true, false);
-    jqLitePatchJQueryRemove('empty', false, false, false);
-    jqLitePatchJQueryRemove('html', false, false, true);
-  } else {
-    jqLite = JQLite;
-  }
-  angular.element = jqLite;
-}
-
-/**
- * throw error if the argument is falsy.
- */
-function assertArg(arg, name, reason) {
-  if (!arg) {
-    throw ngMinErr('areq', "Argument '{0}' is {1}", (name || '?'), (reason || "required"));
-  }
-  return arg;
-}
-
-function assertArgFn(arg, name, acceptArrayAnnotation) {
-  if (acceptArrayAnnotation && isArray(arg)) {
-      arg = arg[arg.length - 1];
-  }
-
-  assertArg(isFunction(arg), name, 'not a function, got ' +
-      (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg));
-  return arg;
-}
-
-/**
- * throw error if the name given is hasOwnProperty
- * @param  {String} name    the name to test
- * @param  {String} context the context in which the name is used, such as module or directive
- */
-function assertNotHasOwnProperty(name, context) {
-  if (name === 'hasOwnProperty') {
-    throw ngMinErr('badname', "hasOwnProperty is not a valid {0} name", context);
-  }
-}
-
-/**
- * Return the value accessible from the object by path. Any undefined traversals are ignored
- * @param {Object} obj starting object
- * @param {string} path path to traverse
- * @param {boolean=true} bindFnToScope
- * @returns value as accessible by path
- */
-//TODO(misko): this function needs to be removed
-function getter(obj, path, bindFnToScope) {
-  if (!path) return obj;
-  var keys = path.split('.');
-  var key;
-  var lastInstance = obj;
-  var len = keys.length;
-
-  for (var i = 0; i < len; i++) {
-    key = keys[i];
-    if (obj) {
-      obj = (lastInstance = obj)[key];
-    }
-  }
-  if (!bindFnToScope && isFunction(obj)) {
-    return bind(lastInstance, obj);
-  }
-  return obj;
-}
-
-/**
- * Return the DOM siblings between the first and last node in the given array.
- * @param {Array} array like object
- * @returns jQlite object containing the elements
- */
-function getBlockElements(nodes) {
-  var startNode = nodes[0],
-      endNode = nodes[nodes.length - 1];
-  if (startNode === endNode) {
-    return jqLite(startNode);
-  }
-
-  var element = startNode;
-  var elements = [element];
-
-  do {
-    element = element.nextSibling;
-    if (!element) break;
-    elements.push(element);
-  } while (element !== endNode);
-
-  return jqLite(elements);
-}
-
-/**
- * @ngdoc interface
- * @name angular.Module
- * @description
- *
- * Interface for configuring angular {@link angular.module modules}.
- */
-
-function setupModuleLoader(window) {
-
-  var $injectorMinErr = minErr('$injector');
-  var ngMinErr = minErr('ng');
-
-  function ensure(obj, name, factory) {
-    return obj[name] || (obj[name] = factory());
-  }
-
-  var angular = ensure(window, 'angular', Object);
-
-  // We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
-  angular.$$minErr = angular.$$minErr || minErr;
-
-  return ensure(angular, 'module', function() {
-    /** @type {Object.<string, angular.Module>} */
-    var modules = {};
-
-    /**
-     * @ngdoc function
-     * @name angular.module
-     * @description
-     *
-     * The `angular.module` is a global place for creating, registering and retrieving Angular
-     * modules.
-     * All modules (angular core or 3rd party) that should be available to an application must be
-     * registered using this mechanism.
-     *
-     * When passed two or more arguments, a new module is created.  If passed only one argument, an
-     * existing module (the name passed as the first argument to `module`) is retrieved.
-     *
-     *
-     * # Module
-     *
-     * A module is a collection of services, directives, filters, and configuration information.
-     * `angular.module` is used to configure the {@link AUTO.$injector $injector}.
-     *
-     * <pre>
-     * // Create a new module
-     * var myModule = angular.module('myModule', []);
-     *
-     * // register a new service
-     * myModule.value('appName', 'MyCoolApp');
-     *
-     * // configure existing services inside initialization blocks.
-     * myModule.config(function($locationProvider) {
-     *   // Configure existing providers
-     *   $locationProvider.hashPrefix('!');
-     * });
-     * </pre>
-     *
-     * Then you can create an injector and load your modules like this:
-     *
-     * <pre>
-     * var injector = angular.injector(['ng', 'MyModule'])
-     * </pre>
-     *
-     * However it's more likely that you'll just use
-     * {@link ng.directive:ngApp ngApp} or
-     * {@link angular.bootstrap} to simplify this process for you.
-     *
-     * @param {!string} name The name of the module to create or retrieve.
-     * @param {Array.<string>=} requires If specified then new module is being created. If
-     *        unspecified then the the module is being retrieved for further configuration.
-     * @param {Function} configFn Optional configuration function for the module. Same as
-     *        {@link angular.Module#methods_config Module#config()}.
-     * @returns {module} new module with the {@link angular.Module} api.
-     */
-    return function module(name, requires, configFn) {
-      var assertNotHasOwnProperty = function(name, context) {
-        if (name === 'hasOwnProperty') {
-          throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
-        }
-      };
-
-      assertNotHasOwnProperty(name, 'module');
-      if (requires && modules.hasOwnProperty(name)) {
-        modules[name] = null;
-      }
-      return ensure(modules, name, function() {
-        if (!requires) {
-          throw $injectorMinErr('nomod', "Module '{0}' is not available! You either misspelled " +
-             "the module name or forgot to load it. If registering a module ensure that you " +
-             "specify the dependencies as the second argument.", name);
-        }
-
-        /** @type {!Array.<Array.<*>>} */
-        var invokeQueue = [];
-
-        /** @type {!Array.<Function>} */
-        var runBlocks = [];
-
-        var config = invokeLater('$injector', 'invoke');
-
-        /** @type {angular.Module} */
-        var moduleInstance = {
-          // Private state
-          _invokeQueue: invokeQueue,
-          _runBlocks: runBlocks,
-
-          /**
-           * @ngdoc property
-           * @name angular.Module#requires
-           * @propertyOf angular.Module
-           * @returns {Array.<string>} List of module names which must be loaded before this module.
-           * @description
-           * Holds the list of modules which the injector will load before the current module is
-           * loaded.
-           */
-          requires: requires,
-
-          /**
-           * @ngdoc property
-           * @name angular.Module#name
-           * @propertyOf angular.Module
-           * @returns {string} Name of the module.
-           * @description
-           */
-          name: name,
-
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#provider
-           * @methodOf angular.Module
-           * @param {string} name service name
-           * @param {Function} providerType Construction function for creating new instance of the
-           *                                service.
-           * @description
-           * See {@link AUTO.$provide#provider $provide.provider()}.
-           */
-          provider: invokeLater('$provide', 'provider'),
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#factory
-           * @methodOf angular.Module
-           * @param {string} name service name
-           * @param {Function} providerFunction Function for creating new instance of the service.
-           * @description
-           * See {@link AUTO.$provide#factory $provide.factory()}.
-           */
-          factory: invokeLater('$provide', 'factory'),
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#service
-           * @methodOf angular.Module
-           * @param {string} name service name
-           * @param {Function} constructor A constructor function that will be instantiated.
-           * @description
-           * See {@link AUTO.$provide#service $provide.service()}.
-           */
-          service: invokeLater('$provide', 'service'),
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#value
-           * @methodOf angular.Module
-           * @param {string} name service name
-           * @param {*} object Service instance object.
-           * @description
-           * See {@link AUTO.$provide#value $provide.value()}.
-           */
-          value: invokeLater('$provide', 'value'),
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#constant
-           * @methodOf angular.Module
-           * @param {string} name constant name
-           * @param {*} object Constant value.
-           * @description
-           * Because the constant are fixed, they get applied before other provide methods.
-           * See {@link AUTO.$provide#constant $provide.constant()}.
-           */
-          constant: invokeLater('$provide', 'constant', 'unshift'),
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#animation
-           * @methodOf angular.Module
-           * @param {string} name animation name
-           * @param {Function} animationFactory Factory function for creating new instance of an
-           *                                    animation.
-           * @description
-           *
-           * **NOTE**: animations take effect only if the **ngAnimate** module is loaded.
-           *
-           *
-           * Defines an animation hook that can be later used with
-           * {@link ngAnimate.$animate $animate} service and directives that use this service.
-           *
-           * <pre>
-           * module.animation('.animation-name', function($inject1, $inject2) {
-           *   return {
-           *     eventName : function(element, done) {
-           *       //code to run the animation
-           *       //once complete, then run done()
-           *       return function cancellationFunction(element) {
-           *         //code to cancel the animation
-           *       }
-           *     }
-           *   }
-           * })
-           * </pre>
-           *
-           * See {@link ngAnimate.$animateProvider#register $animateProvider.register()} and
-           * {@link ngAnimate ngAnimate module} for more information.
-           */
-          animation: invokeLater('$animateProvider', 'register'),
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#filter
-           * @methodOf angular.Module
-           * @param {string} name Filter name.
-           * @param {Function} filterFactory Factory function for creating new instance of filter.
-           * @description
-           * See {@link ng.$filterProvider#register $filterProvider.register()}.
-           */
-          filter: invokeLater('$filterProvider', 'register'),
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#controller
-           * @methodOf angular.Module
-           * @param {string|Object} name Controller name, or an object map of controllers where the
-           *    keys are the names and the values are the constructors.
-           * @param {Function} constructor Controller constructor function.
-           * @description
-           * See {@link ng.$controllerProvider#register $controllerProvider.register()}.
-           */
-          controller: invokeLater('$controllerProvider', 'register'),
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#directive
-           * @methodOf angular.Module
-           * @param {string|Object} name Directive name, or an object map of directives where the
-           *    keys are the names and the values are the factories.
-           * @param {Function} directiveFactory Factory function for creating new instance of
-           * directives.
-           * @description
-           * See {@link ng.$compileProvider#methods_directive $compileProvider.directive()}.
-           */
-          directive: invokeLater('$compileProvider', 'directive'),
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#config
-           * @methodOf angular.Module
-           * @param {Function} configFn Execute this function on module load. Useful for service
-           *    configuration.
-           * @description
-           * Use this method to register work which needs to be performed on module loading.
-           */
-          config: config,
-
-          /**
-           * @ngdoc method
-           * @name angular.Module#run
-           * @methodOf angular.Module
-           * @param {Function} initializationFn Execute this function after injector creation.
-           *    Useful for application initialization.
-           * @description
-           * Use this method to register work which should be performed when the injector is done
-           * loading all modules.
-           */
-          run: function(block) {
-            runBlocks.push(block);
-            return this;
-          }
-        };
-
-        if (configFn) {
-          config(configFn);
-        }
-
-        return  moduleInstance;
-
-        /**
-         * @param {string} provider
-         * @param {string} method
-         * @param {String=} insertMethod
-         * @returns {angular.Module}
-         */
-        function invokeLater(provider, method, insertMethod) {
-          return function() {
-            invokeQueue[insertMethod || 'push']([provider, method, arguments]);
-            return moduleInstance;
-          };
-        }
-      });
-    };
-  });
-
-}
-
-/* global
-    angularModule: true,
-    version: true,
-    
-    $LocaleProvider,
-    $CompileProvider,
-    
-    htmlAnchorDirective,
-    inputDirective,
-    inputDirective,
-    formDirective,
-    scriptDirective,
-    selectDirective,
-    styleDirective,
-    optionDirective,
-    ngBindDirective,
-    ngBindHtmlDirective,
-    ngBindTemplateDirective,
-    ngClassDirective,
-    ngClassEvenDirective,
-    ngClassOddDirective,
-    ngCspDirective,
-    ngCloakDirective,
-    ngControllerDirective,
-    ngFormDirective,
-    ngHideDirective,
-    ngIfDirective,
-    ngIncludeDirective,
-    ngIncludeFillContentDirective,
-    ngInitDirective,
-    ngNonBindableDirective,
-    ngPluralizeDirective,
-    ngRepeatDirective,
-    ngShowDirective,
-    ngStyleDirective,
-    ngSwitchDirective,
-    ngSwitchWhenDirective,
-    ngSwitchDefaultDirective,
-    ngOptionsDirective,
-    ngTranscludeDirective,
-    ngModelDirective,
-    ngListDirective,
-    ngChangeDirective,
-    requiredDirective,
-    requiredDirective,
-    ngValueDirective,
-    ngAttributeAliasDirectives,
-    ngEventDirectives,
-
-    $AnchorScrollProvider,
-    $AnimateProvider,
-    $BrowserProvider,
-    $CacheFactoryProvider,
-    $ControllerProvider,
-    $DocumentProvider,
-    $ExceptionHandlerProvider,
-    $FilterProvider,
-    $InterpolateProvider,
-    $IntervalProvider,
-    $HttpProvider,
-    $HttpBackendProvider,
-    $LocationProvider,
-    $LogProvider,
-    $ParseProvider,
-    $RootScopeProvider,
-    $QProvider,
-    $$SanitizeUriProvider,
-    $SceProvider,
-    $SceDelegateProvider,
-    $SnifferProvider,
-    $TemplateCacheProvider,
-    $TimeoutProvider,
-    $WindowProvider
-*/
-
-
-/**
- * @ngdoc property
- * @name angular.version
- * @description
- * An object that contains information about the current AngularJS version. This object has the
- * following properties:
- *
- * - `full` – `{string}` – Full version string, such as "0.9.18".
- * - `major` – `{number}` – Major version number, such as "0".
- * - `minor` – `{number}` – Minor version number, such as "9".
- * - `dot` – `{number}` – Dot version number, such as "18".
- * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
- */
-var version = {
-  full: '1.2.5',    // all of these placeholder strings will be replaced by grunt's
-  major: 1,    // package task
-  minor: 2,
-  dot: 5,
-  codeName: 'singularity-expansion'
-};
-
-
-function publishExternalAPI(angular){
-  extend(angular, {
-    'bootstrap': bootstrap,
-    'copy': copy,
-    'extend': extend,
-    'equals': equals,
-    'element': jqLite,
-    'forEach': forEach,
-    'injector': createInjector,
-    'noop':noop,
-    'bind':bind,
-    'toJson': toJson,
-    'fromJson': fromJson,
-    'identity':identity,
-    'isUndefined': isUndefined,
-    'isDefined': isDefined,
-    'isString': isString,
-    'isFunction': isFunction,
-    'isObject': isObject,
-    'isNumber': isNumber,
-    'isElement': isElement,
-    'isArray': isArray,
-    'version': version,
-    'isDate': isDate,
-    'lowercase': lowercase,
-    'uppercase': uppercase,
-    'callbacks': {counter: 0},
-    '$$minErr': minErr,
-    '$$csp': csp
-  });
-
-  angularModule = setupModuleLoader(window);
-  try {
-    angularModule('ngLocale');
-  } catch (e) {
-    angularModule('ngLocale', []).provider('$locale', $LocaleProvider);
-  }
-
-  angularModule('ng', ['ngLocale'], ['$provide',
-    function ngModule($provide) {
-      // $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
-      $provide.provider({
-        $$sanitizeUri: $$SanitizeUriProvider
-      });
-      $provide.provider('$compile', $CompileProvider).
-        directive({
-            a: htmlAnchorDirective,
-            input: inputDirective,
-            textarea: inputDirective,
-            form: formDirective,
-            script: scriptDirective,
-            select: selectDirective,
-            style: styleDirective,
-            option: optionDirective,
-            ngBind: ngBindDirective,
-            ngBindHtml: ngBindHtmlDirective,
-            ngBindTemplate: ngBindTemplateDirective,
-            ngClass: ngClassDirective,
-            ngClassEven: ngClassEvenDirective,
-            ngClassOdd: ngClassOddDirective,
-            ngCloak: ngCloakDirective,
-            ngController: ngControllerDirective,
-            ngForm: ngFormDirective,
-            ngHide: ngHideDirective,
-            ngIf: ngIfDirective,
-            ngInclude: ngIncludeDirective,
-            ngInit: ngInitDirective,
-            ngNonBindable: ngNonBindableDirective,
-            ngPluralize: ngPluralizeDirective,
-            ngRepeat: ngRepeatDirective,
-            ngShow: ngShowDirective,
-            ngStyle: ngStyleDirective,
-            ngSwitch: ngSwitchDirective,
-            ngSwitchWhen: ngSwitchWhenDirective,
-            ngSwitchDefault: ngSwitchDefaultDirective,
-            ngOptions: ngOptionsDirective,
-            ngTransclude: ngTranscludeDirective,
-            ngModel: ngModelDirective,
-            ngList: ngListDirective,
-            ngChange: ngChangeDirective,
-            required: requiredDirective,
-            ngRequired: requiredDirective,
-            ngValue: ngValueDirective
-        }).
-        directive({
-          ngInclude: ngIncludeFillContentDirective
-        }).
-        directive(ngAttributeAliasDirectives).
-        directive(ngEventDirectives);
-      $provide.provider({
-        $anchorScroll: $AnchorScrollProvider,
-        $animate: $AnimateProvider,
-        $browser: $BrowserProvider,
-        $cacheFactory: $CacheFactoryProvider,
-        $controller: $ControllerProvider,
-        $document: $DocumentProvider,
-        $exceptionHandler: $ExceptionHandlerProvider,
-        $filter: $FilterProvider,
-        $interpolate: $InterpolateProvider,
-        $interval: $IntervalProvider,
-        $http: $HttpProvider,
-        $httpBackend: $HttpBackendProvider,
-        $location: $LocationProvider,
-        $log: $LogProvider,
-        $parse: $ParseProvider,
-        $rootScope: $RootScopeProvider,
-        $q: $QProvider,
-        $sce: $SceProvider,
-        $sceDelegate: $SceDelegateProvider,
-        $sniffer: $SnifferProvider,
-        $templateCache: $TemplateCacheProvider,
-        $timeout: $TimeoutProvider,
-        $window: $WindowProvider
-      });
-    }
-  ]);
-}
-
-/* global
-
-  -JQLitePrototype,
-  -addEventListenerFn,
-  -removeEventListenerFn,
-  -BOOLEAN_ATTR
-*/
-
-//////////////////////////////////
-//JQLite
-//////////////////////////////////
-
-/**
- * @ngdoc function
- * @name angular.element
- * @function
- *
- * @description
- * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element.
- *
- * If jQuery is available, `angular.element` is an alias for the
- * [jQuery](http://api.jquery.com/jQuery/) function. If jQuery is not available, `angular.element`
- * delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite."
- *
- * <div class="alert alert-success">jqLite is a tiny, API-compatible subset of jQuery that allows
- * Angular to manipulate the DOM in a cross-browser compatible way. **jqLite** implements only the most
- * commonly needed functionality with the goal of having a very small footprint.</div>
- *
- * To use jQuery, simply load it before `DOMContentLoaded` event fired.
- *
- * <div class="alert">**Note:** all element references in Angular are always wrapped with jQuery or
- * jqLite; they are never raw DOM references.</div>
- *
- * ## Angular's jqLite
- * jqLite provides only the following jQuery methods:
- *
- * - [`addClass()`](http://api.jquery.com/addClass/)
- * - [`after()`](http://api.jquery.com/after/)
- * - [`append()`](http://api.jquery.com/append/)
- * - [`attr()`](http://api.jquery.com/attr/)
- * - [`bind()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
- * - [`children()`](http://api.jquery.com/children/) - Does not support selectors
- * - [`clone()`](http://api.jquery.com/clone/)
- * - [`contents()`](http://api.jquery.com/contents/)
- * - [`css()`](http://api.jquery.com/css/)
- * - [`data()`](http://api.jquery.com/data/)
- * - [`empty()`](http://api.jquery.com/empty/)
- * - [`eq()`](http://api.jquery.com/eq/)
- * - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
- * - [`hasClass()`](http://api.jquery.com/hasClass/)
- * - [`html()`](http://api.jquery.com/html/)
- * - [`next()`](http://api.jquery.com/next/) - Does not support selectors
- * - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
- * - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
- * - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
- * - [`prepend()`](http://api.jquery.com/prepend/)
- * - [`prop()`](http://api.jquery.com/prop/)
- * - [`ready()`](http://api.jquery.com/ready/)
- * - [`remove()`](http://api.jquery.com/remove/)
- * - [`removeAttr()`](http://api.jquery.com/removeAttr/)
- * - [`removeClass()`](http://api.jquery.com/removeClass/)
- * - [`removeData()`](http://api.jquery.com/removeData/)
- * - [`replaceWith()`](http://api.jquery.com/replaceWith/)
- * - [`text()`](http://api.jquery.com/text/)
- * - [`toggleClass()`](http://api.jquery.com/toggleClass/)
- * - [`triggerHandler()`](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers.
- * - [`unbind()`](http://api.jquery.com/off/) - Does not support namespaces
- * - [`val()`](http://api.jquery.com/val/)
- * - [`wrap()`](http://api.jquery.com/wrap/)
- *
- * ## jQuery/jqLite Extras
- * Angular also provides the following additional methods and events to both jQuery and jqLite:
- *
- * ### Events
- * - `$destroy` - AngularJS intercepts all jqLite/jQuery's DOM destruction apis and fires this event
- *    on all DOM nodes being removed.  This can be used to clean up any 3rd party bindings to the DOM
- *    element before it is removed.
- *
- * ### Methods
- * - `controller(name)` - retrieves the controller of the current element or its parent. By default
- *   retrieves controller associated with the `ngController` directive. If `name` is provided as
- *   camelCase directive name, then the controller for this directive will be retrieved (e.g.
- *   `'ngModel'`).
- * - `injector()` - retrieves the injector of the current element or its parent.
- * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current
- *   element or its parent.
- * - `isolateScope()` - retrieves an isolate {@link api/ng.$rootScope.Scope scope} if one is attached directly to the
- *   current element. This getter should be used only on elements that contain a directive which starts a new isolate
- *   scope. Calling `scope()` on this element always returns the original non-isolate scope.
- * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top
- *   parent element is reached.
- *
- * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
- * @returns {Object} jQuery object.
- */
-
-var jqCache = JQLite.cache = {},
-    jqName = JQLite.expando = '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); });
-
-function jqNextId() { return ++jqId; }
-
-
-var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g;
-var MOZ_HACK_REGEXP = /^moz([A-Z])/;
-var jqLiteMinErr = minErr('jqLite');
-
-/**
- * Converts snake_case to camelCase.
- * Also there is special case for Moz prefix starting with upper case letter.
- * @param name Name to normalize
- */
-function camelCase(name) {
-  return name.
-    replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) {
-      return offset ? letter.toUpperCase() : letter;
-    }).
-    replace(MOZ_HACK_REGEXP, 'Moz$1');
-}
-
-/////////////////////////////////////////////
-// jQuery mutation patch
-//
-// In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a
-// $destroy event on all DOM nodes being removed.
-//
-/////////////////////////////////////////////
-
-function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) {
-  var originalJqFn = jQuery.fn[name];
-  originalJqFn = originalJqFn.$original || originalJqFn;
-  removePatch.$original = originalJqFn;
-  jQuery.fn[name] = removePatch;
-
-  function removePatch(param) {
-    // jshint -W040
-    var list = filterElems && param ? [this.filter(param)] : [this],
-        fireEvent = dispatchThis,
-        set, setIndex, setLength,
-        element, childIndex, childLength, children;
-
-    if (!getterIfNoArguments || param != null) {
-      while(list.length) {
-        set = list.shift();
-        for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
-          element = jqLite(set[setIndex]);
-          if (fireEvent) {
-            element.triggerHandler('$destroy');
-          } else {
-            fireEvent = !fireEvent;
-          }
-          for(childIndex = 0, childLength = (children = element.children()).length;
-              childIndex < childLength;
-              childIndex++) {
-            list.push(jQuery(children[childIndex]));
-          }
-        }
-      }
-    }
-    return originalJqFn.apply(this, arguments);
-  }
-}
-
-/////////////////////////////////////////////
-function JQLite(element) {
-  if (element instanceof JQLite) {
-    return element;
-  }
-  if (!(this instanceof JQLite)) {
-    if (isString(element) && element.charAt(0) != '<') {
-      throw jqLiteMinErr('nosel', 'Looking up elements via selectors is not supported by jqLite! See: http://docs.angularjs.org/api/angular.element');
-    }
-    return new JQLite(element);
-  }
-
-  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>&#160;</div>' + element; // IE insanity to make NoScope elements work!
-    div.removeChild(div.firstChild); // remove the superfluous div
-    jqLiteAddNodes(this, div.childNodes);
-    var fragment = jqLite(document.createDocumentFragment());
-    fragment.append(this); // detach the elements from the temporary DOM div.
-  } else {
-    jqLiteAddNodes(this, element);
-  }
-}
-
-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 jqLiteOff(element, type, fn, unsupported) {
-  if (isDefined(unsupported)) throw jqLiteMinErr('offargs', 'jqLite#off() does not support the `selector` argument');
-
-  var events = jqLiteExpandoStore(element, 'events'),
-      handle = jqLiteExpandoStore(element, 'handle');
-
-  if (!handle) return; //no listeners registered
-
-  if (isUndefined(type)) {
-    forEach(events, function(eventHandler, type) {
-      removeEventListenerFn(element, type, eventHandler);
-      delete events[type];
-    });
-  } else {
-    forEach(type.split(' '), function(type) {
-      if (isUndefined(fn)) {
-        removeEventListenerFn(element, type, events[type]);
-        delete events[type];
-      } else {
-        arrayRemove(events[type] || [], fn);
-      }
-    });
-  }
-}
-
-function jqLiteRemoveData(element, name) {
-  var expandoId = element[jqName],
-      expandoStore = jqCache[expandoId];
-
-  if (expandoStore) {
-    if (name) {
-      delete jqCache[expandoId].data[name];
-      return;
-    }
-
-    if (expandoStore.handle) {
-      expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
-      jqLiteOff(element);
-    }
-    delete jqCache[expandoId];
-    element[jqName] = undefined; // ie does not allow deletion of attributes on elements.
-  }
-}
-
-function jqLiteExpandoStore(element, key, value) {
-  var expandoId = element[jqName],
-      expandoStore = jqCache[expandoId || -1];
-
-  if (isDefined(value)) {
-    if (!expandoStore) {
-      element[jqName] = expandoId = jqNextId();
-      expandoStore = jqCache[expandoId] = {};
-    }
-    expandoStore[key] = value;
-  } else {
-    return expandoStore && expandoStore[key];
-  }
-}
-
-function jqLiteData(element, key, value) {
-  var data = jqLiteExpandoStore(element, 'data'),
-      isSetter = isDefined(value),
-      keyDefined = !isSetter && isDefined(key),
-      isSimpleGetter = keyDefined && !isObject(key);
-
-  if (!data && !isSimpleGetter) {
-    jqLiteExpandoStore(element, 'data', data = {});
-  }
-
-  if (isSetter) {
-    data[key] = value;
-  } else {
-    if (keyDefined) {
-      if (isSimpleGetter) {
-        // don't create data in this case.
-        return data && data[key];
-      } else {
-        extend(data, key);
-      }
-    } else {
-      return data;
-    }
-  }
-}
-
-function jqLiteHasClass(element, selector) {
-  if (!element.getAttribute) return false;
-  return ((" " + (element.getAttribute('class') || '') + " ").replace(/[\n\t]/g, " ").
-      indexOf( " " + selector + " " ) > -1);
-}
-
-function jqLiteRemoveClass(element, cssClasses) {
-  if (cssClasses && element.setAttribute) {
-    forEach(cssClasses.split(' '), function(cssClass) {
-      element.setAttribute('class', trim(
-          (" " + (element.getAttribute('class') || '') + " ")
-          .replace(/[\n\t]/g, " ")
-          .replace(" " + trim(cssClass) + " ", " "))
-      );
-    });
-  }
-}
-
-function jqLiteAddClass(element, cssClasses) {
-  if (cssClasses && element.setAttribute) {
-    var existingClasses = (' ' + (element.getAttribute('class') || '') + ' ')
-                            .replace(/[\n\t]/g, " ");
-
-    forEach(cssClasses.split(' '), function(cssClass) {
-      cssClass = trim(cssClass);
-      if (existingClasses.indexOf(' ' + cssClass + ' ') === -1) {
-        existingClasses += cssClass + ' ';
-      }
-    });
-
-    element.setAttribute('class', trim(existingClasses));
-  }
-}
-
-function jqLiteAddNodes(root, elements) {
-  if (elements) {
-    elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
-      ? elements
-      : [ elements ];
-    for(var i=0; i < elements.length; i++) {
-      root.push(elements[i]);
-    }
-  }
-}
-
-function jqLiteController(element, name) {
-  return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
-}
-
-function jqLiteInheritedData(element, name, value) {
-  element = jqLite(element);
-
-  // if element is the document object work with the html element instead
-  // this makes $(document).scope() possible
-  if(element[0].nodeType == 9) {
-    element = element.find('html');
-  }
-  var names = isArray(name) ? name : [name];
-
-  while (element.length) {
-
-    for (var i = 0, ii = names.length; i < ii; i++) {
-      if ((value = element.data(names[i])) !== undefined) return value;
-    }
-    element = element.parent();
-  }
-}
-
-function jqLiteEmpty(element) {
-  for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
-    jqLiteDealoc(childNodes[i]);
-  }
-  while (element.firstChild) {
-    element.removeChild(element.firstChild);
-  }
-}
-
-//////////////////////////////////////////
-// Functions which are declared directly.
-//////////////////////////////////////////
-var JQLitePrototype = JQLite.prototype = {
-  ready: function(fn) {
-    var fired = false;
-
-    function trigger() {
-      if (fired) return;
-      fired = true;
-      fn();
-    }
-
-    // check if document already is loaded
-    if (document.readyState === 'complete'){
-      setTimeout(trigger);
-    } else {
-      this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
-      // we can not use jqLite since we are not done loading and jQuery could be loaded later.
-      // jshint -W064
-      JQLite(window).on('load', trigger); // fallback to window.onload for others
-      // jshint +W064
-    }
-  },
-  toString: function() {
-    var value = [];
-    forEach(this, function(e){ value.push('' + e);});
-    return '[' + value.join(', ') + ']';
-  },
-
-  eq: function(index) {
-      return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]);
-  },
-
-  length: 0,
-  push: push,
-  sort: [].sort,
-  splice: [].splice
-};
-
-//////////////////////////////////////////
-// Functions iterating getter/setters.
-// these functions return self on setter and
-// value on get.
-//////////////////////////////////////////
-var BOOLEAN_ATTR = {};
-forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
-  BOOLEAN_ATTR[lowercase(value)] = value;
-});
-var BOOLEAN_ELEMENTS = {};
-forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
-  BOOLEAN_ELEMENTS[uppercase(value)] = true;
-});
-
-function getBooleanAttrName(element, name) {
-  // check dom last since we will most likely fail on name
-  var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
-
-  // booleanAttr is here twice to minimize DOM access
-  return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
-}
-
-forEach({
-  data: jqLiteData,
-  inheritedData: jqLiteInheritedData,
-
-  scope: function(element) {
-    // Can't use jqLiteData here directly so we stay compatible with jQuery!
-    return jqLite(element).data('$scope') || jqLiteInheritedData(element.parentNode || element, ['$isolateScope', '$scope']);
-  },
-
-  isolateScope: function(element) {
-    // Can't use jqLiteData here directly so we stay compatible with jQuery!
-    return jqLite(element).data('$isolateScope') || jqLite(element).data('$isolateScopeNoTemplate');
-  },
-
-  controller: jqLiteController ,
-
-  injector: function(element) {
-    return jqLiteInheritedData(element, '$injector');
-  },
-
-  removeAttr: function(element,name) {
-    element.removeAttribute(name);
-  },
-
-  hasClass: jqLiteHasClass,
-
-  css: function(element, name, value) {
-    name = camelCase(name);
-
-    if (isDefined(value)) {
-      element.style[name] = value;
-    } else {
-      var val;
-
-      if (msie <= 8) {
-        // this is some IE specific weirdness that jQuery 1.6.4 does not sure why
-        val = element.currentStyle && element.currentStyle[name];
-        if (val === '') val = 'auto';
-      }
-
-      val = val || element.style[name];
-
-      if (msie <= 8) {
-        // jquery weirdness :-/
-        val = (val === '') ? undefined : val;
-      }
-
-      return  val;
-    }
-  },
-
-  attr: function(element, name, value){
-    var lowercasedName = lowercase(name);
-    if (BOOLEAN_ATTR[lowercasedName]) {
-      if (isDefined(value)) {
-        if (!!value) {
-          element[name] = true;
-          element.setAttribute(name, lowercasedName);
-        } else {
-          element[name] = false;
-          element.removeAttribute(lowercasedName);
-        }
-      } else {
-        return (element[name] ||
-                 (element.attributes.getNamedItem(name)|| noop).specified)
-               ? lowercasedName
-               : undefined;
-      }
-    } else 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
-      var ret = element.getAttribute(name, 2);
-      // normalize non-existing attributes to undefined (as jQuery)
-      return ret === null ? undefined : ret;
-    }
-  },
-
-  prop: function(element, name, value) {
-    if (isDefined(value)) {
-      element[name] = value;
-    } else {
-      return element[name];
-    }
-  },
-
-  text: (function() {
-    var NODE_TYPE_TEXT_PROPERTY = [];
-    if (msie < 9) {
-      NODE_TYPE_TEXT_PROPERTY[1] = 'innerText';    /** Element **/
-      NODE_TYPE_TEXT_PROPERTY[3] = 'nodeValue';    /** Text **/
-    } else {
-      NODE_TYPE_TEXT_PROPERTY[1] =                 /** Element **/
-      NODE_TYPE_TEXT_PROPERTY[3] = 'textContent';  /** Text **/
-    }
-    getText.$dv = '';
-    return getText;
-
-    function getText(element, value) {
-      var textProp = NODE_TYPE_TEXT_PROPERTY[element.nodeType];
-      if (isUndefined(value)) {
-        return textProp ? element[textProp] : '';
-      }
-      element[textProp] = value;
-    }
-  })(),
-
-  val: function(element, value) {
-    if (isUndefined(value)) {
-      if (nodeName_(element) === 'SELECT' && element.multiple) {
-        var result = [];
-        forEach(element.options, function (option) {
-          if (option.selected) {
-            result.push(option.value || option.text);
-          }
-        });
-        return result.length === 0 ? null : result;
-      }
-      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;
-  },
-
-  empty: jqLiteEmpty
-}, function(fn, name){
-  /**
-   * Properties: writes return selection, reads return first value
-   */
-  JQLite.prototype[name] = function(arg1, arg2) {
-    var i, key;
-
-    // jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
-    // in a way that survives minification.
-    // jqLiteEmpty takes no arguments but is a setter.
-    if (fn !== jqLiteEmpty &&
-        (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
-      if (isObject(arg1)) {
-
-        // we are a write, but the object properties are the key/values
-        for (i = 0; i < this.length; i++) {
-          if (fn === jqLiteData) {
-            // data() takes the whole object in jQuery
-            fn(this[i], arg1);
-          } else {
-            for (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.
-        var value = fn.$dv;
-        // Only if we have $dv do we iterate over all, otherwise it is just the first element.
-        var jj = (value === undefined) ? Math.min(this.length, 1) : this.length;
-        for (var j = 0; j < jj; j++) {
-          var nodeValue = fn(this[j], arg1, arg2);
-          value = value ? value + nodeValue : nodeValue;
-        }
-        return value;
-      }
-    } else {
-      // we are a write, so apply to all children
-      for (i = 0; i < this.length; i++) {
-        fn(this[i], arg1, arg2);
-      }
-      // return self for chaining
-      return this;
-    }
-  };
-});
-
-function createEventHandler(element, events) {
-  var eventHandler = function (event, type) {
-    if (!event.preventDefault) {
-      event.preventDefault = function() {
-        event.returnValue = false; //ie
-      };
-    }
-
-    if (!event.stopPropagation) {
-      event.stopPropagation = function() {
-        event.cancelBubble = true; //ie
-      };
-    }
-
-    if (!event.target) {
-      event.target = event.srcElement || document;
-    }
-
-    if (isUndefined(event.defaultPrevented)) {
-      var prevent = event.preventDefault;
-      event.preventDefault = function() {
-        event.defaultPrevented = true;
-        prevent.call(event);
-      };
-      event.defaultPrevented = false;
-    }
-
-    event.isDefaultPrevented = function() {
-      return event.defaultPrevented || event.returnValue === false;
-    };
-
-    forEach(events[type || event.type], function(fn) {
-      fn.call(element, event);
-    });
-
-    // Remove monkey-patched methods (IE),
-    // as they would cause memory leaks in IE8.
-    if (msie <= 8) {
-      // IE7/8 does not allow to delete property on native object
-      event.preventDefault = null;
-      event.stopPropagation = null;
-      event.isDefaultPrevented = null;
-    } else {
-      // It shouldn't affect normal browsers (native methods are defined on prototype).
-      delete event.preventDefault;
-      delete event.stopPropagation;
-      delete event.isDefaultPrevented;
-    }
-  };
-  eventHandler.elem = element;
-  return eventHandler;
-}
-
-//////////////////////////////////////////
-// Functions iterating traversal.
-// These functions chain results into a single
-// selector.
-//////////////////////////////////////////
-forEach({
-  removeData: jqLiteRemoveData,
-
-  dealoc: jqLiteDealoc,
-
-  on: function onFn(element, type, fn, unsupported){
-    if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
-
-    var events = jqLiteExpandoStore(element, 'events'),
-        handle = jqLiteExpandoStore(element, 'handle');
-
-    if (!events) jqLiteExpandoStore(element, 'events', events = {});
-    if (!handle) jqLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));
-
-    forEach(type.split(' '), function(type){
-      var eventFns = events[type];
-
-      if (!eventFns) {
-        if (type == 'mouseenter' || type == 'mouseleave') {
-          var contains = document.body.contains || document.body.compareDocumentPosition ?
-          function( a, b ) {
-            // jshint bitwise: false
-            var adown = a.nodeType === 9 ? a.documentElement : a,
-            bup = b && b.parentNode;
-            return a === bup || !!( bup && bup.nodeType === 1 && (
-              adown.contains ?
-              adown.contains( bup ) :
-              a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
-              ));
-            } :
-            function( a, b ) {
-              if ( b ) {
-                while ( (b = b.parentNode) ) {
-                  if ( b === a ) {
-                    return true;
-                  }
-                }
-              }
-              return false;
-            };
-
-          events[type] = [];
-
-          // Refer to jQuery's implementation of mouseenter & mouseleave
-          // Read about mouseenter and mouseleave:
-          // http://www.quirksmode.org/js/events_mouse.html#link8
-          var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"};
-
-          onFn(element, eventmap[type], function(event) {
-            var target = this, related = event.relatedTarget;
-            // For mousenter/leave call the handler if related is outside the target.
-            // NB: No relatedTarget if the mouse left/entered the browser window
-            if ( !related || (related !== target && !contains(target, related)) ){
-              handle(event, type);
-            }
-          });
-
-        } else {
-          addEventListenerFn(element, type, handle);
-          events[type] = [];
-        }
-        eventFns = events[type];
-      }
-      eventFns.push(fn);
-    });
-  },
-
-  off: jqLiteOff,
-
-  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(element) {
-    var children = [];
-    forEach(element.childNodes, function(element){
-      if (element.nodeType === 1)
-        children.push(element);
-    });
-    return children;
-  },
-
-  contents: function(element) {
-    return element.childNodes || [];
-  },
-
-  append: function(element, node) {
-    forEach(new JQLite(node), function(child){
-      if (element.nodeType === 1 || element.nodeType === 11) {
-        element.appendChild(child);
-      }
-    });
-  },
-
-  prepend: function(element, node) {
-    if (element.nodeType === 1) {
-      var index = element.firstChild;
-      forEach(new JQLite(node), function(child){
-        element.insertBefore(child, index);
-      });
-    }
-  },
-
-  wrap: function(element, wrapNode) {
-    wrapNode = jqLite(wrapNode)[0];
-    var parent = element.parentNode;
-    if (parent) {
-      parent.replaceChild(wrapNode, element);
-    }
-    wrapNode.appendChild(element);
-  },
-
-  remove: function(element) {
-    jqLiteDealoc(element);
-    var parent = element.parentNode;
-    if (parent) parent.removeChild(element);
-  },
-
-  after: function(element, newElement) {
-    var index = element, parent = element.parentNode;
-    forEach(new JQLite(newElement), function(node){
-      parent.insertBefore(node, index.nextSibling);
-      index = node;
-    });
-  },
-
-  addClass: jqLiteAddClass,
-  removeClass: jqLiteRemoveClass,
-
-  toggleClass: function(element, selector, condition) {
-    if (isUndefined(condition)) {
-      condition = !jqLiteHasClass(element, selector);
-    }
-    (condition ? jqLiteAddClass : jqLiteRemoveClass)(element, selector);
-  },
-
-  parent: function(element) {
-    var parent = element.parentNode;
-    return parent && parent.nodeType !== 11 ? parent : null;
-  },
-
-  next: function(element) {
-    if (element.nextElementSibling) {
-      return element.nextElementSibling;
-    }
-
-    // IE8 doesn't have nextElementSibling
-    var elm = element.nextSibling;
-    while (elm != null && elm.nodeType !== 1) {
-      elm = elm.nextSibling;
-    }
-    return elm;
-  },
-
-  find: function(element, selector) {
-    if (element.getElementsByTagName) {
-      return element.getElementsByTagName(selector);
-    } else {
-      return [];
-    }
-  },
-
-  clone: jqLiteClone,
-
-  triggerHandler: function(element, eventName, eventData) {
-    var eventFns = (jqLiteExpandoStore(element, 'events') || {})[eventName];
-
-    eventData = eventData || [];
-
-    var event = [{
-      preventDefault: noop,
-      stopPropagation: noop
-    }];
-
-    forEach(eventFns, function(fn) {
-      fn.apply(element, event.concat(eventData));
-    });
-  }
-}, function(fn, name){
-  /**
-   * chaining functions
-   */
-  JQLite.prototype[name] = function(arg1, arg2, arg3) {
-    var value;
-    for(var i=0; i < this.length; i++) {
-      if (isUndefined(value)) {
-        value = fn(this[i], arg1, arg2, arg3);
-        if (isDefined(value)) {
-          // any function which returns a value needs to be wrapped
-          value = jqLite(value);
-        }
-      } else {
-        jqLiteAddNodes(value, fn(this[i], arg1, arg2, arg3));
-      }
-    }
-    return isDefined(value) ? value : this;
-  };
-
-  // bind legacy bind/unbind to on/off
-  JQLite.prototype.bind = JQLite.prototype.on;
-  JQLite.prototype.unbind = JQLite.prototype.off;
-});
-
-/**
- * Computes a hash of an 'obj'.
- * Hash of a:
- *  string is string
- *  number is number as string
- *  object is either result of calling $$hashKey function on the object or uniquely generated id,
- *         that is also assigned to the $$hashKey property of the object.
- *
- * @param obj
- * @returns {string} hash string such that the same input will have the same hash string.
- *         The resulting string key is in 'type:hashKey' format.
- */
-function hashKey(obj) {
-  var objType = typeof obj,
-      key;
-
-  if (objType == 'object' && obj !== null) {
-    if (typeof (key = obj.$$hashKey) == 'function') {
-      // must invoke on object to keep the right this
-      key = obj.$$hashKey();
-    } else if (key === undefined) {
-      key = obj.$$hashKey = nextUid();
-    }
-  } else {
-    key = obj;
-  }
-
-  return objType + ':' + key;
-}
-
-/**
- * HashMap which can use objects as keys
- */
-function HashMap(array){
-  forEach(array, this.put, this);
-}
-HashMap.prototype = {
-  /**
-   * Store key value pair
-   * @param key key to store can be any type
-   * @param value value to store can be any type
-   */
-  put: function(key, value) {
-    this[hashKey(key)] = value;
-  },
-
-  /**
-   * @param key
-   * @returns the value for the key
-   */
-  get: function(key) {
-    return this[hashKey(key)];
-  },
-
-  /**
-   * Remove the key/value pair
-   * @param key
-   */
-  remove: function(key) {
-    var value = this[key = hashKey(key)];
-    delete this[key];
-    return value;
-  }
-};
-
-/**
- * @ngdoc function
- * @name angular.injector
- * @function
- *
- * @description
- * Creates an injector function that can be used for retrieving services as well as for
- * dependency injection (see {@link guide/di dependency injection}).
- *
-
- * @param {Array.<string|Function>} modules A list of module functions or their aliases. See
- *        {@link angular.module}. The `ng` module must be explicitly added.
- * @returns {function()} Injector function. See {@link AUTO.$injector $injector}.
- *
- * @example
- * Typical usage
- * <pre>
- *   // create an injector
- *   var $injector = angular.injector(['ng']);
- *
- *   // use the injector to kick off your application
- *   // use the type inference to auto inject arguments, or use implicit injection
- *   $injector.invoke(function($rootScope, $compile, $document){
- *     $compile($document)($rootScope);
- *     $rootScope.$digest();
- *   });
- * </pre>
- *
- * Sometimes you want to get access to the injector of a currently running Angular app
- * from outside Angular. Perhaps, you want to inject and compile some markup after the
- * application has been bootstrapped. You can do this using extra `injector()` added
- * to JQuery/jqLite elements. See {@link angular.element}.
- *
- * *This is fairly rare but could be the case if a third party library is injecting the
- * markup.*
- *
- * In the following example a new block of HTML containing a `ng-controller`
- * directive is added to the end of the document body by JQuery. We then compile and link
- * it into the current AngularJS scope.
- *
- * <pre>
- * var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
- * $(document.body).append($div);
- *
- * angular.element(document).injector().invoke(function($compile) {
- *   var scope = angular.element($div).scope();
- *   $compile($div)(scope);
- * });
- * </pre>
- */
-
-
-/**
- * @ngdoc overview
- * @name AUTO
- * @description
- *
- * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}.
- */
-
-var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
-var FN_ARG_SPLIT = /,/;
-var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
-var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
-var $injectorMinErr = minErr('$injector');
-function annotate(fn) {
-  var $inject,
-      fnText,
-      argDecl,
-      last;
-
-  if (typeof fn == 'function') {
-    if (!($inject = fn.$inject)) {
-      $inject = [];
-      if (fn.length) {
-        fnText = fn.toString().replace(STRIP_COMMENTS, '');
-        argDecl = fnText.match(FN_ARGS);
-        forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
-          arg.replace(FN_ARG, function(all, underscore, name){
-            $inject.push(name);
-          });
-        });
-      }
-      fn.$inject = $inject;
-    }
-  } else if (isArray(fn)) {
-    last = fn.length - 1;
-    assertArgFn(fn[last], 'fn');
-    $inject = fn.slice(0, last);
-  } else {
-    assertArgFn(fn, 'fn', true);
-  }
-  return $inject;
-}
-
-///////////////////////////////////////
-
-/**
- * @ngdoc object
- * @name AUTO.$injector
- * @function
- *
- * @description
- *
- * `$injector` is used to retrieve object instances as defined by
- * {@link AUTO.$provide provider}, instantiate types, invoke methods,
- * and load modules.
- *
- * The following always holds true:
- *
- * <pre>
- *   var $injector = angular.injector();
- *   expect($injector.get('$injector')).toBe($injector);
- *   expect($injector.invoke(function($injector){
- *     return $injector;
- *   }).toBe($injector);
- * </pre>
- *
- * # Injection Function Annotation
- *
- * JavaScript does not have annotations, and annotations are needed for dependency injection. The
- * following are all valid ways of annotating function with injection arguments and are equivalent.
- *
- * <pre>
- *   // inferred (only works if code not minified/obfuscated)
- *   $injector.invoke(function(serviceA){});
- *
- *   // annotated
- *   function explicit(serviceA) {};
- *   explicit.$inject = ['serviceA'];
- *   $injector.invoke(explicit);
- *
- *   // inline
- *   $injector.invoke(['serviceA', function(serviceA){}]);
- * </pre>
- *
- * ## Inference
- *
- * In JavaScript calling `toString()` on a function returns the function definition. The definition
- * can then be parsed and the function arguments can be extracted. *NOTE:* This does not work with
- * minification, and obfuscation tools since these tools change the argument names.
- *
- * ## `$inject` Annotation
- * By adding a `$inject` property onto a function the injection parameters can be specified.
- *
- * ## Inline
- * As an array of injection names, where the last item in the array is the function to call.
- */
-
-/**
- * @ngdoc method
- * @name AUTO.$injector#get
- * @methodOf AUTO.$injector
- *
- * @description
- * Return an instance of the service.
- *
- * @param {string} name The name of the instance to retrieve.
- * @return {*} The instance.
- */
-
-/**
- * @ngdoc method
- * @name AUTO.$injector#invoke
- * @methodOf AUTO.$injector
- *
- * @description
- * Invoke the method and supply the method arguments from the `$injector`.
- *
- * @param {!function} fn The function to invoke. Function parameters are injected according to the
- *   {@link guide/di $inject Annotation} rules.
- * @param {Object=} self The `this` for the invoked method.
- * @param {Object=} locals Optional object. If preset then any argument names are read from this
- *                         object first, before the `$injector` is consulted.
- * @returns {*} the value returned by the invoked `fn` function.
- */
-
-/**
- * @ngdoc method
- * @name AUTO.$injector#has
- * @methodOf AUTO.$injector
- *
- * @description
- * Allows the user to query if the particular service exist.
- *
- * @param {string} Name of the service to query.
- * @returns {boolean} returns true if injector has given service.
- */
-
-/**
- * @ngdoc method
- * @name AUTO.$injector#instantiate
- * @methodOf AUTO.$injector
- * @description
- * Create a new instance of JS type. The method takes a constructor function invokes the new
- * operator and supplies all of the arguments to the constructor function as specified by the
- * constructor annotation.
- *
- * @param {function} Type Annotated constructor function.
- * @param {Object=} locals Optional object. If preset then any argument names are read from this
- * object first, before the `$injector` is consulted.
- * @returns {Object} new instance of `Type`.
- */
-
-/**
- * @ngdoc method
- * @name AUTO.$injector#annotate
- * @methodOf AUTO.$injector
- *
- * @description
- * Returns an array of service names which the function is requesting for injection. This API is
- * used by the injector to determine which services need to be injected into the function when the
- * function is invoked. There are three ways in which the function can be annotated with the needed
- * dependencies.
- *
- * # Argument names
- *
- * The simplest form is to extract the dependencies from the arguments of the function. This is done
- * by converting the function into a string using `toString()` method and extracting the argument
- * names.
- * <pre>
- *   // Given
- *   function MyController($scope, $route) {
- *     // ...
- *   }
- *
- *   // Then
- *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
- * </pre>
- *
- * This method does not work with code minification / obfuscation. For this reason the following
- * annotation strategies are supported.
- *
- * # The `$inject` property
- *
- * If a function has an `$inject` property and its value is an array of strings, then the strings
- * represent names of services to be injected into the function.
- * <pre>
- *   // Given
- *   var MyController = function(obfuscatedScope, obfuscatedRoute) {
- *     // ...
- *   }
- *   // Define function dependencies
- *   MyController['$inject'] = ['$scope', '$route'];
- *
- *   // Then
- *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
- * </pre>
- *
- * # The array notation
- *
- * It is often desirable to inline Injected functions and that's when setting the `$inject` property
- * is very inconvenient. In these situations using the array notation to specify the dependencies in
- * a way that survives minification is a better choice:
- *
- * <pre>
- *   // We wish to write this (not minification / obfuscation safe)
- *   injector.invoke(function($compile, $rootScope) {
- *     // ...
- *   });
- *
- *   // We are forced to write break inlining
- *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
- *     // ...
- *   };
- *   tmpFn.$inject = ['$compile', '$rootScope'];
- *   injector.invoke(tmpFn);
- *
- *   // To better support inline function the inline annotation is supported
- *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
- *     // ...
- *   }]);
- *
- *   // Therefore
- *   expect(injector.annotate(
- *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
- *    ).toEqual(['$compile', '$rootScope']);
- * </pre>
- *
- * @param {function|Array.<string|Function>} fn Function for which dependent service names need to
- * be retrieved as described above.
- *
- * @returns {Array.<string>} The names of the services which the function requires.
- */
-
-
-
-
-/**
- * @ngdoc object
- * @name AUTO.$provide
- *
- * @description
- *
- * The {@link AUTO.$provide $provide} service has a number of methods for registering components
- * with the {@link AUTO.$injector $injector}. Many of these functions are also exposed on
- * {@link angular.Module}.
- *
- * An Angular **service** is a singleton object created by a **service factory**.  These **service
- * factories** are functions which, in turn, are created by a **service provider**.
- * The **service providers** are constructor functions. When instantiated they must contain a
- * property called `$get`, which holds the **service factory** function.
- *
- * When you request a service, the {@link AUTO.$injector $injector} is responsible for finding the
- * correct **service provider**, instantiating it and then calling its `$get` **service factory**
- * function to get the instance of the **service**.
- *
- * Often services have no configuration options and there is no need to add methods to the service
- * provider.  The provider will be no more than a constructor function with a `$get` property. For
- * these cases the {@link AUTO.$provide $provide} service has additional helper methods to register
- * services without specifying a provider.
- *
- * * {@link AUTO.$provide#methods_provider provider(provider)} - registers a **service provider** with the
- *     {@link AUTO.$injector $injector}
- * * {@link AUTO.$provide#methods_constant constant(obj)} - registers a value/object that can be accessed by
- *     providers and services.
- * * {@link AUTO.$provide#methods_value value(obj)} - registers a value/object that can only be accessed by
- *     services, not providers.
- * * {@link AUTO.$provide#methods_factory factory(fn)} - registers a service **factory function**, `fn`,
- *     that will be wrapped in a **service provider** object, whose `$get` property will contain the
- *     given factory function.
- * * {@link AUTO.$provide#methods_service service(class)} - registers a **constructor function**, `class` that
- *     that will be wrapped in a **service provider** object, whose `$get` property will instantiate
- *      a new object using the given constructor function.
- *
- * See the individual methods for more information and examples.
- */
-
-/**
- * @ngdoc method
- * @name AUTO.$provide#provider
- * @methodOf AUTO.$provide
- * @description
- *
- * Register a **provider function** with the {@link AUTO.$injector $injector}. Provider functions
- * are constructor functions, whose instances are responsible for "providing" a factory for a
- * service.
- *
- * Service provider names start with the name of the service they provide followed by `Provider`.
- * For example, the {@link ng.$log $log} service has a provider called
- * {@link ng.$logProvider $logProvider}.
- *
- * Service provider objects can have additional methods which allow configuration of the provider
- * and its service. Importantly, you can configure what kind of service is created by the `$get`
- * method, or how that service will act. For example, the {@link ng.$logProvider $logProvider} has a
- * method {@link ng.$logProvider#debugEnabled debugEnabled}
- * which lets you specify whether the {@link ng.$log $log} service will log debug messages to the
- * console or not.
- *
- * @param {string} name The name of the instance. NOTE: the provider will be available under `name +
-                        'Provider'` key.
- * @param {(Object|function())} provider If the provider is:
- *
- *   - `Object`: then it should have a `$get` method. The `$get` method will be invoked using
- *               {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be
- *               created.
- *   - `Constructor`: a new instance of the provider will be created using
- *               {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as
- *               `object`.
- *
- * @returns {Object} registered provider instance
-
- * @example
- *
- * The following example shows how to create a simple event tracking service and register it using
- * {@link AUTO.$provide#methods_provider $provide.provider()}.
- *
- * <pre>
- *  // Define the eventTracker provider
- *  function EventTrackerProvider() {
- *    var trackingUrl = '/track';
- *
- *    // A provider method for configuring where the tracked events should been saved
- *    this.setTrackingUrl = function(url) {
- *      trackingUrl = url;
- *    };
- *
- *    // The service factory function
- *    this.$get = ['$http', function($http) {
- *      var trackedEvents = {};
- *      return {
- *        // Call this to track an event
- *        event: function(event) {
- *          var count = trackedEvents[event] || 0;
- *          count += 1;
- *          trackedEvents[event] = count;
- *          return count;
- *        },
- *        // Call this to save the tracked events to the trackingUrl
- *        save: function() {
- *          $http.post(trackingUrl, trackedEvents);
- *        }
- *      };
- *    }];
- *  }
- *
- *  describe('eventTracker', function() {
- *    var postSpy;
- *
- *    beforeEach(module(function($provide) {
- *      // Register the eventTracker provider
- *      $provide.provider('eventTracker', EventTrackerProvider);
- *    }));
- *
- *    beforeEach(module(function(eventTrackerProvider) {
- *      // Configure eventTracker provider
- *      eventTrackerProvider.setTrackingUrl('/custom-track');
- *    }));
- *
- *    it('tracks events', inject(function(eventTracker) {
- *      expect(eventTracker.event('login')).toEqual(1);
- *      expect(eventTracker.event('login')).toEqual(2);
- *    }));
- *
- *    it('saves to the tracking url', inject(function(eventTracker, $http) {
- *      postSpy = spyOn($http, 'post');
- *      eventTracker.event('login');
- *      eventTracker.save();
- *      expect(postSpy).toHaveBeenCalled();
- *      expect(postSpy.mostRecentCall.args[0]).not.toEqual('/track');
- *      expect(postSpy.mostRecentCall.args[0]).toEqual('/custom-track');
- *      expect(postSpy.mostRecentCall.args[1]).toEqual({ 'login': 1 });
- *    }));
- *  });
- * </pre>
- */
-
-/**
- * @ngdoc method
- * @name AUTO.$provide#factory
- * @methodOf AUTO.$provide
- * @description
- *
- * Register a **service factory**, which will be called to return the service instance.
- * This is short for registering a service where its provider consists of only a `$get` property,
- * which is the given service factory function.
- * You should use {@link AUTO.$provide#factory $provide.factory(getFn)} if you do not need to
- * configure your service in a provider.
- *
- * @param {string} name The name of the instance.
- * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand
- *                            for `$provide.provider(name, {$get: $getFn})`.
- * @returns {Object} registered provider instance
- *
- * @example
- * Here is an example of registering a service
- * <pre>
- *   $provide.factory('ping', ['$http', function($http) {
- *     return function ping() {
- *       return $http.send('/ping');
- *     };
- *   }]);
- * </pre>
- * You would then inject and use this service like this:
- * <pre>
- *   someModule.controller('Ctrl', ['ping', function(ping) {
- *     ping();
- *   }]);
- * </pre>
- */
-
-
-/**
- * @ngdoc method
- * @name AUTO.$provide#service
- * @methodOf AUTO.$provide
- * @description
- *
- * Register a **service constructor**, which will be invoked with `new` to create the service
- * instance.
- * This is short for registering a service where its provider's `$get` property is the service
- * constructor function that will be used to instantiate the service instance.
- *
- * You should use {@link AUTO.$provide#methods_service $provide.service(class)} if you define your service
- * as a type/class. This is common when using {@link http://coffeescript.org CoffeeScript}.
- *
- * @param {string} name The name of the instance.
- * @param {Function} constructor A class (constructor function) that will be instantiated.
- * @returns {Object} registered provider instance
- *
- * @example
- * Here is an example of registering a service using
- * {@link AUTO.$provide#methods_service $provide.service(class)} that is defined as a CoffeeScript class.
- * <pre>
- *   class Ping
- *     constructor: (@$http)->
- *     send: ()=>
- *       @$http.get('/ping')
- *
- *   $provide.service('ping', ['$http', Ping])
- * </pre>
- * You would then inject and use this service like this:
- * <pre>
- *   someModule.controller 'Ctrl', ['ping', (ping)->
- *     ping.send()
- *   ]
- * </pre>
- */
-
-
-/**
- * @ngdoc method
- * @name AUTO.$provide#value
- * @methodOf AUTO.$provide
- * @description
- *
- * Register a **value service** with the {@link AUTO.$injector $injector}, such as a string, a
- * number, an array, an object or a function.  This is short for registering a service where its
- * provider's `$get` property is a factory function that takes no arguments and returns the **value
- * service**.
- *
- * Value services are similar to constant services, except that they cannot be injected into a
- * module configuration function (see {@link angular.Module#config}) but they can be overridden by
- * an Angular
- * {@link AUTO.$provide#decorator decorator}.
- *
- * @param {string} name The name of the instance.
- * @param {*} value The value.
- * @returns {Object} registered provider instance
- *
- * @example
- * Here are some examples of creating value services.
- * <pre>
- *   $provide.value('ADMIN_USER', 'admin');
- *
- *   $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
- *
- *   $provide.value('halfOf', function(value) {
- *     return value / 2;
- *   });
- * </pre>
- */
-
-
-/**
- * @ngdoc method
- * @name AUTO.$provide#constant
- * @methodOf AUTO.$provide
- * @description
- *
- * Register a **constant service**, such as a string, a number, an array, an object or a function,
- * with the {@link AUTO.$injector $injector}. Unlike {@link AUTO.$provide#value value} it can be
- * injected into a module configuration function (see {@link angular.Module#config}) and it cannot
- * be overridden by an Angular {@link AUTO.$provide#decorator decorator}.
- *
- * @param {string} name The name of the constant.
- * @param {*} value The constant value.
- * @returns {Object} registered instance
- *
- * @example
- * Here a some examples of creating constants:
- * <pre>
- *   $provide.constant('SHARD_HEIGHT', 306);
- *
- *   $provide.constant('MY_COLOURS', ['red', 'blue', 'grey']);
- *
- *   $provide.constant('double', function(value) {
- *     return value * 2;
- *   });
- * </pre>
- */
-
-
-/**
- * @ngdoc method
- * @name AUTO.$provide#decorator
- * @methodOf AUTO.$provide
- * @description
- *
- * Register a **service decorator** with the {@link AUTO.$injector $injector}. A service decorator
- * intercepts the creation of a service, allowing it to override or modify the behaviour of the
- * service. The object returned by the decorator may be the original service, or a new service
- * object which replaces or wraps and delegates to the original service.
- *
- * @param {string} name The name of the service to decorate.
- * @param {function()} decorator This function will be invoked when the service needs to be
- *    instantiated and should return the decorated service instance. The function is called using
- *    the {@link AUTO.$injector#invoke injector.invoke} method and is therefore fully injectable.
- *    Local injection arguments:
- *
- *    * `$delegate` - The original service instance, which can be monkey patched, configured,
- *      decorated or delegated to.
- *
- * @example
- * Here we decorate the {@link ng.$log $log} service to convert warnings to errors by intercepting
- * calls to {@link ng.$log#error $log.warn()}.
- * <pre>
- *   $provider.decorator('$log', ['$delegate', function($delegate) {
- *     $delegate.warn = $delegate.error;
- *     return $delegate;
- *   }]);
- * </pre>
- */
-
-
-function createInjector(modulesToLoad) {
-  var INSTANTIATING = {},
-      providerSuffix = 'Provider',
-      path = [],
-      loadedModules = new HashMap(),
-      providerCache = {
-        $provide: {
-            provider: supportObject(provider),
-            factory: supportObject(factory),
-            service: supportObject(service),
-            value: supportObject(value),
-            constant: supportObject(constant),
-            decorator: decorator
-          }
-      },
-      providerInjector = (providerCache.$injector =
-          createInternalInjector(providerCache, function() {
-            throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
-          })),
-      instanceCache = {},
-      instanceInjector = (instanceCache.$injector =
-          createInternalInjector(instanceCache, function(servicename) {
-            var provider = providerInjector.get(servicename + providerSuffix);
-            return instanceInjector.invoke(provider.$get, provider);
-          }));
-
-
-  forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
-
-  return instanceInjector;
-
-  ////////////////////////////////////
-  // $provider
-  ////////////////////////////////////
-
-  function supportObject(delegate) {
-    return function(key, value) {
-      if (isObject(key)) {
-        forEach(key, reverseParams(delegate));
-      } else {
-        return delegate(key, value);
-      }
-    };
-  }
-
-  function provider(name, provider_) {
-    assertNotHasOwnProperty(name, 'service');
-    if (isFunction(provider_) || isArray(provider_)) {
-      provider_ = providerInjector.instantiate(provider_);
-    }
-    if (!provider_.$get) {
-      throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name);
-    }
-    return providerCache[name + providerSuffix] = provider_;
-  }
-
-  function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
-
-  function service(name, constructor) {
-    return factory(name, ['$injector', function($injector) {
-      return $injector.instantiate(constructor);
-    }]);
-  }
-
-  function value(name, val) { return factory(name, valueFn(val)); }
-
-  function constant(name, value) {
-    assertNotHasOwnProperty(name, 'constant');
-    providerCache[name] = value;
-    instanceCache[name] = value;
-  }
-
-  function decorator(serviceName, decorFn) {
-    var origProvider = providerInjector.get(serviceName + providerSuffix),
-        orig$get = origProvider.$get;
-
-    origProvider.$get = function() {
-      var origInstance = instanceInjector.invoke(orig$get, origProvider);
-      return instanceInjector.invoke(decorFn, null, {$delegate: origInstance});
-    };
-  }
-
-  ////////////////////////////////////
-  // Module Loading
-  ////////////////////////////////////
-  function loadModules(modulesToLoad){
-    var runBlocks = [], moduleFn, invokeQueue, i, ii;
-    forEach(modulesToLoad, function(module) {
-      if (loadedModules.get(module)) return;
-      loadedModules.put(module, true);
-
-      try {
-        if (isString(module)) {
-          moduleFn = angularModule(module);
-          runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
-
-          for(invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
-            var invokeArgs = invokeQueue[i],
-                provider = providerInjector.get(invokeArgs[0]);
-
-            provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
-          }
-        } else if (isFunction(module)) {
-            runBlocks.push(providerInjector.invoke(module));
-        } else if (isArray(module)) {
-            runBlocks.push(providerInjector.invoke(module));
-        } else {
-          assertArgFn(module, 'module');
-        }
-      } catch (e) {
-        if (isArray(module)) {
-          module = module[module.length - 1];
-        }
-        if (e.message && e.stack && e.stack.indexOf(e.message) == -1) {
-          // Safari & FF's stack traces don't contain error.message content
-          // unlike those of Chrome and IE
-          // So if stack doesn't contain message, we create a new string that contains both.
-          // Since error.stack is read-only in Safari, I'm overriding e and not e.stack here.
-          /* jshint -W022 */
-          e = e.message + '\n' + e.stack;
-        }
-        throw $injectorMinErr('modulerr', "Failed to instantiate module {0} due to:\n{1}",
-                  module, e.stack || e.message || e);
-      }
-    });
-    return runBlocks;
-  }
-
-  ////////////////////////////////////
-  // internal Injector
-  ////////////////////////////////////
-
-  function createInternalInjector(cache, factory) {
-
-    function getService(serviceName) {
-      if (cache.hasOwnProperty(serviceName)) {
-        if (cache[serviceName] === INSTANTIATING) {
-          throw $injectorMinErr('cdep', 'Circular dependency found: {0}', path.join(' <- '));
-        }
-        return cache[serviceName];
-      } else {
-        try {
-          path.unshift(serviceName);
-          cache[serviceName] = INSTANTIATING;
-          return cache[serviceName] = factory(serviceName);
-        } finally {
-          path.shift();
-        }
-      }
-    }
-
-    function invoke(fn, self, locals){
-      var args = [],
-          $inject = annotate(fn),
-          length, i,
-          key;
-
-      for(i = 0, length = $inject.length; i < length; i++) {
-        key = $inject[i];
-        if (typeof key !== 'string') {
-          throw $injectorMinErr('itkn',
-                  'Incorrect injection token! Expected service name as string, got {0}', key);
-        }
-        args.push(
-          locals && locals.hasOwnProperty(key)
-          ? locals[key]
-          : getService(key)
-        );
-      }
-      if (!fn.$inject) {
-        // this means that we must be an array.
-        fn = fn[length];
-      }
-
-      // http://jsperf.com/angularjs-invoke-apply-vs-switch
-      // #5388
-      return fn.apply(self, args);
-    }
-
-    function instantiate(Type, locals) {
-      var Constructor = function() {},
-          instance, returnedValue;
-
-      // Check if Type is annotated and use just the given function at n-1 as parameter
-      // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
-      Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
-      instance = new Constructor();
-      returnedValue = invoke(Type, instance, locals);
-
-      return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
-    }
-
-    return {
-      invoke: invoke,
-      instantiate: instantiate,
-      get: getService,
-      annotate: annotate,
-      has: function(name) {
-        return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name);
-      }
-    };
-  }
-}
-
-/**
- * @ngdoc function
- * @name ng.$anchorScroll
- * @requires $window
- * @requires $location
- * @requires $rootScope
- *
- * @description
- * When called, it checks current value of `$location.hash()` and scroll to related element,
- * according to rules specified in
- * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}.
- *
- * It also watches the `$location.hash()` and scrolls whenever it changes to match any anchor.
- * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
- * 
- * @example
-   <example>
-     <file name="index.html">
-       <div id="scrollArea" ng-controller="ScrollCtrl">
-         <a ng-click="gotoBottom()">Go to bottom</a>
-         <a id="bottom"></a> You're at the bottom!
-       </div>
-     </file>
-     <file name="script.js">
-       function ScrollCtrl($scope, $location, $anchorScroll) {
-         $scope.gotoBottom = function (){
-           // set the location.hash to the id of
-           // the element you wish to scroll to.
-           $location.hash('bottom');
-           
-           // call $anchorScroll()
-           $anchorScroll();
-         }
-       }
-     </file>
-     <file name="style.css">
-       #scrollArea {
-         height: 350px;
-         overflow: auto;
-       }
-
-       #bottom {
-         display: block;
-         margin-top: 2000px;
-       }
-     </file>
-   </example>
- */
-function $AnchorScrollProvider() {
-
-  var autoScrollingEnabled = true;
-
-  this.disableAutoScrolling = function() {
-    autoScrollingEnabled = false;
-  };
-
-  this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {
-    var document = $window.document;
-
-    // helper function to get first anchor from a NodeList
-    // can't use filter.filter, as it accepts only instances of Array
-    // and IE can't convert NodeList to an array using [].slice
-    // TODO(vojta): use filter if we change it to accept lists as well
-    function getFirstAnchor(list) {
-      var result = null;
-      forEach(list, function(element) {
-        if (!result && lowercase(element.nodeName) === 'a') result = element;
-      });
-      return result;
-    }
-
-    function scroll() {
-      var hash = $location.hash(), elm;
-
-      // empty hash, scroll to the top of the page
-      if (!hash) $window.scrollTo(0, 0);
-
-      // element with given id
-      else if ((elm = document.getElementById(hash))) elm.scrollIntoView();
-
-      // first anchor with given name :-D
-      else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView();
-
-      // no element and hash == 'top', scroll to the top of the page
-      else if (hash === 'top') $window.scrollTo(0, 0);
-    }
-
-    // does not scroll when user clicks on anchor link that is currently on
-    // (no url change, no $location.hash() change), browser native does scroll
-    if (autoScrollingEnabled) {
-      $rootScope.$watch(function autoScrollWatch() {return $location.hash();},
-        function autoScrollWatchAction() {
-          $rootScope.$evalAsync(scroll);
-        });
-    }
-
-    return scroll;
-  }];
-}
-
-var $animateMinErr = minErr('$animate');
-
-/**
- * @ngdoc object
- * @name ng.$animateProvider
- *
- * @description
- * Default implementation of $animate that doesn't perform any animations, instead just
- * synchronously performs DOM
- * updates and calls done() callbacks.
- *
- * In order to enable animations the ngAnimate module has to be loaded.
- *
- * To see the functional implementation check out src/ngAnimate/animate.js
- */
-var $AnimateProvider = ['$provide', function($provide) {
-
-  
-  this.$$selectors = {};
-
-
-  /**
-   * @ngdoc function
-   * @name ng.$animateProvider#register
-   * @methodOf ng.$animateProvider
-   *
-   * @description
-   * Registers a new injectable animation factory function. The factory function produces the
-   * animation object which contains callback functions for each event that is expected to be
-   * animated.
-   *
-   *   * `eventFn`: `function(Element, doneFunction)` The element to animate, the `doneFunction`
-   *   must be called once the element animation is complete. If a function is returned then the
-   *   animation service will use this function to cancel the animation whenever a cancel event is
-   *   triggered.
-   *
-   *
-   *<pre>
-   *   return {
-     *     eventFn : function(element, done) {
-     *       //code to run the animation
-     *       //once complete, then run done()
-     *       return function cancellationFunction() {
-     *         //code to cancel the animation
-     *       }
-     *     }
-     *   }
-   *</pre>
-   *
-   * @param {string} name The name of the animation.
-   * @param {function} factory The factory function that will be executed to return the animation
-   *                           object.
-   */
-  this.register = function(name, factory) {
-    var key = name + '-animation';
-    if (name && name.charAt(0) != '.') throw $animateMinErr('notcsel',
-        "Expecting class selector starting with '.' got '{0}'.", name);
-    this.$$selectors[name.substr(1)] = key;
-    $provide.factory(key, factory);
-  };
-
-  this.$get = ['$timeout', function($timeout) {
-
-    /**
-     *
-     * @ngdoc object
-     * @name ng.$animate
-     * @description The $animate service provides rudimentary DOM manipulation functions to
-     * insert, remove and move elements within the DOM, as well as adding and removing classes.
-     * This service is the core service used by the ngAnimate $animator service which provides
-     * high-level animation hooks for CSS and JavaScript.
-     *
-     * $animate is available in the AngularJS core, however, the ngAnimate module must be included
-     * to enable full out animation support. Otherwise, $animate will only perform simple DOM
-     * manipulation operations.
-     *
-     * To learn more about enabling animation support, click here to visit the {@link ngAnimate
-     * ngAnimate module page} as well as the {@link ngAnimate.$animate ngAnimate $animate service
-     * page}.
-     */
-    return {
-
-      /**
-       *
-       * @ngdoc function
-       * @name ng.$animate#enter
-       * @methodOf ng.$animate
-       * @function
-       * @description Inserts the element into the DOM either after the `after` element or within
-       *   the `parent` element. Once complete, the done() callback will be fired (if provided).
-       * @param {jQuery/jqLite element} element the element which will be inserted into the DOM
-       * @param {jQuery/jqLite element} parent the parent element which will append the element as
-       *   a child (if the after element is not present)
-       * @param {jQuery/jqLite element} after the sibling element which will append the element
-       *   after itself
-       * @param {function=} done callback function that will be called after the element has been
-       *   inserted into the DOM
-       */
-      enter : function(element, parent, after, done) {
-        if (after) {
-          after.after(element);
-        } else {
-          if (!parent || !parent[0]) {
-            parent = after.parent();
-          }
-          parent.append(element);
-        }
-        done && $timeout(done, 0, false);
-      },
-
-      /**
-       *
-       * @ngdoc function
-       * @name ng.$animate#leave
-       * @methodOf ng.$animate
-       * @function
-       * @description Removes the element from the DOM. Once complete, the done() callback will be
-       *   fired (if provided).
-       * @param {jQuery/jqLite element} element the element which will be removed from the DOM
-       * @param {function=} done callback function that will be called after the element has been
-       *   removed from the DOM
-       */
-      leave : function(element, done) {
-        element.remove();
-        done && $timeout(done, 0, false);
-      },
-
-      /**
-       *
-       * @ngdoc function
-       * @name ng.$animate#move
-       * @methodOf ng.$animate
-       * @function
-       * @description Moves the position of the provided element within the DOM to be placed
-       * either after the `after` element or inside of the `parent` element. Once complete, the
-       * done() callback will be fired (if provided).
-       * 
-       * @param {jQuery/jqLite element} element the element which will be moved around within the
-       *   DOM
-       * @param {jQuery/jqLite element} parent the parent element where the element will be
-       *   inserted into (if the after element is not present)
-       * @param {jQuery/jqLite element} after the sibling element where the element will be
-       *   positioned next to
-       * @param {function=} done the callback function (if provided) that will be fired after the
-       *   element has been moved to its new position
-       */
-      move : function(element, parent, after, done) {
-        // Do not remove element before insert. Removing will cause data associated with the
-        // element to be dropped. Insert will implicitly do the remove.
-        this.enter(element, parent, after, done);
-      },
-
-      /**
-       *
-       * @ngdoc function
-       * @name ng.$animate#addClass
-       * @methodOf ng.$animate
-       * @function
-       * @description Adds the provided className CSS class value to the provided element. Once
-       * complete, the done() callback will be fired (if provided).
-       * @param {jQuery/jqLite element} element the element which will have the className value
-       *   added to it
-       * @param {string} className the CSS class which will be added to the element
-       * @param {function=} done the callback function (if provided) that will be fired after the
-       *   className value has been added to the element
-       */
-      addClass : function(element, className, done) {
-        className = isString(className) ?
-                      className :
-                      isArray(className) ? className.join(' ') : '';
-        forEach(element, function (element) {
-          jqLiteAddClass(element, className);
-        });
-        done && $timeout(done, 0, false);
-      },
-
-      /**
-       *
-       * @ngdoc function
-       * @name ng.$animate#removeClass
-       * @methodOf ng.$animate
-       * @function
-       * @description Removes the provided className CSS class value from the provided element.
-       * Once complete, the done() callback will be fired (if provided).
-       * @param {jQuery/jqLite element} element the element which will have the className value
-       *   removed from it
-       * @param {string} className the CSS class which will be removed from the element
-       * @param {function=} done the callback function (if provided) that will be fired after the
-       *   className value has been removed from the element
-       */
-      removeClass : function(element, className, done) {
-        className = isString(className) ?
-                      className :
-                      isArray(className) ? className.join(' ') : '';
-        forEach(element, function (element) {
-          jqLiteRemoveClass(element, className);
-        });
-        done && $timeout(done, 0, false);
-      },
-
-      enabled : noop
-    };
-  }];
-}];
-
-/**
- * ! This is a private undocumented service !
- *
- * @name ng.$browser
- * @requires $log
- * @description
- * This object has two goals:
- *
- * - hide all the global state in the browser caused by the window object
- * - abstract away all the browser specific features and inconsistencies
- *
- * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser`
- * service, which can be used for convenient testing of the application without the interaction with
- * the real browser apis.
- */
-/**
- * @param {object} window The global window object.
- * @param {object} document jQuery wrapped document.
- * @param {function()} XHR XMLHttpRequest constructor.
- * @param {object} $log console.log or an object with the same interface.
- * @param {object} $sniffer $sniffer service
- */
-function Browser(window, document, $log, $sniffer) {
-  var self = this,
-      rawDocument = document[0],
-      location = window.location,
-      history = window.history,
-      setTimeout = window.setTimeout,
-      clearTimeout = window.clearTimeout,
-      pendingDeferIds = {};
-
-  self.isMock = false;
-
-  var outstandingRequestCount = 0;
-  var outstandingRequestCallbacks = [];
-
-  // TODO(vojta): remove this temporary api
-  self.$$completeOutstandingRequest = completeOutstandingRequest;
-  self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; };
-
-  /**
-   * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks`
-   * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed.
-   */
-  function completeOutstandingRequest(fn) {
-    try {
-      fn.apply(null, sliceArgs(arguments, 1));
-    } finally {
-      outstandingRequestCount--;
-      if (outstandingRequestCount === 0) {
-        while(outstandingRequestCallbacks.length) {
-          try {
-            outstandingRequestCallbacks.pop()();
-          } catch (e) {
-            $log.error(e);
-          }
-        }
-      }
-    }
-  }
-
-  /**
-   * @private
-   * Note: this method is used only by scenario runner
-   * TODO(vojta): prefix this method with $$ ?
-   * @param {function()} callback Function that will be called when no outstanding request
-   */
-  self.notifyWhenNoOutstandingRequests = function(callback) {
-    // force browser to execute all pollFns - this is needed so that cookies and other pollers fire
-    // at some deterministic time in respect to the test runner's actions. Leaving things up to the
-    // regular poller would result in flaky tests.
-    forEach(pollFns, function(pollFn){ pollFn(); });
-
-    if (outstandingRequestCount === 0) {
-      callback();
-    } else {
-      outstandingRequestCallbacks.push(callback);
-    }
-  };
-
-  //////////////////////////////////////////////////////////////
-  // Poll Watcher API
-  //////////////////////////////////////////////////////////////
-  var pollFns = [],
-      pollTimeout;
-
-  /**
-   * @name ng.$browser#addPollFn
-   * @methodOf ng.$browser
-   *
-   * @param {function()} fn Poll function to add
-   *
-   * @description
-   * Adds a function to the list of functions that poller periodically executes,
-   * and starts polling if not started yet.
-   *
-   * @returns {function()} the added function
-   */
-  self.addPollFn = function(fn) {
-    if (isUndefined(pollTimeout)) startPoller(100, setTimeout);
-    pollFns.push(fn);
-    return fn;
-  };
-
-  /**
-   * @param {number} interval How often should browser call poll functions (ms)
-   * @param {function()} setTimeout Reference to a real or fake `setTimeout` function.
-   *
-   * @description
-   * Configures the poller to run in the specified intervals, using the specified
-   * setTimeout fn and kicks it off.
-   */
-  function startPoller(interval, setTimeout) {
-    (function check() {
-      forEach(pollFns, function(pollFn){ pollFn(); });
-      pollTimeout = setTimeout(check, interval);
-    })();
-  }
-
-  //////////////////////////////////////////////////////////////
-  // URL API
-  //////////////////////////////////////////////////////////////
-
-  var lastBrowserUrl = location.href,
-      baseElement = document.find('base'),
-      newLocation = null;
-
-  /**
-   * @name ng.$browser#url
-   * @methodOf ng.$browser
-   *
-   * @description
-   * GETTER:
-   * Without any argument, this method just returns current value of location.href.
-   *
-   * SETTER:
-   * With at least one argument, this method sets url to new value.
-   * If html5 history api supported, pushState/replaceState is used, otherwise
-   * location.href/location.replace is used.
-   * Returns its own instance to allow chaining
-   *
-   * NOTE: this api is intended for use only by the $location service. Please use the
-   * {@link ng.$location $location service} to change url.
-   *
-   * @param {string} url New url (when used as setter)
-   * @param {boolean=} replace Should new url replace current history record ?
-   */
-  self.url = function(url, replace) {
-    // Android Browser BFCache causes location reference to become stale.
-    if (location !== window.location) location = window.location;
-
-    // setter
-    if (url) {
-      if (lastBrowserUrl == url) return;
-      lastBrowserUrl = url;
-      if ($sniffer.history) {
-        if (replace) history.replaceState(null, '', url);
-        else {
-          history.pushState(null, '', url);
-          // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462
-          baseElement.attr('href', baseElement.attr('href'));
-        }
-      } else {
-        newLocation = url;
-        if (replace) {
-          location.replace(url);
-        } else {
-          location.href = url;
-        }
-      }
-      return self;
-    // getter
-    } else {
-      // - newLocation is a workaround for an IE7-9 issue with location.replace and location.href
-      //   methods not updating location.href synchronously.
-      // - the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172
-      return newLocation || location.href.replace(/%27/g,"'");
-    }
-  };
-
-  var urlChangeListeners = [],
-      urlChangeInit = false;
-
-  function fireUrlChange() {
-    newLocation = null;
-    if (lastBrowserUrl == self.url()) return;
-
-    lastBrowserUrl = self.url();
-    forEach(urlChangeListeners, function(listener) {
-      listener(self.url());
-    });
-  }
-
-  /**
-   * @name ng.$browser#onUrlChange
-   * @methodOf ng.$browser
-   * @TODO(vojta): refactor to use node's syntax for events
-   *
-   * @description
-   * Register callback function that will be called, when url changes.
-   *
-   * It's only called when the url is changed by outside of angular:
-   * - user types different url into address bar
-   * - user clicks on history (forward/back) button
-   * - user clicks on a link
-   *
-   * It's not called when url is changed by $browser.url() method
-   *
-   * The listener gets called with new url as parameter.
-   *
-   * NOTE: this api is intended for use only by the $location service. Please use the
-   * {@link ng.$location $location service} to monitor url changes in angular apps.
-   *
-   * @param {function(string)} listener Listener function to be called when url changes.
-   * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous.
-   */
-  self.onUrlChange = function(callback) {
-    if (!urlChangeInit) {
-      // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera)
-      // don't fire popstate when user change the address bar and don't fire hashchange when url
-      // changed by push/replaceState
-
-      // html5 history api - popstate event
-      if ($sniffer.history) jqLite(window).on('popstate', fireUrlChange);
-      // hashchange event
-      if ($sniffer.hashchange) jqLite(window).on('hashchange', fireUrlChange);
-      // polling
-      else self.addPollFn(fireUrlChange);
-
-      urlChangeInit = true;
-    }
-
-    urlChangeListeners.push(callback);
-    return callback;
-  };
-
-  //////////////////////////////////////////////////////////////
-  // Misc API
-  //////////////////////////////////////////////////////////////
-
-  /**
-   * @name ng.$browser#baseHref
-   * @methodOf ng.$browser
-   * 
-   * @description
-   * Returns current <base href>
-   * (always relative - without domain)
-   *
-   * @returns {string=} current <base href>
-   */
-  self.baseHref = function() {
-    var href = baseElement.attr('href');
-    return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : '';
-  };
-
-  //////////////////////////////////////////////////////////////
-  // Cookies API
-  //////////////////////////////////////////////////////////////
-  var lastCookies = {};
-  var lastCookieString = '';
-  var cookiePath = self.baseHref();
-
-  /**
-   * @name ng.$browser#cookies
-   * @methodOf ng.$browser
-   *
-   * @param {string=} name Cookie name
-   * @param {string=} value Cookie value
-   *
-   * @description
-   * The cookies method provides a 'private' low level access to browser cookies.
-   * It is not meant to be used directly, use the $cookie service instead.
-   *
-   * The return values vary depending on the arguments that the method was called with as follows:
-   * 
-   * - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
-   *   it
-   * - cookies(name, value) -> set name to value, if value is undefined delete the cookie
-   * - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that
-   *   way)
-   * 
-   * @returns {Object} Hash of all cookies (if called without any parameter)
-   */
-  self.cookies = function(name, value) {
-    /* global escape: false, unescape: false */
-    var cookieLength, cookieArray, cookie, i, index;
-
-    if (name) {
-      if (value === undefined) {
-        rawDocument.cookie = escape(name) + "=;path=" + cookiePath +
-                                ";expires=Thu, 01 Jan 1970 00:00:00 GMT";
-      } else {
-        if (isString(value)) {
-          cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) +
-                                ';path=' + cookiePath).length + 1;
-
-          // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
-          // - 300 cookies
-          // - 20 cookies per unique domain
-          // - 4096 bytes per cookie
-          if (cookieLength > 4096) {
-            $log.warn("Cookie '"+ name +
-              "' possibly not set or overflowed because it was too large ("+
-              cookieLength + " > 4096 bytes)!");
-          }
-        }
-      }
-    } else {
-      if (rawDocument.cookie !== lastCookieString) {
-        lastCookieString = rawDocument.cookie;
-        cookieArray = lastCookieString.split("; ");
-        lastCookies = {};
-
-        for (i = 0; i < cookieArray.length; i++) {
-          cookie = cookieArray[i];
-          index = cookie.indexOf('=');
-          if (index > 0) { //ignore nameless cookies
-            name = unescape(cookie.substring(0, index));
-            // the first value that is seen for a cookie is the most
-            // specific one.  values for the same cookie name that
-            // follow are for less specific paths.
-            if (lastCookies[name] === undefined) {
-              lastCookies[name] = unescape(cookie.substring(index + 1));
-            }
-          }
-        }
-      }
-      return lastCookies;
-    }
-  };
-
-
-  /**
-   * @name ng.$browser#defer
-   * @methodOf ng.$browser
-   * @param {function()} fn A function, who's execution should be deferred.
-   * @param {number=} [delay=0] of milliseconds to defer the function execution.
-   * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`.
-   *
-   * @description
-   * Executes a fn asynchronously 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 programmatically flushed
-   * via `$browser.defer.flush()`.
-   *
-   */
-  self.defer = function(fn, delay) {
-    var timeoutId;
-    outstandingRequestCount++;
-    timeoutId = setTimeout(function() {
-      delete pendingDeferIds[timeoutId];
-      completeOutstandingRequest(fn);
-    }, delay || 0);
-    pendingDeferIds[timeoutId] = true;
-    return timeoutId;
-  };
-
-
-  /**
-   * @name ng.$browser#defer.cancel
-   * @methodOf ng.$browser.defer
-   *
-   * @description
-   * Cancels a deferred task identified with `deferId`.
-   *
-   * @param {*} deferId Token returned by the `$browser.defer` function.
-   * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
-   *                    canceled.
-   */
-  self.defer.cancel = function(deferId) {
-    if (pendingDeferIds[deferId]) {
-      delete pendingDeferIds[deferId];
-      clearTimeout(deferId);
-      completeOutstandingRequest(noop);
-      return true;
-    }
-    return false;
-  };
-
-}
-
-function $BrowserProvider(){
-  this.$get = ['$window', '$log', '$sniffer', '$document',
-      function( $window,   $log,   $sniffer,   $document){
-        return new Browser($window, $document, $log, $sniffer);
-      }];
-}
-
-/**
- * @ngdoc object
- * @name ng.$cacheFactory
- *
- * @description
- * Factory that constructs cache objects and gives access to them.
- * 
- * <pre>
- * 
- *  var cache = $cacheFactory('cacheId');
- *  expect($cacheFactory.get('cacheId')).toBe(cache);
- *  expect($cacheFactory.get('noSuchCacheId')).not.toBeDefined();
- *
- *  cache.put("key", "value");
- *  cache.put("another key", "another value");
- *
- *  // We've specified no options on creation
- *  expect(cache.info()).toEqual({id: 'cacheId', size: 2}); 
- * 
- * </pre>
- *
- *
- * @param {string} cacheId Name or id of the newly created cache.
- * @param {object=} options Options object that specifies the cache behavior. Properties:
- *
- *   - `{number=}` `capacity` — turns the cache into LRU cache.
- *
- * @returns {object} Newly created cache object with the following set of methods:
- *
- * - `{object}` `info()` — Returns id, size, and options of cache.
- * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns
- *   it.
- * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
- * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
- * - `{void}` `removeAll()` — Removes all cached values.
- * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
- *
- */
-function $CacheFactoryProvider() {
-
-  this.$get = function() {
-    var caches = {};
-
-    function cacheFactory(cacheId, options) {
-      if (cacheId in caches) {
-        throw minErr('$cacheFactory')('iid', "CacheId '{0}' is already taken!", cacheId);
-      }
-
-      var size = 0,
-          stats = extend({}, options, {id: cacheId}),
-          data = {},
-          capacity = (options && options.capacity) || Number.MAX_VALUE,
-          lruHash = {},
-          freshEnd = null,
-          staleEnd = null;
-
-      return caches[cacheId] = {
-
-        put: function(key, value) {
-          var lruEntry = lruHash[key] || (lruHash[key] = {key: key});
-
-          refresh(lruEntry);
-
-          if (isUndefined(value)) return;
-          if (!(key in data)) size++;
-          data[key] = value;
-
-          if (size > capacity) {
-            this.remove(staleEnd.key);
-          }
-
-          return value;
-        },
-
-
-        get: function(key) {
-          var lruEntry = lruHash[key];
-
-          if (!lruEntry) return;
-
-          refresh(lruEntry);
-
-          return data[key];
-        },
-
-
-        remove: function(key) {
-          var lruEntry = lruHash[key];
-
-          if (!lruEntry) return;
-
-          if (lruEntry == freshEnd) freshEnd = lruEntry.p;
-          if (lruEntry == staleEnd) staleEnd = lruEntry.n;
-          link(lruEntry.n,lruEntry.p);
-
-          delete lruHash[key];
-          delete data[key];
-          size--;
-        },
-
-
-        removeAll: function() {
-          data = {};
-          size = 0;
-          lruHash = {};
-          freshEnd = staleEnd = null;
-        },
-
-
-        destroy: function() {
-          data = null;
-          stats = null;
-          lruHash = null;
-          delete caches[cacheId];
-        },
-
-
-        info: function() {
-          return extend({}, stats, {size: size});
-        }
-      };
-
-
-      /**
-       * makes the `entry` the freshEnd of the LRU linked list
-       */
-      function refresh(entry) {
-        if (entry != freshEnd) {
-          if (!staleEnd) {
-            staleEnd = entry;
-          } else if (staleEnd == entry) {
-            staleEnd = entry.n;
-          }
-
-          link(entry.n, entry.p);
-          link(entry, freshEnd);
-          freshEnd = entry;
-          freshEnd.n = null;
-        }
-      }
-
-
-      /**
-       * bidirectionally links two entries of the LRU linked list
-       */
-      function link(nextEntry, prevEntry) {
-        if (nextEntry != prevEntry) {
-          if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify
-          if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify
-        }
-      }
-    }
-
-
-  /**
-   * @ngdoc method
-   * @name ng.$cacheFactory#info
-   * @methodOf ng.$cacheFactory
-   *
-   * @description
-   * Get information about all the of the caches that have been created
-   *
-   * @returns {Object} - key-value map of `cacheId` to the result of calling `cache#info`
-   */
-    cacheFactory.info = function() {
-      var info = {};
-      forEach(caches, function(cache, cacheId) {
-        info[cacheId] = cache.info();
-      });
-      return info;
-    };
-
-
-  /**
-   * @ngdoc method
-   * @name ng.$cacheFactory#get
-   * @methodOf ng.$cacheFactory
-   *
-   * @description
-   * Get access to a cache object by the `cacheId` used when it was created.
-   *
-   * @param {string} cacheId Name or id of a cache to access.
-   * @returns {object} Cache object identified by the cacheId or undefined if no such cache.
-   */
-    cacheFactory.get = function(cacheId) {
-      return caches[cacheId];
-    };
-
-
-    return cacheFactory;
-  };
-}
-
-/**
- * @ngdoc object
- * @name ng.$templateCache
- *
- * @description
- * The first time a template is used, it is loaded in the template cache for quick retrieval. You
- * can load templates directly into the cache in a `script` tag, or by consuming the
- * `$templateCache` service directly.
- * 
- * Adding via the `script` tag:
- * <pre>
- * <html ng-app>
- * <head>
- * <script type="text/ng-template" id="templateId.html">
- *   This is the content of the template
- * </script>
- * </head>
- *   ...
- * </html>
- * </pre>
- * 
- * **Note:** the `script` tag containing the template does not need to be included in the `head` of
- * the document, but it must be below the `ng-app` definition.
- * 
- * Adding via the $templateCache service:
- * 
- * <pre>
- * var myApp = angular.module('myApp', []);
- * myApp.run(function($templateCache) {
- *   $templateCache.put('templateId.html', 'This is the content of the template');
- * });
- * </pre>
- * 
- * To retrieve the template later, simply use it in your HTML:
- * <pre>
- * <div ng-include=" 'templateId.html' "></div>
- * </pre>
- * 
- * or get it via Javascript:
- * <pre>
- * $templateCache.get('templateId.html')
- * </pre>
- * 
- * See {@link ng.$cacheFactory $cacheFactory}.
- *
- */
-function $TemplateCacheProvider() {
-  this.$get = ['$cacheFactory', function($cacheFactory) {
-    return $cacheFactory('templates');
-  }];
-}
-
-/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE!
- *
- * DOM-related variables:
- *
- * - "node" - DOM Node
- * - "element" - DOM Element or Node
- * - "$node" or "$element" - jqLite-wrapped node or element
- *
- *
- * Compiler related stuff:
- *
- * - "linkFn" - linking fn of a single directive
- * - "nodeLinkFn" - function that aggregates all linking fns for a particular node
- * - "childLinkFn" -  function that aggregates all linking fns for child nodes of a particular node
- * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList)
- */
-
-
-/**
- * @ngdoc function
- * @name ng.$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 ng.$rootScope.Scope `scope`} and the template together.
- *
- * The compilation is a process of walking the DOM tree and matching DOM elements to
- * {@link ng.$compileProvider#methods_directive directives}.
- *
- * <div class="alert alert-warning">
- * **Note:** This document is an in-depth reference of all directive options.
- * For a gentle introduction to directives with examples of common use cases,
- * see the {@link guide/directive directive guide}.
- * </div>
- *
- * ## Comprehensive Directive API
- *
- * There are many different options for a directive.
- *
- * The difference resides in the return value of the factory function.
- * You can either return a "Directive Definition Object" (see below) that defines the directive properties,
- * or just the `postLink` function (all other properties will have the default values).
- *
- * <div class="alert alert-success">
- * **Best Practice:** It's recommended to use the "directive definition object" form.
- * </div>
- *
- * Here's an example directive declared with a Directive Definition Object:
- *
- * <pre>
- *   var myModule = angular.module(...);
- *
- *   myModule.directive('directiveName', function factory(injectables) {
- *     var directiveDefinitionObject = {
- *       priority: 0,
- *       template: '<div></div>', // or // function(tElement, tAttrs) { ... },
- *       // or
- *       // templateUrl: 'directive.html', // or // function(tElement, tAttrs) { ... },
- *       replace: false,
- *       transclude: false,
- *       restrict: 'A',
- *       scope: false,
- *       controller: function($scope, $element, $attrs, $transclude, otherInjectables) { ... },
- *       require: 'siblingDirectiveName', // or // ['^parentDirectiveName', '?optionalDirectiveName', '?^optionalParent'],
- *       compile: function compile(tElement, tAttrs, transclude) {
- *         return {
- *           pre: function preLink(scope, iElement, iAttrs, controller) { ... },
- *           post: function postLink(scope, iElement, iAttrs, controller) { ... }
- *         }
- *         // or
- *         // return function postLink( ... ) { ... }
- *       },
- *       // or
- *       // link: {
- *       //  pre: function preLink(scope, iElement, iAttrs, controller) { ... },
- *       //  post: function postLink(scope, iElement, iAttrs, controller) { ... }
- *       // }
- *       // or
- *       // link: function postLink( ... ) { ... }
- *     };
- *     return directiveDefinitionObject;
- *   });
- * </pre>
- *
- * <div class="alert alert-warning">
- * **Note:** Any unspecified options will use the default value. You can see the default values below.
- * </div>
- *
- * Therefore the above can be simplified as:
- *
- * <pre>
- *   var myModule = angular.module(...);
- *
- *   myModule.directive('directiveName', function factory(injectables) {
- *     var directiveDefinitionObject = {
- *       link: function postLink(scope, iElement, iAttrs) { ... }
- *     };
- *     return directiveDefinitionObject;
- *     // or
- *     // return function postLink(scope, iElement, iAttrs) { ... }
- *   });
- * </pre>
- *
- *
- *
- * ### Directive Definition Object
- *
- * The directive definition object provides instructions to the {@link api/ng.$compile
- * compiler}. The attributes are:
- *
- * #### `priority`
- * When there are multiple directives defined on a single DOM element, sometimes it
- * is necessary to specify the order in which the directives are applied. The `priority` is used
- * to sort the directives before their `compile` functions get called. Priority is defined as a
- * number. Directives with greater numerical `priority` are compiled first. Pre-link functions
- * are also run in priority order, but post-link functions are run in reverse order. The order
- * of directives with the same priority is undefined. The default priority is `0`.
- *
- * #### `terminal`
- * If set to true then the current `priority` will be the last set of directives
- * which will execute (any directives at the current priority will still execute
- * as the order of execution on same `priority` is undefined).
- *
- * #### `scope`
- * **If set to `true`,** then a new scope will be created for this directive. If multiple directives on the
- * same element request a new scope, only one new scope is created. The new scope rule does not
- * apply for the root of the template since the root of the template always gets a new scope.
- *
- * **If set to `{}` (object hash),** then a new "isolate" scope is created. The 'isolate' scope differs from
- * normal scope in that it does not prototypically inherit from the parent scope. This is useful
- * when creating reusable components, which should not accidentally read or modify data in the
- * parent scope.
- *
- * The 'isolate' scope takes an object hash which defines a set of local scope properties
- * derived from the parent scope. These local properties are useful for aliasing values for
- * templates. Locals definition is a hash of local scope property to its source:
- *
- * * `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
- *   always a string since DOM attributes are strings. If no `attr` name is specified  then the
- *   attribute name is assumed to be the same as the local name.
- *   Given `<widget my-attr="hello {{name}}">` and widget definition
- *   of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
- *   the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
- *   `localName` property on the widget scope. The `name` is read from the parent scope (not
- *   component scope).
- *
- * * `=` or `=attr` - set up bi-directional binding between a local scope property and the
- *   parent scope property of name defined via the value of the `attr` attribute. If no `attr`
- *   name is specified then the attribute name is assumed to be the same as the local name.
- *   Given `<widget my-attr="parentModel">` and widget definition of
- *   `scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
- *   value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
- *   in `localModel` and any changes in `localModel` will reflect in `parentModel`. If the parent
- *   scope property doesn't exist, it will throw a NON_ASSIGNABLE_MODEL_EXPRESSION exception. You
- *   can avoid this behavior using `=?` or `=?attr` in order to flag the property as optional.
- *
- * * `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
- *   If no `attr` name is specified then the attribute name is assumed to be the same as the
- *   local name. Given `<widget my-attr="count = count + value">` and widget definition of
- *   `scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
- *   a function wrapper for the `count = count + value` expression. Often it's desirable to
- *   pass data from the isolated scope via an expression and to the parent scope, this can be
- *   done by passing a map of local variable names and values into the expression wrapper fn.
- *   For example, if the expression is `increment(amount)` then we can specify the amount value
- *   by calling the `localFn` as `localFn({amount: 22})`.
- *
- *
- *
- * #### `controller`
- * Controller constructor function. The controller is instantiated before the
- * pre-linking phase and it is shared with other directives (see
- * `require` attribute). This allows the directives to communicate with each other and augment
- * each other's behavior. The controller is injectable (and supports bracket notation) with the following locals:
- *
- * * `$scope` - Current scope associated with the element
- * * `$element` - Current element
- * * `$attrs` - Current attributes object for the element
- * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope.
- *    The scope can be overridden by an optional first argument.
- *   `function([scope], cloneLinkingFn)`.
- *
- *
- * #### `require`
- * Require another directive and inject its controller as the fourth argument to the linking function. The
- * `require` takes a string name (or array of strings) of the directive(s) to pass in. If an array is used, the
- * injected argument will be an array in corresponding order. If no such directive can be
- * found, or if the directive does not have a controller, then an error is raised. The name can be prefixed with:
- *
- * * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
- * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
- * * `^` - Locate the required controller by searching the element's parents. Throw an error if not found.
- * * `?^` - Attempt to locate the required controller by searching the element's parents or pass `null` to the
- *   `link` fn if not found.
- *
- *
- * #### `controllerAs`
- * Controller alias at the directive scope. An alias for the controller so it
- * can be referenced at the directive template. The directive needs to define a scope for this
- * configuration to be used. Useful in the case when directive is used as component.
- *
- *
- * #### `restrict`
- * String of subset of `EACM` which restricts the directive to a specific directive
- * declaration style. If omitted, the default (attributes only) is used.
- *
- * * `E` - Element name: `<my-directive></my-directive>`
- * * `A` - Attribute (default): `<div my-directive="exp"></div>`
- * * `C` - Class: `<div class="my-directive: exp;"></div>`
- * * `M` - Comment: `<!-- directive: my-directive exp -->`
- *
- *
- * #### `template`
- * replace the current element with the contents of the HTML. The replacement process
- * migrates all of the attributes / classes from the old element to the new one. See the
- * {@link guide/directive#creating-custom-directives_creating-directives_template-expanding-directive
- * Directives Guide} for an example.
- *
- * You can specify `template` as a string representing the template or as a function which takes
- * two arguments `tElement` and `tAttrs` (described in the `compile` function api below) and
- * returns a string value representing the template.
- *
- *
- * #### `templateUrl`
- * Same as `template` but the template is loaded from the specified URL. Because
- * the template loading is asynchronous the compilation/linking is suspended until the template
- * is loaded.
- *
- * You can specify `templateUrl` as a string representing the URL or as a function which takes two
- * arguments `tElement` and `tAttrs` (described in the `compile` function api below) and returns
- * a string value representing the url.  In either case, the template URL is passed through {@link
- * api/ng.$sce#methods_getTrustedResourceUrl $sce.getTrustedResourceUrl}.
- *
- *
- * #### `replace`
- * specify where the template should be inserted. Defaults to `false`.
- *
- * * `true` - the template will replace the current element.
- * * `false` - the template will replace the contents of the current element.
- *
- *
- * #### `transclude`
- * compile the content of the element and make it available to the directive.
- * Typically used with {@link api/ng.directive:ngTransclude
- * ngTransclude}. The advantage of transclusion is that the linking function receives a
- * transclusion function which is pre-bound to the correct scope. In a typical setup the widget
- * creates an `isolate` scope, but the transclusion is not a child, but a sibling of the `isolate`
- * scope. This makes it possible for the widget to have private state, and the transclusion to
- * be bound to the parent (pre-`isolate`) scope.
- *
- * * `true` - transclude the content of the directive.
- * * `'element'` - transclude the whole element including any directives defined at lower priority.
- *
- *
- * #### `compile`
- *
- * <pre>
- *   function compile(tElement, tAttrs, transclude) { ... }
- * </pre>
- *
- * The compile function deals with transforming the template DOM. Since most directives do not do
- * template transformation, it is not used often. Examples that require compile functions are
- * directives that transform template DOM, such as {@link
- * api/ng.directive:ngRepeat ngRepeat}, or load the contents
- * asynchronously, such as {@link api/ngRoute.directive:ngView ngView}. The
- * compile function takes the following arguments.
- *
- *   * `tElement` - template element - The element where the directive has been declared. It is
- *     safe to do template transformation on the element and child elements only.
- *
- *   * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
- *     between all directive compile functions.
- *
- *   * `transclude` -  [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
- *
- * <div class="alert alert-warning">
- * **Note:** The template instance and the link instance may be different objects if the template has
- * been cloned. For this reason it is **not** safe to do anything other than DOM transformations that
- * apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration
- * should be done in a linking function rather than in a compile function.
- * </div>
- *
- * <div class="alert alert-error">
- * **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
- *   e.g. does not know about the right outer scope. Please use the transclude function that is passed
- *   to the link function instead.
- * </div>
-
- * A compile function can have a return value which can be either a function or an object.
- *
- * * returning a (post-link) function - is equivalent to registering the linking function via the
- *   `link` property of the config object when the compile function is empty.
- *
- * * returning an object with function(s) registered via `pre` and `post` properties - allows you to
- *   control when a linking function should be called during the linking phase. See info about
- *   pre-linking and post-linking functions below.
- *
- *
- * #### `link`
- * This property is used only if the `compile` property is not defined.
- *
- * <pre>
- *   function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
- * </pre>
- *
- * The link function is responsible for registering DOM listeners as well as updating the DOM. It is
- * executed after the template has been cloned. This is where most of the directive logic will be
- * put.
- *
- *   * `scope` - {@link api/ng.$rootScope.Scope Scope} - The scope to be used by the
- *     directive for registering {@link api/ng.$rootScope.Scope#methods_$watch watches}.
- *
- *   * `iElement` - instance element - The element where the directive is to be used. It is safe to
- *     manipulate the children of the element only in `postLink` function since the children have
- *     already been linked.
- *
- *   * `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
- *     between all directive linking functions.
- *
- *   * `controller` - a controller instance - A controller instance if at least one directive on the
- *     element defines a controller. The controller is shared among all the directives, which allows
- *     the directives to use the controllers as a communication channel.
- *
- *   * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
- *     The scope can be overridden by an optional first argument. This is the same as the `$transclude`
- *     parameter of directive controllers.
- *     `function([scope], cloneLinkingFn)`.
- *
- *
- * #### Pre-linking function
- *
- * Executed before the child elements are linked. Not safe to do DOM transformation since the
- * compiler linking function will fail to locate the correct elements for linking.
- *
- * #### Post-linking function
- *
- * Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function.
- *
- * <a name="Attributes"></a>
- * ### Attributes
- *
- * The {@link api/ng.$compile.directive.Attributes Attributes} object - passed as a parameter in the
- * `link()` or `compile()` functions. It has a variety of uses.
- *
- * accessing *Normalized attribute names:*
- * Directives like 'ngBind' can be expressed in many ways: 'ng:bind', `data-ng-bind`, or 'x-ng-bind'.
- * the attributes object allows for normalized access to
- *   the attributes.
- *
- * * *Directive inter-communication:* All directives share the same instance of the attributes
- *   object which allows the directives to use the attributes object as inter directive
- *   communication.
- *
- * * *Supports interpolation:* Interpolation attributes are assigned to the attribute object
- *   allowing other directives to read the interpolated value.
- *
- * * *Observing interpolated attributes:* Use `$observe` to observe the value changes of attributes
- *   that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also
- *   the only way to easily get the actual value because during the linking phase the interpolation
- *   hasn't been evaluated yet and so the value is at this time set to `undefined`.
- *
- * <pre>
- * function linkingFn(scope, elm, attrs, ctrl) {
- *   // get the attribute value
- *   console.log(attrs.ngModel);
- *
- *   // change the attribute
- *   attrs.$set('ngModel', 'new value');
- *
- *   // observe changes to interpolated attribute
- *   attrs.$observe('ngModel', function(value) {
- *     console.log('ngModel has changed value to ' + value);
- *   });
- * }
- * </pre>
- *
- * Below is an example using `$compileProvider`.
- *
- * <div class="alert alert-warning">
- * **Note**: Typically directives are registered with `module.directive`. The example below is
- * to illustrate how `$compile` works.
- * </div>
- *
- <doc:example module="compile">
-   <doc:source>
-    <script>
-      angular.module('compile', [], function($compileProvider) {
-        // configure new 'compile' directive by passing a directive
-        // factory function. The factory function injects the '$compile'
-        $compileProvider.directive('compile', function($compile) {
-          // directive factory creates a link function
-          return function(scope, element, attrs) {
-            scope.$watch(
-              function(scope) {
-                 // watch the 'compile' expression for changes
-                return scope.$eval(attrs.compile);
-              },
-              function(value) {
-                // when the 'compile' expression changes
-                // assign it into the current DOM
-                element.html(value);
-
-                // compile the new DOM and link it to the current
-                // scope.
-                // NOTE: we only compile .childNodes so that
-                // we don't get into infinite loop compiling ourselves
-                $compile(element.contents())(scope);
-              }
-            );
-          };
-        })
-      });
-
-      function Ctrl($scope) {
-        $scope.name = 'Angular';
-        $scope.html = 'Hello {{name}}';
-      }
-    </script>
-    <div ng-controller="Ctrl">
-      <input ng-model="name"> <br>
-      <textarea ng-model="html"></textarea> <br>
-      <div compile="html"></div>
-    </div>
-   </doc:source>
-   <doc:scenario>
-     it('should auto compile', function() {
-       expect(element('div[compile]').text()).toBe('Hello Angular');
-       input('html').enter('{{name}}!');
-       expect(element('div[compile]').text()).toBe('Angular!');
-     });
-   </doc:scenario>
- </doc:example>
-
- *
- *
- * @param {string|DOMElement} element Element or HTML string to compile into a template function.
- * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives.
- * @param {number} maxPriority only apply directives lower then given priority (Only effects the
- *                 root element(s), not their children)
- * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template
- * (a DOM element/tree) to a scope. Where:
- *
- *  * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to.
- *  * `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 appropriate 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 linking function returns the element of the template. It is either the original
- * element passed in, or the clone of the element if the `cloneAttachFn` is provided.
- *
- * After linking the view is not updated until after a call to $digest which typically is done by
- * Angular automatically.
- *
- * 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 element = $compile('<p>{{total}}</p>')(scope);
- *   </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 templateHTML = angular.element('<p>{{total}}</p>'),
- *         scope = ....;
- *
- *     var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {
- *       //attach the clone to DOM document at the right place
- *     });
- *
- *     //now we have reference to the cloned DOM via `clone`
- *   </pre>
- *
- *
- * For information on how the compiler works, see the
- * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide.
- */
-
-var $compileMinErr = minErr('$compile');
-
-/**
- * @ngdoc service
- * @name ng.$compileProvider
- * @function
- *
- * @description
- */
-$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
-function $CompileProvider($provide, $$sanitizeUriProvider) {
-  var hasDirectives = {},
-      Suffix = 'Directive',
-      COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
-      CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/;
-
-  // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
-  // The assumption is that future DOM event attribute names will begin with
-  // 'on' and be composed of only English letters.
-  var EVENT_HANDLER_ATTR_REGEXP = /^(on[a-z]+|formaction)$/;
-
-  /**
-   * @ngdoc function
-   * @name ng.$compileProvider#directive
-   * @methodOf ng.$compileProvider
-   * @function
-   *
-   * @description
-   * Register a new directive with the compiler.
-   *
-   * @param {string|Object} name Name of the directive in camel-case (i.e. <code>ngBind</code> which
-   *    will match as <code>ng-bind</code>), or an object map of directives where the keys are the
-   *    names and the values are the factories.
-   * @param {function|Array} directiveFactory An injectable directive factory function. See
-   *    {@link guide/directive} for more info.
-   * @returns {ng.$compileProvider} Self for chaining.
-   */
-   this.directive = function registerDirective(name, directiveFactory) {
-    assertNotHasOwnProperty(name, 'directive');
-    if (isString(name)) {
-      assertArg(directiveFactory, 'directiveFactory');
-      if (!hasDirectives.hasOwnProperty(name)) {
-        hasDirectives[name] = [];
-        $provide.factory(name + Suffix, ['$injector', '$exceptionHandler',
-          function($injector, $exceptionHandler) {
-            var directives = [];
-            forEach(hasDirectives[name], function(directiveFactory, index) {
-              try {
-                var directive = $injector.invoke(directiveFactory);
-                if (isFunction(directive)) {
-                  directive = { compile: valueFn(directive) };
-                } else if (!directive.compile && directive.link) {
-                  directive.compile = valueFn(directive.link);
-                }
-                directive.priority = directive.priority || 0;
-                directive.index = index;
-                directive.name = directive.name || name;
-                directive.require = directive.require || (directive.controller && directive.name);
-                directive.restrict = directive.restrict || 'A';
-                directives.push(directive);
-              } catch (e) {
-                $exceptionHandler(e);
-              }
-            });
-            return directives;
-          }]);
-      }
-      hasDirectives[name].push(directiveFactory);
-    } else {
-      forEach(name, reverseParams(registerDirective));
-    }
-    return this;
-  };
-
-
-  /**
-   * @ngdoc function
-   * @name ng.$compileProvider#aHrefSanitizationWhitelist
-   * @methodOf ng.$compileProvider
-   * @function
-   *
-   * @description
-   * Retrieves or overrides the default regular expression that is used for whitelisting of safe
-   * urls during a[href] sanitization.
-   *
-   * The sanitization is a security measure aimed at prevent XSS attacks via html links.
-   *
-   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
-   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
-   * regular expression. If a match is found, the original url is written into the dom. Otherwise,
-   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
-   *
-   * @param {RegExp=} regexp New regexp to whitelist urls with.
-   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
-   *    chaining otherwise.
-   */
-  this.aHrefSanitizationWhitelist = function(regexp) {
-    if (isDefined(regexp)) {
-      $$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
-      return this;
-    } else {
-      return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
-    }
-  };
-
-
-  /**
-   * @ngdoc function
-   * @name ng.$compileProvider#imgSrcSanitizationWhitelist
-   * @methodOf ng.$compileProvider
-   * @function
-   *
-   * @description
-   * Retrieves or overrides the default regular expression that is used for whitelisting of safe
-   * urls during img[src] sanitization.
-   *
-   * The sanitization is a security measure aimed at prevent XSS attacks via html links.
-   *
-   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
-   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
-   * regular expression. If a match is found, the original url is written into the dom. Otherwise,
-   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
-   *
-   * @param {RegExp=} regexp New regexp to whitelist urls with.
-   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
-   *    chaining otherwise.
-   */
-  this.imgSrcSanitizationWhitelist = function(regexp) {
-    if (isDefined(regexp)) {
-      $$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
-      return this;
-    } else {
-      return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
-    }
-  };
-
-  this.$get = [
-            '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
-            '$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
-    function($injector,   $interpolate,   $exceptionHandler,   $http,   $templateCache,   $parse,
-             $controller,   $rootScope,   $document,   $sce,   $animate,   $$sanitizeUri) {
-
-    var Attributes = function(element, attr) {
-      this.$$element = element;
-      this.$attr = attr || {};
-    };
-
-    Attributes.prototype = {
-      $normalize: directiveNormalize,
-
-
-      /**
-       * @ngdoc function
-       * @name ng.$compile.directive.Attributes#$addClass
-       * @methodOf ng.$compile.directive.Attributes
-       * @function
-       *
-       * @description
-       * Adds the CSS class value specified by the classVal parameter to the element. If animations
-       * are enabled then an animation will be triggered for the class addition.
-       *
-       * @param {string} classVal The className value that will be added to the element
-       */
-      $addClass : function(classVal) {
-        if(classVal && classVal.length > 0) {
-          $animate.addClass(this.$$element, classVal);
-        }
-      },
-
-      /**
-       * @ngdoc function
-       * @name ng.$compile.directive.Attributes#$removeClass
-       * @methodOf ng.$compile.directive.Attributes
-       * @function
-       *
-       * @description
-       * Removes the CSS class value specified by the classVal parameter from the element. If
-       * animations are enabled then an animation will be triggered for the class removal.
-       *
-       * @param {string} classVal The className value that will be removed from the element
-       */
-      $removeClass : function(classVal) {
-        if(classVal && classVal.length > 0) {
-          $animate.removeClass(this.$$element, classVal);
-        }
-      },
-
-      /**
-       * @ngdoc function
-       * @name ng.$compile.directive.Attributes#$updateClass
-       * @methodOf ng.$compile.directive.Attributes
-       * @function
-       *
-       * @description
-       * Adds and removes the appropriate CSS class values to the element based on the difference
-       * between the new and old CSS class values (specified as newClasses and oldClasses).
-       *
-       * @param {string} newClasses The current CSS className value
-       * @param {string} oldClasses The former CSS className value
-       */
-      $updateClass : function(newClasses, oldClasses) {
-        this.$removeClass(tokenDifference(oldClasses, newClasses));
-        this.$addClass(tokenDifference(newClasses, oldClasses));
-      },
-
-      /**
-       * Set a normalized attribute on the element in a way such that all directives
-       * can share the attribute. This function properly handles boolean attributes.
-       * @param {string} key Normalized key. (ie ngAttribute)
-       * @param {string|boolean} value The value to set. If `null` attribute will be deleted.
-       * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute.
-       *     Defaults to true.
-       * @param {string=} attrName Optional none normalized name. Defaults to key.
-       */
-      $set: function(key, value, writeAttr, attrName) {
-        // TODO: decide whether or not to throw an error if "class"
-        //is set through this function since it may cause $updateClass to
-        //become unstable.
-
-        var booleanKey = getBooleanAttrName(this.$$element[0], key),
-            normalizedVal,
-            nodeName;
-
-        if (booleanKey) {
-          this.$$element.prop(key, value);
-          attrName = booleanKey;
-        }
-
-        this[key] = value;
-
-        // translate normalized key to actual key
-        if (attrName) {
-          this.$attr[key] = attrName;
-        } else {
-          attrName = this.$attr[key];
-          if (!attrName) {
-            this.$attr[key] = attrName = snake_case(key, '-');
-          }
-        }
-
-        nodeName = nodeName_(this.$$element);
-
-        // sanitize a[href] and img[src] values
-        if ((nodeName === 'A' && key === 'href') ||
-            (nodeName === 'IMG' && key === 'src')) {
-          this[key] = value = $$sanitizeUri(value, key === 'src');
-        }
-
-        if (writeAttr !== false) {
-          if (value === null || value === undefined) {
-            this.$$element.removeAttr(attrName);
-          } else {
-            this.$$element.attr(attrName, value);
-          }
-        }
-
-        // fire observers
-        var $$observers = this.$$observers;
-        $$observers && forEach($$observers[key], function(fn) {
-          try {
-            fn(value);
-          } catch (e) {
-            $exceptionHandler(e);
-          }
-        });
-      },
-
-
-      /**
-       * @ngdoc function
-       * @name ng.$compile.directive.Attributes#$observe
-       * @methodOf ng.$compile.directive.Attributes
-       * @function
-       *
-       * @description
-       * Observes an interpolated attribute.
-       *
-       * The observer function will be invoked once during the next `$digest` following
-       * compilation. The observer is then invoked whenever the interpolated value
-       * changes.
-       *
-       * @param {string} key Normalized key. (ie ngAttribute) .
-       * @param {function(interpolatedValue)} fn Function that will be called whenever
-                the interpolated value of the attribute changes.
-       *        See the {@link guide/directive#Attributes Directives} guide for more info.
-       * @returns {function()} the `fn` parameter.
-       */
-      $observe: function(key, fn) {
-        var attrs = this,
-            $$observers = (attrs.$$observers || (attrs.$$observers = {})),
-            listeners = ($$observers[key] || ($$observers[key] = []));
-
-        listeners.push(fn);
-        $rootScope.$evalAsync(function() {
-          if (!listeners.$$inter) {
-            // no one registered attribute interpolation function, so lets call it manually
-            fn(attrs[key]);
-          }
-        });
-        return fn;
-      }
-    };
-
-    var startSymbol = $interpolate.startSymbol(),
-        endSymbol = $interpolate.endSymbol(),
-        denormalizeTemplate = (startSymbol == '{{' || endSymbol  == '}}')
-            ? identity
-            : function denormalizeTemplate(template) {
-              return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol);
-        },
-        NG_ATTR_BINDING = /^ngAttr[A-Z]/;
-
-
-    return compile;
-
-    //================================
-
-    function compile($compileNodes, transcludeFn, maxPriority, ignoreDirective,
-                        previousCompileContext) {
-      if (!($compileNodes instanceof jqLite)) {
-        // jquery always rewraps, whereas we need to preserve the original selector so that we can
-        // modify it.
-        $compileNodes = jqLite($compileNodes);
-      }
-      // We can not compile top level text elements since text nodes can be merged and we will
-      // not be able to attach scope data to them, so we will wrap them in <span>
-      forEach($compileNodes, function(node, index){
-        if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) {
-          $compileNodes[index] = node = jqLite(node).wrap('<span></span>').parent()[0];
-        }
-      });
-      var compositeLinkFn =
-              compileNodes($compileNodes, transcludeFn, $compileNodes,
-                           maxPriority, ignoreDirective, previousCompileContext);
-      return function publicLinkFn(scope, cloneConnectFn, transcludeControllers){
-        assertArg(scope, 'scope');
-        // 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 $linkNode = cloneConnectFn
-          ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
-          : $compileNodes;
-
-        forEach(transcludeControllers, function(instance, name) {
-          $linkNode.data('$' + name + 'Controller', instance);
-        });
-
-        // Attach scope only to non-text nodes.
-        for(var i = 0, ii = $linkNode.length; i<ii; i++) {
-          var node = $linkNode[i];
-          if (node.nodeType == 1 /* element */ || node.nodeType == 9 /* document */) {
-            $linkNode.eq(i).data('$scope', scope);
-          }
-        }
-        safeAddClass($linkNode, 'ng-scope');
-        if (cloneConnectFn) cloneConnectFn($linkNode, scope);
-        if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);
-        return $linkNode;
-      };
-    }
-
-    function safeAddClass($element, className) {
-      try {
-        $element.addClass(className);
-      } catch(e) {
-        // ignore, since it means that we are trying to set class on
-        // SVG element, where class name is read-only.
-      }
-    }
-
-    /**
-     * Compile function matches each node in nodeList against the directives. Once all directives
-     * for a particular node are collected their compile functions are executed. The compile
-     * functions return values - the linking functions - are combined into a composite linking
-     * function, which is the a linking function for the node.
-     *
-     * @param {NodeList} nodeList an array of nodes or NodeList to compile
-     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
-     *        scope argument is auto-generated to the new child of the transcluded parent scope.
-     * @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
-     *        the rootElement must be set the jqLite collection of the compile root. This is
-     *        needed so that the jqLite collection items can be replaced with widgets.
-     * @param {number=} max directive priority
-     * @returns {?function} A composite linking function of all of the matched directives or null.
-     */
-    function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
-                            previousCompileContext) {
-      var linkFns = [],
-          nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
-
-      for(var i = 0; i < nodeList.length; i++) {
-        attrs = new Attributes();
-
-        // we must always refer to nodeList[i] since the nodes can be replaced underneath us.
-        directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
-                                        ignoreDirective);
-
-        nodeLinkFn = (directives.length)
-            ? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement,
-                                      null, [], [], previousCompileContext)
-            : null;
-
-        childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
-                      !nodeList[i].childNodes ||
-                      !nodeList[i].childNodes.length)
-            ? null
-            : compileNodes(nodeList[i].childNodes,
-                 nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
-
-        linkFns.push(nodeLinkFn);
-        linkFns.push(childLinkFn);
-        linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
-        //use the previous context only for the first element in the virtual group
-        previousCompileContext = null;
-      }
-
-      // return a linking function if we have found anything, null otherwise
-      return linkFnFound ? compositeLinkFn : null;
-
-      function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
-        var nodeLinkFn, childLinkFn, node, $node, childScope, childTranscludeFn, i, ii, n;
-
-        // copy nodeList so that linking doesn't break due to live list updates.
-        var stableNodeList = [];
-        for (i = 0, ii = nodeList.length; i < ii; i++) {
-          stableNodeList.push(nodeList[i]);
-        }
-
-        for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
-          node = stableNodeList[n];
-          nodeLinkFn = linkFns[i++];
-          childLinkFn = linkFns[i++];
-          $node = jqLite(node);
-
-          if (nodeLinkFn) {
-            if (nodeLinkFn.scope) {
-              childScope = scope.$new();
-              $node.data('$scope', childScope);
-              safeAddClass($node, 'ng-scope');
-            } else {
-              childScope = scope;
-            }
-            childTranscludeFn = nodeLinkFn.transclude;
-            if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
-              nodeLinkFn(childLinkFn, childScope, node, $rootElement,
-                createBoundTranscludeFn(scope, childTranscludeFn || transcludeFn)
-              );
-            } else {
-              nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
-            }
-          } else if (childLinkFn) {
-            childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
-          }
-        }
-      }
-    }
-
-    function createBoundTranscludeFn(scope, transcludeFn) {
-      return function boundTranscludeFn(transcludedScope, cloneFn, controllers) {
-        var scopeCreated = false;
-
-        if (!transcludedScope) {
-          transcludedScope = scope.$new();
-          transcludedScope.$$transcluded = true;
-          scopeCreated = true;
-        }
-
-        var clone = transcludeFn(transcludedScope, cloneFn, controllers);
-        if (scopeCreated) {
-          clone.on('$destroy', bind(transcludedScope, transcludedScope.$destroy));
-        }
-        return clone;
-      };
-    }
-
-    /**
-     * Looks for directives on the given node and adds them to the directive collection which is
-     * sorted.
-     *
-     * @param node Node to search.
-     * @param directives An array to which the directives are added to. This array is sorted before
-     *        the function returns.
-     * @param attrs The shared attrs object which is used to populate the normalized attributes.
-     * @param {number=} maxPriority Max directive priority.
-     */
-    function collectDirectives(node, directives, attrs, maxPriority, ignoreDirective) {
-      var nodeType = node.nodeType,
-          attrsMap = attrs.$attr,
-          match,
-          className;
-
-      switch(nodeType) {
-        case 1: /* Element */
-          // use the node name: <directive>
-          addDirective(directives,
-              directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);
-
-          // iterate over the attributes
-          for (var attr, name, nName, ngAttrName, value, nAttrs = node.attributes,
-                   j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) {
-            var attrStartName = false;
-            var attrEndName = false;
-
-            attr = nAttrs[j];
-            if (!msie || msie >= 8 || attr.specified) {
-              name = attr.name;
-              // support ngAttr attribute binding
-              ngAttrName = directiveNormalize(name);
-              if (NG_ATTR_BINDING.test(ngAttrName)) {
-                name = snake_case(ngAttrName.substr(6), '-');
-              }
-
-              var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
-              if (ngAttrName === directiveNName + 'Start') {
-                attrStartName = name;
-                attrEndName = name.substr(0, name.length - 5) + 'end';
-                name = name.substr(0, name.length - 6);
-              }
-
-              nName = directiveNormalize(name.toLowerCase());
-              attrsMap[nName] = name;
-              attrs[nName] = value = trim((msie && name == 'href')
-                ? decodeURIComponent(node.getAttribute(name, 2))
-                : attr.value);
-              if (getBooleanAttrName(node, nName)) {
-                attrs[nName] = true; // presence means true
-              }
-              addAttrInterpolateDirective(node, directives, value, nName);
-              addDirective(directives, nName, 'A', maxPriority, ignoreDirective, attrStartName,
-                            attrEndName);
-            }
-          }
-
-          // use class as directive
-          className = node.className;
-          if (isString(className) && className !== '') {
-            while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) {
-              nName = directiveNormalize(match[2]);
-              if (addDirective(directives, nName, 'C', maxPriority, ignoreDirective)) {
-                attrs[nName] = trim(match[3]);
-              }
-              className = className.substr(match.index + match[0].length);
-            }
-          }
-          break;
-        case 3: /* Text Node */
-          addTextInterpolateDirective(directives, node.nodeValue);
-          break;
-        case 8: /* Comment */
-          try {
-            match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue);
-            if (match) {
-              nName = directiveNormalize(match[1]);
-              if (addDirective(directives, nName, 'M', maxPriority, ignoreDirective)) {
-                attrs[nName] = trim(match[2]);
-              }
-            }
-          } catch (e) {
-            // turns out that under some circumstances IE9 throws errors when one attempts to read
-            // comment's node value.
-            // Just ignore it and continue. (Can't seem to reproduce in test case.)
-          }
-          break;
-      }
-
-      directives.sort(byPriority);
-      return directives;
-    }
-
-    /**
-     * Given a node with an directive-start it collects all of the siblings until it finds
-     * directive-end.
-     * @param node
-     * @param attrStart
-     * @param attrEnd
-     * @returns {*}
-     */
-    function groupScan(node, attrStart, attrEnd) {
-      var nodes = [];
-      var depth = 0;
-      if (attrStart && node.hasAttribute && node.hasAttribute(attrStart)) {
-        var startNode = node;
-        do {
-          if (!node) {
-            throw $compileMinErr('uterdir',
-                      "Unterminated attribute, found '{0}' but no matching '{1}' found.",
-                      attrStart, attrEnd);
-          }
-          if (node.nodeType == 1 /** Element **/) {
-            if (node.hasAttribute(attrStart)) depth++;
-            if (node.hasAttribute(attrEnd)) depth--;
-          }
-          nodes.push(node);
-          node = node.nextSibling;
-        } while (depth > 0);
-      } else {
-        nodes.push(node);
-      }
-
-      return jqLite(nodes);
-    }
-
-    /**
-     * Wrapper for linking function which converts normal linking function into a grouped
-     * linking function.
-     * @param linkFn
-     * @param attrStart
-     * @param attrEnd
-     * @returns {Function}
-     */
-    function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
-      return function(scope, element, attrs, controllers, transcludeFn) {
-        element = groupScan(element[0], attrStart, attrEnd);
-        return linkFn(scope, element, attrs, controllers, transcludeFn);
-      };
-    }
-
-    /**
-     * Once the directives have been collected, their compile functions are executed. This method
-     * is responsible for inlining directive templates as well as terminating the application
-     * of the directives if the terminal directive has been reached.
-     *
-     * @param {Array} directives Array of collected directives to execute their compile function.
-     *        this needs to be pre-sorted by priority order.
-     * @param {Node} compileNode The raw DOM node to apply the compile functions to
-     * @param {Object} templateAttrs The shared attribute function
-     * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
-     *                                                  scope argument is auto-generated to the new
-     *                                                  child of the transcluded parent scope.
-     * @param {JQLite} jqCollection If we are working on the root of the compile tree then this
-     *                              argument has the root jqLite array so that we can replace nodes
-     *                              on it.
-     * @param {Object=} originalReplaceDirective An optional directive that will be ignored when
-     *                                           compiling the transclusion.
-     * @param {Array.<Function>} preLinkFns
-     * @param {Array.<Function>} postLinkFns
-     * @param {Object} previousCompileContext Context used for previous compilation of the current
-     *                                        node
-     * @returns linkFn
-     */
-    function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
-                                   jqCollection, originalReplaceDirective, preLinkFns, postLinkFns,
-                                   previousCompileContext) {
-      previousCompileContext = previousCompileContext || {};
-
-      var terminalPriority = -Number.MAX_VALUE,
-          newScopeDirective,
-          controllerDirectives = previousCompileContext.controllerDirectives,
-          newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
-          templateDirective = previousCompileContext.templateDirective,
-          nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
-          hasTranscludeDirective = false,
-          hasElementTranscludeDirective = false,
-          $compileNode = templateAttrs.$$element = jqLite(compileNode),
-          directive,
-          directiveName,
-          $template,
-          replaceDirective = originalReplaceDirective,
-          childTranscludeFn = transcludeFn,
-          linkFn,
-          directiveValue;
-
-      // executes all directives on the current element
-      for(var i = 0, ii = directives.length; i < ii; i++) {
-        directive = directives[i];
-        var attrStart = directive.$$start;
-        var attrEnd = directive.$$end;
-
-        // collect multiblock sections
-        if (attrStart) {
-          $compileNode = groupScan(compileNode, attrStart, attrEnd);
-        }
-        $template = undefined;
-
-        if (terminalPriority > directive.priority) {
-          break; // prevent further processing of directives
-        }
-
-        if (directiveValue = directive.scope) {
-          newScopeDirective = newScopeDirective || directive;
-
-          // skip the check for directives with async templates, we'll check the derived sync
-          // directive when the template arrives
-          if (!directive.templateUrl) {
-            assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
-                              $compileNode);
-            if (isObject(directiveValue)) {
-              newIsolateScopeDirective = directive;
-            }
-          }
-        }
-
-        directiveName = directive.name;
-
-        if (!directive.templateUrl && directive.controller) {
-          directiveValue = directive.controller;
-          controllerDirectives = controllerDirectives || {};
-          assertNoDuplicate("'" + directiveName + "' controller",
-              controllerDirectives[directiveName], directive, $compileNode);
-          controllerDirectives[directiveName] = directive;
-        }
-
-        if (directiveValue = directive.transclude) {
-          hasTranscludeDirective = true;
-
-          // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
-          // This option should only be used by directives that know how to how to safely handle element transclusion,
-          // where the transcluded nodes are added or replaced after linking.
-          if (!directive.$$tlb) {
-            assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
-            nonTlbTranscludeDirective = directive;
-          }
-
-          if (directiveValue == 'element') {
-            hasElementTranscludeDirective = true;
-            terminalPriority = directive.priority;
-            $template = groupScan(compileNode, attrStart, attrEnd);
-            $compileNode = templateAttrs.$$element =
-                jqLite(document.createComment(' ' + directiveName + ': ' +
-                                              templateAttrs[directiveName] + ' '));
-            compileNode = $compileNode[0];
-            replaceWith(jqCollection, jqLite(sliceArgs($template)), compileNode);
-
-            childTranscludeFn = compile($template, transcludeFn, terminalPriority,
-                                        replaceDirective && replaceDirective.name, {
-                                          // Don't pass in:
-                                          // - controllerDirectives - otherwise we'll create duplicates controllers
-                                          // - newIsolateScopeDirective or templateDirective - combining templates with
-                                          //   element transclusion doesn't make sense.
-                                          //
-                                          // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
-                                          // on the same element more than once.
-                                          nonTlbTranscludeDirective: nonTlbTranscludeDirective
-                                        });
-          } else {
-            $template = jqLite(jqLiteClone(compileNode)).contents();
-            $compileNode.empty(); // clear contents
-            childTranscludeFn = compile($template, transcludeFn);
-          }
-        }
-
-        if (directive.template) {
-          assertNoDuplicate('template', templateDirective, directive, $compileNode);
-          templateDirective = directive;
-
-          directiveValue = (isFunction(directive.template))
-              ? directive.template($compileNode, templateAttrs)
-              : directive.template;
-
-          directiveValue = denormalizeTemplate(directiveValue);
-
-          if (directive.replace) {
-            replaceDirective = directive;
-            $template = jqLite('<div>' +
-                                 trim(directiveValue) +
-                               '</div>').contents();
-            compileNode = $template[0];
-
-            if ($template.length != 1 || compileNode.nodeType !== 1) {
-              throw $compileMinErr('tplrt',
-                  "Template for directive '{0}' must have exactly one root element. {1}",
-                  directiveName, '');
-            }
-
-            replaceWith(jqCollection, $compileNode, compileNode);
-
-            var newTemplateAttrs = {$attr: {}};
-
-            // combine directives from the original node and from the template:
-            // - take the array of directives for this element
-            // - split it into two parts, those that already applied (processed) and those that weren't (unprocessed)
-            // - collect directives from the template and sort them by priority
-            // - combine directives as: processed + template + unprocessed
-            var templateDirectives = collectDirectives(compileNode, [], newTemplateAttrs);
-            var unprocessedDirectives = directives.splice(i + 1, directives.length - (i + 1));
-
-            if (newIsolateScopeDirective) {
-              markDirectivesAsIsolate(templateDirectives);
-            }
-            directives = directives.concat(templateDirectives).concat(unprocessedDirectives);
-            mergeTemplateAttributes(templateAttrs, newTemplateAttrs);
-
-            ii = directives.length;
-          } else {
-            $compileNode.html(directiveValue);
-          }
-        }
-
-        if (directive.templateUrl) {
-          assertNoDuplicate('template', templateDirective, directive, $compileNode);
-          templateDirective = directive;
-
-          if (directive.replace) {
-            replaceDirective = directive;
-          }
-
-          nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
-              templateAttrs, jqCollection, childTranscludeFn, preLinkFns, postLinkFns, {
-                controllerDirectives: controllerDirectives,
-                newIsolateScopeDirective: newIsolateScopeDirective,
-                templateDirective: templateDirective,
-                nonTlbTranscludeDirective: nonTlbTranscludeDirective
-              });
-          ii = directives.length;
-        } else if (directive.compile) {
-          try {
-            linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn);
-            if (isFunction(linkFn)) {
-              addLinkFns(null, linkFn, attrStart, attrEnd);
-            } else if (linkFn) {
-              addLinkFns(linkFn.pre, linkFn.post, attrStart, attrEnd);
-            }
-          } catch (e) {
-            $exceptionHandler(e, startingTag($compileNode));
-          }
-        }
-
-        if (directive.terminal) {
-          nodeLinkFn.terminal = true;
-          terminalPriority = Math.max(terminalPriority, directive.priority);
-        }
-
-      }
-
-      nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
-      nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn;
-
-      // might be normal or delayed nodeLinkFn depending on if templateUrl is present
-      return nodeLinkFn;
-
-      ////////////////////
-
-      function addLinkFns(pre, post, attrStart, attrEnd) {
-        if (pre) {
-          if (attrStart) pre = groupElementsLinkFnWrapper(pre, attrStart, attrEnd);
-          pre.require = directive.require;
-          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
-            pre = cloneAndAnnotateFn(pre, {isolateScope: true});
-          }
-          preLinkFns.push(pre);
-        }
-        if (post) {
-          if (attrStart) post = groupElementsLinkFnWrapper(post, attrStart, attrEnd);
-          post.require = directive.require;
-          if (newIsolateScopeDirective === directive || directive.$$isolateScope) {
-            post = cloneAndAnnotateFn(post, {isolateScope: true});
-          }
-          postLinkFns.push(post);
-        }
-      }
-
-
-      function getControllers(require, $element, elementControllers) {
-        var value, retrievalMethod = 'data', optional = false;
-        if (isString(require)) {
-          while((value = require.charAt(0)) == '^' || value == '?') {
-            require = require.substr(1);
-            if (value == '^') {
-              retrievalMethod = 'inheritedData';
-            }
-            optional = optional || value == '?';
-          }
-          value = null;
-
-          if (elementControllers && retrievalMethod === 'data') {
-            value = elementControllers[require];
-          }
-          value = value || $element[retrievalMethod]('$' + require + 'Controller');
-
-          if (!value && !optional) {
-            throw $compileMinErr('ctreq',
-                "Controller '{0}', required by directive '{1}', can't be found!",
-                require, directiveName);
-          }
-          return value;
-        } else if (isArray(require)) {
-          value = [];
-          forEach(require, function(require) {
-            value.push(getControllers(require, $element, elementControllers));
-          });
-        }
-        return value;
-      }
-
-
-      function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
-        var attrs, $element, i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn;
-
-        if (compileNode === linkNode) {
-          attrs = templateAttrs;
-        } else {
-          attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr));
-        }
-        $element = attrs.$$element;
-
-        if (newIsolateScopeDirective) {
-          var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/;
-          var $linkNode = jqLite(linkNode);
-
-          isolateScope = scope.$new(true);
-
-          if (templateDirective && (templateDirective === newIsolateScopeDirective.$$originalDirective)) {
-            $linkNode.data('$isolateScope', isolateScope) ;
-          } else {
-            $linkNode.data('$isolateScopeNoTemplate', isolateScope);
-          }
-
-
-
-          safeAddClass($linkNode, 'ng-isolate-scope');
-
-          forEach(newIsolateScopeDirective.scope, function(definition, scopeName) {
-            var match = definition.match(LOCAL_REGEXP) || [],
-                attrName = match[3] || scopeName,
-                optional = (match[2] == '?'),
-                mode = match[1], // @, =, or &
-                lastValue,
-                parentGet, parentSet, compare;
-
-            isolateScope.$$isolateBindings[scopeName] = mode + attrName;
-
-            switch (mode) {
-
-              case '@':
-                attrs.$observe(attrName, function(value) {
-                  isolateScope[scopeName] = value;
-                });
-                attrs.$$observers[attrName].$$scope = scope;
-                if( attrs[attrName] ) {
-                  // If the attribute has been provided then we trigger an interpolation to ensure
-                  // the value is there for use in the link fn
-                  isolateScope[scopeName] = $interpolate(attrs[attrName])(scope);
-                }
-                break;
-
-              case '=':
-                if (optional && !attrs[attrName]) {
-                  return;
-                }
-                parentGet = $parse(attrs[attrName]);
-                if (parentGet.literal) {
-                  compare = equals;
-                } else {
-                  compare = function(a,b) { return a === b; };
-                }
-                parentSet = parentGet.assign || function() {
-                  // reset the change, or we will throw this exception on every $digest
-                  lastValue = isolateScope[scopeName] = parentGet(scope);
-                  throw $compileMinErr('nonassign',
-                      "Expression '{0}' used with directive '{1}' is non-assignable!",
-                      attrs[attrName], newIsolateScopeDirective.name);
-                };
-                lastValue = isolateScope[scopeName] = parentGet(scope);
-                isolateScope.$watch(function parentValueWatch() {
-                  var parentValue = parentGet(scope);
-                  if (!compare(parentValue, isolateScope[scopeName])) {
-                    // we are out of sync and need to copy
-                    if (!compare(parentValue, lastValue)) {
-                      // parent changed and it has precedence
-                      isolateScope[scopeName] = parentValue;
-                    } else {
-                      // if the parent can be assigned then do so
-                      parentSet(scope, parentValue = isolateScope[scopeName]);
-                    }
-                  }
-                  return lastValue = parentValue;
-                }, null, parentGet.literal);
-                break;
-
-              case '&':
-                parentGet = $parse(attrs[attrName]);
-                isolateScope[scopeName] = function(locals) {
-                  return parentGet(scope, locals);
-                };
-                break;
-
-              default:
-                throw $compileMinErr('iscp',
-                    "Invalid isolate scope definition for directive '{0}'." +
-                    " Definition: {... {1}: '{2}' ...}",
-                    newIsolateScopeDirective.name, scopeName, definition);
-            }
-          });
-        }
-        transcludeFn = boundTranscludeFn && controllersBoundTransclude;
-        if (controllerDirectives) {
-          forEach(controllerDirectives, function(directive) {
-            var locals = {
-              $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
-              $element: $element,
-              $attrs: attrs,
-              $transclude: transcludeFn
-            }, controllerInstance;
-
-            controller = directive.controller;
-            if (controller == '@') {
-              controller = attrs[directive.name];
-            }
-
-            controllerInstance = $controller(controller, locals);
-            // For directives with element transclusion the element is a comment,
-            // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
-            // clean up (http://bugs.jquery.com/ticket/8335).
-            // Instead, we save the controllers for the element in a local hash and attach to .data
-            // later, once we have the actual element.
-            elementControllers[directive.name] = controllerInstance;
-            if (!hasElementTranscludeDirective) {
-              $element.data('$' + directive.name + 'Controller', controllerInstance);
-            }
-
-            if (directive.controllerAs) {
-              locals.$scope[directive.controllerAs] = controllerInstance;
-            }
-          });
-        }
-
-        // PRELINKING
-        for(i = 0, ii = preLinkFns.length; i < ii; i++) {
-          try {
-            linkFn = preLinkFns[i];
-            linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
-                linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
-          } catch (e) {
-            $exceptionHandler(e, startingTag($element));
-          }
-        }
-
-        // RECURSION
-        // We only pass the isolate scope, if the isolate directive has a template,
-        // otherwise the child elements do not belong to the isolate directive.
-        var scopeToChild = scope;
-        if (newIsolateScopeDirective && (newIsolateScopeDirective.template || newIsolateScopeDirective.templateUrl === null)) {
-          scopeToChild = isolateScope;
-        }
-        childLinkFn && childLinkFn(scopeToChild, linkNode.childNodes, undefined, boundTranscludeFn);
-
-        // POSTLINKING
-        for(i = postLinkFns.length - 1; i >= 0; i--) {
-          try {
-            linkFn = postLinkFns[i];
-            linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
-                linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
-          } catch (e) {
-            $exceptionHandler(e, startingTag($element));
-          }
-        }
-
-        // This is the function that is injected as `$transclude`.
-        function controllersBoundTransclude(scope, cloneAttachFn) {
-          var transcludeControllers;
-
-          // no scope passed
-          if (arguments.length < 2) {
-            cloneAttachFn = scope;
-            scope = undefined;
-          }
-
-          if (hasElementTranscludeDirective) {
-            transcludeControllers = elementControllers;
-          }
-
-          return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers);
-        }
-      }
-    }
-
-    function markDirectivesAsIsolate(directives) {
-      // mark all directives as needing isolate scope.
-      for (var j = 0, jj = directives.length; j < jj; j++) {
-        directives[j] = inherit(directives[j], {$$isolateScope: true});
-      }
-    }
-
-    /**
-     * looks up the directive and decorates it with exception handling and proper parameters. We
-     * call this the boundDirective.
-     *
-     * @param {string} name name of the directive to look up.
-     * @param {string} location The directive must be found in specific format.
-     *   String containing any of theses characters:
-     *
-     *   * `E`: element name
-     *   * `A': attribute
-     *   * `C`: class
-     *   * `M`: comment
-     * @returns true if directive was added.
-     */
-    function addDirective(tDirectives, name, location, maxPriority, ignoreDirective, startAttrName,
-                          endAttrName) {
-      if (name === ignoreDirective) return null;
-      var match = null;
-      if (hasDirectives.hasOwnProperty(name)) {
-        for(var directive, directives = $injector.get(name + Suffix),
-            i = 0, ii = directives.length; i<ii; i++) {
-          try {
-            directive = directives[i];
-            if ( (maxPriority === undefined || maxPriority > directive.priority) &&
-                 directive.restrict.indexOf(location) != -1) {
-              if (startAttrName) {
-                directive = inherit(directive, {$$start: startAttrName, $$end: endAttrName});
-              }
-              tDirectives.push(directive);
-              match = directive;
-            }
-          } catch(e) { $exceptionHandler(e); }
-        }
-      }
-      return match;
-    }
-
-
-    /**
-     * When the element is replaced with HTML template then the new attributes
-     * on the template need to be merged with the existing attributes in the DOM.
-     * The desired effect is to have both of the attributes present.
-     *
-     * @param {object} dst destination attributes (original DOM)
-     * @param {object} src source attributes (from the directive template)
-     */
-    function mergeTemplateAttributes(dst, src) {
-      var srcAttr = src.$attr,
-          dstAttr = dst.$attr,
-          $element = dst.$$element;
-
-      // reapply the old attributes to the new element
-      forEach(dst, function(value, key) {
-        if (key.charAt(0) != '$') {
-          if (src[key]) {
-            value += (key === 'style' ? ';' : ' ') + src[key];
-          }
-          dst.$set(key, value, true, srcAttr[key]);
-        }
-      });
-
-      // copy the new attributes on the old attrs object
-      forEach(src, function(value, key) {
-        if (key == 'class') {
-          safeAddClass($element, value);
-          dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
-        } else if (key == 'style') {
-          $element.attr('style', $element.attr('style') + ';' + value);
-          dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
-          // `dst` will never contain hasOwnProperty as DOM parser won't let it.
-          // You will get an "InvalidCharacterError: DOM Exception 5" error if you
-          // have an attribute like "has-own-property" or "data-has-own-property", etc.
-        } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) {
-          dst[key] = value;
-          dstAttr[key] = srcAttr[key];
-        }
-      });
-    }
-
-
-    function compileTemplateUrl(directives, $compileNode, tAttrs,
-        $rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
-      var linkQueue = [],
-          afterTemplateNodeLinkFn,
-          afterTemplateChildLinkFn,
-          beforeTemplateCompileNode = $compileNode[0],
-          origAsyncDirective = directives.shift(),
-          // The fact that we have to copy and patch the directive seems wrong!
-          derivedSyncDirective = extend({}, origAsyncDirective, {
-            templateUrl: null, transclude: null, replace: null, $$originalDirective: origAsyncDirective
-          }),
-          templateUrl = (isFunction(origAsyncDirective.templateUrl))
-              ? origAsyncDirective.templateUrl($compileNode, tAttrs)
-              : origAsyncDirective.templateUrl;
-
-      $compileNode.empty();
-
-      $http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
-        success(function(content) {
-          var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
-
-          content = denormalizeTemplate(content);
-
-          if (origAsyncDirective.replace) {
-            $template = jqLite('<div>' + trim(content) + '</div>').contents();
-            compileNode = $template[0];
-
-            if ($template.length != 1 || compileNode.nodeType !== 1) {
-              throw $compileMinErr('tplrt',
-                  "Template for directive '{0}' must have exactly one root element. {1}",
-                  origAsyncDirective.name, templateUrl);
-            }
-
-            tempTemplateAttrs = {$attr: {}};
-            replaceWith($rootElement, $compileNode, compileNode);
-            var templateDirectives = collectDirectives(compileNode, [], tempTemplateAttrs);
-
-            if (isObject(origAsyncDirective.scope)) {
-              markDirectivesAsIsolate(templateDirectives);
-            }
-            directives = templateDirectives.concat(directives);
-            mergeTemplateAttributes(tAttrs, tempTemplateAttrs);
-          } else {
-            compileNode = beforeTemplateCompileNode;
-            $compileNode.html(content);
-          }
-
-          directives.unshift(derivedSyncDirective);
-
-          afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
-              childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns,
-              previousCompileContext);
-          forEach($rootElement, function(node, i) {
-            if (node == compileNode) {
-              $rootElement[i] = $compileNode[0];
-            }
-          });
-          afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn);
-
-
-          while(linkQueue.length) {
-            var scope = linkQueue.shift(),
-                beforeTemplateLinkNode = linkQueue.shift(),
-                linkRootElement = linkQueue.shift(),
-                boundTranscludeFn = linkQueue.shift(),
-                linkNode = $compileNode[0];
-
-            if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
-              // it was cloned therefore we have to clone as well.
-              linkNode = jqLiteClone(compileNode);
-              replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
-            }
-            if (afterTemplateNodeLinkFn.transclude) {
-              childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude);
-            } else {
-              childBoundTranscludeFn = boundTranscludeFn;
-            }
-            afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
-              childBoundTranscludeFn);
-          }
-          linkQueue = null;
-        }).
-        error(function(response, code, headers, config) {
-          throw $compileMinErr('tpload', 'Failed to load template: {0}', config.url);
-        });
-
-      return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
-        if (linkQueue) {
-          linkQueue.push(scope);
-          linkQueue.push(node);
-          linkQueue.push(rootElement);
-          linkQueue.push(boundTranscludeFn);
-        } else {
-          afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, boundTranscludeFn);
-        }
-      };
-    }
-
-
-    /**
-     * Sorting function for bound directives.
-     */
-    function byPriority(a, b) {
-      var diff = b.priority - a.priority;
-      if (diff !== 0) return diff;
-      if (a.name !== b.name) return (a.name < b.name) ? -1 : 1;
-      return a.index - b.index;
-    }
-
-
-    function assertNoDuplicate(what, previousDirective, directive, element) {
-      if (previousDirective) {
-        throw $compileMinErr('multidir', 'Multiple directives [{0}, {1}] asking for {2} on: {3}',
-            previousDirective.name, directive.name, what, startingTag(element));
-      }
-    }
-
-
-    function addTextInterpolateDirective(directives, text) {
-      var interpolateFn = $interpolate(text, true);
-      if (interpolateFn) {
-        directives.push({
-          priority: 0,
-          compile: valueFn(function textInterpolateLinkFn(scope, node) {
-            var parent = node.parent(),
-                bindings = parent.data('$binding') || [];
-            bindings.push(interpolateFn);
-            safeAddClass(parent.data('$binding', bindings), 'ng-binding');
-            scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
-              node[0].nodeValue = value;
-            });
-          })
-        });
-      }
-    }
-
-
-    function getTrustedContext(node, attrNormalizedName) {
-      if (attrNormalizedName == "srcdoc") {
-        return $sce.HTML;
-      }
-      var tag = nodeName_(node);
-      // maction[xlink:href] can source SVG.  It's not limited to <maction>.
-      if (attrNormalizedName == "xlinkHref" ||
-          (tag == "FORM" && attrNormalizedName == "action") ||
-          (tag != "IMG" && (attrNormalizedName == "src" ||
-                            attrNormalizedName == "ngSrc"))) {
-        return $sce.RESOURCE_URL;
-      }
-    }
-
-
-    function addAttrInterpolateDirective(node, directives, value, name) {
-      var interpolateFn = $interpolate(value, true);
-
-      // no interpolation found -> ignore
-      if (!interpolateFn) return;
-
-
-      if (name === "multiple" && nodeName_(node) === "SELECT") {
-        throw $compileMinErr("selmulti",
-            "Binding to the 'multiple' attribute is not supported. Element: {0}",
-            startingTag(node));
-      }
-
-      directives.push({
-        priority: 100,
-        compile: function() {
-            return {
-              pre: function attrInterpolatePreLinkFn(scope, element, attr) {
-                var $$observers = (attr.$$observers || (attr.$$observers = {}));
-
-                if (EVENT_HANDLER_ATTR_REGEXP.test(name)) {
-                  throw $compileMinErr('nodomevents',
-                      "Interpolations for HTML DOM event attributes are disallowed.  Please use the " +
-                          "ng- versions (such as ng-click instead of onclick) instead.");
-                }
-
-                // we need to interpolate again, in case the attribute value has been updated
-                // (e.g. by another directive's compile function)
-                interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name));
-
-                // if attribute was updated so that there is no interpolation going on we don't want to
-                // register any observers
-                if (!interpolateFn) return;
-
-                // TODO(i): this should likely be attr.$set(name, iterpolateFn(scope) so that we reset the
-                // actual attr value
-                attr[name] = interpolateFn(scope);
-                ($$observers[name] || ($$observers[name] = [])).$$inter = true;
-                (attr.$$observers && attr.$$observers[name].$$scope || scope).
-                  $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
-                    //special case for class attribute addition + removal
-                    //so that class changes can tap into the animation
-                    //hooks provided by the $animate service. Be sure to
-                    //skip animations when the first digest occurs (when
-                    //both the new and the old values are the same) since
-                    //the CSS classes are the non-interpolated values
-                    if(name === 'class' && newValue != oldValue) {
-                      attr.$updateClass(newValue, oldValue);
-                    } else {
-                      attr.$set(name, newValue);
-                    }
-                  });
-              }
-            };
-          }
-      });
-    }
-
-
-    /**
-     * This is a special jqLite.replaceWith, which can replace items which
-     * have no parents, provided that the containing jqLite collection is provided.
-     *
-     * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes
-     *                               in the root of the tree.
-     * @param {JqLite} elementsToRemove The jqLite element which we are going to replace. We keep
-     *                                  the shell, but replace its DOM node reference.
-     * @param {Node} newNode The new DOM node.
-     */
-    function replaceWith($rootElement, elementsToRemove, newNode) {
-      var firstElementToRemove = elementsToRemove[0],
-          removeCount = elementsToRemove.length,
-          parent = firstElementToRemove.parentNode,
-          i, ii;
-
-      if ($rootElement) {
-        for(i = 0, ii = $rootElement.length; i < ii; i++) {
-          if ($rootElement[i] == firstElementToRemove) {
-            $rootElement[i++] = newNode;
-            for (var j = i, j2 = j + removeCount - 1,
-                     jj = $rootElement.length;
-                 j < jj; j++, j2++) {
-              if (j2 < jj) {
-                $rootElement[j] = $rootElement[j2];
-              } else {
-                delete $rootElement[j];
-              }
-            }
-            $rootElement.length -= removeCount - 1;
-            break;
-          }
-        }
-      }
-
-      if (parent) {
-        parent.replaceChild(newNode, firstElementToRemove);
-      }
-      var fragment = document.createDocumentFragment();
-      fragment.appendChild(firstElementToRemove);
-      newNode[jqLite.expando] = firstElementToRemove[jqLite.expando];
-      for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
-        var element = elementsToRemove[k];
-        jqLite(element).remove(); // must do this way to clean up expando
-        fragment.appendChild(element);
-        delete elementsToRemove[k];
-      }
-
-      elementsToRemove[0] = newNode;
-      elementsToRemove.length = 1;
-    }
-
-
-    function cloneAndAnnotateFn(fn, annotation) {
-      return extend(function() { return fn.apply(null, arguments); }, fn, annotation);
-    }
-  }];
-}
-
-var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i;
-/**
- * Converts all accepted directives format into proper directive name.
- * All of these will become 'myDirective':
- *   my:Directive
- *   my-directive
- *   x-my-directive
- *   data-my:directive
- *
- * Also there is special case for Moz prefix starting with upper case letter.
- * @param name Name to normalize
- */
-function directiveNormalize(name) {
-  return camelCase(name.replace(PREFIX_REGEXP, ''));
-}
-
-/**
- * @ngdoc object
- * @name ng.$compile.directive.Attributes
- *
- * @description
- * A shared object between directive compile / linking functions which contains normalized DOM
- * element attributes. The values reflect current binding state `{{ }}`. The normalization is
- * needed since all of these are treated as equivalent in Angular:
- *
- *    <span ng:bind="a" ng-bind="a" data-ng-bind="a" x-ng-bind="a">
- */
-
-/**
- * @ngdoc property
- * @name ng.$compile.directive.Attributes#$attr
- * @propertyOf ng.$compile.directive.Attributes
- * @returns {object} A map of DOM element attribute names to the normalized name. This is
- *                   needed to do reverse lookup from normalized name back to actual name.
- */
-
-
-/**
- * @ngdoc function
- * @name ng.$compile.directive.Attributes#$set
- * @methodOf ng.$compile.directive.Attributes
- * @function
- *
- * @description
- * Set DOM element attribute value.
- *
- *
- * @param {string} name Normalized element attribute name of the property to modify. The name is
- *          revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr}
- *          property to the original name.
- * @param {string} value Value to set the attribute to. The value can be an interpolated string.
- */
-
-
-
-/**
- * Closure compiler type information
- */
-
-function nodesetLinkingFn(
-  /* angular.Scope */ scope,
-  /* NodeList */ nodeList,
-  /* Element */ rootElement,
-  /* function(Function) */ boundTranscludeFn
-){}
-
-function directiveLinkingFn(
-  /* nodesetLinkingFn */ nodesetLinkingFn,
-  /* angular.Scope */ scope,
-  /* Node */ node,
-  /* Element */ rootElement,
-  /* function(Function) */ boundTranscludeFn
-){}
-
-function tokenDifference(str1, str2) {
-  var values = '',
-      tokens1 = str1.split(/\s+/),
-      tokens2 = str2.split(/\s+/);
-
-  outer:
-  for(var i = 0; i < tokens1.length; i++) {
-    var token = tokens1[i];
-    for(var j = 0; j < tokens2.length; j++) {
-      if(token == tokens2[j]) continue outer;
-    }
-    values += (values.length > 0 ? ' ' : '') + token;
-  }
-  return values;
-}
-
-/**
- * @ngdoc object
- * @name ng.$controllerProvider
- * @description
- * The {@link ng.$controller $controller service} is used by Angular to create new
- * controllers.
- *
- * This provider allows controller registration via the
- * {@link ng.$controllerProvider#methods_register register} method.
- */
-function $ControllerProvider() {
-  var controllers = {},
-      CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
-
-
-  /**
-   * @ngdoc function
-   * @name ng.$controllerProvider#register
-   * @methodOf ng.$controllerProvider
-   * @param {string|Object} name Controller name, or an object map of controllers where the keys are
-   *    the names and the values are the constructors.
-   * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
-   *    annotations in the array notation).
-   */
-  this.register = function(name, constructor) {
-    assertNotHasOwnProperty(name, 'controller');
-    if (isObject(name)) {
-      extend(controllers, name);
-    } else {
-      controllers[name] = constructor;
-    }
-  };
-
-
-  this.$get = ['$injector', '$window', function($injector, $window) {
-
-    /**
-     * @ngdoc function
-     * @name ng.$controller
-     * @requires $injector
-     *
-     * @param {Function|string} constructor If called with a function then it's considered to be the
-     *    controller constructor function. Otherwise it's considered to be a string which is used
-     *    to retrieve the controller constructor using the following steps:
-     *
-     *    * check if a controller with given name is registered via `$controllerProvider`
-     *    * check if evaluating the string on the current scope returns a constructor
-     *    * check `window[constructor]` on the global `window` object
-     *
-     * @param {Object} locals Injection locals for Controller.
-     * @return {Object} Instance of given controller.
-     *
-     * @description
-     * `$controller` service is responsible for instantiating controllers.
-     *
-     * It's just a simple call to {@link AUTO.$injector $injector}, but extracted into
-     * a service, so that one can override this service with {@link https://gist.github.com/1649788
-     * BC version}.
-     */
-    return function(expression, locals) {
-      var instance, match, constructor, identifier;
-
-      if(isString(expression)) {
-        match = expression.match(CNTRL_REG),
-        constructor = match[1],
-        identifier = match[3];
-        expression = controllers.hasOwnProperty(constructor)
-            ? controllers[constructor]
-            : getter(locals.$scope, constructor, true) || getter($window, constructor, true);
-
-        assertArgFn(expression, constructor, true);
-      }
-
-      instance = $injector.instantiate(expression, locals);
-
-      if (identifier) {
-        if (!(locals && typeof locals.$scope == 'object')) {
-          throw minErr('$controller')('noscp',
-              "Cannot export controller '{0}' as '{1}'! No $scope object provided via `locals`.",
-              constructor || expression.name, identifier);
-        }
-
-        locals.$scope[identifier] = instance;
-      }
-
-      return instance;
-    };
-  }];
-}
-
-/**
- * @ngdoc object
- * @name ng.$document
- * @requires $window
- *
- * @description
- * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`
- * element.
- */
-function $DocumentProvider(){
-  this.$get = ['$window', function(window){
-    return jqLite(window.document);
-  }];
-}
-
-/**
- * @ngdoc function
- * @name ng.$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 overridden by
- * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
- *
- * ## Example:
- * 
- * <pre>
- *   angular.module('exceptionOverride', []).factory('$exceptionHandler', function () {
- *     return function (exception, cause) {
- *       exception.message += ' (caused by "' + cause + '")';
- *       throw exception;
- *     };
- *   });
- * </pre>
- * 
- * This example will override the normal action of `$exceptionHandler`, to make angular
- * exceptions fail hard when they happen, instead of just logging to the console.
- *
- * @param {Error} exception Exception associated with the error.
- * @param {string=} cause optional information about the context in which
- *       the error was thrown.
- *
- */
-function $ExceptionHandlerProvider() {
-  this.$get = ['$log', function($log) {
-    return function(exception, cause) {
-      $log.error.apply($log, arguments);
-    };
-  }];
-}
-
-/**
- * Parse headers into key value object
- *
- * @param {string} headers Raw headers as a string
- * @returns {Object} Parsed headers as key value object
- */
-function parseHeaders(headers) {
-  var parsed = {}, key, val, i;
-
-  if (!headers) return parsed;
-
-  forEach(headers.split('\n'), function(line) {
-    i = line.indexOf(':');
-    key = lowercase(trim(line.substr(0, i)));
-    val = trim(line.substr(i + 1));
-
-    if (key) {
-      if (parsed[key]) {
-        parsed[key] += ', ' + val;
-      } else {
-        parsed[key] = val;
-      }
-    }
-  });
-
-  return parsed;
-}
-
-
-/**
- * Returns a function that provides access to parsed headers.
- *
- * Headers are lazy parsed when first requested.
- * @see parseHeaders
- *
- * @param {(string|Object)} headers Headers to provide access to.
- * @returns {function(string=)} Returns a getter function which if called with:
- *
- *   - if called with single an argument returns a single header value or null
- *   - if called with no arguments returns an object containing all headers.
- */
-function headersGetter(headers) {
-  var headersObj = isObject(headers) ? headers : undefined;
-
-  return function(name) {
-    if (!headersObj) headersObj =  parseHeaders(headers);
-
-    if (name) {
-      return headersObj[lowercase(name)] || null;
-    }
-
-    return headersObj;
-  };
-}
-
-
-/**
- * Chain all given functions
- *
- * This function is used for both request and response transforming
- *
- * @param {*} data Data to transform.
- * @param {function(string=)} headers Http headers getter fn.
- * @param {(function|Array.<function>)} fns Function or an array of functions.
- * @returns {*} Transformed data.
- */
-function transformData(data, headers, fns) {
-  if (isFunction(fns))
-    return fns(data, headers);
-
-  forEach(fns, function(fn) {
-    data = fn(data, headers);
-  });
-
-  return data;
-}
-
-
-function isSuccess(status) {
-  return 200 <= status && status < 300;
-}
-
-
-function $HttpProvider() {
-  var JSON_START = /^\s*(\[|\{[^\{])/,
-      JSON_END = /[\}\]]\s*$/,
-      PROTECTION_PREFIX = /^\)\]\}',?\n/,
-      CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'};
-
-  var defaults = this.defaults = {
-    // transform incoming response data
-    transformResponse: [function(data) {
-      if (isString(data)) {
-        // strip json vulnerability protection prefix
-        data = data.replace(PROTECTION_PREFIX, '');
-        if (JSON_START.test(data) && JSON_END.test(data))
-          data = fromJson(data);
-      }
-      return data;
-    }],
-
-    // transform outgoing request data
-    transformRequest: [function(d) {
-      return isObject(d) && !isFile(d) ? toJson(d) : d;
-    }],
-
-    // default headers
-    headers: {
-      common: {
-        'Accept': 'application/json, text/plain, */*'
-      },
-      post:   CONTENT_TYPE_APPLICATION_JSON,
-      put:    CONTENT_TYPE_APPLICATION_JSON,
-      patch:  CONTENT_TYPE_APPLICATION_JSON
-    },
-
-    xsrfCookieName: 'XSRF-TOKEN',
-    xsrfHeaderName: 'X-XSRF-TOKEN'
-  };
-
-  /**
-   * Are ordered by request, i.e. they are applied in the same order as the
-   * array, on request, but reverse order, on response.
-   */
-  var interceptorFactories = this.interceptors = [];
-
-  /**
-   * For historical reasons, response interceptors are ordered by the order in which
-   * they are applied to the response. (This is the opposite of interceptorFactories)
-   */
-  var responseInterceptorFactories = this.responseInterceptors = [];
-
-  this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
-      function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {
-
-    var defaultCache = $cacheFactory('$http');
-
-    /**
-     * Interceptors stored in reverse order. Inner interceptors before outer interceptors.
-     * The reversal is needed so that we can build up the interception chain around the
-     * server request.
-     */
-    var reversedInterceptors = [];
-
-    forEach(interceptorFactories, function(interceptorFactory) {
-      reversedInterceptors.unshift(isString(interceptorFactory)
-          ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
-    });
-
-    forEach(responseInterceptorFactories, function(interceptorFactory, index) {
-      var responseFn = isString(interceptorFactory)
-          ? $injector.get(interceptorFactory)
-          : $injector.invoke(interceptorFactory);
-
-      /**
-       * Response interceptors go before "around" interceptors (no real reason, just
-       * had to pick one.) But they are already reversed, so we can't use unshift, hence
-       * the splice.
-       */
-      reversedInterceptors.splice(index, 0, {
-        response: function(response) {
-          return responseFn($q.when(response));
-        },
-        responseError: function(response) {
-          return responseFn($q.reject(response));
-        }
-      });
-    });
-
-
-    /**
-     * @ngdoc function
-     * @name ng.$http
-     * @requires $httpBackend
-     * @requires $browser
-     * @requires $cacheFactory
-     * @requires $rootScope
-     * @requires $q
-     * @requires $injector
-     *
-     * @description
-     * The `$http` service is a core Angular service that facilitates communication with the remote
-     * HTTP servers via the browser's {@link https://developer.mozilla.org/en/xmlhttprequest
-     * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}.
-     *
-     * For unit testing applications that use `$http` service, see
-     * {@link ngMock.$httpBackend $httpBackend mock}.
-     *
-     * For a higher level of abstraction, please check out the {@link ngResource.$resource
-     * $resource} service.
-     *
-     * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by
-     * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage
-     * it is important to familiarize yourself with these APIs and the guarantees they provide.
-     *
-     *
-     * # General usage
-     * The `$http` service is a function which takes a single argument — a configuration object —
-     * that is used to generate an HTTP request and returns  a {@link ng.$q promise}
-     * with two $http specific methods: `success` and `error`.
-     *
-     * <pre>
-     *   $http({method: 'GET', url: '/someUrl'}).
-     *     success(function(data, status, headers, config) {
-     *       // this callback will be called asynchronously
-     *       // when the response is available
-     *     }).
-     *     error(function(data, status, headers, config) {
-     *       // called asynchronously if an error occurs
-     *       // or server returns response with an error status.
-     *     });
-     * </pre>
-     *
-     * Since the returned value of calling the $http function is a `promise`, you can also use
-     * the `then` method to register callbacks, and these callbacks will receive a single argument –
-     * an object representing the response. See the API signature and type info below for more
-     * details.
-     *
-     * A response status code between 200 and 299 is considered a success status and
-     * will result in the success callback being called. Note that if the response is a redirect,
-     * XMLHttpRequest will transparently follow it, meaning that the error callback will not be
-     * called for such responses.
-     * 
-     * # Calling $http from outside AngularJS
-     * The `$http` service will not actually send the request until the next `$digest()` is
-     * executed. Normally this is not an issue, since almost all the time your call to `$http` will
-     * be from within a `$apply()` block.
-     * If you are calling `$http` from outside Angular, then you should wrap it in a call to
-     * `$apply` to cause a $digest to occur and also to handle errors in the block correctly.
-     *
-     * ```
-     * $scope.$apply(function() {
-     *   $http(...);
-     * });
-     * ```
-     *
-     * # Writing Unit Tests that use $http
-     * When unit testing you are mostly responsible for scheduling the `$digest` cycle. If you do
-     * not trigger a `$digest` before calling `$httpBackend.flush()` then the request will not have
-     * been made and `$httpBackend.expect(...)` expectations will fail.  The solution is to run the
-     * code that calls the `$http()` method inside a $apply block as explained in the previous
-     * section.
-     *
-     * ```
-     * $httpBackend.expectGET(...);
-     * $scope.$apply(function() {
-     *   $http.get(...);
-     * });
-     * $httpBackend.flush();
-     * ```
-     *
-     * # Shortcut methods
-     *
-     * Since all invocations of the $http service require passing in an HTTP method and URL, and
-     * POST/PUT requests require request data to be provided as well, shortcut methods
-     * were created:
-     *
-     * <pre>
-     *   $http.get('/someUrl').success(successCallback);
-     *   $http.post('/someUrl', data).success(successCallback);
-     * </pre>
-     *
-     * Complete list of shortcut methods:
-     *
-     * - {@link ng.$http#methods_get $http.get}
-     * - {@link ng.$http#methods_head $http.head}
-     * - {@link ng.$http#methods_post $http.post}
-     * - {@link ng.$http#methods_put $http.put}
-     * - {@link ng.$http#methods_delete $http.delete}
-     * - {@link ng.$http#methods_jsonp $http.jsonp}
-     *
-     *
-     * # Setting HTTP Headers
-     *
-     * The $http service will automatically add certain HTTP headers to all requests. These defaults
-     * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration
-     * object, which currently contains this default configuration:
-     *
-     * - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
-     *   - `Accept: application/json, text/plain, * / *`
-     * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests)
-     *   - `Content-Type: application/json`
-     * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests)
-     *   - `Content-Type: application/json`
-     *
-     * To add or overwrite these defaults, simply add or remove a property from these configuration
-     * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object
-     * with the lowercased HTTP method name as the key, e.g.
-     * `$httpProvider.defaults.headers.get = { 'My-Header' : 'value' }.
-     *
-     * The defaults can also be set at runtime via the `$http.defaults` object in the same
-     * fashion. In addition, you can supply a `headers` property in the config object passed when
-     * calling `$http(config)`, which overrides the defaults without changing them globally.
-     *
-     *
-     * # Transforming Requests and Responses
-     *
-     * Both requests and responses can be transformed using transform functions. By default, Angular
-     * applies these transformations:
-     *
-     * Request transformations:
-     *
-     * - If the `data` property of the request configuration object contains an object, serialize it
-     *   into JSON format.
-     *
-     * Response transformations:
-     *
-     *  - If XSRF prefix is detected, strip it (see Security Considerations section below).
-     *  - If JSON response is detected, deserialize it using a JSON parser.
-     *
-     * To globally augment or override the default transforms, modify the
-     * `$httpProvider.defaults.transformRequest` and `$httpProvider.defaults.transformResponse`
-     * properties. These properties are by default an array of transform functions, which allows you
-     * to `push` or `unshift` a new transformation function into the transformation chain. You can
-     * also decide to completely override any default transformations by assigning your
-     * transformation functions to these properties directly without the array wrapper.
-     *
-     * Similarly, to locally override the request/response transforms, augment the
-     * `transformRequest` and/or `transformResponse` properties of the configuration object passed
-     * into `$http`.
-     *
-     *
-     * # Caching
-     *
-     * To enable caching, set the request configuration `cache` property to `true` (to use default
-     * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
-     * When the cache is enabled, `$http` stores the response from the server in the specified
-     * cache. The next time the same request is made, the response is served from the cache without
-     * sending a request to the server.
-     *
-     * Note that even if the response is served from cache, delivery of the data is asynchronous in
-     * the same way that real requests are.
-     *
-     * If there are multiple GET requests for the same URL that should be cached using the same
-     * cache, but the cache is not populated yet, only one request to the server will be made and
-     * the remaining requests will be fulfilled using the response from the first request.
-     *
-     * You can change the default cache to a new object (built with
-     * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
-     * {@link ng.$http#properties_defaults `$http.defaults.cache`} property. All requests who set
-     * their `cache` property to `true` will now use this cache object.
-     *
-     * If you set the default cache to `false` then only requests that specify their own custom
-     * cache object will be cached.
-     *
-     * # Interceptors
-     *
-     * Before you start creating interceptors, be sure to understand the
-     * {@link ng.$q $q and deferred/promise APIs}.
-     *
-     * For purposes of global error handling, authentication, or any kind of synchronous or
-     * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be
-     * able to intercept requests before they are handed to the server and
-     * responses before they are handed over to the application code that
-     * initiated these requests. The interceptors leverage the {@link ng.$q
-     * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing.
-     *
-     * The interceptors are service factories that are registered with the `$httpProvider` by
-     * adding them to the `$httpProvider.interceptors` array. The factory is called and
-     * injected with dependencies (if specified) and returns the interceptor.
-     *
-     * There are two kinds of interceptors (and two kinds of rejection interceptors):
-     *
-     *   * `request`: interceptors get called with http `config` object. The function is free to
-     *     modify the `config` or create a new one. The function needs to return the `config`
-     *     directly or as a promise.
-     *   * `requestError`: interceptor gets called when a previous interceptor threw an error or
-     *     resolved with a rejection.
-     *   * `response`: interceptors get called with http `response` object. The function is free to
-     *     modify the `response` or create a new one. The function needs to return the `response`
-     *     directly or as a promise.
-     *   * `responseError`: interceptor gets called when a previous interceptor threw an error or
-     *     resolved with a rejection.
-     *
-     *
-     * <pre>
-     *   // register the interceptor as a service
-     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
-     *     return {
-     *       // optional method
-     *       'request': function(config) {
-     *         // do something on success
-     *         return config || $q.when(config);
-     *       },
-     *
-     *       // optional method
-     *      'requestError': function(rejection) {
-     *         // do something on error
-     *         if (canRecover(rejection)) {
-     *           return responseOrNewPromise
-     *         }
-     *         return $q.reject(rejection);
-     *       },
-     *
-     *
-     *
-     *       // optional method
-     *       'response': function(response) {
-     *         // do something on success
-     *         return response || $q.when(response);
-     *       },
-     *
-     *       // optional method
-     *      'responseError': function(rejection) {
-     *         // do something on error
-     *         if (canRecover(rejection)) {
-     *           return responseOrNewPromise
-     *         }
-     *         return $q.reject(rejection);
-     *       };
-     *     }
-     *   });
-     *
-     *   $httpProvider.interceptors.push('myHttpInterceptor');
-     *
-     *
-     *   // register the interceptor via an anonymous factory
-     *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
-     *     return {
-     *      'request': function(config) {
-     *          // same as above
-     *       },
-     *       'response': function(response) {
-     *          // same as above
-     *       }
-     *     };
-     *   });
-     * </pre>
-     *
-     * # Response interceptors (DEPRECATED)
-     *
-     * Before you start creating interceptors, be sure to understand the
-     * {@link ng.$q $q and deferred/promise APIs}.
-     *
-     * For purposes of global error handling, authentication or any kind of synchronous or
-     * asynchronous preprocessing of received responses, it is desirable to be able to intercept
-     * responses for http requests before they are handed over to the application code that
-     * initiated these requests. The response interceptors leverage the {@link ng.$q
-     * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.
-     *
-     * The interceptors are service factories that are registered with the $httpProvider by
-     * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and
-     * injected with dependencies (if specified) and returns the interceptor  — a function that
-     * takes a {@link ng.$q promise} and returns the original or a new promise.
-     *
-     * <pre>
-     *   // register the interceptor as a service
-     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
-     *     return function(promise) {
-     *       return promise.then(function(response) {
-     *         // do something on success
-     *         return response;
-     *       }, function(response) {
-     *         // do something on error
-     *         if (canRecover(response)) {
-     *           return responseOrNewPromise
-     *         }
-     *         return $q.reject(response);
-     *       });
-     *     }
-     *   });
-     *
-     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');
-     *
-     *
-     *   // register the interceptor via an anonymous factory
-     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {
-     *     return function(promise) {
-     *       // same as above
-     *     }
-     *   });
-     * </pre>
-     *
-     *
-     * # Security Considerations
-     *
-     * When designing web applications, consider security threats from:
-     *
-     * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
-     *   JSON vulnerability}
-     * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF}
-     *
-     * Both server and the client must cooperate in order to eliminate these threats. Angular comes
-     * pre-configured with strategies that address these issues, but for this to work backend server
-     * cooperation is required.
-     *
-     * ## JSON Vulnerability Protection
-     *
-     * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx
-     * JSON vulnerability} allows third party website to turn your JSON resource URL into
-     * {@link http://en.wikipedia.org/wiki/JSONP JSONP} request under some conditions. To
-     * counter this your server can prefix all JSON requests with following string `")]}',\n"`.
-     * Angular will automatically strip the prefix before processing it as JSON.
-     *
-     * For example if your server needs to return:
-     * <pre>
-     * ['one','two']
-     * </pre>
-     *
-     * which is vulnerable to attack, your server can return:
-     * <pre>
-     * )]}',
-     * ['one','two']
-     * </pre>
-     *
-     * Angular will strip the prefix, before processing the JSON.
-     *
-     *
-     * ## Cross Site Request Forgery (XSRF) Protection
-     *
-     * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which
-     * an unauthorized site can gain your user's private data. Angular provides a mechanism
-     * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
-     * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
-     * JavaScript that runs on your domain could read the cookie, your server can be assured that
-     * the XHR came from JavaScript running on your domain. The header will not be set for
-     * cross-domain requests.
-     *
-     * To take advantage of this, your server needs to set a token in a JavaScript readable session
-     * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
-     * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
-     * that only JavaScript running on your domain could have sent the request. The token must be
-     * unique for each user and must be verifiable by the server (to prevent the JavaScript from
-     * making up its own tokens). We recommend that the token is a digest of your site's
-     * authentication cookie with a {@link https://en.wikipedia.org/wiki/Salt_(cryptography) salt}
-     * for added security.
-     *
-     * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
-     * properties of either $httpProvider.defaults, or the per-request config object.
-     *
-     *
-     * @param {object} config Object describing the request to be made and how it should be
-     *    processed. The object has following properties:
-     *
-     *    - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc)
-     *    - **url** – `{string}` – Absolute or relative URL of the resource that is being requested.
-     *    - **params** – `{Object.<string|Object>}` – Map of strings or objects which will be turned
-     *      to `?key1=value1&key2=value2` after the url. If the value is not a string, it will be
-     *      JSONified.
-     *    - **data** – `{string|Object}` – Data to be sent as the request message data.
-     *    - **headers** – `{Object}` – Map of strings or functions which return strings representing
-     *      HTTP headers to send to the server. If the return value of a function is null, the
-     *      header will not be sent.
-     *    - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
-     *    - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
-     *    - **transformRequest** –
-     *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
-     *      transform function or an array of such functions. The transform function takes the http
-     *      request body and headers and returns its transformed (typically serialized) version.
-     *    - **transformResponse** –
-     *      `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
-     *      transform function or an array of such functions. The transform function takes the http
-     *      response body and headers and returns its transformed (typically deserialized) version.
-     *    - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
-     *      GET request, otherwise if a cache instance built with
-     *      {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
-     *      caching.
-     *    - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise}
-     *      that should abort the request when resolved.
-     *    - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the
-     *      XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
-     *      requests with credentials} for more information.
-     *    - **responseType** - `{string}` - see {@link
-     *      https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
-     *
-     * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
-     *   standard `then` method and two http specific methods: `success` and `error`. The `then`
-     *   method takes two arguments a success and an error callback which will be called with a
-     *   response object. The `success` and `error` methods take a single argument - a function that
-     *   will be called when the request succeeds or fails respectively. The arguments passed into
-     *   these functions are destructured representation of the response object passed into the
-     *   `then` method. The response object has these properties:
-     *
-     *   - **data** – `{string|Object}` – The response body transformed with the transform
-     *     functions.
-     *   - **status** – `{number}` – HTTP status code of the response.
-     *   - **headers** – `{function([headerName])}` – Header getter function.
-     *   - **config** – `{Object}` – The configuration object that was used to generate the request.
-     *
-     * @property {Array.<Object>} pendingRequests Array of config objects for currently pending
-     *   requests. This is primarily meant to be used for debugging purposes.
-     *
-     *
-     * @example
-<example>
-<file name="index.html">
-  <div ng-controller="FetchCtrl">
-    <select ng-model="method">
-      <option>GET</option>
-      <option>JSONP</option>
-    </select>
-    <input type="text" ng-model="url" size="80"/>
-    <button ng-click="fetch()">fetch</button><br>
-    <button ng-click="updateModel('GET', 'http-hello.html')">Sample GET</button>
-    <button
-      ng-click="updateModel('JSONP',
-                    'http://angularjs.org/greet.php?callback=JSON_CALLBACK&name=Super%20Hero')">
-      Sample JSONP
-    </button>
-    <button
-      ng-click="updateModel('JSONP', 'http://angularjs.org/doesntexist&callback=JSON_CALLBACK')">
-        Invalid JSONP
-      </button>
-    <pre>http status code: {{status}}</pre>
-    <pre>http response data: {{data}}</pre>
-  </div>
-</file>
-<file name="script.js">
-  function FetchCtrl($scope, $http, $templateCache) {
-    $scope.method = 'GET';
-    $scope.url = 'http-hello.html';
-
-    $scope.fetch = function() {
-      $scope.code = null;
-      $scope.response = null;
-
-      $http({method: $scope.method, url: $scope.url, cache: $templateCache}).
-        success(function(data, status) {
-          $scope.status = status;
-          $scope.data = data;
-        }).
-        error(function(data, status) {
-          $scope.data = data || "Request failed";
-          $scope.status = status;
-      });
-    };
-
-    $scope.updateModel = function(method, url) {
-      $scope.method = method;
-      $scope.url = url;
-    };
-  }
-</file>
-<file name="http-hello.html">
-  Hello, $http!
-</file>
-<file name="scenario.js">
-  it('should make an xhr GET request', function() {
-    element(':button:contains("Sample GET")').click();
-    element(':button:contains("fetch")').click();
-    expect(binding('status')).toBe('200');
-    expect(binding('data')).toMatch(/Hello, \$http!/);
-  });
-
-  it('should make a JSONP request to angularjs.org', function() {
-    element(':button:contains("Sample JSONP")').click();
-    element(':button:contains("fetch")').click();
-    expect(binding('status')).toBe('200');
-    expect(binding('data')).toMatch(/Super Hero!/);
-  });
-
-  it('should make JSONP request to invalid URL and invoke the error handler',
-      function() {
-    element(':button:contains("Invalid JSONP")').click();
-    element(':button:contains("fetch")').click();
-    expect(binding('status')).toBe('0');
-    expect(binding('data')).toBe('Request failed');
-  });
-</file>
-</example>
-     */
-    function $http(requestConfig) {
-      var config = {
-        transformRequest: defaults.transformRequest,
-        transformResponse: defaults.transformResponse
-      };
-      var headers = mergeHeaders(requestConfig);
-
-      extend(config, requestConfig);
-      config.headers = headers;
-      config.method = uppercase(config.method);
-
-      var xsrfValue = urlIsSameOrigin(config.url)
-          ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName]
-          : undefined;
-      if (xsrfValue) {
-        headers[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
-      }
-
-
-      var serverRequest = function(config) {
-        headers = config.headers;
-        var reqData = transformData(config.data, headersGetter(headers), config.transformRequest);
-
-        // strip content-type if data is undefined
-        if (isUndefined(config.data)) {
-          forEach(headers, function(value, header) {
-            if (lowercase(header) === 'content-type') {
-                delete headers[header];
-            }
-          });
-        }
-
-        if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
-          config.withCredentials = defaults.withCredentials;
-        }
-
-        // send request
-        return sendReq(config, reqData, headers).then(transformResponse, transformResponse);
-      };
-
-      var chain = [serverRequest, undefined];
-      var promise = $q.when(config);
-
-      // apply interceptors
-      forEach(reversedInterceptors, function(interceptor) {
-        if (interceptor.request || interceptor.requestError) {
-          chain.unshift(interceptor.request, interceptor.requestError);
-        }
-        if (interceptor.response || interceptor.responseError) {
-          chain.push(interceptor.response, interceptor.responseError);
-        }
-      });
-
-      while(chain.length) {
-        var thenFn = chain.shift();
-        var rejectFn = chain.shift();
-
-        promise = promise.then(thenFn, rejectFn);
-      }
-
-      promise.success = function(fn) {
-        promise.then(function(response) {
-          fn(response.data, response.status, response.headers, config);
-        });
-        return promise;
-      };
-
-      promise.error = function(fn) {
-        promise.then(null, function(response) {
-          fn(response.data, response.status, response.headers, config);
-        });
-        return promise;
-      };
-
-      return promise;
-
-      function transformResponse(response) {
-        // make a copy since the response must be cacheable
-        var resp = extend({}, response, {
-          data: transformData(response.data, response.headers, config.transformResponse)
-        });
-        return (isSuccess(response.status))
-          ? resp
-          : $q.reject(resp);
-      }
-
-      function mergeHeaders(config) {
-        var defHeaders = defaults.headers,
-            reqHeaders = extend({}, config.headers),
-            defHeaderName, lowercaseDefHeaderName, reqHeaderName;
-
-        defHeaders = extend({}, defHeaders.common, defHeaders[lowercase(config.method)]);
-
-        // execute if header value is function
-        execHeaders(defHeaders);
-        execHeaders(reqHeaders);
-
-        // using for-in instead of forEach to avoid unecessary iteration after header has been found
-        defaultHeadersIteration:
-        for (defHeaderName in defHeaders) {
-          lowercaseDefHeaderName = lowercase(defHeaderName);
-
-          for (reqHeaderName in reqHeaders) {
-            if (lowercase(reqHeaderName) === lowercaseDefHeaderName) {
-              continue defaultHeadersIteration;
-            }
-          }
-
-          reqHeaders[defHeaderName] = defHeaders[defHeaderName];
-        }
-
-        return reqHeaders;
-
-        function execHeaders(headers) {
-          var headerContent;
-
-          forEach(headers, function(headerFn, header) {
-            if (isFunction(headerFn)) {
-              headerContent = headerFn();
-              if (headerContent != null) {
-                headers[header] = headerContent;
-              } else {
-                delete headers[header];
-              }
-            }
-          });
-        }
-      }
-    }
-
-    $http.pendingRequests = [];
-
-    /**
-     * @ngdoc method
-     * @name ng.$http#get
-     * @methodOf ng.$http
-     *
-     * @description
-     * Shortcut method to perform `GET` request.
-     *
-     * @param {string} url Relative or absolute URL specifying the destination of the request
-     * @param {Object=} config Optional configuration object
-     * @returns {HttpPromise} Future object
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$http#delete
-     * @methodOf ng.$http
-     *
-     * @description
-     * Shortcut method to perform `DELETE` request.
-     *
-     * @param {string} url Relative or absolute URL specifying the destination of the request
-     * @param {Object=} config Optional configuration object
-     * @returns {HttpPromise} Future object
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$http#head
-     * @methodOf ng.$http
-     *
-     * @description
-     * Shortcut method to perform `HEAD` request.
-     *
-     * @param {string} url Relative or absolute URL specifying the destination of the request
-     * @param {Object=} config Optional configuration object
-     * @returns {HttpPromise} Future object
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$http#jsonp
-     * @methodOf ng.$http
-     *
-     * @description
-     * Shortcut method to perform `JSONP` request.
-     *
-     * @param {string} url Relative or absolute URL specifying the destination of the request.
-     *                     Should contain `JSON_CALLBACK` string.
-     * @param {Object=} config Optional configuration object
-     * @returns {HttpPromise} Future object
-     */
-    createShortMethods('get', 'delete', 'head', 'jsonp');
-
-    /**
-     * @ngdoc method
-     * @name ng.$http#post
-     * @methodOf ng.$http
-     *
-     * @description
-     * Shortcut method to perform `POST` request.
-     *
-     * @param {string} url Relative or absolute URL specifying the destination of the request
-     * @param {*} data Request content
-     * @param {Object=} config Optional configuration object
-     * @returns {HttpPromise} Future object
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$http#put
-     * @methodOf ng.$http
-     *
-     * @description
-     * Shortcut method to perform `PUT` request.
-     *
-     * @param {string} url Relative or absolute URL specifying the destination of the request
-     * @param {*} data Request content
-     * @param {Object=} config Optional configuration object
-     * @returns {HttpPromise} Future object
-     */
-    createShortMethodsWithData('post', 'put');
-
-        /**
-         * @ngdoc property
-         * @name ng.$http#defaults
-         * @propertyOf ng.$http
-         *
-         * @description
-         * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
-         * default headers, withCredentials as well as request and response transformations.
-         *
-         * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
-         */
-    $http.defaults = defaults;
-
-
-    return $http;
-
-
-    function createShortMethods(names) {
-      forEach(arguments, function(name) {
-        $http[name] = function(url, config) {
-          return $http(extend(config || {}, {
-            method: name,
-            url: url
-          }));
-        };
-      });
-    }
-
-
-    function createShortMethodsWithData(name) {
-      forEach(arguments, function(name) {
-        $http[name] = function(url, data, config) {
-          return $http(extend(config || {}, {
-            method: name,
-            url: url,
-            data: data
-          }));
-        };
-      });
-    }
-
-
-    /**
-     * Makes the request.
-     *
-     * !!! ACCESSES CLOSURE VARS:
-     * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
-     */
-    function sendReq(config, reqData, reqHeaders) {
-      var deferred = $q.defer(),
-          promise = deferred.promise,
-          cache,
-          cachedResp,
-          url = buildUrl(config.url, config.params);
-
-      $http.pendingRequests.push(config);
-      promise.then(removePendingReq, removePendingReq);
-
-
-      if ((config.cache || defaults.cache) && config.cache !== false && config.method == 'GET') {
-        cache = isObject(config.cache) ? config.cache
-              : isObject(defaults.cache) ? defaults.cache
-              : defaultCache;
-      }
-
-      if (cache) {
-        cachedResp = cache.get(url);
-        if (isDefined(cachedResp)) {
-          if (cachedResp.then) {
-            // cached request has already been sent, but there is no response yet
-            cachedResp.then(removePendingReq, removePendingReq);
-            return cachedResp;
-          } else {
-            // serving from cache
-            if (isArray(cachedResp)) {
-              resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2]));
-            } else {
-              resolvePromise(cachedResp, 200, {});
-            }
-          }
-        } else {
-          // put the promise for the non-transformed response into cache as a placeholder
-          cache.put(url, promise);
-        }
-      }
-
-      // if we won't have the response in cache, send the request to the backend
-      if (isUndefined(cachedResp)) {
-        $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
-            config.withCredentials, config.responseType);
-      }
-
-      return promise;
-
-
-      /**
-       * Callback registered to $httpBackend():
-       *  - caches the response if desired
-       *  - resolves the raw $http promise
-       *  - calls $apply
-       */
-      function done(status, response, headersString) {
-        if (cache) {
-          if (isSuccess(status)) {
-            cache.put(url, [status, response, parseHeaders(headersString)]);
-          } else {
-            // remove promise from the cache
-            cache.remove(url);
-          }
-        }
-
-        resolvePromise(response, status, headersString);
-        if (!$rootScope.$$phase) $rootScope.$apply();
-      }
-
-
-      /**
-       * Resolves the raw $http promise.
-       */
-      function resolvePromise(response, status, headers) {
-        // normalize internal statuses to 0
-        status = Math.max(status, 0);
-
-        (isSuccess(status) ? deferred.resolve : deferred.reject)({
-          data: response,
-          status: status,
-          headers: headersGetter(headers),
-          config: config
-        });
-      }
-
-
-      function removePendingReq() {
-        var idx = indexOf($http.pendingRequests, config);
-        if (idx !== -1) $http.pendingRequests.splice(idx, 1);
-      }
-    }
-
-
-    function buildUrl(url, params) {
-          if (!params) return url;
-          var parts = [];
-          forEachSorted(params, function(value, key) {
-            if (value === null || isUndefined(value)) return;
-            if (!isArray(value)) value = [value];
-
-            forEach(value, function(v) {
-              if (isObject(v)) {
-                v = toJson(v);
-              }
-              parts.push(encodeUriQuery(key) + '=' +
-                         encodeUriQuery(v));
-            });
-          });
-          return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
-        }
-
-
-  }];
-}
-
-var XHR = window.XMLHttpRequest || function() {
-  /* global ActiveXObject */
-  try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {}
-  try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
-  try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {}
-  throw minErr('$httpBackend')('noxhr', "This browser does not support XMLHttpRequest.");
-};
-
-
-/**
- * @ngdoc object
- * @name ng.$httpBackend
- * @requires $browser
- * @requires $window
- * @requires $document
- *
- * @description
- * HTTP backend used by the {@link ng.$http service} that delegates to
- * XMLHttpRequest object or JSONP and deals with browser incompatibilities.
- *
- * You should never need to use this service directly, instead use the higher-level abstractions:
- * {@link ng.$http $http} or {@link ngResource.$resource $resource}.
- *
- * During testing this implementation is swapped with {@link ngMock.$httpBackend mock
- * $httpBackend} which can be trained with responses.
- */
-function $HttpBackendProvider() {
-  this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
-    return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks, $document[0]);
-  }];
-}
-
-function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument) {
-  var ABORTED = -1;
-
-  // TODO(vojta): fix the signature
-  return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
-    var status;
-    $browser.$$incOutstandingRequestCount();
-    url = url || $browser.url();
-
-    if (lowercase(method) == 'jsonp') {
-      var callbackId = '_' + (callbacks.counter++).toString(36);
-      callbacks[callbackId] = function(data) {
-        callbacks[callbackId].data = data;
-      };
-
-      var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId),
-          function() {
-        if (callbacks[callbackId].data) {
-          completeRequest(callback, 200, callbacks[callbackId].data);
-        } else {
-          completeRequest(callback, status || -2);
-        }
-        delete callbacks[callbackId];
-      });
-    } else {
-      var xhr = new XHR();
-      xhr.open(method, url, true);
-      forEach(headers, function(value, key) {
-        if (isDefined(value)) {
-            xhr.setRequestHeader(key, value);
-        }
-      });
-
-      // In IE6 and 7, this might be called synchronously when xhr.send below is called and the
-      // response is in the cache. the promise api will ensure that to the app code the api is
-      // always async
-      xhr.onreadystatechange = function() {
-        if (xhr.readyState == 4) {
-          var responseHeaders = null,
-              response = null;
-
-          if(status !== ABORTED) {
-            responseHeaders = xhr.getAllResponseHeaders();
-            response = xhr.responseType ? xhr.response : xhr.responseText;
-          }
-
-          // responseText is the old-school way of retrieving response (supported by IE8 & 9)
-          // response/responseType properties were introduced in XHR Level2 spec (supported by IE10)
-          completeRequest(callback,
-              status || xhr.status,
-              response,
-              responseHeaders);
-        }
-      };
-
-      if (withCredentials) {
-        xhr.withCredentials = true;
-      }
-
-      if (responseType) {
-        xhr.responseType = responseType;
-      }
-
-      xhr.send(post || null);
-    }
-
-    if (timeout > 0) {
-      var timeoutId = $browserDefer(timeoutRequest, timeout);
-    } else if (timeout && timeout.then) {
-      timeout.then(timeoutRequest);
-    }
-
-
-    function timeoutRequest() {
-      status = ABORTED;
-      jsonpDone && jsonpDone();
-      xhr && xhr.abort();
-    }
-
-    function completeRequest(callback, status, response, headersString) {
-      var protocol = urlResolve(url).protocol;
-
-      // cancel timeout and subsequent timeout promise resolution
-      timeoutId && $browserDefer.cancel(timeoutId);
-      jsonpDone = xhr = null;
-
-      // fix status code for file protocol (it's always 0)
-      status = (protocol == 'file' && status === 0) ? (response ? 200 : 404) : status;
-
-      // normalize IE bug (http://bugs.jquery.com/ticket/1450)
-      status = status == 1223 ? 204 : status;
-
-      callback(status, response, headersString);
-      $browser.$$completeOutstandingRequest(noop);
-    }
-  };
-
-  function jsonpReq(url, done) {
-    // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
-    // - fetches local scripts via XHR and evals them
-    // - adds and immediately removes script elements from the document
-    var script = rawDocument.createElement('script'),
-        doneWrapper = function() {
-          script.onreadystatechange = script.onload = script.onerror = null;
-          rawDocument.body.removeChild(script);
-          if (done) done();
-        };
-
-    script.type = 'text/javascript';
-    script.src = url;
-
-    if (msie && msie <= 8) {
-      script.onreadystatechange = function() {
-        if (/loaded|complete/.test(script.readyState)) {
-          doneWrapper();
-        }
-      };
-    } else {
-      script.onload = script.onerror = function() {
-        doneWrapper();
-      };
-    }
-
-    rawDocument.body.appendChild(script);
-    return doneWrapper;
-  }
-}
-
-var $interpolateMinErr = minErr('$interpolate');
-
-/**
- * @ngdoc object
- * @name ng.$interpolateProvider
- * @function
- *
- * @description
- *
- * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
- *
- * @example
-<doc:example module="customInterpolationApp">
-<doc:source>
-<script>
-  var customInterpolationApp = angular.module('customInterpolationApp', []);
-
-  customInterpolationApp.config(function($interpolateProvider) {
-    $interpolateProvider.startSymbol('//');
-    $interpolateProvider.endSymbol('//');
-  });
-
-
-  customInterpolationApp.controller('DemoController', function DemoController() {
-      this.label = "This binding is brought you by // interpolation symbols.";
-  });
-</script>
-<div ng-app="App" ng-controller="DemoController as demo">
-    //demo.label//
-</div>
-</doc:source>
-<doc:scenario>
- it('should interpolate binding with custom symbols', function() {
-  expect(binding('demo.label')).toBe('This binding is brought you by // interpolation symbols.');
- });
-</doc:scenario>
-</doc:example>
- */
-function $InterpolateProvider() {
-  var startSymbol = '{{';
-  var endSymbol = '}}';
-
-  /**
-   * @ngdoc method
-   * @name ng.$interpolateProvider#startSymbol
-   * @methodOf ng.$interpolateProvider
-   * @description
-   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
-   *
-   * @param {string=} value new value to set the starting symbol to.
-   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
-   */
-  this.startSymbol = function(value){
-    if (value) {
-      startSymbol = value;
-      return this;
-    } else {
-      return startSymbol;
-    }
-  };
-
-  /**
-   * @ngdoc method
-   * @name ng.$interpolateProvider#endSymbol
-   * @methodOf ng.$interpolateProvider
-   * @description
-   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
-   *
-   * @param {string=} value new value to set the ending symbol to.
-   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
-   */
-  this.endSymbol = function(value){
-    if (value) {
-      endSymbol = value;
-      return this;
-    } else {
-      return endSymbol;
-    }
-  };
-
-
-  this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
-    var startSymbolLength = startSymbol.length,
-        endSymbolLength = endSymbol.length;
-
-    /**
-     * @ngdoc function
-     * @name ng.$interpolate
-     * @function
-     *
-     * @requires $parse
-     * @requires $sce
-     *
-     * @description
-     *
-     * Compiles a string with markup into an interpolation function. This service is used by the
-     * HTML {@link ng.$compile $compile} service for data binding. See
-     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
-     * interpolation markup.
-     *
-     *
-       <pre>
-         var $interpolate = ...; // injected
-         var exp = $interpolate('Hello {{name | uppercase}}!');
-         expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
-       </pre>
-     *
-     *
-     * @param {string} text The text with markup to interpolate.
-     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
-     *    embedded expression in order to return an interpolation function. Strings with no
-     *    embedded expression will return null for the interpolation function.
-     * @param {string=} trustedContext when provided, the returned function passes the interpolated
-     *    result through {@link ng.$sce#methods_getTrusted $sce.getTrusted(interpolatedResult,
-     *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that
-     *    provides Strict Contextual Escaping for details.
-     * @returns {function(context)} an interpolation function which is used to compute the
-     *    interpolated string. The function has these parameters:
-     *
-     *    * `context`: an object against which any expressions embedded in the strings are evaluated
-     *      against.
-     *
-     */
-    function $interpolate(text, mustHaveExpression, trustedContext) {
-      var startIndex,
-          endIndex,
-          index = 0,
-          parts = [],
-          length = text.length,
-          hasInterpolation = false,
-          fn,
-          exp,
-          concat = [];
-
-      while(index < length) {
-        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&
-             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {
-          (index != startIndex) && parts.push(text.substring(index, startIndex));
-          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));
-          fn.exp = exp;
-          index = endIndex + endSymbolLength;
-          hasInterpolation = true;
-        } else {
-          // we did not find anything, so we have to add the remainder to the parts array
-          (index != length) && parts.push(text.substring(index));
-          index = length;
-        }
-      }
-
-      if (!(length = parts.length)) {
-        // we added, nothing, must have been an empty string.
-        parts.push('');
-        length = 1;
-      }
-
-      // Concatenating expressions makes it hard to reason about whether some combination of
-      // concatenated values are unsafe to use and could easily lead to XSS.  By requiring that a
-      // single expression be used for iframe[src], object[src], etc., we ensure that the value
-      // that's used is assigned or constructed by some JS code somewhere that is more testable or
-      // make it obvious that you bound the value to some user controlled value.  This helps reduce
-      // the load when auditing for XSS issues.
-      if (trustedContext && parts.length > 1) {
-          throw $interpolateMinErr('noconcat',
-              "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
-              "interpolations that concatenate multiple expressions when a trusted value is " +
-              "required.  See http://docs.angularjs.org/api/ng.$sce", text);
-      }
-
-      if (!mustHaveExpression  || hasInterpolation) {
-        concat.length = length;
-        fn = function(context) {
-          try {
-            for(var i = 0, ii = length, part; i<ii; i++) {
-              if (typeof (part = parts[i]) == 'function') {
-                part = part(context);
-                if (trustedContext) {
-                  part = $sce.getTrusted(trustedContext, part);
-                } else {
-                  part = $sce.valueOf(part);
-                }
-                if (part === null || isUndefined(part)) {
-                  part = '';
-                } else if (typeof part != 'string') {
-                  part = toJson(part);
-                }
-              }
-              concat[i] = part;
-            }
-            return concat.join('');
-          }
-          catch(err) {
-            var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
-                err.toString());
-            $exceptionHandler(newErr);
-          }
-        };
-        fn.exp = text;
-        fn.parts = parts;
-        return fn;
-      }
-    }
-
-
-    /**
-     * @ngdoc method
-     * @name ng.$interpolate#startSymbol
-     * @methodOf ng.$interpolate
-     * @description
-     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
-     *
-     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change
-     * the symbol.
-     *
-     * @returns {string} start symbol.
-     */
-    $interpolate.startSymbol = function() {
-      return startSymbol;
-    };
-
-
-    /**
-     * @ngdoc method
-     * @name ng.$interpolate#endSymbol
-     * @methodOf ng.$interpolate
-     * @description
-     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
-     *
-     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change
-     * the symbol.
-     *
-     * @returns {string} start symbol.
-     */
-    $interpolate.endSymbol = function() {
-      return endSymbol;
-    };
-
-    return $interpolate;
-  }];
-}
-
-function $IntervalProvider() {
-  this.$get = ['$rootScope', '$window', '$q',
-       function($rootScope,   $window,   $q) {
-    var intervals = {};
-
-
-     /**
-      * @ngdoc function
-      * @name ng.$interval
-      *
-      * @description
-      * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay`
-      * milliseconds.
-      *
-      * The return value of registering an interval function is a promise. This promise will be
-      * notified upon each tick of the interval, and will be resolved after `count` iterations, or
-      * run indefinitely if `count` is not defined. The value of the notification will be the
-      * number of iterations that have run.
-      * To cancel an interval, call `$interval.cancel(promise)`.
-      *
-      * In tests you can use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to
-      * move forward by `millis` milliseconds and trigger any functions scheduled to run in that
-      * time.
-      *
-      * @param {function()} fn A function that should be called repeatedly.
-      * @param {number} delay Number of milliseconds between each function call.
-      * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat
-      *   indefinitely.
-      * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
-      *   will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block.
-      * @returns {promise} A promise which will be notified on each iteration.
-      */
-    function interval(fn, delay, count, invokeApply) {
-      var setInterval = $window.setInterval,
-          clearInterval = $window.clearInterval,
-          deferred = $q.defer(),
-          promise = deferred.promise,
-          iteration = 0,
-          skipApply = (isDefined(invokeApply) && !invokeApply);
-      
-      count = isDefined(count) ? count : 0,
-
-      promise.then(null, null, fn);
-
-      promise.$$intervalId = setInterval(function tick() {
-        deferred.notify(iteration++);
-
-        if (count > 0 && iteration >= count) {
-          deferred.resolve(iteration);
-          clearInterval(promise.$$intervalId);
-          delete intervals[promise.$$intervalId];
-        }
-
-        if (!skipApply) $rootScope.$apply();
-
-      }, delay);
-
-      intervals[promise.$$intervalId] = deferred;
-
-      return promise;
-    }
-
-
-     /**
-      * @ngdoc function
-      * @name ng.$interval#cancel
-      * @methodOf ng.$interval
-      *
-      * @description
-      * Cancels a task associated with the `promise`.
-      *
-      * @param {number} promise Promise returned by the `$interval` function.
-      * @returns {boolean} Returns `true` if the task was successfully canceled.
-      */
-    interval.cancel = function(promise) {
-      if (promise && promise.$$intervalId in intervals) {
-        intervals[promise.$$intervalId].reject('canceled');
-        clearInterval(promise.$$intervalId);
-        delete intervals[promise.$$intervalId];
-        return true;
-      }
-      return false;
-    };
-
-    return interval;
-  }];
-}
-
-/**
- * @ngdoc object
- * @name ng.$locale
- *
- * @description
- * $locale service provides localization rules for various Angular components. As of right now the
- * only public api is:
- *
- * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`)
- */
-function $LocaleProvider(){
-  this.$get = function() {
-    return {
-      id: 'en-us',
-
-      NUMBER_FORMATS: {
-        DECIMAL_SEP: '.',
-        GROUP_SEP: ',',
-        PATTERNS: [
-          { // Decimal Pattern
-            minInt: 1,
-            minFrac: 0,
-            maxFrac: 3,
-            posPre: '',
-            posSuf: '',
-            negPre: '-',
-            negSuf: '',
-            gSize: 3,
-            lgSize: 3
-          },{ //Currency Pattern
-            minInt: 1,
-            minFrac: 2,
-            maxFrac: 2,
-            posPre: '\u00A4',
-            posSuf: '',
-            negPre: '(\u00A4',
-            negSuf: ')',
-            gSize: 3,
-            lgSize: 3
-          }
-        ],
-        CURRENCY_SYM: '$'
-      },
-
-      DATETIME_FORMATS: {
-        MONTH:
-            'January,February,March,April,May,June,July,August,September,October,November,December'
-            .split(','),
-        SHORTMONTH:  'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','),
-        DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','),
-        SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','),
-        AMPMS: ['AM','PM'],
-        medium: 'MMM d, y h:mm:ss a',
-        short: 'M/d/yy h:mm a',
-        fullDate: 'EEEE, MMMM d, y',
-        longDate: 'MMMM d, y',
-        mediumDate: 'MMM d, y',
-        shortDate: 'M/d/yy',
-        mediumTime: 'h:mm:ss a',
-        shortTime: 'h:mm a'
-      },
-
-      pluralCat: function(num) {
-        if (num === 1) {
-          return 'one';
-        }
-        return 'other';
-      }
-    };
-  };
-}
-
-var PATH_MATCH = /^([^\?#]*)(\?([^#]*))?(#(.*))?$/,
-    DEFAULT_PORTS = {'http': 80, 'https': 443, 'ftp': 21};
-var $locationMinErr = minErr('$location');
-
-
-/**
- * Encode path using encodeUriSegment, ignoring forward slashes
- *
- * @param {string} path Path to encode
- * @returns {string}
- */
-function encodePath(path) {
-  var segments = path.split('/'),
-      i = segments.length;
-
-  while (i--) {
-    segments[i] = encodeUriSegment(segments[i]);
-  }
-
-  return segments.join('/');
-}
-
-function parseAbsoluteUrl(absoluteUrl, locationObj, appBase) {
-  var parsedUrl = urlResolve(absoluteUrl, appBase);
-
-  locationObj.$$protocol = parsedUrl.protocol;
-  locationObj.$$host = parsedUrl.hostname;
-  locationObj.$$port = int(parsedUrl.port) || DEFAULT_PORTS[parsedUrl.protocol] || null;
-}
-
-
-function parseAppUrl(relativeUrl, locationObj, appBase) {
-  var prefixed = (relativeUrl.charAt(0) !== '/');
-  if (prefixed) {
-    relativeUrl = '/' + relativeUrl;
-  }
-  var match = urlResolve(relativeUrl, appBase);
-  locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
-      match.pathname.substring(1) : match.pathname);
-  locationObj.$$search = parseKeyValue(match.search);
-  locationObj.$$hash = decodeURIComponent(match.hash);
-
-  // make sure path starts with '/';
-  if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
-    locationObj.$$path = '/' + locationObj.$$path;
-  }
-}
-
-
-/**
- *
- * @param {string} begin
- * @param {string} whole
- * @returns {string} returns text from whole after begin or undefined if it does not begin with
- *                   expected string.
- */
-function beginsWith(begin, whole) {
-  if (whole.indexOf(begin) === 0) {
-    return whole.substr(begin.length);
-  }
-}
-
-
-function stripHash(url) {
-  var index = url.indexOf('#');
-  return index == -1 ? url : url.substr(0, index);
-}
-
-
-function stripFile(url) {
-  return url.substr(0, stripHash(url).lastIndexOf('/') + 1);
-}
-
-/* return the server only (scheme://host:port) */
-function serverBase(url) {
-  return url.substring(0, url.indexOf('/', url.indexOf('//') + 2));
-}
-
-
-/**
- * LocationHtml5Url represents an url
- * This object is exposed as $location service when HTML5 mode is enabled and supported
- *
- * @constructor
- * @param {string} appBase application base URL
- * @param {string} basePrefix url path prefix
- */
-function LocationHtml5Url(appBase, basePrefix) {
-  this.$$html5 = true;
-  basePrefix = basePrefix || '';
-  var appBaseNoFile = stripFile(appBase);
-  parseAbsoluteUrl(appBase, this, appBase);
-
-
-  /**
-   * Parse given html5 (regular) url string into properties
-   * @param {string} newAbsoluteUrl HTML5 url
-   * @private
-   */
-  this.$$parse = function(url) {
-    var pathUrl = beginsWith(appBaseNoFile, url);
-    if (!isString(pathUrl)) {
-      throw $locationMinErr('ipthprfx', 'Invalid url "{0}", missing path prefix "{1}".', url,
-          appBaseNoFile);
-    }
-
-    parseAppUrl(pathUrl, this, appBase);
-
-    if (!this.$$path) {
-      this.$$path = '/';
-    }
-
-    this.$$compose();
-  };
-
-  /**
-   * Compose url and update `absUrl` property
-   * @private
-   */
-  this.$$compose = function() {
-    var search = toKeyValue(this.$$search),
-        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
-
-    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
-    this.$$absUrl = appBaseNoFile + this.$$url.substr(1); // first char is always '/'
-  };
-
-  this.$$rewrite = function(url) {
-    var appUrl, prevAppUrl;
-
-    if ( (appUrl = beginsWith(appBase, url)) !== undefined ) {
-      prevAppUrl = appUrl;
-      if ( (appUrl = beginsWith(basePrefix, appUrl)) !== undefined ) {
-        return appBaseNoFile + (beginsWith('/', appUrl) || appUrl);
-      } else {
-        return appBase + prevAppUrl;
-      }
-    } else if ( (appUrl = beginsWith(appBaseNoFile, url)) !== undefined ) {
-      return appBaseNoFile + appUrl;
-    } else if (appBaseNoFile == url + '/') {
-      return appBaseNoFile;
-    }
-  };
-}
-
-
-/**
- * LocationHashbangUrl represents url
- * This object is exposed as $location service when developer doesn't opt into html5 mode.
- * It also serves as the base class for html5 mode fallback on legacy browsers.
- *
- * @constructor
- * @param {string} appBase application base URL
- * @param {string} hashPrefix hashbang prefix
- */
-function LocationHashbangUrl(appBase, hashPrefix) {
-  var appBaseNoFile = stripFile(appBase);
-
-  parseAbsoluteUrl(appBase, this, appBase);
-
-
-  /**
-   * Parse given hashbang url into properties
-   * @param {string} url Hashbang url
-   * @private
-   */
-  this.$$parse = function(url) {
-    var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
-    var withoutHashUrl = withoutBaseUrl.charAt(0) == '#'
-        ? beginsWith(hashPrefix, withoutBaseUrl)
-        : (this.$$html5)
-          ? withoutBaseUrl
-          : '';
-
-    if (!isString(withoutHashUrl)) {
-      throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
-          hashPrefix);
-    }
-    parseAppUrl(withoutHashUrl, this, appBase);
-
-    this.$$path = removeWindowsDriveName(this.$$path, withoutHashUrl, appBase);
-
-    this.$$compose();
-
-    /*
-     * In Windows, on an anchor node on documents loaded from
-     * the filesystem, the browser will return a pathname
-     * prefixed with the drive name ('/C:/path') when a
-     * pathname without a drive is set:
-     *  * a.setAttribute('href', '/foo')
-     *   * a.pathname === '/C:/foo' //true
-     *
-     * Inside of Angular, we're always using pathnames that
-     * do not include drive names for routing.
-     */
-    function removeWindowsDriveName (path, url, base) {
-      /*
-      Matches paths for file protocol on windows,
-      such as /C:/foo/bar, and captures only /foo/bar.
-      */
-      var windowsFilePathExp = /^\/?.*?:(\/.*)/;
-
-      var firstPathSegmentMatch;
-
-      //Get the relative path from the input URL.
-      if (url.indexOf(base) === 0) {
-        url = url.replace(base, '');
-      }
-
-      /*
-       * The input URL intentionally contains a
-       * first path segment that ends with a colon.
-       */
-      if (windowsFilePathExp.exec(url)) {
-        return path;
-      }
-
-      firstPathSegmentMatch = windowsFilePathExp.exec(path);
-      return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
-    }
-  };
-
-  /**
-   * Compose hashbang url and update `absUrl` property
-   * @private
-   */
-  this.$$compose = function() {
-    var search = toKeyValue(this.$$search),
-        hash = this.$$hash ? '#' + encodeUriSegment(this.$$hash) : '';
-
-    this.$$url = encodePath(this.$$path) + (search ? '?' + search : '') + hash;
-    this.$$absUrl = appBase + (this.$$url ? hashPrefix + this.$$url : '');
-  };
-
-  this.$$rewrite = function(url) {
-    if(stripHash(appBase) == stripHash(url)) {
-      return url;
-    }
-  };
-}
-
-
-/**
- * LocationHashbangUrl represents url
- * This object is exposed as $location service when html5 history api is enabled but the browser
- * does not support it.
- *
- * @constructor
- * @param {string} appBase application base URL
- * @param {string} hashPrefix hashbang prefix
- */
-function LocationHashbangInHtml5Url(appBase, hashPrefix) {
-  this.$$html5 = true;
-  LocationHashbangUrl.apply(this, arguments);
-
-  var appBaseNoFile = stripFile(appBase);
-
-  this.$$rewrite = function(url) {
-    var appUrl;
-
-    if ( appBase == stripHash(url) ) {
-      return url;
-    } else if ( (appUrl = beginsWith(appBaseNoFile, url)) ) {
-      return appBase + hashPrefix + appUrl;
-    } else if ( appBaseNoFile === url + '/') {
-      return appBaseNoFile;
-    }
-  };
-}
-
-
-LocationHashbangInHtml5Url.prototype =
-  LocationHashbangUrl.prototype =
-  LocationHtml5Url.prototype = {
-
-  /**
-   * Are we in html5 mode?
-   * @private
-   */
-  $$html5: false,
-
-  /**
-   * Has any change been replacing ?
-   * @private
-   */
-  $$replace: false,
-
-  /**
-   * @ngdoc method
-   * @name ng.$location#absUrl
-   * @methodOf ng.$location
-   *
-   * @description
-   * This method is getter only.
-   *
-   * Return full url representation with all segments encoded according to rules specified in
-   * {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}.
-   *
-   * @return {string} full url
-   */
-  absUrl: locationGetter('$$absUrl'),
-
-  /**
-   * @ngdoc method
-   * @name ng.$location#url
-   * @methodOf ng.$location
-   *
-   * @description
-   * This method is getter / setter.
-   *
-   * Return url (e.g. `/path?a=b#hash`) when called without any parameter.
-   *
-   * Change path, search and hash, when called with parameter and return `$location`.
-   *
-   * @param {string=} url New url without base prefix (e.g. `/path?a=b#hash`)
-   * @param {string=} replace The path that will be changed
-   * @return {string} url
-   */
-  url: function(url, replace) {
-    if (isUndefined(url))
-      return this.$$url;
-
-    var match = PATH_MATCH.exec(url);
-    if (match[1]) this.path(decodeURIComponent(match[1]));
-    if (match[2] || match[1]) this.search(match[3] || '');
-    this.hash(match[5] || '', replace);
-
-    return this;
-  },
-
-  /**
-   * @ngdoc method
-   * @name ng.$location#protocol
-   * @methodOf ng.$location
-   *
-   * @description
-   * This method is getter only.
-   *
-   * Return protocol of current url.
-   *
-   * @return {string} protocol of current url
-   */
-  protocol: locationGetter('$$protocol'),
-
-  /**
-   * @ngdoc method
-   * @name ng.$location#host
-   * @methodOf ng.$location
-   *
-   * @description
-   * This method is getter only.
-   *
-   * Return host of current url.
-   *
-   * @return {string} host of current url.
-   */
-  host: locationGetter('$$host'),
-
-  /**
-   * @ngdoc method
-   * @name ng.$location#port
-   * @methodOf ng.$location
-   *
-   * @description
-   * This method is getter only.
-   *
-   * Return port of current url.
-   *
-   * @return {Number} port
-   */
-  port: locationGetter('$$port'),
-
-  /**
-   * @ngdoc method
-   * @name ng.$location#path
-   * @methodOf ng.$location
-   *
-   * @description
-   * This method is getter / setter.
-   *
-   * Return path of current url when called without any parameter.
-   *
-   * Change path when called with parameter and return `$location`.
-   *
-   * Note: Path should always begin with forward slash (/), this method will add the forward slash
-   * if it is missing.
-   *
-   * @param {string=} path New path
-   * @return {string} path
-   */
-  path: locationGetterSetter('$$path', function(path) {
-    return path.charAt(0) == '/' ? path : '/' + path;
-  }),
-
-  /**
-   * @ngdoc method
-   * @name ng.$location#search
-   * @methodOf ng.$location
-   *
-   * @description
-   * This method is getter / setter.
-   *
-   * Return search part (as object) of current url when called without any parameter.
-   *
-   * Change search part when called with parameter and return `$location`.
-   *
-   * @param {string|Object.<string>|Object.<Array.<string>>} search New search params - string or
-   * hash object. Hash object may contain an array of values, which will be decoded as duplicates in
-   * the url.
-   *
-   * @param {(string|Array<string>)=} paramValue If `search` is a string, then `paramValue` will override only a
-   * single search parameter. If `paramValue` is an array, it will set the parameter as a
-   * comma-separated value. If `paramValue` is `null`, the parameter will be deleted.
-   *
-   * @return {string} search
-   */
-  search: function(search, paramValue) {
-    switch (arguments.length) {
-      case 0:
-        return this.$$search;
-      case 1:
-        if (isString(search)) {
-          this.$$search = parseKeyValue(search);
-        } else if (isObject(search)) {
-          this.$$search = search;
-        } else {
-          throw $locationMinErr('isrcharg',
-              'The first argument of the `$location#search()` call must be a string or an object.');
-        }
-        break;
-      default:
-        if (isUndefined(paramValue) || paramValue === null) {
-          delete this.$$search[search];
-        } else {
-          this.$$search[search] = paramValue;
-        }
-    }
-
-    this.$$compose();
-    return this;
-  },
-
-  /**
-   * @ngdoc method
-   * @name ng.$location#hash
-   * @methodOf ng.$location
-   *
-   * @description
-   * This method is getter / setter.
-   *
-   * Return hash fragment when called without any parameter.
-   *
-   * Change hash fragment when called with parameter and return `$location`.
-   *
-   * @param {string=} hash New hash fragment
-   * @return {string} hash
-   */
-  hash: locationGetterSetter('$$hash', identity),
-
-  /**
-   * @ngdoc method
-   * @name ng.$location#replace
-   * @methodOf ng.$location
-   *
-   * @description
-   * If called, all changes to $location during current `$digest` will be replacing current history
-   * record, instead of adding new one.
-   */
-  replace: function() {
-    this.$$replace = true;
-    return this;
-  }
-};
-
-function locationGetter(property) {
-  return function() {
-    return this[property];
-  };
-}
-
-
-function locationGetterSetter(property, preprocess) {
-  return function(value) {
-    if (isUndefined(value))
-      return this[property];
-
-    this[property] = preprocess(value);
-    this.$$compose();
-
-    return this;
-  };
-}
-
-
-/**
- * @ngdoc object
- * @name ng.$location
- *
- * @requires $browser
- * @requires $sniffer
- * @requires $rootElement
- *
- * @description
- * The $location service parses the URL in the browser address bar (based on the
- * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL
- * available to your application. Changes to the URL in the address bar are reflected into
- * $location service and changes to $location are reflected into the browser address bar.
- *
- * **The $location service:**
- *
- * - Exposes the current URL in the browser address bar, so you can
- *   - Watch and observe the URL.
- *   - Change the URL.
- * - Synchronizes the URL with the browser when the user
- *   - Changes the address bar.
- *   - Clicks the back or forward button (or clicks a History link).
- *   - Clicks on a link.
- * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
- *
- * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular
- * Services: Using $location}
- */
-
-/**
- * @ngdoc object
- * @name ng.$locationProvider
- * @description
- * Use the `$locationProvider` to configure how the application deep linking paths are stored.
- */
-function $LocationProvider(){
-  var hashPrefix = '',
-      html5Mode = false;
-
-  /**
-   * @ngdoc property
-   * @name ng.$locationProvider#hashPrefix
-   * @methodOf ng.$locationProvider
-   * @description
-   * @param {string=} prefix Prefix for hash part (containing path and search)
-   * @returns {*} current value if used as getter or itself (chaining) if used as setter
-   */
-  this.hashPrefix = function(prefix) {
-    if (isDefined(prefix)) {
-      hashPrefix = prefix;
-      return this;
-    } else {
-      return hashPrefix;
-    }
-  };
-
-  /**
-   * @ngdoc property
-   * @name ng.$locationProvider#html5Mode
-   * @methodOf ng.$locationProvider
-   * @description
-   * @param {boolean=} mode Use HTML5 strategy if available.
-   * @returns {*} current value if used as getter or itself (chaining) if used as setter
-   */
-  this.html5Mode = function(mode) {
-    if (isDefined(mode)) {
-      html5Mode = mode;
-      return this;
-    } else {
-      return html5Mode;
-    }
-  };
-
-  /**
-   * @ngdoc event
-   * @name ng.$location#$locationChangeStart
-   * @eventOf ng.$location
-   * @eventType broadcast on root scope
-   * @description
-   * Broadcasted before a URL will change. This change can be prevented by calling
-   * `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on} for more
-   * details about event object. Upon successful change
-   * {@link ng.$location#$locationChangeSuccess $locationChangeSuccess} is fired.
-   *
-   * @param {Object} angularEvent Synthetic event object.
-   * @param {string} newUrl New URL
-   * @param {string=} oldUrl URL that was before it was changed.
-   */
-
-  /**
-   * @ngdoc event
-   * @name ng.$location#$locationChangeSuccess
-   * @eventOf ng.$location
-   * @eventType broadcast on root scope
-   * @description
-   * Broadcasted after a URL was changed.
-   *
-   * @param {Object} angularEvent Synthetic event object.
-   * @param {string} newUrl New URL
-   * @param {string=} oldUrl URL that was before it was changed.
-   */
-
-  this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement',
-      function( $rootScope,   $browser,   $sniffer,   $rootElement) {
-    var $location,
-        LocationMode,
-        baseHref = $browser.baseHref(), // if base[href] is undefined, it defaults to ''
-        initialUrl = $browser.url(),
-        appBase;
-
-    if (html5Mode) {
-      appBase = serverBase(initialUrl) + (baseHref || '/');
-      LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url;
-    } else {
-      appBase = stripHash(initialUrl);
-      LocationMode = LocationHashbangUrl;
-    }
-    $location = new LocationMode(appBase, '#' + hashPrefix);
-    $location.$$parse($location.$$rewrite(initialUrl));
-
-    $rootElement.on('click', function(event) {
-      // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
-      // currently we open nice url link and redirect then
-
-      if (event.ctrlKey || event.metaKey || event.which == 2) return;
-
-      var elm = jqLite(event.target);
-
-      // traverse the DOM up to find first A tag
-      while (lowercase(elm[0].nodeName) !== 'a') {
-        // ignore rewriting if no A tag (reached root element, or no parent - removed from document)
-        if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
-      }
-
-      var absHref = elm.prop('href');
-      var rewrittenUrl = $location.$$rewrite(absHref);
-
-      if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) {
-        event.preventDefault();
-        if (rewrittenUrl != $browser.url()) {
-          // update location manually
-          $location.$$parse(rewrittenUrl);
-          $rootScope.$apply();
-          // hack to work around FF6 bug 684208 when scenario runner clicks on links
-          window.angular['ff-684208-preventDefault'] = true;
-        }
-      }
-    });
-
-
-    // rewrite hashbang url <> html5 url
-    if ($location.absUrl() != initialUrl) {
-      $browser.url($location.absUrl(), true);
-    }
-
-    // update $location when $browser url changes
-    $browser.onUrlChange(function(newUrl) {
-      if ($location.absUrl() != newUrl) {
-        if ($rootScope.$broadcast('$locationChangeStart', newUrl,
-                                  $location.absUrl()).defaultPrevented) {
-          $browser.url($location.absUrl());
-          return;
-        }
-        $rootScope.$evalAsync(function() {
-          var oldUrl = $location.absUrl();
-
-          $location.$$parse(newUrl);
-          afterLocationChange(oldUrl);
-        });
-        if (!$rootScope.$$phase) $rootScope.$digest();
-      }
-    });
-
-    // update browser
-    var changeCounter = 0;
-    $rootScope.$watch(function $locationWatch() {
-      var oldUrl = $browser.url();
-      var currentReplace = $location.$$replace;
-
-      if (!changeCounter || oldUrl != $location.absUrl()) {
-        changeCounter++;
-        $rootScope.$evalAsync(function() {
-          if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).
-              defaultPrevented) {
-            $location.$$parse(oldUrl);
-          } else {
-            $browser.url($location.absUrl(), currentReplace);
-            afterLocationChange(oldUrl);
-          }
-        });
-      }
-      $location.$$replace = false;
-
-      return changeCounter;
-    });
-
-    return $location;
-
-    function afterLocationChange(oldUrl) {
-      $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl);
-    }
-}];
-}
-
-/**
- * @ngdoc object
- * @name ng.$log
- * @requires $window
- *
- * @description
- * Simple service for logging. Default implementation safely writes the message
- * into the browser's console (if present).
- * 
- * The main purpose of this service is to simplify debugging and troubleshooting.
- *
- * The default is to log `debug` messages. You can use
- * {@link ng.$logProvider ng.$logProvider#debugEnabled} to change this.
- *
- * @example
-   <example>
-     <file name="script.js">
-       function LogCtrl($scope, $log) {
-         $scope.$log = $log;
-         $scope.message = 'Hello World!';
-       }
-     </file>
-     <file name="index.html">
-       <div ng-controller="LogCtrl">
-         <p>Reload this page with open console, enter text and hit the log button...</p>
-         Message:
-         <input type="text" ng-model="message"/>
-         <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>
-       </div>
-     </file>
-   </example>
- */
-
-/**
- * @ngdoc object
- * @name ng.$logProvider
- * @description
- * Use the `$logProvider` to configure how the application logs messages
- */
-function $LogProvider(){
-  var debug = true,
-      self = this;
-  
-  /**
-   * @ngdoc property
-   * @name ng.$logProvider#debugEnabled
-   * @methodOf ng.$logProvider
-   * @description
-   * @param {string=} flag enable or disable debug level messages
-   * @returns {*} current value if used as getter or itself (chaining) if used as setter
-   */
-  this.debugEnabled = function(flag) {
-    if (isDefined(flag)) {
-      debug = flag;
-    return this;
-    } else {
-      return debug;
-    }
-  };
-  
-  this.$get = ['$window', function($window){
-    return {
-      /**
-       * @ngdoc method
-       * @name ng.$log#log
-       * @methodOf ng.$log
-       *
-       * @description
-       * Write a log message
-       */
-      log: consoleLog('log'),
-
-      /**
-       * @ngdoc method
-       * @name ng.$log#info
-       * @methodOf ng.$log
-       *
-       * @description
-       * Write an information message
-       */
-      info: consoleLog('info'),
-
-      /**
-       * @ngdoc method
-       * @name ng.$log#warn
-       * @methodOf ng.$log
-       *
-       * @description
-       * Write a warning message
-       */
-      warn: consoleLog('warn'),
-
-      /**
-       * @ngdoc method
-       * @name ng.$log#error
-       * @methodOf ng.$log
-       *
-       * @description
-       * Write an error message
-       */
-      error: consoleLog('error'),
-      
-      /**
-       * @ngdoc method
-       * @name ng.$log#debug
-       * @methodOf ng.$log
-       * 
-       * @description
-       * Write a debug message
-       */
-      debug: (function () {
-        var fn = consoleLog('debug');
-
-        return function() {
-          if (debug) {
-            fn.apply(self, arguments);
-          }
-        };
-      }())
-    };
-
-    function formatError(arg) {
-      if (arg instanceof Error) {
-        if (arg.stack) {
-          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
-              ? 'Error: ' + arg.message + '\n' + arg.stack
-              : arg.stack;
-        } else if (arg.sourceURL) {
-          arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
-        }
-      }
-      return arg;
-    }
-
-    function consoleLog(type) {
-      var console = $window.console || {},
-          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);
-        };
-      }
-
-      // we are IE which either doesn't have window.console => this is noop and we do nothing,
-      // or we are IE where console.log doesn't have apply so we log at least first 2 args
-      return function(arg1, arg2) {
-        logFn(arg1, arg2 == null ? '' : arg2);
-      };
-    }
-  }];
-}
-
-var $parseMinErr = minErr('$parse');
-var promiseWarningCache = {};
-var promiseWarning;
-
-// Sandboxing Angular Expressions
-// ------------------------------
-// Angular expressions are generally considered safe because these expressions only have direct
-// access to $scope and locals. However, one can obtain the ability to execute arbitrary JS code by
-// obtaining a reference to native JS functions such as the Function constructor.
-//
-// As an example, consider the following Angular expression:
-//
-//   {}.toString.constructor(alert("evil JS code"))
-//
-// We want to prevent this type of access. For the sake of performance, during the lexing phase we
-// disallow any "dotted" access to any member named "constructor".
-//
-// For reflective calls (a[b]) we check that the value of the lookup is not the Function constructor
-// while evaluating the expression, which is a stronger but more expensive test. Since reflective
-// calls are expensive anyway, this is not such a big deal compared to static dereferencing.
-//
-// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
-// against the expression language, but not to prevent exploits that were enabled by exposing
-// sensitive JavaScript or browser apis on Scope. Exposing such objects on a Scope is never a good
-// practice and therefore we are not even trying to protect against interaction with an object
-// explicitly exposed in this way.
-//
-// A developer could foil the name check by aliasing the Function constructor under a different
-// name on the scope.
-//
-// In general, it is not possible to access a Window object from an angular expression unless a
-// window or some DOM object that has a reference to window is published onto a Scope.
-
-function ensureSafeMemberName(name, fullExpression) {
-  if (name === "constructor") {
-    throw $parseMinErr('isecfld',
-        'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}',
-        fullExpression);
-  }
-  return name;
-}
-
-function ensureSafeObject(obj, fullExpression) {
-  // nifty check if obj is Function that is fast and works across iframes and other contexts
-  if (obj) {
-    if (obj.constructor === obj) {
-      throw $parseMinErr('isecfn',
-          'Referencing Function in Angular expressions is disallowed! Expression: {0}',
-          fullExpression);
-    } else if (// isWindow(obj)
-        obj.document && obj.location && obj.alert && obj.setInterval) {
-      throw $parseMinErr('isecwindow',
-          'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
-          fullExpression);
-    } else if (// isElement(obj)
-        obj.children && (obj.nodeName || (obj.on && obj.find))) {
-      throw $parseMinErr('isecdom',
-          'Referencing DOM nodes in Angular expressions is disallowed! Expression: {0}',
-          fullExpression);
-    }
-  }
-  return obj;
-}
-
-var OPERATORS = {
-    /* jshint bitwise : false */
-    'null':function(){return null;},
-    'true':function(){return true;},
-    'false':function(){return false;},
-    undefined:noop,
-    '+':function(self, locals, a,b){
-      a=a(self, locals); b=b(self, locals);
-      if (isDefined(a)) {
-        if (isDefined(b)) {
-          return a + b;
-        }
-        return a;
-      }
-      return isDefined(b)?b:undefined;},
-    '-':function(self, locals, a,b){
-          a=a(self, locals); b=b(self, locals);
-          return (isDefined(a)?a:0)-(isDefined(b)?b:0);
-        },
-    '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);},
-    '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);},
-    '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);},
-    '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);},
-    '=':noop,
-    '===':function(self, locals, a, b){return a(self, locals)===b(self, locals);},
-    '!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);},
-    '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);},
-    '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);},
-    '<':function(self, locals, a,b){return a(self, locals)<b(self, locals);},
-    '>':function(self, locals, a,b){return a(self, locals)>b(self, locals);},
-    '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);},
-    '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);},
-    '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);},
-    '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);},
-    '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);},
-//    '|':function(self, locals, a,b){return a|b;},
-    '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));},
-    '!':function(self, locals, a){return !a(self, locals);}
-};
-/* jshint bitwise: true */
-var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
-
-
-/////////////////////////////////////////
-
-
-/**
- * @constructor
- */
-var Lexer = function (options) {
-  this.options = options;
-};
-
-Lexer.prototype = {
-  constructor: Lexer,
-
-  lex: function (text) {
-    this.text = text;
-
-    this.index = 0;
-    this.ch = undefined;
-    this.lastCh = ':'; // can start regexp
-
-    this.tokens = [];
-
-    var token;
-    var json = [];
-
-    while (this.index < this.text.length) {
-      this.ch = this.text.charAt(this.index);
-      if (this.is('"\'')) {
-        this.readString(this.ch);
-      } else if (this.isNumber(this.ch) || this.is('.') && this.isNumber(this.peek())) {
-        this.readNumber();
-      } else if (this.isIdent(this.ch)) {
-        this.readIdent();
-        // identifiers can only be if the preceding char was a { or ,
-        if (this.was('{,') && json[0] === '{' &&
-            (token = this.tokens[this.tokens.length - 1])) {
-          token.json = token.text.indexOf('.') === -1;
-        }
-      } else if (this.is('(){}[].,;:?')) {
-        this.tokens.push({
-          index: this.index,
-          text: this.ch,
-          json: (this.was(':[,') && this.is('{[')) || this.is('}]:,')
-        });
-        if (this.is('{[')) json.unshift(this.ch);
-        if (this.is('}]')) json.shift();
-        this.index++;
-      } else if (this.isWhitespace(this.ch)) {
-        this.index++;
-        continue;
-      } else {
-        var ch2 = this.ch + this.peek();
-        var ch3 = ch2 + this.peek(2);
-        var fn = OPERATORS[this.ch];
-        var fn2 = OPERATORS[ch2];
-        var fn3 = OPERATORS[ch3];
-        if (fn3) {
-          this.tokens.push({index: this.index, text: ch3, fn: fn3});
-          this.index += 3;
-        } else if (fn2) {
-          this.tokens.push({index: this.index, text: ch2, fn: fn2});
-          this.index += 2;
-        } else if (fn) {
-          this.tokens.push({
-            index: this.index,
-            text: this.ch,
-            fn: fn,
-            json: (this.was('[,:') && this.is('+-'))
-          });
-          this.index += 1;
-        } else {
-          this.throwError('Unexpected next character ', this.index, this.index + 1);
-        }
-      }
-      this.lastCh = this.ch;
-    }
-    return this.tokens;
-  },
-
-  is: function(chars) {
-    return chars.indexOf(this.ch) !== -1;
-  },
-
-  was: function(chars) {
-    return chars.indexOf(this.lastCh) !== -1;
-  },
-
-  peek: function(i) {
-    var num = i || 1;
-    return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
-  },
-
-  isNumber: function(ch) {
-    return ('0' <= ch && ch <= '9');
-  },
-
-  isWhitespace: function(ch) {
-    // IE treats non-breaking space as \u00A0
-    return (ch === ' ' || ch === '\r' || ch === '\t' ||
-            ch === '\n' || ch === '\v' || ch === '\u00A0');
-  },
-
-  isIdent: function(ch) {
-    return ('a' <= ch && ch <= 'z' ||
-            'A' <= ch && ch <= 'Z' ||
-            '_' === ch || ch === '$');
-  },
-
-  isExpOperator: function(ch) {
-    return (ch === '-' || ch === '+' || this.isNumber(ch));
-  },
-
-  throwError: function(error, start, end) {
-    end = end || this.index;
-    var colStr = (isDefined(start)
-            ? 's ' + start +  '-' + this.index + ' [' + this.text.substring(start, end) + ']'
-            : ' ' + end);
-    throw $parseMinErr('lexerr', 'Lexer Error: {0} at column{1} in expression [{2}].',
-        error, colStr, this.text);
-  },
-
-  readNumber: function() {
-    var number = '';
-    var start = this.index;
-    while (this.index < this.text.length) {
-      var ch = lowercase(this.text.charAt(this.index));
-      if (ch == '.' || this.isNumber(ch)) {
-        number += ch;
-      } else {
-        var peekCh = this.peek();
-        if (ch == 'e' && this.isExpOperator(peekCh)) {
-          number += ch;
-        } else if (this.isExpOperator(ch) &&
-            peekCh && this.isNumber(peekCh) &&
-            number.charAt(number.length - 1) == 'e') {
-          number += ch;
-        } else if (this.isExpOperator(ch) &&
-            (!peekCh || !this.isNumber(peekCh)) &&
-            number.charAt(number.length - 1) == 'e') {
-          this.throwError('Invalid exponent');
-        } else {
-          break;
-        }
-      }
-      this.index++;
-    }
-    number = 1 * number;
-    this.tokens.push({
-      index: start,
-      text: number,
-      json: true,
-      fn: function() { return number; }
-    });
-  },
-
-  readIdent: function() {
-    var parser = this;
-
-    var ident = '';
-    var start = this.index;
-
-    var lastDot, peekIndex, methodName, ch;
-
-    while (this.index < this.text.length) {
-      ch = this.text.charAt(this.index);
-      if (ch === '.' || this.isIdent(ch) || this.isNumber(ch)) {
-        if (ch === '.') lastDot = this.index;
-        ident += ch;
-      } else {
-        break;
-      }
-      this.index++;
-    }
-
-    //check if this is not a method invocation and if it is back out to last dot
-    if (lastDot) {
-      peekIndex = this.index;
-      while (peekIndex < this.text.length) {
-        ch = this.text.charAt(peekIndex);
-        if (ch === '(') {
-          methodName = ident.substr(lastDot - start + 1);
-          ident = ident.substr(0, lastDot - start);
-          this.index = peekIndex;
-          break;
-        }
-        if (this.isWhitespace(ch)) {
-          peekIndex++;
-        } else {
-          break;
-        }
-      }
-    }
-
-
-    var token = {
-      index: start,
-      text: ident
-    };
-
-    // OPERATORS is our own object so we don't need to use special hasOwnPropertyFn
-    if (OPERATORS.hasOwnProperty(ident)) {
-      token.fn = OPERATORS[ident];
-      token.json = OPERATORS[ident];
-    } else {
-      var getter = getterFn(ident, this.options, this.text);
-      token.fn = extend(function(self, locals) {
-        return (getter(self, locals));
-      }, {
-        assign: function(self, value) {
-          return setter(self, ident, value, parser.text, parser.options);
-        }
-      });
-    }
-
-    this.tokens.push(token);
-
-    if (methodName) {
-      this.tokens.push({
-        index:lastDot,
-        text: '.',
-        json: false
-      });
-      this.tokens.push({
-        index: lastDot + 1,
-        text: methodName,
-        json: false
-      });
-    }
-  },
-
-  readString: function(quote) {
-    var start = this.index;
-    this.index++;
-    var string = '';
-    var rawString = quote;
-    var escape = false;
-    while (this.index < this.text.length) {
-      var ch = this.text.charAt(this.index);
-      rawString += ch;
-      if (escape) {
-        if (ch === 'u') {
-          var hex = this.text.substring(this.index + 1, this.index + 5);
-          if (!hex.match(/[\da-f]{4}/i))
-            this.throwError('Invalid unicode escape [\\u' + hex + ']');
-          this.index += 4;
-          string += String.fromCharCode(parseInt(hex, 16));
-        } else {
-          var rep = ESCAPE[ch];
-          if (rep) {
-            string += rep;
-          } else {
-            string += ch;
-          }
-        }
-        escape = false;
-      } else if (ch === '\\') {
-        escape = true;
-      } else if (ch === quote) {
-        this.index++;
-        this.tokens.push({
-          index: start,
-          text: rawString,
-          string: string,
-          json: true,
-          fn: function() { return string; }
-        });
-        return;
-      } else {
-        string += ch;
-      }
-      this.index++;
-    }
-    this.throwError('Unterminated quote', start);
-  }
-};
-
-
-/**
- * @constructor
- */
-var Parser = function (lexer, $filter, options) {
-  this.lexer = lexer;
-  this.$filter = $filter;
-  this.options = options;
-};
-
-Parser.ZERO = function () { return 0; };
-
-Parser.prototype = {
-  constructor: Parser,
-
-  parse: function (text, json) {
-    this.text = text;
-
-    //TODO(i): strip all the obsolte json stuff from this file
-    this.json = json;
-
-    this.tokens = this.lexer.lex(text);
-
-    if (json) {
-      // The extra level of aliasing is here, just in case the lexer misses something, so that
-      // we prevent any accidental execution in JSON.
-      this.assignment = this.logicalOR;
-
-      this.functionCall =
-      this.fieldAccess =
-      this.objectIndex =
-      this.filterChain = function() {
-        this.throwError('is not valid json', {text: text, index: 0});
-      };
-    }
-
-    var value = json ? this.primary() : this.statements();
-
-    if (this.tokens.length !== 0) {
-      this.throwError('is an unexpected token', this.tokens[0]);
-    }
-
-    value.literal = !!value.literal;
-    value.constant = !!value.constant;
-
-    return value;
-  },
-
-  primary: function () {
-    var primary;
-    if (this.expect('(')) {
-      primary = this.filterChain();
-      this.consume(')');
-    } else if (this.expect('[')) {
-      primary = this.arrayDeclaration();
-    } else if (this.expect('{')) {
-      primary = this.object();
-    } else {
-      var token = this.expect();
-      primary = token.fn;
-      if (!primary) {
-        this.throwError('not a primary expression', token);
-      }
-      if (token.json) {
-        primary.constant = true;
-        primary.literal = true;
-      }
-    }
-
-    var next, context;
-    while ((next = this.expect('(', '[', '.'))) {
-      if (next.text === '(') {
-        primary = this.functionCall(primary, context);
-        context = null;
-      } else if (next.text === '[') {
-        context = primary;
-        primary = this.objectIndex(primary);
-      } else if (next.text === '.') {
-        context = primary;
-        primary = this.fieldAccess(primary);
-      } else {
-        this.throwError('IMPOSSIBLE');
-      }
-    }
-    return primary;
-  },
-
-  throwError: function(msg, token) {
-    throw $parseMinErr('syntax',
-        'Syntax Error: Token \'{0}\' {1} at column {2} of the expression [{3}] starting at [{4}].',
-          token.text, msg, (token.index + 1), this.text, this.text.substring(token.index));
-  },
-
-  peekToken: function() {
-    if (this.tokens.length === 0)
-      throw $parseMinErr('ueoe', 'Unexpected end of expression: {0}', this.text);
-    return this.tokens[0];
-  },
-
-  peek: function(e1, e2, e3, e4) {
-    if (this.tokens.length > 0) {
-      var token = this.tokens[0];
-      var t = token.text;
-      if (t === e1 || t === e2 || t === e3 || t === e4 ||
-          (!e1 && !e2 && !e3 && !e4)) {
-        return token;
-      }
-    }
-    return false;
-  },
-
-  expect: function(e1, e2, e3, e4){
-    var token = this.peek(e1, e2, e3, e4);
-    if (token) {
-      if (this.json && !token.json) {
-        this.throwError('is not valid json', token);
-      }
-      this.tokens.shift();
-      return token;
-    }
-    return false;
-  },
-
-  consume: function(e1){
-    if (!this.expect(e1)) {
-      this.throwError('is unexpected, expecting [' + e1 + ']', this.peek());
-    }
-  },
-
-  unaryFn: function(fn, right) {
-    return extend(function(self, locals) {
-      return fn(self, locals, right);
-    }, {
-      constant:right.constant
-    });
-  },
-
-  ternaryFn: function(left, middle, right){
-    return extend(function(self, locals){
-      return left(self, locals) ? middle(self, locals) : right(self, locals);
-    }, {
-      constant: left.constant && middle.constant && right.constant
-    });
-  },
-
-  binaryFn: function(left, fn, right) {
-    return extend(function(self, locals) {
-      return fn(self, locals, left, right);
-    }, {
-      constant:left.constant && right.constant
-    });
-  },
-
-  statements: function() {
-    var statements = [];
-    while (true) {
-      if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
-        statements.push(this.filterChain());
-      if (!this.expect(';')) {
-        // optimize for the common case where there is only one statement.
-        // TODO(size): maybe we should not support multiple statements?
-        return (statements.length === 1)
-            ? statements[0]
-            : function(self, locals) {
-                var value;
-                for (var i = 0; i < statements.length; i++) {
-                  var statement = statements[i];
-                  if (statement) {
-                    value = statement(self, locals);
-                  }
-                }
-                return value;
-              };
-      }
-    }
-  },
-
-  filterChain: function() {
-    var left = this.expression();
-    var token;
-    while (true) {
-      if ((token = this.expect('|'))) {
-        left = this.binaryFn(left, token.fn, this.filter());
-      } else {
-        return left;
-      }
-    }
-  },
-
-  filter: function() {
-    var token = this.expect();
-    var fn = this.$filter(token.text);
-    var argsFn = [];
-    while (true) {
-      if ((token = this.expect(':'))) {
-        argsFn.push(this.expression());
-      } else {
-        var fnInvoke = function(self, locals, input) {
-          var args = [input];
-          for (var i = 0; i < argsFn.length; i++) {
-            args.push(argsFn[i](self, locals));
-          }
-          return fn.apply(self, args);
-        };
-        return function() {
-          return fnInvoke;
-        };
-      }
-    }
-  },
-
-  expression: function() {
-    return this.assignment();
-  },
-
-  assignment: function() {
-    var left = this.ternary();
-    var right;
-    var token;
-    if ((token = this.expect('='))) {
-      if (!left.assign) {
-        this.throwError('implies assignment but [' +
-            this.text.substring(0, token.index) + '] can not be assigned to', token);
-      }
-      right = this.ternary();
-      return function(scope, locals) {
-        return left.assign(scope, right(scope, locals), locals);
-      };
-    }
-    return left;
-  },
-
-  ternary: function() {
-    var left = this.logicalOR();
-    var middle;
-    var token;
-    if ((token = this.expect('?'))) {
-      middle = this.ternary();
-      if ((token = this.expect(':'))) {
-        return this.ternaryFn(left, middle, this.ternary());
-      } else {
-        this.throwError('expected :', token);
-      }
-    } else {
-      return left;
-    }
-  },
-
-  logicalOR: function() {
-    var left = this.logicalAND();
-    var token;
-    while (true) {
-      if ((token = this.expect('||'))) {
-        left = this.binaryFn(left, token.fn, this.logicalAND());
-      } else {
-        return left;
-      }
-    }
-  },
-
-  logicalAND: function() {
-    var left = this.equality();
-    var token;
-    if ((token = this.expect('&&'))) {
-      left = this.binaryFn(left, token.fn, this.logicalAND());
-    }
-    return left;
-  },
-
-  equality: function() {
-    var left = this.relational();
-    var token;
-    if ((token = this.expect('==','!=','===','!=='))) {
-      left = this.binaryFn(left, token.fn, this.equality());
-    }
-    return left;
-  },
-
-  relational: function() {
-    var left = this.additive();
-    var token;
-    if ((token = this.expect('<', '>', '<=', '>='))) {
-      left = this.binaryFn(left, token.fn, this.relational());
-    }
-    return left;
-  },
-
-  additive: function() {
-    var left = this.multiplicative();
-    var token;
-    while ((token = this.expect('+','-'))) {
-      left = this.binaryFn(left, token.fn, this.multiplicative());
-    }
-    return left;
-  },
-
-  multiplicative: function() {
-    var left = this.unary();
-    var token;
-    while ((token = this.expect('*','/','%'))) {
-      left = this.binaryFn(left, token.fn, this.unary());
-    }
-    return left;
-  },
-
-  unary: function() {
-    var token;
-    if (this.expect('+')) {
-      return this.primary();
-    } else if ((token = this.expect('-'))) {
-      return this.binaryFn(Parser.ZERO, token.fn, this.unary());
-    } else if ((token = this.expect('!'))) {
-      return this.unaryFn(token.fn, this.unary());
-    } else {
-      return this.primary();
-    }
-  },
-
-  fieldAccess: function(object) {
-    var parser = this;
-    var field = this.expect().text;
-    var getter = getterFn(field, this.options, this.text);
-
-    return extend(function(scope, locals, self) {
-      return getter(self || object(scope, locals), locals);
-    }, {
-      assign: function(scope, value, locals) {
-        return setter(object(scope, locals), field, value, parser.text, parser.options);
-      }
-    });
-  },
-
-  objectIndex: function(obj) {
-    var parser = this;
-
-    var indexFn = this.expression();
-    this.consume(']');
-
-    return extend(function(self, locals) {
-      var o = obj(self, locals),
-          i = indexFn(self, locals),
-          v, p;
-
-      if (!o) return undefined;
-      v = ensureSafeObject(o[i], parser.text);
-      if (v && v.then && parser.options.unwrapPromises) {
-        p = v;
-        if (!('$$v' in v)) {
-          p.$$v = undefined;
-          p.then(function(val) { p.$$v = val; });
-        }
-        v = v.$$v;
-      }
-      return v;
-    }, {
-      assign: function(self, value, locals) {
-        var key = indexFn(self, locals);
-        // prevent overwriting of Function.constructor which would break ensureSafeObject check
-        var safe = ensureSafeObject(obj(self, locals), parser.text);
-        return safe[key] = value;
-      }
-    });
-  },
-
-  functionCall: function(fn, contextGetter) {
-    var argsFn = [];
-    if (this.peekToken().text !== ')') {
-      do {
-        argsFn.push(this.expression());
-      } while (this.expect(','));
-    }
-    this.consume(')');
-
-    var parser = this;
-
-    return function(scope, locals) {
-      var args = [];
-      var context = contextGetter ? contextGetter(scope, locals) : scope;
-
-      for (var i = 0; i < argsFn.length; i++) {
-        args.push(argsFn[i](scope, locals));
-      }
-      var fnPtr = fn(scope, locals, context) || noop;
-
-      ensureSafeObject(context, parser.text);
-      ensureSafeObject(fnPtr, parser.text);
-
-      // IE stupidity! (IE doesn't have apply for some native functions)
-      var v = fnPtr.apply
-            ? fnPtr.apply(context, args)
-            : fnPtr(args[0], args[1], args[2], args[3], args[4]);
-
-      return ensureSafeObject(v, parser.text);
-    };
-  },
-
-  // This is used with json array declaration
-  arrayDeclaration: function () {
-    var elementFns = [];
-    var allConstant = true;
-    if (this.peekToken().text !== ']') {
-      do {
-        var elementFn = this.expression();
-        elementFns.push(elementFn);
-        if (!elementFn.constant) {
-          allConstant = false;
-        }
-      } while (this.expect(','));
-    }
-    this.consume(']');
-
-    return extend(function(self, locals) {
-      var array = [];
-      for (var i = 0; i < elementFns.length; i++) {
-        array.push(elementFns[i](self, locals));
-      }
-      return array;
-    }, {
-      literal: true,
-      constant: allConstant
-    });
-  },
-
-  object: function () {
-    var keyValues = [];
-    var allConstant = true;
-    if (this.peekToken().text !== '}') {
-      do {
-        var token = this.expect(),
-        key = token.string || token.text;
-        this.consume(':');
-        var value = this.expression();
-        keyValues.push({key: key, value: value});
-        if (!value.constant) {
-          allConstant = false;
-        }
-      } while (this.expect(','));
-    }
-    this.consume('}');
-
-    return extend(function(self, locals) {
-      var object = {};
-      for (var i = 0; i < keyValues.length; i++) {
-        var keyValue = keyValues[i];
-        object[keyValue.key] = keyValue.value(self, locals);
-      }
-      return object;
-    }, {
-      literal: true,
-      constant: allConstant
-    });
-  }
-};
-
-
-//////////////////////////////////////////////////
-// Parser helper functions
-//////////////////////////////////////////////////
-
-function setter(obj, path, setValue, fullExp, options) {
-  //needed?
-  options = options || {};
-
-  var element = path.split('.'), key;
-  for (var i = 0; element.length > 1; i++) {
-    key = ensureSafeMemberName(element.shift(), fullExp);
-    var propertyObj = obj[key];
-    if (!propertyObj) {
-      propertyObj = {};
-      obj[key] = propertyObj;
-    }
-    obj = propertyObj;
-    if (obj.then && options.unwrapPromises) {
-      promiseWarning(fullExp);
-      if (!("$$v" in obj)) {
-        (function(promise) {
-          promise.then(function(val) { promise.$$v = val; }); }
-        )(obj);
-      }
-      if (obj.$$v === undefined) {
-        obj.$$v = {};
-      }
-      obj = obj.$$v;
-    }
-  }
-  key = ensureSafeMemberName(element.shift(), fullExp);
-  obj[key] = setValue;
-  return setValue;
-}
-
-var getterFnCache = {};
-
-/**
- * Implementation of the "Black Hole" variant from:
- * - http://jsperf.com/angularjs-parse-getter/4
- * - http://jsperf.com/path-evaluation-simplified/7
- */
-function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
-  ensureSafeMemberName(key0, fullExp);
-  ensureSafeMemberName(key1, fullExp);
-  ensureSafeMemberName(key2, fullExp);
-  ensureSafeMemberName(key3, fullExp);
-  ensureSafeMemberName(key4, fullExp);
-
-  return !options.unwrapPromises
-      ? function cspSafeGetter(scope, locals) {
-          var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
-
-          if (pathVal === null || pathVal === undefined) return pathVal;
-          pathVal = pathVal[key0];
-
-          if (!key1 || pathVal === null || pathVal === undefined) return pathVal;
-          pathVal = pathVal[key1];
-
-          if (!key2 || pathVal === null || pathVal === undefined) return pathVal;
-          pathVal = pathVal[key2];
-
-          if (!key3 || pathVal === null || pathVal === undefined) return pathVal;
-          pathVal = pathVal[key3];
-
-          if (!key4 || pathVal === null || pathVal === undefined) return pathVal;
-          pathVal = pathVal[key4];
-
-          return pathVal;
-        }
-      : function cspSafePromiseEnabledGetter(scope, locals) {
-          var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,
-              promise;
-
-          if (pathVal === null || pathVal === undefined) return pathVal;
-
-          pathVal = pathVal[key0];
-          if (pathVal && pathVal.then) {
-            promiseWarning(fullExp);
-            if (!("$$v" in pathVal)) {
-              promise = pathVal;
-              promise.$$v = undefined;
-              promise.then(function(val) { promise.$$v = val; });
-            }
-            pathVal = pathVal.$$v;
-          }
-          if (!key1 || pathVal === null || pathVal === undefined) return pathVal;
-
-          pathVal = pathVal[key1];
-          if (pathVal && pathVal.then) {
-            promiseWarning(fullExp);
-            if (!("$$v" in pathVal)) {
-              promise = pathVal;
-              promise.$$v = undefined;
-              promise.then(function(val) { promise.$$v = val; });
-            }
-            pathVal = pathVal.$$v;
-          }
-          if (!key2 || pathVal === null || pathVal === undefined) return pathVal;
-
-          pathVal = pathVal[key2];
-          if (pathVal && pathVal.then) {
-            promiseWarning(fullExp);
-            if (!("$$v" in pathVal)) {
-              promise = pathVal;
-              promise.$$v = undefined;
-              promise.then(function(val) { promise.$$v = val; });
-            }
-            pathVal = pathVal.$$v;
-          }
-          if (!key3 || pathVal === null || pathVal === undefined) return pathVal;
-
-          pathVal = pathVal[key3];
-          if (pathVal && pathVal.then) {
-            promiseWarning(fullExp);
-            if (!("$$v" in pathVal)) {
-              promise = pathVal;
-              promise.$$v = undefined;
-              promise.then(function(val) { promise.$$v = val; });
-            }
-            pathVal = pathVal.$$v;
-          }
-          if (!key4 || pathVal === null || pathVal === undefined) return pathVal;
-
-          pathVal = pathVal[key4];
-          if (pathVal && pathVal.then) {
-            promiseWarning(fullExp);
-            if (!("$$v" in pathVal)) {
-              promise = pathVal;
-              promise.$$v = undefined;
-              promise.then(function(val) { promise.$$v = val; });
-            }
-            pathVal = pathVal.$$v;
-          }
-          return pathVal;
-        };
-}
-
-function getterFn(path, options, fullExp) {
-  // Check whether the cache has this getter already.
-  // We can use hasOwnProperty directly on the cache because we ensure,
-  // see below, that the cache never stores a path called 'hasOwnProperty'
-  if (getterFnCache.hasOwnProperty(path)) {
-    return getterFnCache[path];
-  }
-
-  var pathKeys = path.split('.'),
-      pathKeysLength = pathKeys.length,
-      fn;
-
-  if (options.csp) {
-    if (pathKeysLength < 6) {
-      fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp,
-                          options);
-    } else {
-      fn = function(scope, locals) {
-        var i = 0, val;
-        do {
-          val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],
-                                pathKeys[i++], fullExp, options)(scope, locals);
-
-          locals = undefined; // clear after first iteration
-          scope = val;
-        } while (i < pathKeysLength);
-        return val;
-      };
-    }
-  } else {
-    var code = 'var l, fn, p;\n';
-    forEach(pathKeys, function(key, index) {
-      ensureSafeMemberName(key, fullExp);
-      code += 'if(s === null || s === undefined) return s;\n' +
-              'l=s;\n' +
-              's='+ (index
-                      // we simply dereference 's' on any .dot notation
-                      ? 's'
-                      // but if we are first then we check locals first, and if so read it first
-                      : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' +
-              (options.unwrapPromises
-                ? 'if (s && s.then) {\n' +
-                  ' pw("' + fullExp.replace(/(["\r\n])/g, '\\$1') + '");\n' +
-                  ' if (!("$$v" in s)) {\n' +
-                    ' p=s;\n' +
-                    ' p.$$v = undefined;\n' +
-                    ' p.then(function(v) {p.$$v=v;});\n' +
-                    '}\n' +
-                  ' s=s.$$v\n' +
-                '}\n'
-                : '');
-    });
-    code += 'return s;';
-
-    /* jshint -W054 */
-    var evaledFnGetter = new Function('s', 'k', 'pw', code); // s=scope, k=locals, pw=promiseWarning
-    /* jshint +W054 */
-    evaledFnGetter.toString = function() { return code; };
-    fn = function(scope, locals) {
-      return evaledFnGetter(scope, locals, promiseWarning);
-    };
-  }
-
-  // Only cache the value if it's not going to mess up the cache object
-  // This is more performant that using Object.prototype.hasOwnProperty.call
-  if (path !== 'hasOwnProperty') {
-    getterFnCache[path] = fn;
-  }
-  return fn;
-}
-
-///////////////////////////////////
-
-/**
- * @ngdoc function
- * @name ng.$parse
- * @function
- *
- * @description
- *
- * Converts Angular {@link guide/expression expression} into a function.
- *
- * <pre>
- *   var getter = $parse('user.name');
- *   var setter = getter.assign;
- *   var context = {user:{name:'angular'}};
- *   var locals = {user:{name:'local'}};
- *
- *   expect(getter(context)).toEqual('angular');
- *   setter(context, 'newValue');
- *   expect(context.user.name).toEqual('newValue');
- *   expect(getter(context, locals)).toEqual('local');
- * </pre>
- *
- *
- * @param {string} expression String expression to compile.
- * @returns {function(context, locals)} a function which represents the compiled expression:
- *
- *    * `context` – `{object}` – an object against which any expressions embedded in the strings
- *      are evaluated against (typically a scope object).
- *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
- *      `context`.
- *
- *    The returned function also has the following properties:
- *      * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript
- *        literal.
- *      * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript
- *        constant literals.
- *      * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be
- *        set to a function to change its value on the given context.
- *
- */
-
-
-/**
- * @ngdoc object
- * @name ng.$parseProvider
- * @function
- *
- * @description
- * `$parseProvider` can be used for configuring the default behavior of the {@link ng.$parse $parse}
- *  service.
- */
-function $ParseProvider() {
-  var cache = {};
-
-  var $parseOptions = {
-    csp: false,
-    unwrapPromises: false,
-    logPromiseWarnings: true
-  };
-
-
-  /**
-   * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
-   *
-   * @ngdoc method
-   * @name ng.$parseProvider#unwrapPromises
-   * @methodOf ng.$parseProvider
-   * @description
-   *
-   * **This feature is deprecated, see deprecation notes below for more info**
-   *
-   * If set to true (default is false), $parse will unwrap promises automatically when a promise is
-   * found at any part of the expression. In other words, if set to true, the expression will always
-   * result in a non-promise value.
-   *
-   * While the promise is unresolved, it's treated as undefined, but once resolved and fulfilled,
-   * the fulfillment value is used in place of the promise while evaluating the expression.
-   *
-   * **Deprecation notice**
-   *
-   * This is a feature that didn't prove to be wildly useful or popular, primarily because of the
-   * dichotomy between data access in templates (accessed as raw values) and controller code
-   * (accessed as promises).
-   *
-   * In most code we ended up resolving promises manually in controllers anyway and thus unifying
-   * the model access there.
-   *
-   * Other downsides of automatic promise unwrapping:
-   *
-   * - when building components it's often desirable to receive the raw promises
-   * - adds complexity and slows down expression evaluation
-   * - makes expression code pre-generation unattractive due to the amount of code that needs to be
-   *   generated
-   * - makes IDE auto-completion and tool support hard
-   *
-   * **Warning Logs**
-   *
-   * If the unwrapping is enabled, Angular will log a warning about each expression that unwraps a
-   * promise (to reduce the noise, each expression is logged only once). To disable this logging use
-   * `$parseProvider.logPromiseWarnings(false)` api.
-   *
-   *
-   * @param {boolean=} value New value.
-   * @returns {boolean|self} Returns the current setting when used as getter and self if used as
-   *                         setter.
-   */
-  this.unwrapPromises = function(value) {
-    if (isDefined(value)) {
-      $parseOptions.unwrapPromises = !!value;
-      return this;
-    } else {
-      return $parseOptions.unwrapPromises;
-    }
-  };
-
-
-  /**
-   * @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
-   *
-   * @ngdoc method
-   * @name ng.$parseProvider#logPromiseWarnings
-   * @methodOf ng.$parseProvider
-   * @description
-   *
-   * Controls whether Angular should log a warning on any encounter of a promise in an expression.
-   *
-   * The default is set to `true`.
-   *
-   * This setting applies only if `$parseProvider.unwrapPromises` setting is set to true as well.
-   *
-   * @param {boolean=} value New value.
-   * @returns {boolean|self} Returns the current setting when used as getter and self if used as
-   *                         setter.
-   */
- this.logPromiseWarnings = function(value) {
-    if (isDefined(value)) {
-      $parseOptions.logPromiseWarnings = value;
-      return this;
-    } else {
-      return $parseOptions.logPromiseWarnings;
-    }
-  };
-
-
-  this.$get = ['$filter', '$sniffer', '$log', function($filter, $sniffer, $log) {
-    $parseOptions.csp = $sniffer.csp;
-
-    promiseWarning = function promiseWarningFn(fullExp) {
-      if (!$parseOptions.logPromiseWarnings || promiseWarningCache.hasOwnProperty(fullExp)) return;
-      promiseWarningCache[fullExp] = true;
-      $log.warn('[$parse] Promise found in the expression `' + fullExp + '`. ' +
-          'Automatic unwrapping of promises in Angular expressions is deprecated.');
-    };
-
-    return function(exp) {
-      var parsedExpression;
-
-      switch (typeof exp) {
-        case 'string':
-
-          if (cache.hasOwnProperty(exp)) {
-            return cache[exp];
-          }
-
-          var lexer = new Lexer($parseOptions);
-          var parser = new Parser(lexer, $filter, $parseOptions);
-          parsedExpression = parser.parse(exp, false);
-
-          if (exp !== 'hasOwnProperty') {
-            // Only cache the value if it's not going to mess up the cache object
-            // This is more performant that using Object.prototype.hasOwnProperty.call
-            cache[exp] = parsedExpression;
-          }
-
-          return parsedExpression;
-
-        case 'function':
-          return exp;
-
-        default:
-          return noop;
-      }
-    };
-  }];
-}
-
-/**
- * @ngdoc service
- * @name ng.$q
- * @requires $rootScope
- *
- * @description
- * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).
- *
- * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
- * interface for interacting with an object that represents the result of an action that is
- * performed asynchronously, and may or may not be finished at any given point in time.
- *
- * From the perspective of dealing with error handling, deferred and promise APIs are to
- * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming.
- *
- * <pre>
- *   // for the purpose of this example let's assume that variables `$q` and `scope` are
- *   // available in the current lexical scope (they could have been injected or passed in).
- *
- *   function asyncGreet(name) {
- *     var deferred = $q.defer();
- *
- *     setTimeout(function() {
- *       // since this fn executes async in a future turn of the event loop, we need to wrap
- *       // our code into an $apply call so that the model changes are properly observed.
- *       scope.$apply(function() {
- *         deferred.notify('About to greet ' + name + '.');
- *
- *         if (okToGreet(name)) {
- *           deferred.resolve('Hello, ' + name + '!');
- *         } else {
- *           deferred.reject('Greeting ' + name + ' is not allowed.');
- *         }
- *       });
- *     }, 1000);
- *
- *     return deferred.promise;
- *   }
- *
- *   var promise = asyncGreet('Robin Hood');
- *   promise.then(function(greeting) {
- *     alert('Success: ' + greeting);
- *   }, function(reason) {
- *     alert('Failed: ' + reason);
- *   }, function(update) {
- *     alert('Got notification: ' + update);
- *   });
- * </pre>
- *
- * At first it might not be obvious why this extra complexity is worth the trouble. The payoff
- * comes in the way of guarantees that promise and deferred APIs make, see
- * https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md.
- *
- * Additionally the promise api allows for composition that is very hard to do with the
- * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach.
- * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
- * section on serial or parallel joining of promises.
- *
- *
- * # The Deferred API
- *
- * A new instance of deferred is constructed by calling `$q.defer()`.
- *
- * The purpose of the deferred object is to expose the associated Promise instance as well as APIs
- * that can be used for signaling the successful or unsuccessful completion, as well as the status
- * of the task.
- *
- * **Methods**
- *
- * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection
- *   constructed via `$q.reject`, the promise will be rejected instead.
- * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to
- *   resolving it with a rejection constructed via `$q.reject`.
- * - `notify(value)` - provides updates on the status of the promises execution. This may be called
- *   multiple times before the promise is either resolved or rejected.
- *
- * **Properties**
- *
- * - promise – `{Promise}` – promise object associated with this deferred.
- *
- *
- * # The Promise API
- *
- * A new promise instance is created when a deferred instance is created and can be retrieved by
- * calling `deferred.promise`.
- *
- * The purpose of the promise object is to allow for interested parties to get access to the result
- * of the deferred task when it completes.
- *
- * **Methods**
- *
- * - `then(successCallback, errorCallback, notifyCallback)` – regardless of when the promise was or
- *   will be resolved or rejected, `then` calls one of the success or error callbacks asynchronously
- *   as soon as the result is available. The callbacks are called with a single argument: the result
- *   or rejection reason. Additionally, the notify callback may be called zero or more times to
- *   provide a progress indication, before the promise is resolved or rejected.
- *
- *   This method *returns a new promise* which is resolved or rejected via the return value of the
- *   `successCallback`, `errorCallback`. It also notifies via the return value of the
- *   `notifyCallback` method. The promise can not be resolved or rejected from the notifyCallback
- *   method.
- *
- * - `catch(errorCallback)` – shorthand for `promise.then(null, errorCallback)`
- *
- * - `finally(callback)` – allows you to observe either the fulfillment or rejection of a promise,
- *   but to do so without modifying the final value. This is useful to release resources or do some
- *   clean-up that needs to be done whether the promise was rejected or resolved. See the [full
- *   specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for
- *   more information.
- *
- *   Because `finally` is a reserved word in JavaScript and reserved keywords are not supported as
- *   property names by ES3, you'll need to invoke the method like `promise['finally'](callback)` to
- *   make your code IE8 compatible.
- *
- * # Chaining promises
- *
- * Because calling the `then` method of a promise returns a new derived promise, it is easily
- * possible to create a chain of promises:
- *
- * <pre>
- *   promiseB = promiseA.then(function(result) {
- *     return result + 1;
- *   });
- *
- *   // promiseB will be resolved immediately after promiseA is resolved and its value
- *   // will be the result of promiseA incremented by 1
- * </pre>
- *
- * It is possible to create chains of any length and since a promise can be resolved with another
- * promise (which will defer its resolution further), it is possible to pause/defer resolution of
- * the promises at any point in the chain. This makes it possible to implement powerful APIs like
- * $http's response interceptors.
- *
- *
- * # Differences between Kris Kowal's Q and $q
- *
- *  There are two main differences:
- *
- * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation
- *   mechanism in angular, which means faster propagation of resolution or rejection into your
- *   models and avoiding unnecessary browser repaints, which would result in flickering UI.
- * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains
- *   all the important functionality needed for common async tasks.
- *
- *  # Testing
- *
- *  <pre>
- *    it('should simulate promise', inject(function($q, $rootScope) {
- *      var deferred = $q.defer();
- *      var promise = deferred.promise;
- *      var resolvedValue;
- *
- *      promise.then(function(value) { resolvedValue = value; });
- *      expect(resolvedValue).toBeUndefined();
- *
- *      // Simulate resolving of promise
- *      deferred.resolve(123);
- *      // Note that the 'then' function does not get called synchronously.
- *      // This is because we want the promise API to always be async, whether or not
- *      // it got called synchronously or asynchronously.
- *      expect(resolvedValue).toBeUndefined();
- *
- *      // Propagate promise resolution to 'then' functions using $apply().
- *      $rootScope.$apply();
- *      expect(resolvedValue).toEqual(123);
- *    }));
- *  </pre>
- */
-function $QProvider() {
-
-  this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
-    return qFactory(function(callback) {
-      $rootScope.$evalAsync(callback);
-    }, $exceptionHandler);
-  }];
-}
-
-
-/**
- * Constructs a promise manager.
- *
- * @param {function(function)} nextTick Function for executing functions in the next turn.
- * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for
- *     debugging purposes.
- * @returns {object} Promise manager.
- */
-function qFactory(nextTick, exceptionHandler) {
-
-  /**
-   * @ngdoc
-   * @name ng.$q#defer
-   * @methodOf ng.$q
-   * @description
-   * Creates a `Deferred` object which represents a task which will finish in the future.
-   *
-   * @returns {Deferred} Returns a new instance of deferred.
-   */
-  var defer = function() {
-    var pending = [],
-        value, deferred;
-
-    deferred = {
-
-      resolve: function(val) {
-        if (pending) {
-          var callbacks = pending;
-          pending = undefined;
-          value = ref(val);
-
-          if (callbacks.length) {
-            nextTick(function() {
-              var callback;
-              for (var i = 0, ii = callbacks.length; i < ii; i++) {
-                callback = callbacks[i];
-                value.then(callback[0], callback[1], callback[2]);
-              }
-            });
-          }
-        }
-      },
-
-
-      reject: function(reason) {
-        deferred.resolve(reject(reason));
-      },
-
-
-      notify: function(progress) {
-        if (pending) {
-          var callbacks = pending;
-
-          if (pending.length) {
-            nextTick(function() {
-              var callback;
-              for (var i = 0, ii = callbacks.length; i < ii; i++) {
-                callback = callbacks[i];
-                callback[2](progress);
-              }
-            });
-          }
-        }
-      },
-
-
-      promise: {
-        then: function(callback, errback, progressback) {
-          var result = defer();
-
-          var wrappedCallback = function(value) {
-            try {
-              result.resolve((isFunction(callback) ? callback : defaultCallback)(value));
-            } catch(e) {
-              result.reject(e);
-              exceptionHandler(e);
-            }
-          };
-
-          var wrappedErrback = function(reason) {
-            try {
-              result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
-            } catch(e) {
-              result.reject(e);
-              exceptionHandler(e);
-            }
-          };
-
-          var wrappedProgressback = function(progress) {
-            try {
-              result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));
-            } catch(e) {
-              exceptionHandler(e);
-            }
-          };
-
-          if (pending) {
-            pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);
-          } else {
-            value.then(wrappedCallback, wrappedErrback, wrappedProgressback);
-          }
-
-          return result.promise;
-        },
-
-        "catch": function(callback) {
-          return this.then(null, callback);
-        },
-
-        "finally": function(callback) {
-
-          function makePromise(value, resolved) {
-            var result = defer();
-            if (resolved) {
-              result.resolve(value);
-            } else {
-              result.reject(value);
-            }
-            return result.promise;
-          }
-
-          function handleCallback(value, isResolved) {
-            var callbackOutput = null;
-            try {
-              callbackOutput = (callback ||defaultCallback)();
-            } catch(e) {
-              return makePromise(e, false);
-            }
-            if (callbackOutput && isFunction(callbackOutput.then)) {
-              return callbackOutput.then(function() {
-                return makePromise(value, isResolved);
-              }, function(error) {
-                return makePromise(error, false);
-              });
-            } else {
-              return makePromise(value, isResolved);
-            }
-          }
-
-          return this.then(function(value) {
-            return handleCallback(value, true);
-          }, function(error) {
-            return handleCallback(error, false);
-          });
-        }
-      }
-    };
-
-    return deferred;
-  };
-
-
-  var ref = function(value) {
-    if (value && isFunction(value.then)) return value;
-    return {
-      then: function(callback) {
-        var result = defer();
-        nextTick(function() {
-          result.resolve(callback(value));
-        });
-        return result.promise;
-      }
-    };
-  };
-
-
-  /**
-   * @ngdoc
-   * @name ng.$q#reject
-   * @methodOf ng.$q
-   * @description
-   * Creates a promise that is resolved as rejected with the specified `reason`. This api should be
-   * used to forward rejection in a chain of promises. If you are dealing with the last promise in
-   * a promise chain, you don't need to worry about it.
-   *
-   * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of
-   * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via
-   * a promise error callback and you want to forward the error to the promise derived from the
-   * current promise, you have to "rethrow" the error by returning a rejection constructed via
-   * `reject`.
-   *
-   * <pre>
-   *   promiseB = promiseA.then(function(result) {
-   *     // success: do something and resolve promiseB
-   *     //          with the old or a new result
-   *     return result;
-   *   }, function(reason) {
-   *     // error: handle the error if possible and
-   *     //        resolve promiseB with newPromiseOrValue,
-   *     //        otherwise forward the rejection to promiseB
-   *     if (canHandle(reason)) {
-   *      // handle the error and recover
-   *      return newPromiseOrValue;
-   *     }
-   *     return $q.reject(reason);
-   *   });
-   * </pre>
-   *
-   * @param {*} reason Constant, message, exception or an object representing the rejection reason.
-   * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
-   */
-  var reject = function(reason) {
-    return {
-      then: function(callback, errback) {
-        var result = defer();
-        nextTick(function() {
-          try {
-            result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
-          } catch(e) {
-            result.reject(e);
-            exceptionHandler(e);
-          }
-        });
-        return result.promise;
-      }
-    };
-  };
-
-
-  /**
-   * @ngdoc
-   * @name ng.$q#when
-   * @methodOf ng.$q
-   * @description
-   * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise.
-   * This is useful when you are dealing with an object that might or might not be a promise, or if
-   * the promise comes from a source that can't be trusted.
-   *
-   * @param {*} value Value or a promise
-   * @returns {Promise} Returns a promise of the passed value or promise
-   */
-  var when = function(value, callback, errback, progressback) {
-    var result = defer(),
-        done;
-
-    var wrappedCallback = function(value) {
-      try {
-        return (isFunction(callback) ? callback : defaultCallback)(value);
-      } catch (e) {
-        exceptionHandler(e);
-        return reject(e);
-      }
-    };
-
-    var wrappedErrback = function(reason) {
-      try {
-        return (isFunction(errback) ? errback : defaultErrback)(reason);
-      } catch (e) {
-        exceptionHandler(e);
-        return reject(e);
-      }
-    };
-
-    var wrappedProgressback = function(progress) {
-      try {
-        return (isFunction(progressback) ? progressback : defaultCallback)(progress);
-      } catch (e) {
-        exceptionHandler(e);
-      }
-    };
-
-    nextTick(function() {
-      ref(value).then(function(value) {
-        if (done) return;
-        done = true;
-        result.resolve(ref(value).then(wrappedCallback, wrappedErrback, wrappedProgressback));
-      }, function(reason) {
-        if (done) return;
-        done = true;
-        result.resolve(wrappedErrback(reason));
-      }, function(progress) {
-        if (done) return;
-        result.notify(wrappedProgressback(progress));
-      });
-    });
-
-    return result.promise;
-  };
-
-
-  function defaultCallback(value) {
-    return value;
-  }
-
-
-  function defaultErrback(reason) {
-    return reject(reason);
-  }
-
-
-  /**
-   * @ngdoc
-   * @name ng.$q#all
-   * @methodOf ng.$q
-   * @description
-   * Combines multiple promises into a single promise that is resolved when all of the input
-   * promises are resolved.
-   *
-   * @param {Array.<Promise>|Object.<Promise>} promises An array or hash of promises.
-   * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values,
-   *   each value corresponding to the promise at the same index/key in the `promises` array/hash.
-   *   If any of the promises is resolved with a rejection, this resulting promise will be rejected
-   *   with the same rejection value.
-   */
-  function all(promises) {
-    var deferred = defer(),
-        counter = 0,
-        results = isArray(promises) ? [] : {};
-
-    forEach(promises, function(promise, key) {
-      counter++;
-      ref(promise).then(function(value) {
-        if (results.hasOwnProperty(key)) return;
-        results[key] = value;
-        if (!(--counter)) deferred.resolve(results);
-      }, function(reason) {
-        if (results.hasOwnProperty(key)) return;
-        deferred.reject(reason);
-      });
-    });
-
-    if (counter === 0) {
-      deferred.resolve(results);
-    }
-
-    return deferred.promise;
-  }
-
-  return {
-    defer: defer,
-    reject: reject,
-    when: when,
-    all: all
-  };
-}
-
-/**
- * DESIGN NOTES
- *
- * The design decisions behind the scope are heavily favored for speed and memory consumption.
- *
- * The typical use of scope is to watch the expressions, which most of the time return the same
- * value as last time so we optimize the operation.
- *
- * Closures construction is expensive in terms of speed as well as memory:
- *   - No closures, instead use prototypical inheritance for API
- *   - Internal state needs to be stored on scope directly, which means that private state is
- *     exposed as $$____ properties
- *
- * Loop operations are optimized by using while(count--) { ... }
- *   - this means that in order to keep the same order of execution as addition we have to add
- *     items to the array at the beginning (shift) instead of at the end (push)
- *
- * Child scopes are created and removed often
- *   - Using an array would be slow since inserts in middle are expensive so we use linked list
- *
- * There are few watches then a lot of observers. This is why you don't want the observer to be
- * implemented in the same way as watch. Watch requires return of initialization function which
- * are expensive to construct.
- */
-
-
-/**
- * @ngdoc object
- * @name ng.$rootScopeProvider
- * @description
- *
- * Provider for the $rootScope service.
- */
-
-/**
- * @ngdoc function
- * @name ng.$rootScopeProvider#digestTtl
- * @methodOf ng.$rootScopeProvider
- * @description
- *
- * Sets the number of `$digest` iterations the scope should attempt to execute before giving up and
- * assuming that the model is unstable.
- *
- * The current default is 10 iterations.
- *
- * In complex applications it's possible that the dependencies between `$watch`s will result in
- * several digest iterations. However if an application needs more than the default 10 digest
- * iterations for its model to stabilize then you should investigate what is causing the model to
- * continuously change during the digest.
- *
- * Increasing the TTL could have performance implications, so you should not change it without
- * proper justification.
- *
- * @param {number} limit The number of digest iterations.
- */
-
-
-/**
- * @ngdoc object
- * @name ng.$rootScope
- * @description
- *
- * Every application has a single root {@link ng.$rootScope.Scope scope}.
- * All other scopes are descendant scopes of the root scope. Scopes provide separation
- * between the model and the view, via a mechanism for watching the model for changes.
- * They also provide an event emission/broadcast and subscription facility. See the
- * {@link guide/scope developer guide on scopes}.
- */
-function $RootScopeProvider(){
-  var TTL = 10;
-  var $rootScopeMinErr = minErr('$rootScope');
-  var lastDirtyWatch = null;
-
-  this.digestTtl = function(value) {
-    if (arguments.length) {
-      TTL = value;
-    }
-    return TTL;
-  };
-
-  this.$get = ['$injector', '$exceptionHandler', '$parse', '$browser',
-      function( $injector,   $exceptionHandler,   $parse,   $browser) {
-
-    /**
-     * @ngdoc function
-     * @name ng.$rootScope.Scope
-     *
-     * @description
-     * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the
-     * {@link AUTO.$injector $injector}. Child scopes are created using the
-     * {@link ng.$rootScope.Scope#methods_$new $new()} method. (Most scopes are created automatically when
-     * compiled HTML template is executed.)
-     *
-     * Here is a simple scope snippet to show how you can interact with the scope.
-     * <pre>
-     * <file src="./test/ng/rootScopeSpec.js" tag="docs1" />
-     * </pre>
-     *
-     * # Inheritance
-     * A scope can inherit from a parent scope, as in this example:
-     * <pre>
-         var parent = $rootScope;
-         var child = parent.$new();
-
-         parent.salutation = "Hello";
-         child.name = "World";
-         expect(child.salutation).toEqual('Hello');
-
-         child.salutation = "Welcome";
-         expect(child.salutation).toEqual('Welcome');
-         expect(parent.salutation).toEqual('Hello');
-     * </pre>
-     *
-     *
-     * @param {Object.<string, function()>=} providers Map of service factory which need to be
-     *                                       provided for the current scope. Defaults to {@link ng}.
-     * @param {Object.<string, *>=} instanceCache Provides pre-instantiated services which should
-     *                              append/override services provided by `providers`. This is handy
-     *                              when unit-testing and having the need to override a default
-     *                              service.
-     * @returns {Object} Newly created scope.
-     *
-     */
-    function Scope() {
-      this.$id = nextUid();
-      this.$$phase = this.$parent = this.$$watchers =
-                     this.$$nextSibling = this.$$prevSibling =
-                     this.$$childHead = this.$$childTail = null;
-      this['this'] = this.$root =  this;
-      this.$$destroyed = false;
-      this.$$asyncQueue = [];
-      this.$$postDigestQueue = [];
-      this.$$listeners = {};
-      this.$$isolateBindings = {};
-    }
-
-    /**
-     * @ngdoc property
-     * @name ng.$rootScope.Scope#$id
-     * @propertyOf ng.$rootScope.Scope
-     * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for
-     *   debugging.
-     */
-
-
-    Scope.prototype = {
-      constructor: Scope,
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$new
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * Creates a new child {@link ng.$rootScope.Scope scope}.
-       *
-       * The parent scope will propagate the {@link ng.$rootScope.Scope#methods_$digest $digest()} and
-       * {@link ng.$rootScope.Scope#methods_$digest $digest()} events. The scope can be removed from the
-       * scope hierarchy using {@link ng.$rootScope.Scope#methods_$destroy $destroy()}.
-       *
-       * {@link ng.$rootScope.Scope#methods_$destroy $destroy()} must be called on a scope when it is
-       * desired for the scope and its child scopes to be permanently detached from the parent and
-       * thus stop participating in model change detection and listener notification by invoking.
-       *
-       * @param {boolean} isolate If true, then the scope does not prototypically inherit from the
-       *         parent scope. The scope is isolated, as it can not see parent scope properties.
-       *         When creating widgets, it is useful for the widget to not accidentally read parent
-       *         state.
-       *
-       * @returns {Object} The newly created child scope.
-       *
-       */
-      $new: function(isolate) {
-        var ChildScope,
-            child;
-
-        if (isolate) {
-          child = new Scope();
-          child.$root = this.$root;
-          // ensure that there is just one async queue per $rootScope and its children
-          child.$$asyncQueue = this.$$asyncQueue;
-          child.$$postDigestQueue = this.$$postDigestQueue;
-        } else {
-          ChildScope = function() {}; // should be anonymous; This is so that when the minifier munges
-            // the name it does not become random set of chars. This will then show up as class
-            // name in the debugger.
-          ChildScope.prototype = this;
-          child = new ChildScope();
-          child.$id = nextUid();
-        }
-        child['this'] = child;
-        child.$$listeners = {};
-        child.$parent = this;
-        child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null;
-        child.$$prevSibling = this.$$childTail;
-        if (this.$$childHead) {
-          this.$$childTail.$$nextSibling = child;
-          this.$$childTail = child;
-        } else {
-          this.$$childHead = this.$$childTail = child;
-        }
-        return child;
-      },
-
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$watch
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * Registers a `listener` callback to be executed whenever the `watchExpression` changes.
-       *
-       * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#methods_$digest
-       *   $digest()} and should return the value that will be watched. (Since
-       *   {@link ng.$rootScope.Scope#methods_$digest $digest()} reruns when it detects changes the
-       *   `watchExpression` can execute multiple times per
-       *   {@link ng.$rootScope.Scope#methods_$digest $digest()} and should be idempotent.)
-       * - The `listener` is called only when the value from the current `watchExpression` and the
-       *   previous call to `watchExpression` are not equal (with the exception of the initial run,
-       *   see below). The inequality is determined according to
-       *   {@link angular.equals} function. To save the value of the object for later comparison,
-       *   the {@link angular.copy} function is used. It also means that watching complex options
-       *   will have adverse memory and performance implications.
-       * - The watch `listener` may change the model, which may trigger other `listener`s to fire.
-       *   This is achieved by rerunning the watchers until no changes are detected. The rerun
-       *   iteration limit is 10 to prevent an infinite loop deadlock.
-       *
-       *
-       * If you want to be notified whenever {@link ng.$rootScope.Scope#methods_$digest $digest} is called,
-       * you can register a `watchExpression` function with no `listener`. (Since `watchExpression`
-       * can execute multiple times per {@link ng.$rootScope.Scope#methods_$digest $digest} cycle when a
-       * change is detected, be prepared for multiple calls to your listener.)
-       *
-       * After a watcher is registered with the scope, the `listener` fn is called asynchronously
-       * (via {@link ng.$rootScope.Scope#methods_$evalAsync $evalAsync}) to initialize the
-       * watcher. In rare cases, this is undesirable because the listener is called when the result
-       * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you
-       * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
-       * listener was called due to initialization.
-       *
-       * The example below contains an illustration of using a function as your $watch listener
-       *
-       *
-       * # Example
-       * <pre>
-           // let's assume that scope was dependency injected as the $rootScope
-           var scope = $rootScope;
-           scope.name = 'misko';
-           scope.counter = 0;
-
-           expect(scope.counter).toEqual(0);
-           scope.$watch('name', function(newValue, oldValue) {
-             scope.counter = scope.counter + 1;
-           });
-           expect(scope.counter).toEqual(0);
-
-           scope.$digest();
-           // no variable change
-           expect(scope.counter).toEqual(0);
-
-           scope.name = 'adam';
-           scope.$digest();
-           expect(scope.counter).toEqual(1);
-
-
-
-           // Using a listener function
-           var food;
-           scope.foodCounter = 0;
-           expect(scope.foodCounter).toEqual(0);
-           scope.$watch(
-             // This is the listener function
-             function() { return food; },
-             // This is the change handler
-             function(newValue, oldValue) {
-               if ( newValue !== oldValue ) {
-                 // Only increment the counter if the value changed
-                 scope.foodCounter = scope.foodCounter + 1;
-               }
-             }
-           );
-           // No digest has been run so the counter will be zero
-           expect(scope.foodCounter).toEqual(0);
-
-           // Run the digest but since food has not changed cout will still be zero
-           scope.$digest();
-           expect(scope.foodCounter).toEqual(0);
-
-           // Update food and run digest.  Now the counter will increment
-           food = 'cheeseburger';
-           scope.$digest();
-           expect(scope.foodCounter).toEqual(1);
-
-       * </pre>
-       *
-       *
-       *
-       * @param {(function()|string)} watchExpression Expression that is evaluated on each
-       *    {@link ng.$rootScope.Scope#methods_$digest $digest} cycle. A change in the return value triggers
-       *    a call to the `listener`.
-       *
-       *    - `string`: Evaluated as {@link guide/expression expression}
-       *    - `function(scope)`: called with current `scope` as a parameter.
-       * @param {(function()|string)=} listener Callback called whenever the return value of
-       *   the `watchExpression` changes.
-       *
-       *    - `string`: Evaluated as {@link guide/expression expression}
-       *    - `function(newValue, oldValue, scope)`: called with current and previous values as
-       *      parameters.
-       *
-       * @param {boolean=} objectEquality Compare object for equality rather than for reference.
-       * @returns {function()} Returns a deregistration function for this listener.
-       */
-      $watch: function(watchExp, listener, objectEquality) {
-        var scope = this,
-            get = compileToFn(watchExp, 'watch'),
-            array = scope.$$watchers,
-            watcher = {
-              fn: listener,
-              last: initWatchVal,
-              get: get,
-              exp: watchExp,
-              eq: !!objectEquality
-            };
-
-        lastDirtyWatch = null;
-
-        // in the case user pass string, we need to compile it, do we really need this ?
-        if (!isFunction(listener)) {
-          var listenFn = compileToFn(listener || noop, 'listener');
-          watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};
-        }
-
-        if (typeof watchExp == 'string' && get.constant) {
-          var originalFn = watcher.fn;
-          watcher.fn = function(newVal, oldVal, scope) {
-            originalFn.call(this, newVal, oldVal, scope);
-            arrayRemove(array, watcher);
-          };
-        }
-
-        if (!array) {
-          array = scope.$$watchers = [];
-        }
-        // we use unshift since we use a while loop in $digest for speed.
-        // the while loop reads in reverse order.
-        array.unshift(watcher);
-
-        return function() {
-          arrayRemove(array, watcher);
-        };
-      },
-
-
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$watchCollection
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * Shallow watches the properties of an object and fires whenever any of the properties change
-       * (for arrays, this implies watching the array items; for object maps, this implies watching
-       * the properties). If a change is detected, the `listener` callback is fired.
-       *
-       * - The `obj` collection is observed via standard $watch operation and is examined on every
-       *   call to $digest() to see if any items have been added, removed, or moved.
-       * - The `listener` is called whenever anything within the `obj` has changed. Examples include
-       *   adding, removing, and moving items belonging to an object or array.
-       *
-       *
-       * # Example
-       * <pre>
-          $scope.names = ['igor', 'matias', 'misko', 'james'];
-          $scope.dataCount = 4;
-
-          $scope.$watchCollection('names', function(newNames, oldNames) {
-            $scope.dataCount = newNames.length;
-          });
-
-          expect($scope.dataCount).toEqual(4);
-          $scope.$digest();
-
-          //still at 4 ... no changes
-          expect($scope.dataCount).toEqual(4);
-
-          $scope.names.pop();
-          $scope.$digest();
-
-          //now there's been a change
-          expect($scope.dataCount).toEqual(3);
-       * </pre>
-       *
-       *
-       * @param {string|Function(scope)} obj Evaluated as {@link guide/expression expression}. The
-       *    expression value should evaluate to an object or an array which is observed on each
-       *    {@link ng.$rootScope.Scope#methods_$digest $digest} cycle. Any shallow change within the
-       *    collection will trigger a call to the `listener`.
-       *
-       * @param {function(newCollection, oldCollection, scope)} listener a callback function that is
-       *    fired with both the `newCollection` and `oldCollection` as parameters.
-       *    The `newCollection` object is the newly modified data obtained from the `obj` expression
-       *    and the `oldCollection` object is a copy of the former collection data.
-       *    The `scope` refers to the current scope.
-       *
-       * @returns {function()} Returns a de-registration function for this listener. When the
-       *    de-registration function is executed, the internal watch operation is terminated.
-       */
-      $watchCollection: function(obj, listener) {
-        var self = this;
-        var oldValue;
-        var newValue;
-        var changeDetected = 0;
-        var objGetter = $parse(obj);
-        var internalArray = [];
-        var internalObject = {};
-        var oldLength = 0;
-
-        function $watchCollectionWatch() {
-          newValue = objGetter(self);
-          var newLength, key;
-
-          if (!isObject(newValue)) {
-            if (oldValue !== newValue) {
-              oldValue = newValue;
-              changeDetected++;
-            }
-          } else if (isArrayLike(newValue)) {
-            if (oldValue !== internalArray) {
-              // we are transitioning from something which was not an array into array.
-              oldValue = internalArray;
-              oldLength = oldValue.length = 0;
-              changeDetected++;
-            }
-
-            newLength = newValue.length;
-
-            if (oldLength !== newLength) {
-              // if lengths do not match we need to trigger change notification
-              changeDetected++;
-              oldValue.length = oldLength = newLength;
-            }
-            // copy the items to oldValue and look for changes.
-            for (var i = 0; i < newLength; i++) {
-              if (oldValue[i] !== newValue[i]) {
-                changeDetected++;
-                oldValue[i] = newValue[i];
-              }
-            }
-          } else {
-            if (oldValue !== internalObject) {
-              // we are transitioning from something which was not an object into object.
-              oldValue = internalObject = {};
-              oldLength = 0;
-              changeDetected++;
-            }
-            // copy the items to oldValue and look for changes.
-            newLength = 0;
-            for (key in newValue) {
-              if (newValue.hasOwnProperty(key)) {
-                newLength++;
-                if (oldValue.hasOwnProperty(key)) {
-                  if (oldValue[key] !== newValue[key]) {
-                    changeDetected++;
-                    oldValue[key] = newValue[key];
-                  }
-                } else {
-                  oldLength++;
-                  oldValue[key] = newValue[key];
-                  changeDetected++;
-                }
-              }
-            }
-            if (oldLength > newLength) {
-              // we used to have more keys, need to find them and destroy them.
-              changeDetected++;
-              for(key in oldValue) {
-                if (oldValue.hasOwnProperty(key) && !newValue.hasOwnProperty(key)) {
-                  oldLength--;
-                  delete oldValue[key];
-                }
-              }
-            }
-          }
-          return changeDetected;
-        }
-
-        function $watchCollectionAction() {
-          listener(newValue, oldValue, self);
-        }
-
-        return this.$watch($watchCollectionWatch, $watchCollectionAction);
-      },
-
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$digest
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * Processes all of the {@link ng.$rootScope.Scope#methods_$watch watchers} of the current scope and
-       * its children. Because a {@link ng.$rootScope.Scope#methods_$watch watcher}'s listener can change
-       * the model, the `$digest()` keeps calling the {@link ng.$rootScope.Scope#methods_$watch watchers}
-       * until no more listeners are firing. This means that it is possible to get into an infinite
-       * loop. This function will throw `'Maximum iteration limit exceeded.'` if the number of
-       * iterations exceeds 10.
-       *
-       * Usually, you don't call `$digest()` directly in
-       * {@link ng.directive:ngController controllers} or in
-       * {@link ng.$compileProvider#methods_directive directives}.
-       * Instead, you should call {@link ng.$rootScope.Scope#methods_$apply $apply()} (typically from within
-       * a {@link ng.$compileProvider#methods_directive directives}), which will force a `$digest()`.
-       *
-       * If you want to be notified whenever `$digest()` is called,
-       * you can register a `watchExpression` function with
-       * {@link ng.$rootScope.Scope#methods_$watch $watch()} with no `listener`.
-       *
-       * In unit tests, you may need to call `$digest()` to simulate the scope life cycle.
-       *
-       * # Example
-       * <pre>
-           var scope = ...;
-           scope.name = 'misko';
-           scope.counter = 0;
-
-           expect(scope.counter).toEqual(0);
-           scope.$watch('name', function(newValue, oldValue) {
-             scope.counter = scope.counter + 1;
-           });
-           expect(scope.counter).toEqual(0);
-
-           scope.$digest();
-           // no variable change
-           expect(scope.counter).toEqual(0);
-
-           scope.name = 'adam';
-           scope.$digest();
-           expect(scope.counter).toEqual(1);
-       * </pre>
-       *
-       */
-      $digest: function() {
-        var watch, value, last,
-            watchers,
-            asyncQueue = this.$$asyncQueue,
-            postDigestQueue = this.$$postDigestQueue,
-            length,
-            dirty, ttl = TTL,
-            next, current, target = this,
-            watchLog = [],
-            logIdx, logMsg, asyncTask;
-
-        beginPhase('$digest');
-
-        lastDirtyWatch = null;
-
-        do { // "while dirty" loop
-          dirty = false;
-          current = target;
-
-          while(asyncQueue.length) {
-            try {
-              asyncTask = asyncQueue.shift();
-              asyncTask.scope.$eval(asyncTask.expression);
-            } catch (e) {
-              clearPhase();
-              $exceptionHandler(e);
-            }
-            lastDirtyWatch = null;
-          }
-
-          traverseScopesLoop:
-          do { // "traverse the scopes" loop
-            if ((watchers = current.$$watchers)) {
-              // process our watches
-              length = watchers.length;
-              while (length--) {
-                try {
-                  watch = watchers[length];
-                  // Most common watches are on primitives, in which case we can short
-                  // circuit it with === operator, only when === fails do we use .equals
-                  if (watch) {
-                    if ((value = watch.get(current)) !== (last = watch.last) &&
-                        !(watch.eq
-                            ? equals(value, last)
-                            : (typeof value == 'number' && typeof last == 'number'
-                               && isNaN(value) && isNaN(last)))) {
-                      dirty = true;
-                      lastDirtyWatch = watch;
-                      watch.last = watch.eq ? copy(value) : value;
-                      watch.fn(value, ((last === initWatchVal) ? value : last), current);
-                      if (ttl < 5) {
-                        logIdx = 4 - ttl;
-                        if (!watchLog[logIdx]) watchLog[logIdx] = [];
-                        logMsg = (isFunction(watch.exp))
-                            ? 'fn: ' + (watch.exp.name || watch.exp.toString())
-                            : watch.exp;
-                        logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last);
-                        watchLog[logIdx].push(logMsg);
-                      }
-                    } else if (watch === lastDirtyWatch) {
-                      // If the most recently dirty watcher is now clean, short circuit since the remaining watchers
-                      // have already been tested.
-                      dirty = false;
-                      break traverseScopesLoop;
-                    }
-                  }
-                } catch (e) {
-                  clearPhase();
-                  $exceptionHandler(e);
-                }
-              }
-            }
-
-            // Insanity Warning: scope depth-first traversal
-            // yes, this code is a bit crazy, but it works and we have tests to prove it!
-            // this piece should be kept in sync with the traversal in $broadcast
-            if (!(next = (current.$$childHead ||
-                (current !== target && current.$$nextSibling)))) {
-              while(current !== target && !(next = current.$$nextSibling)) {
-                current = current.$parent;
-              }
-            }
-          } while ((current = next));
-
-          // `break traverseScopesLoop;` takes us to here
-
-          if(dirty && !(ttl--)) {
-            clearPhase();
-            throw $rootScopeMinErr('infdig',
-                '{0} $digest() iterations reached. Aborting!\n' +
-                'Watchers fired in the last 5 iterations: {1}',
-                TTL, toJson(watchLog));
-          }
-
-        } while (dirty || asyncQueue.length);
-
-        clearPhase();
-
-        while(postDigestQueue.length) {
-          try {
-            postDigestQueue.shift()();
-          } catch (e) {
-            $exceptionHandler(e);
-          }
-        }
-      },
-
-
-      /**
-       * @ngdoc event
-       * @name ng.$rootScope.Scope#$destroy
-       * @eventOf ng.$rootScope.Scope
-       * @eventType broadcast on scope being destroyed
-       *
-       * @description
-       * Broadcasted when a scope and its children are being destroyed.
-       *
-       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
-       * clean up DOM bindings before an element is removed from the DOM.
-       */
-
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$destroy
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * Removes the current scope (and all of its children) from the parent scope. Removal implies
-       * that calls to {@link ng.$rootScope.Scope#methods_$digest $digest()} will no longer
-       * propagate to the current scope and its children. Removal also implies that the current
-       * scope is eligible for garbage collection.
-       *
-       * The `$destroy()` is usually used by directives such as
-       * {@link ng.directive:ngRepeat ngRepeat} for managing the
-       * unrolling of the loop.
-       *
-       * Just before a scope is destroyed, a `$destroy` event is broadcasted on this scope.
-       * Application code can register a `$destroy` event handler that will give it a chance to
-       * perform any necessary cleanup.
-       *
-       * Note that, in AngularJS, there is also a `$destroy` jQuery event, which can be used to
-       * clean up DOM bindings before an element is removed from the DOM.
-       */
-      $destroy: function() {
-        // we can't destroy the root scope or a scope that has been already destroyed
-        if (this.$$destroyed) return;
-        var parent = this.$parent;
-
-        this.$broadcast('$destroy');
-        this.$$destroyed = true;
-        if (this === $rootScope) return;
-
-        if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling;
-        if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling;
-        if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling;
-        if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling;
-
-        // This is bogus code that works around Chrome's GC leak
-        // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451
-        this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead =
-            this.$$childTail = null;
-      },
-
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$eval
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * Executes the `expression` on the current scope and returns the result. Any exceptions in
-       * the expression are propagated (uncaught). This is useful when evaluating Angular
-       * expressions.
-       *
-       * # Example
-       * <pre>
-           var scope = ng.$rootScope.Scope();
-           scope.a = 1;
-           scope.b = 2;
-
-           expect(scope.$eval('a+b')).toEqual(3);
-           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
-       * </pre>
-       *
-       * @param {(string|function())=} expression An angular expression to be executed.
-       *
-       *    - `string`: execute using the rules as defined in  {@link guide/expression expression}.
-       *    - `function(scope)`: execute the function with the current `scope` parameter.
-       *
-       * @param {(object)=} locals Local variables object, useful for overriding values in scope.
-       * @returns {*} The result of evaluating the expression.
-       */
-      $eval: function(expr, locals) {
-        return $parse(expr)(this, locals);
-      },
-
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$evalAsync
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * Executes the expression on the current scope at a later point in time.
-       *
-       * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only
-       * that:
-       *
-       *   - it will execute after the function that scheduled the evaluation (preferably before DOM
-       *     rendering).
-       *   - at least one {@link ng.$rootScope.Scope#methods_$digest $digest cycle} will be performed after
-       *     `expression` execution.
-       *
-       * Any exceptions from the execution of the expression are forwarded to the
-       * {@link ng.$exceptionHandler $exceptionHandler} service.
-       *
-       * __Note:__ if this function is called outside of a `$digest` cycle, a new `$digest` cycle
-       * will be scheduled. However, it is encouraged to always call code that changes the model
-       * from within an `$apply` call. That includes code evaluated via `$evalAsync`.
-       *
-       * @param {(string|function())=} expression An angular expression to be executed.
-       *
-       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.
-       *    - `function(scope)`: execute the function with the current `scope` parameter.
-       *
-       */
-      $evalAsync: function(expr) {
-        // if we are outside of an $digest loop and this is the first time we are scheduling async
-        // task also schedule async auto-flush
-        if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) {
-          $browser.defer(function() {
-            if ($rootScope.$$asyncQueue.length) {
-              $rootScope.$digest();
-            }
-          });
-        }
-
-        this.$$asyncQueue.push({scope: this, expression: expr});
-      },
-
-      $$postDigest : function(fn) {
-        this.$$postDigestQueue.push(fn);
-      },
-
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$apply
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * `$apply()` is used to execute an expression in angular from outside of the angular
-       * framework. (For example from browser DOM events, setTimeout, XHR or third party libraries).
-       * Because we are calling into the angular framework we need to perform proper scope life
-       * cycle of {@link ng.$exceptionHandler exception handling},
-       * {@link ng.$rootScope.Scope#methods_$digest executing watches}.
-       *
-       * ## Life cycle
-       *
-       * # Pseudo-Code of `$apply()`
-       * <pre>
-           function $apply(expr) {
-             try {
-               return $eval(expr);
-             } catch (e) {
-               $exceptionHandler(e);
-             } finally {
-               $root.$digest();
-             }
-           }
-       * </pre>
-       *
-       *
-       * Scope's `$apply()` method transitions through the following stages:
-       *
-       * 1. The {@link guide/expression expression} is executed using the
-       *    {@link ng.$rootScope.Scope#methods_$eval $eval()} method.
-       * 2. Any exceptions from the execution of the expression are forwarded to the
-       *    {@link ng.$exceptionHandler $exceptionHandler} service.
-       * 3. The {@link ng.$rootScope.Scope#methods_$watch watch} listeners are fired immediately after the
-       *    expression was executed using the {@link ng.$rootScope.Scope#methods_$digest $digest()} method.
-       *
-       *
-       * @param {(string|function())=} exp An angular expression to be executed.
-       *
-       *    - `string`: execute using the rules as defined in {@link guide/expression expression}.
-       *    - `function(scope)`: execute the function with current `scope` parameter.
-       *
-       * @returns {*} The result of evaluating the expression.
-       */
-      $apply: function(expr) {
-        try {
-          beginPhase('$apply');
-          return this.$eval(expr);
-        } catch (e) {
-          $exceptionHandler(e);
-        } finally {
-          clearPhase();
-          try {
-            $rootScope.$digest();
-          } catch (e) {
-            $exceptionHandler(e);
-            throw e;
-          }
-        }
-      },
-
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$on
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * Listens on events of a given type. See {@link ng.$rootScope.Scope#methods_$emit $emit} for
-       * discussion of event life cycle.
-       *
-       * The event listener function format is: `function(event, args...)`. The `event` object
-       * passed into the listener has the following attributes:
-       *
-       *   - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
-       *     `$broadcast`-ed.
-       *   - `currentScope` - `{Scope}`: the current scope which is handling the event.
-       *   - `name` - `{string}`: name of the event.
-       *   - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
-       *     further event propagation (available only for events that were `$emit`-ed).
-       *   - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag
-       *     to true.
-       *   - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called.
-       *
-       * @param {string} name Event name to listen on.
-       * @param {function(event, args...)} listener Function to call when the event is emitted.
-       * @returns {function()} Returns a deregistration function for this listener.
-       */
-      $on: function(name, listener) {
-        var namedListeners = this.$$listeners[name];
-        if (!namedListeners) {
-          this.$$listeners[name] = namedListeners = [];
-        }
-        namedListeners.push(listener);
-
-        return function() {
-          namedListeners[indexOf(namedListeners, listener)] = null;
-        };
-      },
-
-
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$emit
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * Dispatches an event `name` upwards through the scope hierarchy notifying the
-       * registered {@link ng.$rootScope.Scope#methods_$on} listeners.
-       *
-       * The event life cycle starts at the scope on which `$emit` was called. All
-       * {@link ng.$rootScope.Scope#methods_$on listeners} listening for `name` event on this scope get
-       * notified. Afterwards, the event traverses upwards toward the root scope and calls all
-       * registered listeners along the way. The event will stop propagating if one of the listeners
-       * cancels it.
-       *
-       * Any exception emitted from the {@link ng.$rootScope.Scope#methods_$on listeners} will be passed
-       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
-       *
-       * @param {string} name Event name to emit.
-       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.
-       * @return {Object} Event object (see {@link ng.$rootScope.Scope#methods_$on}).
-       */
-      $emit: function(name, args) {
-        var empty = [],
-            namedListeners,
-            scope = this,
-            stopPropagation = false,
-            event = {
-              name: name,
-              targetScope: scope,
-              stopPropagation: function() {stopPropagation = true;},
-              preventDefault: function() {
-                event.defaultPrevented = true;
-              },
-              defaultPrevented: false
-            },
-            listenerArgs = concat([event], arguments, 1),
-            i, length;
-
-        do {
-          namedListeners = scope.$$listeners[name] || empty;
-          event.currentScope = scope;
-          for (i=0, length=namedListeners.length; i<length; i++) {
-
-            // if listeners were deregistered, defragment the array
-            if (!namedListeners[i]) {
-              namedListeners.splice(i, 1);
-              i--;
-              length--;
-              continue;
-            }
-            try {
-              //allow all listeners attached to the current scope to run
-              namedListeners[i].apply(null, listenerArgs);
-            } catch (e) {
-              $exceptionHandler(e);
-            }
-          }
-          //if any listener on the current scope stops propagation, prevent bubbling
-          if (stopPropagation) return event;
-          //traverse upwards
-          scope = scope.$parent;
-        } while (scope);
-
-        return event;
-      },
-
-
-      /**
-       * @ngdoc function
-       * @name ng.$rootScope.Scope#$broadcast
-       * @methodOf ng.$rootScope.Scope
-       * @function
-       *
-       * @description
-       * Dispatches an event `name` downwards to all child scopes (and their children) notifying the
-       * registered {@link ng.$rootScope.Scope#methods_$on} listeners.
-       *
-       * The event life cycle starts at the scope on which `$broadcast` was called. All
-       * {@link ng.$rootScope.Scope#methods_$on listeners} listening for `name` event on this scope get
-       * notified. Afterwards, the event propagates to all direct and indirect scopes of the current
-       * scope and calls all registered listeners along the way. The event cannot be canceled.
-       *
-       * Any exception emitted from the {@link ng.$rootScope.Scope#methods_$on listeners} will be passed
-       * onto the {@link ng.$exceptionHandler $exceptionHandler} service.
-       *
-       * @param {string} name Event name to broadcast.
-       * @param {...*} args Optional set of arguments which will be passed onto the event listeners.
-       * @return {Object} Event object, see {@link ng.$rootScope.Scope#methods_$on}
-       */
-      $broadcast: function(name, args) {
-        var target = this,
-            current = target,
-            next = target,
-            event = {
-              name: name,
-              targetScope: target,
-              preventDefault: function() {
-                event.defaultPrevented = true;
-              },
-              defaultPrevented: false
-            },
-            listenerArgs = concat([event], arguments, 1),
-            listeners, i, length;
-
-        //down while you can, then up and next sibling or up and next sibling until back at root
-        do {
-          current = next;
-          event.currentScope = current;
-          listeners = current.$$listeners[name] || [];
-          for (i=0, length = listeners.length; i<length; i++) {
-            // if listeners were deregistered, defragment the array
-            if (!listeners[i]) {
-              listeners.splice(i, 1);
-              i--;
-              length--;
-              continue;
-            }
-
-            try {
-              listeners[i].apply(null, listenerArgs);
-            } catch(e) {
-              $exceptionHandler(e);
-            }
-          }
-
-          // Insanity Warning: scope depth-first traversal
-          // yes, this code is a bit crazy, but it works and we have tests to prove it!
-          // this piece should be kept in sync with the traversal in $digest
-          if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) {
-            while(current !== target && !(next = current.$$nextSibling)) {
-              current = current.$parent;
-            }
-          }
-        } while ((current = next));
-
-        return event;
-      }
-    };
-
-    var $rootScope = new Scope();
-
-    return $rootScope;
-
-
-    function beginPhase(phase) {
-      if ($rootScope.$$phase) {
-        throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase);
-      }
-
-      $rootScope.$$phase = phase;
-    }
-
-    function clearPhase() {
-      $rootScope.$$phase = null;
-    }
-
-    function compileToFn(exp, name) {
-      var fn = $parse(exp);
-      assertArgFn(fn, name);
-      return fn;
-    }
-
-    /**
-     * function used as an initial value for watchers.
-     * because it's unique we can easily tell it apart from other values
-     */
-    function initWatchVal() {}
-  }];
-}
-
-/**
- * @description
- * Private service to sanitize uris for links and images. Used by $compile and $sanitize.
- */
-function $$SanitizeUriProvider() {
-  var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
-    imgSrcSanitizationWhitelist = /^\s*(https?|ftp|file):|data:image\//;
-
-  /**
-   * @description
-   * Retrieves or overrides the default regular expression that is used for whitelisting of safe
-   * urls during a[href] sanitization.
-   *
-   * The sanitization is a security measure aimed at prevent XSS attacks via html links.
-   *
-   * Any url about to be assigned to a[href] via data-binding is first normalized and turned into
-   * an absolute url. Afterwards, the url is matched against the `aHrefSanitizationWhitelist`
-   * regular expression. If a match is found, the original url is written into the dom. Otherwise,
-   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
-   *
-   * @param {RegExp=} regexp New regexp to whitelist urls with.
-   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
-   *    chaining otherwise.
-   */
-  this.aHrefSanitizationWhitelist = function(regexp) {
-    if (isDefined(regexp)) {
-      aHrefSanitizationWhitelist = regexp;
-      return this;
-    }
-    return aHrefSanitizationWhitelist;
-  };
-
-
-  /**
-   * @description
-   * Retrieves or overrides the default regular expression that is used for whitelisting of safe
-   * urls during img[src] sanitization.
-   *
-   * The sanitization is a security measure aimed at prevent XSS attacks via html links.
-   *
-   * Any url about to be assigned to img[src] via data-binding is first normalized and turned into
-   * an absolute url. Afterwards, the url is matched against the `imgSrcSanitizationWhitelist`
-   * regular expression. If a match is found, the original url is written into the dom. Otherwise,
-   * the absolute url is prefixed with `'unsafe:'` string and only then is it written into the DOM.
-   *
-   * @param {RegExp=} regexp New regexp to whitelist urls with.
-   * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for
-   *    chaining otherwise.
-   */
-  this.imgSrcSanitizationWhitelist = function(regexp) {
-    if (isDefined(regexp)) {
-      imgSrcSanitizationWhitelist = regexp;
-      return this;
-    }
-    return imgSrcSanitizationWhitelist;
-  };
-
-  this.$get = function() {
-    return function sanitizeUri(uri, isImage) {
-      var regex = isImage ? imgSrcSanitizationWhitelist : aHrefSanitizationWhitelist;
-      var normalizedVal;
-      // NOTE: urlResolve() doesn't support IE < 8 so we don't sanitize for that case.
-      if (!msie || msie >= 8 ) {
-        normalizedVal = urlResolve(uri).href;
-        if (normalizedVal !== '' && !normalizedVal.match(regex)) {
-          return 'unsafe:'+normalizedVal;
-        }
-      }
-      return uri;
-    };
-  };
-}
-
-var $sceMinErr = minErr('$sce');
-
-var SCE_CONTEXTS = {
-  HTML: 'html',
-  CSS: 'css',
-  URL: 'url',
-  // RESOURCE_URL is a subtype of URL used in contexts where a privileged resource is sourced from a
-  // url.  (e.g. ng-include, script src, templateUrl)
-  RESOURCE_URL: 'resourceUrl',
-  JS: 'js'
-};
-
-// Helper functions follow.
-
-// Copied from:
-// http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962
-// Prereq: s is a string.
-function escapeForRegexp(s) {
-  return s.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, '\\$1').
-           replace(/\x08/g, '\\x08');
-}
-
-
-function adjustMatcher(matcher) {
-  if (matcher === 'self') {
-    return matcher;
-  } else if (isString(matcher)) {
-    // Strings match exactly except for 2 wildcards - '*' and '**'.
-    // '*' matches any character except those from the set ':/.?&'.
-    // '**' matches any character (like .* in a RegExp).
-    // More than 2 *'s raises an error as it's ill defined.
-    if (matcher.indexOf('***') > -1) {
-      throw $sceMinErr('iwcard',
-          'Illegal sequence *** in string matcher.  String: {0}', matcher);
-    }
-    matcher = escapeForRegexp(matcher).
-                  replace('\\*\\*', '.*').
-                  replace('\\*', '[^:/.?&;]*');
-    return new RegExp('^' + matcher + '$');
-  } else if (isRegExp(matcher)) {
-    // The only other type of matcher allowed is a Regexp.
-    // Match entire URL / disallow partial matches.
-    // Flags are reset (i.e. no global, ignoreCase or multiline)
-    return new RegExp('^' + matcher.source + '$');
-  } else {
-    throw $sceMinErr('imatcher',
-        'Matchers may only be "self", string patterns or RegExp objects');
-  }
-}
-
-
-function adjustMatchers(matchers) {
-  var adjustedMatchers = [];
-  if (isDefined(matchers)) {
-    forEach(matchers, function(matcher) {
-      adjustedMatchers.push(adjustMatcher(matcher));
-    });
-  }
-  return adjustedMatchers;
-}
-
-
-/**
- * @ngdoc service
- * @name ng.$sceDelegate
- * @function
- *
- * @description
- *
- * `$sceDelegate` is a service that is used by the `$sce` service to provide {@link ng.$sce Strict
- * Contextual Escaping (SCE)} services to AngularJS.
- *
- * Typically, you would configure or override the {@link ng.$sceDelegate $sceDelegate} instead of
- * the `$sce` service to customize the way Strict Contextual Escaping works in AngularJS.  This is
- * because, while the `$sce` provides numerous shorthand methods, etc., you really only need to
- * override 3 core functions (`trustAs`, `getTrusted` and `valueOf`) to replace the way things
- * work because `$sce` delegates to `$sceDelegate` for these operations.
- *
- * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} to configure this service.
- *
- * The default instance of `$sceDelegate` should work out of the box with little pain.  While you
- * can override it completely to change the behavior of `$sce`, the common case would
- * involve configuring the {@link ng.$sceDelegateProvider $sceDelegateProvider} instead by setting
- * your own whitelists and blacklists for trusting URLs used for loading AngularJS resources such as
- * templates.  Refer {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist
- * $sceDelegateProvider.resourceUrlWhitelist} and {@link
- * ng.$sceDelegateProvider#methods_resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
- */
-
-/**
- * @ngdoc object
- * @name ng.$sceDelegateProvider
- * @description
- *
- * The `$sceDelegateProvider` provider allows developers to configure the {@link ng.$sceDelegate
- * $sceDelegate} service.  This allows one to get/set the whitelists and blacklists used to ensure
- * that the URLs used for sourcing Angular templates are safe.  Refer {@link
- * ng.$sceDelegateProvider#methods_resourceUrlWhitelist $sceDelegateProvider.resourceUrlWhitelist} and
- * {@link ng.$sceDelegateProvider#methods_resourceUrlBlacklist $sceDelegateProvider.resourceUrlBlacklist}
- *
- * For the general details about this service in Angular, read the main page for {@link ng.$sce
- * Strict Contextual Escaping (SCE)}.
- *
- * **Example**:  Consider the following case. <a name="example"></a>
- *
- * - your app is hosted at url `http://myapp.example.com/`
- * - but some of your templates are hosted on other domains you control such as
- *   `http://srv01.assets.example.com/`,  `http://srv02.assets.example.com/`, etc.
- * - and you have an open redirect at `http://myapp.example.com/clickThru?...`.
- *
- * Here is what a secure configuration for this scenario might look like:
- *
- * <pre class="prettyprint">
- *    angular.module('myApp', []).config(function($sceDelegateProvider) {
- *      $sceDelegateProvider.resourceUrlWhitelist([
- *        // Allow same origin resource loads.
- *        'self',
- *        // Allow loading from our assets domain.  Notice the difference between * and **.
- *        'http://srv*.assets.example.com/**']);
- *
- *      // The blacklist overrides the whitelist so the open redirect here is blocked.
- *      $sceDelegateProvider.resourceUrlBlacklist([
- *        'http://myapp.example.com/clickThru**']);
- *      });
- * </pre>
- */
-
-function $SceDelegateProvider() {
-  this.SCE_CONTEXTS = SCE_CONTEXTS;
-
-  // Resource URLs can also be trusted by policy.
-  var resourceUrlWhitelist = ['self'],
-      resourceUrlBlacklist = [];
-
-  /**
-   * @ngdoc function
-   * @name ng.sceDelegateProvider#resourceUrlWhitelist
-   * @methodOf ng.$sceDelegateProvider
-   * @function
-   *
-   * @param {Array=} whitelist When provided, replaces the resourceUrlWhitelist with the value
-   *     provided.  This must be an array or null.  A snapshot of this array is used so further
-   *     changes to the array are ignored.
-   *
-   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
-   *     allowed in this array.
-   *
-   *     Note: **an empty whitelist array will block all URLs**!
-   *
-   * @return {Array} the currently set whitelist array.
-   *
-   * The **default value** when no whitelist has been explicitly set is `['self']` allowing only
-   * same origin resource requests.
-   *
-   * @description
-   * Sets/Gets the whitelist of trusted resource URLs.
-   */
-  this.resourceUrlWhitelist = function (value) {
-    if (arguments.length) {
-      resourceUrlWhitelist = adjustMatchers(value);
-    }
-    return resourceUrlWhitelist;
-  };
-
-  /**
-   * @ngdoc function
-   * @name ng.sceDelegateProvider#resourceUrlBlacklist
-   * @methodOf ng.$sceDelegateProvider
-   * @function
-   *
-   * @param {Array=} blacklist When provided, replaces the resourceUrlBlacklist with the value
-   *     provided.  This must be an array or null.  A snapshot of this array is used so further
-   *     changes to the array are ignored.
-   *
-   *     Follow {@link ng.$sce#resourceUrlPatternItem this link} for a description of the items
-   *     allowed in this array.
-   *
-   *     The typical usage for the blacklist is to **block
-   *     [open redirects](http://cwe.mitre.org/data/definitions/601.html)** served by your domain as
-   *     these would otherwise be trusted but actually return content from the redirected domain.
-   *
-   *     Finally, **the blacklist overrides the whitelist** and has the final say.
-   *
-   * @return {Array} the currently set blacklist array.
-   *
-   * The **default value** when no whitelist has been explicitly set is the empty array (i.e. there
-   * is no blacklist.)
-   *
-   * @description
-   * Sets/Gets the blacklist of trusted resource URLs.
-   */
-
-  this.resourceUrlBlacklist = function (value) {
-    if (arguments.length) {
-      resourceUrlBlacklist = adjustMatchers(value);
-    }
-    return resourceUrlBlacklist;
-  };
-
-  this.$get = ['$injector', function($injector) {
-
-    var htmlSanitizer = function htmlSanitizer(html) {
-      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
-    };
-
-    if ($injector.has('$sanitize')) {
-      htmlSanitizer = $injector.get('$sanitize');
-    }
-
-
-    function matchUrl(matcher, parsedUrl) {
-      if (matcher === 'self') {
-        return urlIsSameOrigin(parsedUrl);
-      } else {
-        // definitely a regex.  See adjustMatchers()
-        return !!matcher.exec(parsedUrl.href);
-      }
-    }
-
-    function isResourceUrlAllowedByPolicy(url) {
-      var parsedUrl = urlResolve(url.toString());
-      var i, n, allowed = false;
-      // Ensure that at least one item from the whitelist allows this url.
-      for (i = 0, n = resourceUrlWhitelist.length; i < n; i++) {
-        if (matchUrl(resourceUrlWhitelist[i], parsedUrl)) {
-          allowed = true;
-          break;
-        }
-      }
-      if (allowed) {
-        // Ensure that no item from the blacklist blocked this url.
-        for (i = 0, n = resourceUrlBlacklist.length; i < n; i++) {
-          if (matchUrl(resourceUrlBlacklist[i], parsedUrl)) {
-            allowed = false;
-            break;
-          }
-        }
-      }
-      return allowed;
-    }
-
-    function generateHolderType(Base) {
-      var holderType = function TrustedValueHolderType(trustedValue) {
-        this.$$unwrapTrustedValue = function() {
-          return trustedValue;
-        };
-      };
-      if (Base) {
-        holderType.prototype = new Base();
-      }
-      holderType.prototype.valueOf = function sceValueOf() {
-        return this.$$unwrapTrustedValue();
-      };
-      holderType.prototype.toString = function sceToString() {
-        return this.$$unwrapTrustedValue().toString();
-      };
-      return holderType;
-    }
-
-    var trustedValueHolderBase = generateHolderType(),
-        byType = {};
-
-    byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase);
-    byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase);
-    byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase);
-    byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase);
-    byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]);
-
-    /**
-     * @ngdoc method
-     * @name ng.$sceDelegate#trustAs
-     * @methodOf ng.$sceDelegate
-     *
-     * @description
-     * Returns an object that is trusted by angular for use in specified strict
-     * contextual escaping contexts (such as ng-html-bind-unsafe, ng-include, any src
-     * attribute interpolation, any dom event binding attribute interpolation
-     * such as for onclick,  etc.) that uses the provided value.
-     * See {@link ng.$sce $sce} for enabling strict contextual escaping.
-     *
-     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,
-     *   resourceUrl, html, js and css.
-     * @param {*} value The value that that should be considered trusted/safe.
-     * @returns {*} A value that can be used to stand in for the provided `value` in places
-     * where Angular expects a $sce.trustAs() return value.
-     */
-    function trustAs(type, trustedValue) {
-      var Constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
-      if (!Constructor) {
-        throw $sceMinErr('icontext',
-            'Attempted to trust a value in invalid context. Context: {0}; Value: {1}',
-            type, trustedValue);
-      }
-      if (trustedValue === null || trustedValue === undefined || trustedValue === '') {
-        return trustedValue;
-      }
-      // All the current contexts in SCE_CONTEXTS happen to be strings.  In order to avoid trusting
-      // mutable objects, we ensure here that the value passed in is actually a string.
-      if (typeof trustedValue !== 'string') {
-        throw $sceMinErr('itype',
-            'Attempted to trust a non-string value in a content requiring a string: Context: {0}',
-            type);
-      }
-      return new Constructor(trustedValue);
-    }
-
-    /**
-     * @ngdoc method
-     * @name ng.$sceDelegate#valueOf
-     * @methodOf ng.$sceDelegate
-     *
-     * @description
-     * If the passed parameter had been returned by a prior call to {@link ng.$sceDelegate#methods_trustAs
-     * `$sceDelegate.trustAs`}, returns the value that had been passed to {@link
-     * ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}.
-     *
-     * If the passed parameter is not a value that had been returned by {@link
-     * ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}, returns it as-is.
-     *
-     * @param {*} value The result of a prior {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}
-     *      call or anything else.
-     * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#methods_trustAs
-     *     `$sceDelegate.trustAs`} if `value` is the result of such a call.  Otherwise, returns
-     *     `value` unchanged.
-     */
-    function valueOf(maybeTrusted) {
-      if (maybeTrusted instanceof trustedValueHolderBase) {
-        return maybeTrusted.$$unwrapTrustedValue();
-      } else {
-        return maybeTrusted;
-      }
-    }
-
-    /**
-     * @ngdoc method
-     * @name ng.$sceDelegate#getTrusted
-     * @methodOf ng.$sceDelegate
-     *
-     * @description
-     * Takes the result of a {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`} call and
-     * returns the originally supplied value if the queried context type is a supertype of the
-     * created type.  If this condition isn't satisfied, throws an exception.
-     *
-     * @param {string} type The kind of context in which this value is to be used.
-     * @param {*} maybeTrusted The result of a prior {@link ng.$sceDelegate#methods_trustAs
-     *     `$sceDelegate.trustAs`} call.
-     * @returns {*} The value the was originally provided to {@link ng.$sceDelegate#methods_trustAs
-     *     `$sceDelegate.trustAs`} if valid in this context.  Otherwise, throws an exception.
-     */
-    function getTrusted(type, maybeTrusted) {
-      if (maybeTrusted === null || maybeTrusted === undefined || maybeTrusted === '') {
-        return maybeTrusted;
-      }
-      var constructor = (byType.hasOwnProperty(type) ? byType[type] : null);
-      if (constructor && maybeTrusted instanceof constructor) {
-        return maybeTrusted.$$unwrapTrustedValue();
-      }
-      // If we get here, then we may only take one of two actions.
-      // 1. sanitize the value for the requested type, or
-      // 2. throw an exception.
-      if (type === SCE_CONTEXTS.RESOURCE_URL) {
-        if (isResourceUrlAllowedByPolicy(maybeTrusted)) {
-          return maybeTrusted;
-        } else {
-          throw $sceMinErr('insecurl',
-              'Blocked loading resource from url not allowed by $sceDelegate policy.  URL: {0}',
-              maybeTrusted.toString());
-        }
-      } else if (type === SCE_CONTEXTS.HTML) {
-        return htmlSanitizer(maybeTrusted);
-      }
-      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');
-    }
-
-    return { trustAs: trustAs,
-             getTrusted: getTrusted,
-             valueOf: valueOf };
-  }];
-}
-
-
-/**
- * @ngdoc object
- * @name ng.$sceProvider
- * @description
- *
- * The $sceProvider provider allows developers to configure the {@link ng.$sce $sce} service.
- * -   enable/disable Strict Contextual Escaping (SCE) in a module
- * -   override the default implementation with a custom delegate
- *
- * Read more about {@link ng.$sce Strict Contextual Escaping (SCE)}.
- */
-
-/* jshint maxlen: false*/
-
-/**
- * @ngdoc service
- * @name ng.$sce
- * @function
- *
- * @description
- *
- * `$sce` is a service that provides Strict Contextual Escaping services to AngularJS.
- *
- * # Strict Contextual Escaping
- *
- * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain
- * contexts to result in a value that is marked as safe to use for that context.  One example of
- * such a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer
- * to these contexts as privileged or SCE contexts.
- *
- * As of version 1.2, Angular ships with SCE enabled by default.
- *
- * Note:  When enabled (the default), IE8 in quirks mode is not supported.  In this mode, IE8 allows
- * one to execute arbitrary javascript by the use of the expression() syntax.  Refer
- * <http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx> to learn more about them.
- * You can ensure your document is in standards mode and not quirks mode by adding `<!doctype html>`
- * to the top of your HTML document.
- *
- * SCE assists in writing code in way that (a) is secure by default and (b) makes auditing for
- * security vulnerabilities such as XSS, clickjacking, etc. a lot easier.
- *
- * Here's an example of a binding in a privileged context:
- *
- * <pre class="prettyprint">
- *     <input ng-model="userHtml">
- *     <div ng-bind-html="userHtml">
- * </pre>
- *
- * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user.  With SCE
- * disabled, this application allows the user to render arbitrary HTML into the DIV.
- * In a more realistic example, one may be rendering user comments, blog articles, etc. via
- * bindings.  (HTML is just one example of a context where rendering user controlled input creates
- * security vulnerabilities.)
- *
- * For the case of HTML, you might use a library, either on the client side, or on the server side,
- * to sanitize unsafe HTML before binding to the value and rendering it in the document.
- *
- * How would you ensure that every place that used these types of bindings was bound to a value that
- * was sanitized by your library (or returned as safe for rendering by your server?)  How can you
- * ensure that you didn't accidentally delete the line that sanitized the value, or renamed some
- * properties/fields and forgot to update the binding to the sanitized value?
- *
- * To be secure by default, you want to ensure that any such bindings are disallowed unless you can
- * determine that something explicitly says it's safe to use a value for binding in that
- * context.  You can then audit your code (a simple grep would do) to ensure that this is only done
- * for those values that you can easily tell are safe - because they were received from your server,
- * sanitized by your library, etc.  You can organize your codebase to help with this - perhaps
- * allowing only the files in a specific directory to do this.  Ensuring that the internal API
- * exposed by that code doesn't markup arbitrary values as safe then becomes a more manageable task.
- *
- * In the case of AngularJS' SCE service, one uses {@link ng.$sce#methods_trustAs $sce.trustAs} 
- * (and shorthand methods such as {@link ng.$sce#methods_trustAsHtml $sce.trustAsHtml}, etc.) to
- * obtain values that will be accepted by SCE / privileged contexts.
- *
- *
- * ## How does it work?
- *
- * In privileged contexts, directives and code will bind to the result of {@link ng.$sce#methods_getTrusted
- * $sce.getTrusted(context, value)} rather than to the value directly.  Directives use {@link
- * ng.$sce#methods_parse $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the
- * {@link ng.$sce#methods_getTrusted $sce.getTrusted} behind the scenes on non-constant literals.
- *
- * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link
- * ng.$sce#methods_parseAsHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly
- * simplified):
- *
- * <pre class="prettyprint">
- *   var ngBindHtmlDirective = ['$sce', function($sce) {
- *     return function(scope, element, attr) {
- *       scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {
- *         element.html(value || '');
- *       });
- *     };
- *   }];
- * </pre>
- *
- * ## Impact on loading templates
- *
- * This applies both to the {@link ng.directive:ngInclude `ng-include`} directive as well as
- * `templateUrl`'s specified by {@link guide/directive directives}.
- *
- * By default, Angular only loads templates from the same domain and protocol as the application
- * document.  This is done by calling {@link ng.$sce#methods_getTrustedResourceUrl
- * $sce.getTrustedResourceUrl} on the template URL.  To load templates from other domains and/or
- * protocols, you may either either {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelist
- * them} or {@link ng.$sce#methods_trustAsResourceUrl wrap it} into a trusted value.
- *
- * *Please note*:
- * The browser's
- * {@link https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest
- * Same Origin Policy} and {@link http://www.w3.org/TR/cors/ Cross-Origin Resource Sharing (CORS)}
- * policy apply in addition to this and may further restrict whether the template is successfully
- * loaded.  This means that without the right CORS policy, loading templates from a different domain
- * won't work on all browsers.  Also, loading templates from `file://` URL does not work on some
- * browsers.
- *
- * ## This feels like too much overhead for the developer?
- *
- * It's important to remember that SCE only applies to interpolation expressions.
- *
- * If your expressions are constant literals, they're automatically trusted and you don't need to
- * call `$sce.trustAs` on them.  (e.g.
- * `<div ng-html-bind-unsafe="'<b>implicitly trusted</b>'"></div>`) just works.
- *
- * Additionally, `a[href]` and `img[src]` automatically sanitize their URLs and do not pass them
- * through {@link ng.$sce#methods_getTrusted $sce.getTrusted}.  SCE doesn't play a role here.
- *
- * The included {@link ng.$sceDelegate $sceDelegate} comes with sane defaults to allow you to load
- * templates in `ng-include` from your application's domain without having to even know about SCE.
- * It blocks loading templates from other domains or loading templates over http from an https
- * served document.  You can change these by setting your own custom {@link
- * ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelists} and {@link
- * ng.$sceDelegateProvider#methods_resourceUrlBlacklist blacklists} for matching such URLs.
- *
- * This significantly reduces the overhead.  It is far easier to pay the small overhead and have an
- * application that's secure and can be audited to verify that with much more ease than bolting
- * security onto an application later.
- *
- * <a name="contexts"></a>
- * ## What trusted context types are supported?
- *
- * | Context             | Notes          |
- * |---------------------|----------------|
- * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. |
- * | `$sce.CSS`          | For CSS that's safe to source into the application.  Currently unused.  Feel free to use it in your own directives. |
- * | `$sce.URL`          | For URLs that are safe to follow as links.  Currently unused (`<a href=` and `<img src=` sanitize their urls and don't consititute an SCE context. |
- * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contens are also safe to include in your application.  Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)  <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. |
- * | `$sce.JS`           | For JavaScript that is safe to execute in your application's context.  Currently unused.  Feel free to use it in your own directives. |
- *
- * ## Format of items in {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist resourceUrlWhitelist}/{@link ng.$sceDelegateProvider#methods_resourceUrlBlacklist Blacklist} <a name="resourceUrlPatternItem"></a>
- *
- *  Each element in these arrays must be one of the following:
- *
- *  - **'self'**
- *    - The special **string**, `'self'`, can be used to match against all URLs of the **same
- *      domain** as the application document using the **same protocol**.
- *  - **String** (except the special value `'self'`)
- *    - The string is matched against the full *normalized / absolute URL* of the resource
- *      being tested (substring matches are not good enough.)
- *    - There are exactly **two wildcard sequences** - `*` and `**`.  All other characters
- *      match themselves.
- *    - `*`: matches zero or more occurances of any character other than one of the following 6
- *      characters: '`:`', '`/`', '`.`', '`?`', '`&`' and ';'.  It's a useful wildcard for use
- *      in a whitelist.
- *    - `**`: matches zero or more occurances of *any* character.  As such, it's not
- *      not appropriate to use in for a scheme, domain, etc. as it would match too much.  (e.g.
- *      http://**.example.com/ would match http://evil.com/?ignore=.example.com/ and that might
- *      not have been the intention.)  It's usage at the very end of the path is ok.  (e.g.
- *      http://foo.example.com/templates/**).
- *  - **RegExp** (*see caveat below*)
- *    - *Caveat*:  While regular expressions are powerful and offer great flexibility,  their syntax
- *      (and all the inevitable escaping) makes them *harder to maintain*.  It's easy to
- *      accidentally introduce a bug when one updates a complex expression (imho, all regexes should
- *      have good test coverage.).  For instance, the use of `.` in the regex is correct only in a
- *      small number of cases.  A `.` character in the regex used when matching the scheme or a
- *      subdomain could be matched against a `:` or literal `.` that was likely not intended.   It
- *      is highly recommended to use the string patterns and only fall back to regular expressions
- *      if they as a last resort.
- *    - The regular expression must be an instance of RegExp (i.e. not a string.)  It is
- *      matched against the **entire** *normalized / absolute URL* of the resource being tested
- *      (even when the RegExp did not have the `^` and `$` codes.)  In addition, any flags
- *      present on the RegExp (such as multiline, global, ignoreCase) are ignored.
- *    - If you are generating your Javascript from some other templating engine (not
- *      recommended, e.g. in issue [#4006](https://github.com/angular/angular.js/issues/4006)),
- *      remember to escape your regular expression (and be aware that you might need more than
- *      one level of escaping depending on your templating engine and the way you interpolated
- *      the value.)  Do make use of your platform's escaping mechanism as it might be good
- *      enough before coding your own.  e.g. Ruby has
- *      [Regexp.escape(str)](http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-c-escape)
- *      and Python has [re.escape](http://docs.python.org/library/re.html#re.escape).
- *      Javascript lacks a similar built in function for escaping.  Take a look at Google
- *      Closure library's [goog.string.regExpEscape(s)](
- *      http://docs.closure-library.googlecode.com/git/closure_goog_string_string.js.source.html#line962).
- *
- * Refer {@link ng.$sceDelegateProvider $sceDelegateProvider} for an example.
- *
- * ## Show me an example using SCE.
- *
- * @example
-<example module="mySceApp">
-<file name="index.html">
-  <div ng-controller="myAppController as myCtrl">
-    <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
-    <b>User comments</b><br>
-    By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
-    $sanitize is available.  If $sanitize isn't available, this results in an error instead of an
-    exploit.
-    <div class="well">
-      <div ng-repeat="userComment in myCtrl.userComments">
-        <b>{{userComment.name}}</b>:
-        <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span>
-        <br>
-      </div>
-    </div>
-  </div>
-</file>
-
-<file name="script.js">
-  var mySceApp = angular.module('mySceApp', ['ngSanitize']);
-
-  mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) {
-    var self = this;
-    $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
-      self.userComments = userComments;
-    });
-    self.explicitlyTrustedHtml = $sce.trustAsHtml(
-        '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
-        'sanitization.&quot;">Hover over this text.</span>');
-  });
-</file>
-
-<file name="test_data.json">
-[
-  { "name": "Alice",
-    "htmlComment":
-        "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"
-  },
-  { "name": "Bob",
-    "htmlComment": "<i>Yes!</i>  Am I the only other one?"
-  }
-]
-</file>
-
-<file name="scenario.js">
-  describe('SCE doc demo', function() {
-    it('should sanitize untrusted values', function() {
-      expect(element('.htmlComment').html()).toBe('<span>Is <i>anyone</i> reading this?</span>');
-    });
-    it('should NOT sanitize explicitly trusted values', function() {
-      expect(element('#explicitlyTrustedHtml').html()).toBe(
-          '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
-          'sanitization.&quot;">Hover over this text.</span>');
-    });
-  });
-</file>
-</example>
- *
- *
- *
- * ## Can I disable SCE completely?
- *
- * Yes, you can.  However, this is strongly discouraged.  SCE gives you a lot of security benefits
- * for little coding overhead.  It will be much harder to take an SCE disabled application and
- * either secure it on your own or enable SCE at a later stage.  It might make sense to disable SCE
- * for cases where you have a lot of existing code that was written before SCE was introduced and
- * you're migrating them a module at a time.
- *
- * That said, here's how you can completely disable SCE:
- *
- * <pre class="prettyprint">
- *   angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
- *     // Completely disable SCE.  For demonstration purposes only!
- *     // Do not use in new projects.
- *     $sceProvider.enabled(false);
- *   });
- * </pre>
- *
- */
-/* jshint maxlen: 100 */
-
-function $SceProvider() {
-  var enabled = true;
-
-  /**
-   * @ngdoc function
-   * @name ng.sceProvider#enabled
-   * @methodOf ng.$sceProvider
-   * @function
-   *
-   * @param {boolean=} value If provided, then enables/disables SCE.
-   * @return {boolean} true if SCE is enabled, false otherwise.
-   *
-   * @description
-   * Enables/disables SCE and returns the current value.
-   */
-  this.enabled = function (value) {
-    if (arguments.length) {
-      enabled = !!value;
-    }
-    return enabled;
-  };
-
-
-  /* Design notes on the default implementation for SCE.
-   *
-   * The API contract for the SCE delegate
-   * -------------------------------------
-   * The SCE delegate object must provide the following 3 methods:
-   *
-   * - trustAs(contextEnum, value)
-   *     This method is used to tell the SCE service that the provided value is OK to use in the
-   *     contexts specified by contextEnum.  It must return an object that will be accepted by
-   *     getTrusted() for a compatible contextEnum and return this value.
-   *
-   * - valueOf(value)
-   *     For values that were not produced by trustAs(), return them as is.  For values that were
-   *     produced by trustAs(), return the corresponding input value to trustAs.  Basically, if
-   *     trustAs is wrapping the given values into some type, this operation unwraps it when given
-   *     such a value.
-   *
-   * - getTrusted(contextEnum, value)
-   *     This function should return the a value that is safe to use in the context specified by
-   *     contextEnum or throw and exception otherwise.
-   *
-   * NOTE: This contract deliberately does NOT state that values returned by trustAs() must be
-   * opaque or wrapped in some holder object.  That happens to be an implementation detail.  For
-   * instance, an implementation could maintain a registry of all trusted objects by context.  In
-   * such a case, trustAs() would return the same object that was passed in.  getTrusted() would
-   * return the same object passed in if it was found in the registry under a compatible context or
-   * throw an exception otherwise.  An implementation might only wrap values some of the time based
-   * on some criteria.  getTrusted() might return a value and not throw an exception for special
-   * constants or objects even if not wrapped.  All such implementations fulfill this contract.
-   *
-   *
-   * A note on the inheritance model for SCE contexts
-   * ------------------------------------------------
-   * I've used inheritance and made RESOURCE_URL wrapped types a subtype of URL wrapped types.  This
-   * is purely an implementation details.
-   *
-   * The contract is simply this:
-   *
-   *     getTrusted($sce.RESOURCE_URL, value) succeeding implies that getTrusted($sce.URL, value)
-   *     will also succeed.
-   *
-   * Inheritance happens to capture this in a natural way.  In some future, we
-   * may not use inheritance anymore.  That is OK because no code outside of
-   * sce.js and sceSpecs.js would need to be aware of this detail.
-   */
-
-  this.$get = ['$parse', '$sniffer', '$sceDelegate', function(
-                $parse,   $sniffer,   $sceDelegate) {
-    // Prereq: Ensure that we're not running in IE8 quirks mode.  In that mode, IE allows
-    // the "expression(javascript expression)" syntax which is insecure.
-    if (enabled && $sniffer.msie && $sniffer.msieDocumentMode < 8) {
-      throw $sceMinErr('iequirks',
-        'Strict Contextual Escaping does not support Internet Explorer version < 9 in quirks ' +
-        'mode.  You can fix this by adding the text <!doctype html> to the top of your HTML ' +
-        'document.  See http://docs.angularjs.org/api/ng.$sce for more information.');
-    }
-
-    var sce = copy(SCE_CONTEXTS);
-
-    /**
-     * @ngdoc function
-     * @name ng.sce#isEnabled
-     * @methodOf ng.$sce
-     * @function
-     *
-     * @return {Boolean} true if SCE is enabled, false otherwise.  If you want to set the value, you
-     * have to do it at module config time on {@link ng.$sceProvider $sceProvider}.
-     *
-     * @description
-     * Returns a boolean indicating if SCE is enabled.
-     */
-    sce.isEnabled = function () {
-      return enabled;
-    };
-    sce.trustAs = $sceDelegate.trustAs;
-    sce.getTrusted = $sceDelegate.getTrusted;
-    sce.valueOf = $sceDelegate.valueOf;
-
-    if (!enabled) {
-      sce.trustAs = sce.getTrusted = function(type, value) { return value; };
-      sce.valueOf = identity;
-    }
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#parse
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Converts Angular {@link guide/expression expression} into a function.  This is like {@link
-     * ng.$parse $parse} and is identical when the expression is a literal constant.  Otherwise, it
-     * wraps the expression in a call to {@link ng.$sce#methods_getTrusted $sce.getTrusted(*type*,
-     * *result*)}
-     *
-     * @param {string} type The kind of SCE context in which this result will be used.
-     * @param {string} expression String expression to compile.
-     * @returns {function(context, locals)} a function which represents the compiled expression:
-     *
-     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
-     *      are evaluated against (typically a scope object).
-     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
-     *      `context`.
-     */
-    sce.parseAs = function sceParseAs(type, expr) {
-      var parsed = $parse(expr);
-      if (parsed.literal && parsed.constant) {
-        return parsed;
-      } else {
-        return function sceParseAsTrusted(self, locals) {
-          return sce.getTrusted(type, parsed(self, locals));
-        };
-      }
-    };
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#trustAs
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Delegates to {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs`}.  As such,
-     * returns an objectthat is trusted by angular for use in specified strict contextual
-     * escaping contexts (such as ng-html-bind-unsafe, ng-include, any src attribute
-     * interpolation, any dom event binding attribute interpolation such as for onclick,  etc.)
-     * that uses the provided value.  See * {@link ng.$sce $sce} for enabling strict contextual
-     * escaping.
-     *
-     * @param {string} type The kind of context in which this value is safe for use.  e.g. url,
-     *   resource_url, html, js and css.
-     * @param {*} value The value that that should be considered trusted/safe.
-     * @returns {*} A value that can be used to stand in for the provided `value` in places
-     * where Angular expects a $sce.trustAs() return value.
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#trustAsHtml
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.trustAsHtml(value)` →
-     *     {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.HTML, value)`}
-     *
-     * @param {*} value The value to trustAs.
-     * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedHtml
-     *     $sce.getTrustedHtml(value)} to obtain the original value.  (privileged directives
-     *     only accept expressions that are either literal constants or are the
-     *     return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#trustAsUrl
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.trustAsUrl(value)` →
-     *     {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.URL, value)`}
-     *
-     * @param {*} value The value to trustAs.
-     * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedUrl
-     *     $sce.getTrustedUrl(value)} to obtain the original value.  (privileged directives
-     *     only accept expressions that are either literal constants or are the
-     *     return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#trustAsResourceUrl
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.trustAsResourceUrl(value)` →
-     *     {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.RESOURCE_URL, value)`}
-     *
-     * @param {*} value The value to trustAs.
-     * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedResourceUrl
-     *     $sce.getTrustedResourceUrl(value)} to obtain the original value.  (privileged directives
-     *     only accept expressions that are either literal constants or are the return
-     *     value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#trustAsJs
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.trustAsJs(value)` →
-     *     {@link ng.$sceDelegate#methods_trustAs `$sceDelegate.trustAs($sce.JS, value)`}
-     *
-     * @param {*} value The value to trustAs.
-     * @returns {*} An object that can be passed to {@link ng.$sce#methods_getTrustedJs
-     *     $sce.getTrustedJs(value)} to obtain the original value.  (privileged directives
-     *     only accept expressions that are either literal constants or are the
-     *     return value of {@link ng.$sce#methods_trustAs $sce.trustAs}.)
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#getTrusted
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Delegates to {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted`}.  As such,
-     * takes the result of a {@link ng.$sce#methods_trustAs `$sce.trustAs`}() call and returns the
-     * originally supplied value if the queried context type is a supertype of the created type.
-     * If this condition isn't satisfied, throws an exception.
-     *
-     * @param {string} type The kind of context in which this value is to be used.
-     * @param {*} maybeTrusted The result of a prior {@link ng.$sce#methods_trustAs `$sce.trustAs`}
-     *                         call.
-     * @returns {*} The value the was originally provided to
-     *              {@link ng.$sce#methods_trustAs `$sce.trustAs`} if valid in this context.
-     *              Otherwise, throws an exception.
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#getTrustedHtml
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.getTrustedHtml(value)` →
-     *     {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.HTML, value)`}
-     *
-     * @param {*} value The value to pass to `$sce.getTrusted`.
-     * @returns {*} The return value of `$sce.getTrusted($sce.HTML, value)`
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#getTrustedCss
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.getTrustedCss(value)` →
-     *     {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.CSS, value)`}
-     *
-     * @param {*} value The value to pass to `$sce.getTrusted`.
-     * @returns {*} The return value of `$sce.getTrusted($sce.CSS, value)`
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#getTrustedUrl
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.getTrustedUrl(value)` →
-     *     {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.URL, value)`}
-     *
-     * @param {*} value The value to pass to `$sce.getTrusted`.
-     * @returns {*} The return value of `$sce.getTrusted($sce.URL, value)`
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#getTrustedResourceUrl
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.getTrustedResourceUrl(value)` →
-     *     {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.RESOURCE_URL, value)`}
-     *
-     * @param {*} value The value to pass to `$sceDelegate.getTrusted`.
-     * @returns {*} The return value of `$sce.getTrusted($sce.RESOURCE_URL, value)`
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#getTrustedJs
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.getTrustedJs(value)` →
-     *     {@link ng.$sceDelegate#methods_getTrusted `$sceDelegate.getTrusted($sce.JS, value)`}
-     *
-     * @param {*} value The value to pass to `$sce.getTrusted`.
-     * @returns {*} The return value of `$sce.getTrusted($sce.JS, value)`
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#parseAsHtml
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.parseAsHtml(expression string)` →
-     *     {@link ng.$sce#methods_parse `$sce.parseAs($sce.HTML, value)`}
-     *
-     * @param {string} expression String expression to compile.
-     * @returns {function(context, locals)} a function which represents the compiled expression:
-     *
-     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
-     *      are evaluated against (typically a scope object).
-     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
-     *      `context`.
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#parseAsCss
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.parseAsCss(value)` →
-     *     {@link ng.$sce#methods_parse `$sce.parseAs($sce.CSS, value)`}
-     *
-     * @param {string} expression String expression to compile.
-     * @returns {function(context, locals)} a function which represents the compiled expression:
-     *
-     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
-     *      are evaluated against (typically a scope object).
-     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
-     *      `context`.
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#parseAsUrl
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.parseAsUrl(value)` →
-     *     {@link ng.$sce#methods_parse `$sce.parseAs($sce.URL, value)`}
-     *
-     * @param {string} expression String expression to compile.
-     * @returns {function(context, locals)} a function which represents the compiled expression:
-     *
-     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
-     *      are evaluated against (typically a scope object).
-     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
-     *      `context`.
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#parseAsResourceUrl
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.parseAsResourceUrl(value)` →
-     *     {@link ng.$sce#methods_parse `$sce.parseAs($sce.RESOURCE_URL, value)`}
-     *
-     * @param {string} expression String expression to compile.
-     * @returns {function(context, locals)} a function which represents the compiled expression:
-     *
-     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
-     *      are evaluated against (typically a scope object).
-     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
-     *      `context`.
-     */
-
-    /**
-     * @ngdoc method
-     * @name ng.$sce#parseAsJs
-     * @methodOf ng.$sce
-     *
-     * @description
-     * Shorthand method.  `$sce.parseAsJs(value)` →
-     *     {@link ng.$sce#methods_parse `$sce.parseAs($sce.JS, value)`}
-     *
-     * @param {string} expression String expression to compile.
-     * @returns {function(context, locals)} a function which represents the compiled expression:
-     *
-     *    * `context` – `{object}` – an object against which any expressions embedded in the strings
-     *      are evaluated against (typically a scope object).
-     *    * `locals` – `{object=}` – local variables context object, useful for overriding values in
-     *      `context`.
-     */
-
-    // Shorthand delegations.
-    var parse = sce.parseAs,
-        getTrusted = sce.getTrusted,
-        trustAs = sce.trustAs;
-
-    forEach(SCE_CONTEXTS, function (enumValue, name) {
-      var lName = lowercase(name);
-      sce[camelCase("parse_as_" + lName)] = function (expr) {
-        return parse(enumValue, expr);
-      };
-      sce[camelCase("get_trusted_" + lName)] = function (value) {
-        return getTrusted(enumValue, value);
-      };
-      sce[camelCase("trust_as_" + lName)] = function (value) {
-        return trustAs(enumValue, value);
-      };
-    });
-
-    return sce;
-  }];
-}
-
-/**
- * !!! This is an undocumented "private" service !!!
- *
- * @name ng.$sniffer
- * @requires $window
- * @requires $document
- *
- * @property {boolean} history Does the browser support html5 history api ?
- * @property {boolean} hashchange Does the browser support hashchange event ?
- * @property {boolean} transitions Does the browser support CSS transition events ?
- * @property {boolean} animations Does the browser support CSS animation events ?
- *
- * @description
- * This is very simple implementation of testing browser's features.
- */
-function $SnifferProvider() {
-  this.$get = ['$window', '$document', function($window, $document) {
-    var eventSupport = {},
-        android =
-          int((/android (\d+)/.exec(lowercase(($window.navigator || {}).userAgent)) || [])[1]),
-        boxee = /Boxee/i.test(($window.navigator || {}).userAgent),
-        document = $document[0] || {},
-        documentMode = document.documentMode,
-        vendorPrefix,
-        vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/,
-        bodyStyle = document.body && document.body.style,
-        transitions = false,
-        animations = false,
-        match;
-
-    if (bodyStyle) {
-      for(var prop in bodyStyle) {
-        if(match = vendorRegex.exec(prop)) {
-          vendorPrefix = match[0];
-          vendorPrefix = vendorPrefix.substr(0, 1).toUpperCase() + vendorPrefix.substr(1);
-          break;
-        }
-      }
-
-      if(!vendorPrefix) {
-        vendorPrefix = ('WebkitOpacity' in bodyStyle) && 'webkit';
-      }
-
-      transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
-      animations  = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
-
-      if (android && (!transitions||!animations)) {
-        transitions = isString(document.body.style.webkitTransition);
-        animations = isString(document.body.style.webkitAnimation);
-      }
-    }
-
-
-    return {
-      // Android has history.pushState, but it does not update location correctly
-      // so let's not use the history API at all.
-      // http://code.google.com/p/android/issues/detail?id=17471
-      // https://github.com/angular/angular.js/issues/904
-
-      // older webit browser (533.9) on Boxee box has exactly the same problem as Android has
-      // so let's not use the history API also
-      // We are purposefully using `!(android < 4)` to cover the case when `android` is undefined
-      // jshint -W018
-      history: !!($window.history && $window.history.pushState && !(android < 4) && !boxee),
-      // jshint +W018
-      hashchange: 'onhashchange' in $window &&
-                  // IE8 compatible mode lies
-                  (!documentMode || documentMode > 7),
-      hasEvent: function(event) {
-        // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have
-        // it. In particular the event is not fired when backspace or delete key are pressed or
-        // when cut operation is performed.
-        if (event == 'input' && msie == 9) return false;
-
-        if (isUndefined(eventSupport[event])) {
-          var divElm = document.createElement('div');
-          eventSupport[event] = 'on' + event in divElm;
-        }
-
-        return eventSupport[event];
-      },
-      csp: csp(),
-      vendorPrefix: vendorPrefix,
-      transitions : transitions,
-      animations : animations,
-      msie : msie,
-      msieDocumentMode: documentMode
-    };
-  }];
-}
-
-function $TimeoutProvider() {
-  this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',
-       function($rootScope,   $browser,   $q,   $exceptionHandler) {
-    var deferreds = {};
-
-
-     /**
-      * @ngdoc function
-      * @name ng.$timeout
-      * @requires $browser
-      *
-      * @description
-      * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch
-      * block and delegates any exceptions to
-      * {@link ng.$exceptionHandler $exceptionHandler} service.
-      *
-      * The return value of registering a timeout function is a promise, which will be resolved when
-      * the timeout is reached and the timeout function is executed.
-      *
-      * To cancel a timeout request, call `$timeout.cancel(promise)`.
-      *
-      * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to
-      * synchronously flush the queue of deferred functions.
-      *
-      * @param {function()} fn A function, whose execution should be delayed.
-      * @param {number=} [delay=0] Delay in milliseconds.
-      * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise
-      *   will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block.
-      * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this
-      *   promise will be resolved with is the return value of the `fn` function.
-      * 
-      * @example
-      <doc:example module="time">
-        <doc:source>
-          <script>
-            function Ctrl2($scope,$timeout) {
-              $scope.format = 'M/d/yy h:mm:ss a';
-              $scope.blood_1 = 100;
-              $scope.blood_2 = 120;
-
-              var stop;
-              $scope.fight = function() {
-                stop = $timeout(function() {
-                  if ($scope.blood_1 > 0 && $scope.blood_2 > 0) {
-                      $scope.blood_1 = $scope.blood_1 - 3;
-                      $scope.blood_2 = $scope.blood_2 - 4;
-                      $scope.fight();
-                  } else {
-                      $timeout.cancel(stop);
-                  }
-                }, 100);
-              };
-
-              $scope.stopFight = function() {
-                $timeout.cancel(stop);
-              };
-
-              $scope.resetFight = function() {
-                $scope.blood_1 = 100;
-                $scope.blood_2 = 120;
-              }
-            }
-
-            angular.module('time', [])
-              // Register the 'myCurrentTime' directive factory method.
-              // We inject $timeout and dateFilter service since the factory method is DI.
-              .directive('myCurrentTime', function($timeout, dateFilter) {
-                // return the directive link function. (compile function not needed)
-                return function(scope, element, attrs) {
-                  var format,  // date format
-                  timeoutId; // timeoutId, so that we can cancel the time updates
-
-                  // used to update the UI
-                  function updateTime() {
-                    element.text(dateFilter(new Date(), format));
-                  }
-
-                  // watch the expression, and update the UI on change.
-                  scope.$watch(attrs.myCurrentTime, function(value) {
-                    format = value;
-                    updateTime();
-                  });
-
-                  // schedule update in one second
-                  function updateLater() {
-                    // save the timeoutId for canceling
-                    timeoutId = $timeout(function() {
-                      updateTime(); // update DOM
-                      updateLater(); // schedule another update
-                    }, 1000);
-                  }
-
-                  // listen on DOM destroy (removal) event, and cancel the next UI update
-                  // to prevent updating time ofter the DOM element was removed.
-                  element.bind('$destroy', function() {
-                    $timeout.cancel(timeoutId);
-                  });
-
-                  updateLater(); // kick off the UI update process.
-                }
-              });
-          </script>
-
-          <div>
-            <div ng-controller="Ctrl2">
-              Date format: <input ng-model="format"> <hr/>
-              Current time is: <span my-current-time="format"></span>
-              <hr/>
-              Blood 1 : <font color='red'>{{blood_1}}</font>
-              Blood 2 : <font color='red'>{{blood_2}}</font>
-              <button type="button" data-ng-click="fight()">Fight</button>
-              <button type="button" data-ng-click="stopFight()">StopFight</button>
-              <button type="button" data-ng-click="resetFight()">resetFight</button>
-            </div>
-          </div>
-
-        </doc:source>
-      </doc:example>
-      */
-    function timeout(fn, delay, invokeApply) {
-      var deferred = $q.defer(),
-          promise = deferred.promise,
-          skipApply = (isDefined(invokeApply) && !invokeApply),
-          timeoutId;
-
-      timeoutId = $browser.defer(function() {
-        try {
-          deferred.resolve(fn());
-        } catch(e) {
-          deferred.reject(e);
-          $exceptionHandler(e);
-        }
-        finally {
-          delete deferreds[promise.$$timeoutId];
-        }
-
-        if (!skipApply) $rootScope.$apply();
-      }, delay);
-
-      promise.$$timeoutId = timeoutId;
-      deferreds[timeoutId] = deferred;
-
-      return promise;
-    }
-
-
-     /**
-      * @ngdoc function
-      * @name ng.$timeout#cancel
-      * @methodOf ng.$timeout
-      *
-      * @description
-      * Cancels a task associated with the `promise`. As a result of this, the promise will be
-      * resolved with a rejection.
-      *
-      * @param {Promise=} promise Promise returned by the `$timeout` function.
-      * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully
-      *   canceled.
-      */
-    timeout.cancel = function(promise) {
-      if (promise && promise.$$timeoutId in deferreds) {
-        deferreds[promise.$$timeoutId].reject('canceled');
-        delete deferreds[promise.$$timeoutId];
-        return $browser.defer.cancel(promise.$$timeoutId);
-      }
-      return false;
-    };
-
-    return timeout;
-  }];
-}
-
-// NOTE:  The usage of window and document instead of $window and $document here is
-// deliberate.  This service depends on the specific behavior of anchor nodes created by the
-// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and
-// cause us to break tests.  In addition, when the browser resolves a URL for XHR, it
-// doesn't know about mocked locations and resolves URLs to the real document - which is
-// exactly the behavior needed here.  There is little value is mocking these out for this
-// service.
-var urlParsingNode = document.createElement("a");
-var originUrl = urlResolve(window.location.href, true);
-
-
-/**
- *
- * Implementation Notes for non-IE browsers
- * ----------------------------------------
- * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM,
- * results both in the normalizing and parsing of the URL.  Normalizing means that a relative
- * URL will be resolved into an absolute URL in the context of the application document.
- * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related
- * properties are all populated to reflect the normalized URL.  This approach has wide
- * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc.  See
- * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
- *
- * Implementation Notes for IE
- * ---------------------------
- * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other
- * browsers.  However, the parsed components will not be set if the URL assigned did not specify
- * them.  (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.)  We
- * work around that by performing the parsing in a 2nd step by taking a previously normalized
- * URL (e.g. by assigning to a.href) and assigning it a.href again.  This correctly populates the
- * properties such as protocol, hostname, port, etc.
- *
- * IE7 does not normalize the URL when assigned to an anchor node.  (Apparently, it does, if one
- * uses the inner HTML approach to assign the URL as part of an HTML snippet -
- * http://stackoverflow.com/a/472729)  However, setting img[src] does normalize the URL.
- * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception.
- * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that
- * method and IE < 8 is unsupported.
- *
- * References:
- *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement
- *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html
- *   http://url.spec.whatwg.org/#urlutils
- *   https://github.com/angular/angular.js/pull/2902
- *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/
- *
- * @function
- * @param {string} url The URL to be parsed.
- * @description Normalizes and parses a URL.
- * @returns {object} Returns the normalized URL as a dictionary.
- *
- *   | member name   | Description    |
- *   |---------------|----------------|
- *   | href          | A normalized version of the provided URL if it was not an absolute URL |
- *   | protocol      | The protocol including the trailing colon                              |
- *   | host          | The host and port (if the port is non-default) of the normalizedUrl    |
- *   | search        | The search params, minus the question mark                             |
- *   | hash          | The hash string, minus the hash symbol
- *   | hostname      | The hostname
- *   | port          | The port, without ":"
- *   | pathname      | The pathname, beginning with "/"
- *
- */
-function urlResolve(url, base) {
-  var href = url;
-
-  if (msie) {
-    // Normalize before parse.  Refer Implementation Notes on why this is
-    // done in two steps on IE.
-    urlParsingNode.setAttribute("href", href);
-    href = urlParsingNode.href;
-  }
-
-  urlParsingNode.setAttribute('href', href);
-
-  // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
-  return {
-    href: urlParsingNode.href,
-    protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
-    host: urlParsingNode.host,
-    search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '',
-    hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
-    hostname: urlParsingNode.hostname,
-    port: urlParsingNode.port,
-    pathname: (urlParsingNode.pathname.charAt(0) === '/')
-      ? urlParsingNode.pathname
-      : '/' + urlParsingNode.pathname
-  };
-}
-
-/**
- * Parse a request URL and determine whether this is a same-origin request as the application document.
- *
- * @param {string|object} requestUrl The url of the request as a string that will be resolved
- * or a parsed URL object.
- * @returns {boolean} Whether the request is for the same origin as the application document.
- */
-function urlIsSameOrigin(requestUrl) {
-  var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl;
-  return (parsed.protocol === originUrl.protocol &&
-          parsed.host === originUrl.host);
-}
-
-/**
- * @ngdoc object
- * @name ng.$window
- *
- * @description
- * 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 overridden, removed or mocked for testing.
- *
- * Expressions, like the one defined for the `ngClick` directive in the example
- * below, are evaluated with respect to the current scope.  Therefore, there is
- * no risk of inadvertently coding in a dependency on a global value in such an
- * expression.
- *
- * @example
-   <doc:example>
-     <doc:source>
-       <script>
-         function Ctrl($scope, $window) {
-           $scope.greeting = 'Hello, World!';
-           $scope.doGreeting = function(greeting) {
-               $window.alert(greeting);
-           };
-         }
-       </script>
-       <div ng-controller="Ctrl">
-         <input type="text" ng-model="greeting" />
-         <button ng-click="doGreeting(greeting)">ALERT</button>
-       </div>
-     </doc:source>
-     <doc:scenario>
-      it('should display the greeting in the input box', function() {
-       input('greeting').enter('Hello, E2E Tests');
-       // If we click the button it will block the test runner
-       // element(':button').click();
-      });
-     </doc:scenario>
-   </doc:example>
- */
-function $WindowProvider(){
-  this.$get = valueFn(window);
-}
-
-/**
- * @ngdoc object
- * @name ng.$filterProvider
- * @description
- *
- * Filters are just functions which transform input to an output. However filters need to be
- * Dependency Injected. To achieve this a filter definition consists of a factory function which is
- * annotated with dependencies and is responsible for creating a filter function.
- *
- * <pre>
- *   // Filter registration
- *   function MyModule($provide, $filterProvider) {
- *     // create a service to demonstrate injection (not always needed)
- *     $provide.value('greet', function(name){
- *       return 'Hello ' + name + '!';
- *     });
- *
- *     // register a filter factory which uses the
- *     // greet service to demonstrate DI.
- *     $filterProvider.register('greet', function(greet){
- *       // return the filter function which uses the greet service
- *       // to generate salutation
- *       return function(text) {
- *         // filters need to be forgiving so check input validity
- *         return text && greet(text) || text;
- *       };
- *     });
- *   }
- * </pre>
- *
- * The filter function is registered with the `$injector` under the filter name suffix with
- * `Filter`.
- * 
- * <pre>
- *   it('should be the same instance', inject(
- *     function($filterProvider) {
- *       $filterProvider.register('reverse', function(){
- *         return ...;
- *       });
- *     },
- *     function($filter, reverseFilter) {
- *       expect($filter('reverse')).toBe(reverseFilter);
- *     });
- * </pre>
- *
- *
- * For more information about how angular filters work, and how to create your own filters, see
- * {@link guide/filter Filters} in the Angular Developer Guide.
- */
-/**
- * @ngdoc method
- * @name ng.$filterProvider#register
- * @methodOf ng.$filterProvider
- * @description
- * Register filter factory function.
- *
- * @param {String} name Name of the filter.
- * @param {function} fn The filter factory function which is injectable.
- */
-
-
-/**
- * @ngdoc function
- * @name ng.$filter
- * @function
- * @description
- * Filters are used for formatting data displayed to the user.
- *
- * The general syntax in templates is as follows:
- *
- *         {{ expression [| filter_name[:parameter_value] ... ] }}
- *
- * @param {String} name Name of the filter function to retrieve
- * @return {Function} the filter function
- */
-$FilterProvider.$inject = ['$provide'];
-function $FilterProvider($provide) {
-  var suffix = 'Filter';
-
-  /**
-   * @ngdoc function
-   * @name ng.$controllerProvider#register
-   * @methodOf ng.$controllerProvider
-   * @param {string|Object} name Name of the filter function, or an object map of filters where
-   *    the keys are the filter names and the values are the filter factories.
-   * @returns {Object} Registered filter instance, or if a map of filters was provided then a map
-   *    of the registered filter instances.
-   */
-  function register(name, factory) {
-    if(isObject(name)) {
-      var filters = {};
-      forEach(name, function(filter, key) {
-        filters[key] = register(key, filter);
-      });
-      return filters;
-    } else {
-      return $provide.factory(name + suffix, factory);
-    }
-  }
-  this.register = register;
-
-  this.$get = ['$injector', function($injector) {
-    return function(name) {
-      return $injector.get(name + suffix);
-    };
-  }];
-
-  ////////////////////////////////////////
-  
-  /* global
-    currencyFilter: false,
-    dateFilter: false,
-    filterFilter: false,
-    jsonFilter: false,
-    limitToFilter: false,
-    lowercaseFilter: false,
-    numberFilter: false,
-    orderByFilter: false,
-    uppercaseFilter: false,
-  */
-
-  register('currency', currencyFilter);
-  register('date', dateFilter);
-  register('filter', filterFilter);
-  register('json', jsonFilter);
-  register('limitTo', limitToFilter);
-  register('lowercase', lowercaseFilter);
-  register('number', numberFilter);
-  register('orderBy', orderByFilter);
-  register('uppercase', uppercaseFilter);
-}
-
-/**
- * @ngdoc filter
- * @name ng.filter:filter
- * @function
- *
- * @description
- * Selects a subset of items from `array` and returns it as a new array.
- *
- * @param {Array} array The source array.
- * @param {string|Object|function()} expression The predicate to be used for selecting items from
- *   `array`.
- *
- *   Can be one of:
- *
- *   - `string`: Predicate that results in a substring match using the value of `expression`
- *     string. All strings or objects with string properties in `array` that contain this string
- *     will be returned. The predicate can be negated by prefixing the string with `!`.
- *
- *   - `Object`: A pattern object can be used to filter specific properties on objects contained
- *     by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items
- *     which have property `name` containing "M" and property `phone` containing "1". A special
- *     property name `$` can be used (as in `{$:"text"}`) to accept a match against any
- *     property of the object. That's equivalent to the simple substring match with a `string`
- *     as described above.
- *
- *   - `function`: A predicate function can be used to write arbitrary filters. The function is
- *     called for each element of `array`. The final result is an array of those elements that
- *     the predicate returned true for.
- *
- * @param {function(expected, actual)|true|undefined} comparator Comparator which is used in
- *     determining if the expected value (from the filter expression) and actual value (from
- *     the object in the array) should be considered a match.
- *
- *   Can be one of:
- *
- *     - `function(expected, actual)`:
- *       The function will be given the object value and the predicate value to compare and
- *       should return true if the item should be included in filtered result.
- *
- *     - `true`: A shorthand for `function(expected, actual) { return angular.equals(expected, actual)}`.
- *       this is essentially strict comparison of expected and actual.
- *
- *     - `false|undefined`: A short hand for a function which will look for a substring match in case
- *       insensitive way.
- *
- * @example
-   <doc:example>
-     <doc:source>
-       <div ng-init="friends = [{name:'John', phone:'555-1276'},
-                                {name:'Mary', phone:'800-BIG-MARY'},
-                                {name:'Mike', phone:'555-4321'},
-                                {name:'Adam', phone:'555-5678'},
-                                {name:'Julie', phone:'555-8765'},
-                                {name:'Juliette', phone:'555-5678'}]"></div>
-
-       Search: <input ng-model="searchText">
-       <table id="searchTextResults">
-         <tr><th>Name</th><th>Phone</th></tr>
-         <tr ng-repeat="friend in friends | filter:searchText">
-           <td>{{friend.name}}</td>
-           <td>{{friend.phone}}</td>
-         </tr>
-       </table>
-       <hr>
-       Any: <input ng-model="search.$"> <br>
-       Name only <input ng-model="search.name"><br>
-       Phone only <input ng-model="search.phone"><br>
-       Equality <input type="checkbox" ng-model="strict"><br>
-       <table id="searchObjResults">
-         <tr><th>Name</th><th>Phone</th></tr>
-         <tr ng-repeat="friend in friends | filter:search:strict">
-           <td>{{friend.name}}</td>
-           <td>{{friend.phone}}</td>
-         </tr>
-       </table>
-     </doc:source>
-     <doc:scenario>
-       it('should search across all fields when filtering with a string', function() {
-         input('searchText').enter('m');
-         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).
-           toEqual(['Mary', 'Mike', 'Adam']);
-
-         input('searchText').enter('76');
-         expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).
-           toEqual(['John', 'Julie']);
-       });
-
-       it('should search in specific fields when filtering with a predicate object', function() {
-         input('search.$').enter('i');
-         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).
-           toEqual(['Mary', 'Mike', 'Julie', 'Juliette']);
-       });
-       it('should use a equal comparison when comparator is true', function() {
-         input('search.name').enter('Julie');
-         input('strict').check();
-         expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')).
-           toEqual(['Julie']);
-       });
-     </doc:scenario>
-   </doc:example>
- */
-function filterFilter() {
-  return function(array, expression, comparator) {
-    if (!isArray(array)) return array;
-
-    var comparatorType = typeof(comparator),
-        predicates = [];
-
-    predicates.check = function(value) {
-      for (var j = 0; j < predicates.length; j++) {
-        if(!predicates[j](value)) {
-          return false;
-        }
-      }
-      return true;
-    };
-
-    if (comparatorType !== 'function') {
-      if (comparatorType === 'boolean' && comparator) {
-        comparator = function(obj, text) {
-          return angular.equals(obj, text);
-        };
-      } else {
-        comparator = function(obj, text) {
-          text = (''+text).toLowerCase();
-          return (''+obj).toLowerCase().indexOf(text) > -1;
-        };
-      }
-    }
-
-    var search = function(obj, text){
-      if (typeof text == 'string' && text.charAt(0) === '!') {
-        return !search(obj, text.substr(1));
-      }
-      switch (typeof obj) {
-        case "boolean":
-        case "number":
-        case "string":
-          return comparator(obj, text);
-        case "object":
-          switch (typeof text) {
-            case "object":
-              return comparator(obj, text);
-            default:
-              for ( var objKey in obj) {
-                if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
-                  return true;
-                }
-              }
-              break;
-          }
-          return false;
-        case "array":
-          for ( var i = 0; i < obj.length; i++) {
-            if (search(obj[i], text)) {
-              return true;
-            }
-          }
-          return false;
-        default:
-          return false;
-      }
-    };
-    switch (typeof expression) {
-      case "boolean":
-      case "number":
-      case "string":
-        // Set up expression object and fall through
-        expression = {$:expression};
-        // jshint -W086
-      case "object":
-        // jshint +W086
-        for (var key_4 in expression) {
-          if (key_4 == '$') {
-            (function() {
-              if (!expression[key_4]) return;
-              var path = key_4;
-              predicates.push(function(value) {
-                return search(value, expression[path]);
-              });
-            })();
-          } else {
-            (function() {
-              if (typeof(expression[key_4]) == 'undefined') { return; }
-              var path = key_4;
-              predicates.push(function(value) {
-                return search(getter(value,path), expression[path]);
-              });
-            })();
-          }
-        }
-        break;
-      case 'function':
-        predicates.push(expression);
-        break;
-      default:
-        return array;
-    }
-    var filtered = [];
-    for ( var j = 0; j < array.length; j++) {
-      var value = array[j];
-      if (predicates.check(value)) {
-        filtered.push(value);
-      }
-    }
-    return filtered;
-  };
-}
-
-/**
- * @ngdoc filter
- * @name ng.filter:currency
- * @function
- *
- * @description
- * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default
- * symbol for current locale is used.
- *
- * @param {number} amount Input to filter.
- * @param {string=} symbol Currency symbol or identifier to be displayed.
- * @returns {string} Formatted number.
- *
- *
- * @example
-   <doc:example>
-     <doc:source>
-       <script>
-         function Ctrl($scope) {
-           $scope.amount = 1234.56;
-         }
-       </script>
-       <div ng-controller="Ctrl">
-         <input type="number" ng-model="amount"> <br>
-         default currency symbol ($): {{amount | currency}}<br>
-         custom currency identifier (USD$): {{amount | currency:"USD$"}}
-       </div>
-     </doc:source>
-     <doc:scenario>
-       it('should init with 1234.56', function() {
-         expect(binding('amount | currency')).toBe('$1,234.56');
-         expect(binding('amount | currency:"USD$"')).toBe('USD$1,234.56');
-       });
-       it('should update', function() {
-         input('amount').enter('-1234');
-         expect(binding('amount | currency')).toBe('($1,234.00)');
-         expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)');
-       });
-     </doc:scenario>
-   </doc:example>
- */
-currencyFilter.$inject = ['$locale'];
-function currencyFilter($locale) {
-  var formats = $locale.NUMBER_FORMATS;
-  return function(amount, currencySymbol){
-    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM;
-    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2).
-                replace(/\u00A4/g, currencySymbol);
-  };
-}
-
-/**
- * @ngdoc filter
- * @name ng.filter:number
- * @function
- *
- * @description
- * Formats a number as text.
- *
- * If the input is not a number an empty string is returned.
- *
- * @param {number|string} number Number to format.
- * @param {(number|string)=} fractionSize Number of decimal places to round the number to.
- * If this is not provided then the fraction size is computed from the current locale's number
- * formatting pattern. In the case of the default locale, it will be 3.
- * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
- *
- * @example
-   <doc:example>
-     <doc:source>
-       <script>
-         function Ctrl($scope) {
-           $scope.val = 1234.56789;
-         }
-       </script>
-       <div ng-controller="Ctrl">
-         Enter number: <input ng-model='val'><br>
-         Default formatting: {{val | number}}<br>
-         No fractions: {{val | number:0}}<br>
-         Negative number: {{-val | number:4}}
-       </div>
-     </doc:source>
-     <doc:scenario>
-       it('should format numbers', function() {
-         expect(binding('val | number')).toBe('1,234.568');
-         expect(binding('val | number:0')).toBe('1,235');
-         expect(binding('-val | number:4')).toBe('-1,234.5679');
-       });
-
-       it('should update', function() {
-         input('val').enter('3374.333');
-         expect(binding('val | number')).toBe('3,374.333');
-         expect(binding('val | number:0')).toBe('3,374');
-         expect(binding('-val | number:4')).toBe('-3,374.3330');
-       });
-     </doc:scenario>
-   </doc:example>
- */
-
-
-numberFilter.$inject = ['$locale'];
-function numberFilter($locale) {
-  var formats = $locale.NUMBER_FORMATS;
-  return function(number, fractionSize) {
-    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP,
-      fractionSize);
-  };
-}
-
-var DECIMAL_SEP = '.';
-function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {
-  if (isNaN(number) || !isFinite(number)) return '';
-
-  var isNegative = number < 0;
-  number = Math.abs(number);
-  var numStr = number + '',
-      formatedText = '',
-      parts = [];
-
-  var hasExponent = false;
-  if (numStr.indexOf('e') !== -1) {
-    var match = numStr.match(/([\d\.]+)e(-?)(\d+)/);
-    if (match && match[2] == '-' && match[3] > fractionSize + 1) {
-      numStr = '0';
-    } else {
-      formatedText = numStr;
-      hasExponent = true;
-    }
-  }
-
-  if (!hasExponent) {
-    var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length;
-
-    // determine fractionSize if it is not specified
-    if (isUndefined(fractionSize)) {
-      fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac);
-    }
-
-    var pow = Math.pow(10, fractionSize);
-    number = Math.round(number * pow) / pow;
-    var fraction = ('' + number).split(DECIMAL_SEP);
-    var whole = fraction[0];
-    fraction = fraction[1] || '';
-
-    var i, pos = 0,
-        lgroup = pattern.lgSize,
-        group = pattern.gSize;
-
-    if (whole.length >= (lgroup + group)) {
-      pos = whole.length - lgroup;
-      for (i = 0; i < pos; i++) {
-        if ((pos - i)%group === 0 && i !== 0) {
-          formatedText += groupSep;
-        }
-        formatedText += whole.charAt(i);
-      }
-    }
-
-    for (i = pos; i < whole.length; i++) {
-      if ((whole.length - i)%lgroup === 0 && i !== 0) {
-        formatedText += groupSep;
-      }
-      formatedText += whole.charAt(i);
-    }
-
-    // format fraction part.
-    while(fraction.length < fractionSize) {
-      fraction += '0';
-    }
-
-    if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize);
-  } else {
-
-    if (fractionSize > 0 && number > -1 && number < 1) {
-      formatedText = number.toFixed(fractionSize);
-    }
-  }
-
-  parts.push(isNegative ? pattern.negPre : pattern.posPre);
-  parts.push(formatedText);
-  parts.push(isNegative ? pattern.negSuf : pattern.posSuf);
-  return parts.join('');
-}
-
-function padNumber(num, digits, trim) {
-  var neg = '';
-  if (num < 0) {
-    neg =  '-';
-    num = -num;
-  }
-  num = '' + num;
-  while(num.length < digits) num = '0' + num;
-  if (trim)
-    num = num.substr(num.length - digits);
-  return neg + num;
-}
-
-
-function dateGetter(name, size, offset, trim) {
-  offset = offset || 0;
-  return function(date) {
-    var value = date['get' + name]();
-    if (offset > 0 || value > -offset)
-      value += offset;
-    if (value === 0 && offset == -12 ) value = 12;
-    return padNumber(value, size, trim);
-  };
-}
-
-function dateStrGetter(name, shortForm) {
-  return function(date, formats) {
-    var value = date['get' + name]();
-    var get = uppercase(shortForm ? ('SHORT' + name) : name);
-
-    return formats[get][value];
-  };
-}
-
-function timeZoneGetter(date) {
-  var zone = -1 * date.getTimezoneOffset();
-  var paddedZone = (zone >= 0) ? "+" : "";
-
-  paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) +
-                padNumber(Math.abs(zone % 60), 2);
-
-  return paddedZone;
-}
-
-function ampmGetter(date, formats) {
-  return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
-}
-
-var DATE_FORMATS = {
-  yyyy: dateGetter('FullYear', 4),
-    yy: dateGetter('FullYear', 2, 0, true),
-     y: dateGetter('FullYear', 1),
-  MMMM: dateStrGetter('Month'),
-   MMM: dateStrGetter('Month', true),
-    MM: dateGetter('Month', 2, 1),
-     M: dateGetter('Month', 1, 1),
-    dd: dateGetter('Date', 2),
-     d: dateGetter('Date', 1),
-    HH: dateGetter('Hours', 2),
-     H: dateGetter('Hours', 1),
-    hh: dateGetter('Hours', 2, -12),
-     h: dateGetter('Hours', 1, -12),
-    mm: dateGetter('Minutes', 2),
-     m: dateGetter('Minutes', 1),
-    ss: dateGetter('Seconds', 2),
-     s: dateGetter('Seconds', 1),
-     // while ISO 8601 requires fractions to be prefixed with `.` or `,`
-     // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions
-   sss: dateGetter('Milliseconds', 3),
-  EEEE: dateStrGetter('Day'),
-   EEE: dateStrGetter('Day', true),
-     a: ampmGetter,
-     Z: timeZoneGetter
-};
-
-var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,
-    NUMBER_STRING = /^\-?\d+$/;
-
-/**
- * @ngdoc filter
- * @name ng.filter:date
- * @function
- *
- * @description
- *   Formats `date` to a string based on the requested `format`.
- *
- *   `format` string can be composed of the following elements:
- *
- *   * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
- *   * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
- *   * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
- *   * `'MMMM'`: Month in year (January-December)
- *   * `'MMM'`: Month in year (Jan-Dec)
- *   * `'MM'`: Month in year, padded (01-12)
- *   * `'M'`: Month in year (1-12)
- *   * `'dd'`: Day in month, padded (01-31)
- *   * `'d'`: Day in month (1-31)
- *   * `'EEEE'`: Day in Week,(Sunday-Saturday)
- *   * `'EEE'`: Day in Week, (Sun-Sat)
- *   * `'HH'`: Hour in day, padded (00-23)
- *   * `'H'`: Hour in day (0-23)
- *   * `'hh'`: Hour in am/pm, padded (01-12)
- *   * `'h'`: Hour in am/pm, (1-12)
- *   * `'mm'`: Minute in hour, padded (00-59)
- *   * `'m'`: Minute in hour (0-59)
- *   * `'ss'`: Second in minute, padded (00-59)
- *   * `'s'`: Second in minute (0-59)
- *   * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)
- *   * `'a'`: am/pm marker
- *   * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
- *
- *   `format` string can also be one of the following predefined
- *   {@link guide/i18n localizable formats}:
- *
- *   * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
- *     (e.g. Sep 3, 2010 12:05:08 pm)
- *   * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US  locale (e.g. 9/3/10 12:05 pm)
- *   * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US  locale
- *     (e.g. Friday, September 3, 2010)
- *   * `'longDate'`: equivalent to `'MMMM d, y'` for en_US  locale (e.g. September 3, 2010)
- *   * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US  locale (e.g. Sep 3, 2010)
- *   * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10)
- *   * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm)
- *   * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm)
- *
- *   `format` string can contain literal values. These need to be quoted with single quotes (e.g.
- *   `"h 'in the morning'"`). In order to output single quote, use two single quotes in a sequence
- *   (e.g. `"h 'o''clock'"`).
- *
- * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or
- *    number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and its
- *    shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is
- *    specified in the string input, the time is considered to be in the local timezone.
- * @param {string=} format Formatting rules (see Description). If not specified,
- *    `mediumDate` is used.
- * @returns {string} Formatted string or the input if input is not recognized as date/millis.
- *
- * @example
-   <doc:example>
-     <doc:source>
-       <span ng-non-bindable>{{1288323623006 | date:'medium'}}</span>:
-           {{1288323623006 | date:'medium'}}<br>
-       <span ng-non-bindable>{{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}</span>:
-          {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}<br>
-       <span ng-non-bindable>{{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}</span>:
-          {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}<br>
-     </doc:source>
-     <doc:scenario>
-       it('should format date', function() {
-         expect(binding("1288323623006 | date:'medium'")).
-            toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/);
-         expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")).
-            toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/);
-         expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")).
-            toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/);
-       });
-     </doc:scenario>
-   </doc:example>
- */
-dateFilter.$inject = ['$locale'];
-function dateFilter($locale) {
-
-
-  var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
-                     // 1        2       3         4          5          6          7          8  9     10      11
-  function jsonStringToDate(string) {
-    var match;
-    if (match = string.match(R_ISO8601_STR)) {
-      var date = new Date(0),
-          tzHour = 0,
-          tzMin  = 0,
-          dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
-          timeSetter = match[8] ? date.setUTCHours : date.setHours;
-
-      if (match[9]) {
-        tzHour = int(match[9] + match[10]);
-        tzMin = int(match[9] + match[11]);
-      }
-      dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
-      var h = int(match[4]||0) - tzHour;
-      var m = int(match[5]||0) - tzMin;
-      var s = int(match[6]||0);
-      var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000);
-      timeSetter.call(date, h, m, s, ms);
-      return date;
-    }
-    return string;
-  }
-
-
-  return function(date, format) {
-    var text = '',
-        parts = [],
-        fn, match;
-
-    format = format || 'mediumDate';
-    format = $locale.DATETIME_FORMATS[format] || format;
-    if (isString(date)) {
-      if (NUMBER_STRING.test(date)) {
-        date = int(date);
-      } else {
-        date = jsonStringToDate(date);
-      }
-    }
-
-    if (isNumber(date)) {
-      date = new Date(date);
-    }
-
-    if (!isDate(date)) {
-      return date;
-    }
-
-    while(format) {
-      match = DATE_FORMATS_SPLIT.exec(format);
-      if (match) {
-        parts = concat(parts, match, 1);
-        format = parts.pop();
-      } else {
-        parts.push(format);
-        format = null;
-      }
-    }
-
-    forEach(parts, function(value){
-      fn = DATE_FORMATS[value];
-      text += fn ? fn(date, $locale.DATETIME_FORMATS)
-                 : value.replace(/(^'|'$)/g, '').replace(/''/g, "'");
-    });
-
-    return text;
-  };
-}
-
-
-/**
- * @ngdoc filter
- * @name ng.filter:json
- * @function
- *
- * @description
- *   Allows you to convert a JavaScript object into JSON string.
- *
- *   This filter is mostly useful for debugging. When using the double curly {{value}} notation
- *   the binding is automatically converted to JSON.
- *
- * @param {*} object Any JavaScript object (including arrays and primitive types) to filter.
- * @returns {string} JSON string.
- *
- *
- * @example:
-   <doc:example>
-     <doc:source>
-       <pre>{{ {'name':'value'} | json }}</pre>
-     </doc:source>
-     <doc:scenario>
-       it('should jsonify filtered objects', function() {
-         expect(binding("{'name':'value'}")).toMatch(/\{\n  "name": ?"value"\n}/);
-       });
-     </doc:scenario>
-   </doc:example>
- *
- */
-function jsonFilter() {
-  return function(object) {
-    return toJson(object, true);
-  };
-}
-
-
-/**
- * @ngdoc filter
- * @name ng.filter:lowercase
- * @function
- * @description
- * Converts string to lowercase.
- * @see angular.lowercase
- */
-var lowercaseFilter = valueFn(lowercase);
-
-
-/**
- * @ngdoc filter
- * @name ng.filter:uppercase
- * @function
- * @description
- * Converts string to uppercase.
- * @see angular.uppercase
- */
-var uppercaseFilter = valueFn(uppercase);
-
-/**
- * @ngdoc function
- * @name ng.filter:limitTo
- * @function
- *
- * @description
- * Creates a new array or string containing only a specified number of elements. The elements
- * are taken from either the beginning or the end of the source array or string, as specified by
- * the value and sign (positive or negative) of `limit`.
- *
- * @param {Array|string} input Source array or string to be limited.
- * @param {string|number} limit The length of the returned array or string. If the `limit` number 
- *     is positive, `limit` number of items from the beginning of the source array/string are copied.
- *     If the number is negative, `limit` number  of items from the end of the source array/string 
- *     are copied. The `limit` will be trimmed if it exceeds `array.length`
- * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
- *     had less than `limit` elements.
- *
- * @example
-   <doc:example>
-     <doc:source>
-       <script>
-         function Ctrl($scope) {
-           $scope.numbers = [1,2,3,4,5,6,7,8,9];
-           $scope.letters = "abcdefghi";
-           $scope.numLimit = 3;
-           $scope.letterLimit = 3;
-         }
-       </script>
-       <div ng-controller="Ctrl">
-         Limit {{numbers}} to: <input type="integer" ng-model="numLimit">
-         <p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
-         Limit {{letters}} to: <input type="integer" ng-model="letterLimit">
-         <p>Output letters: {{ letters | limitTo:letterLimit }}</p>
-       </div>
-     </doc:source>
-     <doc:scenario>
-       it('should limit the number array to first three items', function() {
-         expect(element('.doc-example-live input[ng-model=numLimit]').val()).toBe('3');
-         expect(element('.doc-example-live input[ng-model=letterLimit]').val()).toBe('3');
-         expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3]');
-         expect(binding('letters | limitTo:letterLimit')).toEqual('abc');
-       });
-
-       it('should update the output when -3 is entered', function() {
-         input('numLimit').enter(-3);
-         input('letterLimit').enter(-3);
-         expect(binding('numbers | limitTo:numLimit')).toEqual('[7,8,9]');
-         expect(binding('letters | limitTo:letterLimit')).toEqual('ghi');
-       });
-
-       it('should not exceed the maximum size of input array', function() {
-         input('numLimit').enter(100);
-         input('letterLimit').enter(100);
-         expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3,4,5,6,7,8,9]');
-         expect(binding('letters | limitTo:letterLimit')).toEqual('abcdefghi');
-       });
-     </doc:scenario>
-   </doc:example>
- */
-function limitToFilter(){
-  return function(input, limit) {
-    if (!isArray(input) && !isString(input)) return input;
-    
-    limit = int(limit);
-
-    if (isString(input)) {
-      //NaN check on limit
-      if (limit) {
-        return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length);
-      } else {
-        return "";
-      }
-    }
-
-    var out = [],
-      i, n;
-
-    // if abs(limit) exceeds maximum length, trim it
-    if (limit > input.length)
-      limit = input.length;
-    else if (limit < -input.length)
-      limit = -input.length;
-
-    if (limit > 0) {
-      i = 0;
-      n = limit;
-    } else {
-      i = input.length + limit;
-      n = input.length;
-    }
-
-    for (; i<n; i++) {
-      out.push(input[i]);
-    }
-
-    return out;
-  };
-}
-
-/**
- * @ngdoc function
- * @name ng.filter:orderBy
- * @function
- *
- * @description
- * Orders a specified `array` by the `expression` predicate.
- *
- * @param {Array} array The array to sort.
- * @param {function(*)|string|Array.<(function(*)|string)>} expression A predicate to be
- *    used by the comparator to determine the order of elements.
- *
- *    Can be one of:
- *
- *    - `function`: Getter function. The result of this function will be sorted using the
- *      `<`, `=`, `>` operator.
- *    - `string`: An Angular expression which evaluates to an object to order by, such as 'name'
- *      to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control
- *      ascending or descending sort order (for example, +name or -name).
- *    - `Array`: An array of function or string predicates. The first predicate in the array
- *      is used for sorting, but when two items are equivalent, the next predicate is used.
- *
- * @param {boolean=} reverse Reverse the order the array.
- * @returns {Array} Sorted copy of the source array.
- *
- * @example
-   <doc:example>
-     <doc:source>
-       <script>
-         function Ctrl($scope) {
-           $scope.friends =
-               [{name:'John', phone:'555-1212', age:10},
-                {name:'Mary', phone:'555-9876', age:19},
-                {name:'Mike', phone:'555-4321', age:21},
-                {name:'Adam', phone:'555-5678', age:35},
-                {name:'Julie', phone:'555-8765', age:29}]
-           $scope.predicate = '-age';
-         }
-       </script>
-       <div ng-controller="Ctrl">
-         <pre>Sorting predicate = {{predicate}}; reverse = {{reverse}}</pre>
-         <hr/>
-         [ <a href="" ng-click="predicate=''">unsorted</a> ]
-         <table class="friend">
-           <tr>
-             <th><a href="" ng-click="predicate = 'name'; reverse=false">Name</a>
-                 (<a href="" ng-click="predicate = '-name'; reverse=false">^</a>)</th>
-             <th><a href="" ng-click="predicate = 'phone'; reverse=!reverse">Phone Number</a></th>
-             <th><a href="" ng-click="predicate = 'age'; reverse=!reverse">Age</a></th>
-           </tr>
-           <tr ng-repeat="friend in friends | orderBy:predicate:reverse">
-             <td>{{friend.name}}</td>
-             <td>{{friend.phone}}</td>
-             <td>{{friend.age}}</td>
-           </tr>
-         </table>
-       </div>
-     </doc:source>
-     <doc:scenario>
-       it('should be reverse ordered by aged', function() {
-         expect(binding('predicate')).toBe('-age');
-         expect(repeater('table.friend', 'friend in friends').column('friend.age')).
-           toEqual(['35', '29', '21', '19', '10']);
-         expect(repeater('table.friend', '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-live a:contains("Name")').click();
-         expect(repeater('table.friend', 'friend in friends').column('friend.name')).
-           toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']);
-         expect(repeater('table.friend', 'friend in friends').column('friend.age')).
-           toEqual(['35', '10', '29', '19', '21']);
-
-         element('.doc-example-live a:contains("Phone")').click();
-         expect(repeater('table.friend', 'friend in friends').column('friend.phone')).
-           toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']);
-         expect(repeater('table.friend', 'friend in friends').column('friend.name')).
-           toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']);
-       });
-     </doc:scenario>
-   </doc:example>
- */
-orderByFilter.$inject = ['$parse'];
-function orderByFilter($parse){
-  return function(array, sortPredicate, reverseOrder) {
-    if (!isArray(array)) return array;
-    if (!sortPredicate) return array;
-    sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
-    sortPredicate = map(sortPredicate, function(predicate){
-      var descending = false, get = predicate || identity;
-      if (isString(predicate)) {
-        if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) {
-          descending = predicate.charAt(0) == '-';
-          predicate = predicate.substring(1);
-        }
-        get = $parse(predicate);
-      }
-      return reverseComparator(function(a,b){
-        return compare(get(a),get(b));
-      }, descending);
-    });
-    var arrayCopy = [];
-    for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
-    return arrayCopy.sort(reverseComparator(comparator, reverseOrder));
-
-    function comparator(o1, o2){
-      for ( var i = 0; i < sortPredicate.length; i++) {
-        var comp = sortPredicate[i](o1, o2);
-        if (comp !== 0) return comp;
-      }
-      return 0;
-    }
-    function reverseComparator(comp, descending) {
-      return toBoolean(descending)
-          ? function(a,b){return comp(b,a);}
-          : comp;
-    }
-    function compare(v1, v2){
-      var t1 = typeof v1;
-      var t2 = typeof v2;
-      if (t1 == t2) {
-        if (t1 == "string") {
-           v1 = v1.toLowerCase();
-           v2 = v2.toLowerCase();
-        }
-        if (v1 === v2) return 0;
-        return v1 < v2 ? -1 : 1;
-      } else {
-        return t1 < t2 ? -1 : 1;
-      }
-    }
-  };
-}
-
-function ngDirective(directive) {
-  if (isFunction(directive)) {
-    directive = {
-      link: directive
-    };
-  }
-  directive.restrict = directive.restrict || 'AC';
-  return valueFn(directive);
-}
-
-/**
- * @ngdoc directive
- * @name ng.directive:a
- * @restrict E
- *
- * @description
- * Modifies the default behavior of the html A tag so that the default action is prevented when
- * the href attribute is empty.
- *
- * This change permits the easy creation of action links with the `ngClick` directive
- * without changing the location or causing page reloads, e.g.:
- * `<a href="" ng-click="list.addItem()">Add Item</a>`
- */
-var htmlAnchorDirective = valueFn({
-  restrict: 'E',
-  compile: function(element, attr) {
-
-    if (msie <= 8) {
-
-      // turn <a href ng-click="..">link</a> into a stylable link in IE
-      // but only if it doesn't have name attribute, in which case it's an anchor
-      if (!attr.href && !attr.name) {
-        attr.$set('href', '');
-      }
-
-      // add a comment node to anchors to workaround IE bug that causes element content to be reset
-      // to new attribute content if attribute is updated with value containing @ and element also
-      // contains value with @
-      // see issue #1949
-      element.append(document.createComment('IE fix'));
-    }
-
-    if (!attr.href && !attr.name) {
-      return function(scope, element) {
-        element.on('click', function(event){
-          // if we have no href url, then don't navigate anywhere.
-          if (!element.attr('href')) {
-            event.preventDefault();
-          }
-        });
-      };
-    }
-  }
-});
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngHref
- * @restrict A
- *
- * @description
- * Using Angular markup like `{{hash}}` in an href attribute will
- * make the link go to the wrong URL if the user clicks it before
- * Angular has a chance to replace the `{{hash}}` markup with its
- * value. Until Angular replaces the markup the link will be broken
- * and will most likely return a 404 error.
- *
- * The `ngHref` directive solves this problem.
- *
- * The wrong way to write it:
- * <pre>
- * <a href="http://www.gravatar.com/avatar/{{hash}}"/>
- * </pre>
- *
- * The correct way to write it:
- * <pre>
- * <a ng-href="http://www.gravatar.com/avatar/{{hash}}"/>
- * </pre>
- *
- * @element A
- * @param {template} ngHref any string which can contain `{{}}` markup.
- *
- * @example
- * This example shows various combinations of `href`, `ng-href` and `ng-click` attributes
- * in links and their different behaviors:
-    <doc:example>
-      <doc:source>
-        <input ng-model="value" /><br />
-        <a id="link-1" href ng-click="value = 1">link 1</a> (link, don't reload)<br />
-        <a id="link-2" href="" ng-click="value = 2">link 2</a> (link, don't reload)<br />
-        <a id="link-3" ng-href="/{{'123'}}">link 3</a> (link, reload!)<br />
-        <a id="link-4" href="" name="xx" ng-click="value = 4">anchor</a> (link, don't reload)<br />
-        <a id="link-5" name="xxx" ng-click="value = 5">anchor</a> (no link)<br />
-        <a id="link-6" ng-href="{{value}}">link</a> (link, change location)
-      </doc:source>
-      <doc:scenario>
-        it('should execute ng-click but not reload when href without value', function() {
-          element('#link-1').click();
-          expect(input('value').val()).toEqual('1');
-          expect(element('#link-1').attr('href')).toBe("");
-        });
-
-        it('should execute ng-click but not reload when href empty string', function() {
-          element('#link-2').click();
-          expect(input('value').val()).toEqual('2');
-          expect(element('#link-2').attr('href')).toBe("");
-        });
-
-        it('should execute ng-click and change url when ng-href specified', function() {
-          expect(element('#link-3').attr('href')).toBe("/123");
-
-          element('#link-3').click();
-          expect(browser().window().path()).toEqual('/123');
-        });
-
-        it('should execute ng-click but not reload when href empty string and name specified', function() {
-          element('#link-4').click();
-          expect(input('value').val()).toEqual('4');
-          expect(element('#link-4').attr('href')).toBe('');
-        });
-
-        it('should execute ng-click but not reload when no href but name specified', function() {
-          element('#link-5').click();
-          expect(input('value').val()).toEqual('5');
-          expect(element('#link-5').attr('href')).toBe(undefined);
-        });
-
-        it('should only change url when only ng-href', function() {
-          input('value').enter('6');
-          expect(element('#link-6').attr('href')).toBe('6');
-
-          element('#link-6').click();
-          expect(browser().location().url()).toEqual('/6');
-        });
-      </doc:scenario>
-    </doc:example>
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngSrc
- * @restrict A
- *
- * @description
- * Using Angular markup like `{{hash}}` in a `src` attribute doesn't
- * work right: The browser will fetch from the URL with the literal
- * text `{{hash}}` until Angular replaces the expression inside
- * `{{hash}}`. The `ngSrc` directive solves this problem.
- *
- * The buggy way to write it:
- * <pre>
- * <img src="http://www.gravatar.com/avatar/{{hash}}"/>
- * </pre>
- *
- * The correct way to write it:
- * <pre>
- * <img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
- * </pre>
- *
- * @element IMG
- * @param {template} ngSrc any string which can contain `{{}}` markup.
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngSrcset
- * @restrict A
- *
- * @description
- * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
- * work right: The browser will fetch from the URL with the literal
- * text `{{hash}}` until Angular replaces the expression inside
- * `{{hash}}`. The `ngSrcset` directive solves this problem.
- *
- * The buggy way to write it:
- * <pre>
- * <img srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
- * </pre>
- *
- * The correct way to write it:
- * <pre>
- * <img ng-srcset="http://www.gravatar.com/avatar/{{hash}} 2x"/>
- * </pre>
- *
- * @element IMG
- * @param {template} ngSrcset any string which can contain `{{}}` markup.
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngDisabled
- * @restrict A
- *
- * @description
- *
- * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs:
- * <pre>
- * <div ng-init="scope = { isDisabled: false }">
- *  <button disabled="{{scope.isDisabled}}">Disabled</button>
- * </div>
- * </pre>
- *
- * The HTML specification does not require browsers to preserve the values of boolean attributes
- * such as disabled. (Their presence means true and their absence means false.)
- * If we put an Angular interpolation expression into such an attribute then the
- * binding information would be lost when the browser removes the attribute.
- * The `ngDisabled` directive solves this problem for the `disabled` attribute.
- * This complementary directive is not removed by the browser and so provides
- * a permanent reliable place to store the binding information.
- *
- * @example
-    <doc:example>
-      <doc:source>
-        Click me to toggle: <input type="checkbox" ng-model="checked"><br/>
-        <button ng-model="button" ng-disabled="checked">Button</button>
-      </doc:source>
-      <doc:scenario>
-        it('should toggle button', function() {
-          expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy();
-          input('checked').check();
-          expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy();
-        });
-      </doc:scenario>
-    </doc:example>
- *
- * @element INPUT
- * @param {expression} ngDisabled If the {@link guide/expression expression} is truthy, 
- *     then special attribute "disabled" will be set on the element
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngChecked
- * @restrict A
- *
- * @description
- * The HTML specification does not require browsers to preserve the values of boolean attributes
- * such as checked. (Their presence means true and their absence means false.)
- * If we put an Angular interpolation expression into such an attribute then the
- * binding information would be lost when the browser removes the attribute.
- * The `ngChecked` directive solves this problem for the `checked` attribute.
- * This complementary directive is not removed by the browser and so provides
- * a permanent reliable place to store the binding information.
- * @example
-    <doc:example>
-      <doc:source>
-        Check me to check both: <input type="checkbox" ng-model="master"><br/>
-        <input id="checkSlave" type="checkbox" ng-checked="master">
-      </doc:source>
-      <doc:scenario>
-        it('should check both checkBoxes', function() {
-          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy();
-          input('master').check();
-          expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy();
-        });
-      </doc:scenario>
-    </doc:example>
- *
- * @element INPUT
- * @param {expression} ngChecked If the {@link guide/expression expression} is truthy, 
- *     then special attribute "checked" will be set on the element
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngReadonly
- * @restrict A
- *
- * @description
- * The HTML specification does not require browsers to preserve the values of boolean attributes
- * such as readonly. (Their presence means true and their absence means false.)
- * If we put an Angular interpolation expression into such an attribute then the
- * binding information would be lost when the browser removes the attribute.
- * The `ngReadonly` directive solves this problem for the `readonly` attribute.
- * This complementary directive is not removed by the browser and so provides
- * a permanent reliable place to store the binding information.
-
- * @example
-    <doc:example>
-      <doc:source>
-        Check me to make text readonly: <input type="checkbox" ng-model="checked"><br/>
-        <input type="text" ng-readonly="checked" value="I'm Angular"/>
-      </doc:source>
-      <doc:scenario>
-        it('should toggle readonly attr', function() {
-          expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy();
-          input('checked').check();
-          expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy();
-        });
-      </doc:scenario>
-    </doc:example>
- *
- * @element INPUT
- * @param {expression} ngReadonly If the {@link guide/expression expression} is truthy, 
- *     then special attribute "readonly" will be set on the element
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngSelected
- * @restrict A
- *
- * @description
- * The HTML specification does not require browsers to preserve the values of boolean attributes
- * such as selected. (Their presence means true and their absence means false.)
- * If we put an Angular interpolation expression into such an attribute then the
- * binding information would be lost when the browser removes the attribute.
- * The `ngSelected` directive solves this problem for the `selected` atttribute.
- * This complementary directive is not removed by the browser and so provides
- * a permanent reliable place to store the binding information.
- * @example
-    <doc:example>
-      <doc:source>
-        Check me to select: <input type="checkbox" ng-model="selected"><br/>
-        <select>
-          <option>Hello!</option>
-          <option id="greet" ng-selected="selected">Greetings!</option>
-        </select>
-      </doc:source>
-      <doc:scenario>
-        it('should select Greetings!', function() {
-          expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy();
-          input('selected').check();
-          expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy();
-        });
-      </doc:scenario>
-    </doc:example>
- *
- * @element OPTION
- * @param {expression} ngSelected If the {@link guide/expression expression} is truthy, 
- *     then special attribute "selected" will be set on the element
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngOpen
- * @restrict A
- *
- * @description
- * The HTML specification does not require browsers to preserve the values of boolean attributes
- * such as open. (Their presence means true and their absence means false.)
- * If we put an Angular interpolation expression into such an attribute then the
- * binding information would be lost when the browser removes the attribute.
- * The `ngOpen` directive solves this problem for the `open` attribute.
- * This complementary directive is not removed by the browser and so provides
- * a permanent reliable place to store the binding information.
-
- *
- * @example
-     <doc:example>
-       <doc:source>
-         Check me check multiple: <input type="checkbox" ng-model="open"><br/>
-         <details id="details" ng-open="open">
-            <summary>Show/Hide me</summary>
-         </details>
-       </doc:source>
-       <doc:scenario>
-         it('should toggle open', function() {
-           expect(element('#details').prop('open')).toBeFalsy();
-           input('open').check();
-           expect(element('#details').prop('open')).toBeTruthy();
-         });
-       </doc:scenario>
-     </doc:example>
- *
- * @element DETAILS
- * @param {expression} ngOpen If the {@link guide/expression expression} is truthy, 
- *     then special attribute "open" will be set on the element
- */
-
-var ngAttributeAliasDirectives = {};
-
-
-// boolean attrs are evaluated
-forEach(BOOLEAN_ATTR, function(propName, attrName) {
-  // binding to multiple is not supported
-  if (propName == "multiple") return;
-
-  var normalized = directiveNormalize('ng-' + attrName);
-  ngAttributeAliasDirectives[normalized] = function() {
-    return {
-      priority: 100,
-      compile: function() {
-        return function(scope, element, attr) {
-          scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
-            attr.$set(attrName, !!value);
-          });
-        };
-      }
-    };
-  };
-});
-
-
-// ng-src, ng-srcset, ng-href are interpolated
-forEach(['src', 'srcset', 'href'], function(attrName) {
-  var normalized = directiveNormalize('ng-' + attrName);
-  ngAttributeAliasDirectives[normalized] = function() {
-    return {
-      priority: 99, // it needs to run after the attributes are interpolated
-      link: function(scope, element, attr) {
-        attr.$observe(normalized, function(value) {
-          if (!value)
-             return;
-
-          attr.$set(attrName, value);
-
-          // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
-          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
-          // to set the property as well to achieve the desired effect.
-          // we use attr[attrName] value since $set can sanitize the url.
-          if (msie) element.prop(attrName, attr[attrName]);
-        });
-      }
-    };
-  };
-});
-
-/* global -nullFormCtrl */
-var nullFormCtrl = {
-  $addControl: noop,
-  $removeControl: noop,
-  $setValidity: noop,
-  $setDirty: noop,
-  $setPristine: noop
-};
-
-/**
- * @ngdoc object
- * @name ng.directive:form.FormController
- *
- * @property {boolean} $pristine True if user has not interacted with the form yet.
- * @property {boolean} $dirty True if user has already interacted with the form.
- * @property {boolean} $valid True if all of the containing forms and controls are valid.
- * @property {boolean} $invalid True if at least one containing control or form is invalid.
- *
- * @property {Object} $error Is an object hash, containing references to all invalid controls or
- *  forms, where:
- *
- *  - keys are validation tokens (error names),
- *  - values are arrays of controls or forms that are invalid for given error name.
- *
- *
- *  Built-in validation tokens:
- *
- *  - `email`
- *  - `max`
- *  - `maxlength`
- *  - `min`
- *  - `minlength`
- *  - `number`
- *  - `pattern`
- *  - `required`
- *  - `url`
- * 
- * @description
- * `FormController` keeps track of all its controls and nested forms as well as state of them,
- * such as being valid/invalid or dirty/pristine.
- *
- * Each {@link ng.directive:form form} directive creates an instance
- * of `FormController`.
- *
- */
-//asks for $scope to fool the BC controller module
-FormController.$inject = ['$element', '$attrs', '$scope'];
-function FormController(element, attrs) {
-  var form = this,
-      parentForm = element.parent().controller('form') || nullFormCtrl,
-      invalidCount = 0, // used to easily determine if we are valid
-      errors = form.$error = {},
-      controls = [];
-
-  // init state
-  form.$name = attrs.name || attrs.ngForm;
-  form.$dirty = false;
-  form.$pristine = true;
-  form.$valid = true;
-  form.$invalid = false;
-
-  parentForm.$addControl(form);
-
-  // Setup initial state of the control
-  element.addClass(PRISTINE_CLASS);
-  toggleValidCss(true);
-
-  // convenience method for easy toggling of classes
-  function toggleValidCss(isValid, validationErrorKey) {
-    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
-    element.
-      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).
-      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
-  }
-
-  /**
-   * @ngdoc function
-   * @name ng.directive:form.FormController#$addControl
-   * @methodOf ng.directive:form.FormController
-   *
-   * @description
-   * Register a control with the form.
-   *
-   * Input elements using ngModelController do this automatically when they are linked.
-   */
-  form.$addControl = function(control) {
-    // Breaking change - before, inputs whose name was "hasOwnProperty" were quietly ignored
-    // and not added to the scope.  Now we throw an error.
-    assertNotHasOwnProperty(control.$name, 'input');
-    controls.push(control);
-
-    if (control.$name) {
-      form[control.$name] = control;
-    }
-  };
-
-  /**
-   * @ngdoc function
-   * @name ng.directive:form.FormController#$removeControl
-   * @methodOf ng.directive:form.FormController
-   *
-   * @description
-   * Deregister a control from the form.
-   *
-   * Input elements using ngModelController do this automatically when they are destroyed.
-   */
-  form.$removeControl = function(control) {
-    if (control.$name && form[control.$name] === control) {
-      delete form[control.$name];
-    }
-    forEach(errors, function(queue, validationToken) {
-      form.$setValidity(validationToken, true, control);
-    });
-
-    arrayRemove(controls, control);
-  };
-
-  /**
-   * @ngdoc function
-   * @name ng.directive:form.FormController#$setValidity
-   * @methodOf ng.directive:form.FormController
-   *
-   * @description
-   * Sets the validity of a form control.
-   *
-   * This method will also propagate to parent forms.
-   */
-  form.$setValidity = function(validationToken, isValid, control) {
-    var queue = errors[validationToken];
-
-    if (isValid) {
-      if (queue) {
-        arrayRemove(queue, control);
-        if (!queue.length) {
-          invalidCount--;
-          if (!invalidCount) {
-            toggleValidCss(isValid);
-            form.$valid = true;
-            form.$invalid = false;
-          }
-          errors[validationToken] = false;
-          toggleValidCss(true, validationToken);
-          parentForm.$setValidity(validationToken, true, form);
-        }
-      }
-
-    } else {
-      if (!invalidCount) {
-        toggleValidCss(isValid);
-      }
-      if (queue) {
-        if (includes(queue, control)) return;
-      } else {
-        errors[validationToken] = queue = [];
-        invalidCount++;
-        toggleValidCss(false, validationToken);
-        parentForm.$setValidity(validationToken, false, form);
-      }
-      queue.push(control);
-
-      form.$valid = false;
-      form.$invalid = true;
-    }
-  };
-
-  /**
-   * @ngdoc function
-   * @name ng.directive:form.FormController#$setDirty
-   * @methodOf ng.directive:form.FormController
-   *
-   * @description
-   * Sets the form to a dirty state.
-   *
-   * This method can be called to add the 'ng-dirty' class and set the form to a dirty
-   * state (ng-dirty class). This method will also propagate to parent forms.
-   */
-  form.$setDirty = function() {
-    element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);
-    form.$dirty = true;
-    form.$pristine = false;
-    parentForm.$setDirty();
-  };
-
-  /**
-   * @ngdoc function
-   * @name ng.directive:form.FormController#$setPristine
-   * @methodOf ng.directive:form.FormController
-   *
-   * @description
-   * Sets the form to its pristine state.
-   *
-   * This method can be called to remove the 'ng-dirty' class and set the form to its pristine
-   * state (ng-pristine class). This method will also propagate to all the controls contained
-   * in this form.
-   *
-   * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
-   * saving or resetting it.
-   */
-  form.$setPristine = function () {
-    element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
-    form.$dirty = false;
-    form.$pristine = true;
-    forEach(controls, function(control) {
-      control.$setPristine();
-    });
-  };
-}
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngForm
- * @restrict EAC
- *
- * @description
- * Nestable alias of {@link ng.directive:form `form`} directive. HTML
- * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
- * sub-group of controls needs to be determined.
- *
- * @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
- *                       related scope, under this name.
- *
- */
-
- /**
- * @ngdoc directive
- * @name ng.directive:form
- * @restrict E
- *
- * @description
- * Directive that instantiates
- * {@link ng.directive:form.FormController FormController}.
- *
- * If the `name` attribute is specified, the form controller is published onto the current scope under
- * this name.
- *
- * # Alias: {@link ng.directive:ngForm `ngForm`}
- *
- * In Angular forms can be nested. This means that the outer form is valid when all of the child
- * forms are valid as well. However, browsers do not allow nesting of `<form>` elements, so
- * Angular provides the {@link ng.directive:ngForm `ngForm`} directive which behaves identically to
- * `<form>` but can be nested.  This allows you to have nested forms, which is very useful when
- * using Angular validation directives in forms that are dynamically generated using the
- * {@link ng.directive:ngRepeat `ngRepeat`} directive. Since you cannot dynamically generate the `name`
- * attribute of input elements using interpolation, you have to wrap each set of repeated inputs in an
- * `ngForm` directive and nest these in an outer `form` element.
- *
- *
- * # CSS classes
- *  - `ng-valid` Is set if the form is valid.
- *  - `ng-invalid` Is set if the form is invalid.
- *  - `ng-pristine` Is set if the form is pristine.
- *  - `ng-dirty` Is set if the form is dirty.
- *
- *
- * # Submitting a form and preventing the default action
- *
- * Since the role of forms in client-side Angular applications is different than in classical
- * roundtrip apps, it is desirable for the browser not to translate the form submission into a full
- * page reload that sends the data to the server. Instead some javascript logic should be triggered
- * to handle the form submission in an application-specific way.
- *
- * For this reason, Angular prevents the default action (form submission to the server) unless the
- * `<form>` element has an `action` attribute specified.
- *
- * You can use one of the following two ways to specify what javascript method should be called when
- * a form is submitted:
- *
- * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element
- * - {@link ng.directive:ngClick ngClick} directive on the first
-  *  button or input field of type submit (input[type=submit])
- *
- * To prevent double execution of the handler, use only one of the {@link ng.directive:ngSubmit ngSubmit}
- * or {@link ng.directive:ngClick ngClick} directives.
- * This is because of the following form submission rules in the HTML specification:
- *
- * - If a form has only one input field then hitting enter in this field triggers form submit
- * (`ngSubmit`)
- * - if a form has 2+ input fields and no buttons or input[type=submit] then hitting enter
- * doesn't trigger submit
- * - if a form has one or more input fields and one or more buttons or input[type=submit] then
- * hitting enter in any of the input fields will trigger the click handler on the *first* button or
- * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
- *
- * @param {string=} name Name of the form. If specified, the form controller will be published into
- *                       related scope, under this name.
- *
- * @example
-    <doc:example>
-      <doc:source>
-       <script>
-         function Ctrl($scope) {
-           $scope.userType = 'guest';
-         }
-       </script>
-       <form name="myForm" ng-controller="Ctrl">
-         userType: <input name="input" ng-model="userType" required>
-         <span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
-         <tt>userType = {{userType}}</tt><br>
-         <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
-         <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
-         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
-         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
-        </form>
-      </doc:source>
-      <doc:scenario>
-        it('should initialize to model', function() {
-         expect(binding('userType')).toEqual('guest');
-         expect(binding('myForm.input.$valid')).toEqual('true');
-        });
-
-        it('should be invalid if empty', function() {
-         input('userType').enter('');
-         expect(binding('userType')).toEqual('');
-         expect(binding('myForm.input.$valid')).toEqual('false');
-        });
-      </doc:scenario>
-    </doc:example>
- */
-var formDirectiveFactory = function(isNgForm) {
-  return ['$timeout', function($timeout) {
-    var formDirective = {
-      name: 'form',
-      restrict: isNgForm ? 'EAC' : 'E',
-      controller: FormController,
-      compile: function() {
-        return {
-          pre: function(scope, formElement, attr, controller) {
-            if (!attr.action) {
-              // we can't use jq events because if a form is destroyed during submission the default
-              // action is not prevented. see #1238
-              //
-              // IE 9 is not affected because it doesn't fire a submit event and try to do a full
-              // page reload if the form was destroyed by submission of the form via a click handler
-              // on a button in the form. Looks like an IE9 specific bug.
-              var preventDefaultListener = function(event) {
-                event.preventDefault
-                  ? event.preventDefault()
-                  : event.returnValue = false; // IE
-              };
-
-              addEventListenerFn(formElement[0], 'submit', preventDefaultListener);
-
-              // unregister the preventDefault listener so that we don't not leak memory but in a
-              // way that will achieve the prevention of the default action.
-              formElement.on('$destroy', function() {
-                $timeout(function() {
-                  removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);
-                }, 0, false);
-              });
-            }
-
-            var parentFormCtrl = formElement.parent().controller('form'),
-                alias = attr.name || attr.ngForm;
-
-            if (alias) {
-              setter(scope, alias, controller, alias);
-            }
-            if (parentFormCtrl) {
-              formElement.on('$destroy', function() {
-                parentFormCtrl.$removeControl(controller);
-                if (alias) {
-                  setter(scope, alias, undefined, alias);
-                }
-                extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards
-              });
-            }
-          }
-        };
-      }
-    };
-
-    return formDirective;
-  }];
-};
-
-var formDirective = formDirectiveFactory();
-var ngFormDirective = formDirectiveFactory(true);
-
-/* global
-
-    -VALID_CLASS,
-    -INVALID_CLASS,
-    -PRISTINE_CLASS,
-    -DIRTY_CLASS
-*/
-
-var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
-var EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,6}$/;
-var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
-
-var inputType = {
-
-  /**
-   * @ngdoc inputType
-   * @name ng.directive:input.text
-   *
-   * @description
-   * Standard HTML text input with angular data binding.
-   *
-   * @param {string} ngModel Assignable angular expression to data-bind to.
-   * @param {string=} name Property name of the form under which the control is published.
-   * @param {string=} required Adds `required` validation error key if the value is not entered.
-   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
-   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
-   *    `required` when you want to data-bind to the `required` attribute.
-   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
-   *    minlength.
-   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
-   *    maxlength.
-   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
-   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
-   *    patterns defined as scope expressions.
-   * @param {string=} ngChange Angular expression to be executed when input changes due to user
-   *    interaction with the input element.
-   * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trim the input.
-   *
-   * @example
-      <doc:example>
-        <doc:source>
-         <script>
-           function Ctrl($scope) {
-             $scope.text = 'guest';
-             $scope.word = /^\s*\w*\s*$/;
-           }
-         </script>
-         <form name="myForm" ng-controller="Ctrl">
-           Single word: <input type="text" name="input" ng-model="text"
-                               ng-pattern="word" required ng-trim="false">
-           <span class="error" ng-show="myForm.input.$error.required">
-             Required!</span>
-           <span class="error" ng-show="myForm.input.$error.pattern">
-             Single word only!</span>
-
-           <tt>text = {{text}}</tt><br/>
-           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
-           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
-           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
-           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
-          </form>
-        </doc:source>
-        <doc:scenario>
-          it('should initialize to model', function() {
-            expect(binding('text')).toEqual('guest');
-            expect(binding('myForm.input.$valid')).toEqual('true');
-          });
-
-          it('should be invalid if empty', function() {
-            input('text').enter('');
-            expect(binding('text')).toEqual('');
-            expect(binding('myForm.input.$valid')).toEqual('false');
-          });
-
-          it('should be invalid if multi word', function() {
-            input('text').enter('hello world');
-            expect(binding('myForm.input.$valid')).toEqual('false');
-          });
-
-          it('should not be trimmed', function() {
-            input('text').enter('untrimmed ');
-            expect(binding('text')).toEqual('untrimmed ');
-            expect(binding('myForm.input.$valid')).toEqual('true');
-          });
-        </doc:scenario>
-      </doc:example>
-   */
-  'text': textInputType,
-
-
-  /**
-   * @ngdoc inputType
-   * @name ng.directive:input.number
-   *
-   * @description
-   * Text input with number validation and transformation. Sets the `number` validation
-   * error if not a valid number.
-   *
-   * @param {string} ngModel Assignable angular expression to data-bind to.
-   * @param {string=} name Property name of the form under which the control is published.
-   * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`.
-   * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`.
-   * @param {string=} required Sets `required` validation error key if the value is not entered.
-   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
-   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
-   *    `required` when you want to data-bind to the `required` attribute.
-   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
-   *    minlength.
-   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
-   *    maxlength.
-   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
-   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
-   *    patterns defined as scope expressions.
-   * @param {string=} ngChange Angular expression to be executed when input changes due to user
-   *    interaction with the input element.
-   *
-   * @example
-      <doc:example>
-        <doc:source>
-         <script>
-           function Ctrl($scope) {
-             $scope.value = 12;
-           }
-         </script>
-         <form name="myForm" ng-controller="Ctrl">
-           Number: <input type="number" name="input" ng-model="value"
-                          min="0" max="99" required>
-           <span class="error" ng-show="myForm.input.$error.required">
-             Required!</span>
-           <span class="error" ng-show="myForm.input.$error.number">
-             Not valid number!</span>
-           <tt>value = {{value}}</tt><br/>
-           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
-           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
-           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
-           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
-          </form>
-        </doc:source>
-        <doc:scenario>
-          it('should initialize to model', function() {
-           expect(binding('value')).toEqual('12');
-           expect(binding('myForm.input.$valid')).toEqual('true');
-          });
-
-          it('should be invalid if empty', function() {
-           input('value').enter('');
-           expect(binding('value')).toEqual('');
-           expect(binding('myForm.input.$valid')).toEqual('false');
-          });
-
-          it('should be invalid if over max', function() {
-           input('value').enter('123');
-           expect(binding('value')).toEqual('');
-           expect(binding('myForm.input.$valid')).toEqual('false');
-          });
-        </doc:scenario>
-      </doc:example>
-   */
-  'number': numberInputType,
-
-
-  /**
-   * @ngdoc inputType
-   * @name ng.directive:input.url
-   *
-   * @description
-   * Text input with URL validation. Sets the `url` validation error key if the content is not a
-   * valid URL.
-   *
-   * @param {string} ngModel Assignable angular expression to data-bind to.
-   * @param {string=} name Property name of the form under which the control is published.
-   * @param {string=} required Sets `required` validation error key if the value is not entered.
-   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
-   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
-   *    `required` when you want to data-bind to the `required` attribute.
-   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
-   *    minlength.
-   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
-   *    maxlength.
-   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
-   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
-   *    patterns defined as scope expressions.
-   * @param {string=} ngChange Angular expression to be executed when input changes due to user
-   *    interaction with the input element.
-   *
-   * @example
-      <doc:example>
-        <doc:source>
-         <script>
-           function Ctrl($scope) {
-             $scope.text = 'http://google.com';
-           }
-         </script>
-         <form name="myForm" ng-controller="Ctrl">
-           URL: <input type="url" name="input" ng-model="text" required>
-           <span class="error" ng-show="myForm.input.$error.required">
-             Required!</span>
-           <span class="error" ng-show="myForm.input.$error.url">
-             Not valid url!</span>
-           <tt>text = {{text}}</tt><br/>
-           <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
-           <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
-           <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
-           <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
-           <tt>myForm.$error.url = {{!!myForm.$error.url}}</tt><br/>
-          </form>
-        </doc:source>
-        <doc:scenario>
-          it('should initialize to model', function() {
-            expect(binding('text')).toEqual('http://google.com');
-            expect(binding('myForm.input.$valid')).toEqual('true');
-          });
-
-          it('should be invalid if empty', function() {
-            input('text').enter('');
-            expect(binding('text')).toEqual('');
-            expect(binding('myForm.input.$valid')).toEqual('false');
-          });
-
-          it('should be invalid if not url', function() {
-            input('text').enter('xxx');
-            expect(binding('myForm.input.$valid')).toEqual('false');
-          });
-        </doc:scenario>
-      </doc:example>
-   */
-  'url': urlInputType,
-
-
-  /**
-   * @ngdoc inputType
-   * @name ng.directive:input.email
-   *
-   * @description
-   * Text input with email validation. Sets the `email` validation error key if not a valid email
-   * address.
-   *
-   * @param {string} ngModel Assignable angular expression to data-bind to.
-   * @param {string=} name Property name of the form under which the control is published.
-   * @param {string=} required Sets `required` validation error key if the value is not entered.
-   * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
-   *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
-   *    `required` when you want to data-bind to the `required` attribute.
-   * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
-   *    minlength.
-   * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
-   *    maxlength.
-   * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
-   *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
-   *    patterns defined as scope expressions.
-   * @param {string=} ngChange Angular expression to be executed when input changes due to user
-   *    interaction with the input element.
-   *
-   * @example
-      <doc:example>
-        <doc:source>
-         <script>
-           function Ctrl($scope) {
-             $scope.text = 'me@example.com';
-           }
-         </script>
-           <form name="myForm" ng-controller="Ctrl">
-             Email: <input type="email" name="input" ng-model="text" required>
-             <span class="error" ng-show="myForm.input.$error.required">
-               Required!</span>
-             <span class="error" ng-show="myForm.input.$error.email">
-               Not valid email!</span>
-             <tt>text = {{text}}</tt><br/>
-             <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
-             <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
-             <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
-             <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
-             <tt>myForm.$error.email = {{!!myForm.$error.email}}</tt><br/>
-           </form>
-        </doc:source>
-        <doc:scenario>
-          it('should initialize to model', function() {
-            expect(binding('text')).toEqual('me@example.com');
-            expect(binding('myForm.input.$valid')).toEqual('true');
-          });
-
-          it('should be invalid if empty', function() {
-            input('text').enter('');
-            expect(binding('text')).toEqual('');
-            expect(binding('myForm.input.$valid')).toEqual('false');
-          });
-
-          it('should be invalid if not email', function() {
-            input('text').enter('xxx');
-            expect(binding('myForm.input.$valid')).toEqual('false');
-          });
-        </doc:scenario>
-      </doc:example>
-   */
-  'email': emailInputType,
-
-
-  /**
-   * @ngdoc inputType
-   * @name ng.directive:input.radio
-   *
-   * @description
-   * HTML radio button.
-   *
-   * @param {string} ngModel Assignable angular expression to data-bind to.
-   * @param {string} value The value to which the expression should be set when selected.
-   * @param {string=} name Property name of the form under which the control is published.
-   * @param {string=} ngChange Angular expression to be executed when input changes due to user
-   *    interaction with the input element.
-   *
-   * @example
-      <doc:example>
-        <doc:source>
-         <script>
-           function Ctrl($scope) {
-             $scope.color = 'blue';
-           }
-         </script>
-         <form name="myForm" ng-controller="Ctrl">
-           <input type="radio" ng-model="color" value="red">  Red <br/>
-           <input type="radio" ng-model="color" value="green"> Green <br/>
-           <input type="radio" ng-model="color" value="blue"> Blue <br/>
-           <tt>color = {{color}}</tt><br/>
-          </form>
-        </doc:source>
-        <doc:scenario>
-          it('should change state', function() {
-            expect(binding('color')).toEqual('blue');
-
-            input('color').select('red');
-            expect(binding('color')).toEqual('red');
-          });
-        </doc:scenario>
-      </doc:example>
-   */
-  'radio': radioInputType,
-
-
-  /**
-   * @ngdoc inputType
-   * @name ng.directive:input.checkbox
-   *
-   * @description
-   * HTML checkbox.
-   *
-   * @param {string} ngModel Assignable angular expression to data-bind to.
-   * @param {string=} name Property name of the form under which the control is published.
-   * @param {string=} ngTrueValue The value to which the expression should be set when selected.
-   * @param {string=} ngFalseValue The value to which the expression should be set when not selected.
-   * @param {string=} ngChange Angular expression to be executed when input changes due to user
-   *    interaction with the input element.
-   *
-   * @example
-      <doc:example>
-        <doc:source>
-         <script>
-           function Ctrl($scope) {
-             $scope.value1 = true;
-             $scope.value2 = 'YES'
-           }
-         </script>
-         <form name="myForm" ng-controller="Ctrl">
-           Value1: <input type="checkbox" ng-model="value1"> <br/>
-           Value2: <input type="checkbox" ng-model="value2"
-                          ng-true-value="YES" ng-false-value="NO"> <br/>
-           <tt>value1 = {{value1}}</tt><br/>
-           <tt>value2 = {{value2}}</tt><br/>
-          </form>
-        </doc:source>
-        <doc:scenario>
-          it('should change state', function() {
-            expect(binding('value1')).toEqual('true');
-            expect(binding('value2')).toEqual('YES');
-
-            input('value1').check();
-            input('value2').check();
-            expect(binding('value1')).toEqual('false');
-            expect(binding('value2')).toEqual('NO');
-          });
-        </doc:scenario>
-      </doc:example>
-   */
-  'checkbox': checkboxInputType,
-
-  'hidden': noop,
-  'button': noop,
-  'submit': noop,
-  'reset': noop
-};
-
-
-function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
-  // In composition mode, users are still inputing intermediate text buffer,
-  // hold the listener until composition is done.
-  // More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
-  var composing = false;
-
-  element.on('compositionstart', function() {
-    composing = true;
-  });
-
-  element.on('compositionend', function() {
-    composing = false;
-  });
-
-  var listener = function() {
-    if (composing) return;
-    var value = element.val();
-
-    // By default we will trim the value
-    // If the attribute ng-trim exists we will avoid trimming
-    // e.g. <input ng-model="foo" ng-trim="false">
-    if (toBoolean(attr.ngTrim || 'T')) {
-      value = trim(value);
-    }
-
-    if (ctrl.$viewValue !== value) {
-      scope.$apply(function() {
-        ctrl.$setViewValue(value);
-      });
-    }
-  };
-
-  // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the
-  // input event on backspace, delete or cut
-  if ($sniffer.hasEvent('input')) {
-    element.on('input', listener);
-  } else {
-    var timeout;
-
-    var deferListener = function() {
-      if (!timeout) {
-        timeout = $browser.defer(function() {
-          listener();
-          timeout = null;
-        });
-      }
-    };
-
-    element.on('keydown', function(event) {
-      var key = event.keyCode;
-
-      // ignore
-      //    command            modifiers                   arrows
-      if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return;
-
-      deferListener();
-    });
-
-    // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
-    if ($sniffer.hasEvent('paste')) {
-      element.on('paste cut', deferListener);
-    }
-  }
-
-  // if user paste into input using mouse on older browser
-  // or form autocomplete on newer browser, we need "change" event to catch it
-  element.on('change', listener);
-
-  ctrl.$render = function() {
-    element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
-  };
-
-  // pattern validator
-  var pattern = attr.ngPattern,
-      patternValidator,
-      match;
-
-  var validate = function(regexp, value) {
-    if (ctrl.$isEmpty(value) || regexp.test(value)) {
-      ctrl.$setValidity('pattern', true);
-      return value;
-    } else {
-      ctrl.$setValidity('pattern', false);
-      return undefined;
-    }
-  };
-
-  if (pattern) {
-    match = pattern.match(/^\/(.*)\/([gim]*)$/);
-    if (match) {
-      pattern = new RegExp(match[1], match[2]);
-      patternValidator = function(value) {
-        return validate(pattern, value);
-      };
-    } else {
-      patternValidator = function(value) {
-        var patternObj = scope.$eval(pattern);
-
-        if (!patternObj || !patternObj.test) {
-          throw minErr('ngPattern')('noregexp',
-            'Expected {0} to be a RegExp but was {1}. Element: {2}', pattern,
-            patternObj, startingTag(element));
-        }
-        return validate(patternObj, value);
-      };
-    }
-
-    ctrl.$formatters.push(patternValidator);
-    ctrl.$parsers.push(patternValidator);
-  }
-
-  // min length validator
-  if (attr.ngMinlength) {
-    var minlength = int(attr.ngMinlength);
-    var minLengthValidator = function(value) {
-      if (!ctrl.$isEmpty(value) && value.length < minlength) {
-        ctrl.$setValidity('minlength', false);
-        return undefined;
-      } else {
-        ctrl.$setValidity('minlength', true);
-        return value;
-      }
-    };
-
-    ctrl.$parsers.push(minLengthValidator);
-    ctrl.$formatters.push(minLengthValidator);
-  }
-
-  // max length validator
-  if (attr.ngMaxlength) {
-    var maxlength = int(attr.ngMaxlength);
-    var maxLengthValidator = function(value) {
-      if (!ctrl.$isEmpty(value) && value.length > maxlength) {
-        ctrl.$setValidity('maxlength', false);
-        return undefined;
-      } else {
-        ctrl.$setValidity('maxlength', true);
-        return value;
-      }
-    };
-
-    ctrl.$parsers.push(maxLengthValidator);
-    ctrl.$formatters.push(maxLengthValidator);
-  }
-}
-
-function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
-  textInputType(scope, element, attr, ctrl, $sniffer, $browser);
-
-  ctrl.$parsers.push(function(value) {
-    var empty = ctrl.$isEmpty(value);
-    if (empty || NUMBER_REGEXP.test(value)) {
-      ctrl.$setValidity('number', true);
-      return value === '' ? null : (empty ? value : parseFloat(value));
-    } else {
-      ctrl.$setValidity('number', false);
-      return undefined;
-    }
-  });
-
-  ctrl.$formatters.push(function(value) {
-    return ctrl.$isEmpty(value) ? '' : '' + value;
-  });
-
-  if (attr.min) {
-    var minValidator = function(value) {
-      var min = parseFloat(attr.min);
-      if (!ctrl.$isEmpty(value) && value < min) {
-        ctrl.$setValidity('min', false);
-        return undefined;
-      } else {
-        ctrl.$setValidity('min', true);
-        return value;
-      }
-    };
-
-    ctrl.$parsers.push(minValidator);
-    ctrl.$formatters.push(minValidator);
-  }
-
-  if (attr.max) {
-    var maxValidator = function(value) {
-      var max = parseFloat(attr.max);
-      if (!ctrl.$isEmpty(value) && value > max) {
-        ctrl.$setValidity('max', false);
-        return undefined;
-      } else {
-        ctrl.$setValidity('max', true);
-        return value;
-      }
-    };
-
-    ctrl.$parsers.push(maxValidator);
-    ctrl.$formatters.push(maxValidator);
-  }
-
-  ctrl.$formatters.push(function(value) {
-
-    if (ctrl.$isEmpty(value) || isNumber(value)) {
-      ctrl.$setValidity('number', true);
-      return value;
-    } else {
-      ctrl.$setValidity('number', false);
-      return undefined;
-    }
-  });
-}
-
-function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
-  textInputType(scope, element, attr, ctrl, $sniffer, $browser);
-
-  var urlValidator = function(value) {
-    if (ctrl.$isEmpty(value) || URL_REGEXP.test(value)) {
-      ctrl.$setValidity('url', true);
-      return value;
-    } else {
-      ctrl.$setValidity('url', false);
-      return undefined;
-    }
-  };
-
-  ctrl.$formatters.push(urlValidator);
-  ctrl.$parsers.push(urlValidator);
-}
-
-function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
-  textInputType(scope, element, attr, ctrl, $sniffer, $browser);
-
-  var emailValidator = function(value) {
-    if (ctrl.$isEmpty(value) || EMAIL_REGEXP.test(value)) {
-      ctrl.$setValidity('email', true);
-      return value;
-    } else {
-      ctrl.$setValidity('email', false);
-      return undefined;
-    }
-  };
-
-  ctrl.$formatters.push(emailValidator);
-  ctrl.$parsers.push(emailValidator);
-}
-
-function radioInputType(scope, element, attr, ctrl) {
-  // make the name unique, if not defined
-  if (isUndefined(attr.name)) {
-    element.attr('name', nextUid());
-  }
-
-  element.on('click', function() {
-    if (element[0].checked) {
-      scope.$apply(function() {
-        ctrl.$setViewValue(attr.value);
-      });
-    }
-  });
-
-  ctrl.$render = function() {
-    var value = attr.value;
-    element[0].checked = (value == ctrl.$viewValue);
-  };
-
-  attr.$observe('value', ctrl.$render);
-}
-
-function checkboxInputType(scope, element, attr, ctrl) {
-  var trueValue = attr.ngTrueValue,
-      falseValue = attr.ngFalseValue;
-
-  if (!isString(trueValue)) trueValue = true;
-  if (!isString(falseValue)) falseValue = false;
-
-  element.on('click', function() {
-    scope.$apply(function() {
-      ctrl.$setViewValue(element[0].checked);
-    });
-  });
-
-  ctrl.$render = function() {
-    element[0].checked = ctrl.$viewValue;
-  };
-
-  // Override the standard `$isEmpty` because a value of `false` means empty in a checkbox.
-  ctrl.$isEmpty = function(value) {
-    return value !== trueValue;
-  };
-
-  ctrl.$formatters.push(function(value) {
-    return value === trueValue;
-  });
-
-  ctrl.$parsers.push(function(value) {
-    return value ? trueValue : falseValue;
-  });
-}
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:textarea
- * @restrict E
- *
- * @description
- * HTML textarea element control with angular data-binding. The data-binding and validation
- * properties of this element are exactly the same as those of the
- * {@link ng.directive:input input element}.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- *    `required` when you want to data-bind to the `required` attribute.
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- *    minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- *    maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- *    patterns defined as scope expressions.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- *    interaction with the input element.
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:input
- * @restrict E
- *
- * @description
- * HTML input element control with angular data-binding. Input control follows HTML5 input types
- * and polyfills the HTML5 validation behavior for older browsers.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required Sets `required` validation error key if the value is not entered.
- * @param {boolean=} ngRequired Sets `required` attribute if set to true
- * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than
- *    minlength.
- * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than
- *    maxlength.
- * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the
- *    RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for
- *    patterns defined as scope expressions.
- * @param {string=} ngChange Angular expression to be executed when input changes due to user
- *    interaction with the input element.
- *
- * @example
-    <doc:example>
-      <doc:source>
-       <script>
-         function Ctrl($scope) {
-           $scope.user = {name: 'guest', last: 'visitor'};
-         }
-       </script>
-       <div ng-controller="Ctrl">
-         <form name="myForm">
-           User name: <input type="text" name="userName" ng-model="user.name" required>
-           <span class="error" ng-show="myForm.userName.$error.required">
-             Required!</span><br>
-           Last name: <input type="text" name="lastName" ng-model="user.last"
-             ng-minlength="3" ng-maxlength="10">
-           <span class="error" ng-show="myForm.lastName.$error.minlength">
-             Too short!</span>
-           <span class="error" ng-show="myForm.lastName.$error.maxlength">
-             Too long!</span><br>
-         </form>
-         <hr>
-         <tt>user = {{user}}</tt><br/>
-         <tt>myForm.userName.$valid = {{myForm.userName.$valid}}</tt><br>
-         <tt>myForm.userName.$error = {{myForm.userName.$error}}</tt><br>
-         <tt>myForm.lastName.$valid = {{myForm.lastName.$valid}}</tt><br>
-         <tt>myForm.lastName.$error = {{myForm.lastName.$error}}</tt><br>
-         <tt>myForm.$valid = {{myForm.$valid}}</tt><br>
-         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
-         <tt>myForm.$error.minlength = {{!!myForm.$error.minlength}}</tt><br>
-         <tt>myForm.$error.maxlength = {{!!myForm.$error.maxlength}}</tt><br>
-       </div>
-      </doc:source>
-      <doc:scenario>
-        it('should initialize to model', function() {
-          expect(binding('user')).toEqual('{"name":"guest","last":"visitor"}');
-          expect(binding('myForm.userName.$valid')).toEqual('true');
-          expect(binding('myForm.$valid')).toEqual('true');
-        });
-
-        it('should be invalid if empty when required', function() {
-          input('user.name').enter('');
-          expect(binding('user')).toEqual('{"last":"visitor"}');
-          expect(binding('myForm.userName.$valid')).toEqual('false');
-          expect(binding('myForm.$valid')).toEqual('false');
-        });
-
-        it('should be valid if empty when min length is set', function() {
-          input('user.last').enter('');
-          expect(binding('user')).toEqual('{"name":"guest","last":""}');
-          expect(binding('myForm.lastName.$valid')).toEqual('true');
-          expect(binding('myForm.$valid')).toEqual('true');
-        });
-
-        it('should be invalid if less than required min length', function() {
-          input('user.last').enter('xx');
-          expect(binding('user')).toEqual('{"name":"guest"}');
-          expect(binding('myForm.lastName.$valid')).toEqual('false');
-          expect(binding('myForm.lastName.$error')).toMatch(/minlength/);
-          expect(binding('myForm.$valid')).toEqual('false');
-        });
-
-        it('should be invalid if longer than max length', function() {
-          input('user.last').enter('some ridiculously long name');
-          expect(binding('user'))
-            .toEqual('{"name":"guest"}');
-          expect(binding('myForm.lastName.$valid')).toEqual('false');
-          expect(binding('myForm.lastName.$error')).toMatch(/maxlength/);
-          expect(binding('myForm.$valid')).toEqual('false');
-        });
-      </doc:scenario>
-    </doc:example>
- */
-var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {
-  return {
-    restrict: 'E',
-    require: '?ngModel',
-    link: function(scope, element, attr, ctrl) {
-      if (ctrl) {
-        (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,
-                                                            $browser);
-      }
-    }
-  };
-}];
-
-var VALID_CLASS = 'ng-valid',
-    INVALID_CLASS = 'ng-invalid',
-    PRISTINE_CLASS = 'ng-pristine',
-    DIRTY_CLASS = 'ng-dirty';
-
-/**
- * @ngdoc object
- * @name ng.directive:ngModel.NgModelController
- *
- * @property {string} $viewValue Actual string value in the view.
- * @property {*} $modelValue The value in the model, that the control is bound to.
- * @property {Array.<Function>} $parsers Array of functions to execute, as a pipeline, whenever
-       the control reads value from the DOM.  Each function is called, in turn, passing the value
-       through to the next. Used to sanitize / convert the value as well as validation.
-       For validation, the parsers should update the validity state using
-       {@link ng.directive:ngModel.NgModelController#methods_$setValidity $setValidity()},
-       and return `undefined` for invalid values.
-
- *
- * @property {Array.<Function>} $formatters Array of functions to execute, as a pipeline, whenever
-       the model value changes. Each function is called, in turn, passing the value through to the
-       next. Used to format / convert values for display in the control and validation.
- *      <pre>
- *      function formatter(value) {
- *        if (value) {
- *          return value.toUpperCase();
- *        }
- *      }
- *      ngModel.$formatters.push(formatter);
- *      </pre>
- *
- * @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
- *     view value has changed. It is called with no arguments, and its return value is ignored.
- *     This can be used in place of additional $watches against the model value.
- *
- * @property {Object} $error An object hash with all errors as keys.
- *
- * @property {boolean} $pristine True if user has not interacted with the control yet.
- * @property {boolean} $dirty True if user has already interacted with the control.
- * @property {boolean} $valid True if there is no error.
- * @property {boolean} $invalid True if at least one error on the control.
- *
- * @description
- *
- * `NgModelController` provides API for the `ng-model` directive. The controller contains
- * services for data-binding, validation, CSS updates, and value formatting and parsing. It
- * purposefully does not contain any logic which deals with DOM rendering or listening to
- * DOM events. Such DOM related logic should be provided by other directives which make use of
- * `NgModelController` for data-binding.
- *
- * ## Custom Control Example
- * This example shows how to use `NgModelController` with a custom control to achieve
- * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`)
- * collaborate together to achieve the desired result.
- *
- * Note that `contenteditable` is an HTML5 attribute, which tells the browser to let the element
- * contents be edited in place by the user.  This will not work on older browsers.
- *
- * <example module="customControl">
-    <file name="style.css">
-      [contenteditable] {
-        border: 1px solid black;
-        background-color: white;
-        min-height: 20px;
-      }
-
-      .ng-invalid {
-        border: 1px solid red;
-      }
-
-    </file>
-    <file name="script.js">
-      angular.module('customControl', []).
-        directive('contenteditable', function() {
-          return {
-            restrict: 'A', // only activate on element attribute
-            require: '?ngModel', // get a hold of NgModelController
-            link: function(scope, element, attrs, ngModel) {
-              if(!ngModel) return; // do nothing if no ng-model
-
-              // Specify how UI should be updated
-              ngModel.$render = function() {
-                element.html(ngModel.$viewValue || '');
-              };
-
-              // Listen for change events to enable binding
-              element.on('blur keyup change', function() {
-                scope.$apply(read);
-              });
-              read(); // initialize
-
-              // Write data to the model
-              function read() {
-                var html = element.html();
-                // When we clear the content editable the browser leaves a <br> behind
-                // If strip-br attribute is provided then we strip this out
-                if( attrs.stripBr && html == '<br>' ) {
-                  html = '';
-                }
-                ngModel.$setViewValue(html);
-              }
-            }
-          };
-        });
-    </file>
-    <file name="index.html">
-      <form name="myForm">
-       <div contenteditable
-            name="myWidget" ng-model="userContent"
-            strip-br="true"
-            required>Change me!</div>
-        <span ng-show="myForm.myWidget.$error.required">Required!</span>
-       <hr>
-       <textarea ng-model="userContent"></textarea>
-      </form>
-    </file>
-    <file name="scenario.js">
-      it('should data-bind and become invalid', function() {
-        var contentEditable = element('[contenteditable]');
-
-        expect(contentEditable.text()).toEqual('Change me!');
-        input('userContent').enter('');
-        expect(contentEditable.text()).toEqual('');
-        expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/);
-      });
-    </file>
- * </example>
- *
- *
- */
-var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',
-    function($scope, $exceptionHandler, $attr, $element, $parse) {
-  this.$viewValue = Number.NaN;
-  this.$modelValue = Number.NaN;
-  this.$parsers = [];
-  this.$formatters = [];
-  this.$viewChangeListeners = [];
-  this.$pristine = true;
-  this.$dirty = false;
-  this.$valid = true;
-  this.$invalid = false;
-  this.$name = $attr.name;
-
-  var ngModelGet = $parse($attr.ngModel),
-      ngModelSet = ngModelGet.assign;
-
-  if (!ngModelSet) {
-    throw minErr('ngModel')('nonassign', "Expression '{0}' is non-assignable. Element: {1}",
-        $attr.ngModel, startingTag($element));
-  }
-
-  /**
-   * @ngdoc function
-   * @name ng.directive:ngModel.NgModelController#$render
-   * @methodOf ng.directive:ngModel.NgModelController
-   *
-   * @description
-   * Called when the view needs to be updated. It is expected that the user of the ng-model
-   * directive will implement this method.
-   */
-  this.$render = noop;
-
-  /**
-   * @ngdoc function
-   * @name { ng.directive:ngModel.NgModelController#$isEmpty
-   * @methodOf ng.directive:ngModel.NgModelController
-   *
-   * @description
-   * This is called when we need to determine if the value of the input is empty.
-   *
-   * For instance, the required directive does this to work out if the input has data or not.
-   * The default `$isEmpty` function checks whether the value is `undefined`, `''`, `null` or `NaN`.
-   *
-   * You can override this for input directives whose concept of being empty is different to the
-   * default. The `checkboxInputType` directive does this because in its case a value of `false`
-   * implies empty.
-   */
-  this.$isEmpty = function(value) {
-    return isUndefined(value) || value === '' || value === null || value !== value;
-  };
-
-  var parentForm = $element.inheritedData('$formController') || nullFormCtrl,
-      invalidCount = 0, // used to easily determine if we are valid
-      $error = this.$error = {}; // keep invalid keys here
-
-
-  // Setup initial state of the control
-  $element.addClass(PRISTINE_CLASS);
-  toggleValidCss(true);
-
-  // convenience method for easy toggling of classes
-  function toggleValidCss(isValid, validationErrorKey) {
-    validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
-    $element.
-      removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey).
-      addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
-  }
-
-  /**
-   * @ngdoc function
-   * @name ng.directive:ngModel.NgModelController#$setValidity
-   * @methodOf ng.directive:ngModel.NgModelController
-   *
-   * @description
-   * Change the validity state, and notifies the form when the control changes validity. (i.e. it
-   * does not notify form if given validator is already marked as invalid).
-   *
-   * This method should be called by validators - i.e. the parser or formatter functions.
-   *
-   * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign
-   *        to `$error[validationErrorKey]=isValid` so that it is available for data-binding.
-   *        The `validationErrorKey` should be in camelCase and will get converted into dash-case
-   *        for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error`
-   *        class and can be bound to as  `{{someForm.someControl.$error.myError}}` .
-   * @param {boolean} isValid Whether the current state is valid (true) or invalid (false).
-   */
-  this.$setValidity = function(validationErrorKey, isValid) {
-    // Purposeful use of ! here to cast isValid to boolean in case it is undefined
-    // jshint -W018
-    if ($error[validationErrorKey] === !isValid) return;
-    // jshint +W018
-
-    if (isValid) {
-      if ($error[validationErrorKey]) invalidCount--;
-      if (!invalidCount) {
-        toggleValidCss(true);
-        this.$valid = true;
-        this.$invalid = false;
-      }
-    } else {
-      toggleValidCss(false);
-      this.$invalid = true;
-      this.$valid = false;
-      invalidCount++;
-    }
-
-    $error[validationErrorKey] = !isValid;
-    toggleValidCss(isValid, validationErrorKey);
-
-    parentForm.$setValidity(validationErrorKey, isValid, this);
-  };
-
-  /**
-   * @ngdoc function
-   * @name ng.directive:ngModel.NgModelController#$setPristine
-   * @methodOf ng.directive:ngModel.NgModelController
-   *
-   * @description
-   * Sets the control to its pristine state.
-   *
-   * This method can be called to remove the 'ng-dirty' class and set the control to its pristine
-   * state (ng-pristine class).
-   */
-  this.$setPristine = function () {
-    this.$dirty = false;
-    this.$pristine = true;
-    $element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
-  };
-
-  /**
-   * @ngdoc function
-   * @name ng.directive:ngModel.NgModelController#$setViewValue
-   * @methodOf ng.directive:ngModel.NgModelController
-   *
-   * @description
-   * Update the view value.
-   *
-   * This method should be called when the view value changes, typically from within a DOM event handler.
-   * For example {@link ng.directive:input input} and
-   * {@link ng.directive:select select} directives call it.
-   *
-   * It will update the $viewValue, then pass this value through each of the functions in `$parsers`,
-   * which includes any validators. The value that comes out of this `$parsers` pipeline, be applied to
-   * `$modelValue` and the **expression** specified in the `ng-model` attribute.
-   *
-   * Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
-   *
-   * Note that calling this function does not trigger a `$digest`.
-   *
-   * @param {string} value Value from the view.
-   */
-  this.$setViewValue = function(value) {
-    this.$viewValue = value;
-
-    // change to dirty
-    if (this.$pristine) {
-      this.$dirty = true;
-      this.$pristine = false;
-      $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS);
-      parentForm.$setDirty();
-    }
-
-    forEach(this.$parsers, function(fn) {
-      value = fn(value);
-    });
-
-    if (this.$modelValue !== value) {
-      this.$modelValue = value;
-      ngModelSet($scope, value);
-      forEach(this.$viewChangeListeners, function(listener) {
-        try {
-          listener();
-        } catch(e) {
-          $exceptionHandler(e);
-        }
-      });
-    }
-  };
-
-  // model -> value
-  var ctrl = this;
-
-  $scope.$watch(function ngModelWatch() {
-    var value = ngModelGet($scope);
-
-    // if scope model value and ngModel value are out of sync
-    if (ctrl.$modelValue !== value) {
-
-      var formatters = ctrl.$formatters,
-          idx = formatters.length;
-
-      ctrl.$modelValue = value;
-      while(idx--) {
-        value = formatters[idx](value);
-      }
-
-      if (ctrl.$viewValue !== value) {
-        ctrl.$viewValue = value;
-        ctrl.$render();
-      }
-    }
-
-    return value;
-  });
-}];
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngModel
- *
- * @element input
- *
- * @description
- * The `ngModel` directive binds an `input`,`select`, `textarea` (or custom form control) to a
- * property on the scope using {@link ng.directive:ngModel.NgModelController NgModelController},
- * which is created and exposed by this directive.
- *
- * `ngModel` is responsible for:
- *
- * - Binding the view into the model, which other directives such as `input`, `textarea` or `select`
- *   require.
- * - Providing validation behavior (i.e. required, number, email, url).
- * - Keeping the state of the control (valid/invalid, dirty/pristine, validation errors).
- * - Setting related css classes on the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`).
- * - Registering the control with its parent {@link ng.directive:form form}.
- *
- * Note: `ngModel` will try to bind to the property given by evaluating the expression on the
- * current scope. If the property doesn't already exist on this scope, it will be created
- * implicitly and added to the scope.
- *
- * For best practices on using `ngModel`, see:
- *
- *  - {@link https://github.com/angular/angular.js/wiki/Understanding-Scopes}
- *
- * For basic examples, how to use `ngModel`, see:
- *
- *  - {@link ng.directive:input input}
- *    - {@link ng.directive:input.text text}
- *    - {@link ng.directive:input.checkbox checkbox}
- *    - {@link ng.directive:input.radio radio}
- *    - {@link ng.directive:input.number number}
- *    - {@link ng.directive:input.email email}
- *    - {@link ng.directive:input.url url}
- *  - {@link ng.directive:select select}
- *  - {@link ng.directive:textarea textarea}
- *
- */
-var ngModelDirective = function() {
-  return {
-    require: ['ngModel', '^?form'],
-    controller: NgModelController,
-    link: function(scope, element, attr, ctrls) {
-      // notify others, especially parent forms
-
-      var modelCtrl = ctrls[0],
-          formCtrl = ctrls[1] || nullFormCtrl;
-
-      formCtrl.$addControl(modelCtrl);
-
-      scope.$on('$destroy', function() {
-        formCtrl.$removeControl(modelCtrl);
-      });
-    }
-  };
-};
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngChange
- *
- * @description
- * Evaluate given expression when user changes the input.
- * The expression is not evaluated when the value change is coming from the model.
- *
- * Note, this directive requires `ngModel` to be present.
- *
- * @element input
- * @param {expression} ngChange {@link guide/expression Expression} to evaluate upon change
- * in input value.
- *
- * @example
- * <doc:example>
- *   <doc:source>
- *     <script>
- *       function Controller($scope) {
- *         $scope.counter = 0;
- *         $scope.change = function() {
- *           $scope.counter++;
- *         };
- *       }
- *     </script>
- *     <div ng-controller="Controller">
- *       <input type="checkbox" ng-model="confirmed" ng-change="change()" id="ng-change-example1" />
- *       <input type="checkbox" ng-model="confirmed" id="ng-change-example2" />
- *       <label for="ng-change-example2">Confirmed</label><br />
- *       debug = {{confirmed}}<br />
- *       counter = {{counter}}
- *     </div>
- *   </doc:source>
- *   <doc:scenario>
- *     it('should evaluate the expression if changing from view', function() {
- *       expect(binding('counter')).toEqual('0');
- *       element('#ng-change-example1').click();
- *       expect(binding('counter')).toEqual('1');
- *       expect(binding('confirmed')).toEqual('true');
- *     });
- *
- *     it('should not evaluate the expression if changing from model', function() {
- *       element('#ng-change-example2').click();
- *       expect(binding('counter')).toEqual('0');
- *       expect(binding('confirmed')).toEqual('true');
- *     });
- *   </doc:scenario>
- * </doc:example>
- */
-var ngChangeDirective = valueFn({
-  require: 'ngModel',
-  link: function(scope, element, attr, ctrl) {
-    ctrl.$viewChangeListeners.push(function() {
-      scope.$eval(attr.ngChange);
-    });
-  }
-});
-
-
-var requiredDirective = function() {
-  return {
-    require: '?ngModel',
-    link: function(scope, elm, attr, ctrl) {
-      if (!ctrl) return;
-      attr.required = true; // force truthy in case we are on non input element
-
-      var validator = function(value) {
-        if (attr.required && ctrl.$isEmpty(value)) {
-          ctrl.$setValidity('required', false);
-          return;
-        } else {
-          ctrl.$setValidity('required', true);
-          return value;
-        }
-      };
-
-      ctrl.$formatters.push(validator);
-      ctrl.$parsers.unshift(validator);
-
-      attr.$observe('required', function() {
-        validator(ctrl.$viewValue);
-      });
-    }
-  };
-};
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngList
- *
- * @description
- * Text input that converts between a delimited string and an array of strings. The delimiter
- * can be a fixed string (by default a comma) or a regular expression.
- *
- * @element input
- * @param {string=} ngList optional delimiter that should be used to split the value. If
- *   specified in form `/something/` then the value will be converted into a regular expression.
- *
- * @example
-    <doc:example>
-      <doc:source>
-       <script>
-         function Ctrl($scope) {
-           $scope.names = ['igor', 'misko', 'vojta'];
-         }
-       </script>
-       <form name="myForm" ng-controller="Ctrl">
-         List: <input name="namesInput" ng-model="names" ng-list required>
-         <span class="error" ng-show="myForm.namesInput.$error.required">
-           Required!</span>
-         <br>
-         <tt>names = {{names}}</tt><br/>
-         <tt>myForm.namesInput.$valid = {{myForm.namesInput.$valid}}</tt><br/>
-         <tt>myForm.namesInput.$error = {{myForm.namesInput.$error}}</tt><br/>
-         <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
-         <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
-        </form>
-      </doc:source>
-      <doc:scenario>
-        it('should initialize to model', function() {
-          expect(binding('names')).toEqual('["igor","misko","vojta"]');
-          expect(binding('myForm.namesInput.$valid')).toEqual('true');
-          expect(element('span.error').css('display')).toBe('none');
-        });
-
-        it('should be invalid if empty', function() {
-          input('names').enter('');
-          expect(binding('names')).toEqual('');
-          expect(binding('myForm.namesInput.$valid')).toEqual('false');
-          expect(element('span.error').css('display')).not().toBe('none');
-        });
-      </doc:scenario>
-    </doc:example>
- */
-var ngListDirective = function() {
-  return {
-    require: 'ngModel',
-    link: function(scope, element, attr, ctrl) {
-      var match = /\/(.*)\//.exec(attr.ngList),
-          separator = match && new RegExp(match[1]) || attr.ngList || ',';
-
-      var parse = function(viewValue) {
-        // If the viewValue is invalid (say required but empty) it will be `undefined`
-        if (isUndefined(viewValue)) return;
-
-        var list = [];
-
-        if (viewValue) {
-          forEach(viewValue.split(separator), function(value) {
-            if (value) list.push(trim(value));
-          });
-        }
-
-        return list;
-      };
-
-      ctrl.$parsers.push(parse);
-      ctrl.$formatters.push(function(value) {
-        if (isArray(value)) {
-          return value.join(', ');
-        }
-
-        return undefined;
-      });
-
-      // Override the standard $isEmpty because an empty array means the input is empty.
-      ctrl.$isEmpty = function(value) {
-        return !value || !value.length;
-      };
-    }
-  };
-};
-
-
-var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
-/**
- * @ngdoc directive
- * @name ng.directive:ngValue
- *
- * @description
- * Binds the given expression to the value of `input[select]` or `input[radio]`, so
- * that when the element is selected, the `ngModel` of that element is set to the
- * bound value.
- *
- * `ngValue` is useful when dynamically generating lists of radio buttons using `ng-repeat`, as
- * shown below.
- *
- * @element input
- * @param {string=} ngValue angular expression, whose value will be bound to the `value` attribute
- *   of the `input` element
- *
- * @example
-    <doc:example>
-      <doc:source>
-       <script>
-          function Ctrl($scope) {
-            $scope.names = ['pizza', 'unicorns', 'robots'];
-            $scope.my = { favorite: 'unicorns' };
-          }
-       </script>
-        <form ng-controller="Ctrl">
-          <h2>Which is your favorite?</h2>
-            <label ng-repeat="name in names" for="{{name}}">
-              {{name}}
-              <input type="radio"
-                     ng-model="my.favorite"
-                     ng-value="name"
-                     id="{{name}}"
-                     name="favorite">
-            </label>
-          <div>You chose {{my.favorite}}</div>
-        </form>
-      </doc:source>
-      <doc:scenario>
-        it('should initialize to model', function() {
-          expect(binding('my.favorite')).toEqual('unicorns');
-        });
-        it('should bind the values to the inputs', function() {
-          input('my.favorite').select('pizza');
-          expect(binding('my.favorite')).toEqual('pizza');
-        });
-      </doc:scenario>
-    </doc:example>
- */
-var ngValueDirective = function() {
-  return {
-    priority: 100,
-    compile: function(tpl, tplAttr) {
-      if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) {
-        return function ngValueConstantLink(scope, elm, attr) {
-          attr.$set('value', scope.$eval(attr.ngValue));
-        };
-      } else {
-        return function ngValueLink(scope, elm, attr) {
-          scope.$watch(attr.ngValue, function valueWatchAction(value) {
-            attr.$set('value', value);
-          });
-        };
-      }
-    }
-  };
-};
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngBind
- * @restrict AC
- *
- * @description
- * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element
- * with the value of a given expression, and to update the text content when the value of that
- * expression changes.
- *
- * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like
- * `{{ expression }}` which is similar but less verbose.
- *
- * It is preferrable to use `ngBind` instead of `{{ expression }}` when a template is momentarily
- * displayed by the browser in its raw state before Angular compiles it. Since `ngBind` is an
- * element attribute, it makes the bindings invisible to the user while the page is loading.
- *
- * An alternative solution to this problem would be using the
- * {@link ng.directive:ngCloak ngCloak} directive.
- *
- *
- * @element ANY
- * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
- *
- * @example
- * Enter a name in the Live Preview text box; the greeting below the text box changes instantly.
-   <doc:example>
-     <doc:source>
-       <script>
-         function Ctrl($scope) {
-           $scope.name = 'Whirled';
-         }
-       </script>
-       <div ng-controller="Ctrl">
-         Enter name: <input type="text" ng-model="name"><br>
-         Hello <span ng-bind="name"></span>!
-       </div>
-     </doc:source>
-     <doc:scenario>
-       it('should check ng-bind', function() {
-         expect(using('.doc-example-live').binding('name')).toBe('Whirled');
-         using('.doc-example-live').input('name').enter('world');
-         expect(using('.doc-example-live').binding('name')).toBe('world');
-       });
-     </doc:scenario>
-   </doc:example>
- */
-var ngBindDirective = ngDirective(function(scope, element, attr) {
-  element.addClass('ng-binding').data('$binding', attr.ngBind);
-  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
-    // We are purposefully using == here rather than === because we want to
-    // catch when value is "null or undefined"
-    // jshint -W041
-    element.text(value == undefined ? '' : value);
-  });
-});
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngBindTemplate
- *
- * @description
- * The `ngBindTemplate` directive specifies that the element
- * text content should be replaced with the interpolation of the template
- * in the `ngBindTemplate` attribute.
- * Unlike `ngBind`, the `ngBindTemplate` can contain multiple `{{` `}}`
- * expressions. This directive is needed since some HTML elements
- * (such as TITLE and OPTION) cannot contain SPAN elements.
- *
- * @element ANY
- * @param {string} ngBindTemplate template of form
- *   <tt>{{</tt> <tt>expression</tt> <tt>}}</tt> to eval.
- *
- * @example
- * Try it here: enter text in text box and watch the greeting change.
-   <doc:example>
-     <doc:source>
-       <script>
-         function Ctrl($scope) {
-           $scope.salutation = 'Hello';
-           $scope.name = 'World';
-         }
-       </script>
-       <div ng-controller="Ctrl">
-        Salutation: <input type="text" ng-model="salutation"><br>
-        Name: <input type="text" ng-model="name"><br>
-        <pre ng-bind-template="{{salutation}} {{name}}!"></pre>
-       </div>
-     </doc:source>
-     <doc:scenario>
-       it('should check ng-bind', function() {
-         expect(using('.doc-example-live').binding('salutation')).
-           toBe('Hello');
-         expect(using('.doc-example-live').binding('name')).
-           toBe('World');
-         using('.doc-example-live').input('salutation').enter('Greetings');
-         using('.doc-example-live').input('name').enter('user');
-         expect(using('.doc-example-live').binding('salutation')).
-           toBe('Greetings');
-         expect(using('.doc-example-live').binding('name')).
-           toBe('user');
-       });
-     </doc:scenario>
-   </doc:example>
- */
-var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
-  return function(scope, element, attr) {
-    // TODO: move this to scenario runner
-    var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate));
-    element.addClass('ng-binding').data('$binding', interpolateFn);
-    attr.$observe('ngBindTemplate', function(value) {
-      element.text(value);
-    });
-  };
-}];
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngBindHtml
- *
- * @description
- * Creates a binding that will innerHTML the result of evaluating the `expression` into the current
- * element in a secure way.  By default, the innerHTML-ed content will be sanitized using the {@link
- * ngSanitize.$sanitize $sanitize} service.  To utilize this functionality, ensure that `$sanitize`
- * is available, for example, by including {@link ngSanitize} in your module's dependencies (not in
- * core Angular.)  You may also bypass sanitization for values you know are safe. To do so, bind to
- * an explicitly trusted value via {@link ng.$sce#methods_trustAsHtml $sce.trustAsHtml}.  See the example
- * under {@link ng.$sce#Example Strict Contextual Escaping (SCE)}.
- *
- * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you
- * will have an exception (instead of an exploit.)
- *
- * @element ANY
- * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
- *
- * @example
-   Try it here: enter text in text box and watch the greeting change.
- 
-   <example module="ngBindHtmlExample" deps="angular-sanitize.js">
-     <file name="index.html">
-       <div ng-controller="ngBindHtmlCtrl">
-        <p ng-bind-html="myHTML"></p>
-       </div>
-     </file>
-     
-     <file name="script.js">
-       angular.module('ngBindHtmlExample', ['ngSanitize'])
-
-       .controller('ngBindHtmlCtrl', ['$scope', function ngBindHtmlCtrl($scope) {
-         $scope.myHTML =
-            'I am an <code>HTML</code>string with <a href="#">links!</a> and other <em>stuff</em>';
-       }]);
-     </file>
-
-     <file name="scenario.js">
-       it('should check ng-bind-html', function() {
-         expect(using('.doc-example-live').binding('myHTML')).
-           toBe(
-           'I am an <code>HTML</code>string with <a href="#">links!</a> and other <em>stuff</em>'
-           );
-       });
-     </file>
-   </example>
- */
-var ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) {
-  return function(scope, element, attr) {
-    element.addClass('ng-binding').data('$binding', attr.ngBindHtml);
-
-    var parsed = $parse(attr.ngBindHtml);
-    function getStringValue() { return (parsed(scope) || '').toString(); }
-
-    scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) {
-      element.html($sce.getTrustedHtml(parsed(scope)) || '');
-    });
-  };
-}];
-
-function classDirective(name, selector) {
-  name = 'ngClass' + name;
-  return function() {
-    return {
-      restrict: 'AC',
-      link: function(scope, element, attr) {
-        var oldVal;
-
-        scope.$watch(attr[name], ngClassWatchAction, true);
-
-        attr.$observe('class', function(value) {
-          ngClassWatchAction(scope.$eval(attr[name]));
-        });
-
-
-        if (name !== 'ngClass') {
-          scope.$watch('$index', function($index, old$index) {
-            // jshint bitwise: false
-            var mod = $index & 1;
-            if (mod !== old$index & 1) {
-              var classes = flattenClasses(scope.$eval(attr[name]));
-              mod === selector ?
-                attr.$addClass(classes) :
-                attr.$removeClass(classes);
-            }
-          });
-        }
-
-
-        function ngClassWatchAction(newVal) {
-          if (selector === true || scope.$index % 2 === selector) {
-            var newClasses = flattenClasses(newVal || '');
-            if(!oldVal) {
-              attr.$addClass(newClasses);
-            } else if(!equals(newVal,oldVal)) {
-              attr.$updateClass(newClasses, flattenClasses(oldVal));
-            }
-          }
-          oldVal = copy(newVal);
-        }
-
-
-        function flattenClasses(classVal) {
-          if(isArray(classVal)) {
-            return classVal.join(' ');
-          } else if (isObject(classVal)) {
-            var classes = [], i = 0;
-            forEach(classVal, function(v, k) {
-              if (v) {
-                classes.push(k);
-              }
-            });
-            return classes.join(' ');
-          }
-
-          return classVal;
-        }
-      }
-    };
-  };
-}
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngClass
- * @restrict AC
- *
- * @description
- * The `ngClass` directive allows you to dynamically set CSS classes on an HTML element by databinding
- * an expression that represents all classes to be added.
- *
- * The directive won't add duplicate classes if a particular class was already set.
- *
- * When the expression changes, the previously added classes are removed and only then the
- * new classes are added.
- *
- * @animations
- * add - happens just before the class is applied to the element
- * remove - happens just before the class is removed from the element
- *
- * @element ANY
- * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
- *   of the evaluation can be a string representing space delimited class
- *   names, an array, or a map of class names to boolean values. In the case of a map, the
- *   names of the properties whose values are truthy will be added as css classes to the
- *   element.
- *
- * @example Example that demonstrates basic bindings via ngClass directive.
-   <example>
-     <file name="index.html">
-       <p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
-       <input type="checkbox" ng-model="deleted"> deleted (apply "strike" class)<br>
-       <input type="checkbox" ng-model="important"> important (apply "bold" class)<br>
-       <input type="checkbox" ng-model="error"> error (apply "red" class)
-       <hr>
-       <p ng-class="style">Using String Syntax</p>
-       <input type="text" ng-model="style" placeholder="Type: bold strike red">
-       <hr>
-       <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
-       <input ng-model="style1" placeholder="Type: bold, strike or red"><br>
-       <input ng-model="style2" placeholder="Type: bold, strike or red"><br>
-       <input ng-model="style3" placeholder="Type: bold, strike or red"><br>
-     </file>
-     <file name="style.css">
-       .strike {
-         text-decoration: line-through;
-       }
-       .bold {
-           font-weight: bold;
-       }
-       .red {
-           color: red;
-       }
-     </file>
-     <file name="scenario.js">
-       it('should let you toggle the class', function() {
-
-         expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/bold/);
-         expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/red/);
-
-         input('important').check();
-         expect(element('.doc-example-live p:first').prop('className')).toMatch(/bold/);
-
-         input('error').check();
-         expect(element('.doc-example-live p:first').prop('className')).toMatch(/red/);
-       });
-
-       it('should let you toggle string example', function() {
-         expect(element('.doc-example-live p:nth-of-type(2)').prop('className')).toBe('');
-         input('style').enter('red');
-         expect(element('.doc-example-live p:nth-of-type(2)').prop('className')).toBe('red');
-       });
-
-       it('array example should have 3 classes', function() {
-         expect(element('.doc-example-live p:last').prop('className')).toBe('');
-         input('style1').enter('bold');
-         input('style2').enter('strike');
-         input('style3').enter('red');
-         expect(element('.doc-example-live p:last').prop('className')).toBe('bold strike red');
-       });
-     </file>
-   </example>
-
-   ## Animations
-
-   The example below demonstrates how to perform animations using ngClass.
-
-   <example animations="true">
-     <file name="index.html">
-      <input type="button" value="set" ng-click="myVar='my-class'">
-      <input type="button" value="clear" ng-click="myVar=''">
-      <br>
-      <span class="base-class" ng-class="myVar">Sample Text</span>
-     </file>
-     <file name="style.css">
-       .base-class {
-         -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-         transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-       }
-
-       .base-class.my-class {
-         color: red;
-         font-size:3em;
-       }
-     </file>
-     <file name="scenario.js">
-       it('should check ng-class', function() {
-         expect(element('.doc-example-live span').prop('className')).not().
-           toMatch(/my-class/);
-
-         using('.doc-example-live').element(':button:first').click();
-
-         expect(element('.doc-example-live span').prop('className')).
-           toMatch(/my-class/);
-
-         using('.doc-example-live').element(':button:last').click();
-
-         expect(element('.doc-example-live span').prop('className')).not().
-           toMatch(/my-class/);
-       });
-     </file>
-   </example>
-
-
-   ## ngClass and pre-existing CSS3 Transitions/Animations
-   The ngClass directive still supports CSS3 Transitions/Animations even if they do not follow the ngAnimate CSS naming structure.
-   Upon animation ngAnimate will apply supplementary CSS classes to track the start and end of an animation, but this will not hinder
-   any pre-existing CSS transitions already on the element. To get an idea of what happens during a class-based animation, be sure
-   to view the step by step details of {@link ngAnimate.$animate#methods_addclass $animate.addClass} and
-   {@link ngAnimate.$animate#methods_removeclass $animate.removeClass}.
- */
-var ngClassDirective = classDirective('', true);
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngClassOdd
- * @restrict AC
- *
- * @description
- * The `ngClassOdd` and `ngClassEven` directives work exactly as
- * {@link ng.directive:ngClass ngClass}, except they work in
- * conjunction with `ngRepeat` and take effect only on odd (even) rows.
- *
- * This directive can be applied only within the scope of an
- * {@link ng.directive:ngRepeat ngRepeat}.
- *
- * @element ANY
- * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
- *   of the evaluation can be a string representing space delimited class names or an array.
- *
- * @example
-   <example>
-     <file name="index.html">
-        <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
-          <li ng-repeat="name in names">
-           <span ng-class-odd="'odd'" ng-class-even="'even'">
-             {{name}}
-           </span>
-          </li>
-        </ol>
-     </file>
-     <file name="style.css">
-       .odd {
-         color: red;
-       }
-       .even {
-         color: blue;
-       }
-     </file>
-     <file name="scenario.js">
-       it('should check ng-class-odd and ng-class-even', function() {
-         expect(element('.doc-example-live li:first span').prop('className')).
-           toMatch(/odd/);
-         expect(element('.doc-example-live li:last span').prop('className')).
-           toMatch(/even/);
-       });
-     </file>
-   </example>
- */
-var ngClassOddDirective = classDirective('Odd', 0);
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngClassEven
- * @restrict AC
- *
- * @description
- * The `ngClassOdd` and `ngClassEven` directives work exactly as
- * {@link ng.directive:ngClass ngClass}, except they work in
- * conjunction with `ngRepeat` and take effect only on odd (even) rows.
- *
- * This directive can be applied only within the scope of an
- * {@link ng.directive:ngRepeat ngRepeat}.
- *
- * @element ANY
- * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
- *   result of the evaluation can be a string representing space delimited class names or an array.
- *
- * @example
-   <example>
-     <file name="index.html">
-        <ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
-          <li ng-repeat="name in names">
-           <span ng-class-odd="'odd'" ng-class-even="'even'">
-             {{name}} &nbsp; &nbsp; &nbsp;
-           </span>
-          </li>
-        </ol>
-     </file>
-     <file name="style.css">
-       .odd {
-         color: red;
-       }
-       .even {
-         color: blue;
-       }
-     </file>
-     <file name="scenario.js">
-       it('should check ng-class-odd and ng-class-even', function() {
-         expect(element('.doc-example-live li:first span').prop('className')).
-           toMatch(/odd/);
-         expect(element('.doc-example-live li:last span').prop('className')).
-           toMatch(/even/);
-       });
-     </file>
-   </example>
- */
-var ngClassEvenDirective = classDirective('Even', 1);
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngCloak
- * @restrict AC
- *
- * @description
- * The `ngCloak` directive is used to prevent the Angular html template from being briefly
- * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this
- * directive to avoid the undesirable flicker effect caused by the html template display.
- *
- * The directive can be applied to the `<body>` element, but the preferred usage is to apply
- * multiple `ngCloak` directives to small portions of the page to permit progressive rendering
- * of the browser view.
- *
- * `ngCloak` works in cooperation with the following css rule embedded within `angular.js` and
- * `angular.min.js`.
- * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
- *
- * <pre>
- * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
- *   display: none !important;
- * }
- * </pre>
- *
- * When this css rule is loaded by the browser, all html elements (including their children) that
- * are tagged with the `ngCloak` directive are hidden. When Angular encounters this directive
- * during the compilation of the template it deletes the `ngCloak` element attribute, making
- * the compiled element visible.
- *
- * For the best result, the `angular.js` script must be loaded in the head section of the html
- * document; alternatively, the css rule above must be included in the external stylesheet of the
- * application.
- *
- * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they
- * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css
- * class `ngCloak` in addition to the `ngCloak` directive as shown in the example below.
- *
- * @element ANY
- *
- * @example
-   <doc:example>
-     <doc:source>
-        <div id="template1" ng-cloak>{{ 'hello' }}</div>
-        <div id="template2" ng-cloak class="ng-cloak">{{ 'hello IE7' }}</div>
-     </doc:source>
-     <doc:scenario>
-       it('should remove the template directive and css class', function() {
-         expect(element('.doc-example-live #template1').attr('ng-cloak')).
-           not().toBeDefined();
-         expect(element('.doc-example-live #template2').attr('ng-cloak')).
-           not().toBeDefined();
-       });
-     </doc:scenario>
-   </doc:example>
- *
- */
-var ngCloakDirective = ngDirective({
-  compile: function(element, attr) {
-    attr.$set('ngCloak', undefined);
-    element.removeClass('ng-cloak');
-  }
-});
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngController
- *
- * @description
- * The `ngController` directive attaches a controller class to the view. This is a key aspect of how angular
- * supports the principles behind the Model-View-Controller design pattern.
- *
- * MVC components in angular:
- *
- * * Model — The Model is scope properties; scopes are attached to the DOM where scope properties
- *   are accessed through bindings.
- * * View — The template (HTML with data bindings) that is rendered into the View.
- * * Controller — The `ngController` directive specifies a Controller class; the class contains business
- *   logic behind the application to decorate the scope with functions and values
- *
- * Note that you can also attach controllers to the DOM by declaring it in a route definition
- * via the {@link ngRoute.$route $route} service. A common mistake is to declare the controller
- * again using `ng-controller` in the template itself.  This will cause the controller to be attached
- * and executed twice.
- *
- * @element ANY
- * @scope
- * @param {expression} ngController Name of a globally accessible constructor function or an
- *     {@link guide/expression expression} that on the current scope evaluates to a
- *     constructor function. The controller instance can be published into a scope property
- *     by specifying `as propertyName`.
- *
- * @example
- * Here is a simple form for editing user contact information. Adding, removing, clearing, and
- * greeting are methods declared on the controller (see source tab). These methods can
- * easily be called from the angular markup. Notice that the scope becomes the `this` for the
- * controller's instance. This allows for easy access to the view data from the controller. Also
- * notice that any changes to the data are automatically reflected in the View without the need
- * for a manual update. The example is shown in two different declaration styles you may use
- * according to preference.
-   <doc:example>
-     <doc:source>
-      <script>
-        function SettingsController1() {
-          this.name = "John Smith";
-          this.contacts = [
-            {type: 'phone', value: '408 555 1212'},
-            {type: 'email', value: 'john.smith@example.org'} ];
-          };
-
-        SettingsController1.prototype.greet = function() {
-          alert(this.name);
-        };
-
-        SettingsController1.prototype.addContact = function() {
-          this.contacts.push({type: 'email', value: 'yourname@example.org'});
-        };
-
-        SettingsController1.prototype.removeContact = function(contactToRemove) {
-         var index = this.contacts.indexOf(contactToRemove);
-          this.contacts.splice(index, 1);
-        };
-
-        SettingsController1.prototype.clearContact = function(contact) {
-          contact.type = 'phone';
-          contact.value = '';
-        };
-      </script>
-      <div id="ctrl-as-exmpl" ng-controller="SettingsController1 as settings">
-        Name: <input type="text" ng-model="settings.name"/>
-        [ <a href="" ng-click="settings.greet()">greet</a> ]<br/>
-        Contact:
-        <ul>
-          <li ng-repeat="contact in settings.contacts">
-            <select ng-model="contact.type">
-               <option>phone</option>
-               <option>email</option>
-            </select>
-            <input type="text" ng-model="contact.value"/>
-            [ <a href="" ng-click="settings.clearContact(contact)">clear</a>
-            | <a href="" ng-click="settings.removeContact(contact)">X</a> ]
-          </li>
-          <li>[ <a href="" ng-click="settings.addContact()">add</a> ]</li>
-       </ul>
-      </div>
-     </doc:source>
-     <doc:scenario>
-       it('should check controller as', function() {
-         expect(element('#ctrl-as-exmpl>:input').val()).toBe('John Smith');
-         expect(element('#ctrl-as-exmpl li:nth-child(1) input').val())
-           .toBe('408 555 1212');
-         expect(element('#ctrl-as-exmpl li:nth-child(2) input').val())
-           .toBe('john.smith@example.org');
-
-         element('#ctrl-as-exmpl li:first a:contains("clear")').click();
-         expect(element('#ctrl-as-exmpl li:first input').val()).toBe('');
-
-         element('#ctrl-as-exmpl li:last a:contains("add")').click();
-         expect(element('#ctrl-as-exmpl li:nth-child(3) input').val())
-           .toBe('yourname@example.org');
-       });
-     </doc:scenario>
-   </doc:example>
-    <doc:example>
-     <doc:source>
-      <script>
-        function SettingsController2($scope) {
-          $scope.name = "John Smith";
-          $scope.contacts = [
-            {type:'phone', value:'408 555 1212'},
-            {type:'email', value:'john.smith@example.org'} ];
-
-          $scope.greet = function() {
-           alert(this.name);
-          };
-
-          $scope.addContact = function() {
-           this.contacts.push({type:'email', value:'yourname@example.org'});
-          };
-
-          $scope.removeContact = function(contactToRemove) {
-           var index = this.contacts.indexOf(contactToRemove);
-           this.contacts.splice(index, 1);
-          };
-
-          $scope.clearContact = function(contact) {
-           contact.type = 'phone';
-           contact.value = '';
-          };
-        }
-      </script>
-      <div id="ctrl-exmpl" ng-controller="SettingsController2">
-        Name: <input type="text" ng-model="name"/>
-        [ <a href="" ng-click="greet()">greet</a> ]<br/>
-        Contact:
-        <ul>
-          <li ng-repeat="contact in contacts">
-            <select ng-model="contact.type">
-               <option>phone</option>
-               <option>email</option>
-            </select>
-            <input type="text" ng-model="contact.value"/>
-            [ <a href="" ng-click="clearContact(contact)">clear</a>
-            | <a href="" ng-click="removeContact(contact)">X</a> ]
-          </li>
-          <li>[ <a href="" ng-click="addContact()">add</a> ]</li>
-       </ul>
-      </div>
-     </doc:source>
-     <doc:scenario>
-       it('should check controller', function() {
-         expect(element('#ctrl-exmpl>:input').val()).toBe('John Smith');
-         expect(element('#ctrl-exmpl li:nth-child(1) input').val())
-           .toBe('408 555 1212');
-         expect(element('#ctrl-exmpl li:nth-child(2) input').val())
-           .toBe('john.smith@example.org');
-
-         element('#ctrl-exmpl li:first a:contains("clear")').click();
-         expect(element('#ctrl-exmpl li:first input').val()).toBe('');
-
-         element('#ctrl-exmpl li:last a:contains("add")').click();
-         expect(element('#ctrl-exmpl li:nth-child(3) input').val())
-           .toBe('yourname@example.org');
-       });
-     </doc:scenario>
-   </doc:example>
-
- */
-var ngControllerDirective = [function() {
-  return {
-    scope: true,
-    controller: '@',
-    priority: 500
-  };
-}];
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngCsp
- *
- * @element html
- * @description
- * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
- *
- * This is necessary when developing things like Google Chrome Extensions.
- *
- * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things).
- * For us to be compatible, we just need to implement the "getterFn" in $parse without violating
- * any of these restrictions.
- *
- * AngularJS uses `Function(string)` generated functions as a speed optimization. Applying the `ngCsp`
- * directive will cause Angular to use CSP compatibility mode. When this mode is on AngularJS will
- * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will
- * be raised.
- *
- * CSP forbids JavaScript to inline stylesheet rules. In non CSP mode Angular automatically
- * includes some CSS rules (e.g. {@link ng.directive:ngCloak ngCloak}).
- * To make those directives work in CSP mode, include the `angular-csp.css` manually.
- *
- * In order to use this feature put the `ngCsp` directive on the root element of the application.
- *
- * *Note: This directive is only available in the `ng-csp` and `data-ng-csp` attribute form.*
- *
- * @example
- * This example shows how to apply the `ngCsp` directive to the `html` tag.
-   <pre>
-     <!doctype html>
-     <html ng-app ng-csp>
-     ...
-     ...
-     </html>
-   </pre>
- */
-
-// ngCsp is not implemented as a proper directive any more, because we need it be processed while we bootstrap
-// the system (before $parse is instantiated), for this reason we just have a csp() fn that looks for ng-csp attribute
-// anywhere in the current doc
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngClick
- *
- * @description
- * The ngClick directive allows you to specify custom behavior when
- * an element is clicked.
- *
- * @element ANY
- * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
- * click. (Event object is available as `$event`)
- *
- * @example
-   <doc:example>
-     <doc:source>
-      <button ng-click="count = count + 1" ng-init="count=0">
-        Increment
-      </button>
-      count: {{count}}
-     </doc:source>
-     <doc:scenario>
-       it('should check ng-click', function() {
-         expect(binding('count')).toBe('0');
-         element('.doc-example-live :button').click();
-         expect(binding('count')).toBe('1');
-       });
-     </doc:scenario>
-   </doc:example>
- */
-/*
- * A directive that allows creation of custom onclick handlers that are defined as angular
- * expressions and are compiled and executed within the current scope.
- *
- * Events that are handled via these handler are always configured not to propagate further.
- */
-var ngEventDirectives = {};
-forEach(
-  'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
-  function(name) {
-    var directiveName = directiveNormalize('ng-' + name);
-    ngEventDirectives[directiveName] = ['$parse', function($parse) {
-      return {
-        compile: function($element, attr) {
-          var fn = $parse(attr[directiveName]);
-          return function(scope, element, attr) {
-            element.on(lowercase(name), function(event) {
-              scope.$apply(function() {
-                fn(scope, {$event:event});
-              });
-            });
-          };
-        }
-      };
-    }];
-  }
-);
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngDblclick
- *
- * @description
- * The `ngDblclick` directive allows you to specify custom behavior on a dblclick event.
- *
- * @element ANY
- * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon
- * a dblclick. (The Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngMousedown
- *
- * @description
- * The ngMousedown directive allows you to specify custom behavior on mousedown event.
- *
- * @element ANY
- * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon
- * mousedown. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngMouseup
- *
- * @description
- * Specify custom behavior on mouseup event.
- *
- * @element ANY
- * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
- * mouseup. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngMouseover
- *
- * @description
- * Specify custom behavior on mouseover event.
- *
- * @element ANY
- * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon
- * mouseover. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngMouseenter
- *
- * @description
- * Specify custom behavior on mouseenter event.
- *
- * @element ANY
- * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon
- * mouseenter. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngMouseleave
- *
- * @description
- * Specify custom behavior on mouseleave event.
- *
- * @element ANY
- * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon
- * mouseleave. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngMousemove
- *
- * @description
- * Specify custom behavior on mousemove event.
- *
- * @element ANY
- * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon
- * mousemove. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngKeydown
- *
- * @description
- * Specify custom behavior on keydown event.
- *
- * @element ANY
- * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
- * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngKeyup
- *
- * @description
- * Specify custom behavior on keyup event.
- *
- * @element ANY
- * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
- * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngKeypress
- *
- * @description
- * Specify custom behavior on keypress event.
- *
- * @element ANY
- * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon
- * keypress. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngSubmit
- *
- * @description
- * Enables binding angular expressions to onsubmit events.
- *
- * Additionally it prevents the default action (which for form means sending the request to the
- * server and reloading the current page) **but only if the form does not contain an `action`
- * attribute**.
- *
- * @element form
- * @param {expression} ngSubmit {@link guide/expression Expression} to eval. (Event object is available as `$event`)
- *
- * @example
-   <doc:example>
-     <doc:source>
-      <script>
-        function Ctrl($scope) {
-          $scope.list = [];
-          $scope.text = 'hello';
-          $scope.submit = function() {
-            if (this.text) {
-              this.list.push(this.text);
-              this.text = '';
-            }
-          };
-        }
-      </script>
-      <form ng-submit="submit()" ng-controller="Ctrl">
-        Enter text and hit enter:
-        <input type="text" ng-model="text" name="text" />
-        <input type="submit" id="submit" value="Submit" />
-        <pre>list={{list}}</pre>
-      </form>
-     </doc:source>
-     <doc:scenario>
-       it('should check ng-submit', function() {
-         expect(binding('list')).toBe('[]');
-         element('.doc-example-live #submit').click();
-         expect(binding('list')).toBe('["hello"]');
-         expect(input('text').val()).toBe('');
-       });
-       it('should ignore empty strings', function() {
-         expect(binding('list')).toBe('[]');
-         element('.doc-example-live #submit').click();
-         element('.doc-example-live #submit').click();
-         expect(binding('list')).toBe('["hello"]');
-       });
-     </doc:scenario>
-   </doc:example>
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngFocus
- *
- * @description
- * Specify custom behavior on focus event.
- *
- * @element window, input, select, textarea, a
- * @param {expression} ngFocus {@link guide/expression Expression} to evaluate upon
- * focus. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngBlur
- *
- * @description
- * Specify custom behavior on blur event.
- *
- * @element window, input, select, textarea, a
- * @param {expression} ngBlur {@link guide/expression Expression} to evaluate upon
- * blur. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngCopy
- *
- * @description
- * Specify custom behavior on copy event.
- *
- * @element window, input, select, textarea, a
- * @param {expression} ngCopy {@link guide/expression Expression} to evaluate upon
- * copy. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngCut
- *
- * @description
- * Specify custom behavior on cut event.
- *
- * @element window, input, select, textarea, a
- * @param {expression} ngCut {@link guide/expression Expression} to evaluate upon
- * cut. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngPaste
- *
- * @description
- * Specify custom behavior on paste event.
- *
- * @element window, input, select, textarea, a
- * @param {expression} ngPaste {@link guide/expression Expression} to evaluate upon
- * paste. (Event object is available as `$event`)
- *
- * @example
- * See {@link ng.directive:ngClick ngClick}
- */
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngIf
- * @restrict A
- *
- * @description
- * The `ngIf` directive removes or recreates a portion of the DOM tree based on an
- * {expression}. If the expression assigned to `ngIf` evaluates to a false
- * value then the element is removed from the DOM, otherwise a clone of the
- * element is reinserted into the DOM.
- *
- * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the
- * element in the DOM rather than changing its visibility via the `display` css property.  A common
- * case when this difference is significant is when using css selectors that rely on an element's
- * position within the DOM, such as the `:first-child` or `:last-child` pseudo-classes.
- *
- * Note that when an element is removed using `ngIf` its scope is destroyed and a new scope
- * is created when the element is restored.  The scope created within `ngIf` inherits from
- * its parent scope using
- * {@link https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance prototypal inheritance}.
- * An important implication of this is if `ngModel` is used within `ngIf` to bind to
- * a javascript primitive defined in the parent scope. In this case any modifications made to the
- * variable within the child scope will override (hide) the value in the parent scope.
- *
- * Also, `ngIf` recreates elements using their compiled state. An example of this behavior
- * is if an element's class attribute is directly modified after it's compiled, using something like
- * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element
- * the added class will be lost because the original compiled state is used to regenerate the element.
- *
- * Additionally, you can provide animations via the `ngAnimate` module to animate the `enter`
- * and `leave` effects.
- *
- * @animations
- * enter - happens just after the ngIf contents change and a new DOM element is created and injected into the ngIf container
- * leave - happens just before the ngIf contents are removed from the DOM
- *
- * @element ANY
- * @scope
- * @priority 600
- * @param {expression} ngIf If the {@link guide/expression expression} is falsy then
- *     the element is removed from the DOM tree. If it is truthy a copy of the compiled
- *     element is added to the DOM tree.
- *
- * @example
-  <example animations="true">
-    <file name="index.html">
-      Click me: <input type="checkbox" ng-model="checked" ng-init="checked=true" /><br/>
-      Show when checked:
-      <span ng-if="checked" class="animate-if">
-        I'm removed when the checkbox is unchecked.
-      </span>
-    </file>
-    <file name="animations.css">
-      .animate-if {
-        background:white;
-        border:1px solid black;
-        padding:10px;
-      }
-
-      /&#42;
-        The transition styles can also be placed on the CSS base class above
-      &#42;/
-      .animate-if.ng-enter, .animate-if.ng-leave {
-        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-      }
-
-      .animate-if.ng-enter,
-      .animate-if.ng-leave.ng-leave-active {
-        opacity:0;
-      }
-
-      .animate-if.ng-leave,
-      .animate-if.ng-enter.ng-enter-active {
-        opacity:1;
-      }
-    </file>
-  </example>
- */
-var ngIfDirective = ['$animate', function($animate) {
-  return {
-    transclude: 'element',
-    priority: 600,
-    terminal: true,
-    restrict: 'A',
-    $$tlb: true,
-    link: function ($scope, $element, $attr, ctrl, $transclude) {
-        var block, childScope;
-        $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
-
-          if (toBoolean(value)) {
-            if (!childScope) {
-              childScope = $scope.$new();
-              $transclude(childScope, function (clone) {
-                clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
-                // Note: We only need the first/last node of the cloned nodes.
-                // However, we need to keep the reference to the jqlite wrapper as it might be changed later
-                // by a directive with templateUrl when it's template arrives.
-                block = {
-                  clone: clone
-                };
-                $animate.enter(clone, $element.parent(), $element);
-              });
-            }
-          } else {
-
-            if (childScope) {
-              childScope.$destroy();
-              childScope = null;
-            }
-
-            if (block) {
-              $animate.leave(getBlockElements(block.clone));
-              block = null;
-            }
-          }
-        });
-    }
-  };
-}];
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngInclude
- * @restrict ECA
- *
- * @description
- * Fetches, compiles and includes an external HTML fragment.
- *
- * By default, the template URL is restricted to the same domain and protocol as the
- * application document. This is done by calling {@link ng.$sce#methods_getTrustedResourceUrl
- * $sce.getTrustedResourceUrl} on it. To load templates from other domains or protocols
- * you may either {@link ng.$sceDelegateProvider#methods_resourceUrlWhitelist whitelist them} or
- * {@link ng.$sce#methods_trustAsResourceUrl wrap them} as trusted values. Refer to Angular's {@link
- * ng.$sce Strict Contextual Escaping}.
- *
- * In addition, the browser's
- * {@link https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest
- * Same Origin Policy} and {@link http://www.w3.org/TR/cors/ Cross-Origin Resource Sharing
- * (CORS)} policy may further restrict whether the template is successfully loaded.
- * For example, `ngInclude` won't work for cross-domain requests on all browsers and for `file://`
- * access on some browsers.
- *
- * @animations
- * enter - animation is used to bring new content into the browser.
- * leave - animation is used to animate existing content away.
- *
- * The enter and leave animation occur concurrently.
- *
- * @scope
- * @priority 400
- *
- * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant,
- *                 make sure you wrap it in quotes, e.g. `src="'myPartialTemplate.html'"`.
- * @param {string=} onload Expression to evaluate when a new partial is loaded.
- *
- * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll
- *                  $anchorScroll} to scroll the viewport after the content is loaded.
- *
- *                  - If the attribute is not set, disable scrolling.
- *                  - If the attribute is set without value, enable scrolling.
- *                  - Otherwise enable scrolling only if the expression evaluates to truthy value.
- *
- * @example
-  <example animations="true">
-    <file name="index.html">
-     <div ng-controller="Ctrl">
-       <select ng-model="template" ng-options="t.name for t in templates">
-        <option value="">(blank)</option>
-       </select>
-       url of the template: <tt>{{template.url}}</tt>
-       <hr/>
-       <div class="slide-animate-container">
-         <div class="slide-animate" ng-include="template.url"></div>
-       </div>
-     </div>
-    </file>
-    <file name="script.js">
-      function Ctrl($scope) {
-        $scope.templates =
-          [ { name: 'template1.html', url: 'template1.html'}
-          , { name: 'template2.html', url: 'template2.html'} ];
-        $scope.template = $scope.templates[0];
-      }
-     </file>
-    <file name="template1.html">
-      Content of template1.html
-    </file>
-    <file name="template2.html">
-      Content of template2.html
-    </file>
-    <file name="animations.css">
-      .slide-animate-container {
-        position:relative;
-        background:white;
-        border:1px solid black;
-        height:40px;
-        overflow:hidden;
-      }
-
-      .slide-animate {
-        padding:10px;
-      }
-
-      .slide-animate.ng-enter, .slide-animate.ng-leave {
-        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-
-        position:absolute;
-        top:0;
-        left:0;
-        right:0;
-        bottom:0;
-        display:block;
-        padding:10px;
-      }
-
-      .slide-animate.ng-enter {
-        top:-50px;
-      }
-      .slide-animate.ng-enter.ng-enter-active {
-        top:0;
-      }
-
-      .slide-animate.ng-leave {
-        top:0;
-      }
-      .slide-animate.ng-leave.ng-leave-active {
-        top:50px;
-      }
-    </file>
-    <file name="scenario.js">
-      it('should load template1.html', function() {
-       expect(element('.doc-example-live [ng-include]').text()).
-         toMatch(/Content of template1.html/);
-      });
-      it('should load template2.html', function() {
-       select('template').option('1');
-       expect(element('.doc-example-live [ng-include]').text()).
-         toMatch(/Content of template2.html/);
-      });
-      it('should change to blank', function() {
-       select('template').option('');
-       expect(element('.doc-example-live [ng-include]')).toBe(undefined);
-      });
-    </file>
-  </example>
- */
-
-
-/**
- * @ngdoc event
- * @name ng.directive:ngInclude#$includeContentRequested
- * @eventOf ng.directive:ngInclude
- * @eventType emit on the scope ngInclude was declared in
- * @description
- * Emitted every time the ngInclude content is requested.
- */
-
-
-/**
- * @ngdoc event
- * @name ng.directive:ngInclude#$includeContentLoaded
- * @eventOf ng.directive:ngInclude
- * @eventType emit on the current ngInclude scope
- * @description
- * Emitted every time the ngInclude content is reloaded.
- */
-var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce',
-                  function($http,   $templateCache,   $anchorScroll,   $animate,   $sce) {
-  return {
-    restrict: 'ECA',
-    priority: 400,
-    terminal: true,
-    transclude: 'element',
-    controller: angular.noop,
-    compile: function(element, attr) {
-      var srcExp = attr.ngInclude || attr.src,
-          onloadExp = attr.onload || '',
-          autoScrollExp = attr.autoscroll;
-
-      return function(scope, $element, $attr, ctrl, $transclude) {
-        var changeCounter = 0,
-            currentScope,
-            currentElement;
-
-        var cleanupLastIncludeContent = function() {
-          if (currentScope) {
-            currentScope.$destroy();
-            currentScope = null;
-          }
-          if(currentElement) {
-            $animate.leave(currentElement);
-            currentElement = null;
-          }
-        };
-
-        scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {
-          var afterAnimation = function() {
-            if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
-              $anchorScroll();
-            }
-          };
-          var thisChangeId = ++changeCounter;
-
-          if (src) {
-            $http.get(src, {cache: $templateCache}).success(function(response) {
-              if (thisChangeId !== changeCounter) return;
-              var newScope = scope.$new();
-              ctrl.template = response;
-
-              // Note: This will also link all children of ng-include that were contained in the original
-              // html. If that content contains controllers, ... they could pollute/change the scope.
-              // However, using ng-include on an element with additional content does not make sense...
-              // Note: We can't remove them in the cloneAttchFn of $transclude as that
-              // function is called before linking the content, which would apply child
-              // directives to non existing elements.
-              var clone = $transclude(newScope, function(clone) {
-                cleanupLastIncludeContent();
-                $animate.enter(clone, null, $element, afterAnimation);
-              });
-
-              currentScope = newScope;
-              currentElement = clone;
-
-              currentScope.$emit('$includeContentLoaded');
-              scope.$eval(onloadExp);
-            }).error(function() {
-              if (thisChangeId === changeCounter) cleanupLastIncludeContent();
-            });
-            scope.$emit('$includeContentRequested');
-          } else {
-            cleanupLastIncludeContent();
-            ctrl.template = null;
-          }
-        });
-      };
-    }
-  };
-}];
-
-// This directive is called during the $transclude call of the first `ngInclude` directive.
-// It will replace and compile the content of the element with the loaded template.
-// We need this directive so that the element content is already filled when
-// the link function of another directive on the same element as ngInclude
-// is called.
-var ngIncludeFillContentDirective = ['$compile',
-  function($compile) {
-    return {
-      restrict: 'ECA',
-      priority: -400,
-      require: 'ngInclude',
-      link: function(scope, $element, $attr, ctrl) {
-        $element.html(ctrl.template);
-        $compile($element.contents())(scope);
-      }
-    };
-  }];
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngInit
- * @restrict AC
- *
- * @description
- * The `ngInit` directive allows you to evaluate an expression in the
- * current scope.
- *
- * <div class="alert alert-error">
- * The only appropriate use of `ngInit` for aliasing special properties of
- * {@link api/ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
- * should use {@link guide/controller controllers} rather than `ngInit`
- * to initialize values on a scope.
- * </div>
- *
- * @priority 450
- *
- * @element ANY
- * @param {expression} ngInit {@link guide/expression Expression} to eval.
- *
- * @example
-   <doc:example>
-     <doc:source>
-   <script>
-     function Ctrl($scope) {
-       $scope.list = [['a', 'b'], ['c', 'd']];
-     }
-   </script>
-   <div ng-controller="Ctrl">
-     <div ng-repeat="innerList in list" ng-init="outerIndex = $index">
-       <div ng-repeat="value in innerList" ng-init="innerIndex = $index">
-          <span class="example-init">list[ {{outerIndex}} ][ {{innerIndex}} ] = {{value}};</span>
-       </div>
-     </div>
-   </div>
-     </doc:source>
-     <doc:scenario>
-       it('should alias index positions', function() {
-         expect(element('.example-init').text())
-           .toBe('list[ 0 ][ 0 ] = a;' +
-                 'list[ 0 ][ 1 ] = b;' +
-                 'list[ 1 ][ 0 ] = c;' +
-                 'list[ 1 ][ 1 ] = d;');
-       });
-     </doc:scenario>
-   </doc:example>
- */
-var ngInitDirective = ngDirective({
-  priority: 450,
-  compile: function() {
-    return {
-      pre: function(scope, element, attrs) {
-        scope.$eval(attrs.ngInit);
-      }
-    };
-  }
-});
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngNonBindable
- * @restrict AC
- * @priority 1000
- *
- * @description
- * The `ngNonBindable` directive tells Angular not to compile or bind the contents of the current
- * DOM element. This is useful if the element contains what appears to be Angular directives and
- * bindings but which should be ignored by Angular. This could be the case if you have a site that
- * displays snippets of code, for instance.
- *
- * @element ANY
- *
- * @example
- * In this example there are two locations where a simple interpolation binding (`{{}}`) is present,
- * but the one wrapped in `ngNonBindable` is left alone.
- *
- * @example
-    <doc:example>
-      <doc:source>
-        <div>Normal: {{1 + 2}}</div>
-        <div ng-non-bindable>Ignored: {{1 + 2}}</div>
-      </doc:source>
-      <doc:scenario>
-       it('should check ng-non-bindable', function() {
-         expect(using('.doc-example-live').binding('1 + 2')).toBe('3');
-         expect(using('.doc-example-live').element('div:last').text()).
-           toMatch(/1 \+ 2/);
-       });
-      </doc:scenario>
-    </doc:example>
- */
-var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 });
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngPluralize
- * @restrict EA
- *
- * @description
- * # Overview
- * `ngPluralize` is a directive that displays messages according to en-US localization rules.
- * These rules are bundled with angular.js, but can be overridden
- * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive
- * by specifying the mappings between
- * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
- * plural categories} and the strings to be displayed.
- *
- * # Plural categories and explicit number rules
- * There are two
- * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html
- * plural categories} in Angular's default en-US locale: "one" and "other".
- *
- * While a plural category may match many numbers (for example, in en-US locale, "other" can match
- * any number that is not 1), an explicit number rule can only match one number. For example, the
- * explicit number rule for "3" matches the number 3. There are examples of plural categories
- * and explicit number rules throughout the rest of this documentation.
- *
- * # Configuring ngPluralize
- * You configure ngPluralize by providing 2 attributes: `count` and `when`.
- * You can also provide an optional attribute, `offset`.
- *
- * The value of the `count` attribute can be either a string or an {@link guide/expression
- * Angular expression}; these are evaluated on the current scope for its bound value.
- *
- * The `when` attribute specifies the mappings between plural categories and the actual
- * string to be displayed. The value of the attribute should be a JSON object.
- *
- * The following example shows how to configure ngPluralize:
- *
- * <pre>
- * <ng-pluralize count="personCount"
-                 when="{'0': 'Nobody is viewing.',
- *                      'one': '1 person is viewing.',
- *                      'other': '{} people are viewing.'}">
- * </ng-pluralize>
- *</pre>
- *
- * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not
- * specify this rule, 0 would be matched to the "other" category and "0 people are viewing"
- * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for
- * other numbers, for example 12, so that instead of showing "12 people are viewing", you can
- * show "a dozen people are viewing".
- *
- * You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
- * into pluralized strings. In the previous example, Angular will replace `{}` with
- * <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
- * for <span ng-non-bindable>{{numberExpression}}</span>.
- *
- * # Configuring ngPluralize with offset
- * The `offset` attribute allows further customization of pluralized text, which can result in
- * a better user experience. For example, instead of the message "4 people are viewing this document",
- * you might display "John, Kate and 2 others are viewing this document".
- * The offset attribute allows you to offset a number by any desired value.
- * Let's take a look at an example:
- *
- * <pre>
- * <ng-pluralize count="personCount" offset=2
- *               when="{'0': 'Nobody is viewing.',
- *                      '1': '{{person1}} is viewing.',
- *                      '2': '{{person1}} and {{person2}} are viewing.',
- *                      'one': '{{person1}}, {{person2}} and one other person are viewing.',
- *                      'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
- * </ng-pluralize>
- * </pre>
- *
- * Notice that we are still using two plural categories(one, other), but we added
- * three explicit number rules 0, 1 and 2.
- * When one person, perhaps John, views the document, "John is viewing" will be shown.
- * When three people view the document, no explicit number rule is found, so
- * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category.
- * In this case, plural category 'one' is matched and "John, Marry and one other person are viewing"
- * is shown.
- *
- * Note that when you specify offsets, you must provide explicit number rules for
- * numbers from 0 up to and including the offset. If you use an offset of 3, for example,
- * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for
- * plural categories "one" and "other".
- *
- * @param {string|expression} count The variable to be bounded to.
- * @param {string} when The mapping between plural category to its corresponding strings.
- * @param {number=} offset Offset to deduct from the total number.
- *
- * @example
-    <doc:example>
-      <doc:source>
-        <script>
-          function Ctrl($scope) {
-            $scope.person1 = 'Igor';
-            $scope.person2 = 'Misko';
-            $scope.personCount = 1;
-          }
-        </script>
-        <div ng-controller="Ctrl">
-          Person 1:<input type="text" ng-model="person1" value="Igor" /><br/>
-          Person 2:<input type="text" ng-model="person2" value="Misko" /><br/>
-          Number of People:<input type="text" ng-model="personCount" value="1" /><br/>
-
-          <!--- Example with simple pluralization rules for en locale --->
-          Without Offset:
-          <ng-pluralize count="personCount"
-                        when="{'0': 'Nobody is viewing.',
-                               'one': '1 person is viewing.',
-                               'other': '{} people are viewing.'}">
-          </ng-pluralize><br>
-
-          <!--- Example with offset --->
-          With Offset(2):
-          <ng-pluralize count="personCount" offset=2
-                        when="{'0': 'Nobody is viewing.',
-                               '1': '{{person1}} is viewing.',
-                               '2': '{{person1}} and {{person2}} are viewing.',
-                               'one': '{{person1}}, {{person2}} and one other person are viewing.',
-                               'other': '{{person1}}, {{person2}} and {} other people are viewing.'}">
-          </ng-pluralize>
-        </div>
-      </doc:source>
-      <doc:scenario>
-        it('should show correct pluralized string', function() {
-          expect(element('.doc-example-live ng-pluralize:first').text()).
-                                             toBe('1 person is viewing.');
-          expect(element('.doc-example-live ng-pluralize:last').text()).
-                                                toBe('Igor is viewing.');
-
-          using('.doc-example-live').input('personCount').enter('0');
-          expect(element('.doc-example-live ng-pluralize:first').text()).
-                                               toBe('Nobody is viewing.');
-          expect(element('.doc-example-live ng-pluralize:last').text()).
-                                              toBe('Nobody is viewing.');
-
-          using('.doc-example-live').input('personCount').enter('2');
-          expect(element('.doc-example-live ng-pluralize:first').text()).
-                                            toBe('2 people are viewing.');
-          expect(element('.doc-example-live ng-pluralize:last').text()).
-                              toBe('Igor and Misko are viewing.');
-
-          using('.doc-example-live').input('personCount').enter('3');
-          expect(element('.doc-example-live ng-pluralize:first').text()).
-                                            toBe('3 people are viewing.');
-          expect(element('.doc-example-live ng-pluralize:last').text()).
-                              toBe('Igor, Misko and one other person are viewing.');
-
-          using('.doc-example-live').input('personCount').enter('4');
-          expect(element('.doc-example-live ng-pluralize:first').text()).
-                                            toBe('4 people are viewing.');
-          expect(element('.doc-example-live ng-pluralize:last').text()).
-                              toBe('Igor, Misko and 2 other people are viewing.');
-        });
-
-        it('should show data-binded names', function() {
-          using('.doc-example-live').input('personCount').enter('4');
-          expect(element('.doc-example-live ng-pluralize:last').text()).
-              toBe('Igor, Misko and 2 other people are viewing.');
-
-          using('.doc-example-live').input('person1').enter('Di');
-          using('.doc-example-live').input('person2').enter('Vojta');
-          expect(element('.doc-example-live ng-pluralize:last').text()).
-              toBe('Di, Vojta and 2 other people are viewing.');
-        });
-      </doc:scenario>
-    </doc:example>
- */
-var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
-  var BRACE = /{}/g;
-  return {
-    restrict: 'EA',
-    link: function(scope, element, attr) {
-      var numberExp = attr.count,
-          whenExp = attr.$attr.when && element.attr(attr.$attr.when), // we have {{}} in attrs
-          offset = attr.offset || 0,
-          whens = scope.$eval(whenExp) || {},
-          whensExpFns = {},
-          startSymbol = $interpolate.startSymbol(),
-          endSymbol = $interpolate.endSymbol(),
-          isWhen = /^when(Minus)?(.+)$/;
-
-      forEach(attr, function(expression, attributeName) {
-        if (isWhen.test(attributeName)) {
-          whens[lowercase(attributeName.replace('when', '').replace('Minus', '-'))] =
-            element.attr(attr.$attr[attributeName]);
-        }
-      });
-      forEach(whens, function(expression, key) {
-        whensExpFns[key] =
-          $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' +
-            offset + endSymbol));
-      });
-
-      scope.$watch(function ngPluralizeWatch() {
-        var value = parseFloat(scope.$eval(numberExp));
-
-        if (!isNaN(value)) {
-          //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
-          //check it against pluralization rules in $locale service
-          if (!(value in whens)) value = $locale.pluralCat(value - offset);
-           return whensExpFns[value](scope, element, true);
-        } else {
-          return '';
-        }
-      }, function ngPluralizeWatchAction(newVal) {
-        element.text(newVal);
-      });
-    }
-  };
-}];
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngRepeat
- *
- * @description
- * The `ngRepeat` directive instantiates a template once per item from a collection. Each template
- * instance gets its own scope, where the given loop variable is set to the current collection item,
- * and `$index` is set to the item index or key.
- *
- * Special properties are exposed on the local scope of each template instance, including:
- *
- * | Variable  | Type            | Details                                                                     |
- * |-----------|-----------------|-----------------------------------------------------------------------------|
- * | `$index`  | {@type number}  | iterator offset of the repeated element (0..length-1)                       |
- * | `$first`  | {@type boolean} | true if the repeated element is first in the iterator.                      |
- * | `$middle` | {@type boolean} | true if the repeated element is between the first and last in the iterator. |
- * | `$last`   | {@type boolean} | true if the repeated element is last in the iterator.                       |
- * | `$even`   | {@type boolean} | true if the iterator position `$index` is even (otherwise false).           |
- * | `$odd`    | {@type boolean} | true if the iterator position `$index` is odd (otherwise false).            |
- *
- *
- * # Special repeat start and end points
- * To repeat a series of elements instead of just one parent element, ngRepeat (as well as other ng directives) supports extending
- * the range of the repeater by defining explicit start and end points by using **ng-repeat-start** and **ng-repeat-end** respectively.
- * The **ng-repeat-start** directive works the same as **ng-repeat**, but will repeat all the HTML code (including the tag it's defined on)
- * up to and including the ending HTML tag where **ng-repeat-end** is placed.
- *
- * The example below makes use of this feature:
- * <pre>
- *   <header ng-repeat-start="item in items">
- *     Header {{ item }}
- *   </header>
- *   <div class="body">
- *     Body {{ item }}
- *   </div>
- *   <footer ng-repeat-end>
- *     Footer {{ item }}
- *   </footer>
- * </pre>
- *
- * And with an input of {@type ['A','B']} for the items variable in the example above, the output will evaluate to:
- * <pre>
- *   <header>
- *     Header A
- *   </header>
- *   <div class="body">
- *     Body A
- *   </div>
- *   <footer>
- *     Footer A
- *   </footer>
- *   <header>
- *     Header B
- *   </header>
- *   <div class="body">
- *     Body B
- *   </div>
- *   <footer>
- *     Footer B
- *   </footer>
- * </pre>
- *
- * The custom start and end points for ngRepeat also support all other HTML directive syntax flavors provided in AngularJS (such
- * as **data-ng-repeat-start**, **x-ng-repeat-start** and **ng:repeat-start**).
- *
- * @animations
- * enter - when a new item is added to the list or when an item is revealed after a filter
- * leave - when an item is removed from the list or when an item is filtered out
- * move - when an adjacent item is filtered out causing a reorder or when the item contents are reordered
- *
- * @element ANY
- * @scope
- * @priority 1000
- * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These
- *   formats are currently supported:
- *
- *   * `variable in expression` – where variable is the user defined loop variable and `expression`
- *     is a scope expression giving the collection to enumerate.
- *
- *     For example: `album in artist.albums`.
- *
- *   * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers,
- *     and `expression` is the scope expression giving the collection to enumerate.
- *
- *     For example: `(name, age) in {'adam':10, 'amalie':12}`.
- *
- *   * `variable in expression track by tracking_expression` – You can also provide an optional tracking function
- *     which can be used to associate the objects in the collection with the DOM elements. If no tracking function
- *     is specified the ng-repeat associates elements by identity in the collection. It is an error to have
- *     more than one tracking function to resolve to the same key. (This would mean that two distinct objects are
- *     mapped to the same DOM element, which is not possible.)  Filters should be applied to the expression,
- *     before specifying a tracking expression.
- *
- *     For example: `item in items` is equivalent to `item in items track by $id(item)'. This implies that the DOM elements
- *     will be associated by item identity in the array.
- *
- *     For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
- *     `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
- *     with the corresponding item in the array by identity. Moving the same object in array would move the DOM
- *     element in the same way in the DOM.
- *
- *     For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
- *     case the object identity does not matter. Two objects are considered equivalent as long as their `id`
- *     property is same.
- *
- *     For example: `item in items | filter:searchText track by item.id` is a pattern that might be used to apply a filter
- *     to items in conjunction with a tracking expression.
- *
- * @example
- * This example initializes the scope to a list of names and
- * then uses `ngRepeat` to display every person:
-  <example animations="true">
-    <file name="index.html">
-      <div ng-init="friends = [
-        {name:'John', age:25, gender:'boy'},
-        {name:'Jessie', age:30, gender:'girl'},
-        {name:'Johanna', age:28, gender:'girl'},
-        {name:'Joy', age:15, gender:'girl'},
-        {name:'Mary', age:28, gender:'girl'},
-        {name:'Peter', age:95, gender:'boy'},
-        {name:'Sebastian', age:50, gender:'boy'},
-        {name:'Erika', age:27, gender:'girl'},
-        {name:'Patrick', age:40, gender:'boy'},
-        {name:'Samantha', age:60, gender:'girl'}
-      ]">
-        I have {{friends.length}} friends. They are:
-        <input type="search" ng-model="q" placeholder="filter friends..." />
-        <ul class="example-animate-container">
-          <li class="animate-repeat" ng-repeat="friend in friends | filter:q">
-            [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
-          </li>
-        </ul>
-      </div>
-    </file>
-    <file name="animations.css">
-      .example-animate-container {
-        background:white;
-        border:1px solid black;
-        list-style:none;
-        margin:0;
-        padding:0 10px;
-      }
-
-      .animate-repeat {
-        line-height:40px;
-        list-style:none;
-        box-sizing:border-box;
-      }
-
-      .animate-repeat.ng-move,
-      .animate-repeat.ng-enter,
-      .animate-repeat.ng-leave {
-        -webkit-transition:all linear 0.5s;
-        transition:all linear 0.5s;
-      }
-
-      .animate-repeat.ng-leave.ng-leave-active,
-      .animate-repeat.ng-move,
-      .animate-repeat.ng-enter {
-        opacity:0;
-        max-height:0;
-      }
-
-      .animate-repeat.ng-leave,
-      .animate-repeat.ng-move.ng-move-active,
-      .animate-repeat.ng-enter.ng-enter-active {
-        opacity:1;
-        max-height:40px;
-      }
-    </file>
-    <file name="scenario.js">
-       it('should render initial data set', function() {
-         var r = using('.doc-example-live').repeater('ul li');
-         expect(r.count()).toBe(10);
-         expect(r.row(0)).toEqual(["1","John","25"]);
-         expect(r.row(1)).toEqual(["2","Jessie","30"]);
-         expect(r.row(9)).toEqual(["10","Samantha","60"]);
-         expect(binding('friends.length')).toBe("10");
-       });
-
-       it('should update repeater when filter predicate changes', function() {
-         var r = using('.doc-example-live').repeater('ul li');
-         expect(r.count()).toBe(10);
-
-         input('q').enter('ma');
-
-         expect(r.count()).toBe(2);
-         expect(r.row(0)).toEqual(["1","Mary","28"]);
-         expect(r.row(1)).toEqual(["2","Samantha","60"]);
-       });
-      </file>
-    </example>
- */
-var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
-  var NG_REMOVED = '$$NG_REMOVED';
-  var ngRepeatMinErr = minErr('ngRepeat');
-  return {
-    transclude: 'element',
-    priority: 1000,
-    terminal: true,
-    $$tlb: true,
-    link: function($scope, $element, $attr, ctrl, $transclude){
-        var expression = $attr.ngRepeat;
-        var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),
-          trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
-          lhs, rhs, valueIdentifier, keyIdentifier,
-          hashFnLocals = {$id: hashKey};
-
-        if (!match) {
-          throw ngRepeatMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
-            expression);
-        }
-
-        lhs = match[1];
-        rhs = match[2];
-        trackByExp = match[4];
-
-        if (trackByExp) {
-          trackByExpGetter = $parse(trackByExp);
-          trackByIdExpFn = function(key, value, index) {
-            // assign key, value, and $index to the locals so that they can be used in hash functions
-            if (keyIdentifier) hashFnLocals[keyIdentifier] = key;
-            hashFnLocals[valueIdentifier] = value;
-            hashFnLocals.$index = index;
-            return trackByExpGetter($scope, hashFnLocals);
-          };
-        } else {
-          trackByIdArrayFn = function(key, value) {
-            return hashKey(value);
-          };
-          trackByIdObjFn = function(key) {
-            return key;
-          };
-        }
-
-        match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);
-        if (!match) {
-          throw ngRepeatMinErr('iidexp', "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'.",
-                                                                    lhs);
-        }
-        valueIdentifier = match[3] || match[1];
-        keyIdentifier = match[2];
-
-        // Store a list of elements from previous run. This is a hash where key is the item from the
-        // iterator, and the value is objects with following properties.
-        //   - scope: bound scope
-        //   - element: previous element.
-        //   - index: position
-        var lastBlockMap = {};
-
-        //watch props
-        $scope.$watchCollection(rhs, function ngRepeatAction(collection){
-          var index, length,
-              previousNode = $element[0],     // current position of the node
-              nextNode,
-              // Same as lastBlockMap but it has the current state. It will become the
-              // lastBlockMap on the next iteration.
-              nextBlockMap = {},
-              arrayLength,
-              childScope,
-              key, value, // key/value of iteration
-              trackById,
-              trackByIdFn,
-              collectionKeys,
-              block,       // last object information {scope, element, id}
-              nextBlockOrder = [],
-              elementsToRemove;
-
-
-          if (isArrayLike(collection)) {
-            collectionKeys = collection;
-            trackByIdFn = trackByIdExpFn || trackByIdArrayFn;
-          } else {
-            trackByIdFn = trackByIdExpFn || trackByIdObjFn;
-            // if object, extract keys, sort them and use to determine order of iteration over obj props
-            collectionKeys = [];
-            for (key in collection) {
-              if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {
-                collectionKeys.push(key);
-              }
-            }
-            collectionKeys.sort();
-          }
-
-          arrayLength = collectionKeys.length;
-
-          // locate existing items
-          length = nextBlockOrder.length = collectionKeys.length;
-          for(index = 0; index < length; index++) {
-           key = (collection === collectionKeys) ? index : collectionKeys[index];
-           value = collection[key];
-           trackById = trackByIdFn(key, value, index);
-           assertNotHasOwnProperty(trackById, '`track by` id');
-           if(lastBlockMap.hasOwnProperty(trackById)) {
-             block = lastBlockMap[trackById];
-             delete lastBlockMap[trackById];
-             nextBlockMap[trackById] = block;
-             nextBlockOrder[index] = block;
-           } else if (nextBlockMap.hasOwnProperty(trackById)) {
-             // restore lastBlockMap
-             forEach(nextBlockOrder, function(block) {
-               if (block && block.scope) lastBlockMap[block.id] = block;
-             });
-             // This is a duplicate and we need to throw an error
-             throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}",
-                                                                                                                                                    expression,       trackById);
-           } else {
-             // new never before seen block
-             nextBlockOrder[index] = { id: trackById };
-             nextBlockMap[trackById] = false;
-           }
-         }
-
-          // remove existing items
-          for (key in lastBlockMap) {
-            // lastBlockMap is our own object so we don't need to use special hasOwnPropertyFn
-            if (lastBlockMap.hasOwnProperty(key)) {
-              block = lastBlockMap[key];
-              elementsToRemove = getBlockElements(block.clone);
-              $animate.leave(elementsToRemove);
-              forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; });
-              block.scope.$destroy();
-            }
-          }
-
-          // we are not using forEach for perf reasons (trying to avoid #call)
-          for (index = 0, length = collectionKeys.length; index < length; index++) {
-            key = (collection === collectionKeys) ? index : collectionKeys[index];
-            value = collection[key];
-            block = nextBlockOrder[index];
-            if (nextBlockOrder[index - 1]) previousNode = getBlockEnd(nextBlockOrder[index - 1]);
-
-            if (block.scope) {
-              // if we have already seen this object, then we need to reuse the
-              // associated scope/element
-              childScope = block.scope;
-
-              nextNode = previousNode;
-              do {
-                nextNode = nextNode.nextSibling;
-              } while(nextNode && nextNode[NG_REMOVED]);
-
-              if (getBlockStart(block) != nextNode) {
-                // existing item which got moved
-                $animate.move(getBlockElements(block.clone), null, jqLite(previousNode));
-              }
-              previousNode = getBlockEnd(block);
-            } else {
-              // new item which we don't know about
-              childScope = $scope.$new();
-            }
-
-            childScope[valueIdentifier] = value;
-            if (keyIdentifier) childScope[keyIdentifier] = key;
-            childScope.$index = index;
-            childScope.$first = (index === 0);
-            childScope.$last = (index === (arrayLength - 1));
-            childScope.$middle = !(childScope.$first || childScope.$last);
-            // jshint bitwise: false
-            childScope.$odd = !(childScope.$even = (index&1) === 0);
-            // jshint bitwise: true
-
-            if (!block.scope) {
-              $transclude(childScope, function(clone) {
-                clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
-                $animate.enter(clone, null, jqLite(previousNode));
-                previousNode = clone;
-                block.scope = childScope;
-                // Note: We only need the first/last node of the cloned nodes.
-                // However, we need to keep the reference to the jqlite wrapper as it might be changed later
-                // by a directive with templateUrl when it's template arrives.
-                block.clone = clone;
-                nextBlockMap[block.id] = block;
-              });
-            }
-          }
-          lastBlockMap = nextBlockMap;
-        });
-    }
-  };
-
-  function getBlockStart(block) {
-    return block.clone[0];
-  }
-
-  function getBlockEnd(block) {
-    return block.clone[block.clone.length - 1];
-  }
-}];
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngShow
- *
- * @description
- * The `ngShow` directive shows or hides the given HTML element based on the expression
- * provided to the ngShow attribute. The element is shown or hidden by removing or adding
- * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
- * in AngularJS and sets the display style to none (using an !important flag).
- * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
- *
- * <pre>
- * <!-- when $scope.myValue is truthy (element is visible) -->
- * <div ng-show="myValue"></div>
- *
- * <!-- when $scope.myValue is falsy (element is hidden) -->
- * <div ng-show="myValue" class="ng-hide"></div>
- * </pre>
- *
- * When the ngShow expression evaluates to false then the ng-hide CSS class is added to the class attribute
- * on the element causing it to become hidden. When true, the ng-hide CSS class is removed
- * from the element causing the element not to appear hidden.
- *
- * ## Why is !important used?
- *
- * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
- * can be easily overridden by heavier selectors. For example, something as simple
- * as changing the display style on a HTML list item would make hidden elements appear visible.
- * This also becomes a bigger issue when dealing with CSS frameworks.
- *
- * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
- * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
- * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
- *
- * ### Overriding .ng-hide
- *
- * If you wish to change the hide behavior with ngShow/ngHide then this can be achieved by
- * restating the styles for the .ng-hide class in CSS:
- * <pre>
- * .ng-hide {
- *   //!annotate CSS Specificity|Not to worry, this will override the AngularJS default...
- *   display:block!important;
- *
- *   //this is just another form of hiding an element
- *   position:absolute;
- *   top:-9999px;
- *   left:-9999px;
- * }
- * </pre>
- *
- * Just remember to include the important flag so the CSS override will function.
- *
- * ## A note about animations with ngShow
- *
- * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
- * is true and false. This system works like the animation system present with ngClass except that
- * you must also include the !important flag to override the display property
- * so that you can perform an animation when the element is hidden during the time of the animation.
- *
- * <pre>
- * //
- * //a working example can be found at the bottom of this page
- * //
- * .my-element.ng-hide-add, .my-element.ng-hide-remove {
- *   transition:0.5s linear all;
- *   display:block!important;
- * }
- *
- * .my-element.ng-hide-add { ... }
- * .my-element.ng-hide-add.ng-hide-add-active { ... }
- * .my-element.ng-hide-remove { ... }
- * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
- * </pre>
- *
- * @animations
- * addClass: .ng-hide - happens after the ngShow expression evaluates to a truthy value and the just before contents are set to visible
- * removeClass: .ng-hide - happens after the ngShow expression evaluates to a non truthy value and just before the contents are set to hidden
- *
- * @element ANY
- * @param {expression} ngShow If the {@link guide/expression expression} is truthy
- *     then the element is shown or hidden respectively.
- *
- * @example
-  <example animations="true">
-    <file name="index.html">
-      Click me: <input type="checkbox" ng-model="checked"><br/>
-      <div>
-        Show:
-        <div class="check-element animate-show" ng-show="checked">
-          <span class="icon-thumbs-up"></span> I show up when your checkbox is checked.
-        </div>
-      </div>
-      <div>
-        Hide:
-        <div class="check-element animate-show" ng-hide="checked">
-          <span class="icon-thumbs-down"></span> I hide when your checkbox is checked.
-        </div>
-      </div>
-    </file>
-    <file name="animations.css">
-      .animate-show {
-        -webkit-transition:all linear 0.5s;
-        transition:all linear 0.5s;
-        line-height:20px;
-        opacity:1;
-        padding:10px;
-        border:1px solid black;
-        background:white;
-      }
-
-      .animate-show.ng-hide-add,
-      .animate-show.ng-hide-remove {
-        display:block!important;
-      }
-
-      .animate-show.ng-hide {
-        line-height:0;
-        opacity:0;
-        padding:0 10px;
-      }
-
-      .check-element {
-        padding:10px;
-        border:1px solid black;
-        background:white;
-      }
-    </file>
-    <file name="scenario.js">
-       it('should check ng-show / ng-hide', function() {
-         expect(element('.doc-example-live span:first:hidden').count()).toEqual(1);
-         expect(element('.doc-example-live span:last:visible').count()).toEqual(1);
-
-         input('checked').check();
-
-         expect(element('.doc-example-live span:first:visible').count()).toEqual(1);
-         expect(element('.doc-example-live span:last:hidden').count()).toEqual(1);
-       });
-    </file>
-  </example>
- */
-var ngShowDirective = ['$animate', function($animate) {
-  return function(scope, element, attr) {
-    scope.$watch(attr.ngShow, function ngShowWatchAction(value){
-      $animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide');
-    });
-  };
-}];
-
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngHide
- *
- * @description
- * The `ngHide` directive shows or hides the given HTML element based on the expression
- * provided to the ngHide attribute. The element is shown or hidden by removing or adding
- * the `ng-hide` CSS class onto the element. The `.ng-hide` CSS class is predefined
- * in AngularJS and sets the display style to none (using an !important flag).
- * For CSP mode please add `angular-csp.css` to your html file (see {@link ng.directive:ngCsp ngCsp}).
- *
- * <pre>
- * <!-- when $scope.myValue is truthy (element is hidden) -->
- * <div ng-hide="myValue"></div>
- *
- * <!-- when $scope.myValue is falsy (element is visible) -->
- * <div ng-hide="myValue" class="ng-hide"></div>
- * </pre>
- *
- * When the ngHide expression evaluates to true then the .ng-hide CSS class is added to the class attribute
- * on the element causing it to become hidden. When false, the ng-hide CSS class is removed
- * from the element causing the element not to appear hidden.
- *
- * ## Why is !important used?
- *
- * You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
- * can be easily overridden by heavier selectors. For example, something as simple
- * as changing the display style on a HTML list item would make hidden elements appear visible.
- * This also becomes a bigger issue when dealing with CSS frameworks.
- *
- * By using !important, the show and hide behavior will work as expected despite any clash between CSS selector
- * specificity (when !important isn't used with any conflicting styles). If a developer chooses to override the
- * styling to change how to hide an element then it is just a matter of using !important in their own CSS code.
- *
- * ### Overriding .ng-hide
- *
- * If you wish to change the hide behavior with ngShow/ngHide then this can be achieved by
- * restating the styles for the .ng-hide class in CSS:
- * <pre>
- * .ng-hide {
- *   //!annotate CSS Specificity|Not to worry, this will override the AngularJS default...
- *   display:block!important;
- *
- *   //this is just another form of hiding an element
- *   position:absolute;
- *   top:-9999px;
- *   left:-9999px;
- * }
- * </pre>
- *
- * Just remember to include the important flag so the CSS override will function.
- *
- * ## A note about animations with ngHide
- *
- * Animations in ngShow/ngHide work with the show and hide events that are triggered when the directive expression
- * is true and false. This system works like the animation system present with ngClass, except that
- * you must also include the !important flag to override the display property so
- * that you can perform an animation when the element is hidden during the time of the animation.
- *
- * <pre>
- * //
- * //a working example can be found at the bottom of this page
- * //
- * .my-element.ng-hide-add, .my-element.ng-hide-remove {
- *   transition:0.5s linear all;
- *   display:block!important;
- * }
- *
- * .my-element.ng-hide-add { ... }
- * .my-element.ng-hide-add.ng-hide-add-active { ... }
- * .my-element.ng-hide-remove { ... }
- * .my-element.ng-hide-remove.ng-hide-remove-active { ... }
- * </pre>
- *
- * @animations
- * removeClass: .ng-hide - happens after the ngHide expression evaluates to a truthy value and just before the contents are set to hidden
- * addClass: .ng-hide - happens after the ngHide expression evaluates to a non truthy value and just before the contents are set to visible
- *
- * @element ANY
- * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
- *     the element is shown or hidden respectively.
- *
- * @example
-  <example animations="true">
-    <file name="index.html">
-      Click me: <input type="checkbox" ng-model="checked"><br/>
-      <div>
-        Show:
-        <div class="check-element animate-hide" ng-show="checked">
-          <span class="icon-thumbs-up"></span> I show up when your checkbox is checked.
-        </div>
-      </div>
-      <div>
-        Hide:
-        <div class="check-element animate-hide" ng-hide="checked">
-          <span class="icon-thumbs-down"></span> I hide when your checkbox is checked.
-        </div>
-      </div>
-    </file>
-    <file name="animations.css">
-      .animate-hide {
-        -webkit-transition:all linear 0.5s;
-        transition:all linear 0.5s;
-        line-height:20px;
-        opacity:1;
-        padding:10px;
-        border:1px solid black;
-        background:white;
-      }
-
-      .animate-hide.ng-hide-add,
-      .animate-hide.ng-hide-remove {
-        display:block!important;
-      }
-
-      .animate-hide.ng-hide {
-        line-height:0;
-        opacity:0;
-        padding:0 10px;
-      }
-
-      .check-element {
-        padding:10px;
-        border:1px solid black;
-        background:white;
-      }
-    </file>
-    <file name="scenario.js">
-       it('should check ng-show / ng-hide', function() {
-         expect(element('.doc-example-live .check-element:first:hidden').count()).toEqual(1);
-         expect(element('.doc-example-live .check-element:last:visible').count()).toEqual(1);
-
-         input('checked').check();
-
-         expect(element('.doc-example-live .check-element:first:visible').count()).toEqual(1);
-         expect(element('.doc-example-live .check-element:last:hidden').count()).toEqual(1);
-       });
-    </file>
-  </example>
- */
-var ngHideDirective = ['$animate', function($animate) {
-  return function(scope, element, attr) {
-    scope.$watch(attr.ngHide, function ngHideWatchAction(value){
-      $animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide');
-    });
-  };
-}];
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngStyle
- * @restrict AC
- *
- * @description
- * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally.
- *
- * @element ANY
- * @param {expression} ngStyle {@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
-   <example>
-     <file name="index.html">
-        <input type="button" value="set" ng-click="myStyle={color:'red'}">
-        <input type="button" value="clear" ng-click="myStyle={}">
-        <br/>
-        <span ng-style="myStyle">Sample Text</span>
-        <pre>myStyle={{myStyle}}</pre>
-     </file>
-     <file name="style.css">
-       span {
-         color: black;
-       }
-     </file>
-     <file name="scenario.js">
-       it('should check ng-style', function() {
-         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');
-         element('.doc-example-live :button[value=set]').click();
-         expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)');
-         element('.doc-example-live :button[value=clear]').click();
-         expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)');
-       });
-     </file>
-   </example>
- */
-var ngStyleDirective = ngDirective(function(scope, element, attr) {
-  scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) {
-    if (oldStyles && (newStyles !== oldStyles)) {
-      forEach(oldStyles, function(val, style) { element.css(style, '');});
-    }
-    if (newStyles) element.css(newStyles);
-  }, true);
-});
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngSwitch
- * @restrict EA
- *
- * @description
- * The `ngSwitch` directive is used to conditionally swap DOM structure on your template based on a scope expression.
- * Elements within `ngSwitch` but without `ngSwitchWhen` or `ngSwitchDefault` directives will be preserved at the location
- * as specified in the template.
- *
- * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it
- * from the template cache), `ngSwitch` simply choses one of the nested elements and makes it visible based on which element
- * matches the value obtained from the evaluated expression. In other words, you define a container element
- * (where you place the directive), place an expression on the **`on="..."` attribute**
- * (or the **`ng-switch="..."` attribute**), define any inner elements inside of the directive and place
- * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on
- * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default
- * attribute is displayed.
- *
- * <div class="alert alert-info">
- * Be aware that the attribute values to match against cannot be expressions. They are interpreted
- * as literal string values to match against.
- * For example, **`ng-switch-when="someVal"`** will match against the string `"someVal"` not against the
- * value of the expression `$scope.someVal`.
- * </div>
-
- * @animations
- * enter - happens after the ngSwitch contents change and the matched child element is placed inside the container
- * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM
- *
- * @usage
- * <ANY ng-switch="expression">
- *   <ANY ng-switch-when="matchValue1">...</ANY>
- *   <ANY ng-switch-when="matchValue2">...</ANY>
- *   <ANY ng-switch-default>...</ANY>
- * </ANY>
- *
- *
- * @scope
- * @priority 800
- * @param {*} ngSwitch|on expression to match against <tt>ng-switch-when</tt>.
- * @paramDescription
- * On child elements add:
- *
- * * `ngSwitchWhen`: the case statement to match against. If match then this
- *   case will be displayed. If the same match appears multiple times, all the
- *   elements will be displayed.
- * * `ngSwitchDefault`: the default case when no other case match. If there
- *   are multiple default cases, all of them will be displayed when no other
- *   case match.
- *
- *
- * @example
-  <example animations="true">
-    <file name="index.html">
-      <div ng-controller="Ctrl">
-        <select ng-model="selection" ng-options="item for item in items">
-        </select>
-        <tt>selection={{selection}}</tt>
-        <hr/>
-        <div class="animate-switch-container"
-          ng-switch on="selection">
-            <div class="animate-switch" ng-switch-when="settings">Settings Div</div>
-            <div class="animate-switch" ng-switch-when="home">Home Span</div>
-            <div class="animate-switch" ng-switch-default>default</div>
-        </div>
-      </div>
-    </file>
-    <file name="script.js">
-      function Ctrl($scope) {
-        $scope.items = ['settings', 'home', 'other'];
-        $scope.selection = $scope.items[0];
-      }
-    </file>
-    <file name="animations.css">
-      .animate-switch-container {
-        position:relative;
-        background:white;
-        border:1px solid black;
-        height:40px;
-        overflow:hidden;
-      }
-
-      .animate-switch {
-        padding:10px;
-      }
-
-      .animate-switch.ng-animate {
-        -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-        transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-
-        position:absolute;
-        top:0;
-        left:0;
-        right:0;
-        bottom:0;
-      }
-
-      .animate-switch.ng-leave.ng-leave-active,
-      .animate-switch.ng-enter {
-        top:-50px;
-      }
-      .animate-switch.ng-leave,
-      .animate-switch.ng-enter.ng-enter-active {
-        top:0;
-      }
-    </file>
-    <file name="scenario.js">
-      it('should start in settings', function() {
-        expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/);
-      });
-      it('should change to home', function() {
-        select('selection').option('home');
-        expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/);
-      });
-      it('should select default', function() {
-        select('selection').option('other');
-        expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/);
-      });
-    </file>
-  </example>
- */
-var ngSwitchDirective = ['$animate', function($animate) {
-  return {
-    restrict: 'EA',
-    require: 'ngSwitch',
-
-    // asks for $scope to fool the BC controller module
-    controller: ['$scope', function ngSwitchController() {
-     this.cases = {};
-    }],
-    link: function(scope, element, attr, ngSwitchController) {
-      var watchExpr = attr.ngSwitch || attr.on,
-          selectedTranscludes,
-          selectedElements,
-          selectedScopes = [];
-
-      scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
-        for (var i= 0, ii=selectedScopes.length; i<ii; i++) {
-          selectedScopes[i].$destroy();
-          $animate.leave(selectedElements[i]);
-        }
-
-        selectedElements = [];
-        selectedScopes = [];
-
-        if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
-          scope.$eval(attr.change);
-          forEach(selectedTranscludes, function(selectedTransclude) {
-            var selectedScope = scope.$new();
-            selectedScopes.push(selectedScope);
-            selectedTransclude.transclude(selectedScope, function(caseElement) {
-              var anchor = selectedTransclude.element;
-
-              selectedElements.push(caseElement);
-              $animate.enter(caseElement, anchor.parent(), anchor);
-            });
-          });
-        }
-      });
-    }
-  };
-}];
-
-var ngSwitchWhenDirective = ngDirective({
-  transclude: 'element',
-  priority: 800,
-  require: '^ngSwitch',
-  compile: function(element, attrs) {
-    return function(scope, element, attr, ctrl, $transclude) {
-      ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
-      ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
-    };
-  }
-});
-
-var ngSwitchDefaultDirective = ngDirective({
-  transclude: 'element',
-  priority: 800,
-  require: '^ngSwitch',
-  link: function(scope, element, attr, ctrl, $transclude) {
-    ctrl.cases['?'] = (ctrl.cases['?'] || []);
-    ctrl.cases['?'].push({ transclude: $transclude, element: element });
-   }
-});
-
-/**
- * @ngdoc directive
- * @name ng.directive:ngTransclude
- * @restrict AC
- *
- * @description
- * Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
- *
- * Any existing content of the element that this directive is placed on will be removed before the transcluded content is inserted.
- *
- * @element ANY
- *
- * @example
-   <doc:example module="transclude">
-     <doc:source>
-       <script>
-         function Ctrl($scope) {
-           $scope.title = 'Lorem Ipsum';
-           $scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
-         }
-
-         angular.module('transclude', [])
-          .directive('pane', function(){
-             return {
-               restrict: 'E',
-               transclude: true,
-               scope: { title:'@' },
-               template: '<div style="border: 1px solid black;">' +
-                           '<div style="background-color: gray">{{title}}</div>' +
-                           '<div ng-transclude></div>' +
-                         '</div>'
-             };
-         });
-       </script>
-       <div ng-controller="Ctrl">
-         <input ng-model="title"><br>
-         <textarea ng-model="text"></textarea> <br/>
-         <pane title="{{title}}">{{text}}</pane>
-       </div>
-     </doc:source>
-     <doc:scenario>
-        it('should have transcluded', function() {
-          input('title').enter('TITLE');
-          input('text').enter('TEXT');
-          expect(binding('title')).toEqual('TITLE');
-          expect(binding('text')).toEqual('TEXT');
-        });
-     </doc:scenario>
-   </doc:example>
- *
- */
-var ngTranscludeDirective = ngDirective({
-  controller: ['$element', '$transclude', function($element, $transclude) {
-    if (!$transclude) {
-      throw minErr('ngTransclude')('orphan',
-          'Illegal use of ngTransclude directive in the template! ' +
-          'No parent directive that requires a transclusion found. ' +
-          'Element: {0}',
-          startingTag($element));
-    }
-
-    // remember the transclusion fn but call it during linking so that we don't process transclusion before directives on
-    // the parent element even when the transclusion replaces the current element. (we can't use priority here because
-    // that applies only to compile fns and not controllers
-    this.$transclude = $transclude;
-  }],
-
-  link: function($scope, $element, $attrs, controller) {
-    controller.$transclude(function(clone) {
-      $element.empty();
-      $element.append(clone);
-    });
-  }
-});
-
-/**
- * @ngdoc directive
- * @name ng.directive:script
- * @restrict E
- *
- * @description
- * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the
- * template can be used by `ngInclude`, `ngView` or directive templates.
- *
- * @param {'text/ng-template'} type must be set to `'text/ng-template'`
- *
- * @example
-  <doc:example>
-    <doc:source>
-      <script type="text/ng-template" id="/tpl.html">
-        Content of the template.
-      </script>
-
-      <a ng-click="currentTpl='/tpl.html'" id="tpl-link">Load inlined template</a>
-      <div id="tpl-content" ng-include src="currentTpl"></div>
-    </doc:source>
-    <doc:scenario>
-      it('should load template defined inside script tag', function() {
-        element('#tpl-link').click();
-        expect(element('#tpl-content').text()).toMatch(/Content of the template/);
-      });
-    </doc:scenario>
-  </doc:example>
- */
-var scriptDirective = ['$templateCache', function($templateCache) {
-  return {
-    restrict: 'E',
-    terminal: true,
-    compile: function(element, attr) {
-      if (attr.type == 'text/ng-template') {
-        var templateUrl = attr.id,
-            // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent
-            text = element[0].text;
-
-        $templateCache.put(templateUrl, text);
-      }
-    }
-  };
-}];
-
-var ngOptionsMinErr = minErr('ngOptions');
-/**
- * @ngdoc directive
- * @name ng.directive:select
- * @restrict E
- *
- * @description
- * HTML `SELECT` element with angular data-binding.
- *
- * # `ngOptions`
- *
- * The `ngOptions` attribute can be used to dynamically generate a list of `<option>`
- * elements for the `<select>` element using the array or object obtained by evaluating the
- * `ngOptions` comprehension_expression.
- *
- * When an item in the `<select>` menu is selected, the array element or object property
- * represented by the selected option will be bound to the model identified by the `ngModel`
- * directive.
- *
- * Optionally, a single hard-coded `<option>` element, with the value set to an empty string, can
- * be nested into the `<select>` element. This element will then represent the `null` or "not selected"
- * option. See example below for demonstration.
- *
- * Note: `ngOptions` provides iterator facility for `<option>` element which should be used instead
- * of {@link ng.directive:ngRepeat ngRepeat} when you want the
- * `select` model to be bound to a non-string value. This is because an option element can only
- * be bound to string values at present.
- *
- * @param {string} ngModel Assignable angular expression to data-bind to.
- * @param {string=} name Property name of the form under which the control is published.
- * @param {string=} required The control is considered valid only if value is entered.
- * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
- *    the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
- *    `required` when you want to data-bind to the `required` attribute.
- * @param {comprehension_expression=} ngOptions in one of the following forms:
- *
- *   * for array data sources:
- *     * `label` **`for`** `value` **`in`** `array`
- *     * `select` **`as`** `label` **`for`** `value` **`in`** `array`
- *     * `label`  **`group by`** `group` **`for`** `value` **`in`** `array`
- *     * `select` **`as`** `label` **`group by`** `group` **`for`** `value` **`in`** `array` **`track by`** `trackexpr`
- *   * for object data sources:
- *     * `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
- *     * `select` **`as`** `label` **`for (`**`key` **`,`** `value`**`) in`** `object`
- *     * `label` **`group by`** `group` **`for (`**`key`**`,`** `value`**`) in`** `object`
- *     * `select` **`as`** `label` **`group by`** `group`
- *         **`for` `(`**`key`**`,`** `value`**`) in`** `object`
- *
- * Where:
- *
- *   * `array` / `object`: an expression which evaluates to an array / object to iterate over.
- *   * `value`: local variable which will refer to each item in the `array` or each property value
- *      of `object` during iteration.
- *   * `key`: local variable which will refer to a property name in `object` during iteration.
- *   * `label`: The result of this expression will be the label for `<option>` element. The
- *     `expression` will most likely refer to the `value` variable (e.g. `value.propertyName`).
- *   * `select`: The result of this expression will be bound to the model of the parent `<select>`
- *      element. If not specified, `select` expression will default to `value`.
- *   * `group`: The result of this expression will be used to group options using the `<optgroup>`
- *      DOM element.
- *   * `trackexpr`: Used when working with an array of objects. The result of this expression will be
- *      used to identify the objects in the array. The `trackexpr` will most likely refer to the
- *     `value` variable (e.g. `value.propertyName`).
- *
- * @example
-    <doc:example>
-      <doc:source>
-        <script>
-        function MyCntrl($scope) {
-          $scope.colors = [
-            {name:'black', shade:'dark'},
-            {name:'white', shade:'light'},
-            {name:'red', shade:'dark'},
-            {name:'blue', shade:'dark'},
-            {name:'yellow', shade:'light'}
-          ];
-          $scope.color = $scope.colors[2]; // red
-        }
-        </script>
-        <div ng-controller="MyCntrl">
-          <ul>
-            <li ng-repeat="color in colors">
-              Name: <input ng-model="color.name">
-              [<a href ng-click="colors.splice($index, 1)">X</a>]
-            </li>
-            <li>
-              [<a href ng-click="colors.push({})">add</a>]
-            </li>
-          </ul>
-          <hr/>
-          Color (null not allowed):
-          <select ng-model="color" ng-options="c.name for c in colors"></select><br>
-
-          Color (null allowed):
-          <span  class="nullable">
-            <select ng-model="color" ng-options="c.name for c in colors">
-              <option value="">-- choose color --</option>
-            </select>
-          </span><br/>
-
-          Color grouped by shade:
-          <select ng-model="color" ng-options="c.name group by c.shade for c in colors">
-          </select><br/>
-
-
-          Select <a href ng-click="color={name:'not in list'}">bogus</a>.<br>
-          <hr/>
-          Currently selected: {{ {selected_color:color}  }}
-          <div style="border:solid 1px black; height:20px"
-               ng-style="{'background-color':color.name}">
-          </div>
-        </div>
-      </doc:source>
-      <doc:scenario>
-         it('should check ng-options', function() {
-           expect(binding('{selected_color:color}')).toMatch('red');
-           select('color').option('0');
-           expect(binding('{selected_color:color}')).toMatch('black');
-           using('.nullable').select('color').option('');
-           expect(binding('{selected_color:color}')).toMatch('null');
-         });
-      </doc:scenario>
-    </doc:example>
- */
-
-var ngOptionsDirective = valueFn({ terminal: true });
-// jshint maxlen: false
-var selectDirective = ['$compile', '$parse', function($compile,   $parse) {
-                         //0000111110000000000022220000000000000000000000333300000000000000444444444444444000000000555555555555555000000066666666666666600000000000000007777000000000000000000088888
-  var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/,
-      nullModelCtrl = {$setViewValue: noop};
-// jshint maxlen: 100
-
-  return {
-    restrict: 'E',
-    require: ['select', '?ngModel'],
-    controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) {
-      var self = this,
-          optionsMap = {},
-          ngModelCtrl = nullModelCtrl,
-          nullOption,
-          unknownOption;
-
-
-      self.databound = $attrs.ngModel;
-
-
-      self.init = function(ngModelCtrl_, nullOption_, unknownOption_) {
-        ngModelCtrl = ngModelCtrl_;
-        nullOption = nullOption_;
-        unknownOption = unknownOption_;
-      };
-
-
-      self.addOption = function(value) {
-        assertNotHasOwnProperty(value, '"option value"');
-        optionsMap[value] = true;
-
-        if (ngModelCtrl.$viewValue == value) {
-          $element.val(value);
-          if (unknownOption.parent()) unknownOption.remove();
-        }
-      };
-
-
-      self.removeOption = function(value) {
-        if (this.hasOption(value)) {
-          delete optionsMap[value];
-          if (ngModelCtrl.$viewValue == value) {
-            this.renderUnknownOption(value);
-          }
-        }
-      };
-
-
-      self.renderUnknownOption = function(val) {
-        var unknownVal = '? ' + hashKey(val) + ' ?';
-        unknownOption.val(unknownVal);
-        $element.prepend(unknownOption);
-        $element.val(unknownVal);
-        unknownOption.prop('selected', true); // needed for IE
-      };
-
-
-      self.hasOption = function(value) {
-        return optionsMap.hasOwnProperty(value);
-      };
-
-      $scope.$on('$destroy', function() {
-        // disable unknown option so that we don't do work when the whole select is being destroyed
-        self.renderUnknownOption = noop;
-      });
-    }],
-
-    link: function(scope, element, attr, ctrls) {
-      // if ngModel is not defined, we don't need to do anything
-      if (!ctrls[1]) return;
-
-      var selectCtrl = ctrls[0],
-          ngModelCtrl = ctrls[1],
-          multiple = attr.multiple,
-          optionsExp = attr.ngOptions,
-          nullOption = false, // if false, user will not be able to select it (used by ngOptions)
-          emptyOption,
-          // we can't just jqLite('<option>') since jqLite is not smart enough
-          // to create it in <select> and IE barfs otherwise.
-          optionTemplate = jqLite(document.createElement('option')),
-          optGroupTemplate =jqLite(document.createElement('optgroup')),
-          unknownOption = optionTemplate.clone();
-
-      // find "null" option
-      for(var i = 0, children = element.children(), ii = children.length; i < ii; i++) {
-        if (children[i].value === '') {
-          emptyOption = nullOption = children.eq(i);
-          break;
-        }
-      }
-
-      selectCtrl.init(ngModelCtrl, nullOption, unknownOption);
-
-      // required validator
-      if (multiple && (attr.required || attr.ngRequired)) {
-        var requiredValidator = function(value) {
-          ngModelCtrl.$setValidity('required', !attr.required || (value && value.length));
-          return value;
-        };
-
-        ngModelCtrl.$parsers.push(requiredValidator);
-        ngModelCtrl.$formatters.unshift(requiredValidator);
-
-        attr.$observe('required', function() {
-          requiredValidator(ngModelCtrl.$viewValue);
-        });
-      }
-
-      if (optionsExp) setupAsOptions(scope, element, ngModelCtrl);
-      else if (multiple) setupAsMultiple(scope, element, ngModelCtrl);
-      else setupAsSingle(scope, element, ngModelCtrl, selectCtrl);
-
-
-      ////////////////////////////
-
-
-
-      function setupAsSingle(scope, selectElement, ngModelCtrl, selectCtrl) {
-        ngModelCtrl.$render = function() {
-          var viewValue = ngModelCtrl.$viewValue;
-
-          if (selectCtrl.hasOption(viewValue)) {
-            if (unknownOption.parent()) unknownOption.remove();
-            selectElement.val(viewValue);
-            if (viewValue === '') emptyOption.prop('selected', true); // to make IE9 happy
-          } else {
-            if (isUndefined(viewValue) && emptyOption) {
-              selectElement.val('');
-            } else {
-              selectCtrl.renderUnknownOption(viewValue);
-            }
-          }
-        };
-
-        selectElement.on('change', function() {
-          scope.$apply(function() {
-            if (unknownOption.parent()) unknownOption.remove();
-            ngModelCtrl.$setViewValue(selectElement.val());
-          });
-        });
-      }
-
-      function setupAsMultiple(scope, selectElement, ctrl) {
-        var lastView;
-        ctrl.$render = function() {
-          var items = new HashMap(ctrl.$viewValue);
-          forEach(selectElement.find('option'), function(option) {
-            option.selected = isDefined(items.get(option.value));
-          });
-        };
-
-        // we have to do it on each watch since ngModel watches reference, but
-        // we need to work of an array, so we need to see if anything was inserted/removed
-        scope.$watch(function selectMultipleWatch() {
-          if (!equals(lastView, ctrl.$viewValue)) {
-            lastView = copy(ctrl.$viewValue);
-            ctrl.$render();
-          }
-        });
-
-        selectElement.on('change', function() {
-          scope.$apply(function() {
-            var array = [];
-            forEach(selectElement.find('option'), function(option) {
-              if (option.selected) {
-                array.push(option.value);
-              }
-            });
-            ctrl.$setViewValue(array);
-          });
-        });
-      }
-
-      function setupAsOptions(scope, selectElement, ctrl) {
-        var match;
-
-        if (! (match = optionsExp.match(NG_OPTIONS_REGEXP))) {
-          throw ngOptionsMinErr('iexp',
-            "Expected expression in form of " +
-            "'_select_ (as _label_)? for (_key_,)?_value_ in _collection_'" +
-            " but got '{0}'. Element: {1}",
-            optionsExp, startingTag(selectElement));
-        }
-
-        var displayFn = $parse(match[2] || match[1]),
-            valueName = match[4] || match[6],
-            keyName = match[5],
-            groupByFn = $parse(match[3] || ''),
-            valueFn = $parse(match[2] ? match[1] : valueName),
-            valuesFn = $parse(match[7]),
-            track = match[8],
-            trackFn = track ? $parse(match[8]) : null,
-            // This is an array of array of existing option groups in DOM.
-            // We try to reuse these if possible
-            // - optionGroupsCache[0] is the options with no option group
-            // - optionGroupsCache[?][0] is the parent: either the SELECT or OPTGROUP element
-            optionGroupsCache = [[{element: selectElement, label:''}]];
-
-        if (nullOption) {
-          // compile the element since there might be bindings in it
-          $compile(nullOption)(scope);
-
-          // remove the class, which is added automatically because we recompile the element and it
-          // becomes the compilation root
-          nullOption.removeClass('ng-scope');
-
-          // we need to remove it before calling selectElement.empty() because otherwise IE will
-          // remove the label from the element. wtf?
-          nullOption.remove();
-        }
-
-        // clear contents, we'll add what's needed based on the model
-        selectElement.empty();
-
-        selectElement.on('change', function() {
-          scope.$apply(function() {
-            var optionGroup,
-                collection = valuesFn(scope) || [],
-                locals = {},
-                key, value, optionElement, index, groupIndex, length, groupLength, trackIndex;
-
-            if (multiple) {
-              value = [];
-              for (groupIndex = 0, groupLength = optionGroupsCache.length;
-                   groupIndex < groupLength;
-                   groupIndex++) {
-                // list of options for that group. (first item has the parent)
-                optionGroup = optionGroupsCache[groupIndex];
-
-                for(index = 1, length = optionGroup.length; index < length; index++) {
-                  if ((optionElement = optionGroup[index].element)[0].selected) {
-                    key = optionElement.val();
-                    if (keyName) locals[keyName] = key;
-                    if (trackFn) {
-                      for (trackIndex = 0; trackIndex < collection.length; trackIndex++) {
-                        locals[valueName] = collection[trackIndex];
-                        if (trackFn(scope, locals) == key) break;
-                      }
-                    } else {
-                      locals[valueName] = collection[key];
-                    }
-                    value.push(valueFn(scope, locals));
-                  }
-                }
-              }
-            } else {
-              key = selectElement.val();
-              if (key == '?') {
-                value = undefined;
-              } else if (key === ''){
-                value = null;
-              } else {
-                if (trackFn) {
-                  for (trackIndex = 0; trackIndex < collection.length; trackIndex++) {
-                    locals[valueName] = collection[trackIndex];
-                    if (trackFn(scope, locals) == key) {
-                      value = valueFn(scope, locals);
-                      break;
-                    }
-                  }
-                } else {
-                  locals[valueName] = collection[key];
-                  if (keyName) locals[keyName] = key;
-                  value = valueFn(scope, locals);
-                }
-              }
-            }
-            ctrl.$setViewValue(value);
-          });
-        });
-
-        ctrl.$render = render;
-
-        // TODO(vojta): can't we optimize this ?
-        scope.$watch(render);
-
-        function render() {
-              // Temporary location for the option groups before we render them
-          var optionGroups = {'':[]},
-              optionGroupNames = [''],
-              optionGroupName,
-              optionGroup,
-              option,
-              existingParent, existingOptions, existingOption,
-              modelValue = ctrl.$modelValue,
-              values = valuesFn(scope) || [],
-              keys = keyName ? sortedKeys(values) : values,
-              key,
-              groupLength, length,
-              groupIndex, index,
-              locals = {},
-              selected,
-              selectedSet = false, // nothing is selected yet
-              lastElement,
-              element,
-              label;
-
-          if (multiple) {
-            if (trackFn && isArray(modelValue)) {
-              selectedSet = new HashMap([]);
-              for (var trackIndex = 0; trackIndex < modelValue.length; trackIndex++) {
-                locals[valueName] = modelValue[trackIndex];
-                selectedSet.put(trackFn(scope, locals), modelValue[trackIndex]);
-              }
-            } else {
-              selectedSet = new HashMap(modelValue);
-            }
-          }
-
-          // We now build up the list of options we need (we merge later)
-          for (index = 0; length = keys.length, index < length; index++) {
-            
-            key = index;
-            if (keyName) {
-              key = keys[index];
-              if ( key.charAt(0) === '$' ) continue;
-              locals[keyName] = key;
-            }
-
-            locals[valueName] = values[key];
-
-            optionGroupName = groupByFn(scope, locals) || '';
-            if (!(optionGroup = optionGroups[optionGroupName])) {
-              optionGroup = optionGroups[optionGroupName] = [];
-              optionGroupNames.push(optionGroupName);
-            }
-            if (multiple) {
-              selected = isDefined(
-                selectedSet.remove(trackFn ? trackFn(scope, locals) : valueFn(scope, locals))
-              );
-            } else {
-              if (trackFn) {
-                var modelCast = {};
-                modelCast[valueName] = modelValue;
-                selected = trackFn(scope, modelCast) === trackFn(scope, locals);
-              } else {
-                selected = modelValue === valueFn(scope, locals);
-              }
-              selectedSet = selectedSet || selected; // see if at least one item is selected
-            }
-            label = displayFn(scope, locals); // what will be seen by the user
-
-            // doing displayFn(scope, locals) || '' overwrites zero values
-            label = isDefined(label) ? label : '';
-            optionGroup.push({
-              // either the index into array or key from object
-              id: trackFn ? trackFn(scope, locals) : (keyName ? keys[index] : index),
-              label: label,
-              selected: selected                   // determine if we should be selected
-            });
-          }
-          if (!multiple) {
-            if (nullOption || modelValue === null) {
-              // insert null option if we have a placeholder, or the model is null
-              optionGroups[''].unshift({id:'', label:'', selected:!selectedSet});
-            } else if (!selectedSet) {
-              // option could not be found, we have to insert the undefined item
-              optionGroups[''].unshift({id:'?', label:'', selected:true});
-            }
-          }
-
-          // Now we need to update the list of DOM nodes to match the optionGroups we computed above
-          for (groupIndex = 0, groupLength = optionGroupNames.length;
-               groupIndex < groupLength;
-               groupIndex++) {
-            // current option group name or '' if no group
-            optionGroupName = optionGroupNames[groupIndex];
-
-            // list of options for that group. (first item has the parent)
-            optionGroup = optionGroups[optionGroupName];
-
-            if (optionGroupsCache.length <= groupIndex) {
-              // we need to grow the optionGroups
-              existingParent = {
-                element: optGroupTemplate.clone().attr('label', optionGroupName),
-                label: optionGroup.label
-              };
-              existingOptions = [existingParent];
-              optionGroupsCache.push(existingOptions);
-              selectElement.append(existingParent.element);
-            } else {
-              existingOptions = optionGroupsCache[groupIndex];
-              existingParent = existingOptions[0];  // either SELECT (no group) or OPTGROUP element
-
-              // update the OPTGROUP label if not the same.
-              if (existingParent.label != optionGroupName) {
-                existingParent.element.attr('label', existingParent.label = optionGroupName);
-              }
-            }
-
-            lastElement = null;  // start at the beginning
-            for(index = 0, length = optionGroup.length; index < length; index++) {
-              option = optionGroup[index];
-              if ((existingOption = existingOptions[index+1])) {
-                // reuse elements
-                lastElement = existingOption.element;
-                if (existingOption.label !== option.label) {
-                  lastElement.text(existingOption.label = option.label);
-                }
-                if (existingOption.id !== option.id) {
-                  lastElement.val(existingOption.id = option.id);
-                }
-                // lastElement.prop('selected') provided by jQuery has side-effects
-                if (lastElement[0].selected !== option.selected) {
-                  lastElement.prop('selected', (existingOption.selected = option.selected));
-                }
-              } else {
-                // grow elements
-
-                // if it's a null option
-                if (option.id === '' && nullOption) {
-                  // put back the pre-compiled element
-                  element = nullOption;
-                } else {
-                  // jQuery(v1.4.2) Bug: We should be able to chain the method calls, but
-                  // in this version of jQuery on some browser the .text() returns a string
-                  // rather then the element.
-                  (element = optionTemplate.clone())
-                      .val(option.id)
-                      .attr('selected', option.selected)
-                      .text(option.label);
-                }
-
-                existingOptions.push(existingOption = {
-                    element: element,
-                    label: option.label,
-                    id: option.id,
-                    selected: option.selected
-                });
-                if (lastElement) {
-                  lastElement.after(element);
-                } else {
-                  existingParent.element.append(element);
-                }
-                lastElement = element;
-              }
-            }
-            // remove any excessive OPTIONs in a group
-            index++; // increment since the existingOptions[0] is parent element not OPTION
-            while(existingOptions.length > index) {
-              existingOptions.pop().element.remove();
-            }
-          }
-          // remove any excessive OPTGROUPs from select
-          while(optionGroupsCache.length > groupIndex) {
-            optionGroupsCache.pop()[0].element.remove();
-          }
-        }
-      }
-    }
-  };
-}];
-
-var optionDirective = ['$interpolate', function($interpolate) {
-  var nullSelectCtrl = {
-    addOption: noop,
-    removeOption: noop
-  };
-
-  return {
-    restrict: 'E',
-    priority: 100,
-    compile: function(element, attr) {
-      if (isUndefined(attr.value)) {
-        var interpolateFn = $interpolate(element.text(), true);
-        if (!interpolateFn) {
-          attr.$set('value', element.text());
-        }
-      }
-
-      return function (scope, element, attr) {
-        var selectCtrlName = '$selectController',
-            parent = element.parent(),
-            selectCtrl = parent.data(selectCtrlName) ||
-              parent.parent().data(selectCtrlName); // in case we are in optgroup
-
-        if (selectCtrl && selectCtrl.databound) {
-          // For some reason Opera defaults to true and if not overridden this messes up the repeater.
-          // We don't want the view to drive the initialization of the model anyway.
-          element.prop('selected', false);
-        } else {
-          selectCtrl = nullSelectCtrl;
-        }
-
-        if (interpolateFn) {
-          scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
-            attr.$set('value', newVal);
-            if (newVal !== oldVal) selectCtrl.removeOption(oldVal);
-            selectCtrl.addOption(newVal);
-          });
-        } else {
-          selectCtrl.addOption(attr.value);
-        }
-
-        element.on('$destroy', function() {
-          selectCtrl.removeOption(attr.value);
-        });
-      };
-    }
-  };
-}];
-
-var styleDirective = valueFn({
-  restrict: 'E',
-  terminal: true
-});
-
-  //try to bind to jquery now so that one can write angular.element().read()
-  //but we will rebind on bootstrap again.
-  bindJQuery();
-
-  publishExternalAPI(angular);
-
-  jqLite(document).ready(function() {
-    angularInit(document, bootstrap);
-  });
-
-})(window, document);
-
-!angular.$$csp() && angular.element(document).find('head').prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}ng\\:form{display:block;}.ng-animate-start{border-spacing:1px 1px;-ms-zoom:1.0001;}.ng-animate-active{border-spacing:0px 0px;-ms-zoom:1;}</style>');
\ No newline at end of file
deleted file mode 100644
index 2e8c6eca3c148d6d3ea742cba13b3a60a39230e1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/js/src/jsapi-tests/binast/parser/tester/frameworks/backbone-1.1.js
+++ /dev/null
@@ -1,1581 +0,0 @@
-//     Backbone.js 1.1.0
-
-//     (c) 2010-2011 Jeremy Ashkenas, DocumentCloud Inc.
-//     (c) 2011-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
-//     Backbone may be freely distributed under the MIT license.
-//     For all details and documentation:
-//     http://backbonejs.org
-
-(function(){
-
-  // Initial Setup
-  // -------------
-
-  // Save a reference to the global object (`window` in the browser, `exports`
-  // on the server).
-  var root = this;
-
-  // Save the previous value of the `Backbone` variable, so that it can be
-  // restored later on, if `noConflict` is used.
-  var previousBackbone = root.Backbone;
-
-  // Create local references to array methods we'll want to use later.
-  var array = [];
-  var push = array.push;
-  var slice = array.slice;
-  var splice = array.splice;
-
-  // The top-level namespace. All public Backbone classes and modules will
-  // be attached to this. Exported for both the browser and the server.
-  var Backbone;
-  if (typeof exports !== 'undefined') {
-    Backbone = exports;
-  } else {
-    Backbone = root.Backbone = {};
-  }
-
-  // Current version of the library. Keep in sync with `package.json`.
-  Backbone.VERSION = '1.1.0';
-
-  // Require Underscore, if we're on the server, and it's not already present.
-  var _ = root._;
-  if (!_ && (typeof require !== 'undefined')) _ = require('underscore');
-
-  // For Backbone's purposes, jQuery, Zepto, Ender, or My Library (kidding) owns
-  // the `$` variable.
-  Backbone.$ = root.jQuery || root.Zepto || root.ender || root.$;
-
-  // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
-  // to its previous owner. Returns a reference to this Backbone object.
-  Backbone.noConflict = function() {
-    root.Backbone = previousBackbone;
-    return this;
-  };
-
-  // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
-  // will fake `"PATCH"`, `"PUT"` and `"DELETE"` requests via the `_method` parameter and
-  // set a `X-Http-Method-Override` header.
-  Backbone.emulateHTTP = false;
-
-  // Turn on `emulateJSON` to support legacy servers that can't deal with direct
-  // `application/json` requests ... will encode the body as
-  // `application/x-www-form-urlencoded` instead and will send the model in a
-  // form param named `model`.
-  Backbone.emulateJSON = false;
-
-  // Backbone.Events
-  // ---------------
-
-  // A module that can be mixed in to *any object* in order to provide it with
-  // custom events. You may bind with `on` or remove with `off` callback
-  // functions to an event; `trigger`-ing an event fires all callbacks in
-  // succession.
-  //
-  //     var object = {};
-  //     _.extend(object, Backbone.Events);
-  //     object.on('expand', function(){ alert('expanded'); });
-  //     object.trigger('expand');
-  //
-  var Events = Backbone.Events = {
-
-    // Bind an event to a `callback` function. Passing `"all"` will bind
-    // the callback to all events fired.
-    on: function(name, callback, context) {
-      if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this;
-      this._events || (this._events = {});
-      var events = this._events[name] || (this._events[name] = []);
-      events.push({callback: callback, context: context, ctx: context || this});
-      return this;
-    },
-
-    // Bind an event to only be triggered a single time. After the first time
-    // the callback is invoked, it will be removed.
-    once: function(name, callback, context) {
-      if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this;
-      var self = this;
-      var once = _.once(function() {
-        self.off(name, once);
-        callback.apply(this, arguments);
-      });
-      once._callback = callback;
-      return this.on(name, once, context);
-    },
-
-    // Remove one or many callbacks. If `context` is null, removes all
-    // callbacks with that function. If `callback` is null, removes all
-    // callbacks for the event. If `name` is null, removes all bound
-    // callbacks for all events.
-    off: function(name, callback, context) {
-      var retain, ev, events, names, i, l, j, k;
-      if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;
-      if (!name && !callback && !context) {
-        this._events = {};
-        return this;
-      }
-      names = name ? [name] : _.keys(this._events);
-      for (i = 0, l = names.length; i < l; i++) {
-        name = names[i];
-        if (events = this._events[name]) {
-          this._events[name] = retain = [];
-          if (callback || context) {
-            for (j = 0, k = events.length; j < k; j++) {
-              ev = events[j];
-              if ((callback && callback !== ev.callback && callback !== ev.callback._callback) ||
-                  (context && context !== ev.context)) {
-                retain.push(ev);
-              }
-            }
-          }
-          if (!retain.length) delete this._events[name];
-        }
-      }
-
-      return this;
-    },
-
-    // Trigger one or many events, firing all bound callbacks. Callbacks are
-    // passed the same arguments as `trigger` is, apart from the event name
-    // (unless you're listening on `"all"`, which will cause your callback to
-    // receive the true name of the event as the first argument).
-    trigger: function(name) {
-      if (!this._events) return this;
-      var args = slice.call(arguments, 1);
-      if (!eventsApi(this, 'trigger', name, args)) return this;
-      var events = this._events[name];
-      var allEvents = this._events.all;
-      if (events) triggerEvents(events, args);
-      if (allEvents) triggerEvents(allEvents, arguments);
-      return this;
-    },
-
-    // Tell this object to stop listening to either specific events ... or
-    // to every object it's currently listening to.
-    stopListening: function(obj, name, callback) {
-      var listeningTo = this._listeningTo;
-      if (!listeningTo) return this;
-      var remove = !name && !callback;
-      if (!callback && typeof name === 'object') callback = this;
-      if (obj) (listeningTo = {})[obj._listenId] = obj;
-      for (var id in listeningTo) {
-        obj = listeningTo[id];
-        obj.off(name, callback, this);
-        if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id];
-      }
-      return this;
-    }
-
-  };
-
-  // Regular expression used to split event strings.
-  var eventSplitter = /\s+/;
-
-  // Implement fancy features of the Events API such as multiple event
-  // names `"change blur"` and jQuery-style event maps `{change: action}`
-  // in terms of the existing API.
-  var eventsApi = function(obj, action, name, rest) {
-    if (!name) return true;
-
-    // Handle event maps.
-    if (typeof name === 'object') {
-      for (var key in name) {
-        obj[action].apply(obj, [key, name[key]].concat(rest));
-      }
-      return false;
-    }
-
-    // Handle space separated event names.
-    if (eventSplitter.test(name)) {
-      var names = name.split(eventSplitter);
-      for (var i = 0, l = names.length; i < l; i++) {
-        obj[action].apply(obj, [names[i]].concat(rest));
-      }
-      return false;
-    }
-
-    return true;
-  };
-
-  // A difficult-to-believe, but optimized internal dispatch function for
-  // triggering events. Tries to keep the usual cases speedy (most internal
-  // Backbone events have 3 arguments).
-  var triggerEvents = function(events, args) {
-    var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2];
-    switch (args.length) {
-      case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return;
-      case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return;
-      case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return;
-      case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return;
-      default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
-    }
-  };
-
-  var listenMethods = {listenTo: 'on', listenToOnce: 'once'};
-
-  // Inversion-of-control versions of `on` and `once`. Tell *this* object to
-  // listen to an event in another object ... keeping track of what it's
-  // listening to.
-  _.each(listenMethods, function(implementation, method) {
-    Events[method] = function(obj, name, callback) {
-      var listeningTo = this._listeningTo || (this._listeningTo = {});
-      var id = obj._listenId || (obj._listenId = _.uniqueId('l'));
-      listeningTo[id] = obj;
-      if (!callback && typeof name === 'object') callback = this;
-      obj[implementation](name, callback, this);
-      return this;
-    };
-  });
-
-  // Aliases for backwards compatibility.
-  Events.bind   = Events.on;
-  Events.unbind = Events.off;
-
-  // Allow the `Backbone` object to serve as a global event bus, for folks who
-  // want global "pubsub" in a convenient place.
-  _.extend(Backbone, Events);
-
-  // Backbone.Model
-  // --------------
-
-  // Backbone **Models** are the basic data object in the framework --
-  // frequently representing a row in a table in a database on your server.
-  // A discrete chunk of data and a bunch of useful, related methods for
-  // performing computations and transformations on that data.
-
-  // Create a new model with the specified attributes. A client id (`cid`)
-  // is automatically generated and assigned for you.
-  var Model = Backbone.Model = function(attributes, options) {
-    var attrs = attributes || {};
-    options || (options = {});
-    this.cid = _.uniqueId('c');
-    this.attributes = {};
-    if (options.collection) this.collection = options.collection;
-    if (options.parse) attrs = this.parse(attrs, options) || {};
-    attrs = _.defaults({}, attrs, _.result(this, 'defaults'));
-    this.set(attrs, options);
-    this.changed = {};
-    this.initialize.apply(this, arguments);
-  };
-
-  // Attach all inheritable methods to the Model prototype.
-  _.extend(Model.prototype, Events, {
-
-    // A hash of attributes whose current and previous value differ.
-    changed: null,
-
-    // The value returned during the last failed validation.
-    validationError: null,
-
-    // The default name for the JSON `id` attribute is `"id"`. MongoDB and
-    // CouchDB users may want to set this to `"_id"`.
-    idAttribute: 'id',
-
-    // Initialize is an empty function by default. Override it with your own
-    // initialization logic.
-    initialize: function(){},
-
-    // Return a copy of the model's `attributes` object.
-    toJSON: function(options) {
-      return _.clone(this.attributes);
-    },
-
-    // Proxy `Backbone.sync` by default -- but override this if you need
-    // custom syncing semantics for *this* particular model.
-    sync: function() {
-      return Backbone.sync.apply(this, arguments);
-    },
-
-    // Get the value of an attribute.
-    get: function(attr) {
-      return this.attributes[attr];
-    },
-
-    // Get the HTML-escaped value of an attribute.
-    escape: function(attr) {
-      return _.escape(this.get(attr));
-    },
-
-    // Returns `true` if the attribute contains a value that is not null
-    // or undefined.
-    has: function(attr) {
-      return this.get(attr) != null;
-    },
-
-    // Set a hash of model attributes on the object, firing `"change"`. This is
-    // the core primitive operation of a model, updating the data and notifying
-    // anyone who needs to know about the change in state. The heart of the beast.
-    set: function(key, val, options) {
-      var attr, attrs, unset, changes, silent, changing, prev, current;
-      if (key == null) return this;
-
-      // Handle both `"key", value` and `{key: value}` -style arguments.
-      if (typeof key === 'object') {
-        attrs = key;
-        options = val;
-      } else {
-        (attrs = {})[key] = val;
-      }
-
-      options || (options = {});
-
-      // Run validation.
-      if (!this._validate(attrs, options)) return false;
-
-      // Extract attributes and options.
-      unset           = options.unset;
-      silent          = options.silent;
-      changes         = [];
-      changing        = this._changing;
-      this._changing  = true;
-
-      if (!changing) {
-        this._previousAttributes = _.clone(this.attributes);
-        this.changed = {};
-      }
-      current = this.attributes, prev = this._previousAttributes;
-
-      // Check for changes of `id`.
-      if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
-
-      // For each `set` attribute, update or delete the current value.
-      for (attr in attrs) {
-        val = attrs[attr];
-        if (!_.isEqual(current[attr], val)) changes.push(attr);
-        if (!_.isEqual(prev[attr], val)) {
-          this.changed[attr] = val;
-        } else {
-          delete this.changed[attr];
-        }
-        unset ? delete current[attr] : current[attr] = val;
-      }
-
-      // Trigger all relevant attribute changes.
-      if (!silent) {
-        if (changes.length) this._pending = true;
-        for (var i = 0, l = changes.length; i < l; i++) {
-          this.trigger('change:' + changes[i], this, current[changes[i]], options);
-        }
-      }
-
-      // You might be wondering why there's a `while` loop here. Changes can
-      // be recursively nested within `"change"` events.
-      if (changing) return this;
-      if (!silent) {
-        while (this._pending) {
-          this._pending = false;
-          this.trigger('change', this, options);
-        }
-      }
-      this._pending = false;
-      this._changing = false;
-      return this;
-    },
-
-    // Remove an attribute from the model, firing `"change"`. `unset` is a noop
-    // if the attribute doesn't exist.
-    unset: function(attr, options) {
-      return this.set(attr, void 0, _.extend({}, options, {unset: true}));
-    },
-
-    // Clear all attributes on the model, firing `"change"`.
-    clear: function(options) {
-      var attrs = {};
-      for (var key in this.attributes) attrs[key] = void 0;
-      return this.set(attrs, _.extend({}, options, {unset: true}));
-    },
-
-    // Determine if the model has changed since the last `"change"` event.
-    // If you specify an attribute name, determine if that attribute has changed.
-    hasChanged: function(attr) {
-      if (attr == null) return !_.isEmpty(this.changed);
-      return _.has(this.changed, attr);
-    },
-
-    // Return an object containing all the attributes that have changed, or
-    // false if there are no changed attributes. Useful for determining what
-    // parts of a view need to be updated and/or what attributes need to be
-    // persisted to the server. Unset attributes will be set to undefined.
-    // You can also pass an attributes object to diff against the model,
-    // determining if there *would be* a change.
-    changedAttributes: function(diff) {
-      if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
-      var val, changed = false;
-      var old = this._changing ? this._previousAttributes : this.attributes;
-      for (var attr in diff) {
-        if (_.isEqual(old[attr], (val = diff[attr]))) continue;
-        (changed || (changed = {}))[attr] = val;
-      }
-      return changed;
-    },
-
-    // Get the previous value of an attribute, recorded at the time the last
-    // `"change"` event was fired.
-    previous: function(attr) {
-      if (attr == null || !this._previousAttributes) return null;
-      return this._previousAttributes[attr];
-    },
-
-    // Get all of the attributes of the model at the time of the previous
-    // `"change"` event.
-    previousAttributes: function() {
-      return _.clone(this._previousAttributes);
-    },
-
-    // Fetch the model from the server. If the server's representation of the
-    // model differs from its current attributes, they will be overridden,
-    // triggering a `"change"` event.
-    fetch: function(options) {
-      options = options ? _.clone(options) : {};
-      if (options.parse === void 0) options.parse = true;
-      var model = this;
-      var success = options.success;
-      options.success = function(resp) {
-        if (!model.set(model.parse(resp, options), options)) return false;
-        if (success) success(model, resp, options);
-        model.trigger('sync', model, resp, options);
-      };
-      wrapError(this, options);
-      return this.sync('read', this, options);
-    },
-
-    // Set a hash of model attributes, and sync the model to the server.
-    // If the server returns an attributes hash that differs, the model's
-    // state will be `set` again.
-    save: function(key, val, options) {
-      var attrs, method, xhr, attributes = this.attributes;
-
-      // Handle both `"key", value` and `{key: value}` -style arguments.
-      if (key == null || typeof key === 'object') {
-        attrs = key;
-        options = val;
-      } else {
-        (attrs = {})[key] = val;
-      }
-
-      options = _.extend({validate: true}, options);
-
-      // If we're not waiting and attributes exist, save acts as
-      // `set(attr).save(null, opts)` with validation. Otherwise, check if
-      // the model will be valid when the attributes, if any, are set.
-      if (attrs && !options.wait) {
-        if (!this.set(attrs, options)) return false;
-      } else {
-        if (!this._validate(attrs, options)) return false;
-      }
-
-      // Set temporary attributes if `{wait: true}`.
-      if (attrs && options.wait) {
-        this.attributes = _.extend({}, attributes, attrs);
-      }
-
-      // After a successful server-side save, the client is (optionally)
-      // updated with the server-side state.
-      if (options.parse === void 0) options.parse = true;
-      var model = this;
-      var success = options.success;
-      options.success = function(resp) {
-        // Ensure attributes are restored during synchronous saves.
-        model.attributes = attributes;
-        var serverAttrs = model.parse(resp, options);
-        if (options.wait) serverAttrs = _.extend(attrs || {}, serverAttrs);
-        if (_.isObject(serverAttrs) && !model.set(serverAttrs, options)) {
-          return false;
-        }
-        if (success) success(model, resp, options);
-        model.trigger('sync', model, resp, options);
-      };
-      wrapError(this, options);
-
-      method = this.isNew() ? 'create' : (options.patch ? 'patch' : 'update');
-      if (method === 'patch') options.attrs = attrs;
-      xhr = this.sync(method, this, options);
-
-      // Restore attributes.
-      if (attrs && options.wait) this.attributes = attributes;
-
-      return xhr;
-    },
-
-    // Destroy this model on the server if it was already persisted.
-    // Optimistically removes the model from its collection, if it has one.
-    // If `wait: true` is passed, waits for the server to respond before removal.
-    destroy: function(options) {
-      options = options ? _.clone(options) : {};
-      var model = this;
-      var success = options.success;
-
-      var destroy = function() {
-        model.trigger('destroy', model, model.collection, options);
-      };
-
-      options.success = function(resp) {
-        if (options.wait || model.isNew()) destroy();
-        if (success) success(model, resp, options);
-        if (!model.isNew()) model.trigger('sync', model, resp, options);
-      };
-
-      if (this.isNew()) {
-        options.success();
-        return false;
-      }
-      wrapError(this, options);
-
-      var xhr = this.sync('delete', this, options);
-      if (!options.wait) destroy();
-      return xhr;
-    },
-
-    // Default URL for the model's representation on the server -- if you're
-    // using Backbone's restful methods, override this to change the endpoint
-    // that will be called.
-    url: function() {
-      var base = _.result(this, 'urlRoot') || _.result(this.collection, 'url') || urlError();
-      if (this.isNew()) return base;
-      return base + (base.charAt(base.length - 1) === '/' ? '' : '/') + encodeURIComponent(this.id);
-    },
-
-    // **parse** converts a response into the hash of attributes to be `set` on
-    // the model. The default implementation is just to pass the response along.
-    parse: function(resp, options) {
-      return resp;
-    },
-
-    // Create a new model with identical attributes to this one.
-    clone: function() {
-      return new this.constructor(this.attributes);
-    },
-
-    // A model is new if it has never been saved to the server, and lacks an id.
-    isNew: function() {
-      return this.id == null;
-    },
-
-    // Check if the model is currently in a valid state.
-    isValid: function(options) {
-      return this._validate({}, _.extend(options || {}, { validate: true }));
-    },
-
-    // Run validation against the next complete set of model attributes,
-    // returning `true` if all is well. Otherwise, fire an `"invalid"` event.
-    _validate: function(attrs, options) {
-      if (!options.validate || !this.validate) return true;
-      attrs = _.extend({}, this.attributes, attrs);
-      var error = this.validationError = this.validate(attrs, options) || null;
-      if (!error) return true;
-      this.trigger('invalid', this, error, _.extend(options, {validationError: error}));
-      return false;
-    }
-
-  });
-
-  // Underscore methods that we want to implement on the Model.
-  var modelMethods = ['keys', 'values', 'pairs', 'invert', 'pick', 'omit'];
-
-  // Mix in each Underscore method as a proxy to `Model#attributes`.
-  _.each(modelMethods, function(method) {
-    Model.prototype[method] = function() {
-      var args = slice.call(arguments);
-      args.unshift(this.attributes);
-      return _[method].apply(_, args);
-    };
-  });
-
-  // Backbone.Collection
-  // -------------------
-
-  // If models tend to represent a single row of data, a Backbone Collection is
-  // more analagous to a table full of data ... or a small slice or page of that
-  // table, or a collection of rows that belong together for a particular reason
-  // -- all of the messages in this particular folder, all of the documents
-  // belonging to this particular author, and so on. Collections maintain
-  // indexes of their models, both in order, and for lookup by `id`.
-
-  // Create a new **Collection**, perhaps to contain a specific type of `model`.
-  // If a `comparator` is specified, the Collection will maintain
-  // its models in sort order, as they're added and removed.
-  var Collection = Backbone.Collection = function(models, options) {
-    options || (options = {});
-    if (options.model) this.model = options.model;
-    if (options.comparator !== void 0) this.comparator = options.comparator;
-    this._reset();
-    this.initialize.apply(this, arguments);
-    if (models) this.reset(models, _.extend({silent: true}, options));
-  };
-
-  // Default options for `Collection#set`.
-  var setOptions = {add: true, remove: true, merge: true};
-  var addOptions = {add: true, remove: false};
-
-  // Define the Collection's inheritable methods.
-  _.extend(Collection.prototype, Events, {
-
-    // The default model for a collection is just a **Backbone.Model**.
-    // This should be overridden in most cases.
-    model: Model,
-
-    // Initialize is an empty function by default. Override it with your own
-    // initialization logic.
-    initialize: function(){},
-
-    // The JSON representation of a Collection is an array of the
-    // models' attributes.
-    toJSON: function(options) {
-      return this.map(function(model){ return model.toJSON(options); });
-    },
-
-    // Proxy `Backbone.sync` by default.
-    sync: function() {
-      return Backbone.sync.apply(this, arguments);
-    },
-
-    // Add a model, or list of models to the set.
-    add: function(models, options) {
-      return this.set(models, _.extend({merge: false}, options, addOptions));
-    },
-
-    // Remove a model, or a list of models from the set.
-    remove: function(models, options) {
-      var singular = !_.isArray(models);
-      models = singular ? [models] : _.clone(models);
-      options || (options = {});
-      var i, l, index, model;
-      for (i = 0, l = models.length; i < l; i++) {
-        model = models[i] = this.get(models[i]);
-        if (!model) continue;
-        delete this._byId[model.id];
-        delete this._byId[model.cid];
-        index = this.indexOf(model);
-        this.models.splice(index, 1);
-        this.length--;
-        if (!options.silent) {
-          options.index = index;
-          model.trigger('remove', model, this, options);
-        }
-        this._removeReference(model);
-      }
-      return singular ? models[0] : models;
-    },
-
-    // Update a collection by `set`-ing a new list of models, adding new ones,
-    // removing models that are no longer present, and merging models that
-    // already exist in the collection, as necessary. Similar to **Model#set**,
-    // the core operation for updating the data contained by the collection.
-    set: function(models, options) {
-      options = _.defaults({}, options, setOptions);
-      if (options.parse) models = this.parse(models, options);
-      var singular = !_.isArray(models);
-      models = singular ? (models ? [models] : []) : _.clone(models);
-      var i, l, id, model, attrs, existing, sort;
-      var at = options.at;
-      var targetModel = this.model;
-      var sortable = this.comparator && (at == null) && options.sort !== false;
-      var sortAttr = _.isString(this.comparator) ? this.comparator : null;
-      var toAdd = [], toRemove = [], modelMap = {};
-      var add = options.add, merge = options.merge, remove = options.remove;
-      var order = !sortable && add && remove ? [] : false;
-
-      // Turn bare objects into model references, and prevent invalid models
-      // from being added.
-      for (i = 0, l = models.length; i < l; i++) {
-        attrs = models[i];
-        if (attrs instanceof Model) {
-          id = model = attrs;
-        } else {
-          id = attrs[targetModel.prototype.idAttribute];
-        }
-
-        // If a duplicate is found, prevent it from being added and
-        // optionally merge it into the existing model.
-        if (existing = this.get(id)) {
-          if (remove) modelMap[existing.cid] = true;
-          if (merge) {
-            attrs = attrs === model ? model.attributes : attrs;
-            if (options.parse) attrs = existing.parse(attrs, options);
-            existing.set(attrs, options);
-            if (sortable && !sort && existing.hasChanged(sortAttr)) sort = true;
-          }
-          models[i] = existing;
-
-        // If this is a new, valid model, push it to the `toAdd` list.
-        } else if (add) {
-          model = models[i] = this._prepareModel(attrs, options);
-          if (!model) continue;
-          toAdd.push(model);
-
-          // Listen to added models' events, and index models for lookup by
-          // `id` and by `cid`.
-          model.on('all', this._onModelEvent, this);
-          this._byId[model.cid] = model;
-          if (model.id != null) this._byId[model.id] = model;
-        }
-        if (order) order.push(existing || model);
-      }
-
-      // Remove nonexistent models if appropriate.
-      if (remove) {
-        for (i = 0, l = this.length; i < l; ++i) {
-          if (!modelMap[(model = this.models[i]).cid]) toRemove.push(model);
-        }
-        if (toRemove.length) this.remove(toRemove, options);
-      }
-
-      // See if sorting is needed, update `length` and splice in new models.
-      if (toAdd.length || (order && order.length)) {
-        if (sortable) sort = true;
-        this.length += toAdd.length;
-        if (at != null) {
-          for (i = 0, l = toAdd.length; i < l; i++) {
-            this.models.splice(at + i, 0, toAdd[i]);
-          }
-        } else {
-          if (order) this.models.length = 0;
-          var orderedModels = order || toAdd;
-          for (i = 0, l = orderedModels.length; i < l; i++) {
-            this.models.push(orderedModels[i]);
-          }
-        }
-      }
-
-      // Silently sort the collection if appropriate.
-      if (sort) this.sort({silent: true});
-
-      // Unless silenced, it's time to fire all appropriate add/sort events.
-      if (!options.silent) {
-        for (i = 0, l = toAdd.length; i < l; i++) {
-          (model = toAdd[i]).trigger('add', model, this, options);
-        }
-        if (sort || (order && order.length)) this.trigger('sort', this, options);
-      }
-      
-      // Return the added (or merged) model (or models).
-      return singular ? models[0] : models;
-    },
-
-    // When you have more items than you want to add or remove individually,
-    // you can reset the entire set with a new list of models, without firing
-    // any granular `add` or `remove` events. Fires `reset` when finished.
-    // Useful for bulk operations and optimizations.
-    reset: function(models, options) {
-      options || (options = {});
-      for (var i = 0, l = this.models.length; i < l; i++) {
-        this._removeReference(this.models[i]);
-      }
-      options.previousModels = this.models;
-      this._reset();
-      models = this.add(models, _.extend({silent: true}, options));
-      if (!options.silent) this.trigger('reset', this, options);
-      return models;
-    },
-
-    // Add a model to the end of the collection.
-    push: function(model, options) {
-      return this.add(model, _.extend({at: this.length}, options));
-    },
-
-    // Remove a model from the end of the collection.
-    pop: function(options) {
-      var model = this.at(this.length - 1);
-      this.remove(model, options);
-      return model;
-    },
-
-    // Add a model to the beginning of the collection.
-    unshift: function(model, options) {
-      return this.add(model, _.extend({at: 0}, options));
-    },
-
-    // Remove a model from the beginning of the collection.
-    shift: function(options) {
-      var model = this.at(0);
-      this.remove(model, options);
-      return model;
-    },
-
-    // Slice out a sub-array of models from the collection.
-    slice: function() {
-      return slice.apply(this.models, arguments);
-    },
-
-    // Get a model from the set by id.
-    get: function(obj) {
-      if (obj == null) return void 0;
-      return this._byId[obj.id] || this._byId[obj.cid] || this._byId[obj];
-    },
-
-    // Get the model at the given index.
-    at: function(index) {
-      return this.models[index];
-    },
-
-    // Return models with matching attributes. Useful for simple cases of
-    // `filter`.
-    where: function(attrs, first) {
-      if (_.isEmpty(attrs)) return first ? void 0 : [];
-      return this[first ? 'find' : 'filter'](function(model) {
-        for (var key in attrs) {
-          if (attrs[key] !== model.get(key)) return false;
-        }
-        return true;
-      });
-    },
-
-    // Return the first model with matching attributes. Useful for simple cases
-    // of `find`.
-    findWhere: function(attrs) {
-      return this.where(attrs, true);
-    },
-
-    // Force the collection to re-sort itself. You don't need to call this under
-    // normal circumstances, as the set will maintain sort order as each item
-    // is added.
-    sort: function(options) {
-      if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
-      options || (options = {});
-
-      // Run sort based on type of `comparator`.
-      if (_.isString(this.comparator) || this.comparator.length === 1) {
-        this.models = this.sortBy(this.comparator, this);
-      } else {
-        this.models.sort(_.bind(this.comparator, this));
-      }
-
-      if (!options.silent) this.trigger('sort', this, options);
-      return this;
-    },
-
-    // Pluck an attribute from each model in the collection.
-    pluck: function(attr) {
-      return _.invoke(this.models, 'get', attr);
-    },
-
-    // Fetch the default set of models for this collection, resetting the
-    // collection when they arrive. If `reset: true` is passed, the response
-    // data will be passed through the `reset` method instead of `set`.
-    fetch: function(options) {
-      options = options ? _.clone(options) : {};
-      if (options.parse === void 0) options.parse = true;
-      var success = options.success;
-      var collection = this;
-      options.success = function(resp) {
-        var method = options.reset ? 'reset' : 'set';
-        collection[method](resp, options);
-        if (success) success(collection, resp, options);
-        collection.trigger('sync', collection, resp, options);
-      };
-      wrapError(this, options);
-      return this.sync('read', this, options);
-    },
-
-    // Create a new instance of a model in this collection. Add the model to the
-    // collection immediately, unless `wait: true` is passed, in which case we
-    // wait for the server to agree.
-    create: function(model, options) {
-      options = options ? _.clone(options) : {};
-      if (!(model = this._prepareModel(model, options))) return false;
-      if (!options.wait) this.add(model, options);
-      var collection = this;
-      var success = options.success;
-      options.success = function(model, resp, options) {
-        if (options.wait) collection.add(model, options);
-        if (success) success(model, resp, options);
-      };
-      model.save(null, options);
-      return model;
-    },
-
-    // **parse** converts a response into a list of models to be added to the
-    // collection. The default implementation is just to pass it through.
-    parse: function(resp, options) {
-      return resp;
-    },
-
-    // Create a new collection with an identical list of models as this one.
-    clone: function() {
-      return new this.constructor(this.models);
-    },
-
-    // Private method to reset all internal state. Called when the collection
-    // is first initialized or reset.
-    _reset: function() {
-      this.length = 0;
-      this.models = [];
-      this._byId  = {};
-    },
-
-    // Prepare a hash of attributes (or other model) to be added to this
-    // collection.
-    _prepareModel: function(attrs, options) {
-      if (attrs instanceof Model) {
-        if (!attrs.collection) attrs.collection = this;
-        return attrs;
-      }
-      options = options ? _.clone(options) : {};
-      options.collection = this;
-      var model = new this.model(attrs, options);
-      if (!model.validationError) return model;
-      this.trigger('invalid', this, model.validationError, options);
-      return false;
-    },
-
-    // Internal method to sever a model's ties to a collection.
-    _removeReference: function(model) {
-      if (this === model.collection) delete model.collection;
-      model.off('all', this._onModelEvent, this);
-    },
-
-    // Internal method called every time a model in the set fires an event.
-    // Sets need to update their indexes when models change ids. All other
-    // events simply proxy through. "add" and "remove" events that originate
-    // in other collections are ignored.
-    _onModelEvent: function(event, model, collection, options) {
-      if ((event === 'add' || event === 'remove') && collection !== this) return;
-      if (event === 'destroy') this.remove(model, options);
-      if (model && event === 'change:' + model.idAttribute) {
-        delete this._byId[model.previous(model.idAttribute)];
-        if (model.id != null) this._byId[model.id] = model;
-      }
-      this.trigger.apply(this, arguments);
-    }
-
-  });
-
-  // Underscore methods that we want to implement on the Collection.
-  // 90% of the core usefulness of Backbone Collections is actually implemented
-  // right here:
-  var methods = ['forEach', 'each', 'map', 'collect', 'reduce', 'foldl',
-    'inject', 'reduceRight', 'foldr', 'find', 'detect', 'filter', 'select',
-    'reject', 'every', 'all', 'some', 'any', 'include', 'contains', 'invoke',
-    'max', 'min', 'toArray', 'size', 'first', 'head', 'take', 'initial', 'rest',
-    'tail', 'drop', 'last', 'without', 'difference', 'indexOf', 'shuffle',
-    'lastIndexOf', 'isEmpty', 'chain'];
-
-  // Mix in each Underscore method as a proxy to `Collection#models`.
-  _.each(methods, function(method) {
-    Collection.prototype[method] = function() {
-      var args = slice.call(arguments);
-      args.unshift(this.models);
-      return _[method].apply(_, args);
-    };
-  });
-
-  // Underscore methods that take a property name as an argument.
-  var attributeMethods = ['groupBy', 'countBy', 'sortBy'];
-
-  // Use attributes instead of properties.
-  _.each(attributeMethods, function(method) {
-    Collection.prototype[method] = function(value, context) {
-      var iterator = _.isFunction(value) ? value : function(model) {
-        return model.get(value);
-      };
-      return _[method](this.models, iterator, context);
-    };
-  });
-
-  // Backbone.View
-  // -------------
-
-  // Backbone Views are almost more convention than they are actual code. A View
-  // is simply a JavaScript object that represents a logical chunk of UI in the
-  // DOM. This might be a single item, an entire list, a sidebar or panel, or
-  // even the surrounding frame which wraps your whole app. Defining a chunk of
-  // UI as a **View** allows you to define your DOM events declaratively, without
-  // having to worry about render order ... and makes it easy for the view to
-  // react to specific changes in the state of your models.
-
-  // Creating a Backbone.View creates its initial element outside of the DOM,
-  // if an existing element is not provided...
-  var View = Backbone.View = function(options) {
-    this.cid = _.uniqueId('view');
-    options || (options = {});
-    _.extend(this, _.pick(options, viewOptions));
-    this._ensureElement();
-    this.initialize.apply(this, arguments);
-    this.delegateEvents();
-  };
-
-  // Cached regex to split keys for `delegate`.
-  var delegateEventSplitter = /^(\S+)\s*(.*)$/;
-
-  // List of view options to be merged as properties.
-  var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName', 'events'];
-
-  // Set up all inheritable **Backbone.View** properties and methods.
-  _.extend(View.prototype, Events, {
-
-    // The default `tagName` of a View's element is `"div"`.
-    tagName: 'div',
-
-    // jQuery delegate for element lookup, scoped to DOM elements within the
-    // current view. This should be preferred to global lookups where possible.
-    $: function(selector) {
-      return this.$el.find(selector);
-    },
-
-    // Initialize is an empty function by default. Override it with your own
-    // initialization logic.
-    initialize: function(){},
-
-    // **render** is the core function that your view should override, in order
-    // to populate its element (`this.el`), with the appropriate HTML. The
-    // convention is for **render** to always return `this`.
-    render: function() {
-      return this;
-    },
-
-    // Remove this view by taking the element out of the DOM, and removing any
-    // applicable Backbone.Events listeners.
-    remove: function() {
-      this.$el.remove();
-      this.stopListening();
-      return this;
-    },
-
-    // Change the view's element (`this.el` property), including event
-    // re-delegation.
-    setElement: function(element, delegate) {
-      if (this.$el) this.undelegateEvents();
-      this.$el = element instanceof Backbone.$ ? element : Backbone.$(element);
-      this.el = this.$el[0];
-      if (delegate !== false) this.delegateEvents();
-      return this;
-    },
-
-    // Set callbacks, where `this.events` is a hash of
-    //
-    // *{"event selector": "callback"}*
-    //
-    //     {
-    //       'mousedown .title':  'edit',
-    //       'click .button':     'save',
-    //       'click .open':       function(e) { ... }
-    //     }
-    //
-    // pairs. Callbacks will be bound to the view, with `this` set properly.
-    // Uses event delegation for efficiency.
-    // Omitting the selector binds the event to `this.el`.
-    // This only works for delegate-able events: not `focus`, `blur`, and
-    // not `change`, `submit`, and `reset` in Internet Explorer.
-    delegateEvents: function(events) {
-      if (!(events || (events = _.result(this, 'events')))) return this;
-      this.undelegateEvents();
-      for (var key in events) {
-        var method = events[key];
-        if (!_.isFunction(method)) method = this[events[key]];
-        if (!method) continue;
-
-        var match = key.match(delegateEventSplitter);
-        var eventName = match[1], selector = match[2];
-        method = _.bind(method, this);
-        eventName += '.delegateEvents' + this.cid;
-        if (selector === '') {
-          this.$el.on(eventName, method);
-        } else {
-          this.$el.on(eventName, selector, method);
-        }
-      }
-      return this;
-    },
-
-    // Clears all callbacks previously bound to the view with `delegateEvents`.
-    // You usually don't need to use this, but may wish to if you have multiple
-    // Backbone views attached to the same DOM element.
-    undelegateEvents: function() {
-      this.$el.off('.delegateEvents' + this.cid);
-      return this;
-    },
-
-    // Ensure that the View has a DOM element to render into.
-    // If `this.el` is a string, pass it through `$()`, take the first
-    // matching element, and re-assign it to `el`. Otherwise, create
-    // an element from the `id`, `className` and `tagName` properties.
-    _ensureElement: function() {
-      if (!this.el) {
-        var attrs = _.extend({}, _.result(this, 'attributes'));
-        if (this.id) attrs.id = _.result(this, 'id');
-        if (this.className) attrs['class'] = _.result(this, 'className');
-        var $el = Backbone.$('<' + _.result(this, 'tagName') + '>').attr(attrs);
-        this.setElement($el, false);
-      } else {
-        this.setElement(_.result(this, 'el'), false);
-      }
-    }
-
-  });
-
-  // Backbone.sync
-  // -------------
-
-  // Override this function to change the manner in which Backbone persists
-  // models to the server. You will be passed the type of request, and the
-  // model in question. By default, makes a RESTful Ajax request
-  // to the model's `url()`. Some possible customizations could be:
-  //
-  // * Use `setTimeout` to batch rapid-fire updates into a single request.
-  // * Send up the models as XML instead of JSON.
-  // * Persist models via WebSockets instead of Ajax.
-  //
-  // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
-  // as `POST`, with a `_method` parameter containing the true HTTP method,
-  // as well as all requests with the body as `application/x-www-form-urlencoded`
-  // instead of `application/json` with the model in a param named `model`.
-  // Useful when interfacing with server-side languages like **PHP** that make
-  // it difficult to read the body of `PUT` requests.
-  Backbone.sync = function(method, model, options) {
-    var type = methodMap[method];
-
-    // Default options, unless specified.
-    _.defaults(options || (options = {}), {
-      emulateHTTP: Backbone.emulateHTTP,
-      emulateJSON: Backbone.emulateJSON
-    });
-
-    // Default JSON-request options.
-    var params = {type: type, dataType: 'json'};
-
-    // Ensure that we have a URL.
-    if (!options.url) {
-      params.url = _.result(model, 'url') || urlError();
-    }
-
-    // Ensure that we have the appropriate request data.
-    if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) {
-      params.contentType = 'application/json';
-      params.data = JSON.stringify(options.attrs || model.toJSON(options));
-    }
-
-    // For older servers, emulate JSON by encoding the request into an HTML-form.
-    if (options.emulateJSON) {
-      params.contentType = 'application/x-www-form-urlencoded';
-      params.data = params.data ? {model: params.data} : {};
-    }
-
-    // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
-    // And an `X-HTTP-Method-Override` header.
-    if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) {
-      params.type = 'POST';
-      if (options.emulateJSON) params.data._method = type;
-      var beforeSend = options.beforeSend;
-      options.beforeSend = function(xhr) {
-        xhr.setRequestHeader('X-HTTP-Method-Override', type);
-        if (beforeSend) return beforeSend.apply(this, arguments);
-      };
-    }
-
-    // Don't process data on a non-GET request.
-    if (params.type !== 'GET' && !options.emulateJSON) {
-      params.processData = false;
-    }
-
-    // If we're sending a `PATCH` request, and we're in an old Internet Explorer
-    // that still has ActiveX enabled by default, override jQuery to use that
-    // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8.
-    if (params.type === 'PATCH' && noXhrPatch) {
-      params.xhr = function() {
-        return new ActiveXObject("Microsoft.XMLHTTP");
-      };
-    }
-
-    // Make the request, allowing the user to override any Ajax options.
-    var xhr = options.xhr = Backbone.ajax(_.extend(params, options));
-    model.trigger('request', model, xhr, options);
-    return xhr;
-  };
-
-  var noXhrPatch = typeof window !== 'undefined' && !!window.ActiveXObject && !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent);
-
-  // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
-  var methodMap = {
-    'create': 'POST',
-    'update': 'PUT',
-    'patch':  'PATCH',
-    'delete': 'DELETE',
-    'read':   'GET'
-  };
-
-  // Set the default implementation of `Backbone.ajax` to proxy through to `$`.
-  // Override this if you'd like to use a different library.
-  Backbone.ajax = function() {
-    return Backbone.$.ajax.apply(Backbone.$, arguments);
-  };
-
-  // Backbone.Router
-  // ---------------
-
-  // Routers map faux-URLs to actions, and fire events when routes are
-  // matched. Creating a new one sets its `routes` hash, if not set statically.
-  var Router = Backbone.Router = function(options) {
-    options || (options = {});
-    if (options.routes) this.routes = options.routes;
-    this._bindRoutes();
-    this.initialize.apply(this, arguments);
-  };
-
-  // Cached regular expressions for matching named param parts and splatted
-  // parts of route strings.
-  var optionalParam = /\((.*?)\)/g;
-  var namedParam    = /(\(\?)?:\w+/g;
-  var splatParam    = /\*\w+/g;
-  var escapeRegExp  = /[\-{}\[\]+?.,\\\^$|#\s]/g;
-
-  // Set up all inheritable **Backbone.Router** properties and methods.
-  _.extend(Router.prototype, Events, {
-
-    // Initialize is an empty function by default. Override it with your own
-    // initialization logic.
-    initialize: function(){},
-
-    // Manually bind a single named route to a callback. For example:
-    //
-    //     this.route('search/:query/p:num', 'search', function(query, num) {
-    //       ...
-    //     });
-    //
-    route: function(route, name, callback) {
-      if (!_.isRegExp(route)) route = this._routeToRegExp(route);
-      if (_.isFunction(name)) {
-        callback = name;
-        name = '';
-      }
-      if (!callback) callback = this[name];
-      var router = this;
-      Backbone.history.route(route, function(fragment) {
-        var args = router._extractParameters(route, fragment);
-        callback && callback.apply(router, args);
-        router.trigger.apply(router, ['route:' + name].concat(args));
-        router.trigger('route', name, args);
-        Backbone.history.trigger('route', router, name, args);
-      });
-      return this;
-    },
-
-    // Simple proxy to `Backbone.history` to save a fragment into the history.
-    navigate: function(fragment, options) {
-      Backbone.history.navigate(fragment, options);
-      return this;
-    },
-
-    // Bind all defined routes to `Backbone.history`. We have to reverse the
-    // order of the routes here to support behavior where the most general
-    // routes can be defined at the bottom of the route map.
-    _bindRoutes: function() {
-      if (!this.routes) return;
-      this.routes = _.result(this, 'routes');
-      var route, routes = _.keys(this.routes);
-      while ((route = routes.pop()) != null) {
-        this.route(route, this.routes[route]);
-      }
-    },
-
-    // Convert a route string into a regular expression, suitable for matching
-    // against the current location hash.
-    _routeToRegExp: function(route) {
-      route = route.replace(escapeRegExp, '\\$&')
-                   .replace(optionalParam, '(?:$1)?')
-                   .replace(namedParam, function(match, optional) {
-                     return optional ? match : '([^\/]+)';
-                   })
-                   .replace(splatParam, '(.*?)');
-      return new RegExp('^' + route + '$');
-    },
-
-    // Given a route, and a URL fragment that it matches, return the array of
-    // extracted decoded parameters. Empty or unmatched parameters will be
-    // treated as `null` to normalize cross-browser behavior.
-    _extractParameters: function(route, fragment) {
-      var params = route.exec(fragment).slice(1);
-      return _.map(params, function(param) {
-        return param ? decodeURIComponent(param) : null;
-      });
-    }
-
-  });
-
-  // Backbone.History
-  // ----------------
-
-  // Handles cross-browser history management, based on either
-  // [pushState](http://diveintohtml5.info/history.html) and real URLs, or
-  // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange)
-  // and URL fragments. If the browser supports neither (old IE, natch),
-  // falls back to polling.
-  var History = Backbone.History = function() {
-    this.handlers = [];
-    _.bindAll(this, 'checkUrl');
-
-    // Ensure that `History` can be used outside of the browser.
-    if (typeof window !== 'undefined') {
-      this.location = window.location;
-      this.history = window.history;
-    }
-  };
-
-  // Cached regex for stripping a leading hash/slash and trailing space.
-  var routeStripper = /^[#\/]|\s+$/g;
-
-  // Cached regex for stripping leading and trailing slashes.
-  var rootStripper = /^\/+|\/+$/g;
-
-  // Cached regex for detecting MSIE.
-  var isExplorer = /msie [\w.]+/;
-
-  // Cached regex for removing a trailing slash.
-  var trailingSlash = /\/$/;
-
-  // Cached regex for stripping urls of hash and query.
-  var pathStripper = /[?#].*$/;
-
-  // Has the history handling already been started?
-  History.started = false;
-
-  // Set up all inheritable **Backbone.History** properties and methods.
-  _.extend(History.prototype, Events, {
-
-    // The default interval to poll for hash changes, if necessary, is
-    // twenty times a second.
-    interval: 50,
-
-    // Gets the true hash value. Cannot use location.hash directly due to bug
-    // in Firefox where location.hash will always be decoded.
-    getHash: function(window) {
-      var match = (window || this).location.href.match(/#(.*)$/);
-      return match ? match[1] : '';
-    },
-
-    // Get the cross-browser normalized URL fragment, either from the URL,
-    // the hash, or the override.
-    getFragment: function(fragment, forcePushState) {
-      if (fragment == null) {
-        if (this._hasPushState || !this._wantsHashChange || forcePushState) {
-          fragment = this.location.pathname;
-          var root = this.root.replace(trailingSlash, '');
-          if (!fragment.indexOf(root)) fragment = fragment.slice(root.length);
-        } else {
-          fragment = this.getHash();
-        }
-      }
-      return fragment.replace(routeStripper, '');
-    },
-
-    // Start the hash change handling, returning `true` if the current URL matches
-    // an existing route, and `false` otherwise.
-    start: function(options) {
-      if (History.started) throw new Error("Backbone.history has already been started");
-      History.started = true;
-
-      // Figure out the initial configuration. Do we need an iframe?
-      // Is pushState desired ... is it available?
-      this.options          = _.extend({root: '/'}, this.options, options);
-      this.root             = this.options.root;
-      this._wantsHashChange = this.options.hashChange !== false;
-      this._wantsPushState  = !!this.options.pushState;
-      this._hasPushState    = !!(this.options.pushState && this.history && this.history.pushState);
-      var fragment          = this.getFragment();
-      var docMode           = document.documentMode;
-      var oldIE             = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
-
-      // Normalize root to always include a leading and trailing slash.
-      this.root = ('/' + this.root + '/').replace(rootStripper, '/');
-
-      if (oldIE && this._wantsHashChange) {
-        this.iframe = Backbone.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
-        this.navigate(fragment);
-      }
-
-      // Depending on whether we're using pushState or hashes, and whether
-      // 'onhashchange' is supported, determine how we check the URL state.
-      if (this._hasPushState) {
-        Backbone.$(window).on('popstate', this.checkUrl);
-      } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {
-        Backbone.$(window).on('hashchange', this.checkUrl);
-      } else if (this._wantsHashChange) {
-        this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
-      }
-
-      // Determine if we need to change the base url, for a pushState link
-      // opened by a non-pushState browser.
-      this.fragment = fragment;
-      var loc = this.location;
-      var atRoot = loc.pathname.replace(/[^\/]$/, '$&/') === this.root;
-
-      // Transition from hashChange to pushState or vice versa if both are
-      // requested.
-      if (this._wantsHashChange && this._wantsPushState) {
-
-        // If we've started off with a route from a `pushState`-enabled
-        // browser, but we're currently in a browser that doesn't support it...
-        if (!this._hasPushState && !atRoot) {
-          this.fragment = this.getFragment(null, true);
-          this.location.replace(this.root + this.location.search + '#' + this.fragment);
-          // Return immediately as browser will do redirect to new url
-          return true;
-
-        // Or if we've started out with a hash-based route, but we're currently
-        // in a browser where it could be `pushState`-based instead...
-        } else if (this._hasPushState && atRoot && loc.hash) {
-          this.fragment = this.getHash().replace(routeStripper, '');
-          this.history.replaceState({}, document.title, this.root + this.fragment + loc.search);
-        }
-
-      }
-
-      if (!this.options.silent) return this.loadUrl();
-    },
-
-    // Disable Backbone.history, perhaps temporarily. Not useful in a real app,
-    // but possibly useful for unit testing Routers.
-    stop: function() {
-      Backbone.$(window).off('popstate', this.checkUrl).off('hashchange', this.checkUrl);
-      clearInterval(this._checkUrlInterval);
-      History.started = false;
-    },
-
-    // Add a route to be tested when the fragment changes. Routes added later
-    // may override previous routes.
-    route: function(route, callback) {
-      this.handlers.unshift({route: route, callback: callback});
-    },
-
-    // Checks the current URL to see if it has changed, and if it has,
-    // calls `loadUrl`, normalizing across the hidden iframe.
-    checkUrl: function(e) {
-      var current = this.getFragment();
-      if (current === this.fragment && this.iframe) {
-        current = this.getFragment(this.getHash(this.iframe));
-      }
-      if (current === this.fragment) return false;
-      if (this.iframe) this.navigate(current);
-      this.loadUrl();
-    },
-
-    // Attempt to load the current URL fragment. If a route succeeds with a
-    // match, returns `true`. If no defined routes matches the fragment,
-    // returns `false`.
-    loadUrl: function(fragment) {
-      fragment = this.fragment = this.getFragment(fragment);
-      return _.any(this.handlers, function(handler) {
-        if (handler.route.test(fragment)) {
-          handler.callback(fragment);
-          return true;
-        }
-      });
-    },
-
-    // Save a fragment into the hash history, or replace the URL state if the
-    // 'replace' option is passed. You are responsible for properly URL-encoding
-    // the fragment in advance.
-    //
-    // The options object can contain `trigger: true` if you wish to have the
-    // route callback be fired (not usually desirable), or `replace: true`, if
-    // you wish to modify the current URL without adding an entry to the history.
-    navigate: function(fragment, options) {
-      if (!History.started) return false;
-      if (!options || options === true) options = {trigger: !!options};
-
-      var url = this.root + (fragment = this.getFragment(fragment || ''));
-
-      // Strip the fragment of the query and hash for matching.
-      fragment = fragment.replace(pathStripper, '');
-
-      if (this.fragment === fragment) return;
-      this.fragment = fragment;
-
-      // Don't include a trailing slash on the root.
-      if (fragment === '' && url !== '/') url = url.slice(0, -1);
-
-      // If pushState is available, we use it to set the fragment as a real URL.
-      if (this._hasPushState) {
-        this.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, url);
-
-      // If hash changes haven't been explicitly disabled, update the hash
-      // fragment to store history.
-      } else if (this._wantsHashChange) {
-        this._updateHash(this.location, fragment, options.replace);
-        if (this.iframe && (fragment !== this.getFragment(this.getHash(this.iframe)))) {
-          // Opening and closing the iframe tricks IE7 and earlier to push a
-          // history entry on hash-tag change.  When replace is true, we don't
-          // want this.
-          if(!options.replace) this.iframe.document.open().close();
-          this._updateHash(this.iframe.location, fragment, options.replace);
-        }
-
-      // If you've told us that you explicitly don't want fallback hashchange-
-      // based history, then `navigate` becomes a page refresh.
-      } else {
-        return this.location.assign(url);
-      }
-      if (options.trigger) return this.loadUrl(fragment);
-    },
-
-    // Update the hash location, either replacing the current entry, or adding
-    // a new one to the browser history.
-    _updateHash: function(location, fragment, replace) {
-      if (replace) {
-        var href = location.href.replace(/(javascript:|#).*$/, '');
-        location.replace(href + '#' + fragment);
-      } else {
-        // Some browsers require that `hash` contains a leading #.
-        location.hash = '#' + fragment;
-      }
-    }
-
-  });
-
-  // Create the default Backbone.history.
-  Backbone.history = new History;
-
-  // Helpers
-  // -------
-
-  // Helper function to correctly set up the prototype chain, for subclasses.
-  // Similar to `goog.inherits`, but uses a hash of prototype properties and
-  // class properties to be extended.
-  var extend = function(protoProps, staticProps) {
-    var parent = this;
-    var child;
-
-    // The constructor function for the new subclass is either defined by you
-    // (the "constructor" property in your `extend` definition), or defaulted
-    // by us to simply call the parent's constructor.
-    if (protoProps && _.has(protoProps, 'constructor')) {
-      child = protoProps.constructor;
-    } else {
-      child = function(){ return parent.apply(this, arguments); };
-    }
-
-    // Add static properties to the constructor function, if supplied.
-    _.extend(child, parent, staticProps);
-
-    // Set the prototype chain to inherit from `parent`, without calling
-    // `parent`'s constructor function.
-    var Surrogate = function(){ this.constructor = child; };
-    Surrogate.prototype = parent.prototype;
-    child.prototype = new Surrogate;
-
-    // Add prototype properties (instance properties) to the subclass,
-    // if supplied.
-    if (protoProps) _.extend(child.prototype, protoProps);
-
-    // Set a convenience property in case the parent's prototype is needed
-    // later.
-    child.__super__ = parent.prototype;
-
-    return child;
-  };
-
-  // Set up inheritance for the model, collection, router, view and history.
-  Model.extend = Collection.extend = Router.extend = View.extend = History.extend = extend;
-
-  // Throw an error when a URL is needed, and none is supplied.
-  var urlError = function() {
-    throw new Error('A "url" property or function must be specified');
-  };
-
-  // Wrap an optional error callback with a fallback error event.
-  var wrapError = function(model, options) {
-    var error = options.error;
-    options.error = function(resp) {
-      if (error) error(model, resp, options);
-      model.trigger('error', model, resp, options);
-    };
-  };
-
-}).call(this);
deleted file mode 100644
index 3be8ab08667e944c9ead117cef669a2e19884ce6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/js/src/jsapi-tests/binast/parser/tester/frameworks/benchmark.js
+++ /dev/null
@@ -1,3918 +0,0 @@
-/*!
- * Benchmark.js v1.0.0 <http://benchmarkjs.com/>
- * Copyright 2010-2012 Mathias Bynens <http://mths.be/>
- * Based on JSLitmus.js, copyright Robert Kieffer <http://broofa.com/>
- * Modified by John-David Dalton <http://allyoucanleet.com/>
- * Available under MIT license <http://mths.be/mit>
- */
-;(function(window, undefined) {
-  'use strict';
-
-  /** Used to assign each benchmark an incrimented id */
-  var counter = 0;
-
-  /** Detect DOM document object */
-  var doc = isHostType(window, 'document') && document;
-
-  /** Detect free variable `define` */
-  var freeDefine = typeof define == 'function' &&
-    typeof define.amd == 'object' && define.amd && define;
-
-  /** Detect free variable `exports` */
-  var freeExports = typeof exports == 'object' && exports &&
-    (typeof global == 'object' && global && global == global.global && (window = global), exports);
-
-  /** Detect free variable `require` */
-  var freeRequire = typeof require == 'function' && require;
-
-  /** Used to crawl all properties regardless of enumerability */
-  var getAllKeys = Object.getOwnPropertyNames;
-
-  /** Used to get property descriptors */
-  var getDescriptor = Object.getOwnPropertyDescriptor;
-
-  /** Used in case an object doesn't have its own method */
-  var hasOwnProperty = {}.hasOwnProperty;
-
-  /** Used to check if an object is extensible */
-  var isExtensible = Object.isExtensible || function() { return true; };
-
-  /** Used to access Wade Simmons' Node microtime module */
-  var microtimeObject = req('microtime');
-
-  /** Used to access the browser's high resolution timer */
-  var perfObject = isHostType(window, 'performance') && performance;
-
-  /** Used to call the browser's high resolution timer */
-  var perfName = perfObject && (
-    perfObject.now && 'now' ||
-    perfObject.webkitNow && 'webkitNow'
-  );
-
-  /** Used to access Node's high resolution timer */
-  var processObject = isHostType(window, 'process') && process;
-
-  /** Used to check if an own property is enumerable */
-  var propertyIsEnumerable = {}.propertyIsEnumerable;
-
-  /** Used to set property descriptors */
-  var setDescriptor = Object.defineProperty;
-
-  /** Used to resolve a value's internal [[Class]] */
-  var toString = {}.toString;
-
-  /** Used to prevent a `removeChild` memory leak in IE < 9 */
-  var trash = doc && doc.createElement('div');
-
-  /** Used to integrity check compiled tests */
-  var uid = 'uid' + (+new Date);
-
-  /** Used to avoid infinite recursion when methods call each other */
-  var calledBy = {};
-
-  /** Used to avoid hz of Infinity */
-  var divisors = {
-    '1': 4096,
-    '2': 512,
-    '3': 64,
-    '4': 8,
-    '5': 0
-  };
-
-  /**
-   * T-Distribution two-tailed critical values for 95% confidence
-   * http://www.itl.nist.gov/div898/handbook/eda/section3/eda3672.htm
-   */
-  var tTable = {
-    '1':  12.706,'2':  4.303, '3':  3.182, '4':  2.776, '5':  2.571, '6':  2.447,
-    '7':  2.365, '8':  2.306, '9':  2.262, '10': 2.228, '11': 2.201, '12': 2.179,
-    '13': 2.16,  '14': 2.145, '15': 2.131, '16': 2.12,  '17': 2.11,  '18': 2.101,
-    '19': 2.093, '20': 2.086, '21': 2.08,  '22': 2.074, '23': 2.069, '24': 2.064,
-    '25': 2.06,  '26': 2.056, '27': 2.052, '28': 2.048, '29': 2.045, '30': 2.042,
-    'infinity': 1.96
-  };
-
-  /**
-   * Critical Mann-Whitney U-values for 95% confidence
-   * http://www.saburchill.com/IBbiology/stats/003.html
-   */
-  var uTable = {
-    '5':  [0, 1, 2],
-    '6':  [1, 2, 3, 5],
-    '7':  [1, 3, 5, 6, 8],
-    '8':  [2, 4, 6, 8, 10, 13],
-    '9':  [2, 4, 7, 10, 12, 15, 17],
-    '10': [3, 5, 8, 11, 14, 17, 20, 23],
-    '11': [3, 6, 9, 13, 16, 19, 23, 26, 30],
-    '12': [4, 7, 11, 14, 18, 22, 26, 29, 33, 37],
-    '13': [4, 8, 12, 16, 20, 24, 28, 33, 37, 41, 45],
-    '14': [5, 9, 13, 17, 22, 26, 31, 36, 40, 45, 50, 55],
-    '15': [5, 10, 14, 19, 24, 29, 34, 39, 44, 49, 54, 59, 64],
-    '16': [6, 11, 15, 21, 26, 31, 37, 42, 47, 53, 59, 64, 70, 75],
-    '17': [6, 11, 17, 22, 28, 34, 39, 45, 51, 57, 63, 67, 75, 81, 87],
-    '18': [7, 12, 18, 24, 30, 36, 42, 48, 55, 61, 67, 74, 80, 86, 93, 99],
-    '19': [7, 13, 19, 25, 32, 38, 45, 52, 58, 65, 72, 78, 85, 92, 99, 106, 113],
-    '20': [8, 14, 20, 27, 34, 41, 48, 55, 62, 69, 76, 83, 90, 98, 105, 112, 119, 127],
-    '21': [8, 15, 22, 29, 36, 43, 50, 58, 65, 73, 80, 88, 96, 103, 111, 119, 126, 134, 142],
-    '22': [9, 16, 23, 30, 38, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 141, 150, 158],
-    '23': [9, 17, 24, 32, 40, 48, 56, 64, 73, 81, 89, 98, 106, 115, 123, 132, 140, 149, 157, 166, 175],
-    '24': [10, 17, 25, 33, 42, 50, 59, 67, 76, 85, 94, 102, 111, 120, 129, 138, 147, 156, 165, 174, 183, 192],
-    '25': [10, 18, 27, 35, 44, 53, 62, 71, 80, 89, 98, 107, 117, 126, 135, 145, 154, 163, 173, 182, 192, 201, 211],
-    '26': [11, 19, 28, 37, 46, 55, 64, 74, 83, 93, 102, 112, 122, 132, 141, 151, 161, 171, 181, 191, 200, 210, 220, 230],
-    '27': [11, 20, 29, 38, 48, 57, 67, 77, 87, 97, 107, 118, 125, 138, 147, 158, 168, 178, 188, 199, 209, 219, 230, 240, 250],
-    '28': [12, 21, 30, 40, 50, 60, 70, 80, 90, 101, 111, 122, 132, 143, 154, 164, 175, 186, 196, 207, 218, 228, 239, 250, 261, 272],
-    '29': [13, 22, 32, 42, 52, 62, 73, 83, 94, 105, 116, 127, 138, 149, 160, 171, 182, 193, 204, 215, 226, 238, 249, 260, 271, 282, 294],
-    '30': [13, 23, 33, 43, 54, 65, 76, 87, 98, 109, 120, 131, 143, 154, 166, 177, 189, 200, 212, 223, 235, 247, 258, 270, 282, 293, 305, 317]
-  };
-
-  /**
-   * An object used to flag environments/features.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @type Object
-   */
-  var support = {};
-
-  (function() {
-
-    /**
-     * Detect Adobe AIR.
-     *
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    support.air = isClassOf(window.runtime, 'ScriptBridgingProxyObject');
-
-    /**
-     * Detect if `arguments` objects have the correct internal [[Class]] value.
-     *
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    support.argumentsClass = isClassOf(arguments, 'Arguments');
-
-    /**
-     * Detect if in a browser environment.
-     *
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    support.browser = doc && isHostType(window, 'navigator');
-
-    /**
-     * Detect if strings support accessing characters by index.
-     *
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    support.charByIndex =
-      // IE 8 supports indexes on string literals but not string objects
-      ('x'[0] + Object('x')[0]) == 'xx';
-
-    /**
-     * Detect if strings have indexes as own properties.
-     *
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    support.charByOwnIndex =
-      // Narwhal, Rhino, RingoJS, IE 8, and Opera < 10.52 support indexes on
-      // strings but don't detect them as own properties
-      support.charByIndex && hasKey('x', '0');
-
-    /**
-     * Detect if Java is enabled/exposed.
-     *
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    support.java = isClassOf(window.java, 'JavaPackage');
-
-    /**
-     * Detect if the Timers API exists.
-     *
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    support.timeout = isHostType(window, 'setTimeout') && isHostType(window, 'clearTimeout');
-
-    /**
-     * Detect if functions support decompilation.
-     *
-     * @name decompilation
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    try {
-      // Safari 2.x removes commas in object literals
-      // from Function#toString results
-      // http://webk.it/11609
-      // Firefox 3.6 and Opera 9.25 strip grouping
-      // parentheses from Function#toString results
-      // http://bugzil.la/559438
-      support.decompilation = Function(
-        'return (' + (function(x) { return { 'x': '' + (1 + x) + '', 'y': 0 }; }) + ')'
-      )()(0).x === '1';
-    } catch(e) {
-      support.decompilation = false;
-    }
-
-    /**
-     * Detect ES5+ property descriptor API.
-     *
-     * @name descriptors
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    try {
-      var o = {};
-      support.descriptors = (setDescriptor(o, o, o), 'value' in getDescriptor(o, o));
-    } catch(e) {
-      support.descriptors = false;
-    }
-
-    /**
-     * Detect ES5+ Object.getOwnPropertyNames().
-     *
-     * @name getAllKeys
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    try {
-      support.getAllKeys = /\bvalueOf\b/.test(getAllKeys(Object.prototype));
-    } catch(e) {
-      support.getAllKeys = false;
-    }
-
-    /**
-     * Detect if own properties are iterated before inherited properties (all but IE < 9).
-     *
-     * @name iteratesOwnLast
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    support.iteratesOwnFirst = (function() {
-      var props = [];
-      function ctor() { this.x = 1; }
-      ctor.prototype = { 'y': 1 };
-      for (var prop in new ctor) { props.push(prop); }
-      return props[0] == 'x';
-    }());
-
-    /**
-     * Detect if a node's [[Class]] is resolvable (all but IE < 9)
-     * and that the JS engine errors when attempting to coerce an object to a
-     * string without a `toString` property value of `typeof` "function".
-     *
-     * @name nodeClass
-     * @memberOf Benchmark.support
-     * @type Boolean
-     */
-    try {
-      support.nodeClass = ({ 'toString': 0 } + '', toString.call(doc || 0) != '[object Object]');
-    } catch(e) {
-      support.nodeClass = true;
-    }
-  }());
-
-  /**
-   * Timer object used by `clock()` and `Deferred#resolve`.
-   *
-   * @private
-   * @type Object
-   */
-  var timer = {
-
-   /**
-    * The timer namespace object or constructor.
-    *
-    * @private
-    * @memberOf timer
-    * @type Function|Object
-    */
-    'ns': Date,
-
-   /**
-    * Starts the deferred timer.
-    *
-    * @private
-    * @memberOf timer
-    * @param {Object} deferred The deferred instance.
-    */
-    'start': null, // lazy defined in `clock()`
-
-   /**
-    * Stops the deferred timer.
-    *
-    * @private
-    * @memberOf timer
-    * @param {Object} deferred The deferred instance.
-    */
-    'stop': null // lazy defined in `clock()`
-  };
-
-  /** Shortcut for inverse results */
-  var noArgumentsClass = !support.argumentsClass,
-      noCharByIndex = !support.charByIndex,
-      noCharByOwnIndex = !support.charByOwnIndex;
-
-  /** Math shortcuts */
-  var abs   = Math.abs,
-      floor = Math.floor,
-      max   = Math.max,
-      min   = Math.min,
-      pow   = Math.pow,
-      sqrt  = Math.sqrt;
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * The Benchmark constructor.
-   *
-   * @constructor
-   * @param {String} name A name to identify the benchmark.
-   * @param {Function|String} fn The test to benchmark.
-   * @param {Object} [options={}] Options object.
-   * @example
-   *
-   * // basic usage (the `new` operator is optional)
-   * var bench = new Benchmark(fn);
-   *
-   * // or using a name first
-   * var bench = new Benchmark('foo', fn);
-   *
-   * // or with options
-   * var bench = new Benchmark('foo', fn, {
-   *
-   *   // displayed by Benchmark#toString if `name` is not available
-   *   'id': 'xyz',
-   *
-   *   // called when the benchmark starts running
-   *   'onStart': onStart,
-   *
-   *   // called after each run cycle
-   *   'onCycle': onCycle,
-   *
-   *   // called when aborted
-   *   'onAbort': onAbort,
-   *
-   *   // called when a test errors
-   *   'onError': onError,
-   *
-   *   // called when reset
-   *   'onReset': onReset,
-   *
-   *   // called when the benchmark completes running
-   *   'onComplete': onComplete,
-   *
-   *   // compiled/called before the test loop
-   *   'setup': setup,
-   *
-   *   // compiled/called after the test loop
-   *   'teardown': teardown
-   * });
-   *
-   * // or name and options
-   * var bench = new Benchmark('foo', {
-   *
-   *   // a flag to indicate the benchmark is deferred
-   *   'defer': true,
-   *
-   *   // benchmark test function
-   *   'fn': function(deferred) {
-   *     // call resolve() when the deferred test is finished
-   *     deferred.resolve();
-   *   }
-   * });
-   *
-   * // or options only
-   * var bench = new Benchmark({
-   *
-   *   // benchmark name
-   *   'name': 'foo',
-   *
-   *   // benchmark test as a string
-   *   'fn': '[1,2,3,4].sort()'
-   * });
-   *
-   * // a test's `this` binding is set to the benchmark instance
-   * var bench = new Benchmark('foo', function() {
-   *   'My name is '.concat(this.name); // My name is foo
-   * });
-   */
-  function Benchmark(name, fn, options) {
-    var me = this;
-
-    // allow instance creation without the `new` operator
-    if (me == null || me.constructor != Benchmark) {
-      return new Benchmark(name, fn, options);
-    }
-    // juggle arguments
-    if (isClassOf(name, 'Object')) {
-      // 1 argument (options)
-      options = name;
-    }
-    else if (isClassOf(name, 'Function')) {
-      // 2 arguments (fn, options)
-      options = fn;
-      fn = name;
-    }
-    else if (isClassOf(fn, 'Object')) {
-      // 2 arguments (name, options)
-      options = fn;
-      fn = null;
-      me.name = name;
-    }
-    else {
-      // 3 arguments (name, fn [, options])
-      me.name = name;
-    }
-    setOptions(me, options);
-    me.id || (me.id = ++counter);
-    me.fn == null && (me.fn = fn);
-    me.stats = deepClone(me.stats);
-    me.times = deepClone(me.times);
-  }
-
-  /**
-   * The Deferred constructor.
-   *
-   * @constructor
-   * @memberOf Benchmark
-   * @param {Object} clone The cloned benchmark instance.
-   */
-  function Deferred(clone) {
-    var me = this;
-    if (me == null || me.constructor != Deferred) {
-      return new Deferred(clone);
-    }
-    me.benchmark = clone;
-    clock(me);
-  }
-
-  /**
-   * The Event constructor.
-   *
-   * @constructor
-   * @memberOf Benchmark
-   * @param {String|Object} type The event type.
-   */
-  function Event(type) {
-    var me = this;
-    return (me == null || me.constructor != Event)
-      ? new Event(type)
-      : (type instanceof Event)
-          ? type
-          : extend(me, { 'timeStamp': +new Date }, typeof type == 'string' ? { 'type': type } : type);
-  }
-
-  /**
-   * The Suite constructor.
-   *
-   * @constructor
-   * @memberOf Benchmark
-   * @param {String} name A name to identify the suite.
-   * @param {Object} [options={}] Options object.
-   * @example
-   *
-   * // basic usage (the `new` operator is optional)
-   * var suite = new Benchmark.Suite;
-   *
-   * // or using a name first
-   * var suite = new Benchmark.Suite('foo');
-   *
-   * // or with options
-   * var suite = new Benchmark.Suite('foo', {
-   *
-   *   // called when the suite starts running
-   *   'onStart': onStart,
-   *
-   *   // called between running benchmarks
-   *   'onCycle': onCycle,
-   *
-   *   // called when aborted
-   *   'onAbort': onAbort,
-   *
-   *   // called when a test errors
-   *   'onError': onError,
-   *
-   *   // called when reset
-   *   'onReset': onReset,
-   *
-   *   // called when the suite completes running
-   *   'onComplete': onComplete
-   * });
-   */
-  function Suite(name, options) {
-    var me = this;
-
-    // allow instance creation without the `new` operator
-    if (me == null || me.constructor != Suite) {
-      return new Suite(name, options);
-    }
-    // juggle arguments
-    if (isClassOf(name, 'Object')) {
-      // 1 argument (options)
-      options = name;
-    } else {
-      // 2 arguments (name [, options])
-      me.name = name;
-    }
-    setOptions(me, options);
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Note: Some array methods have been implemented in plain JavaScript to avoid
-   * bugs in IE, Opera, Rhino, and Mobile Safari.
-   *
-   * IE compatibility mode and IE < 9 have buggy Array `shift()` and `splice()`
-   * functions that fail to remove the last element, `object[0]`, of
-   * array-like-objects even though the `length` property is set to `0`.
-   * The `shift()` method is buggy in IE 8 compatibility mode, while `splice()`
-   * is buggy regardless of mode in IE < 9 and buggy in compatibility mode in IE 9.
-   *
-   * In Opera < 9.50 and some older/beta Mobile Safari versions using `unshift()`
-   * generically to augment the `arguments` object will pave the value at index 0
-   * without incrimenting the other values's indexes.
-   * https://github.com/documentcloud/underscore/issues/9
-   *
-   * Rhino and environments it powers, like Narwhal and RingoJS, may have
-   * buggy Array `concat()`, `reverse()`, `shift()`, `slice()`, `splice()` and
-   * `unshift()` functions that make sparse arrays non-sparse by assigning the
-   * undefined indexes a value of undefined.
-   * https://github.com/mozilla/rhino/commit/702abfed3f8ca043b2636efd31c14ba7552603dd
-   */
-
-  /**
-   * Creates an array containing the elements of the host array followed by the
-   * elements of each argument in order.
-   *
-   * @memberOf Benchmark.Suite
-   * @returns {Array} The new array.
-   */
-  function concat() {
-    var value,
-        j = -1,
-        length = arguments.length,
-        result = slice.call(this),
-        index = result.length;
-
-    while (++j < length) {
-      value = arguments[j];
-      if (isClassOf(value, 'Array')) {
-        for (var k = 0, l = value.length; k < l; k++, index++) {
-          if (k in value) {
-            result[index] = value[k];
-          }
-        }
-      } else {
-        result[index++] = value;
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Utility function used by `shift()`, `splice()`, and `unshift()`.
-   *
-   * @private
-   * @param {Number} start The index to start inserting elements.
-   * @param {Number} deleteCount The number of elements to delete from the insert point.
-   * @param {Array} elements The elements to insert.
-   * @returns {Array} An array of deleted elements.
-   */
-  function insert(start, deleteCount, elements) {
-    // `result` should have its length set to the `deleteCount`
-    // see https://bugs.ecmascript.org/show_bug.cgi?id=332
-    var deleteEnd = start + deleteCount,
-        elementCount = elements ? elements.length : 0,
-        index = start - 1,
-        length = start + elementCount,
-        object = this,
-        result = Array(deleteCount),
-        tail = slice.call(object, deleteEnd);
-
-    // delete elements from the array
-    while (++index < deleteEnd) {
-      if (index in object) {
-        result[index - start] = object[index];
-        delete object[index];
-      }
-    }
-    // insert elements
-    index = start - 1;
-    while (++index < length) {
-      object[index] = elements[index - start];
-    }
-    // append tail elements
-    start = index--;
-    length = max(0, (object.length >>> 0) - deleteCount + elementCount);
-    while (++index < length) {
-      if ((index - start) in tail) {
-        object[index] = tail[index - start];
-      } else if (index in object) {
-        delete object[index];
-      }
-    }
-    // delete excess elements
-    deleteCount = deleteCount > elementCount ? deleteCount - elementCount : 0;
-    while (deleteCount--) {
-      index = length + deleteCount;
-      if (index in object) {
-        delete object[index];
-      }
-    }
-    object.length = length;
-    return result;
-  }
-
-  /**
-   * Rearrange the host array's elements in reverse order.
-   *
-   * @memberOf Benchmark.Suite
-   * @returns {Array} The reversed array.
-   */
-  function reverse() {
-    var upperIndex,
-        value,
-        index = -1,
-        object = Object(this),
-        length = object.length >>> 0,
-        middle = floor(length / 2);
-
-    if (length > 1) {
-      while (++index < middle) {
-        upperIndex = length - index - 1;
-        value = upperIndex in object ? object[upperIndex] : uid;
-        if (index in object) {
-          object[upperIndex] = object[index];
-        } else {
-          delete object[upperIndex];
-        }
-        if (value != uid) {
-          object[index] = value;
-        } else {
-          delete object[index];
-        }
-      }
-    }
-    return object;
-  }
-
-  /**
-   * Removes the first element of the host array and returns it.
-   *
-   * @memberOf Benchmark.Suite
-   * @returns {Mixed} The first element of the array.
-   */
-  function shift() {
-    return insert.call(this, 0, 1)[0];
-  }
-
-  /**
-   * Creates an array of the host array's elements from the start index up to,
-   * but not including, the end index.
-   *
-   * @memberOf Benchmark.Suite
-   * @param {Number} start The starting index.
-   * @param {Number} end The end index.
-   * @returns {Array} The new array.
-   */
-  function slice(start, end) {
-    var index = -1,
-        object = Object(this),
-        length = object.length >>> 0,
-        result = [];
-
-    start = toInteger(start);
-    start = start < 0 ? max(length + start, 0) : min(start, length);
-    start--;
-    end = end == null ? length : toInteger(end);
-    end = end < 0 ? max(length + end, 0) : min(end, length);
-
-    while ((++index, ++start) < end) {
-      if (start in object) {
-        result[index] = object[start];
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Allows removing a range of elements and/or inserting elements into the
-   * host array.
-   *
-   * @memberOf Benchmark.Suite
-   * @param {Number} start The start index.
-   * @param {Number} deleteCount The number of elements to delete.
-   * @param {Mixed} [val1, val2, ...] values to insert at the `start` index.
-   * @returns {Array} An array of removed elements.
-   */
-  function splice(start, deleteCount) {
-    var object = Object(this),
-        length = object.length >>> 0;
-
-    start = toInteger(start);
-    start = start < 0 ? max(length + start, 0) : min(start, length);
-
-    // support the de-facto SpiderMonkey extension
-    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice#Parameters
-    // https://bugs.ecmascript.org/show_bug.cgi?id=429
-    deleteCount = arguments.length == 1
-      ? length - start
-      : min(max(toInteger(deleteCount), 0), length - start);
-
-    return insert.call(object, start, deleteCount, slice.call(arguments, 2));
-  }
-
-  /**
-   * Converts the specified `value` to an integer.
-   *
-   * @private
-   * @param {Mixed} value The value to convert.
-   * @returns {Number} The resulting integer.
-   */
-  function toInteger(value) {
-    value = +value;
-    return value === 0 || !isFinite(value) ? value || 0 : value - (value % 1);
-  }
-
-  /**
-   * Appends arguments to the host array.
-   *
-   * @memberOf Benchmark.Suite
-   * @returns {Number} The new length.
-   */
-  function unshift() {
-    var object = Object(this);
-    insert.call(object, 0, 0, arguments);
-    return object.length;
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * A generic `Function#bind` like method.
-   *
-   * @private
-   * @param {Function} fn The function to be bound to `thisArg`.
-   * @param {Mixed} thisArg The `this` binding for the given function.
-   * @returns {Function} The bound function.
-   */
-  function bind(fn, thisArg) {
-    return function() { fn.apply(thisArg, arguments); };
-  }
-
-  /**
-   * Creates a function from the given arguments string and body.
-   *
-   * @private
-   * @param {String} args The comma separated function arguments.
-   * @param {String} body The function body.
-   * @returns {Function} The new function.
-   */
-  function createFunction() {
-    // lazy define
-    createFunction = function(args, body) {
-      var result,
-          anchor = freeDefine ? define.amd : Benchmark,
-          prop = uid + 'createFunction';
-
-      runScript((freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '=function(' + args + '){' + body + '}');
-      result = anchor[prop];
-      delete anchor[prop];
-      return result;
-    };
-    // fix JaegerMonkey bug
-    // http://bugzil.la/639720
-    createFunction = support.browser && (createFunction('', 'return"' + uid + '"') || noop)() == uid ? createFunction : Function;
-    return createFunction.apply(null, arguments);
-  }
-
-  /**
-   * Delay the execution of a function based on the benchmark's `delay` property.
-   *
-   * @private
-   * @param {Object} bench The benchmark instance.
-   * @param {Object} fn The function to execute.
-   */
-  function delay(bench, fn) {
-    bench._timerId = setTimeout(fn, bench.delay * 1e3);
-  }
-
-  /**
-   * Destroys the given element.
-   *
-   * @private
-   * @param {Element} element The element to destroy.
-   */
-  function destroyElement(element) {
-    trash.appendChild(element);
-    trash.innerHTML = '';
-  }
-
-  /**
-   * Iterates over an object's properties, executing the `callback` for each.
-   * Callbacks may terminate the loop by explicitly returning `false`.
-   *
-   * @private
-   * @param {Object} object The object to iterate over.
-   * @param {Function} callback The function executed per own property.
-   * @param {Object} options The options object.
-   * @returns {Object} Returns the object iterated over.
-   */
-  function forProps() {
-    var forShadowed,
-        skipSeen,
-        forArgs = true,
-        shadowed = ['constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'valueOf'];
-
-    (function(enumFlag, key) {
-      // must use a non-native constructor to catch the Safari 2 issue
-      function Klass() { this.valueOf = 0; };
-      Klass.prototype.valueOf = 0;
-      // check various for-in bugs
-      for (key in new Klass) {
-        enumFlag += key == 'valueOf' ? 1 : 0;
-      }
-      // check if `arguments` objects have non-enumerable indexes
-      for (key in arguments) {
-        key == '0' && (forArgs = false);
-      }
-      // Safari 2 iterates over shadowed properties twice
-      // http://replay.waybackmachine.org/20090428222941/http://tobielangel.com/2007/1/29/for-in-loop-broken-in-safari/
-      skipSeen = enumFlag == 2;
-      // IE < 9 incorrectly makes an object's properties non-enumerable if they have
-      // the same name as other non-enumerable properties in its prototype chain.
-      forShadowed = !enumFlag;
-    }(0));
-
-    // lazy define
-    forProps = function(object, callback, options) {
-      options || (options = {});
-
-      var result = object;
-      object = Object(object);
-
-      var ctor,
-          key,
-          keys,
-          skipCtor,
-          done = !result,
-          which = options.which,
-          allFlag = which == 'all',
-          index = -1,
-          iteratee = object,
-          length = object.length,
-          ownFlag = allFlag || which == 'own',
-          seen = {},
-          skipProto = isClassOf(object, 'Function'),
-          thisArg = options.bind;
-
-      if (thisArg !== undefined) {
-        callback = bind(callback, thisArg);
-      }
-      // iterate all properties
-      if (allFlag && support.getAllKeys) {
-        for (index = 0, keys = getAllKeys(object), length = keys.length; index < length; index++) {
-          key = keys[index];
-          if (callback(object[key], key, object) === false) {
-            break;
-          }
-        }
-      }
-      // else iterate only enumerable properties
-      else {
-        for (key in object) {
-          // Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1
-          // (if the prototype or a property on the prototype has been set)
-          // incorrectly set a function's `prototype` property [[Enumerable]] value
-          // to `true`. Because of this we standardize on skipping the `prototype`
-          // property of functions regardless of their [[Enumerable]] value.
-          if ((done =
-              !(skipProto && key == 'prototype') &&
-              !(skipSeen && (hasKey(seen, key) || !(seen[key] = true))) &&
-              (!ownFlag || ownFlag && hasKey(object, key)) &&
-              callback(object[key], key, object) === false)) {
-            break;
-          }
-        }
-        // in IE < 9 strings don't support accessing characters by index
-        if (!done && (forArgs && isArguments(object) ||
-            ((noCharByIndex || noCharByOwnIndex) && isClassOf(object, 'String') &&
-              (iteratee = noCharByIndex ? object.split('') : object)))) {
-          while (++index < length) {
-            if ((done =
-                callback(iteratee[index], String(index), object) === false)) {
-              break;
-            }
-          }
-        }
-        if (!done && forShadowed) {
-          // Because IE < 9 can't set the `[[Enumerable]]` attribute of an existing
-          // property and the `constructor` property of a prototype defaults to
-          // non-enumerable, we manually skip the `constructor` property when we
-          // think we are iterating over a `prototype` object.
-          ctor = object.constructor;
-          skipCtor = ctor && ctor.prototype && ctor.prototype.constructor === ctor;
-          for (index = 0; index < 7; index++) {
-            key = shadowed[index];
-            if (!(skipCtor && key == 'constructor') &&
-                hasKey(object, key) &&
-                callback(object[key], key, object) === false) {
-              break;
-            }
-          }
-        }
-      }
-      return result;
-    };
-    return forProps.apply(null, arguments);
-  }
-
-  /**
-   * Gets the name of the first argument from a function's source.
-   *
-   * @private
-   * @param {Function} fn The function.
-   * @returns {String} The argument name.
-   */
-  function getFirstArgument(fn) {
-    return (!hasKey(fn, 'toString') &&
-      (/^[\s(]*function[^(]*\(([^\s,)]+)/.exec(fn) || 0)[1]) || '';
-  }
-
-  /**
-   * Computes the arithmetic mean of a sample.
-   *
-   * @private
-   * @param {Array} sample The sample.
-   * @returns {Number} The mean.
-   */
-  function getMean(sample) {
-    return reduce(sample, function(sum, x) {
-      return sum + x;
-    }) / sample.length || 0;
-  }
-
-  /**
-   * Gets the source code of a function.
-   *
-   * @private
-   * @param {Function} fn The function.
-   * @param {String} altSource A string used when a function's source code is unretrievable.
-   * @returns {String} The function's source code.
-   */
-  function getSource(fn, altSource) {
-    var result = altSource;
-    if (isStringable(fn)) {
-      result = String(fn);
-    } else if (support.decompilation) {
-      // escape the `{` for Firefox 1
-      result = (/^[^{]+\{([\s\S]*)}\s*$/.exec(fn) || 0)[1];
-    }
-    // trim string
-    result = (result || '').replace(/^\s+|\s+$/g, '');
-
-    // detect strings containing only the "use strict" directive
-    return /^(?:\/\*+[\w|\W]*?\*\/|\/\/.*?[\n\r\u2028\u2029]|\s)*(["'])use strict\1;?$/.test(result)
-      ? ''
-      : result;
-  }
-
-  /**
-   * Checks if a value is an `arguments` object.
-   *
-   * @private
-   * @param {Mixed} value The value to check.
-   * @returns {Boolean} Returns `true` if the value is an `arguments` object, else `false`.
-   */
-  function isArguments() {
-    // lazy define
-    isArguments = function(value) {
-      return toString.call(value) == '[object Arguments]';
-    };
-    if (noArgumentsClass) {
-      isArguments = function(value) {
-        return hasKey(value, 'callee') &&
-          !(propertyIsEnumerable && propertyIsEnumerable.call(value, 'callee'));
-      };
-    }
-    return isArguments(arguments[0]);
-  }
-
-  /**
-   * Checks if an object is of the specified class.
-   *
-   * @private
-   * @param {Mixed} value The value to check.
-   * @param {String} name The name of the class.
-   * @returns {Boolean} Returns `true` if the value is of the specified class, else `false`.
-   */
-  function isClassOf(value, name) {
-    return value != null && toString.call(value) == '[object ' + name + ']';
-  }
-
-  /**
-   * Host objects can return type values that are different from their actual
-   * data type. The objects we are concerned with usually return non-primitive
-   * types of object, function, or unknown.
-   *
-   * @private
-   * @param {Mixed} object The owner of the property.
-   * @param {String} property The property to check.
-   * @returns {Boolean} Returns `true` if the property value is a non-primitive, else `false`.
-   */
-  function isHostType(object, property) {
-    var type = object != null ? typeof object[property] : 'number';
-    return !/^(?:boolean|number|string|undefined)$/.test(type) &&
-      (type == 'object' ? !!object[property] : true);
-  }
-
-  /**
-   * Checks if a given `value` is an object created by the `Object` constructor
-   * assuming objects created by the `Object` constructor have no inherited
-   * enumerable properties and that there are no `Object.prototype` extensions.
-   *
-   * @private
-   * @param {Mixed} value The value to check.
-   * @returns {Boolean} Returns `true` if the `value` is a plain `Object` object, else `false`.
-   */
-  function isPlainObject(value) {
-    // avoid non-objects and false positives for `arguments` objects in IE < 9
-    var result = false;
-    if (!(value && typeof value == 'object') || (noArgumentsClass && isArguments(value))) {
-      return result;
-    }
-    // IE < 9 presents DOM nodes as `Object` objects except they have `toString`
-    // methods that are `typeof` "string" and still can coerce nodes to strings.
-    // Also check that the constructor is `Object` (i.e. `Object instanceof Object`)
-    var ctor = value.constructor;
-    if ((support.nodeClass || !(typeof value.toString != 'function' && typeof (value + '') == 'string')) &&
-        (!isClassOf(ctor, 'Function') || ctor instanceof ctor)) {
-      // In most environments an object's own properties are iterated before
-      // its inherited properties. If the last iterated property is an object's
-      // own property then there are no inherited enumerable properties.
-      if (support.iteratesOwnFirst) {
-        forProps(value, function(subValue, subKey) {
-          result = subKey;
-        });
-        return result === false || hasKey(value, result);
-      }
-      // IE < 9 iterates inherited properties before own properties. If the first
-      // iterated property is an object's own property then there are no inherited
-      // enumerable properties.
-      forProps(value, function(subValue, subKey) {
-        result = !hasKey(value, subKey);
-        return false;
-      });
-      return result === false;
-    }
-    return result;
-  }
-
-  /**
-   * Checks if a value can be safely coerced to a string.
-   *
-   * @private
-   * @param {Mixed} value The value to check.
-   * @returns {Boolean} Returns `true` if the value can be coerced, else `false`.
-   */
-  function isStringable(value) {
-    return hasKey(value, 'toString') || isClassOf(value, 'String');
-  }
-
-  /**
-   * Wraps a function and passes `this` to the original function as the
-   * first argument.
-   *
-   * @private
-   * @param {Function} fn The function to be wrapped.
-   * @returns {Function} The new function.
-   */
-  function methodize(fn) {
-    return function() {
-      var args = [this];
-      args.push.apply(args, arguments);
-      return fn.apply(null, args);
-    };
-  }
-
-  /**
-   * A no-operation function.
-   *
-   * @private
-   */
-  function noop() {
-    // no operation performed
-  }
-
-  /**
-   * A wrapper around require() to suppress `module missing` errors.
-   *
-   * @private
-   * @param {String} id The module id.
-   * @returns {Mixed} The exported module or `null`.
-   */
-  function req(id) {
-    try {
-      var result = freeExports && freeRequire(id);
-    } catch(e) { }
-    return result || null;
-  }
-
-  /**
-   * Runs a snippet of JavaScript via script injection.
-   *
-   * @private
-   * @param {String} code The code to run.
-   */
-  function runScript(code) {
-    var anchor = freeDefine ? define.amd : Benchmark,
-        script = doc.createElement('script'),
-        sibling = doc.getElementsByTagName('script')[0],
-        parent = sibling.parentNode,
-        prop = uid + 'runScript',
-        prefix = '(' + (freeDefine ? 'define.amd.' : 'Benchmark.') + prop + '||function(){})();';
-
-    // Firefox 2.0.0.2 cannot use script injection as intended because it executes
-    // asynchronously, but that's OK because script injection is only used to avoid
-    // the previously commented JaegerMonkey bug.
-    try {
-      // remove the inserted script *before* running the code to avoid differences
-      // in the expected script element count/order of the document.
-      script.appendChild(doc.createTextNode(prefix + code));
-      anchor[prop] = function() { destroyElement(script); };
-    } catch(e) {
-      parent = parent.cloneNode(false);
-      sibling = null;
-      script.text = code;
-    }
-    parent.insertBefore(script, sibling);
-    delete anchor[prop];
-  }
-
-  /**
-   * A helper function for setting options/event handlers.
-   *
-   * @private
-   * @param {Object} bench The benchmark instance.
-   * @param {Object} [options={}] Options object.
-   */
-  function setOptions(bench, options) {
-    options = extend({}, bench.constructor.options, options);
-    bench.options = forOwn(options, function(value, key) {
-      if (value != null) {
-        // add event listeners
-        if (/^on[A-Z]/.test(key)) {
-          forEach(key.split(' '), function(key) {
-            bench.on(key.slice(2).toLowerCase(), value);
-          });
-        } else if (!hasKey(bench, key)) {
-          bench[key] = deepClone(value);
-        }
-      }
-    });
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Handles cycling/completing the deferred benchmark.
-   *
-   * @memberOf Benchmark.Deferred
-   */
-  function resolve() {
-    var me = this,
-        clone = me.benchmark,
-        bench = clone._original;
-
-    if (bench.aborted) {
-      // cycle() -> clone cycle/complete event -> compute()'s invoked bench.run() cycle/complete
-      me.teardown();
-      clone.running = false;
-      cycle(me);
-    }
-    else if (++me.cycles < clone.count) {
-      // continue the test loop
-      if (support.timeout) {
-        // use setTimeout to avoid a call stack overflow if called recursively
-        setTimeout(function() { clone.compiled.call(me, timer); }, 0);
-      } else {
-        clone.compiled.call(me, timer);
-      }
-    }
-    else {
-      timer.stop(me);
-      me.teardown();
-      delay(clone, function() { cycle(me); });
-    }
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * A deep clone utility.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Mixed} value The value to clone.
-   * @returns {Mixed} The cloned value.
-   */
-  function deepClone(value) {
-    var accessor,
-        circular,
-        clone,
-        ctor,
-        descriptor,
-        extensible,
-        key,
-        length,
-        markerKey,
-        parent,
-        result,
-        source,
-        subIndex,
-        data = { 'value': value },
-        index = 0,
-        marked = [],
-        queue = { 'length': 0 },
-        unmarked = [];
-
-    /**
-     * An easily detectable decorator for cloned values.
-     */
-    function Marker(object) {
-      this.raw = object;
-    }
-
-    /**
-     * The callback used by `forProps()`.
-     */
-    function forPropsCallback(subValue, subKey) {
-      // exit early to avoid cloning the marker
-      if (subValue && subValue.constructor == Marker) {
-        return;
-      }
-      // add objects to the queue
-      if (subValue === Object(subValue)) {
-        queue[queue.length++] = { 'key': subKey, 'parent': clone, 'source': value };
-      }
-      // assign non-objects
-      else {
-        try {
-          // will throw an error in strict mode if the property is read-only
-          clone[subKey] = subValue;
-        } catch(e) { }
-      }
-    }
-
-    /**
-     * Gets an available marker key for the given object.
-     */
-    function getMarkerKey(object) {
-      // avoid collisions with existing keys
-      var result = uid;
-      while (object[result] && object[result].constructor != Marker) {
-        result += 1;
-      }
-      return result;
-    }
-
-    do {
-      key = data.key;
-      parent = data.parent;
-      source = data.source;
-      clone = value = source ? source[key] : data.value;
-      accessor = circular = descriptor = false;
-
-      // create a basic clone to filter out functions, DOM elements, and
-      // other non `Object` objects
-      if (value === Object(value)) {
-        // use custom deep clone function if available
-        if (isClassOf(value.deepClone, 'Function')) {
-          clone = value.deepClone();
-        } else {
-          ctor = value.constructor;
-          switch (toString.call(value)) {
-            case '[object Array]':
-              clone = new ctor(value.length);
-              break;
-
-            case '[object Boolean]':
-              clone = new ctor(value == true);
-              break;
-
-            case '[object Date]':
-              clone = new ctor(+value);
-              break;
-
-            case '[object Object]':
-              isPlainObject(value) && (clone = {});
-              break;
-
-            case '[object Number]':
-            case '[object String]':
-              clone = new ctor(value);
-              break;
-
-            case '[object RegExp]':
-              clone = ctor(value.source,
-                (value.global     ? 'g' : '') +
-                (value.ignoreCase ? 'i' : '') +
-                (value.multiline  ? 'm' : ''));
-          }
-        }
-        // continue clone if `value` doesn't have an accessor descriptor
-        // http://es5.github.com/#x8.10.1
-        if (clone && clone != value &&
-            !(descriptor = source && support.descriptors && getDescriptor(source, key),
-              accessor = descriptor && (descriptor.get || descriptor.set))) {
-          // use an existing clone (circular reference)
-          if ((extensible = isExtensible(value))) {
-            markerKey = getMarkerKey(value);
-            if (value[markerKey]) {
-              circular = clone = value[markerKey].raw;
-            }
-          } else {
-            // for frozen/sealed objects
-            for (subIndex = 0, length = unmarked.length; subIndex < length; subIndex++) {
-              data = unmarked[subIndex];
-              if (data.object === value) {
-                circular = clone = data.clone;
-                break;
-              }
-            }
-          }
-          if (!circular) {
-            // mark object to allow quickly detecting circular references and tie it to its clone
-            if (extensible) {
-              value[markerKey] = new Marker(clone);
-              marked.push({ 'key': markerKey, 'object': value });
-            } else {
-              // for frozen/sealed objects
-              unmarked.push({ 'clone': clone, 'object': value });
-            }
-            // iterate over object properties
-            forProps(value, forPropsCallback, { 'which': 'all' });
-          }
-        }
-      }
-      if (parent) {
-        // for custom property descriptors
-        if (accessor || (descriptor && !(descriptor.configurable && descriptor.enumerable && descriptor.writable))) {
-          if ('value' in descriptor) {
-            descriptor.value = clone;
-          }
-          setDescriptor(parent, key, descriptor);
-        }
-        // for default property descriptors
-        else {
-          parent[key] = clone;
-        }
-      } else {
-        result = clone;
-      }
-    } while ((data = queue[index++]));
-
-    // remove markers
-    for (index = 0, length = marked.length; index < length; index++) {
-      data = marked[index];
-      delete data.object[data.key];
-    }
-    return result;
-  }
-
-  /**
-   * An iteration utility for arrays and objects.
-   * Callbacks may terminate the loop by explicitly returning `false`.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Array|Object} object The object to iterate over.
-   * @param {Function} callback The function called per iteration.
-   * @param {Mixed} thisArg The `this` binding for the callback.
-   * @returns {Array|Object} Returns the object iterated over.
-   */
-  function each(object, callback, thisArg) {
-    var result = object;
-    object = Object(object);
-
-    var fn = callback,
-        index = -1,
-        length = object.length,
-        isSnapshot = !!(object.snapshotItem && (length = object.snapshotLength)),
-        isSplittable = (noCharByIndex || noCharByOwnIndex) && isClassOf(object, 'String'),
-        isConvertable = isSnapshot || isSplittable || 'item' in object,
-        origObject = object;
-
-    // in Opera < 10.5 `hasKey(object, 'length')` returns `false` for NodeLists
-    if (length === length >>> 0) {
-      if (isConvertable) {
-        // the third argument of the callback is the original non-array object
-        callback = function(value, index) {
-          return fn.call(this, value, index, origObject);
-        };
-        // in IE < 9 strings don't support accessing characters by index
-        if (isSplittable) {
-          object = object.split('');
-        } else {
-          object = [];
-          while (++index < length) {
-            // in Safari 2 `index in object` is always `false` for NodeLists
-            object[index] = isSnapshot ? result.snapshotItem(index) : result[index];
-          }
-        }
-      }
-      forEach(object, callback, thisArg);
-    } else {
-      forOwn(object, callback, thisArg);
-    }
-    return result;
-  }
-
-  /**
-   * Copies enumerable properties from the source(s) object to the destination object.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Object} destination The destination object.
-   * @param {Object} [source={}] The source object.
-   * @returns {Object} The destination object.
-   */
-  function extend(destination, source) {
-    // Chrome < 14 incorrectly sets `destination` to `undefined` when we `delete arguments[0]`
-    // http://code.google.com/p/v8/issues/detail?id=839
-    var result = destination;
-    delete arguments[0];
-
-    forEach(arguments, function(source) {
-      forProps(source, function(value, key) {
-        result[key] = value;
-      });
-    });
-    return result;
-  }
-
-  /**
-   * A generic `Array#filter` like method.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Array} array The array to iterate over.
-   * @param {Function|String} callback The function/alias called per iteration.
-   * @param {Mixed} thisArg The `this` binding for the callback.
-   * @returns {Array} A new array of values that passed callback filter.
-   * @example
-   *
-   * // get odd numbers
-   * Benchmark.filter([1, 2, 3, 4, 5], function(n) {
-   *   return n % 2;
-   * }); // -> [1, 3, 5];
-   *
-   * // get fastest benchmarks
-   * Benchmark.filter(benches, 'fastest');
-   *
-   * // get slowest benchmarks
-   * Benchmark.filter(benches, 'slowest');
-   *
-   * // get benchmarks that completed without erroring
-   * Benchmark.filter(benches, 'successful');
-   */
-  function filter(array, callback, thisArg) {
-    var result;
-
-    if (callback == 'successful') {
-      // callback to exclude those that are errored, unrun, or have hz of Infinity
-      callback = function(bench) { return bench.cycles && isFinite(bench.hz); };
-    }
-    else if (callback == 'fastest' || callback == 'slowest') {
-      // get successful, sort by period + margin of error, and filter fastest/slowest
-      result = filter(array, 'successful').sort(function(a, b) {
-        a = a.stats; b = b.stats;
-        return (a.mean + a.moe > b.mean + b.moe ? 1 : -1) * (callback == 'fastest' ? 1 : -1);
-      });
-      result = filter(result, function(bench) {
-        return result[0].compare(bench) == 0;
-      });
-    }
-    return result || reduce(array, function(result, value, index) {
-      return callback.call(thisArg, value, index, array) ? (result.push(value), result) : result;
-    }, []);
-  }
-
-  /**
-   * A generic `Array#forEach` like method.
-   * Callbacks may terminate the loop by explicitly returning `false`.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Array} array The array to iterate over.
-   * @param {Function} callback The function called per iteration.
-   * @param {Mixed} thisArg The `this` binding for the callback.
-   * @returns {Array} Returns the array iterated over.
-   */
-  function forEach(array, callback, thisArg) {
-    var index = -1,
-        length = (array = Object(array)).length >>> 0;
-
-    if (thisArg !== undefined) {
-      callback = bind(callback, thisArg);
-    }
-    while (++index < length) {
-      if (index in array &&
-          callback(array[index], index, array) === false) {
-        break;
-      }
-    }
-    return array;
-  }
-
-  /**
-   * Iterates over an object's own properties, executing the `callback` for each.
-   * Callbacks may terminate the loop by explicitly returning `false`.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Object} object The object to iterate over.
-   * @param {Function} callback The function executed per own property.
-   * @param {Mixed} thisArg The `this` binding for the callback.
-   * @returns {Object} Returns the object iterated over.
-   */
-  function forOwn(object, callback, thisArg) {
-    return forProps(object, callback, { 'bind': thisArg, 'which': 'own' });
-  }
-
-  /**
-   * Converts a number to a more readable comma-separated string representation.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Number} number The number to convert.
-   * @returns {String} The more readable string representation.
-   */
-  function formatNumber(number) {
-    number = String(number).split('.');
-    return number[0].replace(/(?=(?:\d{3})+$)(?!\b)/g, ',') +
-      (number[1] ? '.' + number[1] : '');
-  }
-
-  /**
-   * Checks if an object has the specified key as a direct property.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Object} object The object to check.
-   * @param {String} key The key to check for.
-   * @returns {Boolean} Returns `true` if key is a direct property, else `false`.
-   */
-  function hasKey() {
-    // lazy define for worst case fallback (not as accurate)
-    hasKey = function(object, key) {
-      var parent = object != null && (object.constructor || Object).prototype;
-      return !!parent && key in Object(object) && !(key in parent && object[key] === parent[key]);
-    };
-    // for modern browsers
-    if (isClassOf(hasOwnProperty, 'Function')) {
-      hasKey = function(object, key) {
-        return object != null && hasOwnProperty.call(object, key);
-      };
-    }
-    // for Safari 2
-    else if ({}.__proto__ == Object.prototype) {
-      hasKey = function(object, key) {
-        var result = false;
-        if (object != null) {
-          object = Object(object);
-          object.__proto__ = [object.__proto__, object.__proto__ = null, result = key in object][0];
-        }
-        return result;
-      };
-    }
-    return hasKey.apply(this, arguments);
-  }
-
-  /**
-   * A generic `Array#indexOf` like method.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Array} array The array to iterate over.
-   * @param {Mixed} value The value to search for.
-   * @param {Number} [fromIndex=0] The index to start searching from.
-   * @returns {Number} The index of the matched value or `-1`.
-   */
-  function indexOf(array, value, fromIndex) {
-    var index = toInteger(fromIndex),
-        length = (array = Object(array)).length >>> 0;
-
-    index = (index < 0 ? max(0, length + index) : index) - 1;
-    while (++index < length) {
-      if (index in array && value === array[index]) {
-        return index;
-      }
-    }
-    return -1;
-  }
-
-  /**
-   * Modify a string by replacing named tokens with matching object property values.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {String} string The string to modify.
-   * @param {Object} object The template object.
-   * @returns {String} The modified string.
-   */
-  function interpolate(string, object) {
-    forOwn(object, function(value, key) {
-      // escape regexp special characters in `key`
-      string = string.replace(RegExp('#\\{' + key.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1') + '\\}', 'g'), value);
-    });
-    return string;
-  }
-
-  /**
-   * Invokes a method on all items in an array.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Array} benches Array of benchmarks to iterate over.
-   * @param {String|Object} name The name of the method to invoke OR options object.
-   * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
-   * @returns {Array} A new array of values returned from each method invoked.
-   * @example
-   *
-   * // invoke `reset` on all benchmarks
-   * Benchmark.invoke(benches, 'reset');
-   *
-   * // invoke `emit` with arguments
-   * Benchmark.invoke(benches, 'emit', 'complete', listener);
-   *
-   * // invoke `run(true)`, treat benchmarks as a queue, and register invoke callbacks
-   * Benchmark.invoke(benches, {
-   *
-   *   // invoke the `run` method
-   *   'name': 'run',
-   *
-   *   // pass a single argument
-   *   'args': true,
-   *
-   *   // treat as queue, removing benchmarks from front of `benches` until empty
-   *   'queued': true,
-   *
-   *   // called before any benchmarks have been invoked.
-   *   'onStart': onStart,
-   *
-   *   // called between invoking benchmarks
-   *   'onCycle': onCycle,
-   *
-   *   // called after all benchmarks have been invoked.
-   *   'onComplete': onComplete
-   * });
-   */
-  function invoke(benches, name) {
-    var args,
-        bench,
-        queued,
-        index = -1,
-        eventProps = { 'currentTarget': benches },
-        options = { 'onStart': noop, 'onCycle': noop, 'onComplete': noop },
-        result = map(benches, function(bench) { return bench; });
-
-    /**
-     * Invokes the method of the current object and if synchronous, fetches the next.
-     */
-    function execute() {
-      var listeners,
-          async = isAsync(bench);
-
-      if (async) {
-        // use `getNext` as the first listener
-        bench.on('complete', getNext);
-        listeners = bench.events.complete;
-        listeners.splice(0, 0, listeners.pop());
-      }
-      // execute method
-      result[index] = isClassOf(bench && bench[name], 'Function') ? bench[name].apply(bench, args) : undefined;
-      // if synchronous return true until finished
-      return !async && getNext();
-    }
-
-    /**
-     * Fetches the next bench or executes `onComplete` callback.
-     */
-    function getNext(event) {
-      var cycleEvent,
-          last = bench,
-          async = isAsync(last);
-
-      if (async) {
-        last.off('complete', getNext);
-        last.emit('complete');
-      }
-      // emit "cycle" event
-      eventProps.type = 'cycle';
-      eventProps.target = last;
-      cycleEvent = Event(eventProps);
-      options.onCycle.call(benches, cycleEvent);
-
-      // choose next benchmark if not exiting early
-      if (!cycleEvent.aborted && raiseIndex() !== false) {
-        bench = queued ? benches[0] : result[index];
-        if (isAsync(bench)) {
-          delay(bench, execute);
-        }
-        else if (async) {
-          // resume execution if previously asynchronous but now synchronous
-          while (execute()) { }
-        }
-        else {
-          // continue synchronous execution
-          return true;
-        }
-      } else {
-        // emit "complete" event
-        eventProps.type = 'complete';
-        options.onComplete.call(benches, Event(eventProps));
-      }
-      // When used as a listener `event.aborted = true` will cancel the rest of
-      // the "complete" listeners because they were already called above and when
-      // used as part of `getNext` the `return false` will exit the execution while-loop.
-      if (event) {
-        event.aborted = true;
-      } else {
-        return false;
-      }
-    }
-
-    /**
-     * Checks if invoking `Benchmark#run` with asynchronous cycles.
-     */
-    function isAsync(object) {
-      // avoid using `instanceof` here because of IE memory leak issues with host objects
-      var async = args[0] && args[0].async;
-      return Object(object).constructor == Benchmark && name == 'run' &&
-        ((async == null ? object.options.async : async) && support.timeout || object.defer);
-    }
-
-    /**
-     * Raises `index` to the next defined index or returns `false`.
-     */
-    function raiseIndex() {
-      var length = result.length;
-      if (queued) {
-        // if queued remove the previous bench and subsequent skipped non-entries
-        do {
-          ++index > 0 && shift.call(benches);
-        } while ((length = benches.length) && !('0' in benches));
-      }
-      else {
-        while (++index < length && !(index in result)) { }
-      }
-      // if we reached the last index then return `false`
-      return (queued ? length : index < length) ? index : (index = false);
-    }
-
-    // juggle arguments
-    if (isClassOf(name, 'String')) {
-      // 2 arguments (array, name)
-      args = slice.call(arguments, 2);
-    } else {
-      // 2 arguments (array, options)
-      options = extend(options, name);
-      name = options.name;
-      args = isClassOf(args = 'args' in options ? options.args : [], 'Array') ? args : [args];
-      queued = options.queued;
-    }
-
-    // start iterating over the array
-    if (raiseIndex() !== false) {
-      // emit "start" event
-      bench = result[index];
-      eventProps.type = 'start';
-      eventProps.target = bench;
-      options.onStart.call(benches, Event(eventProps));
-
-      // end early if the suite was aborted in an "onStart" listener
-      if (benches.aborted && benches.constructor == Suite && name == 'run') {
-        // emit "cycle" event
-        eventProps.type = 'cycle';
-        options.onCycle.call(benches, Event(eventProps));
-        // emit "complete" event
-        eventProps.type = 'complete';
-        options.onComplete.call(benches, Event(eventProps));
-      }
-      // else start
-      else {
-        if (isAsync(bench)) {
-          delay(bench, execute);
-        } else {
-          while (execute()) { }
-        }
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Creates a string of joined array values or object key-value pairs.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Array|Object} object The object to operate on.
-   * @param {String} [separator1=','] The separator used between key-value pairs.
-   * @param {String} [separator2=': '] The separator used between keys and values.
-   * @returns {String} The joined result.
-   */
-  function join(object, separator1, separator2) {
-    var result = [],
-        length = (object = Object(object)).length,
-        arrayLike = length === length >>> 0;
-
-    separator2 || (separator2 = ': ');
-    each(object, function(value, key) {
-      result.push(arrayLike ? value : key + separator2 + value);
-    });
-    return result.join(separator1 || ',');
-  }
-
-  /**
-   * A generic `Array#map` like method.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Array} array The array to iterate over.
-   * @param {Function} callback The function called per iteration.
-   * @param {Mixed} thisArg The `this` binding for the callback.
-   * @returns {Array} A new array of values returned by the callback.
-   */
-  function map(array, callback, thisArg) {
-    return reduce(array, function(result, value, index) {
-      result[index] = callback.call(thisArg, value, index, array);
-      return result;
-    }, Array(Object(array).length >>> 0));
-  }
-
-  /**
-   * Retrieves the value of a specified property from all items in an array.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Array} array The array to iterate over.
-   * @param {String} property The property to pluck.
-   * @returns {Array} A new array of property values.
-   */
-  function pluck(array, property) {
-    return map(array, function(object) {
-      return object == null ? undefined : object[property];
-    });
-  }
-
-  /**
-   * A generic `Array#reduce` like method.
-   *
-   * @static
-   * @memberOf Benchmark
-   * @param {Array} array The array to iterate over.
-   * @param {Function} callback The function called per iteration.
-   * @param {Mixed} accumulator Initial value of the accumulator.
-   * @returns {Mixed} The accumulator.
-   */
-  function reduce(array, callback, accumulator) {
-    var noaccum = arguments.length < 3;
-    forEach(array, function(value, index) {
-      accumulator = noaccum ? (noaccum = false, value) : callback(accumulator, value, index, array);
-    });
-    return accumulator;
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Aborts all benchmarks in the suite.
-   *
-   * @name abort
-   * @memberOf Benchmark.Suite
-   * @returns {Object} The suite instance.
-   */
-  function abortSuite() {
-    var event,
-        me = this,
-        resetting = calledBy.resetSuite;
-
-    if (me.running) {
-      event = Event('abort');
-      me.emit(event);
-      if (!event.cancelled || resetting) {
-        // avoid infinite recursion
-        calledBy.abortSuite = true;
-        me.reset();
-        delete calledBy.abortSuite;
-
-        if (!resetting) {
-          me.aborted = true;
-          invoke(me, 'abort');
-        }
-      }
-    }
-    return me;
-  }
-
-  /**
-   * Adds a test to the benchmark suite.
-   *
-   * @memberOf Benchmark.Suite
-   * @param {String} name A name to identify the benchmark.
-   * @param {Function|String} fn The test to benchmark.
-   * @param {Object} [options={}] Options object.
-   * @returns {Object} The benchmark instance.
-   * @example
-   *
-   * // basic usage
-   * suite.add(fn);
-   *
-   * // or using a name first
-   * suite.add('foo', fn);
-   *
-   * // or with options
-   * suite.add('foo', fn, {
-   *   'onCycle': onCycle,
-   *   'onComplete': onComplete
-   * });
-   *
-   * // or name and options
-   * suite.add('foo', {
-   *   'fn': fn,
-   *   'onCycle': onCycle,
-   *   'onComplete': onComplete
-   * });
-   *
-   * // or options only
-   * suite.add({
-   *   'name': 'foo',
-   *   'fn': fn,
-   *   'onCycle': onCycle,
-   *   'onComplete': onComplete
-   * });
-   */
-  function add(name, fn, options) {
-    var me = this,
-        bench = Benchmark(name, fn, options),
-        event = Event({ 'type': 'add', 'target': bench });
-
-    if (me.emit(event), !event.cancelled) {
-      me.push(bench);
-    }
-    return me;
-  }
-
-  /**
-   * Creates a new suite with cloned benchmarks.
-   *
-   * @name clone
-   * @memberOf Benchmark.Suite
-   * @param {Object} options Options object to overwrite cloned options.
-   * @returns {Object} The new suite instance.
-   */
-  function cloneSuite(options) {
-    var me = this,
-        result = new me.constructor(extend({}, me.options, options));
-
-    // copy own properties
-    forOwn(me, function(value, key) {
-      if (!hasKey(result, key)) {
-        result[key] = value && isClassOf(value.clone, 'Function')
-          ? value.clone()
-          : deepClone(value);
-      }
-    });
-    return result;
-  }
-
-  /**
-   * An `Array#filter` like method.
-   *
-   * @name filter
-   * @memberOf Benchmark.Suite
-   * @param {Function|String} callback The function/alias called per iteration.
-   * @returns {Object} A new suite of benchmarks that passed callback filter.
-   */
-  function filterSuite(callback) {
-    var me = this,
-        result = new me.constructor;
-
-    result.push.apply(result, filter(me, callback));
-    return result;
-  }
-
-  /**
-   * Resets all benchmarks in the suite.
-   *
-   * @name reset
-   * @memberOf Benchmark.Suite
-   * @returns {Object} The suite instance.
-   */
-  function resetSuite() {
-    var event,
-        me = this,
-        aborting = calledBy.abortSuite;
-
-    if (me.running && !aborting) {
-      // no worries, `resetSuite()` is called within `abortSuite()`
-      calledBy.resetSuite = true;
-      me.abort();
-      delete calledBy.resetSuite;
-    }
-    // reset if the state has changed
-    else if ((me.aborted || me.running) &&
-        (me.emit(event = Event('reset')), !event.cancelled)) {
-      me.running = false;
-      if (!aborting) {
-        invoke(me, 'reset');
-      }
-    }
-    return me;
-  }
-
-  /**
-   * Runs the suite.
-   *
-   * @name run
-   * @memberOf Benchmark.Suite
-   * @param {Object} [options={}] Options object.
-   * @returns {Object} The suite instance.
-   * @example
-   *
-   * // basic usage
-   * suite.run();
-   *
-   * // or with options
-   * suite.run({ 'async': true, 'queued': true });
-   */
-  function runSuite(options) {
-    var me = this;
-
-    me.reset();
-    me.running = true;
-    options || (options = {});
-
-    invoke(me, {
-      'name': 'run',
-      'args': options,
-      'queued': options.queued,
-      'onStart': function(event) {
-        me.emit(event);
-      },
-      'onCycle': function(event) {
-        var bench = event.target;
-        if (bench.error) {
-          me.emit({ 'type': 'error', 'target': bench });
-        }
-        me.emit(event);
-        event.aborted = me.aborted;
-      },
-      'onComplete': function(event) {
-        me.running = false;
-        me.emit(event);
-      }
-    });
-    return me;
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Executes all registered listeners of the specified event type.
-   *
-   * @memberOf Benchmark, Benchmark.Suite
-   * @param {String|Object} type The event type or object.
-   * @returns {Mixed} Returns the return value of the last listener executed.
-   */
-  function emit(type) {
-    var listeners,
-        me = this,
-        event = Event(type),
-        events = me.events,
-        args = (arguments[0] = event, arguments);
-
-    event.currentTarget || (event.currentTarget = me);
-    event.target || (event.target = me);
-    delete event.result;
-
-    if (events && (listeners = hasKey(events, event.type) && events[event.type])) {
-      forEach(listeners.slice(), function(listener) {
-        if ((event.result = listener.apply(me, args)) === false) {
-          event.cancelled = true;
-        }
-        return !event.aborted;
-      });
-    }
-    return event.result;
-  }
-
-  /**
-   * Returns an array of event listeners for a given type that can be manipulated
-   * to add or remove listeners.
-   *
-   * @memberOf Benchmark, Benchmark.Suite
-   * @param {String} type The event type.
-   * @returns {Array} The listeners array.
-   */
-  function listeners(type) {
-    var me = this,
-        events = me.events || (me.events = {});
-
-    return hasKey(events, type) ? events[type] : (events[type] = []);
-  }
-
-  /**
-   * Unregisters a listener for the specified event type(s),
-   * or unregisters all listeners for the specified event type(s),
-   * or unregisters all listeners for all event types.
-   *
-   * @memberOf Benchmark, Benchmark.Suite
-   * @param {String} [type] The event type.
-   * @param {Function} [listener] The function to unregister.
-   * @returns {Object} The benchmark instance.
-   * @example
-   *
-   * // unregister a listener for an event type
-   * bench.off('cycle', listener);
-   *
-   * // unregister a listener for multiple event types
-   * bench.off('start cycle', listener);
-   *
-   * // unregister all listeners for an event type
-   * bench.off('cycle');
-   *
-   * // unregister all listeners for multiple event types
-   * bench.off('start cycle complete');
-   *
-   * // unregister all listeners for all event types
-   * bench.off();
-   */
-  function off(type, listener) {
-    var me = this,
-        events = me.events;
-
-    events && each(type ? type.split(' ') : events, function(listeners, type) {
-      var index;
-      if (typeof listeners == 'string') {
-        type = listeners;
-        listeners = hasKey(events, type) && events[type];
-      }
-      if (listeners) {
-        if (listener) {
-          index = indexOf(listeners, listener);
-          if (index > -1) {
-            listeners.splice(index, 1);
-          }
-        } else {
-          listeners.length = 0;
-        }
-      }
-    });
-    return me;
-  }
-
-  /**
-   * Registers a listener for the specified event type(s).
-   *
-   * @memberOf Benchmark, Benchmark.Suite
-   * @param {String} type The event type.
-   * @param {Function} listener The function to register.
-   * @returns {Object} The benchmark instance.
-   * @example
-   *
-   * // register a listener for an event type
-   * bench.on('cycle', listener);
-   *
-   * // register a listener for multiple event types
-   * bench.on('start cycle', listener);
-   */
-  function on(type, listener) {
-    var me = this,
-        events = me.events || (me.events = {});
-
-    forEach(type.split(' '), function(type) {
-      (hasKey(events, type)
-        ? events[type]
-        : (events[type] = [])
-      ).push(listener);
-    });
-    return me;
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Aborts the benchmark without recording times.
-   *
-   * @memberOf Benchmark
-   * @returns {Object} The benchmark instance.
-   */
-  function abort() {
-    var event,
-        me = this,
-        resetting = calledBy.reset;
-
-    if (me.running) {
-      event = Event('abort');
-      me.emit(event);
-      if (!event.cancelled || resetting) {
-        // avoid infinite recursion
-        calledBy.abort = true;
-        me.reset();
-        delete calledBy.abort;
-
-        if (support.timeout) {
-          clearTimeout(me._timerId);
-          delete me._timerId;
-        }
-        if (!resetting) {
-          me.aborted = true;
-          me.running = false;
-        }
-      }
-    }
-    return me;
-  }
-
-  /**
-   * Creates a new benchmark using the same test and options.
-   *
-   * @memberOf Benchmark
-   * @param {Object} options Options object to overwrite cloned options.
-   * @returns {Object} The new benchmark instance.
-   * @example
-   *
-   * var bizarro = bench.clone({
-   *   'name': 'doppelganger'
-   * });
-   */
-  function clone(options) {
-    var me = this,
-        result = new me.constructor(extend({}, me, options));
-
-    // correct the `options` object
-    result.options = extend({}, me.options, options);
-
-    // copy own custom properties
-    forOwn(me, function(value, key) {
-      if (!hasKey(result, key)) {
-        result[key] = deepClone(value);
-      }
-    });
-    return result;
-  }
-
-  /**
-   * Determines if a benchmark is faster than another.
-   *
-   * @memberOf Benchmark
-   * @param {Object} other The benchmark to compare.
-   * @returns {Number} Returns `-1` if slower, `1` if faster, and `0` if indeterminate.
-   */
-  function compare(other) {
-    var critical,
-        zStat,
-        me = this,
-        sample1 = me.stats.sample,
-        sample2 = other.stats.sample,
-        size1 = sample1.length,
-        size2 = sample2.length,
-        maxSize = max(size1, size2),
-        minSize = min(size1, size2),
-        u1 = getU(sample1, sample2),
-        u2 = getU(sample2, sample1),
-        u = min(u1, u2);
-
-    function getScore(xA, sampleB) {
-      return reduce(sampleB, function(total, xB) {
-        return total + (xB > xA ? 0 : xB < xA ? 1 : 0.5);
-      }, 0);
-    }
-
-    function getU(sampleA, sampleB) {
-      return reduce(sampleA, function(total, xA) {
-        return total + getScore(xA, sampleB);
-      }, 0);
-    }
-
-    function getZ(u) {
-      return (u - ((size1 * size2) / 2)) / sqrt((size1 * size2 * (size1 + size2 + 1)) / 12);
-    }
-
-    // exit early if comparing the same benchmark
-    if (me == other) {
-      return 0;
-    }
-    // reject the null hyphothesis the two samples come from the
-    // same population (i.e. have the same median) if...
-    if (size1 + size2 > 30) {
-      // ...the z-stat is greater than 1.96 or less than -1.96
-      // http://www.statisticslectures.com/topics/mannwhitneyu/
-      zStat = getZ(u);
-      return abs(zStat) > 1.96 ? (zStat > 0 ? -1 : 1) : 0;
-    }
-    // ...the U value is less than or equal the critical U value
-    // http://www.geoib.com/mann-whitney-u-test.html
-    critical = maxSize < 5 || minSize < 3 ? 0 : uTable[maxSize][minSize - 3];
-    return u <= critical ? (u == u1 ? 1 : -1) : 0;
-  }
-
-  /**
-   * Reset properties and abort if running.
-   *
-   * @memberOf Benchmark
-   * @returns {Object} The benchmark instance.
-   */
-  function reset() {
-    var data,
-        event,
-        me = this,
-        index = 0,
-        changes = { 'length': 0 },
-        queue = { 'length': 0 };
-
-    if (me.running && !calledBy.abort) {
-      // no worries, `reset()` is called within `abort()`
-      calledBy.reset = true;
-      me.abort();
-      delete calledBy.reset;
-    }
-    else {
-      // a non-recursive solution to check if properties have changed
-      // http://www.jslab.dk/articles/non.recursive.preorder.traversal.part4
-      data = { 'destination': me, 'source': extend({}, me.constructor.prototype, me.options) };
-      do {
-        forOwn(data.source, function(value, key) {
-          var changed,
-              destination = data.destination,
-              currValue = destination[key];
-
-          if (value && typeof value == 'object') {
-            if (isClassOf(value, 'Array')) {
-              // check if an array value has changed to a non-array value
-              if (!isClassOf(currValue, 'Array')) {
-                changed = currValue = [];
-              }
-              // or has changed its length
-              if (currValue.length != value.length) {
-                changed = currValue = currValue.slice(0, value.length);
-                currValue.length = value.length;
-              }
-            }
-            // check if an object has changed to a non-object value
-            else if (!currValue || typeof currValue != 'object') {
-              changed = currValue = {};
-            }
-            // register a changed object
-            if (changed) {
-              changes[changes.length++] = { 'destination': destination, 'key': key, 'value': currValue };
-            }
-            queue[queue.length++] = { 'destination': currValue, 'source': value };
-          }
-          // register a changed primitive
-          else if (value !== currValue && !(value == null || isClassOf(value, 'Function'))) {
-            changes[changes.length++] = { 'destination': destination, 'key': key, 'value': value };
-          }
-        });
-      }
-      while ((data = queue[index++]));
-
-      // if changed emit the `reset` event and if it isn't cancelled reset the benchmark
-      if (changes.length && (me.emit(event = Event('reset')), !event.cancelled)) {
-        forEach(changes, function(data) {
-          data.destination[data.key] = data.value;
-        });
-      }
-    }
-    return me;
-  }
-
-  /**
-   * Displays relevant benchmark information when coerced to a string.
-   *
-   * @name toString
-   * @memberOf Benchmark
-   * @returns {String} A string representation of the benchmark instance.
-   */
-  function toStringBench() {
-    var me = this,
-        error = me.error,
-        hz = me.hz,
-        id = me.id,
-        stats = me.stats,
-        size = stats.sample.length,
-        pm = support.java ? '+/-' : '\xb1',
-        result = me.name || (isNaN(id) ? id : '<Test #' + id + '>');
-
-    if (error) {
-      result += ': ' + join(error);
-    } else {
-      result += ' x ' + formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' ops/sec ' + pm +
-        stats.rme.toFixed(2) + '% (' + size + ' run' + (size == 1 ? '' : 's') + ' sampled)';
-    }
-    return result;
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Clocks the time taken to execute a test per cycle (secs).
-   *
-   * @private
-   * @param {Object} bench The benchmark instance.
-   * @returns {Number} The time taken.
-   */
-  function clock() {
-    var applet,
-        options = Benchmark.options,
-        template = { 'begin': 's$=new n$', 'end': 'r$=(new n$-s$)/1e3', 'uid': uid },
-        timers = [{ 'ns': timer.ns, 'res': max(0.0015, getRes('ms')), 'unit': 'ms' }];
-
-    // lazy define for hi-res timers
-    clock = function(clone) {
-      var deferred;
-      if (clone instanceof Deferred) {
-        deferred = clone;
-        clone = deferred.benchmark;
-      }
-
-      var bench = clone._original,
-          fn = bench.fn,
-          fnArg = deferred ? getFirstArgument(fn) || 'deferred' : '',
-          stringable = isStringable(fn);
-
-      var source = {
-        'setup': getSource(bench.setup, preprocess('m$.setup()')),
-        'fn': getSource(fn, preprocess('m$.fn(' + fnArg + ')')),
-        'fnArg': fnArg,
-        'teardown': getSource(bench.teardown, preprocess('m$.teardown()'))
-      };
-
-      var count = bench.count = clone.count,
-          decompilable = support.decompilation || stringable,
-          id = bench.id,
-          isEmpty = !(source.fn || stringable),
-          name = bench.name || (typeof id == 'number' ? '<Test #' + id + '>' : id),
-          ns = timer.ns,
-          result = 0;
-
-      // init `minTime` if needed
-      clone.minTime = bench.minTime || (bench.minTime = bench.options.minTime = options.minTime);
-
-      // repair nanosecond timer
-      // (some Chrome builds erase the `ns` variable after millions of executions)
-      if (applet) {
-        try {
-          ns.nanoTime();
-        } catch(e) {
-          // use non-element to avoid issues with libs that augment them
-          ns = timer.ns = new applet.Packages.nano;
-        }
-      }
-
-      // Compile in setup/teardown functions and the test loop.
-      // Create a new compiled test, instead of using the cached `bench.compiled`,
-      // to avoid potential engine optimizations enabled over the life of the test.
-      var compiled = bench.compiled = createFunction(preprocess('t$'), interpolate(
-        preprocess(deferred
-          ? 'var d$=this,#{fnArg}=d$,m$=d$.benchmark._original,f$=m$.fn,su$=m$.setup,td$=m$.teardown;' +
-            // when `deferred.cycles` is `0` then...
-            'if(!d$.cycles){' +
-            // set `deferred.fn`
-            'd$.fn=function(){var #{fnArg}=d$;if(typeof f$=="function"){try{#{fn}\n}catch(e$){f$(d$)}}else{#{fn}\n}};' +
-            // set `deferred.teardown`
-            'd$.teardown=function(){d$.cycles=0;if(typeof td$=="function"){try{#{teardown}\n}catch(e$){td$()}}else{#{teardown}\n}};' +
-            // execute the benchmark's `setup`
-            'if(typeof su$=="function"){try{#{setup}\n}catch(e$){su$()}}else{#{setup}\n};' +
-            // start timer
-            't$.start(d$);' +
-            // execute `deferred.fn` and return a dummy object
-            '}d$.fn();return{}'
-
-          : 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count,n$=t$.ns;#{setup}\n#{begin};' +
-            'while(i$--){#{fn}\n}#{end};#{teardown}\nreturn{elapsed:r$,uid:"#{uid}"}'),
-        source
-      ));
-
-      try {
-        if (isEmpty) {
-          // Firefox may remove dead code from Function#toString results
-          // http://bugzil.la/536085
-          throw new Error('The test "' + name + '" is empty. This may be the result of dead code removal.');
-        }
-        else if (!deferred) {
-          // pretest to determine if compiled code is exits early, usually by a
-          // rogue `return` statement, by checking for a return object with the uid
-          bench.count = 1;
-          compiled = (compiled.call(bench, timer) || {}).uid == uid && compiled;
-          bench.count = count;
-        }
-      } catch(e) {
-        compiled = null;
-        clone.error = e || new Error(String(e));
-        bench.count = count;
-      }
-      // fallback when a test exits early or errors during pretest
-      if (decompilable && !compiled && !deferred && !isEmpty) {
-        compiled = createFunction(preprocess('t$'), interpolate(
-          preprocess(
-            (clone.error && !stringable
-              ? 'var r$,s$,m$=this,f$=m$.fn,i$=m$.count'
-              : 'function f$(){#{fn}\n}var r$,s$,m$=this,i$=m$.count'
-            ) +
-            ',n$=t$.ns;#{setup}\n#{begin};m$.f$=f$;while(i$--){m$.f$()}#{end};' +
-            'delete m$.f$;#{teardown}\nreturn{elapsed:r$}'
-          ),
-          source
-        ));
-
-        try {
-          // pretest one more time to check for errors
-          bench.count = 1;
-          compiled.call(bench, timer);
-          bench.compiled = compiled;
-          bench.count = count;
-          delete clone.error;
-        }
-        catch(e) {
-          bench.count = count;
-          if (clone.error) {
-            compiled = null;
-          } else {
-            bench.compiled = compiled;
-            clone.error = e || new Error(String(e));
-          }
-        }
-      }
-      // assign `compiled` to `clone` before calling in case a deferred benchmark
-      // immediately calls `deferred.resolve()`
-      clone.compiled = compiled;
-      // if no errors run the full test loop
-      if (!clone.error) {
-        result = compiled.call(deferred || bench, timer).elapsed;
-      }
-      return result;
-    };
-
-    /*------------------------------------------------------------------------*/
-
-    /**
-     * Gets the current timer's minimum resolution (secs).
-     */
-    function getRes(unit) {
-      var measured,
-          begin,
-          count = 30,
-          divisor = 1e3,
-          ns = timer.ns,
-          sample = [];
-
-      // get average smallest measurable time
-      while (count--) {
-        if (unit == 'us') {
-          divisor = 1e6;
-          if (ns.stop) {
-            ns.start();
-            while (!(measured = ns.microseconds())) { }
-          } else if (ns[perfName]) {
-            divisor = 1e3;
-            measured = Function('n', 'var r,s=n.' + perfName + '();while(!(r=n.' + perfName + '()-s)){};return r')(ns);
-          } else {
-            begin = ns();
-            while (!(measured = ns() - begin)) { }
-          }
-        }
-        else if (unit == 'ns') {
-          divisor = 1e9;
-          if (ns.nanoTime) {
-            begin = ns.nanoTime();
-            while (!(measured = ns.nanoTime() - begin)) { }
-          } else {
-            begin = (begin = ns())[0] + (begin[1] / divisor);
-            while (!(measured = ((measured = ns())[0] + (measured[1] / divisor)) - begin)) { }
-            divisor = 1;
-          }
-        }
-        else {
-          begin = new ns;
-          while (!(measured = new ns - begin)) { }
-        }
-        // check for broken timers (nanoTime may have issues)
-        // http://alivebutsleepy.srnet.cz/unreliable-system-nanotime/
-        if (measured > 0) {
-          sample.push(measured);
-        } else {
-          sample.push(Infinity);
-          break;
-        }
-      }
-      // convert to seconds
-      return getMean(sample) / divisor;
-    }
-
-    /**
-     * Replaces all occurrences of `$` with a unique number and
-     * template tokens with content.
-     */
-    function preprocess(code) {
-      return interpolate(code, template).replace(/\$/g, /\d+/.exec(uid));
-    }
-
-    /*------------------------------------------------------------------------*/
-
-    // detect nanosecond support from a Java applet
-    each(doc && doc.applets || [], function(element) {
-      return !(timer.ns = applet = 'nanoTime' in element && element);
-    });
-
-    // check type in case Safari returns an object instead of a number
-    try {
-      if (typeof timer.ns.nanoTime() == 'number') {
-        timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' });
-      }
-    } catch(e) { }
-
-    // detect Chrome's microsecond timer:
-    // enable benchmarking via the --enable-benchmarking command
-    // line switch in at least Chrome 7 to use chrome.Interval
-    try {
-      if ((timer.ns = new (window.chrome || window.chromium).Interval)) {
-        timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' });
-      }
-    } catch(e) { }
-
-    // detect `performance.now` microsecond resolution timer
-    if ((timer.ns = perfName && perfObject)) {
-      timers.push({ 'ns': timer.ns, 'res': getRes('us'), 'unit': 'us' });
-    }
-
-    // detect Node's nanosecond resolution timer available in Node >= 0.8
-    if (processObject && typeof (timer.ns = processObject.hrtime) == 'function') {
-      timers.push({ 'ns': timer.ns, 'res': getRes('ns'), 'unit': 'ns' });
-    }
-
-    // detect Wade Simmons' Node microtime module
-    if (microtimeObject && typeof (timer.ns = microtimeObject.now) == 'function') {
-      timers.push({ 'ns': timer.ns,  'res': getRes('us'), 'unit': 'us' });
-    }
-
-    // pick timer with highest resolution
-    timer = reduce(timers, function(timer, other) {
-      return other.res < timer.res ? other : timer;
-    });
-
-    // remove unused applet
-    if (timer.unit != 'ns' && applet) {
-      applet = destroyElement(applet);
-    }
-    // error if there are no working timers
-    if (timer.res == Infinity) {
-      throw new Error('Benchmark.js was unable to find a working timer.');
-    }
-    // use API of chosen timer
-    if (timer.unit == 'ns') {
-      if (timer.ns.nanoTime) {
-        extend(template, {
-          'begin': 's$=n$.nanoTime()',
-          'end': 'r$=(n$.nanoTime()-s$)/1e9'
-        });
-      } else {
-        extend(template, {
-          'begin': 's$=n$()',
-          'end': 'r$=n$(s$);r$=r$[0]+(r$[1]/1e9)'
-        });
-      }
-    }
-    else if (timer.unit == 'us') {
-      if (timer.ns.stop) {
-        extend(template, {
-          'begin': 's$=n$.start()',
-          'end': 'r$=n$.microseconds()/1e6'
-        });
-      } else if (perfName) {
-        extend(template, {
-          'begin': 's$=n$.' + perfName + '()',
-          'end': 'r$=(n$.' + perfName + '()-s$)/1e3'
-        });
-      } else {
-        extend(template, {
-          'begin': 's$=n$()',
-          'end': 'r$=(n$()-s$)/1e6'
-        });
-      }
-    }
-
-    // define `timer` methods
-    timer.start = createFunction(preprocess('o$'),
-      preprocess('var n$=this.ns,#{begin};o$.elapsed=0;o$.timeStamp=s$'));
-
-    timer.stop = createFunction(preprocess('o$'),
-      preprocess('var n$=this.ns,s$=o$.timeStamp,#{end};o$.elapsed=r$'));
-
-    // resolve time span required to achieve a percent uncertainty of at most 1%
-    // http://spiff.rit.edu/classes/phys273/uncert/uncert.html
-    options.minTime || (options.minTime = max(timer.res / 2 / 0.01, 0.05));
-    return clock.apply(null, arguments);
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Computes stats on benchmark results.
-   *
-   * @private
-   * @param {Object} bench The benchmark instance.
-   * @param {Object} options The options object.
-   */
-  function compute(bench, options) {
-    options || (options = {});
-
-    var async = options.async,
-        elapsed = 0,
-        initCount = bench.initCount,
-        minSamples = bench.minSamples,
-        queue = [],
-        sample = bench.stats.sample;
-
-    /**
-     * Adds a clone to the queue.
-     */
-    function enqueue() {
-      queue.push(bench.clone({
-        '_original': bench,
-        'events': {
-          'abort': [update],
-          'cycle': [update],
-          'error': [update],
-          'start': [update]
-        }
-      }));
-    }
-
-    /**
-     * Updates the clone/original benchmarks to keep their data in sync.
-     */
-    function update(event) {
-      var clone = this,
-          type = event.type;
-
-      if (bench.running) {
-        if (type == 'start') {
-          // Note: `clone.minTime` prop is inited in `clock()`
-          clone.count = bench.initCount;
-        }
-        else {
-          if (type == 'error') {
-            bench.error = clone.error;
-          }
-          if (type == 'abort') {
-            bench.abort();
-            bench.emit('cycle');
-          } else {
-            event.currentTarget = event.target = bench;
-            bench.emit(event);
-          }
-        }
-      } else if (bench.aborted) {
-        // clear abort listeners to avoid triggering bench's abort/cycle again
-        clone.events.abort.length = 0;
-        clone.abort();
-      }
-    }
-
-    /**
-     * Determines if more clones should be queued or if cycling should stop.
-     */
-    function evaluate(event) {
-      var critical,
-          df,
-          mean,
-          moe,
-          rme,
-          sd,
-          sem,
-          variance,
-          clone = event.target,
-          done = bench.aborted,
-          now = +new Date,
-          size = sample.push(clone.times.period),
-          maxedOut = size >= minSamples && (elapsed += now - clone.times.timeStamp) / 1e3 > bench.maxTime,
-          times = bench.times,
-          varOf = function(sum, x) { return sum + pow(x - mean, 2); };
-
-      // exit early for aborted or unclockable tests
-      if (done || clone.hz == Infinity) {
-        maxedOut = !(size = sample.length = queue.length = 0);
-      }
-
-      if (!done) {
-        // sample mean (estimate of the population mean)
-        mean = getMean(sample);
-        // sample variance (estimate of the population variance)
-        variance = reduce(sample, varOf, 0) / (size - 1) || 0;
-        // sample standard deviation (estimate of the population standard deviation)
-        sd = sqrt(variance);
-        // standard error of the mean (a.k.a. the standard deviation of the sampling distribution of the sample mean)
-        sem = sd / sqrt(size);
-        // degrees of freedom
-        df = size - 1;
-        // critical value
-        critical = tTable[Math.round(df) || 1] || tTable.infinity;
-        // margin of error
-        moe = sem * critical;
-        // relative margin of error
-        rme = (moe / mean) * 100 || 0;
-
-        extend(bench.stats, {
-          'deviation': sd,
-          'mean': mean,
-          'moe': moe,
-          'rme': rme,
-          'sem': sem,
-          'variance': variance
-        });
-
-        // Abort the cycle loop when the minimum sample size has been collected
-        // and the elapsed time exceeds the maximum time allowed per benchmark.
-        // We don't count cycle delays toward the max time because delays may be
-        // increased by browsers that clamp timeouts for inactive tabs.
-        // https://developer.mozilla.org/en/window.setTimeout#Inactive_tabs
-        if (maxedOut) {
-          // reset the `initCount` in case the benchmark is rerun
-          bench.initCount = initCount;
-          bench.running = false;
-          done = true;
-          times.elapsed = (now - times.timeStamp) / 1e3;
-        }
-        if (bench.hz != Infinity) {
-          bench.hz = 1 / mean;
-          times.cycle = mean * bench.count;
-          times.period = mean;
-        }
-      }
-      // if time permits, increase sample size to reduce the margin of error
-      if (queue.length < 2 && !maxedOut) {
-        enqueue();
-      }
-      // abort the invoke cycle when done
-      event.aborted = done;
-    }
-
-    // init queue and begin
-    enqueue();
-    invoke(queue, {
-      'name': 'run',
-      'args': { 'async': async },
-      'queued': true,
-      'onCycle': evaluate,
-      'onComplete': function() { bench.emit('complete'); }
-    });
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Cycles a benchmark until a run `count` can be established.
-   *
-   * @private
-   * @param {Object} clone The cloned benchmark instance.
-   * @param {Object} options The options object.
-   */
-  function cycle(clone, options) {
-    options || (options = {});
-
-    var deferred;
-    if (clone instanceof Deferred) {
-      deferred = clone;
-      clone = clone.benchmark;
-    }
-
-    var clocked,
-        cycles,
-        divisor,
-        event,
-        minTime,
-        period,
-        async = options.async,
-        bench = clone._original,
-        count = clone.count,
-        times = clone.times;
-
-    // continue, if not aborted between cycles
-    if (clone.running) {
-      // `minTime` is set to `Benchmark.options.minTime` in `clock()`
-      cycles = ++clone.cycles;
-      clocked = deferred ? deferred.elapsed : clock(clone);
-      minTime = clone.minTime;
-
-      if (cycles > bench.cycles) {
-        bench.cycles = cycles;
-      }
-      if (clone.error) {
-        event = Event('error');
-        event.message = clone.error;
-        clone.emit(event);
-        if (!event.cancelled) {
-          clone.abort();
-        }
-      }
-    }
-
-    // continue, if not errored
-    if (clone.running) {
-      // time taken to complete last test cycle
-      bench.times.cycle = times.cycle = clocked;
-      // seconds per operation
-      period = bench.times.period = times.period = clocked / count;
-      // ops per second
-      bench.hz = clone.hz = 1 / period;
-      // avoid working our way up to this next time
-      bench.initCount = clone.initCount = count;
-      // do we need to do another cycle?
-      clone.running = clocked < minTime;
-
-      if (clone.running) {
-        // tests may clock at `0` when `initCount` is a small number,
-        // to avoid that we set its count to something a bit higher
-        if (!clocked && (divisor = divisors[clone.cycles]) != null) {
-          count = floor(4e6 / divisor);
-        }
-        // calculate how many more iterations it will take to achive the `minTime`
-        if (count <= clone.count) {
-          count += Math.ceil((minTime - clocked) / period);
-        }
-        clone.running = count != Infinity;
-      }
-    }
-    // should we exit early?
-    event = Event('cycle');
-    clone.emit(event);
-    if (event.aborted) {
-      clone.abort();
-    }
-    // figure out what to do next
-    if (clone.running) {
-      // start a new cycle
-      clone.count = count;
-      if (deferred) {
-        clone.compiled.call(deferred, timer);
-      } else if (async) {
-        delay(clone, function() { cycle(clone, options); });
-      } else {
-        cycle(clone);
-      }
-    }
-    else {
-      // fix TraceMonkey bug associated with clock fallbacks
-      // http://bugzil.la/509069
-      if (support.browser) {
-        runScript(uid + '=1;delete ' + uid);
-      }
-      // done
-      clone.emit('complete');
-    }
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * Runs the benchmark.
-   *
-   * @memberOf Benchmark
-   * @param {Object} [options={}] Options object.
-   * @returns {Object} The benchmark instance.
-   * @example
-   *
-   * // basic usage
-   * bench.run();
-   *
-   * // or with options
-   * bench.run({ 'async': true });
-   */
-  function run(options) {
-    var me = this,
-        event = Event('start');
-
-    // set `running` to `false` so `reset()` won't call `abort()`
-    me.running = false;
-    me.reset();
-    me.running = true;
-
-    me.count = me.initCount;
-    me.times.timeStamp = +new Date;
-    me.emit(event);
-
-    if (!event.cancelled) {
-      options = { 'async': ((options = options && options.async) == null ? me.async : options) && support.timeout };
-
-      // for clones created within `compute()`
-      if (me._original) {
-        if (me.defer) {
-          Deferred(me);
-        } else {
-          cycle(me, options);
-        }
-      }
-      // for original benchmarks
-      else {
-        compute(me, options);
-      }
-    }
-    return me;
-  }
-
-  /*--------------------------------------------------------------------------*/
-
-  // Firefox 1 erroneously defines variable and argument names of functions on
-  // the function itself as non-configurable properties with `undefined` values.
-  // The bugginess continues as the `Benchmark` constructor has an argument
-  // named `options` and Firefox 1 will not assign a value to `Benchmark.options`,
-  // making it non-writable in the process, unless it is the first property
-  // assigned by for-in loop of `extend()`.
-  extend(Benchmark, {
-
-    /**
-     * The default options copied by benchmark instances.
-     *
-     * @static
-     * @memberOf Benchmark
-     * @type Object
-     */
-    'options': {
-
-      /**
-       * A flag to indicate that benchmark cycles will execute asynchronously
-       * by default.
-       *
-       * @memberOf Benchmark.options
-       * @type Boolean
-       */
-      'async': false,
-
-      /**
-       * A flag to indicate that the benchmark clock is deferred.
-       *
-       * @memberOf Benchmark.options
-       * @type Boolean
-       */
-      'defer': false,
-
-      /**
-       * The delay between test cycles (secs).
-       * @memberOf Benchmark.options
-       * @type Number
-       */
-      'delay': 0.005,
-
-      /**
-       * Displayed by Benchmark#toString when a `name` is not available
-       * (auto-generated if absent).
-       *
-       * @memberOf Benchmark.options
-       * @type String
-       */
-      'id': undefined,
-
-      /**
-       * The default number of times to execute a test on a benchmark's first cycle.
-       *
-       * @memberOf Benchmark.options
-       * @type Number
-       */
-      'initCount': 1,
-
-      /**
-       * The maximum time a benchmark is allowed to run before finishing (secs).
-       * Note: Cycle delays aren't counted toward the maximum time.
-       *
-       * @memberOf Benchmark.options
-       * @type Number
-       */
-      'maxTime': 5,
-
-      /**
-       * The minimum sample size required to perform statistical analysis.
-       *
-       * @memberOf Benchmark.options
-       * @type Number
-       */
-      'minSamples': 5,
-
-      /**
-       * The time needed to reduce the percent uncertainty of measurement to 1% (secs).
-       *
-       * @memberOf Benchmark.options
-       * @type Number
-       */
-      'minTime': 0,
-
-      /**
-       * The name of the benchmark.
-       *
-       * @memberOf Benchmark.options
-       * @type String
-       */
-      'name': undefined,
-
-      /**
-       * An event listener called when the benchmark is aborted.
-       *
-       * @memberOf Benchmark.options
-       * @type Function
-       */
-      'onAbort': undefined,
-
-      /**
-       * An event listener called when the benchmark completes running.
-       *
-       * @memberOf Benchmark.options
-       * @type Function
-       */
-      'onComplete': undefined,
-
-      /**
-       * An event listener called after each run cycle.
-       *
-       * @memberOf Benchmark.options
-       * @type Function
-       */
-      'onCycle': undefined,
-
-      /**
-       * An event listener called when a test errors.
-       *
-       * @memberOf Benchmark.options
-       * @type Function
-       */
-      'onError': undefined,
-
-      /**
-       * An event listener called when the benchmark is reset.
-       *
-       * @memberOf Benchmark.options
-       * @type Function
-       */
-      'onReset': undefined,
-
-      /**
-       * An event listener called when the benchmark starts running.
-       *
-       * @memberOf Benchmark.options
-       * @type Function
-       */
-      'onStart': undefined
-    },
-
-    /**
-     * Platform object with properties describing things like browser name,
-     * version, and operating system.
-     *
-     * @static
-     * @memberOf Benchmark
-     * @type Object
-     */
-    'platform': req('platform') || window.platform || {
-
-      /**
-       * The platform description.
-       *
-       * @memberOf Benchmark.platform
-       * @type String
-       */
-      'description': window.navigator && navigator.userAgent || null,
-
-      /**
-       * The name of the browser layout engine.
-       *
-       * @memberOf Benchmark.platform
-       * @type String|Null
-       */
-      'layout': null,
-
-      /**
-       * The name of the product hosting the browser.
-       *
-       * @memberOf Benchmark.platform
-       * @type String|Null
-       */
-      'product': null,
-
-      /**
-       * The name of the browser/environment.
-       *
-       * @memberOf Benchmark.platform
-       * @type String|Null
-       */
-      'name': null,
-
-      /**
-       * The name of the product's manufacturer.
-       *
-       * @memberOf Benchmark.platform
-       * @type String|Null
-       */
-      'manufacturer': null,
-
-      /**
-       * The name of the operating system.
-       *
-       * @memberOf Benchmark.platform
-       * @type String|Null
-       */
-      'os': null,
-
-      /**
-       * The alpha/beta release indicator.
-       *
-       * @memberOf Benchmark.platform
-       * @type String|Null
-       */
-      'prerelease': null,
-
-      /**
-       * The browser/environment version.
-       *
-       * @memberOf Benchmark.platform
-       * @type String|Null
-       */
-      'version': null,
-
-      /**
-       * Return platform description when the platform object is coerced to a string.
-       *
-       * @memberOf Benchmark.platform
-       * @type Function
-       * @returns {String} The platform description.
-       */
-      'toString': function() {
-        return this.description || '';
-      }
-    },
-
-    /**
-     * The semantic version number.
-     *
-     * @static
-     * @memberOf Benchmark
-     * @type String
-     */
-    'version': '1.0.0',
-
-    // an object of environment/feature detection flags
-    'support': support,
-
-    // clone objects
-    'deepClone': deepClone,
-
-    // iteration utility
-    'each': each,
-
-    // augment objects
-    'extend': extend,
-
-    // generic Array#filter
-    'filter': filter,
-
-    // generic Array#forEach
-    'forEach': forEach,
-
-    // generic own property iteration utility
-    'forOwn': forOwn,
-
-    // converts a number to a comma-separated string
-    'formatNumber': formatNumber,
-
-    // generic Object#hasOwnProperty
-    // (trigger hasKey's lazy define before assigning it to Benchmark)
-    'hasKey': (hasKey(Benchmark, ''), hasKey),
-
-    // generic Array#indexOf
-    'indexOf': indexOf,
-
-    // template utility
-    'interpolate': interpolate,
-
-    // invokes a method on each item in an array
-    'invoke': invoke,
-
-    // generic Array#join for arrays and objects
-    'join': join,
-
-    // generic Array#map
-    'map': map,
-
-    // retrieves a property value from each item in an array
-    'pluck': pluck,
-
-    // generic Array#reduce
-    'reduce': reduce
-  });
-
-  /*--------------------------------------------------------------------------*/
-
-  extend(Benchmark.prototype, {
-
-    /**
-     * The number of times a test was executed.
-     *
-     * @memberOf Benchmark
-     * @type Number
-     */
-    'count': 0,
-
-    /**
-     * The number of cycles performed while benchmarking.
-     *
-     * @memberOf Benchmark
-     * @type Number
-     */
-    'cycles': 0,
-
-    /**
-     * The number of executions per second.
-     *
-     * @memberOf Benchmark
-     * @type Number
-     */
-    'hz': 0,
-
-    /**
-     * The compiled test function.
-     *
-     * @memberOf Benchmark
-     * @type Function|String
-     */
-    'compiled': undefined,
-
-    /**
-     * The error object if the test failed.
-     *
-     * @memberOf Benchmark
-     * @type Object
-     */
-    'error': undefined,
-
-    /**
-     * The test to benchmark.
-     *
-     * @memberOf Benchmark
-     * @type Function|String
-     */
-    'fn': undefined,
-
-    /**
-     * A flag to indicate if the benchmark is aborted.
-     *
-     * @memberOf Benchmark
-     * @type Boolean
-     */
-    'aborted': false,
-
-    /**
-     * A flag to indicate if the benchmark is running.
-     *
-     * @memberOf Benchmark
-     * @type Boolean
-     */
-    'running': false,
-
-    /**
-     * Compiled into the test and executed immediately **before** the test loop.
-     *
-     * @memberOf Benchmark
-     * @type Function|String
-     * @example
-     *
-     * // basic usage
-     * var bench = Benchmark({
-     *   'setup': function() {
-     *     var c = this.count,
-     *         element = document.getElementById('container');
-     *     while (c--) {
-     *       element.appendChild(document.createElement('div'));
-     *     }
-     *   },
-     *   'fn': function() {
-     *     element.removeChild(element.lastChild);
-     *   }
-     * });
-     *
-     * // compiles to something like:
-     * var c = this.count,
-     *     element = document.getElementById('container');
-     * while (c--) {
-     *   element.appendChild(document.createElement('div'));
-     * }
-     * var start = new Date;
-     * while (count--) {
-     *   element.removeChild(element.lastChild);
-     * }
-     * var end = new Date - start;
-     *
-     * // or using strings
-     * var bench = Benchmark({
-     *   'setup': '\
-     *     var a = 0;\n\
-     *     (function() {\n\
-     *       (function() {\n\
-     *         (function() {',
-     *   'fn': 'a += 1;',
-     *   'teardown': '\
-     *          }())\n\
-     *        }())\n\
-     *      }())'
-     * });
-     *
-     * // compiles to something like:
-     * var a = 0;
-     * (function() {
-     *   (function() {
-     *     (function() {
-     *       var start = new Date;
-     *       while (count--) {
-     *         a += 1;
-     *       }
-     *       var end = new Date - start;
-     *     }())
-     *   }())
-     * }())
-     */
-    'setup': noop,
-
-    /**
-     * Compiled into the test and executed immediately **after** the test loop.
-     *
-     * @memberOf Benchmark
-     * @type Function|String
-     */
-    'teardown': noop,
-
-    /**
-     * An object of stats including mean, margin or error, and standard deviation.
-     *
-     * @memberOf Benchmark
-     * @type Object
-     */
-    'stats': {
-
-      /**
-       * The margin of error.
-       *
-       * @memberOf Benchmark#stats
-       * @type Number
-       */
-      'moe': 0,
-
-      /**
-       * The relative margin of error (expressed as a percentage of the mean).
-       *
-       * @memberOf Benchmark#stats
-       * @type Number
-       */
-      'rme': 0,
-
-      /**
-       * The standard error of the mean.
-       *
-       * @memberOf Benchmark#stats
-       * @type Number
-       */
-      'sem': 0,
-
-      /**
-       * The sample standard deviation.
-       *
-       * @memberOf Benchmark#stats
-       * @type Number
-       */
-      'deviation': 0,
-
-      /**
-       * The sample arithmetic mean.
-       *
-       * @memberOf Benchmark#stats
-       * @type Number
-       */
-      'mean': 0,
-
-      /**
-       * The array of sampled periods.
-       *
-       * @memberOf Benchmark#stats
-       * @type Array
-       */
-      'sample': [],
-
-      /**
-       * The sample variance.
-       *
-       * @memberOf Benchmark#stats
-       * @type Number
-       */
-      'variance': 0
-    },
-
-    /**
-     * An object of timing data including cycle, elapsed, period, start, and stop.
-     *
-     * @memberOf Benchmark
-     * @type Object
-     */
-    'times': {
-
-      /**
-       * The time taken to complete the last cycle (secs).
-       *
-       * @memberOf Benchmark#times
-       * @type Number
-       */
-      'cycle': 0,
-
-      /**
-       * The time taken to complete the benchmark (secs).
-       *
-       * @memberOf Benchmark#times
-       * @type Number
-       */
-      'elapsed': 0,
-
-      /**
-       * The time taken to execute the test once (secs).
-       *
-       * @memberOf Benchmark#times
-       * @type Number
-       */
-      'period': 0,
-
-      /**
-       * A timestamp of when the benchmark started (ms).
-       *
-       * @memberOf Benchmark#times
-       * @type Number
-       */
-      'timeStamp': 0
-    },
-
-    // aborts benchmark (does not record times)
-    'abort': abort,
-
-    // creates a new benchmark using the same test and options
-    'clone': clone,
-
-    // compares benchmark's hertz with another
-    'compare': compare,
-
-    // executes listeners
-    'emit': emit,
-
-    // get listeners
-    'listeners': listeners,
-
-    // unregister listeners
-    'off': off,
-
-    // register listeners
-    'on': on,
-
-    // reset benchmark properties
-    'reset': reset,
-
-    // runs the benchmark
-    'run': run,
-
-    // pretty print benchmark info
-    'toString': toStringBench
-  });
-
-  /*--------------------------------------------------------------------------*/
-
-  extend(Deferred.prototype, {
-
-    /**
-     * The deferred benchmark instance.
-     *
-     * @memberOf Benchmark.Deferred
-     * @type Object
-     */
-    'benchmark': null,
-
-    /**
-     * The number of deferred cycles performed while benchmarking.
-     *
-     * @memberOf Benchmark.Deferred
-     * @type Number
-     */
-    'cycles': 0,
-
-    /**
-     * The time taken to complete the deferred benchmark (secs).
-     *
-     * @memberOf Benchmark.Deferred
-     * @type Number
-     */
-    'elapsed': 0,
-
-    /**
-     * A timestamp of when the deferred benchmark started (ms).
-     *
-     * @memberOf Benchmark.Deferred
-     * @type Number
-     */
-    'timeStamp': 0,
-
-    // cycles/completes the deferred benchmark
-    'resolve': resolve
-  });
-
-  /*--------------------------------------------------------------------------*/
-
-  extend(Event.prototype, {
-
-    /**
-     * A flag to indicate if the emitters listener iteration is aborted.
-     *
-     * @memberOf Benchmark.Event
-     * @type Boolean
-     */
-    'aborted': false,
-
-    /**
-     * A flag to indicate if the default action is cancelled.
-     *
-     * @memberOf Benchmark.Event
-     * @type Boolean
-     */
-    'cancelled': false,
-
-    /**
-     * The object whose listeners are currently being processed.
-     *
-     * @memberOf Benchmark.Event
-     * @type Object
-     */
-    'currentTarget': undefined,
-
-    /**
-     * The return value of the last executed listener.
-     *
-     * @memberOf Benchmark.Event
-     * @type Mixed
-     */
-    'result': undefined,
-
-    /**
-     * The object to which the event was originally emitted.
-     *
-     * @memberOf Benchmark.Event
-     * @type Object
-     */
-    'target': undefined,
-
-    /**
-     * A timestamp of when the event was created (ms).
-     *
-     * @memberOf Benchmark.Event
-     * @type Number
-     */
-    'timeStamp': 0,
-
-    /**
-     * The event type.
-     *
-     * @memberOf Benchmark.Event
-     * @type String
-     */
-    'type': ''
-  });
-
-  /*--------------------------------------------------------------------------*/
-
-  /**
-   * The default options copied by suite instances.
-   *
-   * @static
-   * @memberOf Benchmark.Suite
-   * @type Object
-   */
-  Suite.options = {
-
-    /**
-     * The name of the suite.
-     *
-     * @memberOf Benchmark.Suite.options
-     * @type String
-     */
-    'name': undefined
-  };
-
-  /*--------------------------------------------------------------------------*/
-
-  extend(Suite.prototype, {
-
-    /**
-     * The number of benchmarks in the suite.
-     *
-     * @memberOf Benchmark.Suite
-     * @type Number
-     */
-    'length': 0,
-
-    /**
-     * A flag to indicate if the suite is aborted.
-     *
-     * @memberOf Benchmark.Suite
-     * @type Boolean
-     */
-    'aborted': false,
-
-    /**
-     * A flag to indicate if the suite is running.
-     *
-     * @memberOf Benchmark.Suite
-     * @type Boolean
-     */
-    'running': false,
-
-    /**
-     * An `Array#forEach` like method.
-     * Callbacks may terminate the loop by explicitly returning `false`.
-     *
-     * @memberOf Benchmark.Suite
-     * @param {Function} callback The function called per iteration.
-     * @returns {Object} The suite iterated over.
-     */
-    'forEach': methodize(forEach),
-
-    /**
-     * An `Array#indexOf` like method.
-     *
-     * @memberOf Benchmark.Suite
-     * @param {Mixed} value The value to search for.
-     * @returns {Number} The index of the matched value or `-1`.
-     */
-    'indexOf': methodize(indexOf),
-
-    /**
-     * Invokes a method on all benchmarks in the suite.
-     *
-     * @memberOf Benchmark.Suite
-     * @param {String|Object} name The name of the method to invoke OR options object.
-     * @param {Mixed} [arg1, arg2, ...] Arguments to invoke the method with.
-     * @returns {Array} A new array of values returned from each method invoked.
-     */
-    'invoke': methodize(invoke),
-
-    /**
-     * Converts the suite of benchmarks to a string.
-     *
-     * @memberOf Benchmark.Suite
-     * @param {String} [separator=','] A string to separate each element of the array.
-     * @returns {String} The string.
-     */
-    'join': [].join,
-
-    /**
-     * An `Array#map` like method.
-     *
-     * @memberOf Benchmark.Suite
-     * @param {Function} callback The function called per iteration.
-     * @returns {Array} A new array of values returned by the callback.
-     */
-    'map': methodize(map),
-
-    /**
-     * Retrieves the value of a specified property from all benchmarks in the suite.
-     *
-     * @memberOf Benchmark.Suite
-     * @param {String} property The property to pluck.
-     * @returns {Array} A new array of property values.
-     */
-    'pluck': methodize(pluck),
-
-    /**
-     * Removes the last benchmark from the suite and returns it.
-     *
-     * @memberOf Benchmark.Suite
-     * @returns {Mixed} The removed benchmark.
-     */
-    'pop': [].pop,
-
-    /**
-     * Appends benchmarks to the suite.
-     *
-     * @memberOf Benchmark.Suite
-     * @returns {Number} The suite's new length.
-     */
-    'push': [].push,
-
-    /**
-     * Sorts the benchmarks of the suite.
-     *
-     * @memberOf Benchmark.Suite
-     * @param {Function} [compareFn=null] A function that defines the sort order.
-     * @returns {Object} The sorted suite.
-     */
-    'sort': [].sort,
-
-    /**
-     * An `Array#reduce` like method.
-     *
-     * @memberOf Benchmark.Suite
-     * @param {Function} callback The function called per iteration.
-     * @param {Mixed} accumulator Initial value of the accumulator.
-     * @returns {Mixed} The accumulator.
-     */
-    'reduce': methodize(reduce),
-
-    // aborts all benchmarks in the suite
-    'abort': abortSuite,
-
-    // adds a benchmark to the suite
-    'add': add,
-
-    // creates a new suite with cloned benchmarks
-    'clone': cloneSuite,
-
-    // executes listeners of a specified type
-    'emit': emit,
-
-    // creates a new suite of filtered benchmarks
-    'filter': filterSuite,
-
-    // get listeners
-    'listeners': listeners,
-
-    // unregister listeners
-    'off': off,
-
-   // register listeners
-    'on': on,
-
-    // resets all benchmarks in the suite
-    'reset': resetSuite,
-
-    // runs all benchmarks in the suite
-    'run': runSuite,
-
-    // array methods
-    'concat': concat,
-
-    'reverse': reverse,
-
-    'shift': shift,
-
-    'slice': slice,
-
-    'splice': splice,
-
-    'unshift': unshift
-  });
-
-  /*--------------------------------------------------------------------------*/
-
-  // expose Deferred, Event and Suite
-  extend(Benchmark, {
-    'Deferred': Deferred,
-    'Event': Event,
-    'Suite': Suite
-  });
-
-  // expose Benchmark
-  // some AMD build optimizers, like r.js, check for specific condition patterns like the following:
-  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
-    // define as an anonymous module so, through path mapping, it can be aliased
-    define(function() {
-      return Benchmark;
-    });
-  }
-  // check for `exports` after `define` in case a build optimizer adds an `exports` object
-  else if (freeExports) {
-    // in Node.js or RingoJS v0.8.0+
-    if (typeof module == 'object' && module && module.exports == freeExports) {
-      (module.exports = Benchmark).Benchmark = Benchmark;
-    }
-    // in Narwhal or RingoJS v0.7.0-
-    else {
-      freeExports.Benchmark = Benchmark;
-    }
-  }
-  // in a browser or Rhino
-  else {
-    // use square bracket notation so Closure Compiler won't munge `Benchmark`
-    // http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
-    window['Benchmark'] = Benchmark;
-  }
-
-  // trigger clock's lazy define early to avoid a security error
-  if (support.air) {
-    clock({ '_original': { 'fn': noop, 'count': 1, 'options': {} } });
-  }
-}(this));
deleted file mode 100644
index cadaa100a068c9f48552aa9b5cedbf7dd6ba7d39..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/js/src/jsapi-tests/binast/parser/tester/frameworks/jquery-1.9.js
+++ /dev/null
@@ -1,9597 +0,0 @@
-/*!
- * jQuery JavaScript Library v1.9.1
- * http://jquery.com/
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- *
- * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors
- * Released under the MIT license
- * http://jquery.org/license
- *
- * Date: 2013-2-4
- */
-(function( window, undefined ) {
-
-// Can't do this because several apps including ASP.NET trace
-// the stack via arguments.caller.callee and Firefox dies if
-// you try to trace through "use strict" call chains. (#13335)
-// Support: Firefox 18+
-//"use strict";
-var
-	// The deferred used on DOM ready
-	readyList,
-
-	// A central reference to the root jQuery(document)
-	rootjQuery,
-
-	// Support: IE<9
-	// For `typeof node.method` instead of `node.method !== undefined`
-	core_strundefined = typeof undefined,
-
-	// Use the correct document accordingly with window argument (sandbox)
-	document = window.document,
-	location = window.location,
-
-	// Map over jQuery in case of overwrite
-	_jQuery = window.jQuery,
-
-	// Map over the $ in case of overwrite
-	_$ = window.$,
-
-	// [[Class]] -> type pairs
-	class2type = {},
-
-	// List of deleted data cache ids, so we can reuse them
-	core_deletedIds = [],
-
-	core_version = "1.9.1",
-
-	// Save a reference to some core methods
-	core_concat = core_deletedIds.concat,
-	core_push = core_deletedIds.push,
-	core_slice = core_deletedIds.slice,
-	core_indexOf = core_deletedIds.indexOf,
-	core_toString = class2type.toString,
-	core_hasOwn = class2type.hasOwnProperty,
-	core_trim = core_version.trim,
-
-	// Define a local copy of jQuery
-	jQuery = function( selector, context ) {
-		// The jQuery object is actually just the init constructor 'enhanced'
-		return new jQuery.fn.init( selector, context, rootjQuery );
-	},
-
-	// Used for matching numbers
-	core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
-
-	// Used for splitting on whitespace
-	core_rnotwhite = /\S+/g,
-
-	// Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)
-	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
-
-	// A simple way to check for HTML strings
-	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
-	// Strict HTML recognition (#11290: must start with <)
-	rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/,
-
-	// Match a standalone tag
-	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
-
-	// JSON RegExp
-	rvalidchars = /^[\],:{}\s]*$/,
-	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
-	rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
-	rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,
-
-	// Matches dashed string for camelizing
-	rmsPrefix = /^-ms-/,
-	rdashAlpha = /-([\da-z])/gi,
-
-	// Used by jQuery.camelCase as callback to replace()
-	fcamelCase = function( all, letter ) {
-		return letter.toUpperCase();
-	},
-
-	// The ready event handler
-	completed = function( event ) {
-
-		// readyState === "complete" is good enough for us to call the dom ready in oldIE
-		if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
-			detach();
-			jQuery.ready();
-		}
-	},
-	// Clean-up method for dom ready events
-	detach = function() {
-		if ( document.addEventListener ) {
-			document.removeEventListener( "DOMContentLoaded", completed, false );
-			window.removeEventListener( "load", completed, false );
-
-		} else {
-			document.detachEvent( "onreadystatechange", completed );
-			window.detachEvent( "onload", completed );
-		}
-	};
-
-jQuery.fn = jQuery.prototype = {
-	// The current version of jQuery being used
-	jquery: core_version,
-
-	constructor: jQuery,
-	init: function( selector, context, rootjQuery ) {
-		var match, elem;
-
-		// HANDLE: $(""), $(null), $(undefined), $(false)
-		if ( !selector ) {
-			return this;
-		}
-
-		// Handle HTML strings
-		if ( typeof selector === "string" ) {
-			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
-				// Assume that strings that start and end with <> are HTML and skip the regex check
-				match = [ null, selector, null ];
-
-			} else {
-				match = rquickExpr.exec( selector );
-			}
-
-			// Match html or make sure no context is specified for #id
-			if ( match && (match[1] || !context) ) {
-
-				// HANDLE: $(html) -> $(array)
-				if ( match[1] ) {
-					context = context instanceof jQuery ? context[0] : context;
-
-					// scripts is true for back-compat
-					jQuery.merge( this, jQuery.parseHTML(
-						match[1],
-						context && context.nodeType ? context.ownerDocument || context : document,
-						true
-					) );
-
-					// HANDLE: $(html, props)
-					if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
-						for ( match in context ) {
-							// Properties of context are called as methods if possible
-							if ( jQuery.isFunction( this[ match ] ) ) {
-								this[ match ]( context[ match ] );
-
-							// ...and otherwise set as attributes
-							} else {
-								this.attr( match, context[ match ] );
-							}
-						}
-					}
-
-					return this;
-
-				// HANDLE: $(#id)
-				} else {
-					elem = document.getElementById( match[2] );
-
-					// Check parentNode to catch when Blackberry 4.6 returns
-					// nodes that are no longer in the document #6963
-					if ( elem && elem.parentNode ) {
-						// Handle the case where IE and Opera return items
-						// by name instead of ID
-						if ( elem.id !== match[2] ) {
-							return rootjQuery.find( selector );
-						}
-
-						// Otherwise, we inject the element directly into the jQuery object
-						this.length = 1;
-						this[0] = elem;
-					}
-
-					this.context = document;
-					this.selector = selector;
-					return this;
-				}
-
-			// HANDLE: $(expr, $(...))
-			} else if ( !context || context.jquery ) {
-				return ( context || rootjQuery ).find( selector );
-
-			// HANDLE: $(expr, context)
-			// (which is just equivalent to: $(context).find(expr)
-			} else {
-				return this.constructor( context ).find( selector );
-			}
-
-		// HANDLE: $(DOMElement)
-		} else if ( selector.nodeType ) {
-			this.context = this[0] = selector;
-			this.length = 1;
-			return this;
-
-		// HANDLE: $(function)
-		// Shortcut for document ready
-		} else if ( jQuery.isFunction( selector ) ) {
-			return rootjQuery.ready( selector );
-		}
-
-		if ( selector.selector !== undefined ) {
-			this.selector = selector.selector;
-			this.context = selector.context;
-		}
-
-		return jQuery.makeArray( selector, this );
-	},
-
-	// Start with an empty selector
-	selector: "",
-
-	// The default length of a jQuery object is 0
-	length: 0,
-
-	// The number of elements contained in the matched element set
-	size: function() {
-		return this.length;
-	},
-
-	toArray: function() {
-		return core_slice.call( this );
-	},
-
-	// Get the Nth element in the matched element set OR
-	// Get the whole matched element set as a clean array
-	get: function( num ) {
-		return num == null ?
-
-			// Return a 'clean' array
-			this.toArray() :
-
-			// Return just the object
-			( num < 0 ? this[ this.length + num ] : this[ num ] );
-	},
-
-	// Take an array of elements and push it onto the stack
-	// (returning the new matched element set)
-	pushStack: function( elems ) {
-
-		// Build a new jQuery matched element set
-		var ret = jQuery.merge( this.constructor(), elems );
-
-		// Add the old object onto the stack (as a reference)
-		ret.prevObject = this;
-		ret.context = this.context;
-
-		// Return the newly-formed element set
-		return ret;
-	},
-
-	// Execute a callback for every element in the matched set.
-	// (You can seed the arguments with an array of args, but this is
-	// only used internally.)
-	each: function( callback, args ) {
-		return jQuery.each( this, callback, args );
-	},
-
-	ready: function( fn ) {
-		// Add the callback
-		jQuery.ready.promise().done( fn );
-
-		return this;
-	},
-
-	slice: function() {
-		return this.pushStack( core_slice.apply( this, arguments ) );
-	},
-
-	first: function() {
-		return this.eq( 0 );
-	},
-
-	last: function() {
-		return this.eq( -1 );
-	},
-
-	eq: function( i ) {
-		var len = this.length,
-			j = +i + ( i < 0 ? len : 0 );
-		return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
-	},
-
-	map: function( callback ) {
-		return this.pushStack( jQuery.map(this, function( elem, i ) {
-			return callback.call( elem, i, elem );
-		}));
-	},
-
-	end: function() {
-		return this.prevObject || this.constructor(null);
-	},
-
-	// For internal use only.
-	// Behaves like an Array's method, not like a jQuery method.
-	push: core_push,
-	sort: [].sort,
-	splice: [].splice
-};
-
-// Give the init function the jQuery prototype for later instantiation
-jQuery.fn.init.prototype = jQuery.fn;
-
-jQuery.extend = jQuery.fn.extend = function() {
-	var src, copyIsArray, copy, name, options, clone,
-		target = arguments[0] || {},
-		i = 1,
-		length = arguments.length,
-		deep = false;
-
-	// Handle a deep copy situation
-	if ( typeof target === "boolean" ) {
-		deep = target;
-		target = arguments[1] || {};
-		// skip the boolean and the target
-		i = 2;
-	}
-
-	// Handle case when target is a string or something (possible in deep copy)
-	if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
-		target = {};
-	}
-
-	// extend jQuery itself if only one argument is passed
-	if ( length === i ) {
-		target = this;
-		--i;
-	}
-
-	for ( ; i < length; i++ ) {
-		// Only deal with non-null/undefined values
-		if ( (options = arguments[ i ]) != null ) {
-			// Extend the base object
-			for ( name in options ) {
-				src = target[ name ];
-				copy = options[ name ];
-
-				// Prevent never-ending loop
-				if ( target === copy ) {
-					continue;
-				}
-
-				// Recurse if we're merging plain objects or arrays
-				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
-					if ( copyIsArray ) {
-						copyIsArray = false;
-						clone = src && jQuery.isArray(src) ? src : [];
-
-					} else {
-						clone = src && jQuery.isPlainObject(src) ? src : {};
-					}
-
-					// Never move original objects, clone them
-					target[ name ] = jQuery.extend( deep, clone, copy );
-
-				// Don't bring in undefined values
-				} else if ( copy !== undefined ) {
-					target[ name ] = copy;
-				}
-			}
-		}
-	}
-
-	// Return the modified object
-	return target;
-};
-
-jQuery.extend({
-	noConflict: function( deep ) {
-		if ( window.$ === jQuery ) {
-			window.$ = _$;
-		}
-
-		if ( deep && window.jQuery === jQuery ) {
-			window.jQuery = _jQuery;
-		}
-
-		return jQuery;
-	},
-
-	// Is the DOM ready to be used? Set to true once it occurs.
-	isReady: false,
-
-	// A counter to track how many items to wait for before
-	// the ready event fires. See #6781
-	readyWait: 1,
-
-	// Hold (or release) the ready event
-	holdReady: function( hold ) {
-		if ( hold ) {
-			jQuery.readyWait++;
-		} else {
-			jQuery.ready( true );
-		}
-	},
-
-	// Handle when the DOM is ready
-	ready: function( wait ) {
-
-		// Abort if there are pending holds or we're already ready
-		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
-			return;
-		}
-
-		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
-		if ( !document.body ) {
-			return setTimeout( jQuery.ready );
-		}
-
-		// Remember that the DOM is ready
-		jQuery.isReady = true;
-
-		// If a normal DOM Ready event fired, decrement, and wait if need be
-		if ( wait !== true && --jQuery.readyWait > 0 ) {
-			return;
-		}
-
-		// If there are functions bound, to execute
-		readyList.resolveWith( document, [ jQuery ] );
-
-		// Trigger any bound ready events
-		if ( jQuery.fn.trigger ) {
-			jQuery( document ).trigger("ready").off("ready");
-		}
-	},
-
-	// See test/unit/core.js for details concerning isFunction.
-	// Since version 1.3, DOM methods and functions like alert
-	// aren't supported. They return false on IE (#2968).
-	isFunction: function( obj ) {
-		return jQuery.type(obj) === "function";
-	},
-
-	isArray: Array.isArray || function( obj ) {
-		return jQuery.type(obj) === "array";
-	},
-
-	isWindow: function( obj ) {
-		return obj != null && obj == obj.window;
-	},
-
-	isNumeric: function( obj ) {
-		return !isNaN( parseFloat(obj) ) && isFinite( obj );
-	},
-
-	type: function( obj ) {
-		if ( obj == null ) {
-			return String( obj );
-		}
-		return typeof obj === "object" || typeof obj === "function" ?
-			class2type[ core_toString.call(obj) ] || "object" :
-			typeof obj;
-	},
-
-	isPlainObject: function( obj ) {
-		// Must be an Object.
-		// Because of IE, we also have to check the presence of the constructor property.
-		// Make sure that DOM nodes and window objects don't pass through, as well
-		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
-			return false;
-		}
-
-		try {
-			// Not own constructor property must be Object
-			if ( obj.constructor &&
-				!core_hasOwn.call(obj, "constructor") &&
-				!core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
-				return false;
-			}
-		} catch ( e ) {
-			// IE8,9 Will throw exceptions on certain host objects #9897
-			return false;
-		}
-
-		// Own properties are enumerated firstly, so to speed up,
-		// if last one is own, then all properties are own.
-
-		var key;
-		for ( key in obj ) {}
-
-		return key === undefined || core_hasOwn.call( obj, key );
-	},
-
-	isEmptyObject: function( obj ) {
-		var name;
-		for ( name in obj ) {
-			return false;
-		}
-		return true;
-	},
-
-	error: function( msg ) {
-		throw new Error( msg );
-	},
-
-	// data: string of html
-	// context (optional): If specified, the fragment will be created in this context, defaults to document
-	// keepScripts (optional): If true, will include scripts passed in the html string
-	parseHTML: function( data, context, keepScripts ) {
-		if ( !data || typeof data !== "string" ) {
-			return null;
-		}
-		if ( typeof context === "boolean" ) {
-			keepScripts = context;
-			context = false;
-		}
-		context = context || document;
-
-		var parsed = rsingleTag.exec( data ),
-			scripts = !keepScripts && [];
-
-		// Single tag
-		if ( parsed ) {
-			return [ context.createElement( parsed[1] ) ];
-		}
-
-		parsed = jQuery.buildFragment( [ data ], context, scripts );
-		if ( scripts ) {
-			jQuery( scripts ).remove();
-		}
-		return jQuery.merge( [], parsed.childNodes );
-	},
-
-	parseJSON: function( data ) {
-		// Attempt to parse using the native JSON parser first
-		if ( window.JSON && window.JSON.parse ) {
-			return window.JSON.parse( data );
-		}
-
-		if ( data === null ) {
-			return data;
-		}
-
-		if ( typeof data === "string" ) {
-
-			// Make sure leading/trailing whitespace is removed (IE can't handle it)
-			data = jQuery.trim( data );
-
-			if ( data ) {
-				// Make sure the incoming data is actual JSON
-				// Logic borrowed from http://json.org/json2.js
-				if ( rvalidchars.test( data.replace( rvalidescape, "@" )
-					.replace( rvalidtokens, "]" )
-					.replace( rvalidbraces, "")) ) {
-
-					return ( new Function( "return " + data ) )();
-				}
-			}
-		}
-
-		jQuery.error( "Invalid JSON: " + data );
-	},
-
-	// Cross-browser xml parsing
-	parseXML: function( data ) {
-		var xml, tmp;
-		if ( !data || typeof data !== "string" ) {
-			return null;
-		}
-		try {
-			if ( window.DOMParser ) { // Standard
-				tmp = new DOMParser();
-				xml = tmp.parseFromString( data , "text/xml" );
-			} else { // IE
-				xml = new ActiveXObject( "Microsoft.XMLDOM" );
-				xml.async = "false";
-				xml.loadXML( data );
-			}
-		} catch( e ) {
-			xml = undefined;
-		}
-		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
-			jQuery.error( "Invalid XML: " + data );
-		}
-		return xml;
-	},
-
-	noop: function() {},
-
-	// Evaluates a script in a global context
-	// Workarounds based on findings by Jim Driscoll
-	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
-	globalEval: function( data ) {
-		if ( data && jQuery.trim( data ) ) {
-			// We use execScript on Internet Explorer
-			// We use an anonymous function so that context is window
-			// rather than jQuery in Firefox
-			( window.execScript || function( data ) {
-				window[ "eval" ].call( window, data );
-			} )( data );
-		}
-	},
-
-	// Convert dashed to camelCase; used by the css and data modules
-	// Microsoft forgot to hump their vendor prefix (#9572)
-	camelCase: function( string ) {
-		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
-	},
-
-	nodeName: function( elem, name ) {
-		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
-	},
-
-	// args is for internal usage only
-	each: function( obj, callback, args ) {
-		var value,
-			i = 0,
-			length = obj.length,
-			isArray = isArraylike( obj );
-
-		if ( args ) {
-			if ( isArray ) {
-				for ( ; i < length; i++ ) {
-					value = callback.apply( obj[ i ], args );
-
-					if ( value === false ) {
-						break;
-					}
-				}
-			} else {
-				for ( i in obj ) {
-					value = callback.apply( obj[ i ], args );
-
-					if ( value === false ) {
-						break;
-					}
-				}
-			}
-
-		// A special, fast, case for the most common use of each
-		} else {
-			if ( isArray ) {
-				for ( ; i < length; i++ ) {
-					value = callback.call( obj[ i ], i, obj[ i ] );
-
-					if ( value === false ) {
-						break;
-					}
-				}
-			} else {
-				for ( i in obj ) {
-					value = callback.call( obj[ i ], i, obj[ i ] );
-
-					if ( value === false ) {
-						break;
-					}
-				}
-			}
-		}
-
-		return obj;
-	},
-
-	// Use native String.trim function wherever possible
-	trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
-		function( text ) {
-			return text == null ?
-				"" :
-				core_trim.call( text );
-		} :
-
-		// Otherwise use our own trimming functionality
-		function( text ) {
-			return text == null ?
-				"" :
-				( text + "" ).replace( rtrim, "" );
-		},
-
-	// results is for internal usage only
-	makeArray: function( arr, results ) {
-		var ret = results || [];
-
-		if ( arr != null ) {
-			if ( isArraylike( Object(arr) ) ) {
-				jQuery.merge( ret,
-					typeof arr === "string" ?
-					[ arr ] : arr
-				);
-			} else {
-				core_push.call( ret, arr );
-			}
-		}
-
-		return ret;
-	},
-
-	inArray: function( elem, arr, i ) {
-		var len;
-
-		if ( arr ) {
-			if ( core_indexOf ) {
-				return core_indexOf.call( arr, elem, i );
-			}
-
-			len = arr.length;
-			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
-
-			for ( ; i < len; i++ ) {
-				// Skip accessing in sparse arrays
-				if ( i in arr && arr[ i ] === elem ) {
-					return i;
-				}
-			}
-		}
-
-		return -1;
-	},
-
-	merge: function( first, second ) {
-		var l = second.length,
-			i = first.length,
-			j = 0;
-
-		if ( typeof l === "number" ) {
-			for ( ; j < l; j++ ) {
-				first[ i++ ] = second[ j ];
-			}
-		} else {
-			while ( second[j] !== undefined ) {
-				first[ i++ ] = second[ j++ ];
-			}
-		}
-
-		first.length = i;
-
-		return first;
-	},
-
-	grep: function( elems, callback, inv ) {
-		var retVal,
-			ret = [],
-			i = 0,
-			length = elems.length;
-		inv = !!inv;
-
-		// Go through the array, only saving the items
-		// that pass the validator function
-		for ( ; i < length; i++ ) {
-			retVal = !!callback( elems[ i ], i );
-			if ( inv !== retVal ) {
-				ret.push( elems[ i ] );
-			}
-		}
-
-		return ret;
-	},
-
-	// arg is for internal usage only
-	map: function( elems, callback, arg ) {
-		var value,
-			i = 0,
-			length = elems.length,
-			isArray = isArraylike( elems ),
-			ret = [];
-
-		// Go through the array, translating each of the items to their
-		if ( isArray ) {
-			for ( ; i < length; i++ ) {
-				value = callback( elems[ i ], i, arg );
-
-				if ( value != null ) {
-					ret[ ret.length ] = value;
-				}
-			}
-
-		// Go through every key on the object,
-		} else {
-			for ( i in elems ) {
-				value = callback( elems[ i ], i, arg );
-
-				if ( value != null ) {
-					ret[ ret.length ] = value;
-				}
-			}
-		}
-
-		// Flatten any nested arrays
-		return core_concat.apply( [], ret );
-	},
-
-	// A global GUID counter for objects
-	guid: 1,
-
-	// Bind a function to a context, optionally partially applying any
-	// arguments.
-	proxy: function( fn, context ) {
-		var args, proxy, tmp;
-
-		if ( typeof context === "string" ) {
-			tmp = fn[ context ];
-			context = fn;
-			fn = tmp;
-		}
-
-		// Quick check to determine if target is callable, in the spec
-		// this throws a TypeError, but we will just return undefined.
-		if ( !jQuery.isFunction( fn ) ) {
-			return undefined;
-		}
-
-		// Simulated bind
-		args = core_slice.call( arguments, 2 );
-		proxy = function() {
-			return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
-		};
-
-		// Set the guid of unique handler to the same of original handler, so it can be removed
-		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
-
-		return proxy;
-	},
-
-	// Multifunctional method to get and set values of a collection
-	// The value/s can optionally be executed if it's a function
-	access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
-		var i = 0,
-			length = elems.length,
-			bulk = key == null;
-
-		// Sets many values
-		if ( jQuery.type( key ) === "object" ) {
-			chainable = true;
-			for ( i in key ) {
-				jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
-			}
-
-		// Sets one value
-		} else if ( value !== undefined ) {
-			chainable = true;
-
-			if ( !jQuery.isFunction( value ) ) {
-				raw = true;
-			}
-
-			if ( bulk ) {
-				// Bulk operations run against the entire set
-				if ( raw ) {
-					fn.call( elems, value );
-					fn = null;
-
-				// ...except when executing function values
-				} else {
-					bulk = fn;
-					fn = function( elem, key, value ) {
-						return bulk.call( jQuery( elem ), value );
-					};
-				}
-			}
-
-			if ( fn ) {
-				for ( ; i < length; i++ ) {
-					fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
-				}
-			}
-		}
-
-		return chainable ?
-			elems :
-
-			// Gets
-			bulk ?
-				fn.call( elems ) :
-				length ? fn( elems[0], key ) : emptyGet;
-	},
-
-	now: function() {
-		return ( new Date() ).getTime();
-	}
-});
-
-jQuery.ready.promise = function( obj ) {
-	if ( !readyList ) {
-
-		readyList = jQuery.Deferred();
-
-		// Catch cases where $(document).ready() is called after the browser event has already occurred.
-		// we once tried to use readyState "interactive" here, but it caused issues like the one
-		// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
-		if ( document.readyState === "complete" ) {
-			// Handle it asynchronously to allow scripts the opportunity to delay ready
-			setTimeout( jQuery.ready );
-
-		// Standards-based browsers support DOMContentLoaded
-		} else if ( document.addEventListener ) {
-			// Use the handy event callback
-			document.addEventListener( "DOMContentLoaded", completed, false );
-
-			// A fallback to window.onload, that will always work
-			window.addEventListener( "load", completed, false );
-
-		// If IE event model is used
-		} else {
-			// Ensure firing before onload, maybe late but safe also for iframes
-			document.attachEvent( "onreadystatechange", completed );
-
-			// A fallback to window.onload, that will always work
-			window.attachEvent( "onload", completed );
-
-			// If IE and not a frame
-			// continually check to see if the document is ready
-			var top = false;
-
-			try {
-				top = window.frameElement == null && document.documentElement;
-			} catch(e) {}
-
-			if ( top && top.doScroll ) {
-				(function doScrollCheck() {
-					if ( !jQuery.isReady ) {
-
-						try {
-							// Use the trick by Diego Perini
-							// http://javascript.nwbox.com/IEContentLoaded/
-							top.doScroll("left");
-						} catch(e) {
-							return setTimeout( doScrollCheck, 50 );
-						}
-
-						// detach all dom ready events
-						detach();
-
-						// and execute any waiting functions
-						jQuery.ready();
-					}
-				})();
-			}
-		}
-	}
-	return readyList.promise( obj );
-};
-
-// Populate the class2type map
-jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
-	class2type[ "[object " + name + "]" ] = name.toLowerCase();
-});
-
-function isArraylike( obj ) {
-	var length = obj.length,
-		type = jQuery.type( obj );
-
-	if ( jQuery.isWindow( obj ) ) {
-		return false;
-	}
-
-	if ( obj.nodeType === 1 && length ) {
-		return true;
-	}
-
-	return type === "array" || type !== "function" &&
-		( length === 0 ||
-		typeof length === "number" && length > 0 && ( length - 1 ) in obj );
-}
-
-// All jQuery objects should point back to these
-rootjQuery = jQuery(document);
-// String to Object options format cache
-var optionsCache = {};
-
-// Convert String-formatted options into Object-formatted ones and store in cache
-function createOptions( options ) {
-	var object = optionsCache[ options ] = {};
-	jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
-		object[ flag ] = true;
-	});
-	return object;
-}
-
-/*
- * Create a callback list using the following parameters:
- *
- *	options: an optional list of space-separated options that will change how
- *			the callback list behaves or a more traditional option object
- *
- * By default a callback list will act like an event callback list and can be
- * "fired" multiple times.
- *
- * Possible options:
- *
- *	once:			will ensure the callback list can only be fired once (like a Deferred)
- *
- *	memory:			will keep track of previous values and will call any callback added
- *					after the list has been fired right away with the latest "memorized"
- *					values (like a Deferred)
- *
- *	unique:			will ensure a callback can only be added once (no duplicate in the list)
- *
- *	stopOnFalse:	interrupt callings when a callback returns false
- *
- */
-jQuery.Callbacks = function( options ) {
-
-	// Convert options from String-formatted to Object-formatted if needed
-	// (we check in cache first)
-	options = typeof options === "string" ?
-		( optionsCache[ options ] || createOptions( options ) ) :
-		jQuery.extend( {}, options );
-
-	var // Flag to know if list is currently firing
-		firing,
-		// Last fire value (for non-forgettable lists)
-		memory,
-		// Flag to know if list was already fired
-		fired,
-		// End of the loop when firing
-		firingLength,
-		// Index of currently firing callback (modified by remove if needed)
-		firingIndex,
-		// First callback to fire (used internally by add and fireWith)
-		firingStart,
-		// Actual callback list
-		list = [],
-		// Stack of fire calls for repeatable lists
-		stack = !options.once && [],
-		// Fire callbacks
-		fire = function( data ) {
-			memory = options.memory && data;
-			fired = true;
-			firingIndex = firingStart || 0;
-			firingStart = 0;
-			firingLength = list.length;
-			firing = true;
-			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
-				if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
-					memory = false; // To prevent further calls using add
-					break;
-				}
-			}
-			firing = false;
-			if ( list ) {
-				if ( stack ) {
-					if ( stack.length ) {
-						fire( stack.shift() );
-					}
-				} else if ( memory ) {
-					list = [];
-				} else {
-					self.disable();
-				}
-			}
-		},
-		// Actual Callbacks object
-		self = {
-			// Add a callback or a collection of callbacks to the list
-			add: function() {
-				if ( list ) {
-					// First, we save the current length
-					var start = list.length;
-					(function add( args ) {
-						jQuery.each( args, function( _, arg ) {
-							var type = jQuery.type( arg );
-							if ( type === "function" ) {
-								if ( !options.unique || !self.has( arg ) ) {
-									list.push( arg );
-								}
-							} else if ( arg && arg.length && type !== "string" ) {
-								// Inspect recursively
-								add( arg );
-							}
-						});
-					})( arguments );
-					// Do we need to add the callbacks to the
-					// current firing batch?
-					if ( firing ) {
-						firingLength = list.length;
-					// With memory, if we're not firing then
-					// we should call right away
-					} else if ( memory ) {
-						firingStart = start;
-						fire( memory );
-					}
-				}
-				return this;
-			},
-			// Remove a callback from the list
-			remove: function() {
-				if ( list ) {
-					jQuery.each( arguments, function( _, arg ) {
-						var index;
-						while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
-							list.splice( index, 1 );
-							// Handle firing indexes
-							if ( firing ) {
-								if ( index <= firingLength ) {
-									firingLength--;
-								}
-								if ( index <= firingIndex ) {
-									firingIndex--;
-								}
-							}
-						}
-					});
-				}
-				return this;
-			},
-			// Check if a given callback is in the list.
-			// If no argument is given, return whether or not list has callbacks attached.
-			has: function( fn ) {
-				return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
-			},
-			// Remove all callbacks from the list
-			empty: function() {
-				list = [];
-				return this;
-			},
-			// Have the list do nothing anymore
-			disable: function() {
-				list = stack = memory = undefined;
-				return this;
-			},
-			// Is it disabled?
-			disabled: function() {
-				return !list;
-			},
-			// Lock the list in its current state
-			lock: function() {
-				stack = undefined;
-				if ( !memory ) {
-					self.disable();
-				}
-				return this;
-			},
-			// Is it locked?
-			locked: function() {
-				return !stack;
-			},
-			// Call all callbacks with the given context and arguments
-			fireWith: function( context, args ) {
-				args = args || [];
-				args = [ context, args.slice ? args.slice() : args ];
-				if ( list && ( !fired || stack ) ) {
-					if ( firing ) {
-						stack.push( args );
-					} else {
-						fire( args );
-					}
-				}
-				return this;
-			},
-			// Call all the callbacks with the given arguments
-			fire: function() {
-				self.fireWith( this, arguments );
-				return this;
-			},
-			// To know if the callbacks have already been called at least once
-			fired: function() {
-				return !!fired;
-			}
-		};
-
-	return self;
-};
-jQuery.extend({
-
-	Deferred: function( func ) {
-		var tuples = [
-				// action, add listener, listener list, final state
-				[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
-				[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
-				[ "notify", "progress", jQuery.Callbacks("memory") ]
-			],
-			state = "pending",
-			promise = {
-				state: function() {
-					return state;
-				},
-				always: function() {
-					deferred.done( arguments ).fail( arguments );
-					return this;
-				},
-				then: function( /* fnDone, fnFail, fnProgress */ ) {
-					var fns = arguments;
-					return jQuery.Deferred(function( newDefer ) {
-						jQuery.each( tuples, function( i, tuple ) {
-							var action = tuple[ 0 ],
-								fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
-							// deferred[ done | fail | progress ] for forwarding actions to newDefer
-							deferred[ tuple[1] ](function() {
-								var returned = fn && fn.apply( this, arguments );
-								if ( returned && jQuery.isFunction( returned.promise ) ) {
-									returned.promise()
-										.done( newDefer.resolve )
-										.fail( newDefer.reject )
-										.progress( newDefer.notify );
-								} else {
-									newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
-								}
-							});
-						});
-						fns = null;
-					}).promise();
-				},
-				// Get a promise for this deferred
-				// If obj is provided, the promise aspect is added to the object
-				promise: function( obj ) {
-					return obj != null ? jQuery.extend( obj, promise ) : promise;
-				}
-			},
-			deferred = {};
-
-		// Keep pipe for back-compat
-		promise.pipe = promise.then;
-
-		// Add list-specific methods
-		jQuery.each( tuples, function( i, tuple ) {
-			var list = tuple[ 2 ],
-				stateString = tuple[ 3 ];
-
-			// promise[ done | fail | progress ] = list.add
-			promise[ tuple[1] ] = list.add;
-
-			// Handle state
-			if ( stateString ) {
-				list.add(function() {
-					// state = [ resolved | rejected ]
-					state = stateString;
-
-				// [ reject_list | resolve_list ].disable; progress_list.lock
-				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
-			}
-
-			// deferred[ resolve | reject | notify ]
-			deferred[ tuple[0] ] = function() {
-				deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
-				return this;
-			};
-			deferred[ tuple[0] + "With" ] = list.fireWith;
-		});
-
-		// Make the deferred a promise
-		promise.promise( deferred );
-
-		// Call given func if any
-		if ( func ) {
-			func.call( deferred, deferred );
-		}
-
-		// All done!
-		return deferred;
-	},
-
-	// Deferred helper
-	when: function( subordinate /* , ..., subordinateN */ ) {
-		var i = 0,
-			resolveValues = core_slice.call( arguments ),
-			length = resolveValues.length,
-
-			// the count of uncompleted subordinates
-			remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
-
-			// the master Deferred. If resolveValues consist of only a single Deferred, just use that.
-			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
-
-			// Update function for both resolve and progress values
-			updateFunc = function( i, contexts, values ) {
-				return function( value ) {
-					contexts[ i ] = this;
-					values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
-					if( values === progressValues ) {
-						deferred.notifyWith( contexts, values );
-					} else if ( !( --remaining ) ) {
-						deferred.resolveWith( contexts, values );
-					}
-				};
-			},
-
-			progressValues, progressContexts, resolveContexts;
-
-		// add listeners to Deferred subordinates; treat others as resolved
-		if ( length > 1 ) {
-			progressValues = new Array( length );
-			progressContexts = new Array( length );
-			resolveContexts = new Array( length );
-			for ( ; i < length; i++ ) {
-				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
-					resolveValues[ i ].promise()
-						.done( updateFunc( i, resolveContexts, resolveValues ) )
-						.fail( deferred.reject )
-						.progress( updateFunc( i, progressContexts, progressValues ) );
-				} else {
-					--remaining;
-				}
-			}
-		}
-
-		// if we're not waiting on anything, resolve the master
-		if ( !remaining ) {
-			deferred.resolveWith( resolveContexts, resolveValues );
-		}
-
-		return deferred.promise();
-	}
-});
-jQuery.support = (function() {
-
-	var support, all, a,
-		input, select, fragment,
-		opt, eventName, isSupported, i,
-		div = document.createElement("div");
-
-	// Setup
-	div.setAttribute( "className", "t" );
-	div.innerHTML = "  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
-
-	// Support tests won't run in some limited or non-browser environments
-	all = div.getElementsByTagName("*");
-	a = div.getElementsByTagName("a")[ 0 ];
-	if ( !all || !a || !all.length ) {
-		return {};
-	}
-
-	// First batch of tests
-	select = document.createElement("select");
-	opt = select.appendChild( document.createElement("option") );
-	input = div.getElementsByTagName("input")[ 0 ];
-
-	a.style.cssText = "top:1px;float:left;opacity:.5";
-	support = {
-		// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
-		getSetAttribute: div.className !== "t",
-
-		// IE strips leading whitespace when .innerHTML is used
-		leadingWhitespace: div.firstChild.nodeType === 3,
-
-		// Make sure that tbody elements aren't automatically inserted
-		// IE will insert them into empty tables
-		tbody: !div.getElementsByTagName("tbody").length,
-
-		// Make sure that link elements get serialized correctly by innerHTML
-		// This requires a wrapper element in IE
-		htmlSerialize: !!div.getElementsByTagName("link").length,
-
-		// Get the style information from getAttribute
-		// (IE uses .cssText instead)
-		style: /top/.test( a.getAttribute("style") ),
-
-		// Make sure that URLs aren't manipulated
-		// (IE normalizes it by default)
-		hrefNormalized: a.getAttribute("href") === "/a",
-
-		// Make sure that element opacity exists
-		// (IE uses filter instead)
-		// Use a regex to work around a WebKit issue. See #5145
-		opacity: /^0.5/.test( a.style.opacity ),
-
-		// Verify style float existence
-		// (IE uses styleFloat instead of cssFloat)
-		cssFloat: !!a.style.cssFloat,
-
-		// Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
-		checkOn: !!input.value,
-
-		// Make sure that a selected-by-default option has a working selected property.
-		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
-		optSelected: opt.selected,
-
-		// Tests for enctype support on a form (#6743)
-		enctype: !!document.createElement("form").enctype,
-
-		// Makes sure cloning an html5 element does not cause problems
-		// Where outerHTML is undefined, this still works
-		html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",
-
-		// jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode
-		boxModel: document.compatMode === "CSS1Compat",
-
-		// Will be defined later
-		deleteExpando: true,
-		noCloneEvent: true,
-		inlineBlockNeedsLayout: false,
-		shrinkWrapBlocks: false,
-		reliableMarginRight: true,
-		boxSizingReliable: true,
-		pixelPosition: false
-	};
-
-	// Make sure checked status is properly cloned
-	input.checked = true;
-	support.noCloneChecked = input.cloneNode( true ).checked;
-
-	// Make sure that the options inside disabled selects aren't marked as disabled
-	// (WebKit marks them as disabled)
-	select.disabled = true;
-	support.optDisabled = !opt.disabled;
-
-	// Support: IE<9
-	try {
-		delete div.test;
-	} catch( e ) {
-		support.deleteExpando = false;
-	}
-
-	// Check if we can trust getAttribute("value")
-	input = document.createElement("input");
-	input.setAttribute( "value", "" );
-	support.input = input.getAttribute( "value" ) === "";
-
-	// Check if an input maintains its value after becoming a radio
-	input.value = "t";
-	input.setAttribute( "type", "radio" );
-	support.radioValue = input.value === "t";
-
-	// #11217 - WebKit loses check when the name is after the checked attribute
-	input.setAttribute( "checked", "t" );
-	input.setAttribute( "name", "t" );
-
-	fragment = document.createDocumentFragment();
-	fragment.appendChild( input );
-
-	// Check if a disconnected checkbox will retain its checked
-	// value of true after appended to the DOM (IE6/7)
-	support.appendChecked = input.checked;
-
-	// WebKit doesn't clone checked state correctly in fragments
-	support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
-
-	// Support: IE<9
-	// Opera does not clone events (and typeof div.attachEvent === undefined).
-	// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
-	if ( div.attachEvent ) {
-		div.attachEvent( "onclick", function() {
-			support.noCloneEvent = false;
-		});
-
-		div.cloneNode( true ).click();
-	}
-
-	// Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)
-	// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php
-	for ( i in { submit: true, change: true, focusin: true }) {
-		div.setAttribute( eventName = "on" + i, "t" );
-
-		support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false;
-	}
-
-	div.style.backgroundClip = "content-box";
-	div.cloneNode( true ).style.backgroundClip = "";
-	support.clearCloneStyle = div.style.backgroundClip === "content-box";
-
-	// Run tests that need a body at doc ready
-	jQuery(function() {
-		var container, marginDiv, tds,
-			divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",
-			body = document.getElementsByTagName("body")[0];
-
-		if ( !body ) {
-			// Return for frameset docs that don't have a body
-			return;
-		}
-
-		container = document.createElement("div");
-		container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
-
-		body.appendChild( container ).appendChild( div );
-
-		// Support: IE8
-		// Check if table cells still have offsetWidth/Height when they are set
-		// to display:none and there are still other visible table cells in a
-		// table row; if so, offsetWidth/Height are not reliable for use when
-		// determining if an element has been hidden directly using
-		// display:none (it is still safe to use offsets if a parent element is
-		// hidden; don safety goggles and see bug #4512 for more information).
-		div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
-		tds = div.getElementsByTagName("td");
-		tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none";
-		isSupported = ( tds[ 0 ].offsetHeight === 0 );
-
-		tds[ 0 ].style.display = "";
-		tds[ 1 ].style.display = "none";
-
-		// Support: IE8
-		// Check if empty table cells still have offsetWidth/Height
-		support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
-
-		// Check box-sizing and margin behavior
-		div.innerHTML = "";
-		div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;";
-		support.boxSizing = ( div.offsetWidth === 4 );
-		support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );
-
-		// Use window.getComputedStyle because jsdom on node.js will break without it.
-		if ( window.getComputedStyle ) {
-			support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
-			support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
-
-			// Check if div with explicit width and no margin-right incorrectly
-			// gets computed margin-right based on width of container. (#3333)
-			// Fails in WebKit before Feb 2011 nightlies
-			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
-			marginDiv = div.appendChild( document.createElement("div") );
-			marginDiv.style.cssText = div.style.cssText = divReset;
-			marginDiv.style.marginRight = marginDiv.style.width = "0";
-			div.style.width = "1px";
-
-			support.reliableMarginRight =
-				!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
-		}
-
-		if ( typeof div.style.zoom !== core_strundefined ) {
-			// Support: IE<8
-			// Check if natively block-level elements act like inline-block
-			// elements when setting their display to 'inline' and giving
-			// them layout
-			div.innerHTML = "";
-			div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1";
-			support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );
-
-			// Support: IE6
-			// Check if elements with layout shrink-wrap their children
-			div.style.display = "block";
-			div.innerHTML = "<div></div>";
-			div.firstChild.style.width = "5px";
-			support.shrinkWrapBlocks = ( div.offsetWidth !== 3 );
-
-			if ( support.inlineBlockNeedsLayout ) {
-				// Prevent IE 6 from affecting layout for positioned elements #11048
-				// Prevent IE from shrinking the body in IE 7 mode #12869
-				// Support: IE<8
-				body.style.zoom = 1;
-			}
-		}
-
-		body.removeChild( container );
-
-		// Null elements to avoid leaks in IE
-		container = div = tds = marginDiv = null;
-	});
-
-	// Null elements to avoid leaks in IE
-	all = select = fragment = opt = a = input = null;
-
-	return support;
-})();
-
-var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
-	rmultiDash = /([A-Z])/g;
-
-function internalData( elem, name, data, pvt /* Internal Use Only */ ){
-	if ( !jQuery.acceptData( elem ) ) {
-		return;
-	}
-
-	var thisCache, ret,
-		internalKey = jQuery.expando,
-		getByName = typeof name === "string",
-
-		// We have to handle DOM nodes and JS objects differently because IE6-7
-		// can't GC object references properly across the DOM-JS boundary
-		isNode = elem.nodeType,
-
-		// Only DOM nodes need the global jQuery cache; JS object data is
-		// attached directly to the object so GC can occur automatically
-		cache = isNode ? jQuery.cache : elem,
-
-		// Only defining an ID for JS objects if its cache already exists allows
-		// the code to shortcut on the same path as a DOM node with no cache
-		id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
-
-	// Avoid doing any more work than we need to when trying to get data on an
-	// object that has no data at all
-	if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {
-		return;
-	}
-
-	if ( !id ) {
-		// Only DOM nodes need a new unique ID for each element since their data
-		// ends up in the global cache
-		if ( isNode ) {
-			elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;
-		} else {
-			id = internalKey;
-		}
-	}
-
-	if ( !cache[ id ] ) {
-		cache[ id ] = {};
-
-		// Avoids exposing jQuery metadata on plain JS objects when the object
-		// is serialized using JSON.stringify
-		if ( !isNode ) {
-			cache[ id ].toJSON = jQuery.noop;
-		}
-	}
-
-	// An object can be passed to jQuery.data instead of a key/value pair; this gets
-	// shallow copied over onto the existing cache
-	if ( typeof name === "object" || typeof name === "function" ) {
-		if ( pvt ) {
-			cache[ id ] = jQuery.extend( cache[ id ], name );
-		} else {
-			cache[ id ].data = jQuery.extend( cache[ id ].data, name );
-		}
-	}
-
-	thisCache = cache[ id ];
-
-	// jQuery data() is stored in a separate object inside the object's internal data
-	// cache in order to avoid key collisions between internal data and user-defined
-	// data.
-	if ( !pvt ) {
-		if ( !thisCache.data ) {
-			thisCache.data = {};
-		}
-
-		thisCache = thisCache.data;
-	}
-
-	if ( data !== undefined ) {
-		thisCache[ jQuery.camelCase( name ) ] = data;
-	}
-
-	// Check for both converted-to-camel and non-converted data property names
-	// If a data property was specified
-	if ( getByName ) {
-
-		// First Try to find as-is property data
-		ret = thisCache[ name ];
-
-		// Test for null|undefined property data
-		if ( ret == null ) {
-
-			// Try to find the camelCased property
-			ret = thisCache[ jQuery.camelCase( name ) ];
-		}
-	} else {
-		ret = thisCache;
-	}
-
-	return ret;
-}
-
-function internalRemoveData( elem, name, pvt ) {
-	if ( !jQuery.acceptData( elem ) ) {
-		return;
-	}
-
-	var i, l, thisCache,
-		isNode = elem.nodeType,
-
-		// See jQuery.data for more information
-		cache = isNode ? jQuery.cache : elem,
-		id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
-
-	// If there is already no cache entry for this object, there is no
-	// purpose in continuing
-	if ( !cache[ id ] ) {
-		return;
-	}
-
-	if ( name ) {
-
-		thisCache = pvt ? cache[ id ] : cache[ id ].data;
-
-		if ( thisCache ) {
-
-			// Support array or space separated string names for data keys
-			if ( !jQuery.isArray( name ) ) {
-
-				// try the string as a key before any manipulation
-				if ( name in thisCache ) {
-					name = [ name ];
-				} else {
-
-					// split the camel cased version by spaces unless a key with the spaces exists
-					name = jQuery.camelCase( name );
-					if ( name in thisCache ) {
-						name = [ name ];
-					} else {
-						name = name.split(" ");
-					}
-				}
-			} else {
-				// If "name" is an array of keys...
-				// When data is initially created, via ("key", "val") signature,
-				// keys will be converted to camelCase.
-				// Since there is no way to tell _how_ a key was added, remove
-				// both plain key and camelCase key. #12786
-				// This will only penalize the array argument path.
-				name = name.concat( jQuery.map( name, jQuery.camelCase ) );
-			}
-
-			for ( i = 0, l = name.length; i < l; i++ ) {
-				delete thisCache[ name[i] ];
-			}
-
-			// If there is no data left in the cache, we want to continue
-			// and let the cache object itself get destroyed
-			if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {
-				return;
-			}
-		}
-	}
-
-	// See jQuery.data for more information
-	if ( !pvt ) {
-		delete cache[ id ].data;
-
-		// Don't destroy the parent cache unless the internal data object
-		// had been the only thing left in it
-		if ( !isEmptyDataObject( cache[ id ] ) ) {
-			return;
-		}
-	}
-
-	// Destroy the cache
-	if ( isNode ) {
-		jQuery.cleanData( [ elem ], true );
-
-	// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
-	} else if ( jQuery.support.deleteExpando || cache != cache.window ) {
-		delete cache[ id ];
-
-	// When all else fails, null
-	} else {
-		cache[ id ] = null;
-	}
-}
-
-jQuery.extend({
-	cache: {},
-
-	// Unique for each copy of jQuery on the page
-	// Non-digits removed to match rinlinejQuery
-	expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
-
-	// The following elements throw uncatchable exceptions if you
-	// attempt to add expando properties to them.
-	noData: {
-		"embed": true,
-		// Ban all objects except for Flash (which handle expandos)
-		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
-		"applet": true
-	},
-
-	hasData: function( elem ) {
-		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
-		return !!elem && !isEmptyDataObject( elem );
-	},
-
-	data: function( elem, name, data ) {
-		return internalData( elem, name, data );
-	},
-
-	removeData: function( elem, name ) {
-		return internalRemoveData( elem, name );
-	},
-
-	// For internal use only.
-	_data: function( elem, name, data ) {
-		return internalData( elem, name, data, true );
-	},
-
-	_removeData: function( elem, name ) {
-		return internalRemoveData( elem, name, true );
-	},
-
-	// A method for determining if a DOM node can handle the data expando
-	acceptData: function( elem ) {
-		// Do not set data on non-element because it will not be cleared (#8335).
-		if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {
-			return false;
-		}
-
-		var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];
-
-		// nodes accept data unless otherwise specified; rejection can be conditional
-		return !noData || noData !== true && elem.getAttribute("classid") === noData;
-	}
-});
-
-jQuery.fn.extend({
-	data: function( key, value ) {
-		var attrs, name,
-			elem = this[0],
-			i = 0,
-			data = null;
-
-		// Gets all values
-		if ( key === undefined ) {
-			if ( this.length ) {
-				data = jQuery.data( elem );
-
-				if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
-					attrs = elem.attributes;
-					for ( ; i < attrs.length; i++ ) {
-						name = attrs[i].name;
-
-						if ( !name.indexOf( "data-" ) ) {
-							name = jQuery.camelCase( name.slice(5) );
-
-							dataAttr( elem, name, data[ name ] );
-						}
-					}
-					jQuery._data( elem, "parsedAttrs", true );
-				}
-			}
-
-			return data;
-		}
-
-		// Sets multiple values
-		if ( typeof key === "object" ) {
-			return this.each(function() {
-				jQuery.data( this, key );
-			});
-		}
-
-		return jQuery.access( this, function( value ) {
-
-			if ( value === undefined ) {
-				// Try to fetch any internally stored data first
-				return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;
-			}
-
-			this.each(function() {
-				jQuery.data( this, key, value );
-			});
-		}, null, value, arguments.length > 1, null, true );
-	},
-
-	removeData: function( key ) {
-		return this.each(function() {
-			jQuery.removeData( this, key );
-		});
-	}
-});
-
-function dataAttr( elem, key, data ) {
-	// If nothing was found internally, try to fetch any
-	// data from the HTML5 data-* attribute
-	if ( data === undefined && elem.nodeType === 1 ) {
-
-		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
-
-		data = elem.getAttribute( name );
-
-		if ( typeof data === "string" ) {
-			try {
-				data = data === "true" ? true :
-					data === "false" ? false :
-					data === "null" ? null :
-					// Only convert to a number if it doesn't change the string
-					+data + "" === data ? +data :
-					rbrace.test( data ) ? jQuery.parseJSON( data ) :
-						data;
-			} catch( e ) {}
-
-			// Make sure we set the data so it isn't changed later
-			jQuery.data( elem, key, data );
-
-		} else {
-			data = undefined;
-		}
-	}
-
-	return data;
-}
-
-// checks a cache object for emptiness
-function isEmptyDataObject( obj ) {
-	var name;
-	for ( name in obj ) {
-
-		// if the public data object is empty, the private is still empty
-		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
-			continue;
-		}
-		if ( name !== "toJSON" ) {
-			return false;
-		}
-	}
-
-	return true;
-}
-jQuery.extend({
-	queue: function( elem, type, data ) {
-		var queue;
-
-		if ( elem ) {
-			type = ( type || "fx" ) + "queue";
-			queue = jQuery._data( elem, type );
-
-			// Speed up dequeue by getting out quickly if this is just a lookup
-			if ( data ) {
-				if ( !queue || jQuery.isArray(data) ) {
-					queue = jQuery._data( elem, type, jQuery.makeArray(data) );
-				} else {
-					queue.push( data );
-				}
-			}
-			return queue || [];
-		}
-	},
-
-	dequeue: function( elem, type ) {
-		type = type || "fx";
-
-		var queue = jQuery.queue( elem, type ),
-			startLength = queue.length,
-			fn = queue.shift(),
-			hooks = jQuery._queueHooks( elem, type ),
-			next = function() {
-				jQuery.dequeue( elem, type );
-			};
-
-		// If the fx queue is dequeued, always remove the progress sentinel
-		if ( fn === "inprogress" ) {
-			fn = queue.shift();
-			startLength--;
-		}
-
-		hooks.cur = fn;
-		if ( fn ) {
-
-			// Add a progress sentinel to prevent the fx queue from being
-			// automatically dequeued
-			if ( type === "fx" ) {
-				queue.unshift( "inprogress" );
-			}
-
-			// clear up the last queue stop function
-			delete hooks.stop;
-			fn.call( elem, next, hooks );
-		}
-
-		if ( !startLength && hooks ) {
-			hooks.empty.fire();
-		}
-	},
-
-	// not intended for public consumption - generates a queueHooks object, or returns the current one
-	_queueHooks: function( elem, type ) {
-		var key = type + "queueHooks";
-		return jQuery._data( elem, key ) || jQuery._data( elem, key, {
-			empty: jQuery.Callbacks("once memory").add(function() {
-				jQuery._removeData( elem, type + "queue" );
-				jQuery._removeData( elem, key );
-			})
-		});
-	}
-});
-
-jQuery.fn.extend({
-	queue: function( type, data ) {
-		var setter = 2;
-
-		if ( typeof type !== "string" ) {
-			data = type;
-			type = "fx";
-			setter--;
-		}
-
-		if ( arguments.length < setter ) {
-			return jQuery.queue( this[0], type );
-		}
-
-		return data === undefined ?
-			this :
-			this.each(function() {
-				var queue = jQuery.queue( this, type, data );
-
-				// ensure a hooks for this queue
-				jQuery._queueHooks( this, type );
-
-				if ( type === "fx" && queue[0] !== "inprogress" ) {
-					jQuery.dequeue( this, type );
-				}
-			});
-	},
-	dequeue: function( type ) {
-		return this.each(function() {
-			jQuery.dequeue( this, type );
-		});
-	},
-	// Based off of the plugin by Clint Helfers, with permission.
-	// http://blindsignals.com/index.php/2009/07/jquery-delay/
-	delay: function( time, type ) {
-		time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
-		type = type || "fx";
-
-		return this.queue( type, function( next, hooks ) {
-			var timeout = setTimeout( next, time );
-			hooks.stop = function() {
-				clearTimeout( timeout );
-			};
-		});
-	},
-	clearQueue: function( type ) {
-		return this.queue( type || "fx", [] );
-	},
-	// Get a promise resolved when queues of a certain type
-	// are emptied (fx is the type by default)
-	promise: function( type, obj ) {
-		var tmp,
-			count = 1,
-			defer = jQuery.Deferred(),
-			elements = this,
-			i = this.length,
-			resolve = function() {
-				if ( !( --count ) ) {
-					defer.resolveWith( elements, [ elements ] );
-				}
-			};
-
-		if ( typeof type !== "string" ) {
-			obj = type;
-			type = undefined;
-		}
-		type = type || "fx";
-
-		while( i-- ) {
-			tmp = jQuery._data( elements[ i ], type + "queueHooks" );
-			if ( tmp && tmp.empty ) {
-				count++;
-				tmp.empty.add( resolve );
-			}
-		}
-		resolve();
-		return defer.promise( obj );
-	}
-});
-var nodeHook, boolHook,
-	rclass = /[\t\r\n]/g,
-	rreturn = /\r/g,
-	rfocusable = /^(?:input|select|textarea|button|object)$/i,
-	rclickable = /^(?:a|area)$/i,
-	rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,
-	ruseDefault = /^(?:checked|selected)$/i,
-	getSetAttribute = jQuery.support.getSetAttribute,
-	getSetInput = jQuery.support.input;
-
-jQuery.fn.extend({
-	attr: function( name, value ) {
-		return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
-	},
-
-	removeAttr: function( name ) {
-		return this.each(function() {
-			jQuery.removeAttr( this, name );
-		});
-	},
-
-	prop: function( name, value ) {
-		return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
-	},
-
-	removeProp: function( name ) {
-		name = jQuery.propFix[ name ] || name;
-		return this.each(function() {
-			// try/catch handles cases where IE balks (such as removing a property on window)
-			try {
-				this[ name ] = undefined;
-				delete this[ name ];
-			} catch( e ) {}
-		});
-	},
-
-	addClass: function( value ) {
-		var classes, elem, cur, clazz, j,
-			i = 0,
-			len = this.length,
-			proceed = typeof value === "string" && value;
-
-		if ( jQuery.isFunction( value ) ) {
-			return this.each(function( j ) {
-				jQuery( this ).addClass( value.call( this, j, this.className ) );
-			});
-		}
-
-		if ( proceed ) {
-			// The disjunction here is for better compressibility (see removeClass)
-			classes = ( value || "" ).match( core_rnotwhite ) || [];
-
-			for ( ; i < len; i++ ) {
-				elem = this[ i ];
-				cur = elem.nodeType === 1 && ( elem.className ?
-					( " " + elem.className + " " ).replace( rclass, " " ) :
-					" "
-				);
-
-				if ( cur ) {
-					j = 0;
-					while ( (clazz = classes[j++]) ) {
-						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
-							cur += clazz + " ";
-						}
-					}
-					elem.className = jQuery.trim( cur );
-
-				}
-			}
-		}
-
-		return this;
-	},
-
-	removeClass: function( value ) {
-		var classes, elem, cur, clazz, j,
-			i = 0,
-			len = this.length,
-			proceed = arguments.length === 0 || typeof value === "string" && value;
-
-		if ( jQuery.isFunction( value ) ) {
-			return this.each(function( j ) {
-				jQuery( this ).removeClass( value.call( this, j, this.className ) );
-			});
-		}
-		if ( proceed ) {
-			classes = ( value || "" ).match( core_rnotwhite ) || [];
-
-			for ( ; i < len; i++ ) {
-				elem = this[ i ];
-				// This expression is here for better compressibility (see addClass)
-				cur = elem.nodeType === 1 && ( elem.className ?
-					( " " + elem.className + " " ).replace( rclass, " " ) :
-					""
-				);
-
-				if ( cur ) {
-					j = 0;
-					while ( (clazz = classes[j++]) ) {
-						// Remove *all* instances
-						while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
-							cur = cur.replace( " " + clazz + " ", " " );
-						}
-					}
-					elem.className = value ? jQuery.trim( cur ) : "";
-				}
-			}
-		}
-
-		return this;
-	},
-
-	toggleClass: function( value, stateVal ) {
-		var type = typeof value,
-			isBool = typeof stateVal === "boolean";
-
-		if ( jQuery.isFunction( value ) ) {
-			return this.each(function( i ) {
-				jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
-			});
-		}
-
-		return this.each(function() {
-			if ( type === "string" ) {
-				// toggle individual class names
-				var className,
-					i = 0,
-					self = jQuery( this ),
-					state = stateVal,
-					classNames = value.match( core_rnotwhite ) || [];
-
-				while ( (className = classNames[ i++ ]) ) {
-					// check each className given, space separated list
-					state = isBool ? state : !self.hasClass( className );
-					self[ state ? "addClass" : "removeClass" ]( className );
-				}
-
-			// Toggle whole class name
-			} else if ( type === core_strundefined || type === "boolean" ) {
-				if ( this.className ) {
-					// store className if set
-					jQuery._data( this, "__className__", this.className );
-				}
-
-				// If the element has a class name or if we're passed "false",
-				// then remove the whole classname (if there was one, the above saved it).
-				// Otherwise bring back whatever was previously saved (if anything),
-				// falling back to the empty string if nothing was stored.
-				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
-			}
-		});
-	},
-
-	hasClass: function( selector ) {
-		var className = " " + selector + " ",
-			i = 0,
-			l = this.length;
-		for ( ; i < l; i++ ) {
-			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
-				return true;
-			}
-		}
-
-		return false;
-	},
-
-	val: function( value ) {
-		var ret, hooks, isFunction,
-			elem = this[0];
-
-		if ( !arguments.length ) {
-			if ( elem ) {
-				hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
-
-				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
-					return ret;
-				}
-
-				ret = elem.value;
-
-				return typeof ret === "string" ?
-					// handle most common string cases
-					ret.replace(rreturn, "") :
-					// handle cases where value is null/undef or number
-					ret == null ? "" : ret;
-			}
-
-			return;
-		}
-
-		isFunction = jQuery.isFunction( value );
-
-		return this.each(function( i ) {
-			var val,
-				self = jQuery(this);
-
-			if ( this.nodeType !== 1 ) {
-				return;
-			}
-
-			if ( isFunction ) {
-				val = value.call( this, i, self.val() );
-			} else {
-				val = value;
-			}
-
-			// Treat null/undefined as ""; convert numbers to string
-			if ( val == null ) {
-				val = "";
-			} else if ( typeof val === "number" ) {
-				val += "";
-			} else if ( jQuery.isArray( val ) ) {
-				val = jQuery.map(val, function ( value ) {
-					return value == null ? "" : value + "";
-				});
-			}
-
-			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
-
-			// If set returns undefined, fall back to normal setting
-			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
-				this.value = val;
-			}
-		});
-	}
-});
-
-jQuery.extend({
-	valHooks: {
-		option: {
-			get: function( elem ) {
-				// attributes.value is undefined in Blackberry 4.7 but
-				// uses .value. See #6932
-				var val = elem.attributes.value;
-				return !val || val.specified ? elem.value : elem.text;
-			}
-		},
-		select: {
-			get: function( elem ) {
-				var value, option,
-					options = elem.options,
-					index = elem.selectedIndex,
-					one = elem.type === "select-one" || index < 0,
-					values = one ? null : [],
-					max = one ? index + 1 : options.length,
-					i = index < 0 ?
-						max :
-						one ? index : 0;
-
-				// Loop through all the selected options
-				for ( ; i < max; i++ ) {
-					option = options[ i ];
-
-					// oldIE doesn't update selected after form reset (#2551)
-					if ( ( option.selected || i === index ) &&
-							// Don't return options that are disabled or in a disabled optgroup
-							( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
-							( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
-
-						// Get the specific value for the option
-						value = jQuery( option ).val();
-
-						// We don't need an array for one selects
-						if ( one ) {
-							return value;
-						}
-
-						// Multi-Selects return an array
-						values.push( value );
-					}
-				}
-
-				return values;
-			},
-
-			set: function( elem, value ) {
-				var values = jQuery.makeArray( value );
-
-				jQuery(elem).find("option").each(function() {
-					this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
-				});
-
-				if ( !values.length ) {
-					elem.selectedIndex = -1;
-				}
-				return values;
-			}
-		}
-	},
-
-	attr: function( elem, name, value ) {
-		var hooks, notxml, ret,
-			nType = elem.nodeType;
-
-		// don't get/set attributes on text, comment and attribute nodes
-		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
-			return;
-		}
-
-		// Fallback to prop when attributes are not supported
-		if ( typeof elem.getAttribute === core_strundefined ) {
-			return jQuery.prop( elem, name, value );
-		}
-
-		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
-		// All attributes are lowercase
-		// Grab necessary hook if one is defined
-		if ( notxml ) {
-			name = name.toLowerCase();
-			hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
-		}
-
-		if ( value !== undefined ) {
-
-			if ( value === null ) {
-				jQuery.removeAttr( elem, name );
-
-			} else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
-				return ret;
-
-			} else {
-				elem.setAttribute( name, value + "" );
-				return value;
-			}
-
-		} else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
-			return ret;
-
-		} else {
-
-			// In IE9+, Flash objects don't have .getAttribute (#12945)
-			// Support: IE9+
-			if ( typeof elem.getAttribute !== core_strundefined ) {
-				ret =  elem.getAttribute( name );
-			}
-
-			// Non-existent attributes return null, we normalize to undefined
-			return ret == null ?
-				undefined :
-				ret;
-		}
-	},
-
-	removeAttr: function( elem, value ) {
-		var name, propName,
-			i = 0,
-			attrNames = value && value.match( core_rnotwhite );
-
-		if ( attrNames && elem.nodeType === 1 ) {
-			while ( (name = attrNames[i++]) ) {
-				propName = jQuery.propFix[ name ] || name;
-
-				// Boolean attributes get special treatment (#10870)
-				if ( rboolean.test( name ) ) {
-					// Set corresponding property to false for boolean attributes
-					// Also clear defaultChecked/defaultSelected (if appropriate) for IE<8
-					if ( !getSetAttribute && ruseDefault.test( name ) ) {
-						elem[ jQuery.camelCase( "default-" + name ) ] =
-							elem[ propName ] = false;
-					} else {
-						elem[ propName ] = false;
-					}
-
-				// See #9699 for explanation of this approach (setting first, then removal)
-				} else {
-					jQuery.attr( elem, name, "" );
-				}
-
-				elem.removeAttribute( getSetAttribute ? name : propName );
-			}
-		}
-	},
-
-	attrHooks: {
-		type: {
-			set: function( elem, value ) {
-				if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
-					// Setting the type on a radio button after the value resets the value in IE6-9
-					// Reset value to default in case type is set after value during creation
-					var val = elem.value;
-					elem.setAttribute( "type", value );
-					if ( val ) {
-						elem.value = val;
-					}
-					return value;
-				}
-			}
-		}
-	},
-
-	propFix: {
-		tabindex: "tabIndex",
-		readonly: "readOnly",
-		"for": "htmlFor",
-		"class": "className",
-		maxlength: "maxLength",
-		cellspacing: "cellSpacing",
-		cellpadding: "cellPadding",
-		rowspan: "rowSpan",
-		colspan: "colSpan",
-		usemap: "useMap",
-		frameborder: "frameBorder",
-		contenteditable: "contentEditable"
-	},
-
-	prop: function( elem, name, value ) {
-		var ret, hooks, notxml,
-			nType = elem.nodeType;
-
-		// don't get/set properties on text, comment and attribute nodes
-		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
-			return;
-		}
-
-		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
-
-		if ( notxml ) {
-			// Fix name and attach hooks
-			name = jQuery.propFix[ name ] || name;
-			hooks = jQuery.propHooks[ name ];
-		}
-
-		if ( value !== undefined ) {
-			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
-				return ret;
-
-			} else {
-				return ( elem[ name ] = value );
-			}
-
-		} else {
-			if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
-				return ret;
-
-			} else {
-				return elem[ name ];
-			}
-		}
-	},
-
-	propHooks: {
-		tabIndex: {
-			get: function( elem ) {
-				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
-				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
-				var attributeNode = elem.getAttributeNode("tabindex");
-
-				return attributeNode && attributeNode.specified ?
-					parseInt( attributeNode.value, 10 ) :
-					rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
-						0 :
-						undefined;
-			}
-		}
-	}
-});
-
-// Hook for boolean attributes
-boolHook = {
-	get: function( elem, name ) {
-		var
-			// Use .prop to determine if this attribute is understood as boolean
-			prop = jQuery.prop( elem, name ),
-
-			// Fetch it accordingly
-			attr = typeof prop === "boolean" && elem.getAttribute( name ),
-			detail = typeof prop === "boolean" ?
-
-				getSetInput && getSetAttribute ?
-					attr != null :
-					// oldIE fabricates an empty string for missing boolean attributes
-					// and conflates checked/selected into attroperties
-					ruseDefault.test( name ) ?
-						elem[ jQuery.camelCase( "default-" + name ) ] :
-						!!attr :
-
-				// fetch an attribute node for properties not recognized as boolean
-				elem.getAttributeNode( name );
-
-		return detail && detail.value !== false ?
-			name.toLowerCase() :
-			undefined;
-	},
-	set: function( elem, value, name ) {
-		if ( value === false ) {
-			// Remove boolean attributes when set to false
-			jQuery.removeAttr( elem, name );
-		} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
-			// IE<8 needs the *property* name
-			elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
-
-		// Use defaultChecked and defaultSelected for oldIE
-		} else {
-			elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
-		}
-
-		return name;
-	}
-};
-
-// fix oldIE value attroperty
-if ( !getSetInput || !getSetAttribute ) {
-	jQuery.attrHooks.value = {
-		get: function( elem, name ) {
-			var ret = elem.getAttributeNode( name );
-			return jQuery.nodeName( elem, "input" ) ?
-
-				// Ignore the value *property* by using defaultValue
-				elem.defaultValue :
-
-				ret && ret.specified ? ret.value : undefined;
-		},
-		set: function( elem, value, name ) {
-			if ( jQuery.nodeName( elem, "input" ) ) {
-				// Does not return so that setAttribute is also used
-				elem.defaultValue = value;
-			} else {
-				// Use nodeHook if defined (#1954); otherwise setAttribute is fine
-				return nodeHook && nodeHook.set( elem, value, name );
-			}
-		}
-	};
-}
-
-// IE6/7 do not support getting/setting some attributes with get/setAttribute
-if ( !getSetAttribute ) {
-
-	// Use this for any attribute in IE6/7
-	// This fixes almost every IE6/7 issue
-	nodeHook = jQuery.valHooks.button = {
-		get: function( elem, name ) {
-			var ret = elem.getAttributeNode( name );
-			return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ?
-				ret.value :
-				undefined;
-		},
-		set: function( elem, value, name ) {
-			// Set the existing or create a new attribute node
-			var ret = elem.getAttributeNode( name );
-			if ( !ret ) {
-				elem.setAttributeNode(
-					(ret = elem.ownerDocument.createAttribute( name ))
-				);
-			}
-
-			ret.value = value += "";
-
-			// Break association with cloned elements by also using setAttribute (#9646)
-			return name === "value" || value === elem.getAttribute( name ) ?
-				value :
-				undefined;
-		}
-	};
-
-	// Set contenteditable to false on removals(#10429)
-	// Setting to empty string throws an error as an invalid value
-	jQuery.attrHooks.contenteditable = {
-		get: nodeHook.get,
-		set: function( elem, value, name ) {
-			nodeHook.set( elem, value === "" ? false : value, name );
-		}
-	};
-
-	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
-	// This is for removals
-	jQuery.each([ "width", "height" ], function( i, name ) {
-		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
-			set: function( elem, value ) {
-				if ( value === "" ) {
-					elem.setAttribute( name, "auto" );
-					return value;
-				}
-			}
-		});
-	});
-}
-
-
-// Some attributes require a special call on IE
-// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
-if ( !jQuery.support.hrefNormalized ) {
-	jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
-		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
-			get: function( elem ) {
-				var ret = elem.getAttribute( name, 2 );
-				return ret == null ? undefined : ret;
-			}
-		});
-	});
-
-	// href/src property should get the full normalized URL (#10299/#12915)
-	jQuery.each([ "href", "src" ], function( i, name ) {
-		jQuery.propHooks[ name ] = {
-			get: function( elem ) {
-				return elem.getAttribute( name, 4 );
-			}
-		};
-	});
-}
-
-if ( !jQuery.support.style ) {
-	jQuery.attrHooks.style = {
-		get: function( elem ) {
-			// Return undefined in the case of empty string
-			// Note: IE uppercases css property names, but if we were to .toLowerCase()
-			// .cssText, that would destroy case senstitivity in URL's, like in "background"
-			return elem.style.cssText || undefined;
-		},
-		set: function( elem, value ) {
-			return ( elem.style.cssText = value + "" );
-		}
-	};
-}
-
-// Safari mis-reports the default selected property of an option
-// Accessing the parent's selectedIndex property fixes it
-if ( !jQuery.support.optSelected ) {
-	jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
-		get: function( elem ) {
-			var parent = elem.parentNode;
-
-			if ( parent ) {
-				parent.selectedIndex;
-
-				// Make sure that it also works with optgroups, see #5701
-				if ( parent.parentNode ) {
-					parent.parentNode.selectedIndex;
-				}
-			}
-			return null;
-		}
-	});
-}
-
-// IE6/7 call enctype encoding
-if ( !jQuery.support.enctype ) {
-	jQuery.propFix.enctype = "encoding";
-}
-
-// Radios and checkboxes getter/setter
-if ( !jQuery.support.checkOn ) {
-	jQuery.each([ "radio", "checkbox" ], function() {
-		jQuery.valHooks[ this ] = {
-			get: function( elem ) {
-				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
-				return elem.getAttribute("value") === null ? "on" : elem.value;
-			}
-		};
-	});
-}
-jQuery.each([ "radio", "checkbox" ], function() {
-	jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
-		set: function( elem, value ) {
-			if ( jQuery.isArray( value ) ) {
-				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
-			}
-		}
-	});
-});
-var rformElems = /^(?:input|select|textarea)$/i,
-	rkeyEvent = /^key/,
-	rmouseEvent = /^(?:mouse|contextmenu)|click/,
-	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
-	rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
-
-function returnTrue() {
-	return true;
-}
-
-function returnFalse() {
-	return false;
-}
-
-/*
- * Helper functions for managing events -- not part of the public interface.
- * Props to Dean Edwards' addEvent library for many of the ideas.
- */
-jQuery.event = {
-
-	global: {},
-
-	add: function( elem, types, handler, data, selector ) {
-		var tmp, events, t, handleObjIn,
-			special, eventHandle, handleObj,
-			handlers, type, namespaces, origType,
-			elemData = jQuery._data( elem );
-
-		// Don't attach events to noData or text/comment nodes (but allow plain objects)
-		if ( !elemData ) {
-			return;
-		}
-
-		// Caller can pass in an object of custom data in lieu of the handler
-		if ( handler.handler ) {
-			handleObjIn = handler;
-			handler = handleObjIn.handler;
-			selector = handleObjIn.selector;
-		}
-
-		// Make sure that the handler has a unique ID, used to find/remove it later
-		if ( !handler.guid ) {
-			handler.guid = jQuery.guid++;
-		}
-
-		// Init the element's event structure and main handler, if this is the first
-		if ( !(events = elemData.events) ) {
-			events = elemData.events = {};
-		}
-		if ( !(eventHandle = elemData.handle) ) {
-			eventHandle = elemData.handle = function( e ) {
-				// Discard the second event of a jQuery.event.trigger() and
-				// when an event is called after a page has unloaded
-				return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
-					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
-					undefined;
-			};
-			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
-			eventHandle.elem = elem;
-		}
-
-		// Handle multiple events separated by a space
-		// jQuery(...).bind("mouseover mouseout", fn);
-		types = ( types || "" ).match( core_rnotwhite ) || [""];
-		t = types.length;
-		while ( t-- ) {
-			tmp = rtypenamespace.exec( types[t] ) || [];
-			type = origType = tmp[1];
-			namespaces = ( tmp[2] || "" ).split( "." ).sort();
-
-			// If event changes its type, use the special event handlers for the changed type
-			special = jQuery.event.special[ type ] || {};
-
-			// If selector defined, determine special event api type, otherwise given type
-			type = ( selector ? special.delegateType : special.bindType ) || type;
-
-			// Update special based on newly reset type
-			special = jQuery.event.special[ type ] || {};
-
-			// handleObj is passed to all event handlers
-			handleObj = jQuery.extend({
-				type: type,
-				origType: origType,
-				data: data,
-				handler: handler,
-				guid: handler.guid,
-				selector: selector,
-				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
-				namespace: namespaces.join(".")
-			}, handleObjIn );
-
-			// Init the event handler queue if we're the first
-			if ( !(handlers = events[ type ]) ) {
-				handlers = events[ type ] = [];
-				handlers.delegateCount = 0;
-
-				// Only use addEventListener/attachEvent if the special events handler returns false
-				if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
-					// Bind the global event handler to the element
-					if ( elem.addEventListener ) {
-						elem.addEventListener( type, eventHandle, false );
-
-					} else if ( elem.attachEvent ) {
-						elem.attachEvent( "on" + type, eventHandle );
-					}
-				}
-			}
-
-			if ( special.add ) {
-				special.add.call( elem, handleObj );
-
-				if ( !handleObj.handler.guid ) {
-					handleObj.handler.guid = handler.guid;
-				}
-			}
-
-			// Add to the element's handler list, delegates in front
-			if ( selector ) {
-				handlers.splice( handlers.delegateCount++, 0, handleObj );
-			} else {
-				handlers.push( handleObj );
-			}
-
-			// Keep track of which events have ever been used, for event optimization
-			jQuery.event.global[ type ] = true;
-		}
-
-		// Nullify elem to prevent memory leaks in IE
-		elem = null;
-	},
-
-	// Detach an event or set of events from an element
-	remove: function( elem, types, handler, selector, mappedTypes ) {
-		var j, handleObj, tmp,
-			origCount, t, events,
-			special, handlers, type,
-			namespaces, origType,
-			elemData = jQuery.hasData( elem ) && jQuery._data( elem );
-
-		if ( !elemData || !(events = elemData.events) ) {
-			return;
-		}
-
-		// Once for each type.namespace in types; type may be omitted
-		types = ( types || "" ).match( core_rnotwhite ) || [""];
-		t = types.length;
-		while ( t-- ) {
-			tmp = rtypenamespace.exec( types[t] ) || [];
-			type = origType = tmp[1];
-			namespaces = ( tmp[2] || "" ).split( "." ).sort();
-
-			// Unbind all events (on this namespace, if provided) for the element
-			if ( !type ) {
-				for ( type in events ) {
-					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
-				}
-				continue;
-			}
-
-			special = jQuery.event.special[ type ] || {};
-			type = ( selector ? special.delegateType : special.bindType ) || type;
-			handlers = events[ type ] || [];
-			tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
-
-			// Remove matching events
-			origCount = j = handlers.length;
-			while ( j-- ) {
-				handleObj = handlers[ j ];
-
-				if ( ( mappedTypes || origType === handleObj.origType ) &&
-					( !handler || handler.guid === handleObj.guid ) &&
-					( !tmp || tmp.test( handleObj.namespace ) ) &&
-					( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
-					handlers.splice( j, 1 );
-
-					if ( handleObj.selector ) {
-						handlers.delegateCount--;
-					}
-					if ( special.remove ) {
-						special.remove.call( elem, handleObj );
-					}
-				}
-			}
-
-			// Remove generic event handler if we removed something and no more handlers exist
-			// (avoids potential for endless recursion during removal of special event handlers)
-			if ( origCount && !handlers.length ) {
-				if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
-					jQuery.removeEvent( elem, type, elemData.handle );
-				}
-
-				delete events[ type ];
-			}
-		}
-
-		// Remove the expando if it's no longer used
-		if ( jQuery.isEmptyObject( events ) ) {
-			delete elemData.handle;
-
-			// removeData also checks for emptiness and clears the expando if empty
-			// so use it instead of delete
-			jQuery._removeData( elem, "events" );
-		}
-	},
-
-	trigger: function( event, data, elem, onlyHandlers ) {
-		var handle, ontype, cur,
-			bubbleType, special, tmp, i,
-			eventPath = [ elem || document ],
-			type = core_hasOwn.call( event, "type" ) ? event.type : event,
-			namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
-
-		cur = tmp = elem = elem || document;
-
-		// Don't do events on text and comment nodes
-		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
-			return;
-		}
-
-		// focus/blur morphs to focusin/out; ensure we're not firing them right now
-		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
-			return;
-		}
-
-		if ( type.indexOf(".") >= 0 ) {
-			// Namespaced trigger; create a regexp to match event type in handle()
-			namespaces = type.split(".");
-			type = namespaces.shift();
-			namespaces.sort();
-		}
-		ontype = type.indexOf(":") < 0 && "on" + type;
-
-		// Caller can pass in a jQuery.Event object, Object, or just an event type string
-		event = event[ jQuery.expando ] ?
-			event :
-			new jQuery.Event( type, typeof event === "object" && event );
-
-		event.isTrigger = true;
-		event.namespace = namespaces.join(".");
-		event.namespace_re = event.namespace ?
-			new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
-			null;
-
-		// Clean up the event in case it is being reused
-		event.result = undefined;
-		if ( !event.target ) {
-			event.target = elem;
-		}
-
-		// Clone any incoming data and prepend the event, creating the handler arg list
-		data = data == null ?
-			[ event ] :
-			jQuery.makeArray( data, [ event ] );
-
-		// Allow special events to draw outside the lines
-		special = jQuery.event.special[ type ] || {};
-		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
-			return;
-		}
-
-		// Determine event propagation path in advance, per W3C events spec (#9951)
-		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
-		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
-
-			bubbleType = special.delegateType || type;
-			if ( !rfocusMorph.test( bubbleType + type ) ) {
-				cur = cur.parentNode;
-			}
-			for ( ; cur; cur = cur.parentNode ) {
-				eventPath.push( cur );
-				tmp = cur;
-			}
-
-			// Only add window if we got to document (e.g., not plain obj or detached DOM)
-			if ( tmp === (elem.ownerDocument || document) ) {
-				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
-			}
-		}
-
-		// Fire handlers on the event path
-		i = 0;
-		while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
-
-			event.type = i > 1 ?
-				bubbleType :
-				special.bindType || type;
-
-			// jQuery handler
-			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
-			if ( handle ) {
-				handle.apply( cur, data );
-			}
-
-			// Native handler
-			handle = ontype && cur[ ontype ];
-			if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
-				event.preventDefault();
-			}
-		}
-		event.type = type;
-
-		// If nobody prevented the default action, do it now
-		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
-
-			if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
-				!(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
-
-				// Call a native DOM method on the target with the same name name as the event.
-				// Can't use an .isFunction() check here because IE6/7 fails that test.
-				// Don't do default actions on window, that's where global variables be (#6170)
-				if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
-
-					// Don't re-trigger an onFOO event when we call its FOO() method
-					tmp = elem[ ontype ];
-
-					if ( tmp ) {
-						elem[ ontype ] = null;
-					}
-
-					// Prevent re-triggering of the same event, since we already bubbled it above
-					jQuery.event.triggered = type;
-					try {
-						elem[ type ]();
-					} catch ( e ) {
-						// IE<9 dies on focus/blur to hidden element (#1486,#12518)
-						// only reproducible on winXP IE8 native, not IE9 in IE8 mode
-					}
-					jQuery.event.triggered = undefined;
-
-					if ( tmp ) {
-						elem[ ontype ] = tmp;
-					}
-				}
-			}
-		}
-
-		return event.result;
-	},
-
-	dispatch: function( event ) {
-
-		// Make a writable jQuery.Event from the native event object
-		event = jQuery.event.fix( event );
-
-		var i, ret, handleObj, matched, j,
-			handlerQueue = [],
-			args = core_slice.call( arguments ),
-			handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
-			special = jQuery.event.special[ event.type ] || {};
-
-		// Use the fix-ed jQuery.Event rather than the (read-only) native event
-		args[0] = event;
-		event.delegateTarget = this;
-
-		// Call the preDispatch hook for the mapped type, and let it bail if desired
-		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
-			return;
-		}
-
-		// Determine handlers
-		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
-
-		// Run delegates first; they may want to stop propagation beneath us
-		i = 0;
-		while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
-			event.currentTarget = matched.elem;
-
-			j = 0;
-			while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
-
-				// Triggered event must either 1) have no namespace, or
-				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
-				if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
-
-					event.handleObj = handleObj;
-					event.data = handleObj.data;
-
-					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
-							.apply( matched.elem, args );
-
-					if ( ret !== undefined ) {
-						if ( (event.result = ret) === false ) {
-							event.preventDefault();
-							event.stopPropagation();
-						}
-					}
-				}
-			}
-		}
-
-		// Call the postDispatch hook for the mapped type
-		if ( special.postDispatch ) {
-			special.postDispatch.call( this, event );
-		}
-
-		return event.result;
-	},
-
-	handlers: function( event, handlers ) {
-		var sel, handleObj, matches, i,
-			handlerQueue = [],
-			delegateCount = handlers.delegateCount,
-			cur = event.target;
-
-		// Find delegate handlers
-		// Black-hole SVG <use> instance trees (#13180)
-		// Avoid non-left-click bubbling in Firefox (#3861)
-		if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
-
-			for ( ; cur != this; cur = cur.parentNode || this ) {
-
-				// Don't check non-elements (#13208)
-				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
-				if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
-					matches = [];
-					for ( i = 0; i < delegateCount; i++ ) {
-						handleObj = handlers[ i ];
-
-						// Don't conflict with Object.prototype properties (#13203)
-						sel = handleObj.selector + " ";
-
-						if ( matches[ sel ] === undefined ) {
-							matches[ sel ] = handleObj.needsContext ?
-								jQuery( sel, this ).index( cur ) >= 0 :
-								jQuery.find( sel, this, null, [ cur ] ).length;
-						}
-						if ( matches[ sel ] ) {
-							matches.push( handleObj );
-						}
-					}
-					if ( matches.length ) {
-						handlerQueue.push({ elem: cur, handlers: matches });
-					}
-				}
-			}
-		}
-
-		// Add the remaining (directly-bound) handlers
-		if ( delegateCount < handlers.length ) {
-			handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
-		}
-
-		return handlerQueue;
-	},
-
-	fix: function( event ) {
-		if ( event[ jQuery.expando ] ) {
-			return event;
-		}
-
-		// Create a writable copy of the event object and normalize some properties
-		var i, prop, copy,
-			type = event.type,
-			originalEvent = event,
-			fixHook = this.fixHooks[ type ];
-
-		if ( !fixHook ) {
-			this.fixHooks[ type ] = fixHook =
-				rmouseEvent.test( type ) ? this.mouseHooks :
-				rkeyEvent.test( type ) ? this.keyHooks :
-				{};
-		}
-		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
-
-		event = new jQuery.Event( originalEvent );
-
-		i = copy.length;
-		while ( i-- ) {
-			prop = copy[ i ];
-			event[ prop ] = originalEvent[ prop ];
-		}
-
-		// Support: IE<9
-		// Fix target property (#1925)
-		if ( !event.target ) {
-			event.target = originalEvent.srcElement || document;
-		}
-
-		// Support: Chrome 23+, Safari?
-		// Target should not be a text node (#504, #13143)
-		if ( event.target.nodeType === 3 ) {
-			event.target = event.target.parentNode;
-		}
-
-		// Support: IE<9
-		// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
-		event.metaKey = !!event.metaKey;
-
-		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
-	},
-
-	// Includes some event props shared by KeyEvent and MouseEvent
-	props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
-
-	fixHooks: {},
-
-	keyHooks: {
-		props: "char charCode key keyCode".split(" "),
-		filter: function( event, original ) {
-
-			// Add which for key events
-			if ( event.which == null ) {
-				event.which = original.charCode != null ? original.charCode : original.keyCode;
-			}
-
-			return event;
-		}
-	},
-
-	mouseHooks: {
-		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
-		filter: function( event, original ) {
-			var body, eventDoc, doc,
-				button = original.button,
-				fromElement = original.fromElement;
-
-			// Calculate pageX/Y if missing and clientX/Y available
-			if ( event.pageX == null && original.clientX != null ) {
-				eventDoc = event.target.ownerDocument || document;
-				doc = eventDoc.documentElement;
-				body = eventDoc.body;
-
-				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
-				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
-			}
-
-			// Add relatedTarget, if necessary
-			if ( !event.relatedTarget && fromElement ) {
-				event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
-			}
-
-			// Add which for click: 1 === left; 2 === middle; 3 === right
-			// Note: button is not normalized, so don't use it
-			if ( !event.which && button !== undefined ) {
-				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
-			}
-
-			return event;
-		}
-	},
-
-	special: {
-		load: {
-			// Prevent triggered image.load events from bubbling to window.load
-			noBubble: true
-		},
-		click: {
-			// For checkbox, fire native event so checked state will be right
-			trigger: function() {
-				if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
-					this.click();
-					return false;
-				}
-			}
-		},
-		focus: {
-			// Fire native event if possible so blur/focus sequence is correct
-			trigger: function() {
-				if ( this !== document.activeElement && this.focus ) {
-					try {
-						this.focus();
-						return false;
-					} catch ( e ) {
-						// Support: IE<9
-						// If we error on focus to hidden element (#1486, #12518),
-						// let .trigger() run the handlers
-					}
-				}
-			},
-			delegateType: "focusin"
-		},
-		blur: {
-			trigger: function() {
-				if ( this === document.activeElement && this.blur ) {
-					this.blur();
-					return false;
-				}
-			},
-			delegateType: "focusout"
-		},
-
-		beforeunload: {
-			postDispatch: function( event ) {
-
-				// Even when returnValue equals to undefined Firefox will still show alert
-				if ( event.result !== undefined ) {
-					event.originalEvent.returnValue = event.result;
-				}
-			}
-		}
-	},
-
-	simulate: function( type, elem, event, bubble ) {
-		// Piggyback on a donor event to simulate a different one.
-		// Fake originalEvent to avoid donor's stopPropagation, but if the
-		// simulated event prevents default then we do the same on the donor.
-		var e = jQuery.extend(
-			new jQuery.Event(),
-			event,
-			{ type: type,
-				isSimulated: true,
-				originalEvent: {}
-			}
-		);
-		if ( bubble ) {
-			jQuery.event.trigger( e, null, elem );
-		} else {
-			jQuery.event.dispatch.call( elem, e );
-		}
-		if ( e.isDefaultPrevented() ) {
-			event.preventDefault();
-		}
-	}
-};
-
-jQuery.removeEvent = document.removeEventListener ?
-	function( elem, type, handle ) {
-		if ( elem.removeEventListener ) {
-			elem.removeEventListener( type, handle, false );
-		}
-	} :
-	function( elem, type, handle ) {
-		var name = "on" + type;
-
-		if ( elem.detachEvent ) {
-
-			// #8545, #7054, preventing memory leaks for custom events in IE6-8
-			// detachEvent needed property on element, by name of that event, to properly expose it to GC
-			if ( typeof elem[ name ] === core_strundefined ) {
-				elem[ name ] = null;
-			}
-
-			elem.detachEvent( name, handle );
-		}
-	};
-
-jQuery.Event = function( src, props ) {
-	// Allow instantiation without the 'new' keyword
-	if ( !(this instanceof jQuery.Event) ) {
-		return new jQuery.Event( src, props );
-	}
-
-	// Event object
-	if ( src && src.type ) {
-		this.originalEvent = src;
-		this.type = src.type;
-
-		// Events bubbling up the document may have been marked as prevented
-		// by a handler lower down the tree; reflect the correct value.
-		this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||
-			src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
-
-	// Event type
-	} else {
-		this.type = src;
-	}
-
-	// Put explicitly provided properties onto the event object
-	if ( props ) {
-		jQuery.extend( this, props );
-	}
-
-	// Create a timestamp if incoming event doesn't have one
-	this.timeStamp = src && src.timeStamp || jQuery.now();
-
-	// Mark it as fixed
-	this[ jQuery.expando ] = true;
-};
-
-// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
-// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
-jQuery.Event.prototype = {
-	isDefaultPrevented: returnFalse,
-	isPropagationStopped: returnFalse,
-	isImmediatePropagationStopped: returnFalse,
-
-	preventDefault: function() {
-		var e = this.originalEvent;
-
-		this.isDefaultPrevented = returnTrue;
-		if ( !e ) {
-			return;
-		}
-
-		// If preventDefault exists, run it on the original event
-		if ( e.preventDefault ) {
-			e.preventDefault();
-
-		// Support: IE
-		// Otherwise set the returnValue property of the original event to false
-		} else {
-			e.returnValue = false;
-		}
-	},
-	stopPropagation: function() {
-		var e = this.originalEvent;
-
-		this.isPropagationStopped = returnTrue;
-		if ( !e ) {
-			return;
-		}
-		// If stopPropagation exists, run it on the original event
-		if ( e.stopPropagation ) {
-			e.stopPropagation();
-		}
-
-		// Support: IE
-		// Set the cancelBubble property of the original event to true
-		e.cancelBubble = true;
-	},
-	stopImmediatePropagation: function() {
-		this.isImmediatePropagationStopped = returnTrue;
-		this.stopPropagation();
-	}
-};
-
-// Create mouseenter/leave events using mouseover/out and event-time checks
-jQuery.each({
-	mouseenter: "mouseover",
-	mouseleave: "mouseout"
-}, function( orig, fix ) {
-	jQuery.event.special[ orig ] = {
-		delegateType: fix,
-		bindType: fix,
-
-		handle: function( event ) {
-			var ret,
-				target = this,
-				related = event.relatedTarget,
-				handleObj = event.handleObj;
-
-			// For mousenter/leave call the handler if related is outside the target.
-			// NB: No relatedTarget if the mouse left/entered the browser window
-			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
-				event.type = handleObj.origType;
-				ret = handleObj.handler.apply( this, arguments );
-				event.type = fix;
-			}
-			return ret;
-		}
-	};
-});
-
-// IE submit delegation
-if ( !jQuery.support.submitBubbles ) {
-
-	jQuery.event.special.submit = {
-		setup: function() {
-			// Only need this for delegated form submit events
-			if ( jQuery.nodeName( this, "form" ) ) {
-				return false;
-			}
-
-			// Lazy-add a submit handler when a descendant form may potentially be submitted
-			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
-				// Node name check avoids a VML-related crash in IE (#9807)
-				var elem = e.target,
-					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
-				if ( form && !jQuery._data( form, "submitBubbles" ) ) {
-					jQuery.event.add( form, "submit._submit", function( event ) {
-						event._submit_bubble = true;
-					});
-					jQuery._data( form, "submitBubbles", true );
-				}
-			});
-			// return undefined since we don't need an event listener
-		},
-
-		postDispatch: function( event ) {
-			// If form was submitted by the user, bubble the event up the tree
-			if ( event._submit_bubble ) {
-				delete event._submit_bubble;
-				if ( this.parentNode && !event.isTrigger ) {
-					jQuery.event.simulate( "submit", this.parentNode, event, true );
-				}
-			}
-		},
-
-		teardown: function() {
-			// Only need this for delegated form submit events
-			if ( jQuery.nodeName( this, "form" ) ) {
-				return false;
-			}
-
-			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
-			jQuery.event.remove( this, "._submit" );
-		}
-	};
-}
-
-// IE change delegation and checkbox/radio fix
-if ( !jQuery.support.changeBubbles ) {
-
-	jQuery.event.special.change = {
-
-		setup: function() {
-
-			if ( rformElems.test( this.nodeName ) ) {
-				// IE doesn't fire change on a check/radio until blur; trigger it on click
-				// after a propertychange. Eat the blur-change in special.change.handle.
-				// This still fires onchange a second time for check/radio after blur.
-				if ( this.type === "checkbox" || this.type === "radio" ) {
-					jQuery.event.add( this, "propertychange._change", function( event ) {
-						if ( event.originalEvent.propertyName === "checked" ) {
-							this._just_changed = true;
-						}
-					});
-					jQuery.event.add( this, "click._change", function( event ) {
-						if ( this._just_changed && !event.isTrigger ) {
-							this._just_changed = false;
-						}
-						// Allow triggered, simulated change events (#11500)
-						jQuery.event.simulate( "change", this, event, true );
-					});
-				}
-				return false;
-			}
-			// Delegated event; lazy-add a change handler on descendant inputs
-			jQuery.event.add( this, "beforeactivate._change", function( e ) {
-				var elem = e.target;
-
-				if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
-					jQuery.event.add( elem, "change._change", function( event ) {
-						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
-							jQuery.event.simulate( "change", this.parentNode, event, true );
-						}
-					});
-					jQuery._data( elem, "changeBubbles", true );
-				}
-			});
-		},
-
-		handle: function( event ) {
-			var elem = event.target;
-
-			// Swallow native change events from checkbox/radio, we already triggered them above
-			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
-				return event.handleObj.handler.apply( this, arguments );
-			}
-		},
-
-		teardown: function() {
-			jQuery.event.remove( this, "._change" );
-
-			return !rformElems.test( this.nodeName );
-		}
-	};
-}
-
-// Create "bubbling" focus and blur events
-if ( !jQuery.support.focusinBubbles ) {
-	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
-
-		// Attach a single capturing handler while someone wants focusin/focusout
-		var attaches = 0,
-			handler = function( event ) {
-				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
-			};
-
-		jQuery.event.special[ fix ] = {
-			setup: function() {
-				if ( attaches++ === 0 ) {
-					document.addEventListener( orig, handler, true );
-				}
-			},
-			teardown: function() {
-				if ( --attaches === 0 ) {
-					document.removeEventListener( orig, handler, true );
-				}
-			}
-		};
-	});
-}
-
-jQuery.fn.extend({
-
-	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
-		var type, origFn;
-
-		// Types can be a map of types/handlers
-		if ( typeof types === "object" ) {
-			// ( types-Object, selector, data )
-			if ( typeof selector !== "string" ) {
-				// ( types-Object, data )
-				data = data || selector;
-				selector = undefined;
-			}
-			for ( type in types ) {
-				this.on( type, selector, data, types[ type ], one );
-			}
-			return this;
-		}
-
-		if ( data == null && fn == null ) {
-			// ( types, fn )
-			fn = selector;
-			data = selector = undefined;
-		} else if ( fn == null ) {
-			if ( typeof selector === "string" ) {
-				// ( types, selector, fn )
-				fn = data;
-				data = undefined;
-			} else {
-				// ( types, data, fn )
-				fn = data;
-				data = selector;
-				selector = undefined;
-			}
-		}
-		if ( fn === false ) {
-			fn = returnFalse;
-		} else if ( !fn ) {
-			return this;
-		}
-
-		if ( one === 1 ) {
-			origFn = fn;
-			fn = function( event ) {
-				// Can use an empty set, since event contains the info
-				jQuery().off( event );
-				return origFn.apply( this, arguments );
-			};
-			// Use same guid so caller can remove using origFn
-			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
-		}
-		return this.each( function() {
-			jQuery.event.add( this, types, fn, data, selector );
-		});
-	},
-	one: function( types, selector, data, fn ) {
-		return this.on( types, selector, data, fn, 1 );
-	},
-	off: function( types, selector, fn ) {
-		var handleObj, type;
-		if ( types && types.preventDefault && types.handleObj ) {
-			// ( event )  dispatched jQuery.Event
-			handleObj = types.handleObj;
-			jQuery( types.delegateTarget ).off(
-				handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
-				handleObj.selector,
-				handleObj.handler
-			);
-			return this;
-		}
-		if ( typeof types === "object" ) {
-			// ( types-object [, selector] )
-			for ( type in types ) {
-				this.off( type, selector, types[ type ] );
-			}
-			return this;
-		}
-		if ( selector === false || typeof selector === "function" ) {
-			// ( types [, fn] )
-			fn = selector;
-			selector = undefined;
-		}
-		if ( fn === false ) {
-			fn = returnFalse;
-		}
-		return this.each(function() {
-			jQuery.event.remove( this, types, fn, selector );
-		});
-	},
-
-	bind: function( types, data, fn ) {
-		return this.on( types, null, data, fn );
-	},
-	unbind: function( types, fn ) {
-		return this.off( types, null, fn );
-	},
-
-	delegate: function( selector, types, data, fn ) {
-		return this.on( types, selector, data, fn );
-	},
-	undelegate: function( selector, types, fn ) {
-		// ( namespace ) or ( selector, types [, fn] )
-		return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
-	},
-
-	trigger: function( type, data ) {
-		return this.each(function() {
-			jQuery.event.trigger( type, data, this );
-		});
-	},
-	triggerHandler: function( type, data ) {
-		var elem = this[0];
-		if ( elem ) {
-			return jQuery.event.trigger( type, data, elem, true );
-		}
-	}
-});
-/*!
- * Sizzle CSS Selector Engine
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license
- * http://sizzlejs.com/
- */
-(function( window, undefined ) {
-
-var i,
-	cachedruns,
-	Expr,
-	getText,
-	isXML,
-	compile,
-	hasDuplicate,
-	outermostContext,
-
-	// Local document vars
-	setDocument,
-	document,
-	docElem,
-	documentIsXML,
-	rbuggyQSA,
-	rbuggyMatches,
-	matches,
-	contains,
-	sortOrder,
-
-	// Instance-specific data
-	expando = "sizzle" + -(new Date()),
-	preferredDoc = window.document,
-	support = {},
-	dirruns = 0,
-	done = 0,
-	classCache = createCache(),
-	tokenCache = createCache(),
-	compilerCache = createCache(),
-
-	// General-purpose constants
-	strundefined = typeof undefined,
-	MAX_NEGATIVE = 1 << 31,
-
-	// Array methods
-	arr = [],
-	pop = arr.pop,
-	push = arr.push,
-	slice = arr.slice,
-	// Use a stripped-down indexOf if we can't use a native one
-	indexOf = arr.indexOf || function( elem ) {
-		var i = 0,
-			len = this.length;
-		for ( ; i < len; i++ ) {
-			if ( this[i] === elem ) {
-				return i;
-			}
-		}
-		return -1;
-	},
-
-
-	// Regular expressions
-
-	// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
-	whitespace = "[\\x20\\t\\r\\n\\f]",
-	// http://www.w3.org/TR/css3-syntax/#characters
-	characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
-
-	// Loosely modeled on CSS identifier characters
-	// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
-	// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
-	identifier = characterEncoding.replace( "w", "w#" ),
-
-	// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
-	operators = "([*^$|!~]?=)",
-	attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
-		"*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
-
-	// Prefer arguments quoted,
-	//   then not containing pseudos/brackets,
-	//   then attribute selectors/non-parenthetical expressions,
-	//   then anything else
-	// These preferences are here to reduce the number of selectors
-	//   needing tokenize in the PSEUDO preFilter
-	pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
-
-	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
-	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
-
-	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
-	rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ),
-	rpseudo = new RegExp( pseudos ),
-	ridentifier = new RegExp( "^" + identifier + "$" ),
-
-	matchExpr = {
-		"ID": new RegExp( "^#(" + characterEncoding + ")" ),
-		"CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
-		"NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ),
-		"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
-		"ATTR": new RegExp( "^" + attributes ),
-		"PSEUDO": new RegExp( "^" + pseudos ),
-		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
-			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
-			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
-		// For use in libraries implementing .is()
-		// We use this for POS matching in `select`
-		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
-			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
-	},
-
-	rsibling = /[\x20\t\r\n\f]*[+~]/,
-
-	rnative = /^[^{]+\{\s*\[native code/,
-
-	// Easily-parseable/retrievable ID or TAG or CLASS selectors
-	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
-
-	rinputs = /^(?:input|select|textarea|button)$/i,
-	rheader = /^h\d$/i,
-
-	rescape = /'|\\/g,
-	rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,
-
-	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
-	runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g,
-	funescape = function( _, escaped ) {
-		var high = "0x" + escaped - 0x10000;
-		// NaN means non-codepoint
-		return high !== high ?
-			escaped :
-			// BMP codepoint
-			high < 0 ?
-				String.fromCharCode( high + 0x10000 ) :
-				// Supplemental Plane codepoint (surrogate pair)
-				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
-	};
-
-// Use a stripped-down slice if we can't use a native one
-try {
-	slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;
-} catch ( e ) {
-	slice = function( i ) {
-		var elem,
-			results = [];
-		while ( (elem = this[i++]) ) {
-			results.push( elem );
-		}
-		return results;
-	};
-}
-
-/**
- * For feature detection
- * @param {Function} fn The function to test for native support
- */
-function isNative( fn ) {
-	return rnative.test( fn + "" );
-}
-
-/**
- * Create key-value caches of limited size
- * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
- *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
- *	deleting the oldest entry
- */
-function createCache() {
-	var cache,
-		keys = [];
-
-	return (cache = function( key, value ) {
-		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
-		if ( keys.push( key += " " ) > Expr.cacheLength ) {
-			// Only keep the most recent entries
-			delete cache[ keys.shift() ];
-		}
-		return (cache[ key ] = value);
-	});
-}
-
-/**
- * Mark a function for special use by Sizzle
- * @param {Function} fn The function to mark
- */
-function markFunction( fn ) {
-	fn[ expando ] = true;
-	return fn;
-}
-
-/**
- * Support testing using an element
- * @param {Function} fn Passed the created div and expects a boolean result
- */
-function assert( fn ) {
-	var div = document.createElement("div");
-
-	try {
-		return fn( div );
-	} catch (e) {
-		return false;
-	} finally {
-		// release memory in IE
-		div = null;
-	}
-}
-
-function Sizzle( selector, context, results, seed ) {
-	var match, elem, m, nodeType,
-		// QSA vars
-		i, groups, old, nid, newContext, newSelector;
-
-	if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
-		setDocument( context );
-	}
-
-	context = context || document;
-	results = results || [];
-
-	if ( !selector || typeof selector !== "string" ) {
-		return results;
-	}
-
-	if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
-		return [];
-	}
-
-	if ( !documentIsXML && !seed ) {
-
-		// Shortcuts
-		if ( (match = rquickExpr.exec( selector )) ) {
-			// Speed-up: Sizzle("#ID")
-			if ( (m = match[1]) ) {
-				if ( nodeType === 9 ) {
-					elem = context.getElementById( m );
-					// Check parentNode to catch when Blackberry 4.6 returns
-					// nodes that are no longer in the document #6963
-					if ( elem && elem.parentNode ) {
-						// Handle the case where IE, Opera, and Webkit return items
-						// by name instead of ID
-						if ( elem.id === m ) {
-							results.push( elem );
-							return results;
-						}
-					} else {
-						return results;
-					}
-				} else {
-					// Context is not a document
-					if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
-						contains( context, elem ) && elem.id === m ) {
-						results.push( elem );
-						return results;
-					}
-				}
-
-			// Speed-up: Sizzle("TAG")
-			} else if ( match[2] ) {
-				push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );
-				return results;
-
-			// Speed-up: Sizzle(".CLASS")
-			} else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {
-				push.apply( results, slice.call(context.getElementsByClassName( m ), 0) );
-				return results;
-			}
-		}
-
-		// QSA path
-		if ( support.qsa && !rbuggyQSA.test(selector) ) {
-			old = true;
-			nid = expando;
-			newContext = context;
-			newSelector = nodeType === 9 && selector;
-
-			// qSA works strangely on Element-rooted queries
-			// We can work around this by specifying an extra ID on the root
-			// and working up from there (Thanks to Andrew Dupont for the technique)
-			// IE 8 doesn't work on object elements
-			if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
-				groups = tokenize( selector );
-
-				if ( (old = context.getAttribute("id")) ) {
-					nid = old.replace( rescape, "\\$&" );
-				} else {
-					context.setAttribute( "id", nid );
-				}
-				nid = "[id='" + nid + "'] ";
-
-				i = groups.length;
-				while ( i-- ) {
-					groups[i] = nid + toSelector( groups[i] );
-				}
-				newContext = rsibling.test( selector ) && context.parentNode || context;
-				newSelector = groups.join(",");
-			}
-
-			if ( newSelector ) {
-				try {
-					push.apply( results, slice.call( newContext.querySelectorAll(
-						newSelector
-					), 0 ) );
-					return results;
-				} catch(qsaError) {
-				} finally {
-					if ( !old ) {
-						context.removeAttribute("id");
-					}
-				}
-			}
-		}
-	}
-
-	// All others
-	return select( selector.replace( rtrim, "$1" ), context, results, seed );
-}
-
-/**
- * Detect xml
- * @param {Element|Object} elem An element or a document
- */
-isXML = Sizzle.isXML = function( elem ) {
-	// documentElement is verified for cases where it doesn't yet exist
-	// (such as loading iframes in IE - #4833)
-	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
-	return documentElement ? documentElement.nodeName !== "HTML" : false;
-};
-
-/**
- * Sets document-related variables once based on the current document
- * @param {Element|Object} [doc] An element or document object to use to set the document
- * @returns {Object} Returns the current document
- */
-setDocument = Sizzle.setDocument = function( node ) {
-	var doc = node ? node.ownerDocument || node : preferredDoc;
-
-	// If no document and documentElement is available, return
-	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
-		return document;
-	}
-
-	// Set our document
-	document = doc;
-	docElem = doc.documentElement;
-
-	// Support tests
-	documentIsXML = isXML( doc );
-
-	// Check if getElementsByTagName("*") returns only elements
-	support.tagNameNoComments = assert(function( div ) {
-		div.appendChild( doc.createComment("") );
-		return !div.getElementsByTagName("*").length;
-	});
-
-	// Check if attributes should be retrieved by attribute nodes
-	support.attributes = assert(function( div ) {
-		div.innerHTML = "<select></select>";
-		var type = typeof div.lastChild.getAttribute("multiple");
-		// IE8 returns a string for some attributes even when not present
-		return type !== "boolean" && type !== "string";
-	});
-
-	// Check if getElementsByClassName can be trusted
-	support.getByClassName = assert(function( div ) {
-		// Opera can't find a second classname (in 9.6)
-		div.innerHTML = "<div class='hidden e'></div><div class='hidden'></div>";
-		if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) {
-			return false;
-		}
-
-		// Safari 3.2 caches class attributes and doesn't catch changes
-		div.lastChild.className = "e";
-		return div.getElementsByClassName("e").length === 2;
-	});
-
-	// Check if getElementById returns elements by name
-	// Check if getElementsByName privileges form controls or returns elements by ID
-	support.getByName = assert(function( div ) {
-		// Inject content
-		div.id = expando + 0;
-		div.innerHTML = "<a name='" + expando + "'></a><div name='" + expando + "'></div>";
-		docElem.insertBefore( div, docElem.firstChild );
-
-		// Test
-		var pass = doc.getElementsByName &&
-			// buggy browsers will return fewer than the correct 2
-			doc.getElementsByName( expando ).length === 2 +
-			// buggy browsers will return more than the correct 0
-			doc.getElementsByName( expando + 0 ).length;
-		support.getIdNotName = !doc.getElementById( expando );
-
-		// Cleanup
-		docElem.removeChild( div );
-
-		return pass;
-	});
-
-	// IE6/7 return modified attributes
-	Expr.attrHandle = assert(function( div ) {
-		div.innerHTML = "<a href='#'></a>";
-		return div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&
-			div.firstChild.getAttribute("href") === "#";
-	}) ?
-		{} :
-		{
-			"href": function( elem ) {
-				return elem.getAttribute( "href", 2 );
-			},
-			"type": function( elem ) {
-				return elem.getAttribute("type");
-			}
-		};
-
-	// ID find and filter
-	if ( support.getIdNotName ) {
-		Expr.find["ID"] = function( id, context ) {
-			if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
-				var m = context.getElementById( id );
-				// Check parentNode to catch when Blackberry 4.6 returns
-				// nodes that are no longer in the document #6963
-				return m && m.parentNode ? [m] : [];
-			}
-		};
-		Expr.filter["ID"] = function( id ) {
-			var attrId = id.replace( runescape, funescape );
-			return function( elem ) {
-				return elem.getAttribute("id") === attrId;
-			};
-		};
-	} else {
-		Expr.find["ID"] = function( id, context ) {
-			if ( typeof context.getElementById !== strundefined && !documentIsXML ) {
-				var m = context.getElementById( id );
-
-				return m ?
-					m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ?
-						[m] :
-						undefined :
-					[];
-			}
-		};
-		Expr.filter["ID"] =  function( id ) {
-			var attrId = id.replace( runescape, funescape );
-			return function( elem ) {
-				var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
-				return node && node.value === attrId;
-			};
-		};
-	}
-
-	// Tag
-	Expr.find["TAG"] = support.tagNameNoComments ?
-		function( tag, context ) {
-			if ( typeof context.getElementsByTagName !== strundefined ) {
-				return context.getElementsByTagName( tag );
-			}
-		} :
-		function( tag, context ) {
-			var elem,
-				tmp = [],
-				i = 0,
-				results = context.getElementsByTagName( tag );
-
-			// Filter out possible comments
-			if ( tag === "*" ) {
-				while ( (elem = results[i++]) ) {
-					if ( elem.nodeType === 1 ) {
-						tmp.push( elem );
-					}
-				}
-
-				return tmp;
-			}
-			return results;
-		};
-
-	// Name
-	Expr.find["NAME"] = support.getByName && function( tag, context ) {
-		if ( typeof context.getElementsByName !== strundefined ) {
-			return context.getElementsByName( name );
-		}
-	};
-
-	// Class
-	Expr.find["CLASS"] = support.getByClassName && function( className, context ) {
-		if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {
-			return context.getElementsByClassName( className );
-		}
-	};
-
-	// QSA and matchesSelector support
-
-	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
-	rbuggyMatches = [];
-
-	// qSa(:focus) reports false when true (Chrome 21),
-	// no need to also add to buggyMatches since matches checks buggyQSA
-	// A support test would require too much code (would include document ready)
-	rbuggyQSA = [ ":focus" ];
-
-	if ( (support.qsa = isNative(doc.querySelectorAll)) ) {
-		// Build QSA regex
-		// Regex strategy adopted from Diego Perini
-		assert(function( div ) {
-			// Select is set to empty string on purpose
-			// This is to test IE's treatment of not explictly
-			// setting a boolean content attribute,
-			// since its presence should be enough
-			// http://bugs.jquery.com/ticket/12359
-			div.innerHTML = "<select><option selected=''></option></select>";
-
-			// IE8 - Some boolean attributes are not treated correctly
-			if ( !div.querySelectorAll("[selected]").length ) {
-				rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" );
-			}
-
-			// Webkit/Opera - :checked should return selected option elements
-			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
-			// IE8 throws error here and will not see later tests
-			if ( !div.querySelectorAll(":checked").length ) {
-				rbuggyQSA.push(":checked");
-			}
-		});
-
-		assert(function( div ) {
-
-			// Opera 10-12/IE8 - ^= $= *= and empty values
-			// Should not select anything
-			div.innerHTML = "<input type='hidden' i=''/>";
-			if ( div.querySelectorAll("[i^='']").length ) {
-				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" );
-			}
-
-			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
-			// IE8 throws error here and will not see later tests
-			if ( !div.querySelectorAll(":enabled").length ) {
-				rbuggyQSA.push( ":enabled", ":disabled" );
-			}
-
-			// Opera 10-11 does not throw on post-comma invalid pseudos
-			div.querySelectorAll("*,:x");
-			rbuggyQSA.push(",.*:");
-		});
-	}
-
-	if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||
-		docElem.mozMatchesSelector ||
-		docElem.webkitMatchesSelector ||
-		docElem.oMatchesSelector ||
-		docElem.msMatchesSelector) )) ) {
-
-		assert(function( div ) {
-			// Check to see if it's possible to do matchesSelector
-			// on a disconnected node (IE 9)
-			support.disconnectedMatch = matches.call( div, "div" );
-
-			// This should fail with an exception
-			// Gecko does not error, returns false instead
-			matches.call( div, "[s!='']:x" );
-			rbuggyMatches.push( "!=", pseudos );
-		});
-	}
-
-	rbuggyQSA = new RegExp( rbuggyQSA.join("|") );
-	rbuggyMatches = new RegExp( rbuggyMatches.join("|") );
-
-	// Element contains another
-	// Purposefully does not implement inclusive descendent
-	// As in, an element does not contain itself
-	contains = isNative(docElem.contains) || docElem.compareDocumentPosition ?
-		function( a, b ) {
-			var adown = a.nodeType === 9 ? a.documentElement : a,
-				bup = b && b.parentNode;
-			return a === bup || !!( bup && bup.nodeType === 1 && (
-				adown.contains ?
-					adown.contains( bup ) :
-					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
-			));
-		} :
-		function( a, b ) {
-			if ( b ) {
-				while ( (b = b.parentNode) ) {
-					if ( b === a ) {
-						return true;
-					}
-				}
-			}
-			return false;
-		};
-
-	// Document order sorting
-	sortOrder = docElem.compareDocumentPosition ?
-	function( a, b ) {
-		var compare;
-
-		if ( a === b ) {
-			hasDuplicate = true;
-			return 0;
-		}
-
-		if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {
-			if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {
-				if ( a === doc || contains( preferredDoc, a ) ) {
-					return -1;
-				}
-				if ( b === doc || contains( preferredDoc, b ) ) {
-					return 1;
-				}
-				return 0;
-			}
-			return compare & 4 ? -1 : 1;
-		}
-
-		return a.compareDocumentPosition ? -1 : 1;
-	} :
-	function( a, b ) {
-		var cur,
-			i = 0,
-			aup = a.parentNode,
-			bup = b.parentNode,
-			ap = [ a ],
-			bp = [ b ];
-
-		// Exit early if the nodes are identical
-		if ( a === b ) {
-			hasDuplicate = true;
-			return 0;
-
-		// Parentless nodes are either documents or disconnected
-		} else if ( !aup || !bup ) {
-			return a === doc ? -1 :
-				b === doc ? 1 :
-				aup ? -1 :
-				bup ? 1 :
-				0;
-
-		// If the nodes are siblings, we can do a quick check
-		} else if ( aup === bup ) {
-			return siblingCheck( a, b );
-		}
-
-		// Otherwise we need full lists of their ancestors for comparison
-		cur = a;
-		while ( (cur = cur.parentNode) ) {
-			ap.unshift( cur );
-		}
-		cur = b;
-		while ( (cur = cur.parentNode) ) {
-			bp.unshift( cur );
-		}
-
-		// Walk down the tree looking for a discrepancy
-		while ( ap[i] === bp[i] ) {
-			i++;
-		}
-
-		return i ?
-			// Do a sibling check if the nodes have a common ancestor
-			siblingCheck( ap[i], bp[i] ) :
-
-			// Otherwise nodes in our document sort first
-			ap[i] === preferredDoc ? -1 :
-			bp[i] === preferredDoc ? 1 :
-			0;
-	};
-
-	// Always assume the presence of duplicates if sort doesn't
-	// pass them to our comparison function (as in Google Chrome).
-	hasDuplicate = false;
-	[0, 0].sort( sortOrder );
-	support.detectDuplicates = hasDuplicate;
-
-	return document;
-};
-
-Sizzle.matches = function( expr, elements ) {
-	return Sizzle( expr, null, null, elements );
-};
-
-Sizzle.matchesSelector = function( elem, expr ) {
-	// Set document vars if needed
-	if ( ( elem.ownerDocument || elem ) !== document ) {
-		setDocument( elem );
-	}
-
-	// Make sure that attribute selectors are quoted
-	expr = expr.replace( rattributeQuotes, "='$1']" );
-
-	// rbuggyQSA always contains :focus, so no need for an existence check
-	if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {
-		try {
-			var ret = matches.call( elem, expr );
-
-			// IE 9's matchesSelector returns false on disconnected nodes
-			if ( ret || support.disconnectedMatch ||
-					// As well, disconnected nodes are said to be in a document
-					// fragment in IE 9
-					elem.document && elem.document.nodeType !== 11 ) {
-				return ret;
-			}
-		} catch(e) {}
-	}
-
-	return Sizzle( expr, document, null, [elem] ).length > 0;
-};
-
-Sizzle.contains = function( context, elem ) {
-	// Set document vars if needed
-	if ( ( context.ownerDocument || context ) !== document ) {
-		setDocument( context );
-	}
-	return contains( context, elem );
-};
-
-Sizzle.attr = function( elem, name ) {
-	var val;
-
-	// Set document vars if needed
-	if ( ( elem.ownerDocument || elem ) !== document ) {
-		setDocument( elem );
-	}
-
-	if ( !documentIsXML ) {
-		name = name.toLowerCase();
-	}
-	if ( (val = Expr.attrHandle[ name ]) ) {
-		return val( elem );
-	}
-	if ( documentIsXML || support.attributes ) {
-		return elem.getAttribute( name );
-	}
-	return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?
-		name :
-		val && val.specified ? val.value : null;
-};
-
-Sizzle.error = function( msg ) {
-	throw new Error( "Syntax error, unrecognized expression: " + msg );
-};
-
-// Document sorting and removing duplicates
-Sizzle.uniqueSort = function( results ) {
-	var elem,
-		duplicates = [],
-		i = 1,
-		j = 0;
-
-	// Unless we *know* we can detect duplicates, assume their presence
-	hasDuplicate = !support.detectDuplicates;
-	results.sort( sortOrder );
-
-	if ( hasDuplicate ) {
-		for ( ; (elem = results[i]); i++ ) {
-			if ( elem === results[ i - 1 ] ) {
-				j = duplicates.push( i );
-			}
-		}
-		while ( j-- ) {
-			results.splice( duplicates[ j ], 1 );
-		}
-	}
-
-	return results;
-};
-
-function siblingCheck( a, b ) {
-	var cur = b && a,
-		diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );
-
-	// Use IE sourceIndex if available on both nodes
-	if ( diff ) {
-		return diff;
-	}
-
-	// Check if b follows a
-	if ( cur ) {
-		while ( (cur = cur.nextSibling) ) {
-			if ( cur === b ) {
-				return -1;
-			}
-		}
-	}
-
-	return a ? 1 : -1;
-}
-
-// Returns a function to use in pseudos for input types
-function createInputPseudo( type ) {
-	return function( elem ) {
-		var name = elem.nodeName.toLowerCase();
-		return name === "input" && elem.type === type;
-	};
-}
-
-// Returns a function to use in pseudos for buttons
-function createButtonPseudo( type ) {
-	return function( elem ) {
-		var name = elem.nodeName.toLowerCase();
-		return (name === "input" || name === "button") && elem.type === type;
-	};
-}
-
-// Returns a function to use in pseudos for positionals
-function createPositionalPseudo( fn ) {
-	return markFunction(function( argument ) {
-		argument = +argument;
-		return markFunction(function( seed, matches ) {
-			var j,
-				matchIndexes = fn( [], seed.length, argument ),
-				i = matchIndexes.length;
-
-			// Match elements found at the specified indexes
-			while ( i-- ) {
-				if ( seed[ (j = matchIndexes[i]) ] ) {
-					seed[j] = !(matches[j] = seed[j]);
-				}
-			}
-		});
-	});
-}
-
-/**
- * Utility function for retrieving the text value of an array of DOM nodes
- * @param {Array|Element} elem
- */
-getText = Sizzle.getText = function( elem ) {
-	var node,
-		ret = "",
-		i = 0,
-		nodeType = elem.nodeType;
-
-	if ( !nodeType ) {
-		// If no nodeType, this is expected to be an array
-		for ( ; (node = elem[i]); i++ ) {
-			// Do not traverse comment nodes
-			ret += getText( node );
-		}
-	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
-		// Use textContent for elements
-		// innerText usage removed for consistency of new lines (see #11153)
-		if ( typeof elem.textContent === "string" ) {
-			return elem.textContent;
-		} else {
-			// Traverse its children
-			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
-				ret += getText( elem );
-			}
-		}
-	} else if ( nodeType === 3 || nodeType === 4 ) {
-		return elem.nodeValue;
-	}
-	// Do not include comment or processing instruction nodes
-
-	return ret;
-};
-
-Expr = Sizzle.selectors = {
-
-	// Can be adjusted by the user
-	cacheLength: 50,
-
-	createPseudo: markFunction,
-
-	match: matchExpr,
-
-	find: {},
-
-	relative: {
-		">": { dir: "parentNode", first: true },
-		" ": { dir: "parentNode" },
-		"+": { dir: "previousSibling", first: true },
-		"~": { dir: "previousSibling" }
-	},
-
-	preFilter: {
-		"ATTR": function( match ) {
-			match[1] = match[1].replace( runescape, funescape );
-
-			// Move the given value to match[3] whether quoted or unquoted
-			match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
-
-			if ( match[2] === "~=" ) {
-				match[3] = " " + match[3] + " ";
-			}
-
-			return match.slice( 0, 4 );
-		},
-
-		"CHILD": function( match ) {
-			/* matches from matchExpr["CHILD"]
-				1 type (only|nth|...)
-				2 what (child|of-type)
-				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
-				4 xn-component of xn+y argument ([+-]?\d*n|)
-				5 sign of xn-component
-				6 x of xn-component
-				7 sign of y-component
-				8 y of y-component
-			*/
-			match[1] = match[1].toLowerCase();
-
-			if ( match[1].slice( 0, 3 ) === "nth" ) {
-				// nth-* requires argument
-				if ( !match[3] ) {
-					Sizzle.error( match[0] );
-				}
-
-				// numeric x and y parameters for Expr.filter.CHILD
-				// remember that false/true cast respectively to 0/1
-				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
-				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
-
-			// other types prohibit arguments
-			} else if ( match[3] ) {
-				Sizzle.error( match[0] );
-			}
-
-			return match;
-		},
-
-		"PSEUDO": function( match ) {
-			var excess,
-				unquoted = !match[5] && match[2];
-
-			if ( matchExpr["CHILD"].test( match[0] ) ) {
-				return null;
-			}
-
-			// Accept quoted arguments as-is
-			if ( match[4] ) {
-				match[2] = match[4];
-
-			// Strip excess characters from unquoted arguments
-			} else if ( unquoted && rpseudo.test( unquoted ) &&
-				// Get excess from tokenize (recursively)
-				(excess = tokenize( unquoted, true )) &&
-				// advance to the next closing parenthesis
-				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
-
-				// excess is a negative index
-				match[0] = match[0].slice( 0, excess );
-				match[2] = unquoted.slice( 0, excess );
-			}
-
-			// Return only captures needed by the pseudo filter method (type and argument)
-			return match.slice( 0, 3 );
-		}
-	},
-
-	filter: {
-
-		"TAG": function( nodeName ) {
-			if ( nodeName === "*" ) {
-				return function() { return true; };
-			}
-
-			nodeName = nodeName.replace( runescape, funescape ).toLowerCase();
-			return function( elem ) {
-				return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
-			};
-		},
-
-		"CLASS": function( className ) {
-			var pattern = classCache[ className + " " ];
-
-			return pattern ||
-				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
-				classCache( className, function( elem ) {
-					return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" );
-				});
-		},
-
-		"ATTR": function( name, operator, check ) {
-			return function( elem ) {
-				var result = Sizzle.attr( elem, name );
-
-				if ( result == null ) {
-					return operator === "!=";
-				}
-				if ( !operator ) {
-					return true;
-				}
-
-				result += "";
-
-				return operator === "=" ? result === check :
-					operator === "!=" ? result !== check :
-					operator === "^=" ? check && result.indexOf( check ) === 0 :
-					operator === "*=" ? check && result.indexOf( check ) > -1 :
-					operator === "$=" ? check && result.slice( -check.length ) === check :
-					operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
-					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
-					false;
-			};
-		},
-
-		"CHILD": function( type, what, argument, first, last ) {
-			var simple = type.slice( 0, 3 ) !== "nth",
-				forward = type.slice( -4 ) !== "last",
-				ofType = what === "of-type";
-
-			return first === 1 && last === 0 ?
-
-				// Shortcut for :nth-*(n)
-				function( elem ) {
-					return !!elem.parentNode;
-				} :
-
-				function( elem, context, xml ) {
-					var cache, outerCache, node, diff, nodeIndex, start,
-						dir = simple !== forward ? "nextSibling" : "previousSibling",
-						parent = elem.parentNode,
-						name = ofType && elem.nodeName.toLowerCase(),
-						useCache = !xml && !ofType;
-
-					if ( parent ) {
-
-						// :(first|last|only)-(child|of-type)
-						if ( simple ) {
-							while ( dir ) {
-								node = elem;
-								while ( (node = node[ dir ]) ) {
-									if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
-										return false;
-									}
-								}
-								// Reverse direction for :only-* (if we haven't yet done so)
-								start = dir = type === "only" && !start && "nextSibling";
-							}
-							return true;
-						}
-
-						start = [ forward ? parent.firstChild : parent.lastChild ];
-
-						// non-xml :nth-child(...) stores cache data on `parent`
-						if ( forward && useCache ) {
-							// Seek `elem` from a previously-cached index
-							outerCache = parent[ expando ] || (parent[ expando ] = {});
-							cache = outerCache[ type ] || [];
-							nodeIndex = cache[0] === dirruns && cache[1];
-							diff = cache[0] === dirruns && cache[2];
-							node = nodeIndex && parent.childNodes[ nodeIndex ];
-
-							while ( (node = ++nodeIndex && node && node[ dir ] ||
-
-								// Fallback to seeking `elem` from the start
-								(diff = nodeIndex = 0) || start.pop()) ) {
-
-								// When found, cache indexes on `parent` and break
-								if ( node.nodeType === 1 && ++diff && node === elem ) {
-									outerCache[ type ] = [ dirruns, nodeIndex, diff ];
-									break;
-								}
-							}
-
-						// Use previously-cached element index if available
-						} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
-							diff = cache[1];
-
-						// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
-						} else {
-							// Use the same loop as above to seek `elem` from the start
-							while ( (node = ++nodeIndex && node && node[ dir ] ||
-								(diff = nodeIndex = 0) || start.pop()) ) {
-
-								if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
-									// Cache the index of each encountered element
-									if ( useCache ) {
-										(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
-									}
-
-									if ( node === elem ) {
-										break;
-									}
-								}
-							}
-						}
-
-						// Incorporate the offset, then check against cycle size
-						diff -= last;
-						return diff === first || ( diff % first === 0 && diff / first >= 0 );
-					}
-				};
-		},
-
-		"PSEUDO": function( pseudo, argument ) {
-			// pseudo-class names are case-insensitive
-			// http://www.w3.org/TR/selectors/#pseudo-classes
-			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
-			// Remember that setFilters inherits from pseudos
-			var args,
-				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
-					Sizzle.error( "unsupported pseudo: " + pseudo );
-
-			// The user may use createPseudo to indicate that
-			// arguments are needed to create the filter function
-			// just as Sizzle does
-			if ( fn[ expando ] ) {
-				return fn( argument );
-			}
-
-			// But maintain support for old signatures
-			if ( fn.length > 1 ) {
-				args = [ pseudo, pseudo, "", argument ];
-				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
-					markFunction(function( seed, matches ) {
-						var idx,
-							matched = fn( seed, argument ),
-							i = matched.length;
-						while ( i-- ) {
-							idx = indexOf.call( seed, matched[i] );
-							seed[ idx ] = !( matches[ idx ] = matched[i] );
-						}
-					}) :
-					function( elem ) {
-						return fn( elem, 0, args );
-					};
-			}
-
-			return fn;
-		}
-	},
-
-	pseudos: {
-		// Potentially complex pseudos
-		"not": markFunction(function( selector ) {
-			// Trim the selector passed to compile
-			// to avoid treating leading and trailing
-			// spaces as combinators
-			var input = [],
-				results = [],
-				matcher = compile( selector.replace( rtrim, "$1" ) );
-
-			return matcher[ expando ] ?
-				markFunction(function( seed, matches, context, xml ) {
-					var elem,
-						unmatched = matcher( seed, null, xml, [] ),
-						i = seed.length;
-
-					// Match elements unmatched by `matcher`
-					while ( i-- ) {
-						if ( (elem = unmatched[i]) ) {
-							seed[i] = !(matches[i] = elem);
-						}
-					}
-				}) :
-				function( elem, context, xml ) {
-					input[0] = elem;
-					matcher( input, null, xml, results );
-					return !results.pop();
-				};
-		}),
-
-		"has": markFunction(function( selector ) {
-			return function( elem ) {
-				return Sizzle( selector, elem ).length > 0;
-			};
-		}),
-
-		"contains": markFunction(function( text ) {
-			return function( elem ) {
-				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
-			};
-		}),
-
-		// "Whether an element is represented by a :lang() selector
-		// is based solely on the element's language value
-		// being equal to the identifier C,
-		// or beginning with the identifier C immediately followed by "-".
-		// The matching of C against the element's language value is performed case-insensitively.
-		// The identifier C does not have to be a valid language name."
-		// http://www.w3.org/TR/selectors/#lang-pseudo
-		"lang": markFunction( function( lang ) {
-			// lang value must be a valid identifider
-			if ( !ridentifier.test(lang || "") ) {
-				Sizzle.error( "unsupported lang: " + lang );
-			}
-			lang = lang.replace( runescape, funescape ).toLowerCase();
-			return function( elem ) {
-				var elemLang;
-				do {
-					if ( (elemLang = documentIsXML ?
-						elem.getAttribute("xml:lang") || elem.getAttribute("lang") :
-						elem.lang) ) {
-
-						elemLang = elemLang.toLowerCase();
-						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
-					}
-				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
-				return false;
-			};
-		}),
-
-		// Miscellaneous
-		"target": function( elem ) {
-			var hash = window.location && window.location.hash;
-			return hash && hash.slice( 1 ) === elem.id;
-		},
-
-		"root": function( elem ) {
-			return elem === docElem;
-		},
-
-		"focus": function( elem ) {
-			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
-		},
-
-		// Boolean properties
-		"enabled": function( elem ) {
-			return elem.disabled === false;
-		},
-
-		"disabled": function( elem ) {
-			return elem.disabled === true;
-		},
-
-		"checked": function( elem ) {
-			// In CSS3, :checked should return both checked and selected elements
-			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
-			var nodeName = elem.nodeName.toLowerCase();
-			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
-		},
-
-		"selected": function( elem ) {
-			// Accessing this property makes selected-by-default
-			// options in Safari work properly
-			if ( elem.parentNode ) {
-				elem.parentNode.selectedIndex;
-			}
-
-			return elem.selected === true;
-		},
-
-		// Contents
-		"empty": function( elem ) {
-			// http://www.w3.org/TR/selectors/#empty-pseudo
-			// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
-			//   not comment, processing instructions, or others
-			// Thanks to Diego Perini for the nodeName shortcut
-			//   Greater than "@" means alpha characters (specifically not starting with "#" or "?")
-			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
-				if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
-					return false;
-				}
-			}
-			return true;
-		},
-
-		"parent": function( elem ) {
-			return !Expr.pseudos["empty"]( elem );
-		},
-
-		// Element/input types
-		"header": function( elem ) {
-			return rheader.test( elem.nodeName );
-		},
-
-		"input": function( elem ) {
-			return rinputs.test( elem.nodeName );
-		},
-
-		"button": function( elem ) {
-			var name = elem.nodeName.toLowerCase();
-			return name === "input" && elem.type === "button" || name === "button";
-		},
-
-		"text": function( elem ) {
-			var attr;
-			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
-			// use getAttribute instead to test this case
-			return elem.nodeName.toLowerCase() === "input" &&
-				elem.type === "text" &&
-				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
-		},
-
-		// Position-in-collection
-		"first": createPositionalPseudo(function() {
-			return [ 0 ];
-		}),
-
-		"last": createPositionalPseudo(function( matchIndexes, length ) {
-			return [ length - 1 ];
-		}),
-
-		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
-			return [ argument < 0 ? argument + length : argument ];
-		}),
-
-		"even": createPositionalPseudo(function( matchIndexes, length ) {
-			var i = 0;
-			for ( ; i < length; i += 2 ) {
-				matchIndexes.push( i );
-			}
-			return matchIndexes;
-		}),
-
-		"odd": createPositionalPseudo(function( matchIndexes, length ) {
-			var i = 1;
-			for ( ; i < length; i += 2 ) {
-				matchIndexes.push( i );
-			}
-			return matchIndexes;
-		}),
-
-		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
-			var i = argument < 0 ? argument + length : argument;
-			for ( ; --i >= 0; ) {
-				matchIndexes.push( i );
-			}
-			return matchIndexes;
-		}),
-
-		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
-			var i = argument < 0 ? argument + length : argument;
-			for ( ; ++i < length; ) {
-				matchIndexes.push( i );
-			}
-			return matchIndexes;
-		})
-	}
-};
-
-// Add button/input type pseudos
-for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
-	Expr.pseudos[ i ] = createInputPseudo( i );
-}
-for ( i in { submit: true, reset: true } ) {
-	Expr.pseudos[ i ] = createButtonPseudo( i );
-}
-
-function tokenize( selector, parseOnly ) {
-	var matched, match, tokens, type,
-		soFar, groups, preFilters,
-		cached = tokenCache[ selector + " " ];
-
-	if ( cached ) {
-		return parseOnly ? 0 : cached.slice( 0 );
-	}
-
-	soFar = selector;
-	groups = [];
-	preFilters = Expr.preFilter;
-
-	while ( soFar ) {
-
-		// Comma and first run
-		if ( !matched || (match = rcomma.exec( soFar )) ) {
-			if ( match ) {
-				// Don't consume trailing commas as valid
-				soFar = soFar.slice( match[0].length ) || soFar;
-			}
-			groups.push( tokens = [] );
-		}
-
-		matched = false;
-
-		// Combinators
-		if ( (match = rcombinators.exec( soFar )) ) {
-			matched = match.shift();
-			tokens.push( {
-				value: matched,
-				// Cast descendant combinators to space
-				type: match[0].replace( rtrim, " " )
-			} );
-			soFar = soFar.slice( matched.length );
-		}
-
-		// Filters
-		for ( type in Expr.filter ) {
-			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
-				(match = preFilters[ type ]( match ))) ) {
-				matched = match.shift();
-				tokens.push( {
-					value: matched,
-					type: type,
-					matches: match
-				} );
-				soFar = soFar.slice( matched.length );
-			}
-		}
-
-		if ( !matched ) {
-			break;
-		}
-	}
-
-	// Return the length of the invalid excess
-	// if we're just parsing
-	// Otherwise, throw an error or return tokens
-	return parseOnly ?
-		soFar.length :
-		soFar ?
-			Sizzle.error( selector ) :
-			// Cache the tokens
-			tokenCache( selector, groups ).slice( 0 );
-}
-
-function toSelector( tokens ) {
-	var i = 0,
-		len = tokens.length,
-		selector = "";
-	for ( ; i < len; i++ ) {
-		selector += tokens[i].value;
-	}
-	return selector;
-}
-
-function addCombinator( matcher, combinator, base ) {
-	var dir = combinator.dir,
-		checkNonElements = base && dir === "parentNode",
-		doneName = done++;
-
-	return combinator.first ?
-		// Check against closest ancestor/preceding element
-		function( elem, context, xml ) {
-			while ( (elem = elem[ dir ]) ) {
-				if ( elem.nodeType === 1 || checkNonElements ) {
-					return matcher( elem, context, xml );
-				}
-			}
-		} :
-
-		// Check against all ancestor/preceding elements
-		function( elem, context, xml ) {
-			var data, cache, outerCache,
-				dirkey = dirruns + " " + doneName;
-
-			// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
-			if ( xml ) {
-				while ( (elem = elem[ dir ]) ) {
-					if ( elem.nodeType === 1 || checkNonElements ) {
-						if ( matcher( elem, context, xml ) ) {
-							return true;
-						}
-					}
-				}
-			} else {
-				while ( (elem = elem[ dir ]) ) {
-					if ( elem.nodeType === 1 || checkNonElements ) {
-						outerCache = elem[ expando ] || (elem[ expando ] = {});
-						if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
-							if ( (data = cache[1]) === true || data === cachedruns ) {
-								return data === true;
-							}
-						} else {
-							cache = outerCache[ dir ] = [ dirkey ];
-							cache[1] = matcher( elem, context, xml ) || cachedruns;
-							if ( cache[1] === true ) {
-								return true;
-							}
-						}
-					}
-				}
-			}
-		};
-}
-
-function elementMatcher( matchers ) {
-	return matchers.length > 1 ?
-		function( elem, context, xml ) {
-			var i = matchers.length;
-			while ( i-- ) {
-				if ( !matchers[i]( elem, context, xml ) ) {
-					return false;
-				}
-			}
-			return true;
-		} :
-		matchers[0];
-}
-
-function condense( unmatched, map, filter, context, xml ) {
-	var elem,
-		newUnmatched = [],
-		i = 0,
-		len = unmatched.length,
-		mapped = map != null;
-
-	for ( ; i < len; i++ ) {
-		if ( (elem = unmatched[i]) ) {
-			if ( !filter || filter( elem, context, xml ) ) {
-				newUnmatched.push( elem );
-				if ( mapped ) {
-					map.push( i );
-				}
-			}
-		}
-	}
-
-	return newUnmatched;
-}
-
-function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
-	if ( postFilter && !postFilter[ expando ] ) {
-		postFilter = setMatcher( postFilter );
-	}
-	if ( postFinder && !postFinder[ expando ] ) {
-		postFinder = setMatcher( postFinder, postSelector );
-	}
-	return markFunction(function( seed, results, context, xml ) {
-		var temp, i, elem,
-			preMap = [],
-			postMap = [],
-			preexisting = results.length,
-
-			// Get initial elements from seed or context
-			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
-
-			// Prefilter to get matcher input, preserving a map for seed-results synchronization
-			matcherIn = preFilter && ( seed || !selector ) ?
-				condense( elems, preMap, preFilter, context, xml ) :
-				elems,
-
-			matcherOut = matcher ?
-				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
-				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
-
-					// ...intermediate processing is necessary
-					[] :
-
-					// ...otherwise use results directly
-					results :
-				matcherIn;
-
-		// Find primary matches
-		if ( matcher ) {
-			matcher( matcherIn, matcherOut, context, xml );
-		}
-
-		// Apply postFilter
-		if ( postFilter ) {
-			temp = condense( matcherOut, postMap );
-			postFilter( temp, [], context, xml );
-
-			// Un-match failing elements by moving them back to matcherIn
-			i = temp.length;
-			while ( i-- ) {
-				if ( (elem = temp[i]) ) {
-					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
-				}
-			}
-		}
-
-		if ( seed ) {
-			if ( postFinder || preFilter ) {
-				if ( postFinder ) {
-					// Get the final matcherOut by condensing this intermediate into postFinder contexts
-					temp = [];
-					i = matcherOut.length;
-					while ( i-- ) {
-						if ( (elem = matcherOut[i]) ) {
-							// Restore matcherIn since elem is not yet a final match
-							temp.push( (matcherIn[i] = elem) );
-						}
-					}
-					postFinder( null, (matcherOut = []), temp, xml );
-				}
-
-				// Move matched elements from seed to results to keep them synchronized
-				i = matcherOut.length;
-				while ( i-- ) {
-					if ( (elem = matcherOut[i]) &&
-						(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
-
-						seed[temp] = !(results[temp] = elem);
-					}
-				}
-			}
-
-		// Add elements to results, through postFinder if defined
-		} else {
-			matcherOut = condense(
-				matcherOut === results ?
-					matcherOut.splice( preexisting, matcherOut.length ) :
-					matcherOut
-			);
-			if ( postFinder ) {
-				postFinder( null, results, matcherOut, xml );
-			} else {
-				push.apply( results, matcherOut );
-			}
-		}
-	});
-}
-
-function matcherFromTokens( tokens ) {
-	var checkContext, matcher, j,
-		len = tokens.length,
-		leadingRelative = Expr.relative[ tokens[0].type ],
-		implicitRelative = leadingRelative || Expr.relative[" "],
-		i = leadingRelative ? 1 : 0,
-
-		// The foundational matcher ensures that elements are reachable from top-level context(s)
-		matchContext = addCombinator( function( elem ) {
-			return elem === checkContext;
-		}, implicitRelative, true ),
-		matchAnyContext = addCombinator( function( elem ) {
-			return indexOf.call( checkContext, elem ) > -1;
-		}, implicitRelative, true ),
-		matchers = [ function( elem, context, xml ) {
-			return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
-				(checkContext = context).nodeType ?
-					matchContext( elem, context, xml ) :
-					matchAnyContext( elem, context, xml ) );
-		} ];
-
-	for ( ; i < len; i++ ) {
-		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
-			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
-		} else {
-			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
-
-			// Return special upon seeing a positional matcher
-			if ( matcher[ expando ] ) {
-				// Find the next relative operator (if any) for proper handling
-				j = ++i;
-				for ( ; j < len; j++ ) {
-					if ( Expr.relative[ tokens[j].type ] ) {
-						break;
-					}
-				}
-				return setMatcher(
-					i > 1 && elementMatcher( matchers ),
-					i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ),
-					matcher,
-					i < j && matcherFromTokens( tokens.slice( i, j ) ),
-					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
-					j < len && toSelector( tokens )
-				);
-			}
-			matchers.push( matcher );
-		}
-	}
-
-	return elementMatcher( matchers );
-}
-
-function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
-	// A counter to specify which element is currently being matched
-	var matcherCachedRuns = 0,
-		bySet = setMatchers.length > 0,
-		byElement = elementMatchers.length > 0,
-		superMatcher = function( seed, context, xml, results, expandContext ) {
-			var elem, j, matcher,
-				setMatched = [],
-				matchedCount = 0,
-				i = "0",
-				unmatched = seed && [],
-				outermost = expandContext != null,
-				contextBackup = outermostContext,
-				// We must always have either seed elements or context
-				elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
-				// Use integer dirruns iff this is the outermost matcher
-				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
-
-			if ( outermost ) {
-				outermostContext = context !== document && context;
-				cachedruns = matcherCachedRuns;
-			}
-
-			// Add elements passing elementMatchers directly to results
-			// Keep `i` a string if there are no elements so `matchedCount` will be "00" below
-			for ( ; (elem = elems[i]) != null; i++ ) {
-				if ( byElement && elem ) {
-					j = 0;
-					while ( (matcher = elementMatchers[j++]) ) {
-						if ( matcher( elem, context, xml ) ) {
-							results.push( elem );
-							break;
-						}
-					}
-					if ( outermost ) {
-						dirruns = dirrunsUnique;
-						cachedruns = ++matcherCachedRuns;
-					}
-				}
-
-				// Track unmatched elements for set filters
-				if ( bySet ) {
-					// They will have gone through all possible matchers
-					if ( (elem = !matcher && elem) ) {
-						matchedCount--;
-					}
-
-					// Lengthen the array for every element, matched or not
-					if ( seed ) {
-						unmatched.push( elem );
-					}
-				}
-			}
-
-			// Apply set filters to unmatched elements
-			matchedCount += i;
-			if ( bySet && i !== matchedCount ) {
-				j = 0;
-				while ( (matcher = setMatchers[j++]) ) {
-					matcher( unmatched, setMatched, context, xml );
-				}
-
-				if ( seed ) {
-					// Reintegrate element matches to eliminate the need for sorting
-					if ( matchedCount > 0 ) {
-						while ( i-- ) {
-							if ( !(unmatched[i] || setMatched[i]) ) {
-								setMatched[i] = pop.call( results );
-							}
-						}
-					}
-
-					// Discard index placeholder values to get only actual matches
-					setMatched = condense( setMatched );
-				}
-
-				// Add matches to results
-				push.apply( results, setMatched );
-
-				// Seedless set matches succeeding multiple successful matchers stipulate sorting
-				if ( outermost && !seed && setMatched.length > 0 &&
-					( matchedCount + setMatchers.length ) > 1 ) {
-
-					Sizzle.uniqueSort( results );
-				}
-			}
-
-			// Override manipulation of globals by nested matchers
-			if ( outermost ) {
-				dirruns = dirrunsUnique;
-				outermostContext = contextBackup;
-			}
-
-			return unmatched;
-		};
-
-	return bySet ?
-		markFunction( superMatcher ) :
-		superMatcher;
-}
-
-compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
-	var i,
-		setMatchers = [],
-		elementMatchers = [],
-		cached = compilerCache[ selector + " " ];
-
-	if ( !cached ) {
-		// Generate a function of recursive functions that can be used to check each element
-		if ( !group ) {
-			group = tokenize( selector );
-		}
-		i = group.length;
-		while ( i-- ) {
-			cached = matcherFromTokens( group[i] );
-			if ( cached[ expando ] ) {
-				setMatchers.push( cached );
-			} else {
-				elementMatchers.push( cached );
-			}
-		}
-
-		// Cache the compiled function
-		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
-	}
-	return cached;
-};
-
-function multipleContexts( selector, contexts, results ) {
-	var i = 0,
-		len = contexts.length;
-	for ( ; i < len; i++ ) {
-		Sizzle( selector, contexts[i], results );
-	}
-	return results;
-}
-
-function select( selector, context, results, seed ) {
-	var i, tokens, token, type, find,
-		match = tokenize( selector );
-
-	if ( !seed ) {
-		// Try to minimize operations if there is only one group
-		if ( match.length === 1 ) {
-
-			// Take a shortcut and set the context if the root selector is an ID
-			tokens = match[0] = match[0].slice( 0 );
-			if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
-					context.nodeType === 9 && !documentIsXML &&
-					Expr.relative[ tokens[1].type ] ) {
-
-				context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0];
-				if ( !context ) {
-					return results;
-				}
-
-				selector = selector.slice( tokens.shift().value.length );
-			}
-
-			// Fetch a seed set for right-to-left matching
-			i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
-			while ( i-- ) {
-				token = tokens[i];
-
-				// Abort if we hit a combinator
-				if ( Expr.relative[ (type = token.type) ] ) {
-					break;
-				}
-				if ( (find = Expr.find[ type ]) ) {
-					// Search, expanding context for leading sibling combinators
-					if ( (seed = find(
-						token.matches[0].replace( runescape, funescape ),
-						rsibling.test( tokens[0].type ) && context.parentNode || context
-					)) ) {
-
-						// If seed is empty or no tokens remain, we can return early
-						tokens.splice( i, 1 );
-						selector = seed.length && toSelector( tokens );
-						if ( !selector ) {
-							push.apply( results, slice.call( seed, 0 ) );
-							return results;
-						}
-
-						break;
-					}
-				}
-			}
-		}
-	}
-
-	// Compile and execute a filtering function
-	// Provide `match` to avoid retokenization if we modified the selector above
-	compile( selector, match )(
-		seed,
-		context,
-		documentIsXML,
-		results,
-		rsibling.test( selector )
-	);
-	return results;
-}
-
-// Deprecated
-Expr.pseudos["nth"] = Expr.pseudos["eq"];
-
-// Easy API for creating new setFilters
-function setFilters() {}
-Expr.filters = setFilters.prototype = Expr.pseudos;
-Expr.setFilters = new setFilters();
-
-// Initialize with the default document
-setDocument();
-
-// Override sizzle attribute retrieval
-Sizzle.attr = jQuery.attr;
-jQuery.find = Sizzle;
-jQuery.expr = Sizzle.selectors;
-jQuery.expr[":"] = jQuery.expr.pseudos;
-jQuery.unique = Sizzle.uniqueSort;
-jQuery.text = Sizzle.getText;
-jQuery.isXMLDoc = Sizzle.isXML;
-jQuery.contains = Sizzle.contains;
-
-
-})( window );
-var runtil = /Until$/,
-	rparentsprev = /^(?:parents|prev(?:Until|All))/,
-	isSimple = /^.[^:#\[\.,]*$/,
-	rneedsContext = jQuery.expr.match.needsContext,
-	// methods guaranteed to produce a unique set when starting from a unique set
-	guaranteedUnique = {
-		children: true,
-		contents: true,
-		next: true,
-		prev: true
-	};
-
-jQuery.fn.extend({
-	find: function( selector ) {
-		var i, ret, self,
-			len = this.length;
-
-		if ( typeof selector !== "string" ) {
-			self = this;
-			return this.pushStack( jQuery( selector ).filter(function() {
-				for ( i = 0; i < len; i++ ) {
-					if ( jQuery.contains( self[ i ], this ) ) {
-						return true;
-					}
-				}
-			}) );
-		}
-
-		ret = [];
-		for ( i = 0; i < len; i++ ) {
-			jQuery.find( selector, this[ i ], ret );
-		}
-
-		// Needed because $( selector, context ) becomes $( context ).find( selector )
-		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
-		ret.selector = ( this.selector ? this.selector + " " : "" ) + selector;
-		return ret;
-	},
-
-	has: function( target ) {
-		var i,
-			targets = jQuery( target, this ),
-			len = targets.length;
-
-		return this.filter(function() {
-			for ( i = 0; i < len; i++ ) {
-				if ( jQuery.contains( this, targets[i] ) ) {
-					return true;
-				}
-			}
-		});
-	},
-
-	not: function( selector ) {
-		return this.pushStack( winnow(this, selector, false) );
-	},
-
-	filter: function( selector ) {
-		return this.pushStack( winnow(this, selector, true) );
-	},
-
-	is: function( selector ) {
-		return !!selector && (
-			typeof selector === "string" ?
-				// If this is a positional/relative selector, check membership in the returned set
-				// so $("p:first").is("p:last") won't return true for a doc with two "p".
-				rneedsContext.test( selector ) ?
-					jQuery( selector, this.context ).index( this[0] ) >= 0 :
-					jQuery.filter( selector, this ).length > 0 :
-				this.filter( selector ).length > 0 );
-	},
-
-	closest: function( selectors, context ) {
-		var cur,
-			i = 0,
-			l = this.length,
-			ret = [],
-			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
-				jQuery( selectors, context || this.context ) :
-				0;
-
-		for ( ; i < l; i++ ) {
-			cur = this[i];
-
-			while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {
-				if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
-					ret.push( cur );
-					break;
-				}
-				cur = cur.parentNode;
-			}
-		}
-
-		return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );
-	},
-
-	// Determine the position of an element within
-	// the matched set of elements
-	index: function( elem ) {
-
-		// No argument, return index in parent
-		if ( !elem ) {
-			return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
-		}
-
-		// index in selector
-		if ( typeof elem === "string" ) {
-			return jQuery.inArray( this[0], jQuery( elem ) );
-		}
-
-		// Locate the position of the desired element
-		return jQuery.inArray(
-			// If it receives a jQuery object, the first element is used
-			elem.jquery ? elem[0] : elem, this );
-	},
-
-	add: function( selector, context ) {
-		var set = typeof selector === "string" ?
-				jQuery( selector, context ) :
-				jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
-			all = jQuery.merge( this.get(), set );
-
-		return this.pushStack( jQuery.unique(all) );
-	},
-
-	addBack: function( selector ) {
-		return this.add( selector == null ?
-			this.prevObject : this.prevObject.filter(selector)
-		);
-	}
-});
-
-jQuery.fn.andSelf = jQuery.fn.addBack;
-
-function sibling( cur, dir ) {
-	do {
-		cur = cur[ dir ];
-	} while ( cur && cur.nodeType !== 1 );
-
-	return cur;
-}
-
-jQuery.each({
-	parent: function( elem ) {
-		var parent = elem.parentNode;
-		return parent && parent.nodeType !== 11 ? parent : null;
-	},
-	parents: function( elem ) {
-		return jQuery.dir( elem, "parentNode" );
-	},
-	parentsUntil: function( elem, i, until ) {
-		return jQuery.dir( elem, "parentNode", until );
-	},
-	next: function( elem ) {
-		return sibling( elem, "nextSibling" );
-	},
-	prev: function( elem ) {
-		return sibling( elem, "previousSibling" );
-	},
-	nextAll: function( elem ) {
-		return jQuery.dir( elem, "nextSibling" );
-	},
-	prevAll: function( elem ) {
-		return jQuery.dir( elem, "previousSibling" );
-	},
-	nextUntil: function( elem, i, until ) {
-		return jQuery.dir( elem, "nextSibling", until );
-	},
-	prevUntil: function( elem, i, until ) {
-		return jQuery.dir( elem, "previousSibling", until );
-	},
-	siblings: function( elem ) {
-		return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
-	},
-	children: function( elem ) {
-		return jQuery.sibling( elem.firstChild );
-	},
-	contents: function( elem ) {
-		return jQuery.nodeName( elem, "iframe" ) ?
-			elem.contentDocument || elem.contentWindow.document :
-			jQuery.merge( [], elem.childNodes );
-	}
-}, function( name, fn ) {
-	jQuery.fn[ name ] = function( until, selector ) {
-		var ret = jQuery.map( this, fn, until );
-
-		if ( !runtil.test( name ) ) {
-			selector = until;
-		}
-
-		if ( selector && typeof selector === "string" ) {
-			ret = jQuery.filter( selector, ret );
-		}
-
-		ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
-
-		if ( this.length > 1 && rparentsprev.test( name ) ) {
-			ret = ret.reverse();
-		}
-
-		return this.pushStack( ret );
-	};
-});
-
-jQuery.extend({
-	filter: function( expr, elems, not ) {
-		if ( not ) {
-			expr = ":not(" + expr + ")";
-		}
-
-		return elems.length === 1 ?
-			jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
-			jQuery.find.matches(expr, elems);
-	},
-
-	dir: function( elem, dir, until ) {
-		var matched = [],
-			cur = elem[ dir ];
-
-		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
-			if ( cur.nodeType === 1 ) {
-				matched.push( cur );
-			}
-			cur = cur[dir];
-		}
-		return matched;
-	},
-
-	sibling: function( n, elem ) {
-		var r = [];
-
-		for ( ; n; n = n.nextSibling ) {
-			if ( n.nodeType === 1 && n !== elem ) {
-				r.push( n );
-			}
-		}
-
-		return r;
-	}
-});
-
-// Implement the identical functionality for filter and not
-function winnow( elements, qualifier, keep ) {
-
-	// Can't pass null or undefined to indexOf in Firefox 4
-	// Set to 0 to skip string check
-	qualifier = qualifier || 0;
-
-	if ( jQuery.isFunction( qualifier ) ) {
-		return jQuery.grep(elements, function( elem, i ) {
-			var retVal = !!qualifier.call( elem, i, elem );
-			return retVal === keep;
-		});
-
-	} else if ( qualifier.nodeType ) {
-		return jQuery.grep(elements, function( elem ) {
-			return ( elem === qualifier ) === keep;
-		});
-
-	} else if ( typeof qualifier === "string" ) {
-		var filtered = jQuery.grep(elements, function( elem ) {
-			return elem.nodeType === 1;
-		});
-
-		if ( isSimple.test( qualifier ) ) {
-			return jQuery.filter(qualifier, filtered, !keep);
-		} else {
-			qualifier = jQuery.filter( qualifier, filtered );
-		}
-	}
-
-	return jQuery.grep(elements, function( elem ) {
-		return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;
-	});
-}
-function createSafeFragment( document ) {
-	var list = nodeNames.split( "|" ),
-		safeFrag = document.createDocumentFragment();
-
-	if ( safeFrag.createElement ) {
-		while ( list.length ) {
-			safeFrag.createElement(
-				list.pop()
-			);
-		}
-	}
-	return safeFrag;
-}
-
-var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
-		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
-	rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
-	rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
-	rleadingWhitespace = /^\s+/,
-	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
-	rtagName = /<([\w:]+)/,
-	rtbody = /<tbody/i,
-	rhtml = /<|&#?\w+;/,
-	rnoInnerhtml = /<(?:script|style|link)/i,
-	manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
-	// checked="checked" or checked
-	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
-	rscriptType = /^$|\/(?:java|ecma)script/i,
-	rscriptTypeMasked = /^true\/(.*)/,
-	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
-
-	// We have to close these tags to support XHTML (#13200)
-	wrapMap = {
-		option: [ 1, "<select multiple='multiple'>", "</select>" ],
-		legend: [ 1, "<fieldset>", "</fieldset>" ],
-		area: [ 1, "<map>", "</map>" ],
-		param: [ 1, "<object>", "</object>" ],
-		thead: [ 1, "<table>", "</table>" ],
-		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
-		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
-		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
-
-		// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
-		// unless wrapped in a div with non-breaking characters in front of it.
-		_default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>"  ]
-	},
-	safeFragment = createSafeFragment( document ),
-	fragmentDiv = safeFragment.appendChild( document.createElement("div") );
-
-wrapMap.optgroup = wrapMap.option;
-wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
-wrapMap.th = wrapMap.td;
-
-jQuery.fn.extend({
-	text: function( value ) {
-		return jQuery.access( this, function( value ) {
-			return value === undefined ?
-				jQuery.text( this ) :
-				this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
-		}, null, value, arguments.length );
-	},
-
-	wrapAll: function( html ) {
-		if ( jQuery.isFunction( html ) ) {
-			return this.each(function(i) {
-				jQuery(this).wrapAll( html.call(this, i) );
-			});
-		}
-
-		if ( this[0] ) {
-			// The elements to wrap the target around
-			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
-
-			if ( this[0].parentNode ) {
-				wrap.insertBefore( this[0] );
-			}
-
-			wrap.map(function() {
-				var elem = this;
-
-				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
-					elem = elem.firstChild;
-				}
-
-				return elem;
-			}).append( this );
-		}
-
-		return this;
-	},
-
-	wrapInner: function( html ) {
-		if ( jQuery.isFunction( html ) ) {
-			return this.each(function(i) {
-				jQuery(this).wrapInner( html.call(this, i) );
-			});
-		}
-
-		return this.each(function() {
-			var self = jQuery( this ),
-				contents = self.contents();
-
-			if ( contents.length ) {
-				contents.wrapAll( html );
-
-			} else {
-				self.append( html );
-			}
-		});
-	},
-
-	wrap: function( html ) {
-		var isFunction = jQuery.isFunction( html );
-
-		return this.each(function(i) {
-			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
-		});
-	},
-
-	unwrap: function() {
-		return this.parent().each(function() {
-			if ( !jQuery.nodeName( this, "body" ) ) {
-				jQuery( this ).replaceWith( this.childNodes );
-			}
-		}).end();
-	},
-
-	append: function() {
-		return this.domManip(arguments, true, function( elem ) {
-			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
-				this.appendChild( elem );
-			}
-		});
-	},
-
-	prepend: function() {
-		return this.domManip(arguments, true, function( elem ) {
-			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
-				this.insertBefore( elem, this.firstChild );
-			}
-		});
-	},
-
-	before: function() {
-		return this.domManip( arguments, false, function( elem ) {
-			if ( this.parentNode ) {
-				this.parentNode.insertBefore( elem, this );
-			}
-		});
-	},
-
-	after: function() {
-		return this.domManip( arguments, false, function( elem ) {
-			if ( this.parentNode ) {
-				this.parentNode.insertBefore( elem, this.nextSibling );
-			}
-		});
-	},
-
-	// keepData is for internal use only--do not document
-	remove: function( selector, keepData ) {
-		var elem,
-			i = 0;
-
-		for ( ; (elem = this[i]) != null; i++ ) {
-			if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {
-				if ( !keepData && elem.nodeType === 1 ) {
-					jQuery.cleanData( getAll( elem ) );
-				}
-
-				if ( elem.parentNode ) {
-					if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
-						setGlobalEval( getAll( elem, "script" ) );
-					}
-					elem.parentNode.removeChild( elem );
-				}
-			}
-		}
-
-		return this;
-	},
-
-	empty: function() {
-		var elem,
-			i = 0;
-
-		for ( ; (elem = this[i]) != null; i++ ) {
-			// Remove element nodes and prevent memory leaks
-			if ( elem.nodeType === 1 ) {
-				jQuery.cleanData( getAll( elem, false ) );
-			}
-
-			// Remove any remaining nodes
-			while ( elem.firstChild ) {
-				elem.removeChild( elem.firstChild );
-			}
-
-			// If this is a select, ensure that it displays empty (#12336)
-			// Support: IE<9
-			if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
-				elem.options.length = 0;
-			}
-		}
-
-		return this;
-	},
-
-	clone: function( dataAndEvents, deepDataAndEvents ) {
-		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
-		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
-
-		return this.map( function () {
-			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
-		});
-	},
-
-	html: function( value ) {
-		return jQuery.access( this, function( value ) {
-			var elem = this[0] || {},
-				i = 0,
-				l = this.length;
-
-			if ( value === undefined ) {
-				return elem.nodeType === 1 ?
-					elem.innerHTML.replace( rinlinejQuery, "" ) :
-					undefined;
-			}
-
-			// See if we can take a shortcut and just use innerHTML
-			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
-				( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&
-				( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
-				!wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) {
-
-				value = value.replace( rxhtmlTag, "<$1></$2>" );
-
-				try {
-					for (; i < l; i++ ) {
-						// Remove element nodes and prevent memory leaks
-						elem = this[i] || {};
-						if ( elem.nodeType === 1 ) {
-							jQuery.cleanData( getAll( elem, false ) );
-							elem.innerHTML = value;
-						}
-					}
-
-					elem = 0;
-
-				// If using innerHTML throws an exception, use the fallback method
-				} catch(e) {}
-			}
-
-			if ( elem ) {
-				this.empty().append( value );
-			}
-		}, null, value, arguments.length );
-	},
-
-	replaceWith: function( value ) {
-		var isFunc = jQuery.isFunction( value );
-
-		// Make sure that the elements are removed from the DOM before they are inserted
-		// this can help fix replacing a parent with child elements
-		if ( !isFunc && typeof value !== "string" ) {
-			value = jQuery( value ).not( this ).detach();
-		}
-
-		return this.domManip( [ value ], true, function( elem ) {
-			var next = this.nextSibling,
-				parent = this.parentNode;
-
-			if ( parent ) {
-				jQuery( this ).remove();
-				parent.insertBefore( elem, next );
-			}
-		});
-	},
-
-	detach: function( selector ) {
-		return this.remove( selector, true );
-	},
-
-	domManip: function( args, table, callback ) {
-
-		// Flatten any nested arrays
-		args = core_concat.apply( [], args );
-
-		var first, node, hasScripts,
-			scripts, doc, fragment,
-			i = 0,
-			l = this.length,
-			set = this,
-			iNoClone = l - 1,
-			value = args[0],
-			isFunction = jQuery.isFunction( value );
-
-		// We can't cloneNode fragments that contain checked, in WebKit
-		if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
-			return this.each(function( index ) {
-				var self = set.eq( index );
-				if ( isFunction ) {
-					args[0] = value.call( this, index, table ? self.html() : undefined );
-				}
-				self.domManip( args, table, callback );
-			});
-		}
-
-		if ( l ) {
-			fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
-			first = fragment.firstChild;
-
-			if ( fragment.childNodes.length === 1 ) {
-				fragment = first;
-			}
-
-			if ( first ) {
-				table = table && jQuery.nodeName( first, "tr" );
-				scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
-				hasScripts = scripts.length;
-
-				// Use the original fragment for the last item instead of the first because it can end up
-				// being emptied incorrectly in certain situations (#8070).
-				for ( ; i < l; i++ ) {
-					node = fragment;
-
-					if ( i !== iNoClone ) {
-						node = jQuery.clone( node, true, true );
-
-						// Keep references to cloned scripts for later restoration
-						if ( hasScripts ) {
-							jQuery.merge( scripts, getAll( node, "script" ) );
-						}
-					}
-
-					callback.call(
-						table && jQuery.nodeName( this[i], "table" ) ?
-							findOrAppend( this[i], "tbody" ) :
-							this[i],
-						node,
-						i
-					);
-				}
-
-				if ( hasScripts ) {
-					doc = scripts[ scripts.length - 1 ].ownerDocument;
-
-					// Reenable scripts
-					jQuery.map( scripts, restoreScript );
-
-					// Evaluate executable scripts on first document insertion
-					for ( i = 0; i < hasScripts; i++ ) {
-						node = scripts[ i ];
-						if ( rscriptType.test( node.type || "" ) &&
-							!jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
-
-							if ( node.src ) {
-								// Hope ajax is available...
-								jQuery.ajax({
-									url: node.src,
-									type: "GET",
-									dataType: "script",
-									async: false,
-									global: false,
-									"throws": true
-								});
-							} else {
-								jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
-							}
-						}
-					}
-				}
-
-				// Fix #11809: Avoid leaking memory
-				fragment = first = null;
-			}
-		}
-
-		return this;
-	}
-});
-
-function findOrAppend( elem, tag ) {
-	return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );
-}
-
-// Replace/restore the type attribute of script elements for safe DOM manipulation
-function disableScript( elem ) {
-	var attr = elem.getAttributeNode("type");
-	elem.type = ( attr && attr.specified ) + "/" + elem.type;
-	return elem;
-}
-function restoreScript( elem ) {
-	var match = rscriptTypeMasked.exec( elem.type );
-	if ( match ) {
-		elem.type = match[1];
-	} else {
-		elem.removeAttribute("type");
-	}
-	return elem;
-}
-
-// Mark scripts as having already been evaluated
-function setGlobalEval( elems, refElements ) {
-	var elem,
-		i = 0;
-	for ( ; (elem = elems[i]) != null; i++ ) {
-		jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
-	}
-}
-
-function cloneCopyEvent( src, dest ) {
-
-	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
-		return;
-	}
-
-	var type, i, l,
-		oldData = jQuery._data( src ),
-		curData = jQuery._data( dest, oldData ),
-		events = oldData.events;
-
-	if ( events ) {
-		delete curData.handle;
-		curData.events = {};
-
-		for ( type in events ) {
-			for ( i = 0, l = events[ type ].length; i < l; i++ ) {
-				jQuery.event.add( dest, type, events[ type ][ i ] );
-			}
-		}
-	}
-
-	// make the cloned public data object a copy from the original
-	if ( curData.data ) {
-		curData.data = jQuery.extend( {}, curData.data );
-	}
-}
-
-function fixCloneNodeIssues( src, dest ) {
-	var nodeName, e, data;
-
-	// We do not need to do anything for non-Elements
-	if ( dest.nodeType !== 1 ) {
-		return;
-	}
-
-	nodeName = dest.nodeName.toLowerCase();
-
-	// IE6-8 copies events bound via attachEvent when using cloneNode.
-	if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {
-		data = jQuery._data( dest );
-
-		for ( e in data.events ) {
-			jQuery.removeEvent( dest, e, data.handle );
-		}
-
-		// Event data gets referenced instead of copied if the expando gets copied too
-		dest.removeAttribute( jQuery.expando );
-	}
-
-	// IE blanks contents when cloning scripts, and tries to evaluate newly-set text
-	if ( nodeName === "script" && dest.text !== src.text ) {
-		disableScript( dest ).text = src.text;
-		restoreScript( dest );
-
-	// IE6-10 improperly clones children of object elements using classid.
-	// IE10 throws NoModificationAllowedError if parent is null, #12132.
-	} else if ( nodeName === "object" ) {
-		if ( dest.parentNode ) {
-			dest.outerHTML = src.outerHTML;
-		}
-
-		// This path appears unavoidable for IE9. When cloning an object
-		// element in IE9, the outerHTML strategy above is not sufficient.
-		// If the src has innerHTML and the destination does not,
-		// copy the src.innerHTML into the dest.innerHTML. #10324
-		if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
-			dest.innerHTML = src.innerHTML;
-		}
-
-	} else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
-		// IE6-8 fails to persist the checked state of a cloned checkbox
-		// or radio button. Worse, IE6-7 fail to give the cloned element
-		// a checked appearance if the defaultChecked value isn't also set
-
-		dest.defaultChecked = dest.checked = src.checked;
-
-		// IE6-7 get confused and end up setting the value of a cloned
-		// checkbox/radio button to an empty string instead of "on"
-		if ( dest.value !== src.value ) {
-			dest.value = src.value;
-		}
-
-	// IE6-8 fails to return the selected option to the default selected
-	// state when cloning options
-	} else if ( nodeName === "option" ) {
-		dest.defaultSelected = dest.selected = src.defaultSelected;
-
-	// IE6-8 fails to set the defaultValue to the correct value when
-	// cloning other types of input fields
-	} else if ( nodeName === "input" || nodeName === "textarea" ) {
-		dest.defaultValue = src.defaultValue;
-	}
-}
-
-jQuery.each({
-	appendTo: "append",
-	prependTo: "prepend",
-	insertBefore: "before",
-	insertAfter: "after",
-	replaceAll: "replaceWith"
-}, function( name, original ) {
-	jQuery.fn[ name ] = function( selector ) {
-		var elems,
-			i = 0,
-			ret = [],
-			insert = jQuery( selector ),
-			last = insert.length - 1;
-
-		for ( ; i <= last; i++ ) {
-			elems = i === last ? this : this.clone(true);
-			jQuery( insert[i] )[ original ]( elems );
-
-			// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
-			core_push.apply( ret, elems.get() );
-		}
-
-		return this.pushStack( ret );
-	};
-});
-
-function getAll( context, tag ) {
-	var elems, elem,
-		i = 0,
-		found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) :
-			typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) :
-			undefined;
-
-	if ( !found ) {
-		for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
-			if ( !tag || jQuery.nodeName( elem, tag ) ) {
-				found.push( elem );
-			} else {
-				jQuery.merge( found, getAll( elem, tag ) );
-			}
-		}
-	}
-
-	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
-		jQuery.merge( [ context ], found ) :
-		found;
-}
-
-// Used in buildFragment, fixes the defaultChecked property
-function fixDefaultChecked( elem ) {
-	if ( manipulation_rcheckableType.test( elem.type ) ) {
-		elem.defaultChecked = elem.checked;
-	}
-}
-
-jQuery.extend({
-	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
-		var destElements, node, clone, i, srcElements,
-			inPage = jQuery.contains( elem.ownerDocument, elem );
-
-		if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
-			clone = elem.cloneNode( true );
-
-		// IE<=8 does not properly clone detached, unknown element nodes
-		} else {
-			fragmentDiv.innerHTML = elem.outerHTML;
-			fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
-		}
-
-		if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
-				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
-
-			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
-			destElements = getAll( clone );
-			srcElements = getAll( elem );
-
-			// Fix all IE cloning issues
-			for ( i = 0; (node = srcElements[i]) != null; ++i ) {
-				// Ensure that the destination node is not null; Fixes #9587
-				if ( destElements[i] ) {
-					fixCloneNodeIssues( node, destElements[i] );
-				}
-			}
-		}
-
-		// Copy the events from the original to the clone
-		if ( dataAndEvents ) {
-			if ( deepDataAndEvents ) {
-				srcElements = srcElements || getAll( elem );
-				destElements = destElements || getAll( clone );
-
-				for ( i = 0; (node = srcElements[i]) != null; i++ ) {
-					cloneCopyEvent( node, destElements[i] );
-				}
-			} else {
-				cloneCopyEvent( elem, clone );
-			}
-		}
-
-		// Preserve script evaluation history
-		destElements = getAll( clone, "script" );
-		if ( destElements.length > 0 ) {
-			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
-		}
-
-		destElements = srcElements = node = null;
-
-		// Return the cloned set
-		return clone;
-	},
-
-	buildFragment: function( elems, context, scripts, selection ) {
-		var j, elem, contains,
-			tmp, tag, tbody, wrap,
-			l = elems.length,
-
-			// Ensure a safe fragment
-			safe = createSafeFragment( context ),
-
-			nodes = [],
-			i = 0;
-
-		for ( ; i < l; i++ ) {
-			elem = elems[ i ];
-
-			if ( elem || elem === 0 ) {
-
-				// Add nodes directly
-				if ( jQuery.type( elem ) === "object" ) {
-					jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
-
-				// Convert non-html into a text node
-				} else if ( !rhtml.test( elem ) ) {
-					nodes.push( context.createTextNode( elem ) );
-
-				// Convert html into DOM nodes
-				} else {
-					tmp = tmp || safe.appendChild( context.createElement("div") );
-
-					// Deserialize a standard representation
-					tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase();
-					wrap = wrapMap[ tag ] || wrapMap._default;
-
-					tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
-
-					// Descend through wrappers to the right content
-					j = wrap[0];
-					while ( j-- ) {
-						tmp = tmp.lastChild;
-					}
-
-					// Manually add leading whitespace removed by IE
-					if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
-						nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
-					}
-
-					// Remove IE's autoinserted <tbody> from table fragments
-					if ( !jQuery.support.tbody ) {
-
-						// String was a <table>, *may* have spurious <tbody>
-						elem = tag === "table" && !rtbody.test( elem ) ?
-							tmp.firstChild :
-
-							// String was a bare <thead> or <tfoot>
-							wrap[1] === "<table>" && !rtbody.test( elem ) ?
-								tmp :
-								0;
-
-						j = elem && elem.childNodes.length;
-						while ( j-- ) {
-							if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
-								elem.removeChild( tbody );
-							}
-						}
-					}
-
-					jQuery.merge( nodes, tmp.childNodes );
-
-					// Fix #12392 for WebKit and IE > 9
-					tmp.textContent = "";
-
-					// Fix #12392 for oldIE
-					while ( tmp.firstChild ) {
-						tmp.removeChild( tmp.firstChild );
-					}
-
-					// Remember the top-level container for proper cleanup
-					tmp = safe.lastChild;
-				}
-			}
-		}
-
-		// Fix #11356: Clear elements from fragment
-		if ( tmp ) {
-			safe.removeChild( tmp );
-		}
-
-		// Reset defaultChecked for any radios and checkboxes
-		// about to be appended to the DOM in IE 6/7 (#8060)
-		if ( !jQuery.support.appendChecked ) {
-			jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
-		}
-
-		i = 0;
-		while ( (elem = nodes[ i++ ]) ) {
-
-			// #4087 - If origin and destination elements are the same, and this is
-			// that element, do not do anything
-			if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
-				continue;
-			}
-
-			contains = jQuery.contains( elem.ownerDocument, elem );
-
-			// Append to fragment
-			tmp = getAll( safe.appendChild( elem ), "script" );
-
-			// Preserve script evaluation history
-			if ( contains ) {
-				setGlobalEval( tmp );
-			}
-
-			// Capture executables
-			if ( scripts ) {
-				j = 0;
-				while ( (elem = tmp[ j++ ]) ) {
-					if ( rscriptType.test( elem.type || "" ) ) {
-						scripts.push( elem );
-					}
-				}
-			}
-		}
-
-		tmp = null;
-
-		return safe;
-	},
-
-	cleanData: function( elems, /* internal */ acceptData ) {
-		var elem, type, id, data,
-			i = 0,
-			internalKey = jQuery.expando,
-			cache = jQuery.cache,
-			deleteExpando = jQuery.support.deleteExpando,
-			special = jQuery.event.special;
-
-		for ( ; (elem = elems[i]) != null; i++ ) {
-
-			if ( acceptData || jQuery.acceptData( elem ) ) {
-
-				id = elem[ internalKey ];
-				data = id && cache[ id ];
-
-				if ( data ) {
-					if ( data.events ) {
-						for ( type in data.events ) {
-							if ( special[ type ] ) {
-								jQuery.event.remove( elem, type );
-
-							// This is a shortcut to avoid jQuery.event.remove's overhead
-							} else {
-								jQuery.removeEvent( elem, type, data.handle );
-							}
-						}
-					}
-
-					// Remove cache only if it was not already removed by jQuery.event.remove
-					if ( cache[ id ] ) {
-
-						delete cache[ id ];
-
-						// IE does not allow us to delete expando properties from nodes,
-						// nor does it have a removeAttribute function on Document nodes;
-						// we must handle all of these cases
-						if ( deleteExpando ) {
-							delete elem[ internalKey ];
-
-						} else if ( typeof elem.removeAttribute !== core_strundefined ) {
-							elem.removeAttribute( internalKey );
-
-						} else {
-							elem[ internalKey ] = null;
-						}
-
-						core_deletedIds.push( id );
-					}
-				}
-			}
-		}
-	}
-});
-var iframe, getStyles, curCSS,
-	ralpha = /alpha\([^)]*\)/i,
-	ropacity = /opacity\s*=\s*([^)]*)/,
-	rposition = /^(top|right|bottom|left)$/,
-	// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
-	// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
-	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
-	rmargin = /^margin/,
-	rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
-	rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
-	rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
-	elemdisplay = { BODY: "block" },
-
-	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
-	cssNormalTransform = {
-		letterSpacing: 0,
-		fontWeight: 400
-	},
-
-	cssExpand = [ "Top", "Right", "Bottom", "Left" ],
-	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
-
-// return a css property mapped to a potentially vendor prefixed property
-function vendorPropName( style, name ) {
-
-	// shortcut for names that are not vendor prefixed
-	if ( name in style ) {
-		return name;
-	}
-
-	// check for vendor prefixed names
-	var capName = name.charAt(0).toUpperCase() + name.slice(1),
-		origName = name,
-		i = cssPrefixes.length;
-
-	while ( i-- ) {
-		name = cssPrefixes[ i ] + capName;
-		if ( name in style ) {
-			return name;
-		}
-	}
-
-	return origName;
-}
-
-function isHidden( elem, el ) {
-	// isHidden might be called from jQuery#filter function;
-	// in that case, element will be second argument
-	elem = el || elem;
-	return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
-}
-
-function showHide( elements, show ) {
-	var display, elem, hidden,
-		values = [],
-		index = 0,
-		length = elements.length;
-
-	for ( ; index < length; index++ ) {
-		elem = elements[ index ];
-		if ( !elem.style ) {
-			continue;
-		}
-
-		values[ index ] = jQuery._data( elem, "olddisplay" );
-		display = elem.style.display;
-		if ( show ) {
-			// Reset the inline display of this element to learn if it is
-			// being hidden by cascaded rules or not
-			if ( !values[ index ] && display === "none" ) {
-				elem.style.display = "";
-			}
-
-			// Set elements which have been overridden with display: none
-			// in a stylesheet to whatever the default browser style is
-			// for such an element
-			if ( elem.style.display === "" && isHidden( elem ) ) {
-				values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
-			}
-		} else {
-
-			if ( !values[ index ] ) {
-				hidden = isHidden( elem );
-
-				if ( display && display !== "none" || !hidden ) {
-					jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
-				}
-			}
-		}
-	}
-
-	// Set the display of most of the elements in a second loop
-	// to avoid the constant reflow
-	for ( index = 0; index < length; index++ ) {
-		elem = elements[ index ];
-		if ( !elem.style ) {
-			continue;
-		}
-		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
-			elem.style.display = show ? values[ index ] || "" : "none";
-		}
-	}
-
-	return elements;
-}
-
-jQuery.fn.extend({
-	css: function( name, value ) {
-		return jQuery.access( this, function( elem, name, value ) {
-			var len, styles,
-				map = {},
-				i = 0;
-
-			if ( jQuery.isArray( name ) ) {
-				styles = getStyles( elem );
-				len = name.length;
-
-				for ( ; i < len; i++ ) {
-					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
-				}
-
-				return map;
-			}
-
-			return value !== undefined ?
-				jQuery.style( elem, name, value ) :
-				jQuery.css( elem, name );
-		}, name, value, arguments.length > 1 );
-	},
-	show: function() {
-		return showHide( this, true );
-	},
-	hide: function() {
-		return showHide( this );
-	},
-	toggle: function( state ) {
-		var bool = typeof state === "boolean";
-
-		return this.each(function() {
-			if ( bool ? state : isHidden( this ) ) {
-				jQuery( this ).show();
-			} else {
-				jQuery( this ).hide();
-			}
-		});
-	}
-});
-
-jQuery.extend({
-	// Add in style property hooks for overriding the default
-	// behavior of getting and setting a style property
-	cssHooks: {
-		opacity: {
-			get: function( elem, computed ) {
-				if ( computed ) {
-					// We should always get a number back from opacity
-					var ret = curCSS( elem, "opacity" );
-					return ret === "" ? "1" : ret;
-				}
-			}
-		}
-	},
-
-	// Exclude the following css properties to add px
-	cssNumber: {
-		"columnCount": true,
-		"fillOpacity": true,
-		"fontWeight": true,
-		"lineHeight": true,
-		"opacity": true,
-		"orphans": true,
-		"widows": true,
-		"zIndex": true,
-		"zoom": true
-	},
-
-	// Add in properties whose names you wish to fix before
-	// setting or getting the value
-	cssProps: {
-		// normalize float css property
-		"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
-	},
-
-	// Get and set the style property on a DOM Node
-	style: function( elem, name, value, extra ) {
-		// Don't set styles on text and comment nodes
-		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
-			return;
-		}
-
-		// Make sure that we're working with the right name
-		var ret, type, hooks,
-			origName = jQuery.camelCase( name ),
-			style = elem.style;
-
-		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
-
-		// gets hook for the prefixed version
-		// followed by the unprefixed version
-		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
-
-		// Check if we're setting a value
-		if ( value !== undefined ) {
-			type = typeof value;
-
-			// convert relative number strings (+= or -=) to relative numbers. #7345
-			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
-				value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
-				// Fixes bug #9237
-				type = "number";
-			}
-
-			// Make sure that NaN and null values aren't set. See: #7116
-			if ( value == null || type === "number" && isNaN( value ) ) {
-				return;
-			}
-
-			// If a number was passed in, add 'px' to the (except for certain CSS properties)
-			if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
-				value += "px";
-			}
-
-			// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
-			// but it would mean to define eight (for every problematic property) identical functions
-			if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
-				style[ name ] = "inherit";
-			}
-
-			// If a hook was provided, use that value, otherwise just set the specified value
-			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
-
-				// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
-				// Fixes bug #5509
-				try {
-					style[ name ] = value;
-				} catch(e) {}
-			}
-
-		} else {
-			// If a hook was provided get the non-computed value from there
-			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
-				return ret;
-			}
-
-			// Otherwise just get the value from the style object
-			return style[ name ];
-		}
-	},
-
-	css: function( elem, name, extra, styles ) {
-		var num, val, hooks,
-			origName = jQuery.camelCase( name );
-
-		// Make sure that we're working with the right name
-		name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
-
-		// gets hook for the prefixed version
-		// followed by the unprefixed version
-		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
-
-		// If a hook was provided get the computed value from there
-		if ( hooks && "get" in hooks ) {
-			val = hooks.get( elem, true, extra );
-		}
-
-		// Otherwise, if a way to get the computed value exists, use that
-		if ( val === undefined ) {
-			val = curCSS( elem, name, styles );
-		}
-
-		//convert "normal" to computed value
-		if ( val === "normal" && name in cssNormalTransform ) {
-			val = cssNormalTransform[ name ];
-		}
-
-		// Return, converting to number if forced or a qualifier was provided and val looks numeric
-		if ( extra === "" || extra ) {
-			num = parseFloat( val );
-			return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
-		}
-		return val;
-	},
-
-	// A method for quickly swapping in/out CSS properties to get correct calculations
-	swap: function( elem, options, callback, args ) {
-		var ret, name,
-			old = {};
-
-		// Remember the old values, and insert the new ones
-		for ( name in options ) {
-			old[ name ] = elem.style[ name ];
-			elem.style[ name ] = options[ name ];
-		}
-
-		ret = callback.apply( elem, args || [] );
-
-		// Revert the old values
-		for ( name in options ) {
-			elem.style[ name ] = old[ name ];
-		}
-
-		return ret;
-	}
-});
-
-// NOTE: we've included the "window" in window.getComputedStyle
-// because jsdom on node.js will break without it.
-if ( window.getComputedStyle ) {
-	getStyles = function( elem ) {
-		return window.getComputedStyle( elem, null );
-	};
-
-	curCSS = function( elem, name, _computed ) {
-		var width, minWidth, maxWidth,
-			computed = _computed || getStyles( elem ),
-
-			// getPropertyValue is only needed for .css('filter') in IE9, see #12537
-			ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
-			style = elem.style;
-
-		if ( computed ) {
-
-			if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
-				ret = jQuery.style( elem, name );
-			}
-
-			// A tribute to the "awesome hack by Dean Edwards"
-			// Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
-			// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
-			// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
-			if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
-
-				// Remember the original values
-				width = style.width;
-				minWidth = style.minWidth;
-				maxWidth = style.maxWidth;
-
-				// Put in the new values to get a computed value out
-				style.minWidth = style.maxWidth = style.width = ret;
-				ret = computed.width;
-
-				// Revert the changed values
-				style.width = width;
-				style.minWidth = minWidth;
-				style.maxWidth = maxWidth;
-			}
-		}
-
-		return ret;
-	};
-} else if ( document.documentElement.currentStyle ) {
-	getStyles = function( elem ) {
-		return elem.currentStyle;
-	};
-
-	curCSS = function( elem, name, _computed ) {
-		var left, rs, rsLeft,
-			computed = _computed || getStyles( elem ),
-			ret = computed ? computed[ name ] : undefined,
-			style = elem.style;
-
-		// Avoid setting ret to empty string here
-		// so we don't default to auto
-		if ( ret == null && style && style[ name ] ) {
-			ret = style[ name ];
-		}
-
-		// From the awesome hack by Dean Edwards
-		// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
-
-		// If we're not dealing with a regular pixel number
-		// but a number that has a weird ending, we need to convert it to pixels
-		// but not position css attributes, as those are proportional to the parent element instead
-		// and we can't measure the parent instead because it might trigger a "stacking dolls" problem
-		if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
-
-			// Remember the original values
-			left = style.left;
-			rs = elem.runtimeStyle;
-			rsLeft = rs && rs.left;
-
-			// Put in the new values to get a computed value out
-			if ( rsLeft ) {
-				rs.left = elem.currentStyle.left;
-			}
-			style.left = name === "fontSize" ? "1em" : ret;
-			ret = style.pixelLeft + "px";
-
-			// Revert the changed values
-			style.left = left;
-			if ( rsLeft ) {
-				rs.left = rsLeft;
-			}
-		}
-
-		return ret === "" ? "auto" : ret;
-	};
-}
-
-function setPositiveNumber( elem, value, subtract ) {
-	var matches = rnumsplit.exec( value );
-	return matches ?
-		// Guard against undefined "subtract", e.g., when used as in cssHooks
-		Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
-		value;
-}
-
-function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
-	var i = extra === ( isBorderBox ? "border" : "content" ) ?
-		// If we already have the right measurement, avoid augmentation
-		4 :
-		// Otherwise initialize for horizontal or vertical properties
-		name === "width" ? 1 : 0,
-
-		val = 0;
-
-	for ( ; i < 4; i += 2 ) {
-		// both box models exclude margin, so add it if we want it
-		if ( extra === "margin" ) {
-			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
-		}
-
-		if ( isBorderBox ) {
-			// border-box includes padding, so remove it if we want content
-			if ( extra === "content" ) {
-				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
-			}
-
-			// at this point, extra isn't border nor margin, so remove border
-			if ( extra !== "margin" ) {
-				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
-			}
-		} else {
-			// at this point, extra isn't content, so add padding
-			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
-
-			// at this point, extra isn't content nor padding, so add border
-			if ( extra !== "padding" ) {
-				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
-			}
-		}
-	}
-
-	return val;
-}
-
-function getWidthOrHeight( elem, name, extra ) {
-
-	// Start with offset property, which is equivalent to the border-box value
-	var valueIsBorderBox = true,
-		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
-		styles = getStyles( elem ),
-		isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
-
-	// some non-html elements return undefined for offsetWidth, so check for null/undefined
-	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
-	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
-	if ( val <= 0 || val == null ) {
-		// Fall back to computed then uncomputed css if necessary
-		val = curCSS( elem, name, styles );
-		if ( val < 0 || val == null ) {
-			val = elem.style[ name ];
-		}
-
-		// Computed unit is not pixels. Stop here and return.
-		if ( rnumnonpx.test(val) ) {
-			return val;
-		}
-
-		// we need the check for style in case a browser which returns unreliable values
-		// for getComputedStyle silently falls back to the reliable elem.style
-		valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
-
-		// Normalize "", auto, and prepare for extra
-		val = parseFloat( val ) || 0;
-	}
-
-	// use the active box-sizing model to add/subtract irrelevant styles
-	return ( val +
-		augmentWidthOrHeight(
-			elem,
-			name,
-			extra || ( isBorderBox ? "border" : "content" ),
-			valueIsBorderBox,
-			styles
-		)
-	) + "px";
-}
-
-// Try to determine the default display value of an element
-function css_defaultDisplay( nodeName ) {
-	var doc = document,
-		display = elemdisplay[ nodeName ];
-
-	if ( !display ) {
-		display = actualDisplay( nodeName, doc );
-
-		// If the simple way fails, read from inside an iframe
-		if ( display === "none" || !display ) {
-			// Use the already-created iframe if possible
-			iframe = ( iframe ||
-				jQuery("<iframe frameborder='0' width='0' height='0'/>")
-				.css( "cssText", "display:block !important" )
-			).appendTo( doc.documentElement );
-
-			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
-			doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
-			doc.write("<!doctype html><html><body>");
-			doc.close();
-
-			display = actualDisplay( nodeName, doc );
-			iframe.detach();
-		}
-
-		// Store the correct default display
-		elemdisplay[ nodeName ] = display;
-	}
-
-	return display;
-}
-
-// Called ONLY from within css_defaultDisplay
-function actualDisplay( name, doc ) {
-	var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
-		display = jQuery.css( elem[0], "display" );
-	elem.remove();
-	return display;
-}
-
-jQuery.each([ "height", "width" ], function( i, name ) {
-	jQuery.cssHooks[ name ] = {
-		get: function( elem, computed, extra ) {
-			if ( computed ) {
-				// certain elements can have dimension info if we invisibly show them
-				// however, it must have a current display style that would benefit from this
-				return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
-					jQuery.swap( elem, cssShow, function() {
-						return getWidthOrHeight( elem, name, extra );
-					}) :
-					getWidthOrHeight( elem, name, extra );
-			}
-		},
-
-		set: function( elem, value, extra ) {
-			var styles = extra && getStyles( elem );
-			return setPositiveNumber( elem, value, extra ?
-				augmentWidthOrHeight(
-					elem,
-					name,
-					extra,
-					jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
-					styles
-				) : 0
-			);
-		}
-	};
-});
-
-if ( !jQuery.support.opacity ) {
-	jQuery.cssHooks.opacity = {
-		get: function( elem, computed ) {
-			// IE uses filters for opacity
-			return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
-				( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
-				computed ? "1" : "";
-		},
-
-		set: function( elem, value ) {
-			var style = elem.style,
-				currentStyle = elem.currentStyle,
-				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
-				filter = currentStyle && currentStyle.filter || style.filter || "";
-
-			// IE has trouble with opacity if it does not have layout
-			// Force it by setting the zoom level
-			style.zoom = 1;
-
-			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
-			// if value === "", then remove inline opacity #12685
-			if ( ( value >= 1 || value === "" ) &&
-					jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
-					style.removeAttribute ) {
-
-				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
-				// if "filter:" is present at all, clearType is disabled, we want to avoid this
-				// style.removeAttribute is IE Only, but so apparently is this code path...
-				style.removeAttribute( "filter" );
-
-				// if there is no filter style applied in a css rule or unset inline opacity, we are done
-				if ( value === "" || currentStyle && !currentStyle.filter ) {
-					return;
-				}
-			}
-
-			// otherwise, set new filter values
-			style.filter = ralpha.test( filter ) ?
-				filter.replace( ralpha, opacity ) :
-				filter + " " + opacity;
-		}
-	};
-}
-
-// These hooks cannot be added until DOM ready because the support test
-// for it is not run until after DOM ready
-jQuery(function() {
-	if ( !jQuery.support.reliableMarginRight ) {
-		jQuery.cssHooks.marginRight = {
-			get: function( elem, computed ) {
-				if ( computed ) {
-					// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
-					// Work around by temporarily setting element display to inline-block
-					return jQuery.swap( elem, { "display": "inline-block" },
-						curCSS, [ elem, "marginRight" ] );
-				}
-			}
-		};
-	}
-
-	// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
-	// getComputedStyle returns percent when specified for top/left/bottom/right
-	// rather than make the css module depend on the offset module, we just check for it here
-	if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
-		jQuery.each( [ "top", "left" ], function( i, prop ) {
-			jQuery.cssHooks[ prop ] = {
-				get: function( elem, computed ) {
-					if ( computed ) {
-						computed = curCSS( elem, prop );
-						// if curCSS returns percentage, fallback to offset
-						return rnumnonpx.test( computed ) ?
-							jQuery( elem ).position()[ prop ] + "px" :
-							computed;
-					}
-				}
-			};
-		});
-	}
-
-});
-
-if ( jQuery.expr && jQuery.expr.filters ) {
-	jQuery.expr.filters.hidden = function( elem ) {
-		// Support: Opera <= 12.12
-		// Opera reports offsetWidths and offsetHeights less than zero on some elements
-		return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
-			(!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
-	};
-
-	jQuery.expr.filters.visible = function( elem ) {
-		return !jQuery.expr.filters.hidden( elem );
-	};
-}
-
-// These hooks are used by animate to expand properties
-jQuery.each({
-	margin: "",
-	padding: "",
-	border: "Width"
-}, function( prefix, suffix ) {
-	jQuery.cssHooks[ prefix + suffix ] = {
-		expand: function( value ) {
-			var i = 0,
-				expanded = {},
-
-				// assumes a single number if not a string
-				parts = typeof value === "string" ? value.split(" ") : [ value ];
-
-			for ( ; i < 4; i++ ) {
-				expanded[ prefix + cssExpand[ i ] + suffix ] =
-					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
-			}
-
-			return expanded;
-		}
-	};
-
-	if ( !rmargin.test( prefix ) ) {
-		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
-	}
-});
-var r20 = /%20/g,
-	rbracket = /\[\]$/,
-	rCRLF = /\r?\n/g,
-	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
-	rsubmittable = /^(?:input|select|textarea|keygen)/i;
-
-jQuery.fn.extend({
-	serialize: function() {
-		return jQuery.param( this.serializeArray() );
-	},
-	serializeArray: function() {
-		return this.map(function(){
-			// Can add propHook for "elements" to filter or add form elements
-			var elements = jQuery.prop( this, "elements" );
-			return elements ? jQuery.makeArray( elements ) : this;
-		})
-		.filter(function(){
-			var type = this.type;
-			// Use .is(":disabled") so that fieldset[disabled] works
-			return this.name && !jQuery( this ).is( ":disabled" ) &&
-				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
-				( this.checked || !manipulation_rcheckableType.test( type ) );
-		})
-		.map(function( i, elem ){
-			var val = jQuery( this ).val();
-
-			return val == null ?
-				null :
-				jQuery.isArray( val ) ?
-					jQuery.map( val, function( val ){
-						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
-					}) :
-					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
-		}).get();
-	}
-});
-
-//Serialize an array of form elements or a set of
-//key/values into a query string
-jQuery.param = function( a, traditional ) {
-	var prefix,
-		s = [],
-		add = function( key, value ) {
-			// If value is a function, invoke it and return its value
-			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
-			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
-		};
-
-	// Set traditional to true for jQuery <= 1.3.2 behavior.
-	if ( traditional === undefined ) {
-		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
-	}
-
-	// If an array was passed in, assume that it is an array of form elements.
-	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
-		// Serialize the form elements
-		jQuery.each( a, function() {
-			add( this.name, this.value );
-		});
-
-	} else {
-		// If traditional, encode the "old" way (the way 1.3.2 or older
-		// did it), otherwise encode params recursively.
-		for ( prefix in a ) {
-			buildParams( prefix, a[ prefix ], traditional, add );
-		}
-	}
-
-	// Return the resulting serialization
-	return s.join( "&" ).replace( r20, "+" );
-};
-
-function buildParams( prefix, obj, traditional, add ) {
-	var name;
-
-	if ( jQuery.isArray( obj ) ) {
-		// Serialize array item.
-		jQuery.each( obj, function( i, v ) {
-			if ( traditional || rbracket.test( prefix ) ) {
-				// Treat each array item as a scalar.
-				add( prefix, v );
-
-			} else {
-				// Item is non-scalar (array or object), encode its numeric index.
-				buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
-			}
-		});
-
-	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
-		// Serialize object item.
-		for ( name in obj ) {
-			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
-		}
-
-	} else {
-		// Serialize scalar item.
-		add( prefix, obj );
-	}
-}
-jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
-	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
-	"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
-
-	// Handle event binding
-	jQuery.fn[ name ] = function( data, fn ) {
-		return arguments.length > 0 ?
-			this.on( name, null, data, fn ) :
-			this.trigger( name );
-	};
-});
-
-jQuery.fn.hover = function( fnOver, fnOut ) {
-	return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
-};
-var
-	// Document location
-	ajaxLocParts,
-	ajaxLocation,
-	ajax_nonce = jQuery.now(),
-
-	ajax_rquery = /\?/,
-	rhash = /#.*$/,
-	rts = /([?&])_=[^&]*/,
-	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
-	// #7653, #8125, #8152: local protocol detection
-	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
-	rnoContent = /^(?:GET|HEAD)$/,
-	rprotocol = /^\/\//,
-	rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
-
-	// Keep a copy of the old load method
-	_load = jQuery.fn.load,
-
-	/* Prefilters
-	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
-	 * 2) These are called:
-	 *    - BEFORE asking for a transport
-	 *    - AFTER param serialization (s.data is a string if s.processData is true)
-	 * 3) key is the dataType
-	 * 4) the catchall symbol "*" can be used
-	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
-	 */
-	prefilters = {},
-
-	/* Transports bindings
-	 * 1) key is the dataType
-	 * 2) the catchall symbol "*" can be used
-	 * 3) selection will start with transport dataType and THEN go to "*" if needed
-	 */
-	transports = {},
-
-	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
-	allTypes = "*/".concat("*");
-
-// #8138, IE may throw an exception when accessing
-// a field from window.location if document.domain has been set
-try {
-	ajaxLocation = location.href;
-} catch( e ) {
-	// Use the href attribute of an A element
-	// since IE will modify it given document.location
-	ajaxLocation = document.createElement( "a" );
-	ajaxLocation.href = "";
-	ajaxLocation = ajaxLocation.href;
-}
-
-// Segment location into parts
-ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
-
-// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
-function addToPrefiltersOrTransports( structure ) {
-
-	// dataTypeExpression is optional and defaults to "*"
-	return function( dataTypeExpression, func ) {
-
-		if ( typeof dataTypeExpression !== "string" ) {
-			func = dataTypeExpression;
-			dataTypeExpression = "*";
-		}
-
-		var dataType,
-			i = 0,
-			dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
-
-		if ( jQuery.isFunction( func ) ) {
-			// For each dataType in the dataTypeExpression
-			while ( (dataType = dataTypes[i++]) ) {
-				// Prepend if requested
-				if ( dataType[0] === "+" ) {
-					dataType = dataType.slice( 1 ) || "*";
-					(structure[ dataType ] = structure[ dataType ] || []).unshift( func );
-
-				// Otherwise append
-				} else {
-					(structure[ dataType ] = structure[ dataType ] || []).push( func );
-				}
-			}
-		}
-	};
-}
-
-// Base inspection function for prefilters and transports
-function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
-
-	var inspected = {},
-		seekingTransport = ( structure === transports );
-
-	function inspect( dataType ) {
-		var selected;
-		inspected[ dataType ] = true;
-		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
-			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
-			if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
-				options.dataTypes.unshift( dataTypeOrTransport );
-				inspect( dataTypeOrTransport );
-				return false;
-			} else if ( seekingTransport ) {
-				return !( selected = dataTypeOrTransport );
-			}
-		});
-		return selected;
-	}
-
-	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
-}
-
-// A special extend for ajax options
-// that takes "flat" options (not to be deep extended)
-// Fixes #9887
-function ajaxExtend( target, src ) {
-	var deep, key,
-		flatOptions = jQuery.ajaxSettings.flatOptions || {};
-
-	for ( key in src ) {
-		if ( src[ key ] !== undefined ) {
-			( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
-		}
-	}
-	if ( deep ) {
-		jQuery.extend( true, target, deep );
-	}
-
-	return target;
-}
-
-jQuery.fn.load = function( url, params, callback ) {
-	if ( typeof url !== "string" && _load ) {
-		return _load.apply( this, arguments );
-	}
-
-	var selector, response, type,
-		self = this,
-		off = url.indexOf(" ");
-
-	if ( off >= 0 ) {
-		selector = url.slice( off, url.length );
-		url = url.slice( 0, off );
-	}
-
-	// If it's a function
-	if ( jQuery.isFunction( params ) ) {
-
-		// We assume that it's the callback
-		callback = params;
-		params = undefined;
-
-	// Otherwise, build a param string
-	} else if ( params && typeof params === "object" ) {
-		type = "POST";
-	}
-
-	// If we have elements to modify, make the request
-	if ( self.length > 0 ) {
-		jQuery.ajax({
-			url: url,
-
-			// if "type" variable is undefined, then "GET" method will be used
-			type: type,
-			dataType: "html",
-			data: params
-		}).done(function( responseText ) {
-
-			// Save response for use in complete callback
-			response = arguments;
-
-			self.html( selector ?
-
-				// If a selector was specified, locate the right elements in a dummy div
-				// Exclude scripts to avoid IE 'Permission Denied' errors
-				jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
-
-				// Otherwise use the full result
-				responseText );
-
-		}).complete( callback && function( jqXHR, status ) {
-			self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
-		});
-	}
-
-	return this;
-};
-
-// Attach a bunch of functions for handling common AJAX events
-jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
-	jQuery.fn[ type ] = function( fn ){
-		return this.on( type, fn );
-	};
-});
-
-jQuery.each( [ "get", "post" ], function( i, method ) {
-	jQuery[ method ] = function( url, data, callback, type ) {
-		// shift arguments if data argument was omitted
-		if ( jQuery.isFunction( data ) ) {
-			type = type || callback;
-			callback = data;
-			data = undefined;
-		}
-
-		return jQuery.ajax({
-			url: url,
-			type: method,
-			dataType: type,
-			data: data,
-			success: callback
-		});
-	};
-});
-
-jQuery.extend({
-
-	// Counter for holding the number of active queries
-	active: 0,
-
-	// Last-Modified header cache for next request
-	lastModified: {},
-	etag: {},
-
-	ajaxSettings: {
-		url: ajaxLocation,
-		type: "GET",
-		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
-		global: true,
-		processData: true,
-		async: true,
-		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
-		/*
-		timeout: 0,
-		data: null,
-		dataType: null,
-		username: null,
-		password: null,
-		cache: null,
-		throws: false,
-		traditional: false,
-		headers: {},
-		*/
-
-		accepts: {
-			"*": allTypes,
-			text: "text/plain",
-			html: "text/html",
-			xml: "application/xml, text/xml",
-			json: "application/json, text/javascript"
-		},
-
-		contents: {
-			xml: /xml/,
-			html: /html/,
-			json: /json/
-		},
-
-		responseFields: {
-			xml: "responseXML",
-			text: "responseText"
-		},
-
-		// Data converters
-		// Keys separate source (or catchall "*") and destination types with a single space
-		converters: {
-
-			// Convert anything to text
-			"* text": window.String,
-
-			// Text to html (true = no transformation)
-			"text html": true,
-
-			// Evaluate text as a json expression
-			"text json": jQuery.parseJSON,
-
-			// Parse text as xml
-			"text xml": jQuery.parseXML
-		},
-
-		// For options that shouldn't be deep extended:
-		// you can add your own custom options here if
-		// and when you create one that shouldn't be
-		// deep extended (see ajaxExtend)
-		flatOptions: {
-			url: true,
-			context: true
-		}
-	},
-
-	// Creates a full fledged settings object into target
-	// with both ajaxSettings and settings fields.
-	// If target is omitted, writes into ajaxSettings.
-	ajaxSetup: function( target, settings ) {
-		return settings ?
-
-			// Building a settings object
-			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
-
-			// Extending ajaxSettings
-			ajaxExtend( jQuery.ajaxSettings, target );
-	},
-
-	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
-	ajaxTransport: addToPrefiltersOrTransports( transports ),
-
-	// Main method
-	ajax: function( url, options ) {
-
-		// If url is an object, simulate pre-1.5 signature
-		if ( typeof url === "object" ) {
-			options = url;
-			url = undefined;
-		}
-
-		// Force options to be an object
-		options = options || {};
-
-		var // Cross-domain detection vars
-			parts,
-			// Loop variable
-			i,
-			// URL without anti-cache param
-			cacheURL,
-			// Response headers as string
-			responseHeadersString,
-			// timeout handle
-			timeoutTimer,
-
-			// To know if global events are to be dispatched
-			fireGlobals,
-
-			transport,
-			// Response headers
-			responseHeaders,
-			// Create the final options object
-			s = jQuery.ajaxSetup( {}, options ),
-			// Callbacks context
-			callbackContext = s.context || s,
-			// Context for global events is callbackContext if it is a DOM node or jQuery collection
-			globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
-				jQuery( callbackContext ) :
-				jQuery.event,
-			// Deferreds
-			deferred = jQuery.Deferred(),
-			completeDeferred = jQuery.Callbacks("once memory"),
-			// Status-dependent callbacks
-			statusCode = s.statusCode || {},
-			// Headers (they are sent all at once)
-			requestHeaders = {},
-			requestHeadersNames = {},
-			// The jqXHR state
-			state = 0,
-			// Default abort message
-			strAbort = "canceled",
-			// Fake xhr
-			jqXHR = {
-				readyState: 0,
-
-				// Builds headers hashtable if needed
-				getResponseHeader: function( key ) {
-					var match;
-					if ( state === 2 ) {
-						if ( !responseHeaders ) {
-							responseHeaders = {};
-							while ( (match = rheaders.exec( responseHeadersString )) ) {
-								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
-							}
-						}
-						match = responseHeaders[ key.toLowerCase() ];
-					}
-					return match == null ? null : match;
-				},
-
-				// Raw string
-				getAllResponseHeaders: function() {
-					return state === 2 ? responseHeadersString : null;
-				},
-
-				// Caches the header
-				setRequestHeader: function( name, value ) {
-					var lname = name.toLowerCase();
-					if ( !state ) {
-						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
-						requestHeaders[ name ] = value;
-					}
-					return this;
-				},
-
-				// Overrides response content-type header
-				overrideMimeType: function( type ) {
-					if ( !state ) {
-						s.mimeType = type;
-					}
-					return this;
-				},
-
-				// Status-dependent callbacks
-				statusCode: function( map ) {
-					var code;
-					if ( map ) {
-						if ( state < 2 ) {
-							for ( code in map ) {
-								// Lazy-add the new callback in a way that preserves old ones
-								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
-							}
-						} else {
-							// Execute the appropriate callbacks
-							jqXHR.always( map[ jqXHR.status ] );
-						}
-					}
-					return this;
-				},
-
-				// Cancel the request
-				abort: function( statusText ) {
-					var finalText = statusText || strAbort;
-					if ( transport ) {
-						transport.abort( finalText );
-					}
-					done( 0, finalText );
-					return this;
-				}
-			};
-
-		// Attach deferreds
-		deferred.promise( jqXHR ).complete = completeDeferred.add;
-		jqXHR.success = jqXHR.done;
-		jqXHR.error = jqXHR.fail;
-
-		// Remove hash character (#7531: and string promotion)
-		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
-		// Handle falsy url in the settings object (#10093: consistency with old signature)
-		// We also use the url parameter if available
-		s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
-
-		// Alias method option to type as per ticket #12004
-		s.type = options.method || options.type || s.method || s.type;
-
-		// Extract dataTypes list
-		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
-
-		// A cross-domain request is in order when we have a protocol:host:port mismatch
-		if ( s.crossDomain == null ) {
-			parts = rurl.exec( s.url.toLowerCase() );
-			s.crossDomain = !!( parts &&
-				( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
-					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
-						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
-			);
-		}
-
-		// Convert data if not already a string
-		if ( s.data && s.processData && typeof s.data !== "string" ) {
-			s.data = jQuery.param( s.data, s.traditional );
-		}
-
-		// Apply prefilters
-		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
-
-		// If request was aborted inside a prefilter, stop there
-		if ( state === 2 ) {
-			return jqXHR;
-		}
-
-		// We can fire global events as of now if asked to
-		fireGlobals = s.global;
-
-		// Watch for a new set of requests
-		if ( fireGlobals && jQuery.active++ === 0 ) {
-			jQuery.event.trigger("ajaxStart");
-		}
-
-		// Uppercase the type
-		s.type = s.type.toUpperCase();
-
-		// Determine if request has content
-		s.hasContent = !rnoContent.test( s.type );
-
-		// Save the URL in case we're toying with the If-Modified-Since
-		// and/or If-None-Match header later on
-		cacheURL = s.url;
-
-		// More options handling for requests with no content
-		if ( !s.hasContent ) {
-
-			// If data is available, append data to url
-			if ( s.data ) {
-				cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
-				// #9682: remove data so that it's not used in an eventual retry
-				delete s.data;
-			}
-
-			// Add anti-cache in url if needed
-			if ( s.cache === false ) {
-				s.url = rts.test( cacheURL ) ?
-
-					// If there is already a '_' parameter, set its value
-					cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
-
-					// Otherwise add one to the end
-					cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
-			}
-		}
-
-		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
-		if ( s.ifModified ) {
-			if ( jQuery.lastModified[ cacheURL ] ) {
-				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
-			}
-			if ( jQuery.etag[ cacheURL ] ) {
-				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
-			}
-		}
-
-		// Set the correct header, if data is being sent
-		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
-			jqXHR.setRequestHeader( "Content-Type", s.contentType );
-		}
-
-		// Set the Accepts header for the server, depending on the dataType
-		jqXHR.setRequestHeader(
-			"Accept",
-			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
-				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
-				s.accepts[ "*" ]
-		);
-
-		// Check for headers option
-		for ( i in s.headers ) {
-			jqXHR.setRequestHeader( i, s.headers[ i ] );
-		}
-
-		// Allow custom headers/mimetypes and early abort
-		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
-			// Abort if not done already and return
-			return jqXHR.abort();
-		}
-
-		// aborting is no longer a cancellation
-		strAbort = "abort";
-
-		// Install callbacks on deferreds
-		for ( i in { success: 1, error: 1, complete: 1 } ) {
-			jqXHR[ i ]( s[ i ] );
-		}
-
-		// Get transport
-		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
-
-		// If no transport, we auto-abort
-		if ( !transport ) {
-			done( -1, "No Transport" );
-		} else {
-			jqXHR.readyState = 1;
-
-			// Send global event
-			if ( fireGlobals ) {
-				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
-			}
-			// Timeout
-			if ( s.async && s.timeout > 0 ) {
-				timeoutTimer = setTimeout(function() {
-					jqXHR.abort("timeout");
-				}, s.timeout );
-			}
-
-			try {
-				state = 1;
-				transport.send( requestHeaders, done );
-			} catch ( e ) {
-				// Propagate exception as error if not done
-				if ( state < 2 ) {
-					done( -1, e );
-				// Simply rethrow otherwise
-				} else {
-					throw e;
-				}
-			}
-		}
-
-		// Callback for when everything is done
-		function done( status, nativeStatusText, responses, headers ) {
-			var isSuccess, success, error, response, modified,
-				statusText = nativeStatusText;
-
-			// Called once
-			if ( state === 2 ) {
-				return;
-			}
-
-			// State is "done" now
-			state = 2;
-
-			// Clear timeout if it exists
-			if ( timeoutTimer ) {
-				clearTimeout( timeoutTimer );
-			}
-
-			// Dereference transport for early garbage collection
-			// (no matter how long the jqXHR object will be used)
-			transport = undefined;
-
-			// Cache response headers
-			responseHeadersString = headers || "";
-
-			// Set readyState
-			jqXHR.readyState = status > 0 ? 4 : 0;
-
-			// Get response data
-			if ( responses ) {
-				response = ajaxHandleResponses( s, jqXHR, responses );
-			}
-
-			// If successful, handle type chaining
-			if ( status >= 200 && status < 300 || status === 304 ) {
-
-				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
-				if ( s.ifModified ) {
-					modified = jqXHR.getResponseHeader("Last-Modified");
-					if ( modified ) {
-						jQuery.lastModified[ cacheURL ] = modified;
-					}
-					modified = jqXHR.getResponseHeader("etag");
-					if ( modified ) {
-						jQuery.etag[ cacheURL ] = modified;
-					}
-				}
-
-				// if no content
-				if ( status === 204 ) {
-					isSuccess = true;
-					statusText = "nocontent";
-
-				// if not modified
-				} else if ( status === 304 ) {
-					isSuccess = true;
-					statusText = "notmodified";
-
-				// If we have data, let's convert it
-				} else {
-					isSuccess = ajaxConvert( s, response );
-					statusText = isSuccess.state;
-					success = isSuccess.data;
-					error = isSuccess.error;
-					isSuccess = !error;
-				}
-			} else {
-				// We extract error from statusText
-				// then normalize statusText and status for non-aborts
-				error = statusText;
-				if ( status || !statusText ) {
-					statusText = "error";
-					if ( status < 0 ) {
-						status = 0;
-					}
-				}
-			}
-
-			// Set data for the fake xhr object
-			jqXHR.status = status;
-			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
-
-			// Success/Error
-			if ( isSuccess ) {
-				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
-			} else {
-				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
-			}
-
-			// Status-dependent callbacks
-			jqXHR.statusCode( statusCode );
-			statusCode = undefined;
-
-			if ( fireGlobals ) {
-				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
-					[ jqXHR, s, isSuccess ? success : error ] );
-			}
-
-			// Complete
-			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
-
-			if ( fireGlobals ) {
-				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
-				// Handle the global AJAX counter
-				if ( !( --jQuery.active ) ) {
-					jQuery.event.trigger("ajaxStop");
-				}
-			}
-		}
-
-		return jqXHR;
-	},
-
-	getScript: function( url, callback ) {
-		return jQuery.get( url, undefined, callback, "script" );
-	},
-
-	getJSON: function( url, data, callback ) {
-		return jQuery.get( url, data, callback, "json" );
-	}
-});
-
-/* Handles responses to an ajax request:
- * - sets all responseXXX fields accordingly
- * - finds the right dataType (mediates between content-type and expected dataType)
- * - returns the corresponding response
- */
-function ajaxHandleResponses( s, jqXHR, responses ) {
-	var firstDataType, ct, finalDataType, type,
-		contents = s.contents,
-		dataTypes = s.dataTypes,
-		responseFields = s.responseFields;
-
-	// Fill responseXXX fields
-	for ( type in responseFields ) {
-		if ( type in responses ) {
-			jqXHR[ responseFields[type] ] = responses[ type ];
-		}
-	}
-
-	// Remove auto dataType and get content-type in the process
-	while( dataTypes[ 0 ] === "*" ) {
-		dataTypes.shift();
-		if ( ct === undefined ) {
-			ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
-		}
-	}
-
-	// Check if we're dealing with a known content-type
-	if ( ct ) {
-		for ( type in contents ) {
-			if ( contents[ type ] && contents[ type ].test( ct ) ) {
-				dataTypes.unshift( type );
-				break;
-			}
-		}
-	}
-
-	// Check to see if we have a response for the expected dataType
-	if ( dataTypes[ 0 ] in responses ) {
-		finalDataType = dataTypes[ 0 ];
-	} else {
-		// Try convertible dataTypes
-		for ( type in responses ) {
-			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
-				finalDataType = type;
-				break;
-			}
-			if ( !firstDataType ) {
-				firstDataType = type;
-			}
-		}
-		// Or just use first one
-		finalDataType = finalDataType || firstDataType;
-	}
-
-	// If we found a dataType
-	// We add the dataType to the list if needed
-	// and return the corresponding response
-	if ( finalDataType ) {
-		if ( finalDataType !== dataTypes[ 0 ] ) {
-			dataTypes.unshift( finalDataType );
-		}
-		return responses[ finalDataType ];
-	}
-}
-
-// Chain conversions given the request and the original response
-function ajaxConvert( s, response ) {
-	var conv2, current, conv, tmp,
-		converters = {},
-		i = 0,
-		// Work with a copy of dataTypes in case we need to modify it for conversion
-		dataTypes = s.dataTypes.slice(),
-		prev = dataTypes[ 0 ];
-
-	// Apply the dataFilter if provided
-	if ( s.dataFilter ) {
-		response = s.dataFilter( response, s.dataType );
-	}
-
-	// Create converters map with lowercased keys
-	if ( dataTypes[ 1 ] ) {
-		for ( conv in s.converters ) {
-			converters[ conv.toLowerCase() ] = s.converters[ conv ];
-		}
-	}
-
-	// Convert to each sequential dataType, tolerating list modification
-	for ( ; (current = dataTypes[++i]); ) {
-
-		// There's only work to do if current dataType is non-auto
-		if ( current !== "*" ) {
-
-			// Convert response if prev dataType is non-auto and differs from current
-			if ( prev !== "*" && prev !== current ) {
-
-				// Seek a direct converter
-				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
-
-				// If none found, seek a pair
-				if ( !conv ) {
-					for ( conv2 in converters ) {
-
-						// If conv2 outputs current
-						tmp = conv2.split(" ");
-						if ( tmp[ 1 ] === current ) {
-
-							// If prev can be converted to accepted input
-							conv = converters[ prev + " " + tmp[ 0 ] ] ||
-								converters[ "* " + tmp[ 0 ] ];
-							if ( conv ) {
-								// Condense equivalence converters
-								if ( conv === true ) {
-									conv = converters[ conv2 ];
-
-								// Otherwise, insert the intermediate dataType
-								} else if ( converters[ conv2 ] !== true ) {
-									current = tmp[ 0 ];
-									dataTypes.splice( i--, 0, current );
-								}
-
-								break;
-							}
-						}
-					}
-				}
-
-				// Apply converter (if not an equivalence)
-				if ( conv !== true ) {
-
-					// Unless errors are allowed to bubble, catch and return them
-					if ( conv && s["throws"] ) {
-						response = conv( response );
-					} else {
-						try {
-							response = conv( response );
-						} catch ( e ) {
-							return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
-						}
-					}
-				}
-			}
-
-			// Update prev for next iteration
-			prev = current;
-		}
-	}
-
-	return { state: "success", data: response };
-}
-// Install script dataType
-jQuery.ajaxSetup({
-	accepts: {
-		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
-	},
-	contents: {
-		script: /(?:java|ecma)script/
-	},
-	converters: {
-		"text script": function( text ) {
-			jQuery.globalEval( text );
-			return text;
-		}
-	}
-});
-
-// Handle cache's special case and global
-jQuery.ajaxPrefilter( "script", function( s ) {
-	if ( s.cache === undefined ) {
-		s.cache = false;
-	}
-	if ( s.crossDomain ) {
-		s.type = "GET";
-		s.global = false;
-	}
-});
-
-// Bind script tag hack transport
-jQuery.ajaxTransport( "script", function(s) {
-
-	// This transport only deals with cross domain requests
-	if ( s.crossDomain ) {
-
-		var script,
-			head = document.head || jQuery("head")[0] || document.documentElement;
-
-		return {
-
-			send: function( _, callback ) {
-
-				script = document.createElement("script");
-
-				script.async = true;
-
-				if ( s.scriptCharset ) {
-					script.charset = s.scriptCharset;
-				}
-
-				script.src = s.url;
-
-				// Attach handlers for all browsers
-				script.onload = script.onreadystatechange = function( _, isAbort ) {
-
-					if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
-
-						// Handle memory leak in IE
-						script.onload = script.onreadystatechange = null;
-
-						// Remove the script
-						if ( script.parentNode ) {
-							script.parentNode.removeChild( script );
-						}
-
-						// Dereference the script
-						script = null;
-
-						// Callback if not abort
-						if ( !isAbort ) {
-							callback( 200, "success" );
-						}
-					}
-				};
-
-				// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
-				// Use native DOM manipulation to avoid our domManip AJAX trickery
-				head.insertBefore( script, head.firstChild );
-			},
-
-			abort: function() {
-				if ( script ) {
-					script.onload( undefined, true );
-				}
-			}
-		};
-	}
-});
-var oldCallbacks = [],
-	rjsonp = /(=)\?(?=&|$)|\?\?/;
-
-// Default jsonp settings
-jQuery.ajaxSetup({
-	jsonp: "callback",
-	jsonpCallback: function() {
-		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
-		this[ callback ] = true;
-		return callback;
-	}
-});
-
-// Detect, normalize options and install callbacks for jsonp requests
-jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
-
-	var callbackName, overwritten, responseContainer,
-		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
-			"url" :
-			typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
-		);
-
-	// Handle iff the expected data type is "jsonp" or we have a parameter to set
-	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
-
-		// Get callback name, remembering preexisting value associated with it
-		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
-			s.jsonpCallback() :
-			s.jsonpCallback;
-
-		// Insert callback into url or form data
-		if ( jsonProp ) {
-			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
-		} else if ( s.jsonp !== false ) {
-			s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
-		}
-
-		// Use data converter to retrieve json after script execution
-		s.converters["script json"] = function() {
-			if ( !responseContainer ) {
-				jQuery.error( callbackName + " was not called" );
-			}
-			return responseContainer[ 0 ];
-		};
-
-		// force json dataType
-		s.dataTypes[ 0 ] = "json";
-
-		// Install callback
-		overwritten = window[ callbackName ];
-		window[ callbackName ] = function() {
-			responseContainer = arguments;
-		};
-
-		// Clean-up function (fires after converters)
-		jqXHR.always(function() {
-			// Restore preexisting value
-			window[ callbackName ] = overwritten;
-
-			// Save back as free
-			if ( s[ callbackName ] ) {
-				// make sure that re-using the options doesn't screw things around
-				s.jsonpCallback = originalSettings.jsonpCallback;
-
-				// save the callback name for future use
-				oldCallbacks.push( callbackName );
-			}
-
-			// Call if it was a function and we have a response
-			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
-				overwritten( responseContainer[ 0 ] );
-			}
-
-			responseContainer = overwritten = undefined;
-		});
-
-		// Delegate to script
-		return "script";
-	}
-});
-var xhrCallbacks, xhrSupported,
-	xhrId = 0,
-	// #5280: Internet Explorer will keep connections alive if we don't abort on unload
-	xhrOnUnloadAbort = window.ActiveXObject && function() {
-		// Abort all pending requests
-		var key;
-		for ( key in xhrCallbacks ) {
-			xhrCallbacks[ key ]( undefined, true );
-		}
-	};
-
-// Functions to create xhrs
-function createStandardXHR() {
-	try {
-		return new window.XMLHttpRequest();
-	} catch( e ) {}
-}
-
-function createActiveXHR() {
-	try {
-		return new window.ActiveXObject("Microsoft.XMLHTTP");
-	} catch( e ) {}
-}
-
-// Create the request object
-// (This is still attached to ajaxSettings for backward compatibility)
-jQuery.ajaxSettings.xhr = window.ActiveXObject ?
-	/* Microsoft failed to properly
-	 * implement the XMLHttpRequest in IE7 (can't request local files),
-	 * so we use the ActiveXObject when it is available
-	 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
-	 * we need a fallback.
-	 */
-	function() {
-		return !this.isLocal && createStandardXHR() || createActiveXHR();
-	} :
-	// For all other browsers, use the standard XMLHttpRequest object
-	createStandardXHR;
-
-// Determine support properties
-xhrSupported = jQuery.ajaxSettings.xhr();
-jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
-xhrSupported = jQuery.support.ajax = !!xhrSupported;
-
-// Create transport if the browser can provide an xhr
-if ( xhrSupported ) {
-
-	jQuery.ajaxTransport(function( s ) {
-		// Cross domain only allowed if supported through XMLHttpRequest
-		if ( !s.crossDomain || jQuery.support.cors ) {
-
-			var callback;
-
-			return {
-				send: function( headers, complete ) {
-
-					// Get a new xhr
-					var handle, i,
-						xhr = s.xhr();
-
-					// Open the socket
-					// Passing null username, generates a login popup on Opera (#2865)
-					if ( s.username ) {
-						xhr.open( s.type, s.url, s.async, s.username, s.password );
-					} else {
-						xhr.open( s.type, s.url, s.async );
-					}
-
-					// Apply custom fields if provided
-					if ( s.xhrFields ) {
-						for ( i in s.xhrFields ) {
-							xhr[ i ] = s.xhrFields[ i ];
-						}
-					}
-
-					// Override mime type if needed
-					if ( s.mimeType && xhr.overrideMimeType ) {
-						xhr.overrideMimeType( s.mimeType );
-					}
-
-					// X-Requested-With header
-					// For cross-domain requests, seeing as conditions for a preflight are
-					// akin to a jigsaw puzzle, we simply never set it to be sure.
-					// (it can always be set on a per-request basis or even using ajaxSetup)
-					// For same-domain requests, won't change header if already provided.
-					if ( !s.crossDomain && !headers["X-Requested-With"] ) {
-						headers["X-Requested-With"] = "XMLHttpRequest";
-					}
-
-					// Need an extra try/catch for cross domain requests in Firefox 3
-					try {
-						for ( i in headers ) {
-							xhr.setRequestHeader( i, headers[ i ] );
-						}
-					} catch( err ) {}
-
-					// Do send the request
-					// This may raise an exception which is actually
-					// handled in jQuery.ajax (so no try/catch here)
-					xhr.send( ( s.hasContent && s.data ) || null );
-
-					// Listener
-					callback = function( _, isAbort ) {
-						var status, responseHeaders, statusText, responses;
-
-						// Firefox throws exceptions when accessing properties
-						// of an xhr when a network error occurred
-						// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
-						try {
-
-							// Was never called and is aborted or complete
-							if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
-
-								// Only called once
-								callback = undefined;
-
-								// Do not keep as active anymore
-								if ( handle ) {
-									xhr.onreadystatechange = jQuery.noop;
-									if ( xhrOnUnloadAbort ) {
-										delete xhrCallbacks[ handle ];
-									}
-								}
-
-								// If it's an abort
-								if ( isAbort ) {
-									// Abort it manually if needed
-									if ( xhr.readyState !== 4 ) {
-										xhr.abort();
-									}
-								} else {
-									responses = {};
-									status = xhr.status;
-									responseHeaders = xhr.getAllResponseHeaders();
-
-									// When requesting binary data, IE6-9 will throw an exception
-									// on any attempt to access responseText (#11426)
-									if ( typeof xhr.responseText === "string" ) {
-										responses.text = xhr.responseText;
-									}
-
-									// Firefox throws an exception when accessing
-									// statusText for faulty cross-domain requests
-									try {
-										statusText = xhr.statusText;
-									} catch( e ) {
-										// We normalize with Webkit giving an empty statusText
-										statusText = "";
-									}
-
-									// Filter status for non standard behaviors
-
-									// If the request is local and we have data: assume a success
-									// (success with no data won't get notified, that's the best we
-									// can do given current implementations)
-									if ( !status && s.isLocal && !s.crossDomain ) {
-										status = responses.text ? 200 : 404;
-									// IE - #1450: sometimes returns 1223 when it should be 204
-									} else if ( status === 1223 ) {
-										status = 204;
-									}
-								}
-							}
-						} catch( firefoxAccessException ) {
-							if ( !isAbort ) {
-								complete( -1, firefoxAccessException );
-							}
-						}
-
-						// Call complete if needed
-						if ( responses ) {
-							complete( status, statusText, responses, responseHeaders );
-						}
-					};
-
-					if ( !s.async ) {
-						// if we're in sync mode we fire the callback
-						callback();
-					} else if ( xhr.readyState === 4 ) {
-						// (IE6 & IE7) if it's in cache and has been
-						// retrieved directly we need to fire the callback
-						setTimeout( callback );
-					} else {
-						handle = ++xhrId;
-						if ( xhrOnUnloadAbort ) {
-							// Create the active xhrs callbacks list if needed
-							// and attach the unload handler
-							if ( !xhrCallbacks ) {
-								xhrCallbacks = {};
-								jQuery( window ).unload( xhrOnUnloadAbort );
-							}
-							// Add to list of active xhrs callbacks
-							xhrCallbacks[ handle ] = callback;
-						}
-						xhr.onreadystatechange = callback;
-					}
-				},
-
-				abort: function() {
-					if ( callback ) {
-						callback( undefined, true );
-					}
-				}
-			};
-		}
-	});
-}
-var fxNow, timerId,
-	rfxtypes = /^(?:toggle|show|hide)$/,
-	rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
-	rrun = /queueHooks$/,
-	animationPrefilters = [ defaultPrefilter ],
-	tweeners = {
-		"*": [function( prop, value ) {
-			var end, unit,
-				tween = this.createTween( prop, value ),
-				parts = rfxnum.exec( value ),
-				target = tween.cur(),
-				start = +target || 0,
-				scale = 1,
-				maxIterations = 20;
-
-			if ( parts ) {
-				end = +parts[2];
-				unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" );
-
-				// We need to compute starting value
-				if ( unit !== "px" && start ) {
-					// Iteratively approximate from a nonzero starting point
-					// Prefer the current property, because this process will be trivial if it uses the same units
-					// Fallback to end or a simple constant
-					start = jQuery.css( tween.elem, prop, true ) || end || 1;
-
-					do {
-						// If previous iteration zeroed out, double until we get *something*
-						// Use a string for doubling factor so we don't accidentally see scale as unchanged below
-						scale = scale || ".5";
-
-						// Adjust and apply
-						start = start / scale;
-						jQuery.style( tween.elem, prop, start + unit );
-
-					// Update scale, tolerating zero or NaN from tween.cur()
-					// And breaking the loop if scale is unchanged or perfect, or if we've just had enough
-					} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
-				}
-
-				tween.unit = unit;
-				tween.start = start;
-				// If a +=/-= token was provided, we're doing a relative animation
-				tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;
-			}
-			return tween;
-		}]
-	};
-
-// Animations created synchronously will run synchronously
-function createFxNow() {
-	setTimeout(function() {
-		fxNow = undefined;
-	});
-	return ( fxNow = jQuery.now() );
-}
-
-function createTweens( animation, props ) {
-	jQuery.each( props, function( prop, value ) {
-		var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
-			index = 0,
-			length = collection.length;
-		for ( ; index < length; index++ ) {
-			if ( collection[ index ].call( animation, prop, value ) ) {
-
-				// we're done with this property
-				return;
-			}
-		}
-	});
-}
-
-function Animation( elem, properties, options ) {
-	var result,
-		stopped,
-		index = 0,
-		length = animationPrefilters.length,
-		deferred = jQuery.Deferred().always( function() {
-			// don't match elem in the :animated selector
-			delete tick.elem;
-		}),
-		tick = function() {
-			if ( stopped ) {
-				return false;
-			}
-			var currentTime = fxNow || createFxNow(),
-				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
-				// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
-				temp = remaining / animation.duration || 0,
-				percent = 1 - temp,
-				index = 0,
-				length = animation.tweens.length;
-
-			for ( ; index < length ; index++ ) {
-				animation.tweens[ index ].run( percent );
-			}
-
-			deferred.notifyWith( elem, [ animation, percent, remaining ]);
-
-			if ( percent < 1 && length ) {
-				return remaining;
-			} else {
-				deferred.resolveWith( elem, [ animation ] );
-				return false;
-			}
-		},
-		animation = deferred.promise({
-			elem: elem,
-			props: jQuery.extend( {}, properties ),
-			opts: jQuery.extend( true, { specialEasing: {} }, options ),
-			originalProperties: properties,
-			originalOptions: options,
-			startTime: fxNow || createFxNow(),
-			duration: options.duration,
-			tweens: [],
-			createTween: function( prop, end ) {
-				var tween = jQuery.Tween( elem, animation.opts, prop, end,
-						animation.opts.specialEasing[ prop ] || animation.opts.easing );
-				animation.tweens.push( tween );
-				return tween;
-			},
-			stop: function( gotoEnd ) {
-				var index = 0,
-					// if we are going to the end, we want to run all the tweens
-					// otherwise we skip this part
-					length = gotoEnd ? animation.tweens.length : 0;
-				if ( stopped ) {
-					return this;
-				}
-				stopped = true;
-				for ( ; index < length ; index++ ) {
-					animation.tweens[ index ].run( 1 );
-				}
-
-				// resolve when we played the last frame
-				// otherwise, reject
-				if ( gotoEnd ) {
-					deferred.resolveWith( elem, [ animation, gotoEnd ] );
-				} else {
-					deferred.rejectWith( elem, [ animation, gotoEnd ] );
-				}
-				return this;
-			}
-		}),
-		props = animation.props;
-
-	propFilter( props, animation.opts.specialEasing );
-
-	for ( ; index < length ; index++ ) {
-		result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
-		if ( result ) {
-			return result;
-		}
-	}
-
-	createTweens( animation, props );
-
-	if ( jQuery.isFunction( animation.opts.start ) ) {
-		animation.opts.start.call( elem, animation );
-	}
-
-	jQuery.fx.timer(
-		jQuery.extend( tick, {
-			elem: elem,
-			anim: animation,
-			queue: animation.opts.queue
-		})
-	);
-
-	// attach callbacks from options
-	return animation.progress( animation.opts.progress )
-		.done( animation.opts.done, animation.opts.complete )
-		.fail( animation.opts.fail )
-		.always( animation.opts.always );
-}
-
-function propFilter( props, specialEasing ) {
-	var value, name, index, easing, hooks;
-
-	// camelCase, specialEasing and expand cssHook pass
-	for ( index in props ) {
-		name = jQuery.camelCase( index );
-		easing = specialEasing[ name ];
-		value = props[ index ];
-		if ( jQuery.isArray( value ) ) {
-			easing = value[ 1 ];
-			value = props[ index ] = value[ 0 ];
-		}
-
-		if ( index !== name ) {
-			props[ name ] = value;
-			delete props[ index ];
-		}
-
-		hooks = jQuery.cssHooks[ name ];
-		if ( hooks && "expand" in hooks ) {
-			value = hooks.expand( value );
-			delete props[ name ];
-
-			// not quite $.extend, this wont overwrite keys already present.
-			// also - reusing 'index' from above because we have the correct "name"
-			for ( index in value ) {
-				if ( !( index in props ) ) {
-					props[ index ] = value[ index ];
-					specialEasing[ index ] = easing;
-				}
-			}
-		} else {
-			specialEasing[ name ] = easing;
-		}
-	}
-}
-
-jQuery.Animation = jQuery.extend( Animation, {
-
-	tweener: function( props, callback ) {
-		if ( jQuery.isFunction( props ) ) {
-			callback = props;
-			props = [ "*" ];
-		} else {
-			props = props.split(" ");
-		}
-
-		var prop,
-			index = 0,
-			length = props.length;
-
-		for ( ; index < length ; index++ ) {
-			prop = props[ index ];
-			tweeners[ prop ] = tweeners[ prop ] || [];
-			tweeners[ prop ].unshift( callback );
-		}
-	},
-
-	prefilter: function( callback, prepend ) {
-		if ( prepend ) {
-			animationPrefilters.unshift( callback );
-		} else {
-			animationPrefilters.push( callback );
-		}
-	}
-});
-
-function defaultPrefilter( elem, props, opts ) {
-	/*jshint validthis:true */
-	var prop, index, length,
-		value, dataShow, toggle,
-		tween, hooks, oldfire,
-		anim = this,
-		style = elem.style,
-		orig = {},
-		handled = [],
-		hidden = elem.nodeType && isHidden( elem );
-
-	// handle queue: false promises
-	if ( !opts.queue ) {
-		hooks = jQuery._queueHooks( elem, "fx" );
-		if ( hooks.unqueued == null ) {
-			hooks.unqueued = 0;
-			oldfire = hooks.empty.fire;
-			hooks.empty.fire = function() {
-				if ( !hooks.unqueued ) {
-					oldfire();
-				}
-			};
-		}
-		hooks.unqueued++;
-
-		anim.always(function() {
-			// doing this makes sure that the complete handler will be called
-			// before this completes
-			anim.always(function() {
-				hooks.unqueued--;
-				if ( !jQuery.queue( elem, "fx" ).length ) {
-					hooks.empty.fire();
-				}
-			});
-		});
-	}
-
-	// height/width overflow pass
-	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
-		// Make sure that nothing sneaks out
-		// Record all 3 overflow attributes because IE does not
-		// change the overflow attribute when overflowX and
-		// overflowY are set to the same value
-		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
-
-		// Set display property to inline-block for height/width
-		// animations on inline elements that are having width/height animated
-		if ( jQuery.css( elem, "display" ) === "inline" &&
-				jQuery.css( elem, "float" ) === "none" ) {
-
-			// inline-level elements accept inline-block;
-			// block-level elements need to be inline with layout
-			if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) {
-				style.display = "inline-block";
-
-			} else {
-				style.zoom = 1;
-			}
-		}
-	}
-
-	if ( opts.overflow ) {
-		style.overflow = "hidden";
-		if ( !jQuery.support.shrinkWrapBlocks ) {
-			anim.always(function() {
-				style.overflow = opts.overflow[ 0 ];
-				style.overflowX = opts.overflow[ 1 ];
-				style.overflowY = opts.overflow[ 2 ];
-			});
-		}
-	}
-
-
-	// show/hide pass
-	for ( index in props ) {
-		value = props[ index ];
-		if ( rfxtypes.exec( value ) ) {
-			delete props[ index ];
-			toggle = toggle || value === "toggle";
-			if ( value === ( hidden ? "hide" : "show" ) ) {
-				continue;
-			}
-			handled.push( index );
-		}
-	}
-
-	length = handled.length;
-	if ( length ) {
-		dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} );
-		if ( "hidden" in dataShow ) {
-			hidden = dataShow.hidden;
-		}
-
-		// store state if its toggle - enables .stop().toggle() to "reverse"
-		if ( toggle ) {
-			dataShow.hidden = !hidden;
-		}
-		if ( hidden ) {
-			jQuery( elem ).show();
-		} else {
-			anim.done(function() {
-				jQuery( elem ).hide();
-			});
-		}
-		anim.done(function() {
-			var prop;
-			jQuery._removeData( elem, "fxshow" );
-			for ( prop in orig ) {
-				jQuery.style( elem, prop, orig[ prop ] );
-			}
-		});
-		for ( index = 0 ; index < length ; index++ ) {
-			prop = handled[ index ];
-			tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );
-			orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );
-
-			if ( !( prop in dataShow ) ) {
-				dataShow[ prop ] = tween.start;
-				if ( hidden ) {
-					tween.end = tween.start;
-					tween.start = prop === "width" || prop === "height" ? 1 : 0;
-				}
-			}
-		}
-	}
-}
-
-function Tween( elem, options, prop, end, easing ) {
-	return new Tween.prototype.init( elem, options, prop, end, easing );
-}
-jQuery.Tween = Tween;
-
-Tween.prototype = {
-	constructor: Tween,
-	init: function( elem, options, prop, end, easing, unit ) {
-		this.elem = elem;
-		this.prop = prop;
-		this.easing = easing || "swing";
-		this.options = options;
-		this.start = this.now = this.cur();
-		this.end = end;
-		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
-	},
-	cur: function() {
-		var hooks = Tween.propHooks[ this.prop ];
-
-		return hooks && hooks.get ?
-			hooks.get( this ) :
-			Tween.propHooks._default.get( this );
-	},
-	run: function( percent ) {
-		var eased,
-			hooks = Tween.propHooks[ this.prop ];
-
-		if ( this.options.duration ) {
-			this.pos = eased = jQuery.easing[ this.easing ](
-				percent, this.options.duration * percent, 0, 1, this.options.duration
-			);
-		} else {
-			this.pos = eased = percent;
-		}
-		this.now = ( this.end - this.start ) * eased + this.start;
-
-		if ( this.options.step ) {
-			this.options.step.call( this.elem, this.now, this );
-		}
-
-		if ( hooks && hooks.set ) {
-			hooks.set( this );
-		} else {
-			Tween.propHooks._default.set( this );
-		}
-		return this;
-	}
-};
-
-Tween.prototype.init.prototype = Tween.prototype;
-
-Tween.propHooks = {
-	_default: {
-		get: function( tween ) {
-			var result;
-
-			if ( tween.elem[ tween.prop ] != null &&
-				(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
-				return tween.elem[ tween.prop ];
-			}
-
-			// passing an empty string as a 3rd parameter to .css will automatically
-			// attempt a parseFloat and fallback to a string if the parse fails
-			// so, simple values such as "10px" are parsed to Float.
-			// complex values such as "rotate(1rad)" are returned as is.
-			result = jQuery.css( tween.elem, tween.prop, "" );
-			// Empty strings, null, undefined and "auto" are converted to 0.
-			return !result || result === "auto" ? 0 : result;
-		},
-		set: function( tween ) {
-			// use step hook for back compat - use cssHook if its there - use .style if its
-			// available and use plain properties where available
-			if ( jQuery.fx.step[ tween.prop ] ) {
-				jQuery.fx.step[ tween.prop ]( tween );
-			} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
-				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
-			} else {
-				tween.elem[ tween.prop ] = tween.now;
-			}
-		}
-	}
-};
-
-// Remove in 2.0 - this supports IE8's panic based approach
-// to setting things on disconnected nodes
-
-Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
-	set: function( tween ) {
-		if ( tween.elem.nodeType && tween.elem.parentNode ) {
-			tween.elem[ tween.prop ] = tween.now;
-		}
-	}
-};
-
-jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
-	var cssFn = jQuery.fn[ name ];
-	jQuery.fn[ name ] = function( speed, easing, callback ) {
-		return speed == null || typeof speed === "boolean" ?
-			cssFn.apply( this, arguments ) :
-			this.animate( genFx( name, true ), speed, easing, callback );
-	};
-});
-
-jQuery.fn.extend({
-	fadeTo: function( speed, to, easing, callback ) {
-
-		// show any hidden elements after setting opacity to 0
-		return this.filter( isHidden ).css( "opacity", 0 ).show()
-
-			// animate to the value specified
-			.end().animate({ opacity: to }, speed, easing, callback );
-	},
-	animate: function( prop, speed, easing, callback ) {
-		var empty = jQuery.isEmptyObject( prop ),
-			optall = jQuery.speed( speed, easing, callback ),
-			doAnimation = function() {
-				// Operate on a copy of prop so per-property easing won't be lost
-				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
-				doAnimation.finish = function() {
-					anim.stop( true );
-				};
-				// Empty animations, or finishing resolves immediately
-				if ( empty || jQuery._data( this, "finish" ) ) {
-					anim.stop( true );
-				}
-			};
-			doAnimation.finish = doAnimation;
-
-		return empty || optall.queue === false ?
-			this.each( doAnimation ) :
-			this.queue( optall.queue, doAnimation );
-	},
-	stop: function( type, clearQueue, gotoEnd ) {
-		var stopQueue = function( hooks ) {
-			var stop = hooks.stop;
-			delete hooks.stop;
-			stop( gotoEnd );
-		};
-
-		if ( typeof type !== "string" ) {
-			gotoEnd = clearQueue;
-			clearQueue = type;
-			type = undefined;
-		}
-		if ( clearQueue && type !== false ) {
-			this.queue( type || "fx", [] );
-		}
-
-		return this.each(function() {
-			var dequeue = true,
-				index = type != null && type + "queueHooks",
-				timers = jQuery.timers,
-				data = jQuery._data( this );
-
-			if ( index ) {
-				if ( data[ index ] && data[ index ].stop ) {
-					stopQueue( data[ index ] );
-				}
-			} else {
-				for ( index in data ) {
-					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
-						stopQueue( data[ index ] );
-					}
-				}
-			}
-
-			for ( index = timers.length; index--; ) {
-				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
-					timers[ index ].anim.stop( gotoEnd );
-					dequeue = false;
-					timers.splice( index, 1 );
-				}
-			}
-
-			// start the next in the queue if the last step wasn't forced
-			// timers currently will call their complete callbacks, which will dequeue
-			// but only if they were gotoEnd
-			if ( dequeue || !gotoEnd ) {
-				jQuery.dequeue( this, type );
-			}
-		});
-	},
-	finish: function( type ) {
-		if ( type !== false ) {
-			type = type || "fx";
-		}
-		return this.each(function() {
-			var index,
-				data = jQuery._data( this ),
-				queue = data[ type + "queue" ],
-				hooks = data[ type + "queueHooks" ],
-				timers = jQuery.timers,
-				length = queue ? queue.length : 0;
-
-			// enable finishing flag on private data
-			data.finish = true;
-
-			// empty the queue first
-			jQuery.queue( this, type, [] );
-
-			if ( hooks && hooks.cur && hooks.cur.finish ) {
-				hooks.cur.finish.call( this );
-			}
-
-			// look for any active animations, and finish them
-			for ( index = timers.length; index--; ) {
-				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
-					timers[ index ].anim.stop( true );
-					timers.splice( index, 1 );
-				}
-			}
-
-			// look for any animations in the old queue and finish them
-			for ( index = 0; index < length; index++ ) {
-				if ( queue[ index ] && queue[ index ].finish ) {
-					queue[ index ].finish.call( this );
-				}
-			}
-
-			// turn off finishing flag
-			delete data.finish;
-		});
-	}
-});
-
-// Generate parameters to create a standard animation
-function genFx( type, includeWidth ) {
-	var which,
-		attrs = { height: type },
-		i = 0;
-
-	// if we include width, step value is 1 to do all cssExpand values,
-	// if we don't include width, step value is 2 to skip over Left and Right
-	includeWidth = includeWidth? 1 : 0;
-	for( ; i < 4 ; i += 2 - includeWidth ) {
-		which = cssExpand[ i ];
-		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
-	}
-
-	if ( includeWidth ) {
-		attrs.opacity = attrs.width = type;
-	}
-
-	return attrs;
-}
-
-// Generate shortcuts for custom animations
-jQuery.each({
-	slideDown: genFx("show"),
-	slideUp: genFx("hide"),
-	slideToggle: genFx("toggle"),
-	fadeIn: { opacity: "show" },
-	fadeOut: { opacity: "hide" },
-	fadeToggle: { opacity: "toggle" }
-}, function( name, props ) {
-	jQuery.fn[ name ] = function( speed, easing, callback ) {
-		return this.animate( props, speed, easing, callback );
-	};
-});
-
-jQuery.speed = function( speed, easing, fn ) {
-	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
-		complete: fn || !fn && easing ||
-			jQuery.isFunction( speed ) && speed,
-		duration: speed,
-		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
-	};
-
-	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
-		opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
-
-	// normalize opt.queue - true/undefined/null -> "fx"
-	if ( opt.queue == null || opt.queue === true ) {
-		opt.queue = "fx";
-	}
-
-	// Queueing
-	opt.old = opt.complete;
-
-	opt.complete = function() {
-		if ( jQuery.isFunction( opt.old ) ) {
-			opt.old.call( this );
-		}
-
-		if ( opt.queue ) {
-			jQuery.dequeue( this, opt.queue );
-		}
-	};
-
-	return opt;
-};
-
-jQuery.easing = {
-	linear: function( p ) {
-		return p;
-	},
-	swing: function( p ) {
-		return 0.5 - Math.cos( p*Math.PI ) / 2;
-	}
-};
-
-jQuery.timers = [];
-jQuery.fx = Tween.prototype.init;
-jQuery.fx.tick = function() {
-	var timer,
-		timers = jQuery.timers,
-		i = 0;
-
-	fxNow = jQuery.now();
-
-	for ( ; i < timers.length; i++ ) {
-		timer = timers[ i ];
-		// Checks the timer has not already been removed
-		if ( !timer() && timers[ i ] === timer ) {
-			timers.splice( i--, 1 );
-		}
-	}
-
-	if ( !timers.length ) {
-		jQuery.fx.stop();
-	}
-	fxNow = undefined;
-};
-
-jQuery.fx.timer = function( timer ) {
-	if ( timer() && jQuery.timers.push( timer ) ) {
-		jQuery.fx.start();
-	}
-};
-
-jQuery.fx.interval = 13;
-
-jQuery.fx.start = function() {
-	if ( !timerId ) {
-		timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
-	}
-};
-
-jQuery.fx.stop = function() {
-	clearInterval( timerId );
-	timerId = null;
-};
-
-jQuery.fx.speeds = {
-	slow: 600,
-	fast: 200,
-	// Default speed
-	_default: 400
-};
-
-// Back Compat <1.8 extension point
-jQuery.fx.step = {};
-
-if ( jQuery.expr && jQuery.expr.filters ) {
-	jQuery.expr.filters.animated = function( elem ) {
-		return jQuery.grep(jQuery.timers, function( fn ) {
-			return elem === fn.elem;
-		}).length;
-	};
-}
-jQuery.fn.offset = function( options ) {
-	if ( arguments.length ) {
-		return options === undefined ?
-			this :
-			this.each(function( i ) {
-				jQuery.offset.setOffset( this, options, i );
-			});
-	}
-
-	var docElem, win,
-		box = { top: 0, left: 0 },
-		elem = this[ 0 ],
-		doc = elem && elem.ownerDocument;
-
-	if ( !doc ) {
-		return;
-	}
-
-	docElem = doc.documentElement;
-
-	// Make sure it's not a disconnected DOM node
-	if ( !jQuery.contains( docElem, elem ) ) {
-		return box;
-	}
-
-	// If we don't have gBCR, just use 0,0 rather than error
-	// BlackBerry 5, iOS 3 (original iPhone)
-	if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
-		box = elem.getBoundingClientRect();
-	}
-	win = getWindow( doc );
-	return {
-		top: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),
-		left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
-	};
-};
-
-jQuery.offset = {
-
-	setOffset: function( elem, options, i ) {
-		var position = jQuery.css( elem, "position" );
-
-		// set position first, in-case top/left are set even on static elem
-		if ( position === "static" ) {
-			elem.style.position = "relative";
-		}
-
-		var curElem = jQuery( elem ),
-			curOffset = curElem.offset(),
-			curCSSTop = jQuery.css( elem, "top" ),
-			curCSSLeft = jQuery.css( elem, "left" ),
-			calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
-			props = {}, curPosition = {}, curTop, curLeft;
-
-		// need to be able to calculate position if either top or left is auto and position is either absolute or fixed
-		if ( calculatePosition ) {
-			curPosition = curElem.position();
-			curTop = curPosition.top;
-			curLeft = curPosition.left;
-		} else {
-			curTop = parseFloat( curCSSTop ) || 0;
-			curLeft = parseFloat( curCSSLeft ) || 0;
-		}
-
-		if ( jQuery.isFunction( options ) ) {
-			options = options.call( elem, i, curOffset );
-		}
-
-		if ( options.top != null ) {
-			props.top = ( options.top - curOffset.top ) + curTop;
-		}
-		if ( options.left != null ) {
-			props.left = ( options.left - curOffset.left ) + curLeft;
-		}
-
-		if ( "using" in options ) {
-			options.using.call( elem, props );
-		} else {
-			curElem.css( props );
-		}
-	}
-};
-
-
-jQuery.fn.extend({
-
-	position: function() {
-		if ( !this[ 0 ] ) {
-			return;
-		}
-
-		var offsetParent, offset,
-			parentOffset = { top: 0, left: 0 },
-			elem = this[ 0 ];
-
-		// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
-		if ( jQuery.css( elem, "position" ) === "fixed" ) {
-			// we assume that getBoundingClientRect is available when computed position is fixed
-			offset = elem.getBoundingClientRect();
-		} else {
-			// Get *real* offsetParent
-			offsetParent = this.offsetParent();
-
-			// Get correct offsets
-			offset = this.offset();
-			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
-				parentOffset = offsetParent.offset();
-			}
-
-			// Add offsetParent borders
-			parentOffset.top  += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
-			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
-		}
-
-		// Subtract parent offsets and element margins
-		// note: when an element has margin: auto the offsetLeft and marginLeft
-		// are the same in Safari causing offset.left to incorrectly be 0
-		return {
-			top:  offset.top  - parentOffset.top - jQuery.css( elem, "marginTop", true ),
-			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
-		};
-	},
-
-	offsetParent: function() {
-		return this.map(function() {
-			var offsetParent = this.offsetParent || document.documentElement;
-			while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
-				offsetParent = offsetParent.offsetParent;
-			}
-			return offsetParent || document.documentElement;
-		});
-	}
-});
-
-
-// Create scrollLeft and scrollTop methods
-jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
-	var top = /Y/.test( prop );
-
-	jQuery.fn[ method ] = function( val ) {
-		return jQuery.access( this, function( elem, method, val ) {
-			var win = getWindow( elem );
-
-			if ( val === undefined ) {
-				return win ? (prop in win) ? win[ prop ] :
-					win.document.documentElement[ method ] :
-					elem[ method ];
-			}
-
-			if ( win ) {
-				win.scrollTo(
-					!top ? val : jQuery( win ).scrollLeft(),
-					top ? val : jQuery( win ).scrollTop()
-				);
-
-			} else {
-				elem[ method ] = val;
-			}
-		}, method, val, arguments.length, null );
-	};
-});
-
-function getWindow( elem ) {
-	return jQuery.isWindow( elem ) ?
-		elem :
-		elem.nodeType === 9 ?
-			elem.defaultView || elem.parentWindow :
-			false;
-}
-// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
-jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
-	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
-		// margin is only for outerHeight, outerWidth
-		jQuery.fn[ funcName ] = function( margin, value ) {
-			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
-				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
-
-			return jQuery.access( this, function( elem, type, value ) {
-				var doc;
-
-				if ( jQuery.isWindow( elem ) ) {
-					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
-					// isn't a whole lot we can do. See pull request at this URL for discussion:
-					// https://github.com/jquery/jquery/pull/764
-					return elem.document.documentElement[ "client" + name ];
-				}
-
-				// Get document width or height
-				if ( elem.nodeType === 9 ) {
-					doc = elem.documentElement;
-
-					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
-					// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
-					return Math.max(
-						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
-						elem.body[ "offset" + name ], doc[ "offset" + name ],
-						doc[ "client" + name ]
-					);
-				}
-
-				return value === undefined ?
-					// Get width or height on the element, requesting but not forcing parseFloat
-					jQuery.css( elem, type, extra ) :
-
-					// Set width or height on the element
-					jQuery.style( elem, type, value, extra );
-			}, type, chainable ? margin : undefined, chainable, null );
-		};
-	});
-});
-// Limit scope pollution from any deprecated API
-// (function() {
-
-// })();
-// Expose jQuery to the global object
-window.jQuery = window.$ = jQuery;
-
-// Expose jQuery as an AMD module, but only for AMD loaders that
-// understand the issues with loading multiple versions of jQuery
-// in a page that all might call define(). The loader will indicate
-// they have special allowances for multiple jQuery versions by
-// specifying define.amd.jQuery = true. Register as a named module,
-// since jQuery can be concatenated with other files that may use define,
-// but not use a proper concatenation script that understands anonymous
-// AMD modules. A named AMD is safest and most robust way to register.
-// Lowercase jquery is used because AMD module names are derived from
-// file names, and jQuery is normally delivered in a lowercase file name.
-// Do this after creating the global so that if an AMD module wants to call
-// noConflict to hide this version of jQuery, it will work.
-if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
-	define( "jquery", [], function () { return jQuery; } );
-}
-
-})( window );
deleted file mode 100644
index 75cdf246af2ce175e72b45314052203fd04a4428..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/js/src/jsapi-tests/binast/parser/tester/frameworks/jquery.mobile-1.4.js
+++ /dev/null
@@ -1,15056 +0,0 @@
-/*!
-* jQuery Mobile 1.4.2
-* Git HEAD hash: 9d9a42a27d0c693e8b5569c3a10d771916af5045 <> Date: Fri Feb 28 2014 17:32:01 UTC
-* http://jquerymobile.com
-*
-* Copyright 2010, 2014 jQuery Foundation, Inc. and other contributors
-* Released under the MIT license.
-* http://jquery.org/license
-*
-*/
-
-
-(function ( root, doc, factory ) {
-	if ( typeof define === "function" && define.amd ) {
-		// AMD. Register as an anonymous module.
-		define( [ "jquery" ], function ( $ ) {
-			factory( $, root, doc );
-			return $.mobile;
-		});
-	} else {
-		// Browser globals
-		factory( root.jQuery, root, doc );
-	}
-}( this, document, function ( jQuery, window, document, undefined ) {
-(function( $ ) {
-	$.mobile = {};
-}( jQuery ));
-
-(function( $, window, undefined ) {
-	$.extend( $.mobile, {
-
-		// Version of the jQuery Mobile Framework
-		version: "1.4.2",
-
-		// Deprecated and no longer used in 1.4 remove in 1.5
-		// Define the url parameter used for referencing widget-generated sub-pages.
-		// Translates to example.html&ui-page=subpageIdentifier
-		// hash segment before &ui-page= is used to make Ajax request
-		subPageUrlKey: "ui-page",
-
-		hideUrlBar: true,
-
-		// Keepnative Selector
-		keepNative: ":jqmData(role='none'), :jqmData(role='nojs')",
-
-		// Deprecated in 1.4 remove in 1.5
-		// Class assigned to page currently in view, and during transitions
-		activePageClass: "ui-page-active",
-
-		// Deprecated in 1.4 remove in 1.5
-		// Class used for "active" button state, from CSS framework
-		activeBtnClass: "ui-btn-active",
-
-		// Deprecated in 1.4 remove in 1.5
-		// Class used for "focus" form element state, from CSS framework
-		focusClass: "ui-focus",
-
-		// Automatically handle clicks and form submissions through Ajax, when same-domain
-		ajaxEnabled: true,
-
-		// Automatically load and show pages based on location.hash
-		hashListeningEnabled: true,
-
-		// disable to prevent jquery from bothering with links
-		linkBindingEnabled: true,
-
-		// Set default page transition - 'none' for no transitions
-		defaultPageTransition: "fade",
-
-		// Set maximum window width for transitions to apply - 'false' for no limit
-		maxTransitionWidth: false,
-
-		// Minimum scroll distance that will be remembered when returning to a page
-		// Deprecated remove in 1.5
-		minScrollBack: 0,
-
-		// Set default dialog transition - 'none' for no transitions
-		defaultDialogTransition: "pop",
-
-		// Error response message - appears when an Ajax page request fails
-		pageLoadErrorMessage: "Error Loading Page",
-
-		// For error messages, which theme does the box uses?
-		pageLoadErrorMessageTheme: "a",
-
-		// replace calls to window.history.back with phonegaps navigation helper
-		// where it is provided on the window object
-		phonegapNavigationEnabled: false,
-
-		//automatically initialize the DOM when it's ready
-		autoInitializePage: true,
-
-		pushStateEnabled: true,
-
-		// allows users to opt in to ignoring content by marking a parent element as
-		// data-ignored
-		ignoreContentEnabled: false,
-
-		buttonMarkup: {
-			hoverDelay: 200
-		},
-
-		// disable the alteration of the dynamic base tag or links in the case
-		// that a dynamic base tag isn't supported
-		dynamicBaseEnabled: true,
-
-		// default the property to remove dependency on assignment in init module
-		pageContainer: $(),
-
-		//enable cross-domain page support
-		allowCrossDomainPages: false,
-
-		dialogHashKey: "&ui-state=dialog"
-	});
-})( jQuery, this );
-
-(function( $, window, undefined ) {
-	var nsNormalizeDict = {},
-		oldFind = $.find,
-		rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
-		jqmDataRE = /:jqmData\(([^)]*)\)/g;
-
-	$.extend( $.mobile, {
-
-		// Namespace used framework-wide for data-attrs. Default is no namespace
-
-		ns: "",
-
-		// Retrieve an attribute from an element and perform some massaging of the value
-
-		getAttribute: function( element, key ) {
-			var data;
-
-			element = element.jquery ? element[0] : element;
-
-			if ( element && element.getAttribute ) {
-				data = element.getAttribute( "data-" + $.mobile.ns + key );
-			}
-
-			// Copied from core's src/data.js:dataAttr()
-			// Convert from a string to a proper data type
-			try {
-				data = data === "true" ? true :
-					data === "false" ? false :
-					data === "null" ? null :
-					// Only convert to a number if it doesn't change the string
-					+data + "" === data ? +data :
-					rbrace.test( data ) ? JSON.parse( data ) :
-					data;
-			} catch( err ) {}
-
-			return data;
-		},
-
-		// Expose our cache for testing purposes.
-		nsNormalizeDict: nsNormalizeDict,
-
-		// Take a data attribute property, prepend the namespace
-		// and then camel case the attribute string. Add the result
-		// to our nsNormalizeDict so we don't have to do this again.
-		nsNormalize: function( prop ) {
-			return nsNormalizeDict[ prop ] ||
-				( nsNormalizeDict[ prop ] = $.camelCase( $.mobile.ns + prop ) );
-		},
-
-		// Find the closest javascript page element to gather settings data jsperf test
-		// http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit
-		// possibly naive, but it shows that the parsing overhead for *just* the page selector vs
-		// the page and dialog selector is negligable. This could probably be speed up by
-		// doing a similar parent node traversal to the one found in the inherited theme code above
-		closestPageData: function( $target ) {
-			return $target
-				.closest( ":jqmData(role='page'), :jqmData(role='dialog')" )
-				.data( "mobile-page" );
-		}
-
-	});
-
-	// Mobile version of data and removeData and hasData methods
-	// ensures all data is set and retrieved using jQuery Mobile's data namespace
-	$.fn.jqmData = function( prop, value ) {
-		var result;
-		if ( typeof prop !== "undefined" ) {
-			if ( prop ) {
-				prop = $.mobile.nsNormalize( prop );
-			}
-
-			// undefined is permitted as an explicit input for the second param
-			// in this case it returns the value and does not set it to undefined
-			if ( arguments.length < 2 || value === undefined ) {
-				result = this.data( prop );
-			} else {
-				result = this.data( prop, value );
-			}
-		}
-		return result;
-	};
-
-	$.jqmData = function( elem, prop, value ) {
-		var result;
-		if ( typeof prop !== "undefined" ) {
-			result = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value );
-		}
-		return result;
-	};
-
-	$.fn.jqmRemoveData = function( prop ) {
-		return this.removeData( $.mobile.nsNormalize( prop ) );
-	};
-
-	$.jqmRemoveData = function( elem, prop ) {
-		return $.removeData( elem, $.mobile.nsNormalize( prop ) );
-	};
-
-	$.find = function( selector, context, ret, extra ) {
-		if ( selector.indexOf( ":jqmData" ) > -1 ) {
-			selector = selector.replace( jqmDataRE, "[data-" + ( $.mobile.ns || "" ) + "$1]" );
-		}
-
-		return oldFind.call( this, selector, context, ret, extra );
-	};
-
-	$.extend( $.find, oldFind );
-
-})( jQuery, this );
-
-/*!
- * jQuery UI Core c0ab71056b936627e8a7821f03c044aec6280a40
- * http://jqueryui.com
- *
- * Copyright 2013 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://api.jqueryui.com/category/ui-core/
- */
-(function( $, undefined ) {
-
-var uuid = 0,
-	runiqueId = /^ui-id-\d+$/;
-
-// $.ui might exist from components with no dependencies, e.g., $.ui.position
-$.ui = $.ui || {};
-
-$.extend( $.ui, {
-	version: "c0ab71056b936627e8a7821f03c044aec6280a40",
-
-	keyCode: {
-		BACKSPACE: 8,
-		COMMA: 188,
-		DELETE: 46,
-		DOWN: 40,
-		END: 35,
-		ENTER: 13,
-		ESCAPE: 27,
-		HOME: 36,
-		LEFT: 37,
-		PAGE_DOWN: 34,
-		PAGE_UP: 33,
-		PERIOD: 190,
-		RIGHT: 39,
-		SPACE: 32,
-		TAB: 9,
-		UP: 38
-	}
-});
-
-// plugins
-$.fn.extend({
-	focus: (function( orig ) {
-		return function( delay, fn ) {
-			return typeof delay === "number" ?
-				this.each(function() {
-					var elem = this;
-					setTimeout(function() {
-						$( elem ).focus();
-						if ( fn ) {
-							fn.call( elem );
-						}
-					}, delay );
-				}) :
-				orig.apply( this, arguments );
-		};
-	})( $.fn.focus ),
-
-	scrollParent: function() {
-		var scrollParent;
-		if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
-			scrollParent = this.parents().filter(function() {
-				return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
-			}).eq(0);
-		} else {
-			scrollParent = this.parents().filter(function() {
-				return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
-			}).eq(0);
-		}
-
-		return ( /fixed/ ).test( this.css( "position") ) || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;
-	},
-
-	uniqueId: function() {
-		return this.each(function() {
-			if ( !this.id ) {
-				this.id = "ui-id-" + (++uuid);
-			}
-		});
-	},
-
-	removeUniqueId: function() {
-		return this.each(function() {
-			if ( runiqueId.test( this.id ) ) {
-				$( this ).removeAttr( "id" );
-			}
-		});
-	}
-});
-
-// selectors
-function focusable( element, isTabIndexNotNaN ) {
-	var map, mapName, img,
-		nodeName = element.nodeName.toLowerCase();
-	if ( "area" === nodeName ) {
-		map = element.parentNode;
-		mapName = map.name;
-		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
-			return false;
-		}
-		img = $( "img[usemap=#" + mapName + "]" )[0];
-		return !!img && visible( img );
-	}
-	return ( /input|select|textarea|button|object/.test( nodeName ) ?
-		!element.disabled :
-		"a" === nodeName ?
-			element.href || isTabIndexNotNaN :
-			isTabIndexNotNaN) &&
-		// the element and all of its ancestors must be visible
-		visible( element );
-}
-
-function visible( element ) {
-	return $.expr.filters.visible( element ) &&
-		!$( element ).parents().addBack().filter(function() {
-			return $.css( this, "visibility" ) === "hidden";
-		}).length;
-}
-
-$.extend( $.expr[ ":" ], {
-	data: $.expr.createPseudo ?
-		$.expr.createPseudo(function( dataName ) {
-			return function( elem ) {
-				return !!$.data( elem, dataName );
-			};
-		}) :
-		// support: jQuery <1.8
-		function( elem, i, match ) {
-			return !!$.data( elem, match[ 3 ] );
-		},
-
-	focusable: function( element ) {
-		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
-	},
-
-	tabbable: function( element ) {
-		var tabIndex = $.attr( element, "tabindex" ),
-			isTabIndexNaN = isNaN( tabIndex );
-		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
-	}
-});
-
-// support: jQuery <1.8
-if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
-	$.each( [ "Width", "Height" ], function( i, name ) {
-		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
-			type = name.toLowerCase(),
-			orig = {
-				innerWidth: $.fn.innerWidth,
-				innerHeight: $.fn.innerHeight,
-				outerWidth: $.fn.outerWidth,
-				outerHeight: $.fn.outerHeight
-			};
-
-		function reduce( elem, size, border, margin ) {
-			$.each( side, function() {
-				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
-				if ( border ) {
-					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
-				}
-				if ( margin ) {
-					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
-				}
-			});
-			return size;
-		}
-
-		$.fn[ "inner" + name ] = function( size ) {
-			if ( size === undefined ) {
-				return orig[ "inner" + name ].call( this );
-			}
-
-			return this.each(function() {
-				$( this ).css( type, reduce( this, size ) + "px" );
-			});
-		};
-
-		$.fn[ "outer" + name] = function( size, margin ) {
-			if ( typeof size !== "number" ) {
-				return orig[ "outer" + name ].call( this, size );
-			}
-
-			return this.each(function() {
-				$( this).css( type, reduce( this, size, true, margin ) + "px" );
-			});
-		};
-	});
-}
-
-// support: jQuery <1.8
-if ( !$.fn.addBack ) {
-	$.fn.addBack = function( selector ) {
-		return this.add( selector == null ?
-			this.prevObject : this.prevObject.filter( selector )
-		);
-	};
-}
-
-// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
-if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
-	$.fn.removeData = (function( removeData ) {
-		return function( key ) {
-			if ( arguments.length ) {
-				return removeData.call( this, $.camelCase( key ) );
-			} else {
-				return removeData.call( this );
-			}
-		};
-	})( $.fn.removeData );
-}
-
-
-
-
-
-// deprecated
-$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
-
-$.support.selectstart = "onselectstart" in document.createElement( "div" );
-$.fn.extend({
-	disableSelection: function() {
-		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
-			".ui-disableSelection", function( event ) {
-				event.preventDefault();
-			});
-	},
-
-	enableSelection: function() {
-		return this.unbind( ".ui-disableSelection" );
-	},
-
-	zIndex: function( zIndex ) {
-		if ( zIndex !== undefined ) {
-			return this.css( "zIndex", zIndex );
-		}
-
-		if ( this.length ) {
-			var elem = $( this[ 0 ] ), position, value;
-			while ( elem.length && elem[ 0 ] !== document ) {
-				// Ignore z-index if position is set to a value where z-index is ignored by the browser
-				// This makes behavior of this function consistent across browsers
-				// WebKit always returns auto if the element is positioned
-				position = elem.css( "position" );
-				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
-					// IE returns 0 when zIndex is not specified
-					// other browsers return a string
-					// we ignore the case of nested elements with an explicit value of 0
-					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
-					value = parseInt( elem.css( "zIndex" ), 10 );
-					if ( !isNaN( value ) && value !== 0 ) {
-						return value;
-					}
-				}
-				elem = elem.parent();
-			}
-		}
-
-		return 0;
-	}
-});
-
-// $.ui.plugin is deprecated. Use $.widget() extensions instead.
-$.ui.plugin = {
-	add: function( module, option, set ) {
-		var i,
-			proto = $.ui[ module ].prototype;
-		for ( i in set ) {
-			proto.plugins[ i ] = proto.plugins[ i ] || [];
-			proto.plugins[ i ].push( [ option, set[ i ] ] );
-		}
-	},
-	call: function( instance, name, args, allowDisconnected ) {
-		var i,
-			set = instance.plugins[ name ];
-
-		if ( !set ) {
-			return;
-		}
-
-		if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
-			return;
-		}
-
-		for ( i = 0; i < set.length; i++ ) {
-			if ( instance.options[ set[ i ][ 0 ] ] ) {
-				set[ i ][ 1 ].apply( instance.element, args );
-			}
-		}
-	}
-};
-
-})( jQuery );
-
-(function( $, window, undefined ) {
-
-	// Subtract the height of external toolbars from the page height, if the page does not have
-	// internal toolbars of the same type
-	var compensateToolbars = function( page, desiredHeight ) {
-		var pageParent = page.parent(),
-			toolbarsAffectingHeight = [],
-			externalHeaders = pageParent.children( ":jqmData(role='header')" ),
-			internalHeaders = page.children( ":jqmData(role='header')" ),
-			externalFooters = pageParent.children( ":jqmData(role='footer')" ),
-			internalFooters = page.children( ":jqmData(role='footer')" );
-
-		// If we have no internal headers, but we do have external headers, then their height
-		// reduces the page height
-		if ( internalHeaders.length === 0 && externalHeaders.length > 0 ) {
-			toolbarsAffectingHeight = toolbarsAffectingHeight.concat( externalHeaders.toArray() );
-		}
-
-		// If we have no internal footers, but we do have external footers, then their height
-		// reduces the page height
-		if ( internalFooters.length === 0 && externalFooters.length > 0 ) {
-			toolbarsAffectingHeight = toolbarsAffectingHeight.concat( externalFooters.toArray() );
-		}
-
-		$.each( toolbarsAffectingHeight, function( index, value ) {
-			desiredHeight -= $( value ).outerHeight();
-		});
-
-		// Height must be at least zero
-		return Math.max( 0, desiredHeight );
-	};
-
-	$.extend( $.mobile, {
-		// define the window and the document objects
-		window: $( window ),
-		document: $( document ),
-
-		// TODO: Remove and use $.ui.keyCode directly
-		keyCode: $.ui.keyCode,
-
-		// Place to store various widget extensions
-		behaviors: {},
-
-		// Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value
-		silentScroll: function( ypos ) {
-			if ( $.type( ypos ) !== "number" ) {
-				ypos = $.mobile.defaultHomeScroll;
-			}
-
-			// prevent scrollstart and scrollstop events
-			$.event.special.scrollstart.enabled = false;
-
-			setTimeout(function() {
-				window.scrollTo( 0, ypos );
-				$.mobile.document.trigger( "silentscroll", { x: 0, y: ypos });
-			}, 20 );
-
-			setTimeout(function() {
-				$.event.special.scrollstart.enabled = true;
-			}, 150 );
-		},
-
-		getClosestBaseUrl: function( ele )	{
-			// Find the closest page and extract out its url.
-			var url = $( ele ).closest( ".ui-page" ).jqmData( "url" ),
-				base = $.mobile.path.documentBase.hrefNoHash;
-
-			if ( !$.mobile.dynamicBaseEnabled || !url || !$.mobile.path.isPath( url ) ) {
-				url = base;
-			}
-
-			return $.mobile.path.makeUrlAbsolute( url, base );
-		},
-		removeActiveLinkClass: function( forceRemoval ) {
-			if ( !!$.mobile.activeClickedLink &&
-				( !$.mobile.activeClickedLink.closest( "." + $.mobile.activePageClass ).length ||
-					forceRemoval ) ) {
-
-				$.mobile.activeClickedLink.removeClass( $.mobile.activeBtnClass );
-			}
-			$.mobile.activeClickedLink = null;
-		},
-
-		// DEPRECATED in 1.4
-		// Find the closest parent with a theme class on it. Note that
-		// we are not using $.fn.closest() on purpose here because this
-		// method gets called quite a bit and we need it to be as fast
-		// as possible.
-		getInheritedTheme: function( el, defaultTheme ) {
-			var e = el[ 0 ],
-				ltr = "",
-				re = /ui-(bar|body|overlay)-([a-z])\b/,
-				c, m;
-			while ( e ) {
-				c = e.className || "";
-				if ( c && ( m = re.exec( c ) ) && ( ltr = m[ 2 ] ) ) {
-					// We found a parent with a theme class
-					// on it so bail from this loop.
-					break;
-				}
-
-				e = e.parentNode;
-			}
-			// Return the theme letter we found, if none, return the
-			// specified default.
-			return ltr || defaultTheme || "a";
-		},
-
-		enhanceable: function( elements ) {
-			return this.haveParents( elements, "enhance" );
-		},
-
-		hijackable: function( elements ) {
-			return this.haveParents( elements, "ajax" );
-		},
-
-		haveParents: function( elements, attr ) {
-			if ( !$.mobile.ignoreContentEnabled ) {
-				return elements;
-			}
-
-			var count = elements.length,
-				$newSet = $(),
-				e, $element, excluded,
-				i, c;
-
-			for ( i = 0; i < count; i++ ) {
-				$element = elements.eq( i );
-				excluded = false;
-				e = elements[ i ];
-
-				while ( e ) {
-					c = e.getAttribute ? e.getAttribute( "data-" + $.mobile.ns + attr ) : "";
-
-					if ( c === "false" ) {
-						excluded = true;
-						break;
-					}
-
-					e = e.parentNode;
-				}
-
-				if ( !excluded ) {
-					$newSet = $newSet.add( $element );
-				}
-			}
-
-			return $newSet;
-		},
-
-		getScreenHeight: function() {
-			// Native innerHeight returns more accurate value for this across platforms,
-			// jQuery version is here as a normalized fallback for platforms like Symbian
-			return window.innerHeight || $.mobile.window.height();
-		},
-
-		//simply set the active page's minimum height to screen height, depending on orientation
-		resetActivePageHeight: function( height ) {
-			var page = $( "." + $.mobile.activePageClass ),
-				pageHeight = page.height(),
-				pageOuterHeight = page.outerHeight( true );
-
-			height = compensateToolbars( page,
-				( typeof height === "number" ) ? height : $.mobile.getScreenHeight() );
-
-			page.css( "min-height", height - ( pageOuterHeight - pageHeight ) );
-		},
-
-		loading: function() {
-			// If this is the first call to this function, instantiate a loader widget
-			var loader = this.loading._widget || $( $.mobile.loader.prototype.defaultHtml ).loader(),
-
-				// Call the appropriate method on the loader
-				returnValue = loader.loader.apply( loader, arguments );
-
-			// Make sure the loader is retained for future calls to this function.
-			this.loading._widget = loader;
-
-			return returnValue;
-		}
-	});
-
-	$.addDependents = function( elem, newDependents ) {
-		var $elem = $( elem ),
-			dependents = $elem.jqmData( "dependents" ) || $();
-
-		$elem.jqmData( "dependents", $( dependents ).add( newDependents ) );
-	};
-
-	// plugins
-	$.fn.extend({
-		removeWithDependents: function() {
-			$.removeWithDependents( this );
-		},
-
-		// Enhance child elements
-		enhanceWithin: function() {
-			var index,
-				widgetElements = {},
-				keepNative = $.mobile.page.prototype.keepNativeSelector(),
-				that = this;
-
-			// Add no js class to elements
-			if ( $.mobile.nojs ) {
-				$.mobile.nojs( this );
-			}
-
-			// Bind links for ajax nav
-			if ( $.mobile.links ) {
-				$.mobile.links( this );
-			}
-
-			// Degrade inputs for styleing
-			if ( $.mobile.degradeInputsWithin ) {
-				$.mobile.degradeInputsWithin( this );
-			}
-
-			// Run buttonmarkup
-			if ( $.fn.buttonMarkup ) {
-				this.find( $.fn.buttonMarkup.initSelector ).not( keepNative )
-				.jqmEnhanceable().buttonMarkup();
-			}
-
-			// Add classes for fieldContain
-			if ( $.fn.fieldcontain ) {
-				this.find( ":jqmData(role='fieldcontain')" ).not( keepNative )
-				.jqmEnhanceable().fieldcontain();
-			}
-
-			// Enhance widgets
-			$.each( $.mobile.widgets, function( name, constructor ) {
-
-				// If initSelector not false find elements
-				if ( constructor.initSelector ) {
-
-					// Filter elements that should not be enhanced based on parents
-					var elements = $.mobile.enhanceable( that.find( constructor.initSelector ) );
-
-					// If any matching elements remain filter ones with keepNativeSelector
-					if ( elements.length > 0 ) {
-
-						// $.mobile.page.prototype.keepNativeSelector is deprecated this is just for backcompat
-						// Switch to $.mobile.keepNative in 1.5 which is just a value not a function
-						elements = elements.not( keepNative );
-					}
-
-					// Enhance whatever is left
-					if ( elements.length > 0 ) {
-						widgetElements[ constructor.prototype.widgetName ] = elements;
-					}
-				}
-			});
-
-			for ( index in widgetElements ) {
-				widgetElements[ index ][ index ]();
-			}
-
-			return this;
-		},
-
-		addDependents: function( newDependents ) {
-			$.addDependents( this, newDependents );
-		},
-
-		// note that this helper doesn't attempt to handle the callback
-		// or setting of an html element's text, its only purpose is
-		// to return the html encoded version of the text in all cases. (thus the name)
-		getEncodedText: function() {
-			return $( "<a>" ).text( this.text() ).html();
-		},
-
-		// fluent helper function for the mobile namespaced equivalent
-		jqmEnhanceable: function() {
-			return $.mobile.enhanceable( this );
-		},
-
-		jqmHijackable: function() {
-			return $.mobile.hijackable( this );
-		}
-	});
-
-	$.removeWithDependents = function( nativeElement ) {
-		var element = $( nativeElement );
-
-		( element.jqmData( "dependents" ) || $() ).remove();
-		element.remove();
-	};
-	$.addDependents = function( nativeElement, newDependents ) {
-		var element = $( nativeElement ),
-			dependents = element.jqmData( "dependents" ) || $();
-
-		element.jqmData( "dependents", $( dependents ).add( newDependents ) );
-	};
-
-	$.find.matches = function( expr, set ) {
-		return $.find( expr, null, null, set );
-	};
-
-	$.find.matchesSelector = function( node, expr ) {
-		return $.find( expr, null, null, [ node ] ).length > 0;
-	};
-
-})( jQuery, this );
-
-
-/*!
- * jQuery UI Widget c0ab71056b936627e8a7821f03c044aec6280a40
- * http://jqueryui.com
- *
- * Copyright 2013 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://api.jqueryui.com/jQuery.widget/
- */
-(function( $, undefined ) {
-
-var uuid = 0,
-	slice = Array.prototype.slice,
-	_cleanData = $.cleanData;
-$.cleanData = function( elems ) {
-	for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
-		try {
-			$( elem ).triggerHandler( "remove" );
-		// http://bugs.jquery.com/ticket/8235
-		} catch( e ) {}
-	}
-	_cleanData( elems );
-};
-
-$.widget = function( name, base, prototype ) {
-	var fullName, existingConstructor, constructor, basePrototype,
-		// proxiedPrototype allows the provided prototype to remain unmodified
-		// so that it can be used as a mixin for multiple widgets (#8876)
-		proxiedPrototype = {},
-		namespace = name.split( "." )[ 0 ];
-
-	name = name.split( "." )[ 1 ];
-	fullName = namespace + "-" + name;
-
-	if ( !prototype ) {
-		prototype = base;
-		base = $.Widget;
-	}
-
-	// create selector for plugin
-	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
-		return !!$.data( elem, fullName );
-	};
-
-	$[ namespace ] = $[ namespace ] || {};
-	existingConstructor = $[ namespace ][ name ];
-	constructor = $[ namespace ][ name ] = function( options, element ) {
-		// allow instantiation without "new" keyword
-		if ( !this._createWidget ) {
-			return new constructor( options, element );
-		}
-
-		// allow instantiation without initializing for simple inheritance
-		// must use "new" keyword (the code above always passes args)
-		if ( arguments.length ) {
-			this._createWidget( options, element );
-		}
-	};
-	// extend with the existing constructor to carry over any static properties
-	$.extend( constructor, existingConstructor, {
-		version: prototype.version,
-		// copy the object used to create the prototype in case we need to
-		// redefine the widget later
-		_proto: $.extend( {}, prototype ),
-		// track widgets that inherit from this widget in case this widget is
-		// redefined after a widget inherits from it
-		_childConstructors: []
-	});
-
-	basePrototype = new base();
-	// we need to make the options hash a property directly on the new instance
-	// otherwise we'll modify the options hash on the prototype that we're
-	// inheriting from
-	basePrototype.options = $.widget.extend( {}, basePrototype.options );
-	$.each( prototype, function( prop, value ) {
-		if ( !$.isFunction( value ) ) {
-			proxiedPrototype[ prop ] = value;
-			return;
-		}
-		proxiedPrototype[ prop ] = (function() {
-			var _super = function() {
-					return base.prototype[ prop ].apply( this, arguments );
-				},
-				_superApply = function( args ) {
-					return base.prototype[ prop ].apply( this, args );
-				};
-			return function() {
-				var __super = this._super,
-					__superApply = this._superApply,
-					returnValue;
-
-				this._super = _super;
-				this._superApply = _superApply;
-
-				returnValue = value.apply( this, arguments );
-
-				this._super = __super;
-				this._superApply = __superApply;
-
-				return returnValue;
-			};
-		})();
-	});
-	constructor.prototype = $.widget.extend( basePrototype, {
-		// TODO: remove support for widgetEventPrefix
-		// always use the name + a colon as the prefix, e.g., draggable:start
-		// don't prefix for widgets that aren't DOM-based
-		widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
-	}, proxiedPrototype, {
-		constructor: constructor,
-		namespace: namespace,
-		widgetName: name,
-		widgetFullName: fullName
-	});
-
-	// If this widget is being redefined then we need to find all widgets that
-	// are inheriting from it and redefine all of them so that they inherit from
-	// the new version of this widget. We're essentially trying to replace one
-	// level in the prototype chain.
-	if ( existingConstructor ) {
-		$.each( existingConstructor._childConstructors, function( i, child ) {
-			var childPrototype = child.prototype;
-
-			// redefine the child widget using the same prototype that was
-			// originally used, but inherit from the new version of the base
-			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
-		});
-		// remove the list of existing child constructors from the old constructor
-		// so the old child constructors can be garbage collected
-		delete existingConstructor._childConstructors;
-	} else {
-		base._childConstructors.push( constructor );
-	}
-
-	$.widget.bridge( name, constructor );
-
-	return constructor;
-};
-
-$.widget.extend = function( target ) {
-	var input = slice.call( arguments, 1 ),
-		inputIndex = 0,
-		inputLength = input.length,
-		key,
-		value;
-	for ( ; inputIndex < inputLength; inputIndex++ ) {
-		for ( key in input[ inputIndex ] ) {
-			value = input[ inputIndex ][ key ];
-			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
-				// Clone objects
-				if ( $.isPlainObject( value ) ) {
-					target[ key ] = $.isPlainObject( target[ key ] ) ?
-						$.widget.extend( {}, target[ key ], value ) :
-						// Don't extend strings, arrays, etc. with objects
-						$.widget.extend( {}, value );
-				// Copy everything else by reference
-				} else {
-					target[ key ] = value;
-				}
-			}
-		}
-	}
-	return target;
-};
-
-$.widget.bridge = function( name, object ) {
-	var fullName = object.prototype.widgetFullName || name;
-	$.fn[ name ] = function( options ) {
-		var isMethodCall = typeof options === "string",
-			args = slice.call( arguments, 1 ),
-			returnValue = this;
-
-		// allow multiple hashes to be passed on init
-		options = !isMethodCall && args.length ?
-			$.widget.extend.apply( null, [ options ].concat(args) ) :
-			options;
-
-		if ( isMethodCall ) {
-			this.each(function() {
-				var methodValue,
-					instance = $.data( this, fullName );
-				if ( options === "instance" ) {
-					returnValue = instance;
-					return false;
-				}
-				if ( !instance ) {
-					return $.error( "cannot call methods on " + name + " prior to initialization; " +
-						"attempted to call method '" + options + "'" );
-				}
-				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
-					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
-				}
-				methodValue = instance[ options ].apply( instance, args );
-				if ( methodValue !== instance && methodValue !== undefined ) {
-					returnValue = methodValue && methodValue.jquery ?
-						returnValue.pushStack( methodValue.get() ) :
-						methodValue;
-					return false;
-				}
-			});
-		} else {
-			this.each(function() {
-				var instance = $.data( this, fullName );
-				if ( instance ) {
-					instance.option( options || {} )._init();
-				} else {
-					$.data( this, fullName, new object( options, this ) );
-				}
-			});
-		}
-
-		return returnValue;
-	};
-};
-
-$.Widget = function( /* options, element */ ) {};
-$.Widget._childConstructors = [];
-
-$.Widget.prototype = {
-	widgetName: "widget",
-	widgetEventPrefix: "",
-	defaultElement: "<div>",
-	options: {
-		disabled: false,
-
-		// callbacks
-		create: null
-	},
-	_createWidget: function( options, element ) {
-		element = $( element || this.defaultElement || this )[ 0 ];
-		this.element = $( element );
-		this.uuid = uuid++;
-		this.eventNamespace = "." + this.widgetName + this.uuid;
-		this.options = $.widget.extend( {},
-			this.options,
-			this._getCreateOptions(),
-			options );
-
-		this.bindings = $();
-		this.hoverable = $();
-		this.focusable = $();
-
-		if ( element !== this ) {
-			$.data( element, this.widgetFullName, this );
-			this._on( true, this.element, {
-				remove: function( event ) {
-					if ( event.target === element ) {
-						this.destroy();
-					}
-				}
-			});
-			this.document = $( element.style ?
-				// element within the document
-				element.ownerDocument :
-				// element is window or document
-				element.document || element );
-			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
-		}
-
-		this._create();
-		this._trigger( "create", null, this._getCreateEventData() );
-		this._init();
-	},
-	_getCreateOptions: $.noop,
-	_getCreateEventData: $.noop,
-	_create: $.noop,
-	_init: $.noop,
-
-	destroy: function() {
-		this._destroy();
-		// we can probably remove the unbind calls in 2.0
-		// all event bindings should go through this._on()
-		this.element
-			.unbind( this.eventNamespace )
-			.removeData( this.widgetFullName )
-			// support: jquery <1.6.3
-			// http://bugs.jquery.com/ticket/9413
-			.removeData( $.camelCase( this.widgetFullName ) );
-		this.widget()
-			.unbind( this.eventNamespace )
-			.removeAttr( "aria-disabled" )
-			.removeClass(
-				this.widgetFullName + "-disabled " +
-				"ui-state-disabled" );
-
-		// clean up events and states
-		this.bindings.unbind( this.eventNamespace );
-		this.hoverable.removeClass( "ui-state-hover" );
-		this.focusable.removeClass( "ui-state-focus" );
-	},
-	_destroy: $.noop,
-
-	widget: function() {
-		return this.element;
-	},
-
-	option: function( key, value ) {
-		var options = key,
-			parts,
-			curOption,
-			i;
-
-		if ( arguments.length === 0 ) {
-			// don't return a reference to the internal hash
-			return $.widget.extend( {}, this.options );
-		}
-
-		if ( typeof key === "string" ) {
-			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
-			options = {};
-			parts = key.split( "." );
-			key = parts.shift();
-			if ( parts.length ) {
-				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
-				for ( i = 0; i < parts.length - 1; i++ ) {
-					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
-					curOption = curOption[ parts[ i ] ];
-				}
-				key = parts.pop();
-				if ( value === undefined ) {
-					return curOption[ key ] === undefined ? null : curOption[ key ];
-				}
-				curOption[ key ] = value;
-			} else {
-				if ( value === undefined ) {
-					return this.options[ key ] === undefined ? null : this.options[ key ];
-				}
-				options[ key ] = value;
-			}
-		}
-
-		this._setOptions( options );
-
-		return this;
-	},
-	_setOptions: function( options ) {
-		var key;
-
-		for ( key in options ) {
-			this._setOption( key, options[ key ] );
-		}
-
-		return this;
-	},
-	_setOption: function( key, value ) {
-		this.options[ key ] = value;
-
-		if ( key === "disabled" ) {
-			this.widget()
-				.toggleClass( this.widgetFullName + "-disabled", !!value );
-			this.hoverable.removeClass( "ui-state-hover" );
-			this.focusable.removeClass( "ui-state-focus" );
-		}
-
-		return this;
-	},
-
-	enable: function() {
-		return this._setOptions({ disabled: false });
-	},
-	disable: function() {
-		return this._setOptions({ disabled: true });
-	},
-
-	_on: function( suppressDisabledCheck, element, handlers ) {
-		var delegateElement,
-			instance = this;
-
-		// no suppressDisabledCheck flag, shuffle arguments
-		if ( typeof suppressDisabledCheck !== "boolean" ) {
-			handlers = element;
-			element = suppressDisabledCheck;
-			suppressDisabledCheck = false;
-		}
-
-		// no element argument, shuffle and use this.element
-		if ( !handlers ) {
-			handlers = element;
-			element = this.element;
-			delegateElement = this.widget();
-		} else {
-			// accept selectors, DOM elements
-			element = delegateElement = $( element );
-			this.bindings = this.bindings.add( element );
-		}
-
-		$.each( handlers, function( event, handler ) {
-			function handlerProxy() {
-				// allow widgets to customize the disabled handling
-				// - disabled as an array instead of boolean
-				// - disabled class as method for disabling individual parts
-				if ( !suppressDisabledCheck &&
-						( instance.options.disabled === true ||
-							$( this ).hasClass( "ui-state-disabled" ) ) ) {
-					return;
-				}
-				return ( typeof handler === "string" ? instance[ handler ] : handler )
-					.apply( instance, arguments );
-			}
-
-			// copy the guid so direct unbinding works
-			if ( typeof handler !== "string" ) {
-				handlerProxy.guid = handler.guid =
-					handler.guid || handlerProxy.guid || $.guid++;
-			}
-
-			var match = event.match( /^(\w+)\s*(.*)$/ ),
-				eventName = match[1] + instance.eventNamespace,
-				selector = match[2];
-			if ( selector ) {
-				delegateElement.delegate( selector, eventName, handlerProxy );
-			} else {
-				element.bind( eventName, handlerProxy );
-			}
-		});
-	},
-
-	_off: function( element, eventName ) {
-		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
-		element.unbind( eventName ).undelegate( eventName );
-	},
-
-	_delay: function( handler, delay ) {
-		function handlerProxy() {
-			return ( typeof handler === "string" ? instance[ handler ] : handler )
-				.apply( instance, arguments );
-		}
-		var instance = this;
-		return setTimeout( handlerProxy, delay || 0 );
-	},
-
-	_hoverable: function( element ) {
-		this.hoverable = this.hoverable.add( element );
-		this._on( element, {
-			mouseenter: function( event ) {
-				$( event.currentTarget ).addClass( "ui-state-hover" );
-			},
-			mouseleave: function( event ) {
-				$( event.currentTarget ).removeClass( "ui-state-hover" );
-			}
-		});
-	},
-
-	_focusable: function( element ) {
-		this.focusable = this.focusable.add( element );
-		this._on( element, {
-			focusin: function( event ) {
-				$( event.currentTarget ).addClass( "ui-state-focus" );
-			},
-			focusout: function( event ) {
-				$( event.currentTarget ).removeClass( "ui-state-focus" );
-			}
-		});
-	},
-
-	_trigger: function( type, event, data ) {
-		var prop, orig,
-			callback = this.options[ type ];
-
-		data = data || {};
-		event = $.Event( event );
-		event.type = ( type === this.widgetEventPrefix ?
-			type :
-			this.widgetEventPrefix + type ).toLowerCase();
-		// the original event may come from any element
-		// so we need to reset the target on the new event
-		event.target = this.element[ 0 ];
-
-		// copy original event properties over to the new event
-		orig = event.originalEvent;
-		if ( orig ) {
-			for ( prop in orig ) {
-				if ( !( prop in event ) ) {
-					event[ prop ] = orig[ prop ];
-				}
-			}
-		}
-
-		this.element.trigger( event, data );
-		return !( $.isFunction( callback ) &&
-			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
-			event.isDefaultPrevented() );
-	}
-};
-
-$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
-	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
-		if ( typeof options === "string" ) {
-			options = { effect: options };
-		}
-		var hasOptions,
-			effectName = !options ?
-				method :
-				options === true || typeof options === "number" ?
-					defaultEffect :
-					options.effect || defaultEffect;
-		options = options || {};
-		if ( typeof options === "number" ) {
-			options = { duration: options };
-		}
-		hasOptions = !$.isEmptyObject( options );
-		options.complete = callback;
-		if ( options.delay ) {
-			element.delay( options.delay );
-		}
-		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
-			element[ method ]( options );
-		} else if ( effectName !== method && element[ effectName ] ) {
-			element[ effectName ]( options.duration, options.easing, callback );
-		} else {
-			element.queue(function( next ) {
-				$( this )[ method ]();
-				if ( callback ) {
-					callback.call( element[ 0 ] );
-				}
-				next();
-			});
-		}
-	};
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-var rcapitals = /[A-Z]/g,
-	replaceFunction = function( c ) {
-		return "-" + c.toLowerCase();
-	};
-
-$.extend( $.Widget.prototype, {
-	_getCreateOptions: function() {
-		var option, value,
-			elem = this.element[ 0 ],
-			options = {};
-
-		//
-		if ( !$.mobile.getAttribute( elem, "defaults" ) ) {
-			for ( option in this.options ) {
-				value = $.mobile.getAttribute( elem, option.replace( rcapitals, replaceFunction ) );
-
-				if ( value != null ) {
-					options[ option ] = value;
-				}
-			}
-		}
-
-		return options;
-	}
-});
-
-//TODO: Remove in 1.5 for backcompat only
-$.mobile.widget = $.Widget;
-
-})( jQuery );
-
-
-(function( $ ) {
-	// TODO move loader class down into the widget settings
-	var loaderClass = "ui-loader", $html = $( "html" );
-
-	$.widget( "mobile.loader", {
-		// NOTE if the global config settings are defined they will override these
-		//      options
-		options: {
-			// the theme for the loading message
-			theme: "a",
-
-			// whether the text in the loading message is shown
-			textVisible: false,
-
-			// custom html for the inner content of the loading message
-			html: "",
-
-			// the text to be displayed when the popup is shown
-			text: "loading"
-		},
-
-		defaultHtml: "<div class='" + loaderClass + "'>" +
-			"<span class='ui-icon-loading'></span>" +
-			"<h1></h1>" +
-			"</div>",
-
-		// For non-fixed supportin browsers. Position at y center (if scrollTop supported), above the activeBtn (if defined), or just 100px from top
-		fakeFixLoader: function() {
-			var activeBtn = $( "." + $.mobile.activeBtnClass ).first();
-
-			this.element
-				.css({
-					top: $.support.scrollTop && this.window.scrollTop() + this.window.height() / 2 ||
-						activeBtn.length && activeBtn.offset().top || 100
-				});
-		},
-
-		// check position of loader to see if it appears to be "fixed" to center
-		// if not, use abs positioning
-		checkLoaderPosition: function() {
-			var offset = this.element.offset(),
-				scrollTop = this.window.scrollTop(),
-				screenHeight = $.mobile.getScreenHeight();
-
-			if ( offset.top < scrollTop || ( offset.top - scrollTop ) > screenHeight ) {
-				this.element.addClass( "ui-loader-fakefix" );
-				this.fakeFixLoader();
-				this.window
-					.unbind( "scroll", this.checkLoaderPosition )
-					.bind( "scroll", $.proxy( this.fakeFixLoader, this ) );
-			}
-		},
-
-		resetHtml: function() {
-			this.element.html( $( this.defaultHtml ).html() );
-		},
-
-		// Turn on/off page loading message. Theme doubles as an object argument
-		// with the following shape: { theme: '', text: '', html: '', textVisible: '' }
-		// NOTE that the $.mobile.loading* settings and params past the first are deprecated
-		// TODO sweet jesus we need to break some of this out
-		show: function( theme, msgText, textonly ) {
-			var textVisible, message, loadSettings;
-
-			this.resetHtml();
-
-			// use the prototype options so that people can set them globally at
-			// mobile init. Consistency, it's what's for dinner
-			if ( $.type( theme ) === "object" ) {
-				loadSettings = $.extend( {}, this.options, theme );
-
-				theme = loadSettings.theme;
-			} else {
-				loadSettings = this.options;
-
-				// here we prefer the theme value passed as a string argument, then
-				// we prefer the global option because we can't use undefined default
-				// prototype options, then the prototype option
-				theme = theme || loadSettings.theme;
-			}
-
-			// set the message text, prefer the param, then the settings object
-			// then loading message
-			message = msgText || ( loadSettings.text === false ? "" : loadSettings.text );
-
-			// prepare the dom
-			$html.addClass( "ui-loading" );
-
-			textVisible = loadSettings.textVisible;
-
-			// add the proper css given the options (theme, text, etc)
-			// Force text visibility if the second argument was supplied, or
-			// if the text was explicitly set in the object args
-			this.element.attr("class", loaderClass +
-				" ui-corner-all ui-body-" + theme +
-				" ui-loader-" + ( textVisible || msgText || theme.text ? "verbose" : "default" ) +
-				( loadSettings.textonly || textonly ? " ui-loader-textonly" : "" ) );
-
-			// TODO verify that jquery.fn.html is ok to use in both cases here
-			//      this might be overly defensive in preventing unknowing xss
-			// if the html attribute is defined on the loading settings, use that
-			// otherwise use the fallbacks from above
-			if ( loadSettings.html ) {
-				this.element.html( loadSettings.html );
-			} else {
-				this.element.find( "h1" ).text( message );
-			}
-
-			// attach the loader to the DOM
-			this.element.appendTo( $.mobile.pageContainer );
-
-			// check that the loader is visible
-			this.checkLoaderPosition();
-
-			// on scroll check the loader position
-			this.window.bind( "scroll", $.proxy( this.checkLoaderPosition, this ) );
-		},
-
-		hide: function() {
-			$html.removeClass( "ui-loading" );
-
-			if ( this.options.text ) {
-				this.element.removeClass( "ui-loader-fakefix" );
-			}
-
-			$.mobile.window.unbind( "scroll", this.fakeFixLoader );
-			$.mobile.window.unbind( "scroll", this.checkLoaderPosition );
-		}
-	});
-
-})(jQuery, this);
-
-
-/*!
- * jQuery hashchange event - v1.3 - 7/21/2010
- * http://benalman.com/projects/jquery-hashchange-plugin/
- * 
- * Copyright (c) 2010 "Cowboy" Ben Alman
- * Dual licensed under the MIT and GPL licenses.
- * http://benalman.com/about/license/
- */
-
-// Script: jQuery hashchange event
-//
-// *Version: 1.3, Last updated: 7/21/2010*
-// 
-// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/
-// GitHub       - http://github.com/cowboy/jquery-hashchange/
-// Source       - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js
-// (Minified)   - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped)
-// 
-// About: License
-// 
-// Copyright (c) 2010 "Cowboy" Ben Alman,
-// Dual licensed under the MIT and GPL licenses.
-// http://benalman.com/about/license/
-// 
-// About: Examples
-// 
-// These working examples, complete with fully commented code, illustrate a few
-// ways in which this plugin can be used.
-// 
-// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/
-// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/
-// 
-// About: Support and Testing
-// 
-// Information about what version or versions of jQuery this plugin has been
-// tested with, what browsers it has been tested in, and where the unit tests
-// reside (so you can test it yourself).
-// 
-// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2
-// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,
-//                   Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.
-// Unit Tests      - http://benalman.com/code/projects/jquery-hashchange/unit/
-// 
-// About: Known issues
-// 
-// While this jQuery hashchange event implementation is quite stable and
-// robust, there are a few unfortunate browser bugs surrounding expected
-// hashchange event-based behaviors, independent of any JavaScript
-// window.onhashchange abstraction. See the following examples for more
-// information:
-// 
-// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/
-// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/
-// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/
-// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/
-// 
-// Also note that should a browser natively support the window.onhashchange 
-// event, but not report that it does, the fallback polling loop will be used.
-// 
-// About: Release History
-// 
-// 1.3   - (7/21/2010) Reorganized IE6/7 Iframe code to make it more
-//         "removable" for mobile-only development. Added IE6/7 document.title
-//         support. Attempted to make Iframe as hidden as possible by using
-//         techniques from http://www.paciellogroup.com/blog/?p=604. Added 
-//         support for the "shortcut" format $(window).hashchange( fn ) and
-//         $(window).hashchange() like jQuery provides for built-in events.
-//         Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and
-//         lowered its default value to 50. Added <jQuery.fn.hashchange.domain>
-//         and <jQuery.fn.hashchange.src> properties plus document-domain.html
-//         file to address access denied issues when setting document.domain in
-//         IE6/7.
-// 1.2   - (2/11/2010) Fixed a bug where coming back to a page using this plugin
-//         from a page on another domain would cause an error in Safari 4. Also,
-//         IE6/7 Iframe is now inserted after the body (this actually works),
-//         which prevents the page from scrolling when the event is first bound.
-//         Event can also now be bound before DOM ready, but it won't be usable
-//         before then in IE6/7.
-// 1.1   - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug
-//         where browser version is incorrectly reported as 8.0, despite
-//         inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.
-// 1.0   - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special
-//         window.onhashchange functionality into a separate plugin for users
-//         who want just the basic event & back button support, without all the
-//         extra awesomeness that BBQ provides. This plugin will be included as
-//         part of jQuery BBQ, but also be available separately.
-
-(function($,window,undefined){
-  '$:nomunge'; // Used by YUI compressor.
-  
-  // Reused string.
-  var str_hashchange = 'hashchange',
-    
-    // Method / object references.
-    doc = document,
-    fake_onhashchange,
-    special = $.event.special,
-    
-    // Does the browser support window.onhashchange? Note that IE8 running in
-    // IE7 compatibility mode reports true for 'onhashchange' in window, even
-    // though the event isn't supported, so also test document.documentMode.
-    doc_mode = doc.documentMode,
-    supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );
-  
-  // Get location.hash (or what you'd expect location.hash to be) sans any
-  // leading #. Thanks for making this necessary, Firefox!
-  function get_fragment( url ) {
-    url = url || location.href;
-    return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' );
-  };
-  
-  // Method: jQuery.fn.hashchange
-  // 
-  // Bind a handler to the window.onhashchange event or trigger all bound
-  // window.onhashchange event handlers. This behavior is consistent with
-  // jQuery's built-in event handlers.
-  // 
-  // Usage:
-  // 
-  // > jQuery(window).hashchange( [ handler ] );
-  // 
-  // Arguments:
-  // 
-  //  handler - (Function) Optional handler to be bound to the hashchange
-  //    event. This is a "shortcut" for the more verbose form:
-  //    jQuery(window).bind( 'hashchange', handler ). If handler is omitted,
-  //    all bound window.onhashchange event handlers will be triggered. This
-  //    is a shortcut for the more verbose
-  //    jQuery(window).trigger( 'hashchange' ). These forms are described in
-  //    the <hashchange event> section.
-  // 
-  // Returns:
-  // 
-  //  (jQuery) The initial jQuery collection of elements.
-  
-  // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and
-  // $(elem).hashchange() for triggering, like jQuery does for built-in events.
-  $.fn[ str_hashchange ] = function( fn ) {
-    return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );
-  };
-  
-  // Property: jQuery.fn.hashchange.delay
-  // 
-  // The numeric interval (in milliseconds) at which the <hashchange event>
-  // polling loop executes. Defaults to 50.
-  
-  // Property: jQuery.fn.hashchange.domain
-  // 
-  // If you're setting document.domain in your JavaScript, and you want hash
-  // history to work in IE6/7, not only must this property be set, but you must
-  // also set document.domain BEFORE jQuery is loaded into the page. This
-  // property is only applicable if you are supporting IE6/7 (or IE8 operating
-  // in "IE7 compatibility" mode).
-  // 
-  // In addition, the <jQuery.fn.hashchange.src> property must be set to the
-  // path of the included "document-domain.html" file, which can be renamed or
-  // modified if necessary (note that the document.domain specified must be the
-  // same in both your main JavaScript as well as in this file).
-  // 
-  // Usage:
-  // 
-  // jQuery.fn.hashchange.domain = document.domain;
-  
-  // Property: jQuery.fn.hashchange.src
-  // 
-  // If, for some reason, you need to specify an Iframe src file (for example,
-  // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can
-  // do so using this property. Note that when using this property, history
-  // won't be recorded in IE6/7 until the Iframe src file loads. This property
-  // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7
-  // compatibility" mode).
-  // 
-  // Usage:
-  // 
-  // jQuery.fn.hashchange.src = 'path/to/file.html';
-  
-  $.fn[ str_hashchange ].delay = 50;
-  /*
-  $.fn[ str_hashchange ].domain = null;
-  $.fn[ str_hashchange ].src = null;
-  */
-  
-  // Event: hashchange event
-  // 
-  // Fired when location.hash changes. In browsers that support it, the native
-  // HTML5 window.onhashchange event is used, otherwise a polling loop is
-  // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to
-  // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7
-  // compatibility" mode), a hidden Iframe is created to allow the back button
-  // and hash-based history to work.
-  // 
-  // Usage as described in <jQuery.fn.hashchange>:
-  // 
-  // > // Bind an event handler.
-  // > jQuery(window).hashchange( function(e) {
-  // >   var hash = location.hash;
-  // >   ...
-  // > });
-  // > 
-  // > // Manually trigger the event handler.
-  // > jQuery(window).hashchange();
-  // 
-  // A more verbose usage that allows for event namespacing:
-  // 
-  // > // Bind an event handler.
-  // > jQuery(window).bind( 'hashchange', function(e) {
-  // >   var hash = location.hash;
-  // >   ...
-  // > });
-  // > 
-  // > // Manually trigger the event handler.
-  // > jQuery(window).trigger( 'hashchange' );
-  // 
-  // Additional Notes:
-  // 
-  // * The polling loop and Iframe are not created until at least one handler
-  //   is actually bound to the 'hashchange' event.
-  // * If you need the bound handler(s) to execute immediately, in cases where
-  //   a location.hash exists on page load, via bookmark or page refresh for
-  //   example, use jQuery(window).hashchange() or the more verbose 
-  //   jQuery(window).trigger( 'hashchange' ).
-  // * The event can be bound before DOM ready, but since it won't be usable
-  //   before then in IE6/7 (due to the necessary Iframe), recommended usage is
-  //   to bind it inside a DOM ready handler.
-  
-  // Override existing $.event.special.hashchange methods (allowing this plugin
-  // to be defined after jQuery BBQ in BBQ's source code).
-  special[ str_hashchange ] = $.extend( special[ str_hashchange ], {
-    
-    // Called only when the first 'hashchange' event is bound to window.
-    setup: function() {
-      // If window.onhashchange is supported natively, there's nothing to do..
-      if ( supports_onhashchange ) { return false; }
-      
-      // Otherwise, we need to create our own. And we don't want to call this
-      // until the user binds to the event, just in case they never do, since it
-      // will create a polling loop and possibly even a hidden Iframe.
-      $( fake_onhashchange.start );
-    },
-    
-    // Called only when the last 'hashchange' event is unbound from window.
-    teardown: function() {
-      // If window.onhashchange is supported natively, there's nothing to do..
-      if ( supports_onhashchange ) { return false; }
-      
-      // Otherwise, we need to stop ours (if possible).
-      $( fake_onhashchange.stop );
-    }
-    
-  });
-  
-  // fake_onhashchange does all the work of triggering the window.onhashchange
-  // event for browsers that don't natively support it, including creating a
-  // polling loop to watch for hash changes and in IE 6/7 creating a hidden
-  // Iframe to enable back and forward.
-  fake_onhashchange = (function(){
-    var self = {},
-      timeout_id,
-      
-      // Remember the initial hash so it doesn't get triggered immediately.
-      last_hash = get_fragment(),
-      
-      fn_retval = function(val){ return val; },
-      history_set = fn_retval,
-      history_get = fn_retval;
-    
-    // Start the polling loop.
-    self.start = function() {
-      timeout_id || poll();
-    };
-    
-    // Stop the polling loop.
-    self.stop = function() {
-      timeout_id && clearTimeout( timeout_id );
-      timeout_id = undefined;
-    };
-    
-    // This polling loop checks every $.fn.hashchange.delay milliseconds to see
-    // if location.hash has changed, and triggers the 'hashchange' event on
-    // window when necessary.
-    function poll() {
-      var hash = get_fragment(),
-        history_hash = history_get( last_hash );
-      
-      if ( hash !== last_hash ) {
-        history_set( last_hash = hash, history_hash );
-        
-        $(window).trigger( str_hashchange );
-        
-      } else if ( history_hash !== last_hash ) {
-        location.href = location.href.replace( /#.*/, '' ) + history_hash;
-      }
-      
-      timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );
-    };
-    
-    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-    // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv
-    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-    window.attachEvent && !window.addEventListener && !supports_onhashchange && (function(){
-      // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8
-      // when running in "IE7 compatibility" mode.
-      
-      var iframe,
-        iframe_src;
-      
-      // When the event is bound and polling starts in IE 6/7, create a hidden
-      // Iframe for history handling.
-      self.start = function(){
-        if ( !iframe ) {
-          iframe_src = $.fn[ str_hashchange ].src;
-          iframe_src = iframe_src && iframe_src + get_fragment();
-          
-          // Create hidden Iframe. Attempt to make Iframe as hidden as possible
-          // by using techniques from http://www.paciellogroup.com/blog/?p=604.
-          iframe = $('<iframe tabindex="-1" title="empty"/>').hide()
-            
-            // When Iframe has completely loaded, initialize the history and
-            // start polling.
-            .one( 'load', function(){
-              iframe_src || history_set( get_fragment() );
-              poll();
-            })
-            
-            // Load Iframe src if specified, otherwise nothing.
-            .attr( 'src', iframe_src || 'javascript:0' )
-            
-            // Append Iframe after the end of the body to prevent unnecessary
-            // initial page scrolling (yes, this works).
-            .insertAfter( 'body' )[0].contentWindow;
-          
-          // Whenever `document.title` changes, update the Iframe's title to
-          // prettify the back/next history menu entries. Since IE sometimes
-          // errors with "Unspecified error" the very first time this is set
-          // (yes, very useful) wrap this with a try/catch block.
-          doc.onpropertychange = function(){
-            try {
-              if ( event.propertyName === 'title' ) {
-                iframe.document.title = doc.title;
-              }
-            } catch(e) {}
-          };
-          
-        }
-      };
-      
-      // Override the "stop" method since an IE6/7 Iframe was created. Even
-      // if there are no longer any bound event handlers, the polling loop
-      // is still necessary for back/next to work at all!
-      self.stop = fn_retval;
-      
-      // Get history by looking at the hidden Iframe's location.hash.
-      history_get = function() {
-        return get_fragment( iframe.location.href );
-      };
-      
-      // Set a new history item by opening and then closing the Iframe
-      // document, *then* setting its location.hash. If document.domain has
-      // been set, update that as well.
-      history_set = function( hash, history_hash ) {
-        var iframe_doc = iframe.document,
-          domain = $.fn[ str_hashchange ].domain;
-        
-        if ( hash !== history_hash ) {
-          // Update Iframe with any initial `document.title` that might be set.
-          iframe_doc.title = doc.title;
-          
-          // Opening the Iframe's document after it has been closed is what
-          // actually adds a history entry.
-          iframe_doc.open();
-          
-          // Set document.domain for the Iframe document as well, if necessary.
-          domain && iframe_doc.write( '<script>document.domain="' + domain + '"</script>' );
-          
-          iframe_doc.close();
-          
-          // Update the Iframe's hash, for great justice.
-          iframe.location.hash = hash;
-        }
-      };
-      
-    })();
-    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-    // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^
-    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-    
-    return self;
-  })();
-  
-})(jQuery,this);
-
-(function( $, undefined ) {
-
-	/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */
-	window.matchMedia = window.matchMedia || (function( doc, undefined ) {
-
-		var bool,
-			docElem = doc.documentElement,
-			refNode = docElem.firstElementChild || docElem.firstChild,
-			// fakeBody required for <FF4 when executed in <head>
-			fakeBody = doc.createElement( "body" ),
-			div = doc.createElement( "div" );
-
-		div.id = "mq-test-1";
-		div.style.cssText = "position:absolute;top:-100em";
-		fakeBody.style.background = "none";
-		fakeBody.appendChild(div);
-
-		return function(q){
-
-			div.innerHTML = "&shy;<style media=\"" + q + "\"> #mq-test-1 { width: 42px; }</style>";
-
-			docElem.insertBefore( fakeBody, refNode );
-			bool = div.offsetWidth === 42;
-			docElem.removeChild( fakeBody );
-
-			return {
-				matches: bool,
-				media: q
-			};
-
-		};
-
-	}( document ));
-
-	// $.mobile.media uses matchMedia to return a boolean.
-	$.mobile.media = function( q ) {
-		return window.matchMedia( q ).matches;
-	};
-
-})(jQuery);
-
-	(function( $, undefined ) {
-		var support = {
-			touch: "ontouchend" in document
-		};
-
-		$.mobile.support = $.mobile.support || {};
-		$.extend( $.support, support );
-		$.extend( $.mobile.support, support );
-	}( jQuery ));
-
-	(function( $, undefined ) {
-		$.extend( $.support, {
-			orientation: "orientation" in window && "onorientationchange" in window
-		});
-	}( jQuery ));
-
-(function( $, undefined ) {
-
-// thx Modernizr
-function propExists( prop ) {
-	var uc_prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ),
-		props = ( prop + " " + vendors.join( uc_prop + " " ) + uc_prop ).split( " " ),
-		v;
-
-	for ( v in props ) {
-		if ( fbCSS[ props[ v ] ] !== undefined ) {
-			return true;
-		}
-	}
-}
-
-var fakeBody = $( "<body>" ).prependTo( "html" ),
-	fbCSS = fakeBody[ 0 ].style,
-	vendors = [ "Webkit", "Moz", "O" ],
-	webos = "palmGetResource" in window, //only used to rule out scrollTop
-	operamini = window.operamini && ({}).toString.call( window.operamini ) === "[object OperaMini]",
-	bb = window.blackberry && !propExists( "-webkit-transform" ), //only used to rule out box shadow, as it's filled opaque on BB 5 and lower
-	nokiaLTE7_3;
-
-// inline SVG support test
-function inlineSVG() {
-	// Thanks Modernizr & Erik Dahlstrom
-	var w = window,
-		svg = !!w.document.createElementNS && !!w.document.createElementNS( "http://www.w3.org/2000/svg", "svg" ).createSVGRect && !( w.opera && navigator.userAgent.indexOf( "Chrome" ) === -1 ),
-		support = function( data ) {
-			if ( !( data && svg ) ) {
-				$( "html" ).addClass( "ui-nosvg" );
-			}
-		},
-		img = new w.Image();
-
-	img.onerror = function() {
-		support( false );
-	};
-	img.onload = function() {
-		support( img.width === 1 && img.height === 1 );
-	};
-	img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
-}
-
-function transform3dTest() {
-	var mqProp = "transform-3d",
-		// Because the `translate3d` test below throws false positives in Android:
-		ret = $.mobile.media( "(-" + vendors.join( "-" + mqProp + "),(-" ) + "-" + mqProp + "),(" + mqProp + ")" ),
-		el, transforms, t;
-
-	if ( ret ) {
-		return !!ret;
-	}
-
-	el = document.createElement( "div" );
-	transforms = {
-		// We’re omitting Opera for the time being; MS uses unprefixed.
-		"MozTransform": "-moz-transform",
-		"transform": "transform"
-	};
-
-	fakeBody.append( el );
-
-	for ( t in transforms ) {
-		if ( el.style[ t ] !== undefined ) {
-			el.style[ t ] = "translate3d( 100px, 1px, 1px )";
-			ret = window.getComputedStyle( el ).getPropertyValue( transforms[ t ] );
-		}
-	}
-	return ( !!ret && ret !== "none" );
-}
-
-// Test for dynamic-updating base tag support ( allows us to avoid href,src attr rewriting )
-function baseTagTest() {
-	var fauxBase = location.protocol + "//" + location.host + location.pathname + "ui-dir/",
-		base = $( "head base" ),
-		fauxEle = null,
-		href = "",
-		link, rebase;
-
-	if ( !base.length ) {
-		base = fauxEle = $( "<base>", { "href": fauxBase }).appendTo( "head" );
-	} else {
-		href = base.attr( "href" );
-	}
-
-	link = $( "<a href='testurl' />" ).prependTo( fakeBody );
-	rebase = link[ 0 ].href;
-	base[ 0 ].href = href || location.pathname;
-
-	if ( fauxEle ) {
-		fauxEle.remove();
-	}
-	return rebase.indexOf( fauxBase ) === 0;
-}
-
-// Thanks Modernizr
-function cssPointerEventsTest() {
-	var element = document.createElement( "x" ),
-		documentElement = document.documentElement,
-		getComputedStyle = window.getComputedStyle,
-		supports;
-
-	if ( !( "pointerEvents" in element.style ) ) {
-		return false;
-	}
-
-	element.style.pointerEvents = "auto";
-	element.style.pointerEvents = "x";
-	documentElement.appendChild( element );
-	supports = getComputedStyle &&
-	getComputedStyle( element, "" ).pointerEvents === "auto";
-	documentElement.removeChild( element );
-	return !!supports;
-}
-
-function boundingRect() {
-	var div = document.createElement( "div" );
-	return typeof div.getBoundingClientRect !== "undefined";
-}
-
-// non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683
-// allows for inclusion of IE 6+, including Windows Mobile 7
-$.extend( $.mobile, { browser: {} } );
-$.mobile.browser.oldIE = (function() {
-	var v = 3,
-		div = document.createElement( "div" ),
-		a = div.all || [];
-
-	do {
-		div.innerHTML = "<!--[if gt IE " + ( ++v ) + "]><br><![endif]-->";
-	} while( a[0] );
-
-	return v > 4 ? v : !v;
-})();
-
-function fixedPosition() {
-	var w = window,
-		ua = navigator.userAgent,
-		platform = navigator.platform,
-		// Rendering engine is Webkit, and capture major version
-		wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ ),
-		wkversion = !!wkmatch && wkmatch[ 1 ],
-		ffmatch = ua.match( /Fennec\/([0-9]+)/ ),
-		ffversion = !!ffmatch && ffmatch[ 1 ],
-		operammobilematch = ua.match( /Opera Mobi\/([0-9]+)/ ),
-		omversion = !!operammobilematch && operammobilematch[ 1 ];
-
-	if (
-		// iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)
-		( ( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1  || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534 ) ||
-		// Opera Mini
-		( w.operamini && ({}).toString.call( w.operamini ) === "[object OperaMini]" ) ||
-		( operammobilematch && omversion < 7458 )	||
-		//Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)
-		( ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533 ) ||
-		// Firefox Mobile before 6.0 -
-		( ffversion && ffversion < 6 ) ||
-		// WebOS less than 3
-		( "palmGetResource" in window && wkversion && wkversion < 534 )	||
-		// MeeGo
-		( ua.indexOf( "MeeGo" ) > -1 && ua.indexOf( "NokiaBrowser/8.5.0" ) > -1 ) ) {
-		return false;
-	}
-
-	return true;
-}
-
-$.extend( $.support, {
-	// Note, Chrome for iOS has an extremely quirky implementation of popstate.
-	// We've chosen to take the shortest path to a bug fix here for issue #5426
-	// See the following link for information about the regex chosen
-	// https://developers.google.com/chrome/mobile/docs/user-agent#chrome_for_ios_user-agent
-	pushState: "pushState" in history &&
-		"replaceState" in history &&
-		// When running inside a FF iframe, calling replaceState causes an error
-		!( window.navigator.userAgent.indexOf( "Firefox" ) >= 0 && window.top !== window ) &&
-		( window.navigator.userAgent.search(/CriOS/) === -1 ),
-
-	mediaquery: $.mobile.media( "only all" ),
-	cssPseudoElement: !!propExists( "content" ),
-	touchOverflow: !!propExists( "overflowScrolling" ),
-	cssTransform3d: transform3dTest(),
-	boxShadow: !!propExists( "boxShadow" ) && !bb,
-	fixedPosition: fixedPosition(),
-	scrollTop: ("pageXOffset" in window ||
-		"scrollTop" in document.documentElement ||
-		"scrollTop" in fakeBody[ 0 ]) && !webos && !operamini,
-
-	dynamicBaseTag: baseTagTest(),
-	cssPointerEvents: cssPointerEventsTest(),
-	boundingRect: boundingRect(),
-	inlineSVG: inlineSVG
-});
-
-fakeBody.remove();
-
-// $.mobile.ajaxBlacklist is used to override ajaxEnabled on platforms that have known conflicts with hash history updates (BB5, Symbian)
-// or that generally work better browsing in regular http for full page refreshes (Opera Mini)
-// Note: This detection below is used as a last resort.
-// We recommend only using these detection methods when all other more reliable/forward-looking approaches are not possible
-nokiaLTE7_3 = (function() {
-
-	var ua = window.navigator.userAgent;
-
-	//The following is an attempt to match Nokia browsers that are running Symbian/s60, with webkit, version 7.3 or older
-	return ua.indexOf( "Nokia" ) > -1 &&
-			( ua.indexOf( "Symbian/3" ) > -1 || ua.indexOf( "Series60/5" ) > -1 ) &&
-			ua.indexOf( "AppleWebKit" ) > -1 &&
-			ua.match( /(BrowserNG|NokiaBrowser)\/7\.[0-3]/ );
-})();
-
-// Support conditions that must be met in order to proceed
-// default enhanced qualifications are media query support OR IE 7+
-
-$.mobile.gradeA = function() {
-	return ( ( $.support.mediaquery && $.support.cssPseudoElement ) || $.mobile.browser.oldIE && $.mobile.browser.oldIE >= 8 ) && ( $.support.boundingRect || $.fn.jquery.match(/1\.[0-7+]\.[0-9+]?/) !== null );
-};
-
-$.mobile.ajaxBlacklist =
-			// BlackBerry browsers, pre-webkit
-			window.blackberry && !window.WebKitPoint ||
-			// Opera Mini
-			operamini ||
-			// Symbian webkits pre 7.3
-			nokiaLTE7_3;
-
-// Lastly, this workaround is the only way we've found so far to get pre 7.3 Symbian webkit devices
-// to render the stylesheets when they're referenced before this script, as we'd recommend doing.
-// This simply reappends the CSS in place, which for some reason makes it apply
-if ( nokiaLTE7_3 ) {
-	$(function() {
-		$( "head link[rel='stylesheet']" ).attr( "rel", "alternate stylesheet" ).attr( "rel", "stylesheet" );
-	});
-}
-
-// For ruling out shadows via css
-if ( !$.support.boxShadow ) {
-	$( "html" ).addClass( "ui-noboxshadow" );
-}
-
-})( jQuery );
-
-
-(function( $, undefined ) {
-	var $win = $.mobile.window, self,
-		dummyFnToInitNavigate = function() {
-		};
-
-	$.event.special.beforenavigate = {
-		setup: function() {
-			$win.on( "navigate", dummyFnToInitNavigate );
-		},
-
-		teardown: function() {
-			$win.off( "navigate", dummyFnToInitNavigate );
-		}
-	};
-
-	$.event.special.navigate = self = {
-		bound: false,
-
-		pushStateEnabled: true,
-
-		originalEventName: undefined,
-
-		// If pushstate support is present and push state support is defined to
-		// be true on the mobile namespace.
-		isPushStateEnabled: function() {
-			return $.support.pushState &&
-				$.mobile.pushStateEnabled === true &&
-				this.isHashChangeEnabled();
-		},
-
-		// !! assumes mobile namespace is present
-		isHashChangeEnabled: function() {
-			return $.mobile.hashListeningEnabled === true;
-		},
-
-		// TODO a lot of duplication between popstate and hashchange
-		popstate: function( event ) {
-			var newEvent = new $.Event( "navigate" ),
-				beforeNavigate = new $.Event( "beforenavigate" ),
-				state = event.originalEvent.state || {};
-
-			beforeNavigate.originalEvent = event;
-			$win.trigger( beforeNavigate );
-
-			if ( beforeNavigate.isDefaultPrevented() ) {
-				return;
-			}
-
-			if ( event.historyState ) {
-				$.extend(state, event.historyState);
-			}
-
-			// Make sure the original event is tracked for the end
-			// user to inspect incase they want to do something special
-			newEvent.originalEvent = event;
-
-			// NOTE we let the current stack unwind because any assignment to
-			//      location.hash will stop the world and run this event handler. By
-			//      doing this we create a similar behavior to hashchange on hash
-			//      assignment
-			setTimeout(function() {
-				$win.trigger( newEvent, {
-					state: state
-				});
-			}, 0);
-		},
-
-		hashchange: function( event /*, data */ ) {
-			var newEvent = new $.Event( "navigate" ),
-				beforeNavigate = new $.Event( "beforenavigate" );
-
-			beforeNavigate.originalEvent = event;
-			$win.trigger( beforeNavigate );
-
-			if ( beforeNavigate.isDefaultPrevented() ) {
-				return;
-			}
-
-			// Make sure the original event is tracked for the end
-			// user to inspect incase they want to do something special
-			newEvent.originalEvent = event;
-
-			// Trigger the hashchange with state provided by the user
-			// that altered the hash
-			$win.trigger( newEvent, {
-				// Users that want to fully normalize the two events
-				// will need to do history management down the stack and
-				// add the state to the event before this binding is fired
-				// TODO consider allowing for the explicit addition of callbacks
-				//      to be fired before this value is set to avoid event timing issues
-				state: event.hashchangeState || {}
-			});
-		},
-
-		// TODO We really only want to set this up once
-		//      but I'm not clear if there's a beter way to achieve
-		//      this with the jQuery special event structure
-		setup: function( /* data, namespaces */ ) {
-			if ( self.bound ) {
-				return;
-			}
-
-			self.bound = true;
-
-			if ( self.isPushStateEnabled() ) {
-				self.originalEventName = "popstate";
-				$win.bind( "popstate.navigate", self.popstate );
-			} else if ( self.isHashChangeEnabled() ) {
-				self.originalEventName = "hashchange";
-				$win.bind( "hashchange.navigate", self.hashchange );
-			}
-		}
-	};
-})( jQuery );
-
-
-
-(function( $, undefined ) {
-		var path, $base, dialogHashKey = "&ui-state=dialog";
-
-		$.mobile.path = path = {
-			uiStateKey: "&ui-state",
-
-			// This scary looking regular expression parses an absolute URL or its relative
-			// variants (protocol, site, document, query, and hash), into the various
-			// components (protocol, host, path, query, fragment, etc that make up the
-			// URL as well as some other commonly used sub-parts. When used with RegExp.exec()
-			// or String.match, it parses the URL into a results array that looks like this:
-			//
-			//     [0]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread#msg-content
-			//     [1]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread
-			//     [2]: http://jblas:password@mycompany.com:8080/mail/inbox
-			//     [3]: http://jblas:password@mycompany.com:8080
-			//     [4]: http:
-			//     [5]: //
-			//     [6]: jblas:password@mycompany.com:8080
-			//     [7]: jblas:password
-			//     [8]: jblas
-			//     [9]: password
-			//    [10]: mycompany.com:8080
-			//    [11]: mycompany.com
-			//    [12]: 8080
-			//    [13]: /mail/inbox
-			//    [14]: /mail/
-			//    [15]: inbox
-			//    [16]: ?msg=1234&type=unread
-			//    [17]: #msg-content
-			//
-			urlParseRE: /^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^:@\/#\?]+)(?:\:([^:@\/#\?]+))?)@)?(([^:\/#\?\]\[]+|\[[^\/\]@#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/,
-
-			// Abstraction to address xss (Issue #4787) by removing the authority in
-			// browsers that auto	decode it. All references to location.href should be
-			// replaced with a call to this method so that it can be dealt with properly here
-			getLocation: function( url ) {
-				var uri = url ? this.parseUrl( url ) : location,
-					hash = this.parseUrl( url || location.href ).hash;
-
-				// mimic the browser with an empty string when the hash is empty
-				hash = hash === "#" ? "" : hash;
-
-				// Make sure to parse the url or the location object for the hash because using location.hash
-				// is autodecoded in firefox, the rest of the url should be from the object (location unless
-				// we're testing) to avoid the inclusion of the authority
-				return uri.protocol + "//" + uri.host + uri.pathname + uri.search + hash;
-			},
-
-			//return the original document url
-			getDocumentUrl: function( asParsedObject ) {
-				return asParsedObject ? $.extend( {}, path.documentUrl ) : path.documentUrl.href;
-			},
-
-			parseLocation: function() {
-				return this.parseUrl( this.getLocation() );
-			},
-
-			//Parse a URL into a structure that allows easy access to
-			//all of the URL components by name.
-			parseUrl: function( url ) {
-				// If we're passed an object, we'll assume that it is
-				// a parsed url object and just return it back to the caller.
-				if ( $.type( url ) === "object" ) {
-					return url;
-				}
-
-				var matches = path.urlParseRE.exec( url || "" ) || [];
-
-					// Create an object that allows the caller to access the sub-matches
-					// by name. Note that IE returns an empty string instead of undefined,
-					// like all other browsers do, so we normalize everything so its consistent
-					// no matter what browser we're running on.
-					return {
-						href:         matches[  0 ] || "",
-						hrefNoHash:   matches[  1 ] || "",
-						hrefNoSearch: matches[  2 ] || "",
-						domain:       matches[  3 ] || "",
-						protocol:     matches[  4 ] || "",
-						doubleSlash:  matches[  5 ] || "",
-						authority:    matches[  6 ] || "",
-						username:     matches[  8 ] || "",
-						password:     matches[  9 ] || "",
-						host:         matches[ 10 ] || "",
-						hostname:     matches[ 11 ] || "",
-						port:         matches[ 12 ] || "",
-						pathname:     matches[ 13 ] || "",
-						directory:    matches[ 14 ] || "",
-						filename:     matches[ 15 ] || "",
-						search:       matches[ 16 ] || "",
-						hash:         matches[ 17 ] || ""
-					};
-			},
-
-			//Turn relPath into an asbolute path. absPath is
-			//an optional absolute path which describes what
-			//relPath is relative to.
-			makePathAbsolute: function( relPath, absPath ) {
-				var absStack,
-					relStack,
-					i, d;
-
-				if ( relPath && relPath.charAt( 0 ) === "/" ) {
-					return relPath;
-				}
-
-				relPath = relPath || "";
-				absPath = absPath ? absPath.replace( /^\/|(\/[^\/]*|[^\/]+)$/g, "" ) : "";
-
-				absStack = absPath ? absPath.split( "/" ) : [];
-				relStack = relPath.split( "/" );
-
-				for ( i = 0; i < relStack.length; i++ ) {
-					d = relStack[ i ];
-					switch ( d ) {
-						case ".":
-							break;
-						case "..":
-							if ( absStack.length ) {
-								absStack.pop();
-							}
-							break;
-						default:
-							absStack.push( d );
-							break;
-					}
-				}
-				return "/" + absStack.join( "/" );
-			},
-
-			//Returns true if both urls have the same domain.
-			isSameDomain: function( absUrl1, absUrl2 ) {
-				return path.parseUrl( absUrl1 ).domain === path.parseUrl( absUrl2 ).domain;
-			},
-
-			//Returns true for any relative variant.
-			isRelativeUrl: function( url ) {
-				// All relative Url variants have one thing in common, no protocol.
-				return path.parseUrl( url ).protocol === "";
-			},
-
-			//Returns true for an absolute url.
-			isAbsoluteUrl: function( url ) {
-				return path.parseUrl( url ).protocol !== "";
-			},
-
-			//Turn the specified realtive URL into an absolute one. This function
-			//can handle all relative variants (protocol, site, document, query, fragment).
-			makeUrlAbsolute: function( relUrl, absUrl ) {
-				if ( !path.isRelativeUrl( relUrl ) ) {
-					return relUrl;
-				}
-
-				if ( absUrl === undefined ) {
-					absUrl = this.documentBase;
-				}
-
-				var relObj = path.parseUrl( relUrl ),
-					absObj = path.parseUrl( absUrl ),
-					protocol = relObj.protocol || absObj.protocol,
-					doubleSlash = relObj.protocol ? relObj.doubleSlash : ( relObj.doubleSlash || absObj.doubleSlash ),
-					authority = relObj.authority || absObj.authority,
-					hasPath = relObj.pathname !== "",
-					pathname = path.makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname ),
-					search = relObj.search || ( !hasPath && absObj.search ) || "",
-					hash = relObj.hash;
-
-				return protocol + doubleSlash + authority + pathname + search + hash;
-			},
-
-			//Add search (aka query) params to the specified url.
-			addSearchParams: function( url, params ) {
-				var u = path.parseUrl( url ),
-					p = ( typeof params === "object" ) ? $.param( params ) : params,
-					s = u.search || "?";
-				return u.hrefNoSearch + s + ( s.charAt( s.length - 1 ) !== "?" ? "&" : "" ) + p + ( u.hash || "" );
-			},
-
-			convertUrlToDataUrl: function( absUrl ) {
-				var u = path.parseUrl( absUrl );
-				if ( path.isEmbeddedPage( u ) ) {
-					// For embedded pages, remove the dialog hash key as in getFilePath(),
-					// and remove otherwise the Data Url won't match the id of the embedded Page.
-					return u.hash
-						.split( dialogHashKey )[0]
-						.replace( /^#/, "" )
-						.replace( /\?.*$/, "" );
-				} else if ( path.isSameDomain( u, this.documentBase ) ) {
-					return u.hrefNoHash.replace( this.documentBase.domain, "" ).split( dialogHashKey )[0];
-				}
-
-				return window.decodeURIComponent(absUrl);
-			},
-
-			//get path from current hash, or from a file path
-			get: function( newPath ) {
-				if ( newPath === undefined ) {
-					newPath = path.parseLocation().hash;
-				}
-				return path.stripHash( newPath ).replace( /[^\/]*\.[^\/*]+$/, "" );
-			},
-
-			//set location hash to path
-			set: function( path ) {
-				location.hash = path;
-			},
-
-			//test if a given url (string) is a path
-			//NOTE might be exceptionally naive
-			isPath: function( url ) {
-				return ( /\// ).test( url );
-			},
-
-			//return a url path with the window's location protocol/hostname/pathname removed
-			clean: function( url ) {
-				return url.replace( this.documentBase.domain, "" );
-			},
-
-			//just return the url without an initial #
-			stripHash: function( url ) {
-				return url.replace( /^#/, "" );
-			},
-
-			stripQueryParams: function( url ) {
-				return url.replace( /\?.*$/, "" );
-			},
-
-			//remove the preceding hash, any query params, and dialog notations
-			cleanHash: function( hash ) {
-				return path.stripHash( hash.replace( /\?.*$/, "" ).replace( dialogHashKey, "" ) );
-			},
-
-			isHashValid: function( hash ) {
-				return ( /^#[^#]+$/ ).test( hash );
-			},
-
-			//check whether a url is referencing the same domain, or an external domain or different protocol
-			//could be mailto, etc
-			isExternal: function( url ) {
-				var u = path.parseUrl( url );
-				return u.protocol && u.domain !== this.documentUrl.domain ? true : false;
-			},
-
-			hasProtocol: function( url ) {
-				return ( /^(:?\w+:)/ ).test( url );
-			},
-
-			isEmbeddedPage: function( url ) {
-				var u = path.parseUrl( url );
-
-				//if the path is absolute, then we need to compare the url against
-				//both the this.documentUrl and the documentBase. The main reason for this
-				//is that links embedded within external documents will refer to the
-				//application document, whereas links embedded within the application
-				//document will be resolved against the document base.
-				if ( u.protocol !== "" ) {
-					return ( !this.isPath(u.hash) && u.hash && ( u.hrefNoHash === this.documentUrl.hrefNoHash || ( this.documentBaseDiffers && u.hrefNoHash === this.documentBase.hrefNoHash ) ) );
-				}
-				return ( /^#/ ).test( u.href );
-			},
-
-			squash: function( url, resolutionUrl ) {
-				var href, cleanedUrl, search, stateIndex,
-					isPath = this.isPath( url ),
-					uri = this.parseUrl( url ),
-					preservedHash = uri.hash,
-					uiState = "";
-
-				// produce a url against which we can resole the provided path
-				resolutionUrl = resolutionUrl || (path.isPath(url) ? path.getLocation() : path.getDocumentUrl());
-
-				// If the url is anything but a simple string, remove any preceding hash
-				// eg #foo/bar -> foo/bar
-				//    #foo -> #foo
-				cleanedUrl = isPath ? path.stripHash( url ) : url;
-
-				// If the url is a full url with a hash check if the parsed hash is a path
-				// if it is, strip the #, and use it otherwise continue without change
-				cleanedUrl = path.isPath( uri.hash ) ? path.stripHash( uri.hash ) : cleanedUrl;
-
-				// Split the UI State keys off the href
-				stateIndex = cleanedUrl.indexOf( this.uiStateKey );
-
-				// store the ui state keys for use
-				if ( stateIndex > -1 ) {
-					uiState = cleanedUrl.slice( stateIndex );
-					cleanedUrl = cleanedUrl.slice( 0, stateIndex );
-				}
-
-				// make the cleanedUrl absolute relative to the resolution url
-				href = path.makeUrlAbsolute( cleanedUrl, resolutionUrl );
-
-				// grab the search from the resolved url since parsing from
-				// the passed url may not yield the correct result
-				search = this.parseUrl( href ).search;
-
-				// TODO all this crap is terrible, clean it up
-				if ( isPath ) {
-					// reject the hash if it's a path or it's just a dialog key
-					if ( path.isPath( preservedHash ) || preservedHash.replace("#", "").indexOf( this.uiStateKey ) === 0) {
-						preservedHash = "";
-					}
-
-					// Append the UI State keys where it exists and it's been removed
-					// from the url
-					if ( uiState && preservedHash.indexOf( this.uiStateKey ) === -1) {
-						preservedHash += uiState;
-					}
-
-					// make sure that pound is on the front of the hash
-					if ( preservedHash.indexOf( "#" ) === -1 && preservedHash !== "" ) {
-						preservedHash = "#" + preservedHash;
-					}
-
-					// reconstruct each of the pieces with the new search string and hash
-					href = path.parseUrl( href );
-					href = href.protocol + "//" + href.host + href.pathname + search + preservedHash;
-				} else {
-					href += href.indexOf( "#" ) > -1 ? uiState : "#" + uiState;
-				}
-
-				return href;
-			},
-
-			isPreservableHash: function( hash ) {
-				return hash.replace( "#", "" ).indexOf( this.uiStateKey ) === 0;
-			},
-
-			// Escape weird characters in the hash if it is to be used as a selector
-			hashToSelector: function( hash ) {
-				var hasHash = ( hash.substring( 0, 1 ) === "#" );
-				if ( hasHash ) {
-					hash = hash.substring( 1 );
-				}
-				return ( hasHash ? "#" : "" ) + hash.replace( /([!"#$%&'()*+,./:;<=>?@[\]^`{|}~])/g, "\\$1" );
-			},
-
-			// return the substring of a filepath before the sub-page key, for making
-			// a server request
-			getFilePath: function( path ) {
-				var splitkey = "&" + $.mobile.subPageUrlKey;
-				return path && path.split( splitkey )[0].split( dialogHashKey )[0];
-			},
-
-			// check if the specified url refers to the first page in the main
-			// application document.
-			isFirstPageUrl: function( url ) {
-				// We only deal with absolute paths.
-				var u = path.parseUrl( path.makeUrlAbsolute( url, this.documentBase ) ),
-
-					// Does the url have the same path as the document?
-					samePath = u.hrefNoHash === this.documentUrl.hrefNoHash ||
-						( this.documentBaseDiffers &&
-							u.hrefNoHash === this.documentBase.hrefNoHash ),
-
-					// Get the first page element.
-					fp = $.mobile.firstPage,
-
-					// Get the id of the first page element if it has one.
-					fpId = fp && fp[0] ? fp[0].id : undefined;
-
-				// The url refers to the first page if the path matches the document and
-				// it either has no hash value, or the hash is exactly equal to the id
-				// of the first page element.
-				return samePath &&
-					( !u.hash ||
-						u.hash === "#" ||
-						( fpId && u.hash.replace( /^#/, "" ) === fpId ) );
-			},
-
-			// Some embedded browsers, like the web view in Phone Gap, allow
-			// cross-domain XHR requests if the document doing the request was loaded
-			// via the file:// protocol. This is usually to allow the application to
-			// "phone home" and fetch app specific data. We normally let the browser
-			// handle external/cross-domain urls, but if the allowCrossDomainPages
-			// option is true, we will allow cross-domain http/https requests to go
-			// through our page loading logic.
-			isPermittedCrossDomainRequest: function( docUrl, reqUrl ) {
-				return $.mobile.allowCrossDomainPages &&
-					(docUrl.protocol === "file:" || docUrl.protocol === "content:") &&
-					reqUrl.search( /^https?:/ ) !== -1;
-			}
-		};
-
-		path.documentUrl = path.parseLocation();
-
-		$base = $( "head" ).find( "base" );
-
-		path.documentBase = $base.length ?
-			path.parseUrl( path.makeUrlAbsolute( $base.attr( "href" ), path.documentUrl.href ) ) :
-			path.documentUrl;
-
-		path.documentBaseDiffers = (path.documentUrl.hrefNoHash !== path.documentBase.hrefNoHash);
-
-		//return the original document base url
-		path.getDocumentBase = function( asParsedObject ) {
-			return asParsedObject ? $.extend( {}, path.documentBase ) : path.documentBase.href;
-		};
-
-		// DEPRECATED as of 1.4.0 - remove in 1.5.0
-		$.extend( $.mobile, {
-
-			//return the original document url
-			getDocumentUrl: path.getDocumentUrl,
-
-			//return the original document base url
-			getDocumentBase: path.getDocumentBase
-		});
-})( jQuery );
-
-
-
-(function( $, undefined ) {
-	$.mobile.History = function( stack, index ) {
-		this.stack = stack || [];
-		this.activeIndex = index || 0;
-	};
-
-	$.extend($.mobile.History.prototype, {
-		getActive: function() {
-			return this.stack[ this.activeIndex ];
-		},
-
-		getLast: function() {
-			return this.stack[ this.previousIndex ];
-		},
-
-		getNext: function() {
-			return this.stack[ this.activeIndex + 1 ];
-		},
-
-		getPrev: function() {
-			return this.stack[ this.activeIndex - 1 ];
-		},
-
-		// addNew is used whenever a new page is added
-		add: function( url, data ) {
-			data = data || {};
-
-			//if there's forward history, wipe it
-			if ( this.getNext() ) {
-				this.clearForward();
-			}
-
-			// if the hash is included in the data make sure the shape
-			// is consistent for comparison
-			if ( data.hash && data.hash.indexOf( "#" ) === -1) {
-				data.hash = "#" + data.hash;
-			}
-
-			data.url = url;
-			this.stack.push( data );
-			this.activeIndex = this.stack.length - 1;
-		},
-
-		//wipe urls ahead of active index
-		clearForward: function() {
-			this.stack = this.stack.slice( 0, this.activeIndex + 1 );
-		},
-
-		find: function( url, stack, earlyReturn ) {
-			stack = stack || this.stack;
-
-			var entry, i, length = stack.length, index;
-
-			for ( i = 0; i < length; i++ ) {
-				entry = stack[i];
-
-				if ( decodeURIComponent(url) === decodeURIComponent(entry.url) ||
-					decodeURIComponent(url) === decodeURIComponent(entry.hash) ) {
-					index = i;
-
-					if ( earlyReturn ) {
-						return index;
-					}
-				}
-			}
-
-			return index;
-		},
-
-		closest: function( url ) {
-			var closest, a = this.activeIndex;
-
-			// First, take the slice of the history stack before the current index and search
-			// for a url match. If one is found, we'll avoid avoid looking through forward history
-			// NOTE the preference for backward history movement is driven by the fact that
-			//      most mobile browsers only have a dedicated back button, and users rarely use
-			//      the forward button in desktop browser anyhow
-			closest = this.find( url, this.stack.slice(0, a) );
-
-			// If nothing was found in backward history check forward. The `true`
-			// value passed as the third parameter causes the find method to break
-			// on the first match in the forward history slice. The starting index
-			// of the slice must then be added to the result to get the element index
-			// in the original history stack :( :(
-			//
-			// TODO this is hyper confusing and should be cleaned up (ugh so bad)
-			if ( closest === undefined ) {
-				closest = this.find( url, this.stack.slice(a), true );
-				closest = closest === undefined ? closest : closest + a;
-			}
-
-			return closest;
-		},
-
-		direct: function( opts ) {
-			var newActiveIndex = this.closest( opts.url ), a = this.activeIndex;
-
-			// save new page index, null check to prevent falsey 0 result
-			// record the previous index for reference
-			if ( newActiveIndex !== undefined ) {
-				this.activeIndex = newActiveIndex;
-				this.previousIndex = a;
-			}
-
-			// invoke callbacks where appropriate
-			//
-			// TODO this is also convoluted and confusing
-			if ( newActiveIndex < a ) {
-				( opts.present || opts.back || $.noop )( this.getActive(), "back" );
-			} else if ( newActiveIndex > a ) {
-				( opts.present || opts.forward || $.noop )( this.getActive(), "forward" );
-			} else if ( newActiveIndex === undefined && opts.missing ) {
-				opts.missing( this.getActive() );
-			}
-		}
-	});
-})( jQuery );
-
-
-
-(function( $, undefined ) {
-	var path = $.mobile.path,
-		initialHref = location.href;
-
-	$.mobile.Navigator = function( history ) {
-		this.history = history;
-		this.ignoreInitialHashChange = true;
-
-		$.mobile.window.bind({
-			"popstate.history": $.proxy( this.popstate, this ),
-			"hashchange.history": $.proxy( this.hashchange, this )
-		});
-	};
-
-	$.extend($.mobile.Navigator.prototype, {
-		squash: function( url, data ) {
-			var state, href, hash = path.isPath(url) ? path.stripHash(url) : url;
-
-			href = path.squash( url );
-
-			// make sure to provide this information when it isn't explicitly set in the
-			// data object that was passed to the squash method
-			state = $.extend({
-				hash: hash,
-				url: href
-			}, data);
-
-			// replace the current url with the new href and store the state
-			// Note that in some cases we might be replacing an url with the
-			// same url. We do this anyways because we need to make sure that
-			// all of our history entries have a state object associated with
-			// them. This allows us to work around the case where $.mobile.back()
-			// is called to transition from an external page to an embedded page.
-			// In that particular case, a hashchange event is *NOT* generated by the browser.
-			// Ensuring each history entry has a state object means that onPopState()
-			// will always trigger our hashchange callback even when a hashchange event
-			// is not fired.
-			window.history.replaceState( state, state.title || document.title, href );
-
-			return state;
-		},
-
-		hash: function( url, href ) {
-			var parsed, loc, hash, resolved;
-
-			// Grab the hash for recording. If the passed url is a path
-			// we used the parsed version of the squashed url to reconstruct,
-			// otherwise we assume it's a hash and store it directly
-			parsed = path.parseUrl( url );
-			loc = path.parseLocation();
-
-			if ( loc.pathname + loc.search === parsed.pathname + parsed.search ) {
-				// If the pathname and search of the passed url is identical to the current loc
-				// then we must use the hash. Otherwise there will be no event
-				// eg, url = "/foo/bar?baz#bang", location.href = "http://example.com/foo/bar?baz"
-				hash = parsed.hash ? parsed.hash : parsed.pathname + parsed.search;
-			} else if ( path.isPath(url) ) {
-				resolved = path.parseUrl( href );
-				// If the passed url is a path, make it domain relative and remove any trailing hash
-				hash = resolved.pathname + resolved.search + (path.isPreservableHash( resolved.hash )? resolved.hash.replace( "#", "" ) : "");
-			} else {
-				hash = url;
-			}
-
-			return hash;
-		},
-
-		// TODO reconsider name
-		go: function( url, data, noEvents ) {
-			var state, href, hash, popstateEvent,
-				isPopStateEvent = $.event.special.navigate.isPushStateEnabled();
-
-			// Get the url as it would look squashed on to the current resolution url
-			href = path.squash( url );
-
-			// sort out what the hash sould be from the url
-			hash = this.hash( url, href );
-
-			// Here we prevent the next hash change or popstate event from doing any
-			// history management. In the case of hashchange we don't swallow it
-			// if there will be no hashchange fired (since that won't reset the value)
-			// and will swallow the following hashchange
-			if ( noEvents && hash !== path.stripHash(path.parseLocation().hash) ) {
-				this.preventNextHashChange = noEvents;
-			}
-
-			// IMPORTANT in the case where popstate is supported the event will be triggered
-			//      directly, stopping further execution - ie, interupting the flow of this
-			//      method call to fire bindings at this expression. Below the navigate method
-			//      there is a binding to catch this event and stop its propagation.
-			//
-			//      We then trigger a new popstate event on the window with a null state
-			//      so that the navigate events can conclude their work properly
-			//
-			// if the url is a path we want to preserve the query params that are available on
-			// the current url.
-			this.preventHashAssignPopState = true;
-			window.location.hash = hash;
-
-			// If popstate is enabled and the browser triggers `popstate` events when the hash
-			// is set (this often happens immediately in browsers like Chrome), then the
-			// this flag will be set to false already. If it's a browser that does not trigger
-			// a `popstate` on hash assignement or `replaceState` then we need avoid the branch
-			// that swallows the event created by the popstate generated by the hash assignment
-			// At the time of this writing this happens with Opera 12 and some version of IE
-			this.preventHashAssignPopState = false;
-
-			state = $.extend({
-				url: href,
-				hash: hash,
-				title: document.title
-			}, data);
-
-			if ( isPopStateEvent ) {
-				popstateEvent = new $.Event( "popstate" );
-				popstateEvent.originalEvent = {
-					type: "popstate",
-					state: null
-				};
-
-				this.squash( url, state );
-
-				// Trigger a new faux popstate event to replace the one that we
-				// caught that was triggered by the hash setting above.
-				if ( !noEvents ) {
-					this.ignorePopState = true;
-					$.mobile.window.trigger( popstateEvent );
-				}
-			}
-
-			// record the history entry so that the information can be included
-			// in hashchange event driven navigate events in a similar fashion to
-			// the state that's provided by popstate
-			this.history.add( state.url, state );
-		},
-
-		// This binding is intended to catch the popstate events that are fired
-		// when execution of the `$.navigate` method stops at window.location.hash = url;
-		// and completely prevent them from propagating. The popstate event will then be
-		// retriggered after execution resumes
-		//
-		// TODO grab the original event here and use it for the synthetic event in the
-		//      second half of the navigate execution that will follow this binding
-		popstate: function( event ) {
-			var hash, state;
-
-			// Partly to support our test suite which manually alters the support
-			// value to test hashchange. Partly to prevent all around weirdness
-			if ( !$.event.special.navigate.isPushStateEnabled() ) {
-				return;
-			}
-
-			// If this is the popstate triggered by the actual alteration of the hash
-			// prevent it completely. History is tracked manually
-			if ( this.preventHashAssignPopState ) {
-				this.preventHashAssignPopState = false;
-				event.stopImmediatePropagation();
-				return;
-			}
-
-			// if this is the popstate triggered after the `replaceState` call in the go
-			// method, then simply ignore it. The history entry has already been captured
-			if ( this.ignorePopState ) {
-				this.ignorePopState = false;
-				return;
-			}
-
-			// If there is no state, and the history stack length is one were
-			// probably getting the page load popstate fired by browsers like chrome
-			// avoid it and set the one time flag to false.
-			// TODO: Do we really need all these conditions? Comparing location hrefs
-			// should be sufficient.
-			if ( !event.originalEvent.state &&
-				this.history.stack.length === 1 &&
-				this.ignoreInitialHashChange ) {
-				this.ignoreInitialHashChange = false;
-
-				if ( location.href === initialHref ) {
-					event.preventDefault();
-					return;
-				}
-			}
-
-			// account for direct manipulation of the hash. That is, we will receive a popstate
-			// when the hash is changed by assignment, and it won't have a state associated. We
-			// then need to squash the hash. See below for handling of hash assignment that
-			// matches an existing history entry
-			// TODO it might be better to only add to the history stack
-			//      when the hash is adjacent to the active history entry
-			hash = path.parseLocation().hash;
-			if ( !event.originalEvent.state && hash ) {
-				// squash the hash that's been assigned on the URL with replaceState
-				// also grab the resulting state object for storage
-				state = this.squash( hash );
-
-				// record the new hash as an additional history entry
-				// to match the browser's treatment of hash assignment
-				this.history.add( state.url, state );
-
-				// pass the newly created state information
-				// along with the event
-				event.historyState = state;
-
-				// do not alter history, we've added a new history entry
-				// so we know where we are
-				return;
-			}
-
-			// If all else fails this is a popstate that comes from the back or forward buttons
-			// make sure to set the state of our history stack properly, and record the directionality
-			this.history.direct({
-				url: (event.originalEvent.state || {}).url || hash,
-
-				// When the url is either forward or backward in history include the entry
-				// as data on the event object for merging as data in the navigate event
-				present: function( historyEntry, direction ) {
-					// make sure to create a new object to pass down as the navigate event data
-					event.historyState = $.extend({}, historyEntry);
-					event.historyState.direction = direction;
-				}
-			});
-		},
-
-		// NOTE must bind before `navigate` special event hashchange binding otherwise the
-		//      navigation data won't be attached to the hashchange event in time for those
-		//      bindings to attach it to the `navigate` special event
-		// TODO add a check here that `hashchange.navigate` is bound already otherwise it's
-		//      broken (exception?)
-		hashchange: function( event ) {
-			var history, hash;
-
-			// If hashchange listening is explicitly disabled or pushstate is supported
-			// avoid making use of the hashchange handler.
-			if (!$.event.special.navigate.isHashChangeEnabled() ||
-				$.event.special.navigate.isPushStateEnabled() ) {
-				return;
-			}
-
-			// On occasion explicitly want to prevent the next hash from propogating because we only
-			// with to alter the url to represent the new state do so here
-			if ( this.preventNextHashChange ) {
-				this.preventNextHashChange = false;
-				event.stopImmediatePropagation();
-				return;
-			}
-
-			history = this.history;
-			hash = path.parseLocation().hash;
-
-			// If this is a hashchange caused by the back or forward button
-			// make sure to set the state of our history stack properly
-			this.history.direct({
-				url: hash,
-
-				// When the url is either forward or backward in history include the entry
-				// as data on the event object for merging as data in the navigate event
-				present: function( historyEntry, direction ) {
-					// make sure to create a new object to pass down as the navigate event data
-					event.hashchangeState = $.extend({}, historyEntry);
-					event.hashchangeState.direction = direction;
-				},
-
-				// When we don't find a hash in our history clearly we're aiming to go there
-				// record the entry as new for future traversal
-				//
-				// NOTE it's not entirely clear that this is the right thing to do given that we
-				//      can't know the users intention. It might be better to explicitly _not_
-				//      support location.hash assignment in preference to $.navigate calls
-				// TODO first arg to add should be the href, but it causes issues in identifying
-				//      embeded pages
-				missing: function() {
-					history.add( hash, {
-						hash: hash,
-						title: document.title
-					});
-				}
-			});
-		}
-	});
-})( jQuery );
-
-
-
-(function( $, undefined ) {
-	// TODO consider queueing navigation activity until previous activities have completed
-	//      so that end users don't have to think about it. Punting for now
-	// TODO !! move the event bindings into callbacks on the navigate event
-	$.mobile.navigate = function( url, data, noEvents ) {
-		$.mobile.navigate.navigator.go( url, data, noEvents );
-	};
-
-	// expose the history on the navigate method in anticipation of full integration with
-	// existing navigation functionalty that is tightly coupled to the history information
-	$.mobile.navigate.history = new $.mobile.History();
-
-	// instantiate an instance of the navigator for use within the $.navigate method
-	$.mobile.navigate.navigator = new $.mobile.Navigator( $.mobile.navigate.history );
-
-	var loc = $.mobile.path.parseLocation();
-	$.mobile.navigate.history.add( loc.href, {hash: loc.hash} );
-})( jQuery );
-
-
-(function( $, undefined ) {
-	var props = {
-			"animation": {},
-			"transition": {}
-		},
-		testElement = document.createElement( "a" ),
-		vendorPrefixes = [ "", "webkit-", "moz-", "o-" ];
-
-	$.each( [ "animation", "transition" ], function( i, test ) {
-
-		// Get correct name for test
-		var testName = ( i === 0 ) ? test + "-" + "name" : test;
-
-		$.each( vendorPrefixes, function( j, prefix ) {
-			if ( testElement.style[ $.camelCase( prefix + testName ) ] !== undefined ) {
-				 props[ test ][ "prefix" ] = prefix;
-				return false;
-			}
-		});
-
-		// Set event and duration names for later use
-		props[ test ][ "duration" ] =
-			$.camelCase( props[ test ][ "prefix" ] + test + "-" + "duration" );
-		props[ test ][ "event" ] =
-			$.camelCase( props[ test ][ "prefix" ] + test + "-" + "end" );
-
-		// All lower case if not a vendor prop
-		if ( props[ test ][ "prefix" ] === "" ) {
-			props[ test ][ "event" ] = props[ test ][ "event" ].toLowerCase();
-		}
-	});
-
-	// If a valid prefix was found then the it is supported by the browser
-	$.support.cssTransitions = ( props[ "transition" ][ "prefix" ] !== undefined );
-	$.support.cssAnimations = ( props[ "animation" ][ "prefix" ] !== undefined );
-
-	// Remove the testElement
-	$( testElement ).remove();
-
-	// Animation complete callback
-	$.fn.animationComplete = function( callback, type, fallbackTime ) {
-		var timer, duration,
-			that = this,
-			animationType = ( !type || type === "animation" ) ? "animation" : "transition";
-
-		// Make sure selected type is supported by browser
-		if ( ( $.support.cssTransitions && animationType === "transition" ) ||
-			( $.support.cssAnimations && animationType === "animation" ) ) {
-
-			// If a fallback time was not passed set one
-			if ( fallbackTime === undefined ) {
-
-				// Make sure the was not bound to document before checking .css
-				if ( $( this ).context !== document ) {
-
-					// Parse the durration since its in second multiple by 1000 for milliseconds
-					// Multiply by 3 to make sure we give the animation plenty of time.
-					duration = parseFloat(
-						$( this ).css( props[ animationType ].duration )
-					) * 3000;
-				}
-
-				// If we could not read a duration use the default
-				if ( duration === 0 || duration === undefined || isNaN( duration ) ) {
-					duration = $.fn.animationComplete.defaultDuration;
-				}
-			}
-
-			// Sets up the fallback if event never comes
-			timer = setTimeout( function() {
-				$( that ).off( props[ animationType ].event );
-				callback.apply( that );
-			}, duration );
-
-			// Bind the event
-			return $( this ).one( props[ animationType ].event, function() {
-
-				// Clear the timer so we dont call callback twice
-				clearTimeout( timer );
-				callback.call( this, arguments );
-			});
-		} else {
-
-			// CSS animation / transitions not supported
-			// Defer execution for consistency between webkit/non webkit
-			setTimeout( $.proxy( callback, this ), 0 );
-			return $( this );
-		}
-	};
-
-	// Allow default callback to be configured on mobileInit
-	$.fn.animationComplete.defaultDuration = 1000;
-})( jQuery );
-
-// This plugin is an experiment for abstracting away the touch and mouse
-// events so that developers don't have to worry about which method of input
-// the device their document is loaded on supports.
-//
-// The idea here is to allow the developer to register listeners for the
-// basic mouse events, such as mousedown, mousemove, mouseup, and click,
-// and the plugin will take care of registering the correct listeners
-// behind the scenes to invoke the listener at the fastest possible time
-// for that device, while still retaining the order of event firing in
-// the traditional mouse environment, should multiple handlers be registered
-// on the same element for different events.
-//
-// The current version exposes the following virtual events to jQuery bind methods:
-// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel"
-
-(function( $, window, document, undefined ) {
-
-var dataPropertyName = "virtualMouseBindings",
-	touchTargetPropertyName = "virtualTouchID",
-	virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ),
-	touchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ),
-	mouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [],
-	mouseEventProps = $.event.props.concat( mouseHookProps ),
-	activeDocHandlers = {},
-	resetTimerID = 0,
-	startX = 0,
-	startY = 0,
-	didScroll = false,
-	clickBlockList = [],
-	blockMouseTriggers = false,
-	blockTouchTriggers = false,
-	eventCaptureSupported = "addEventListener" in document,
-	$document = $( document ),
-	nextTouchID = 1,
-	lastTouchID = 0, threshold,
-	i;
-
-$.vmouse = {
-	moveDistanceThreshold: 10,
-	clickDistanceThreshold: 10,
-	resetTimerDuration: 1500
-};
-
-function getNativeEvent( event ) {
-
-	while ( event && typeof event.originalEvent !== "undefined" ) {
-		event = event.originalEvent;
-	}
-	return event;
-}
-
-function createVirtualEvent( event, eventType ) {
-
-	var t = event.type,
-		oe, props, ne, prop, ct, touch, i, j, len;
-
-	event = $.Event( event );
-	event.type = eventType;
-
-	oe = event.originalEvent;
-	props = $.event.props;
-
-	// addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280
-	// https://github.com/jquery/jquery-mobile/issues/3280
-	if ( t.search( /^(mouse|click)/ ) > -1 ) {
-		props = mouseEventProps;
-	}
-
-	// copy original event properties over to the new event
-	// this would happen if we could call $.event.fix instead of $.Event
-	// but we don't have a way to force an event to be fixed multiple times
-	if ( oe ) {
-		for ( i = props.length, prop; i; ) {
-			prop = props[ --i ];
-			event[ prop ] = oe[ prop ];
-		}
-	}
-
-	// make sure that if the mouse and click virtual events are generated
-	// without a .which one is defined
-	if ( t.search(/mouse(down|up)|click/) > -1 && !event.which ) {
-		event.which = 1;
-	}
-
-	if ( t.search(/^touch/) !== -1 ) {
-		ne = getNativeEvent( oe );
-		t = ne.touches;
-		ct = ne.changedTouches;
-		touch = ( t && t.length ) ? t[0] : ( ( ct && ct.length ) ? ct[ 0 ] : undefined );
-
-		if ( touch ) {
-			for ( j = 0, len = touchEventProps.length; j < len; j++) {
-				prop = touchEventProps[ j ];
-				event[ prop ] = touch[ prop ];
-			}
-		}
-	}
-
-	return event;
-}
-
-function getVirtualBindingFlags( element ) {
-
-	var flags = {},
-		b, k;
-
-	while ( element ) {
-
-		b = $.data( element, dataPropertyName );
-
-		for (  k in b ) {
-			if ( b[ k ] ) {
-				flags[ k ] = flags.hasVirtualBinding = true;
-			}
-		}
-		element = element.parentNode;
-	}
-	return flags;
-}
-
-function getClosestElementWithVirtualBinding( element, eventType ) {
-	var b;
-	while ( element ) {
-
-		b = $.data( element, dataPropertyName );
-
-		if ( b && ( !eventType || b[ eventType ] ) ) {
-			return element;
-		}
-		element = element.parentNode;
-	}
-	return null;
-}
-
-function enableTouchBindings() {
-	blockTouchTriggers = false;
-}
-
-function disableTouchBindings() {
-	blockTouchTriggers = true;
-}
-
-function enableMouseBindings() {
-	lastTouchID = 0;
-	clickBlockList.length = 0;
-	blockMouseTriggers = false;
-
-	// When mouse bindings are enabled, our
-	// touch bindings are disabled.
-	disableTouchBindings();
-}
-
-function disableMouseBindings() {
-	// When mouse bindings are disabled, our
-	// touch bindings are enabled.
-	enableTouchBindings();
-}
-
-function startResetTimer() {
-	clearResetTimer();
-	resetTimerID = setTimeout( function() {
-		resetTimerID = 0;
-		enableMouseBindings();
-	}, $.vmouse.resetTimerDuration );
-}
-
-function clearResetTimer() {
-	if ( resetTimerID ) {
-		clearTimeout( resetTimerID );
-		resetTimerID = 0;
-	}
-}
-
-function triggerVirtualEvent( eventType, event, flags ) {
-	var ve;
-
-	if ( ( flags && flags[ eventType ] ) ||
-				( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {
-
-		ve = createVirtualEvent( event, eventType );
-
-		$( event.target).trigger( ve );
-	}
-
-	return ve;
-}
-
-function mouseEventCallback( event ) {
-	var touchID = $.data( event.target, touchTargetPropertyName ),
-		ve;
-
-	if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ) {
-		ve = triggerVirtualEvent( "v" + event.type, event );
-		if ( ve ) {
-			if ( ve.isDefaultPrevented() ) {
-				event.preventDefault();
-			}
-			if ( ve.isPropagationStopped() ) {
-				event.stopPropagation();
-			}
-			if ( ve.isImmediatePropagationStopped() ) {
-				event.stopImmediatePropagation();
-			}
-		}
-	}
-}
-
-function handleTouchStart( event ) {
-
-	var touches = getNativeEvent( event ).touches,
-		target, flags, t;
-
-	if ( touches && touches.length === 1 ) {
-
-		target = event.target;
-		flags = getVirtualBindingFlags( target );
-
-		if ( flags.hasVirtualBinding ) {
-
-			lastTouchID = nextTouchID++;
-			$.data( target, touchTargetPropertyName, lastTouchID );
-
-			clearResetTimer();
-
-			disableMouseBindings();
-			didScroll = false;
-
-			t = getNativeEvent( event ).touches[ 0 ];
-			startX = t.pageX;
-			startY = t.pageY;
-
-			triggerVirtualEvent( "vmouseover", event, flags );
-			triggerVirtualEvent( "vmousedown", event, flags );
-		}
-	}
-}
-
-function handleScroll( event ) {
-	if ( blockTouchTriggers ) {
-		return;
-	}
-
-	if ( !didScroll ) {
-		triggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) );
-	}
-
-	didScroll = true;
-	startResetTimer();
-}
-
-function handleTouchMove( event ) {
-	if ( blockTouchTriggers ) {
-		return;
-	}
-
-	var t = getNativeEvent( event ).touches[ 0 ],
-		didCancel = didScroll,
-		moveThreshold = $.vmouse.moveDistanceThreshold,
-		flags = getVirtualBindingFlags( event.target );
-
-		didScroll = didScroll ||
-			( Math.abs( t.pageX - startX ) > moveThreshold ||
-				Math.abs( t.pageY - startY ) > moveThreshold );
-
-	if ( didScroll && !didCancel ) {
-		triggerVirtualEvent( "vmousecancel", event, flags );
-	}
-
-	triggerVirtualEvent( "vmousemove", event, flags );
-	startResetTimer();
-}
-
-function handleTouchEnd( event ) {
-	if ( blockTouchTriggers ) {
-		return;
-	}
-
-	disableTouchBindings();
-
-	var flags = getVirtualBindingFlags( event.target ),
-		ve, t;
-	triggerVirtualEvent( "vmouseup", event, flags );
-
-	if ( !didScroll ) {
-		ve = triggerVirtualEvent( "vclick", event, flags );
-		if ( ve && ve.isDefaultPrevented() ) {
-			// The target of the mouse events that follow the touchend
-			// event don't necessarily match the target used during the
-			// touch. This means we need to rely on coordinates for blocking
-			// any click that is generated.
-			t = getNativeEvent( event ).changedTouches[ 0 ];
-			clickBlockList.push({
-				touchID: lastTouchID,
-				x: t.clientX,
-				y: t.clientY
-			});
-
-			// Prevent any mouse events that follow from triggering
-			// virtual event notifications.
-			blockMouseTriggers = true;
-		}
-	}
-	triggerVirtualEvent( "vmouseout", event, flags);
-	didScroll = false;
-
-	startResetTimer();
-}
-
-function hasVirtualBindings( ele ) {
-	var bindings = $.data( ele, dataPropertyName ),
-		k;
-
-	if ( bindings ) {
-		for ( k in bindings ) {
-			if ( bindings[ k ] ) {
-				return true;
-			}
-		}
-	}
-	return false;
-}
-
-function dummyMouseHandler() {}
-
-function getSpecialEventObject( eventType ) {
-	var realType = eventType.substr( 1 );
-
-	return {
-		setup: function(/* data, namespace */) {
-			// If this is the first virtual mouse binding for this element,
-			// add a bindings object to its data.
-
-			if ( !hasVirtualBindings( this ) ) {
-				$.data( this, dataPropertyName, {} );
-			}
-
-			// If setup is called, we know it is the first binding for this
-			// eventType, so initialize the count for the eventType to zero.
-			var bindings = $.data( this, dataPropertyName );
-			bindings[ eventType ] = true;
-
-			// If this is the first virtual mouse event for this type,
-			// register a global handler on the document.
-
-			activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;
-
-			if ( activeDocHandlers[ eventType ] === 1 ) {
-				$document.bind( realType, mouseEventCallback );
-			}
-
-			// Some browsers, like Opera Mini, won't dispatch mouse/click events
-			// for elements unless they actually have handlers registered on them.
-			// To get around this, we register dummy handlers on the elements.
-
-			$( this ).bind( realType, dummyMouseHandler );
-
-			// For now, if event capture is not supported, we rely on mouse handlers.
-			if ( eventCaptureSupported ) {
-				// If this is the first virtual mouse binding for the document,
-				// register our touchstart handler on the document.
-
-				activeDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0) + 1;
-
-				if ( activeDocHandlers[ "touchstart" ] === 1 ) {
-					$document.bind( "touchstart", handleTouchStart )
-						.bind( "touchend", handleTouchEnd )
-
-						// On touch platforms, touching the screen and then dragging your finger
-						// causes the window content to scroll after some distance threshold is
-						// exceeded. On these platforms, a scroll prevents a click event from being
-						// dispatched, and on some platforms, even the touchend is suppressed. To
-						// mimic the suppression of the click event, we need to watch for a scroll
-						// event. Unfortunately, some platforms like iOS don't dispatch scroll
-						// events until *AFTER* the user lifts their finger (touchend). This means
-						// we need to watch both scroll and touchmove events to figure out whether
-						// or not a scroll happenens before the touchend event is fired.
-
-						.bind( "touchmove", handleTouchMove )
-						.bind( "scroll", handleScroll );
-				}
-			}
-		},
-
-		teardown: function(/* data, namespace */) {
-			// If this is the last virtual binding for this eventType,
-			// remove its global handler from the document.
-
-			--activeDocHandlers[ eventType ];
-
-			if ( !activeDocHandlers[ eventType ] ) {
-				$document.unbind( realType, mouseEventCallback );
-			}
-
-			if ( eventCaptureSupported ) {
-				// If this is the last virtual mouse binding in existence,
-				// remove our document touchstart listener.
-
-				--activeDocHandlers[ "touchstart" ];
-
-				if ( !activeDocHandlers[ "touchstart" ] ) {
-					$document.unbind( "touchstart", handleTouchStart )
-						.unbind( "touchmove", handleTouchMove )
-						.unbind( "touchend", handleTouchEnd )
-						.unbind( "scroll", handleScroll );
-				}
-			}
-
-			var $this = $( this ),
-				bindings = $.data( this, dataPropertyName );
-
-			// teardown may be called when an element was
-			// removed from the DOM. If this is the case,
-			// jQuery core may have already stripped the element
-			// of any data bindings so we need to check it before
-			// using it.
-			if ( bindings ) {
-				bindings[ eventType ] = false;
-			}
-
-			// Unregister the dummy event handler.
-
-			$this.unbind( realType, dummyMouseHandler );
-
-			// If this is the last virtual mouse binding on the
-			// element, remove the binding data from the element.
-
-			if ( !hasVirtualBindings( this ) ) {
-				$this.removeData( dataPropertyName );
-			}
-		}
-	};
-}
-
-// Expose our custom events to the jQuery bind/unbind mechanism.
-
-for ( i = 0; i < virtualEventNames.length; i++ ) {
-	$.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );
-}
-
-// Add a capture click handler to block clicks.
-// Note that we require event capture support for this so if the device
-// doesn't support it, we punt for now and rely solely on mouse events.
-if ( eventCaptureSupported ) {
-	document.addEventListener( "click", function( e ) {
-		var cnt = clickBlockList.length,
-			target = e.target,
-			x, y, ele, i, o, touchID;
-
-		if ( cnt ) {
-			x = e.clientX;
-			y = e.clientY;
-			threshold = $.vmouse.clickDistanceThreshold;
-
-			// The idea here is to run through the clickBlockList to see if
-			// the current click event is in the proximity of one of our
-			// vclick events that had preventDefault() called on it. If we find
-			// one, then we block the click.
-			//
-			// Why do we have to rely on proximity?
-			//
-			// Because the target of the touch event that triggered the vclick
-			// can be different from the target of the click event synthesized
-			// by the browser. The target of a mouse/click event that is synthesized
-			// from a touch event seems to be implementation specific. For example,
-			// some browsers will fire mouse/click events for a link that is near
-			// a touch event, even though the target of the touchstart/touchend event
-			// says the user touched outside the link. Also, it seems that with most
-			// browsers, the target of the mouse/click event is not calculated until the
-			// time it is dispatched, so if you replace an element that you touched
-			// with another element, the target of the mouse/click will be the new
-			// element underneath that point.
-			//
-			// Aside from proximity, we also check to see if the target and any
-			// of its ancestors were the ones that blocked a click. This is necessary
-			// because of the strange mouse/click target calculation done in the
-			// Android 2.1 browser, where if you click on an element, and there is a
-			// mouse/click handler on one of its ancestors, the target will be the
-			// innermost child of the touched element, even if that child is no where
-			// near the point of touch.
-
-			ele = target;
-
-			while ( ele ) {
-				for ( i = 0; i < cnt; i++ ) {
-					o = clickBlockList[ i ];
-					touchID = 0;
-
-					if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||
-								$.data( ele, touchTargetPropertyName ) === o.touchID ) {
-						// XXX: We may want to consider removing matches from the block list
-						//      instead of waiting for the reset timer to fire.
-						e.preventDefault();
-						e.stopPropagation();
-						return;
-					}
-				}
-				ele = ele.parentNode;
-			}
-		}
-	}, true);
-}
-})( jQuery, window, document );
-
-
-(function( $, window, undefined ) {
-	var $document = $( document ),
-		supportTouch = $.mobile.support.touch,
-		scrollEvent = "touchmove scroll",
-		touchStartEvent = supportTouch ? "touchstart" : "mousedown",
-		touchStopEvent = supportTouch ? "touchend" : "mouseup",
-		touchMoveEvent = supportTouch ? "touchmove" : "mousemove";
-
-	// setup new event shortcuts
-	$.each( ( "touchstart touchmove touchend " +
-		"tap taphold " +
-		"swipe swipeleft swiperight " +
-		"scrollstart scrollstop" ).split( " " ), function( i, name ) {
-
-		$.fn[ name ] = function( fn ) {
-			return fn ? this.bind( name, fn ) : this.trigger( name );
-		};
-
-		// jQuery < 1.8
-		if ( $.attrFn ) {
-			$.attrFn[ name ] = true;
-		}
-	});
-
-	function triggerCustomEvent( obj, eventType, event, bubble ) {
-		var originalType = event.type;
-		event.type = eventType;
-		if ( bubble ) {
-			$.event.trigger( event, undefined, obj );
-		} else {
-			$.event.dispatch.call( obj, event );
-		}
-		event.type = originalType;
-	}
-
-	// also handles scrollstop
-	$.event.special.scrollstart = {
-
-		enabled: true,
-		setup: function() {
-
-			var thisObject = this,
-				$this = $( thisObject ),
-				scrolling,
-				timer;
-
-			function trigger( event, state ) {
-				scrolling = state;
-				triggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event );
-			}
-
-			// iPhone triggers scroll after a small delay; use touchmove instead
-			$this.bind( scrollEvent, function( event ) {
-
-				if ( !$.event.special.scrollstart.enabled ) {
-					return;
-				}
-
-				if ( !scrolling ) {
-					trigger( event, true );
-				}
-
-				clearTimeout( timer );
-				timer = setTimeout( function() {
-					trigger( event, false );
-				}, 50 );
-			});
-		},
-		teardown: function() {
-			$( this ).unbind( scrollEvent );
-		}
-	};
-
-	// also handles taphold
-	$.event.special.tap = {
-		tapholdThreshold: 750,
-		emitTapOnTaphold: true,
-		setup: function() {
-			var thisObject = this,
-				$this = $( thisObject ),
-				isTaphold = false;
-
-			$this.bind( "vmousedown", function( event ) {
-				isTaphold = false;
-				if ( event.which && event.which !== 1 ) {
-					return false;
-				}
-
-				var origTarget = event.target,
-					timer;
-
-				function clearTapTimer() {
-					clearTimeout( timer );
-				}
-
-				function clearTapHandlers() {
-					clearTapTimer();
-
-					$this.unbind( "vclick", clickHandler )
-						.unbind( "vmouseup", clearTapTimer );
-					$document.unbind( "vmousecancel", clearTapHandlers );
-				}
-
-				function clickHandler( event ) {
-					clearTapHandlers();
-
-					// ONLY trigger a 'tap' event if the start target is
-					// the same as the stop target.
-					if ( !isTaphold && origTarget === event.target ) {
-						triggerCustomEvent( thisObject, "tap", event );
-					} else if ( isTaphold ) {
-						event.stopPropagation();
-					}
-				}
-
-				$this.bind( "vmouseup", clearTapTimer )
-					.bind( "vclick", clickHandler );
-				$document.bind( "vmousecancel", clearTapHandlers );
-
-				timer = setTimeout( function() {
-					if ( !$.event.special.tap.emitTapOnTaphold ) {
-						isTaphold = true;
-					}
-					triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );
-				}, $.event.special.tap.tapholdThreshold );
-			});
-		},
-		teardown: function() {
-			$( this ).unbind( "vmousedown" ).unbind( "vclick" ).unbind( "vmouseup" );
-			$document.unbind( "vmousecancel" );
-		}
-	};
-
-	// Also handles swipeleft, swiperight
-	$.event.special.swipe = {
-
-		// More than this horizontal displacement, and we will suppress scrolling.
-		scrollSupressionThreshold: 30,
-
-		// More time than this, and it isn't a swipe.
-		durationThreshold: 1000,
-
-		// Swipe horizontal displacement must be more than this.
-		horizontalDistanceThreshold: 30,
-
-		// Swipe vertical displacement must be less than this.
-		verticalDistanceThreshold: 30,
-
-		getLocation: function ( event ) {
-			var winPageX = window.pageXOffset,
-				winPageY = window.pageYOffset,
-				x = event.clientX,
-				y = event.clientY;
-
-			if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) ||
-				event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) {
-
-				// iOS4 clientX/clientY have the value that should have been
-				// in pageX/pageY. While pageX/page/ have the value 0
-				x = x - winPageX;
-				y = y - winPageY;
-			} else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) {
-
-				// Some Android browsers have totally bogus values for clientX/Y
-				// when scrolling/zooming a page. Detectable since clientX/clientY
-				// should never be smaller than pageX/pageY minus page scroll
-				x = event.pageX - winPageX;
-				y = event.pageY - winPageY;
-			}
-
-			return {
-				x: x,
-				y: y
-			};
-		},
-
-		start: function( event ) {
-			var data = event.originalEvent.touches ?
-					event.originalEvent.touches[ 0 ] : event,
-				location = $.event.special.swipe.getLocation( data );
-			return {
-						time: ( new Date() ).getTime(),
-						coords: [ location.x, location.y ],
-						origin: $( event.target )
-					};
-		},
-
-		stop: function( event ) {
-			var data = event.originalEvent.touches ?
-					event.originalEvent.touches[ 0 ] : event,
-				location = $.event.special.swipe.getLocation( data );
-			return {
-						time: ( new Date() ).getTime(),
-						coords: [ location.x, location.y ]
-					};
-		},
-
-		handleSwipe: function( start, stop, thisObject, origTarget ) {
-			if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&
-				Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&
-				Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {
-				var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight";
-
-				triggerCustomEvent( thisObject, "swipe", $.Event( "swipe", { target: origTarget, swipestart: start, swipestop: stop }), true );
-				triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true );
-				return true;
-			}
-			return false;
-
-		},
-
-		// This serves as a flag to ensure that at most one swipe event event is
-		// in work at any given time
-		eventInProgress: false,
-
-		setup: function() {
-			var events,
-				thisObject = this,
-				$this = $( thisObject ),
-				context = {};
-
-			// Retrieve the events data for this element and add the swipe context
-			events = $.data( this, "mobile-events" );
-			if ( !events ) {
-				events = { length: 0 };
-				$.data( this, "mobile-events", events );
-			}
-			events.length++;
-			events.swipe = context;
-
-			context.start = function( event ) {
-
-				// Bail if we're already working on a swipe event
-				if ( $.event.special.swipe.eventInProgress ) {
-					return;
-				}
-				$.event.special.swipe.eventInProgress = true;
-
-				var stop,
-					start = $.event.special.swipe.start( event ),
-					origTarget = event.target,
-					emitted = false;
-
-				context.move = function( event ) {
-					if ( !start ) {
-						return;
-					}
-
-					stop = $.event.special.swipe.stop( event );
-					if ( !emitted ) {
-						emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget );
-						if ( emitted ) {
-
-							// Reset the context to make way for the next swipe event
-							$.event.special.swipe.eventInProgress = false;
-						}
-					}
-					// prevent scrolling
-					if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {
-						event.preventDefault();
-					}
-				};
-
-				context.stop = function() {
-						emitted = true;
-
-						// Reset the context to make way for the next swipe event
-						$.event.special.swipe.eventInProgress = false;
-						$document.off( touchMoveEvent, context.move );
-						context.move = null;
-				};
-
-				$document.on( touchMoveEvent, context.move )
-					.one( touchStopEvent, context.stop );
-			};
-			$this.on( touchStartEvent, context.start );
-		},
-
-		teardown: function() {
-			var events, context;
-
-			events = $.data( this, "mobile-events" );
-			if ( events ) {
-				context = events.swipe;
-				delete events.swipe;
-				events.length--;
-				if ( events.length === 0 ) {
-					$.removeData( this, "mobile-events" );
-				}
-			}
-
-			if ( context ) {
-				if ( context.start ) {
-					$( this ).off( touchStartEvent, context.start );
-				}
-				if ( context.move ) {
-					$document.off( touchMoveEvent, context.move );
-				}
-				if ( context.stop ) {
-					$document.off( touchStopEvent, context.stop );
-				}
-			}
-		}
-	};
-	$.each({
-		scrollstop: "scrollstart",
-		taphold: "tap",
-		swipeleft: "swipe",
-		swiperight: "swipe"
-	}, function( event, sourceEvent ) {
-
-		$.event.special[ event ] = {
-			setup: function() {
-				$( this ).bind( sourceEvent, $.noop );
-			},
-			teardown: function() {
-				$( this ).unbind( sourceEvent );
-			}
-		};
-	});
-
-})( jQuery, this );
-
-
-	// throttled resize event
-	(function( $ ) {
-		$.event.special.throttledresize = {
-			setup: function() {
-				$( this ).bind( "resize", handler );
-			},
-			teardown: function() {
-				$( this ).unbind( "resize", handler );
-			}
-		};
-
-		var throttle = 250,
-			handler = function() {
-				curr = ( new Date() ).getTime();
-				diff = curr - lastCall;
-
-				if ( diff >= throttle ) {
-
-					lastCall = curr;
-					$( this ).trigger( "throttledresize" );
-
-				} else {
-
-					if ( heldCall ) {
-						clearTimeout( heldCall );
-					}
-
-					// Promise a held call will still execute
-					heldCall = setTimeout( handler, throttle - diff );
-				}
-			},
-			lastCall = 0,
-			heldCall,
-			curr,
-			diff;
-	})( jQuery );
-
-
-(function( $, window ) {
-	var win = $( window ),
-		event_name = "orientationchange",
-		get_orientation,
-		last_orientation,
-		initial_orientation_is_landscape,
-		initial_orientation_is_default,
-		portrait_map = { "0": true, "180": true },
-		ww, wh, landscape_threshold;
-
-	// It seems that some device/browser vendors use window.orientation values 0 and 180 to
-	// denote the "default" orientation. For iOS devices, and most other smart-phones tested,
-	// the default orientation is always "portrait", but in some Android and RIM based tablets,
-	// the default orientation is "landscape". The following code attempts to use the window
-	// dimensions to figure out what the current orientation is, and then makes adjustments
-	// to the to the portrait_map if necessary, so that we can properly decode the
-	// window.orientation value whenever get_orientation() is called.
-	//
-	// Note that we used to use a media query to figure out what the orientation the browser
-	// thinks it is in:
-	//
-	//     initial_orientation_is_landscape = $.mobile.media("all and (orientation: landscape)");
-	//
-	// but there was an iPhone/iPod Touch bug beginning with iOS 4.2, up through iOS 5.1,
-	// where the browser *ALWAYS* applied the landscape media query. This bug does not
-	// happen on iPad.
-
-	if ( $.support.orientation ) {
-
-		// Check the window width and height to figure out what the current orientation
-		// of the device is at this moment. Note that we've initialized the portrait map
-		// values to 0 and 180, *AND* we purposely check for landscape so that if we guess
-		// wrong, , we default to the assumption that portrait is the default orientation.
-		// We use a threshold check below because on some platforms like iOS, the iPhone
-		// form-factor can report a larger width than height if the user turns on the
-		// developer console. The actual threshold value is somewhat arbitrary, we just
-		// need to make sure it is large enough to exclude the developer console case.
-
-		ww = window.innerWidth || win.width();
-		wh = window.innerHeight || win.height();
-		landscape_threshold = 50;
-
-		initial_orientation_is_landscape = ww > wh && ( ww - wh ) > landscape_threshold;
-
-		// Now check to see if the current window.orientation is 0 or 180.
-		initial_orientation_is_default = portrait_map[ window.orientation ];
-
-		// If the initial orientation is landscape, but window.orientation reports 0 or 180, *OR*
-		// if the initial orientation is portrait, but window.orientation reports 90 or -90, we
-		// need to flip our portrait_map values because landscape is the default orientation for
-		// this device/browser.
-		if ( ( initial_orientation_is_landscape && initial_orientation_is_default ) || ( !initial_orientation_is_landscape && !initial_orientation_is_default ) ) {
-			portrait_map = { "-90": true, "90": true };
-		}
-	}
-
-	$.event.special.orientationchange = $.extend( {}, $.event.special.orientationchange, {
-		setup: function() {
-			// If the event is supported natively, return false so that jQuery
-			// will bind to the event using DOM methods.
-			if ( $.support.orientation && !$.event.special.orientationchange.disabled ) {
-				return false;
-			}
-
-			// Get the current orientation to avoid initial double-triggering.
-			last_orientation = get_orientation();
-
-			// Because the orientationchange event doesn't exist, simulate the
-			// event by testing window dimensions on resize.
-			win.bind( "throttledresize", handler );
-		},
-		teardown: function() {
-			// If the event is not supported natively, return false so that
-			// jQuery will unbind the event using DOM methods.
-			if ( $.support.orientation && !$.event.special.orientationchange.disabled ) {
-				return false;
-			}
-
-			// Because the orientationchange event doesn't exist, unbind the
-			// resize event handler.
-			win.unbind( "throttledresize", handler );
-		},
-		add: function( handleObj ) {
-			// Save a reference to the bound event handler.
-			var old_handler = handleObj.handler;
-
-			handleObj.handler = function( event ) {
-				// Modify event object, adding the .orientation property.
-				event.orientation = get_orientation();
-
-				// Call the originally-bound event handler and return its result.
-				return old_handler.apply( this, arguments );
-			};
-		}
-	});
-
-	// If the event is not supported natively, this handler will be bound to
-	// the window resize event to simulate the orientationchange event.
-	function handler() {
-		// Get the current orientation.
-		var orientation = get_orientation();
-
-		if ( orientation !== last_orientation ) {
-			// The orientation has changed, so trigger the orientationchange event.
-			last_orientation = orientation;
-			win.trigger( event_name );
-		}
-	}
-
-	// Get the current page orientation. This method is exposed publicly, should it
-	// be needed, as jQuery.event.special.orientationchange.orientation()
-	$.event.special.orientationchange.orientation = get_orientation = function() {
-		var isPortrait = true, elem = document.documentElement;
-
-		// prefer window orientation to the calculation based on screensize as
-		// the actual screen resize takes place before or after the orientation change event
-		// has been fired depending on implementation (eg android 2.3 is before, iphone after).
-		// More testing is required to determine if a more reliable method of determining the new screensize
-		// is possible when orientationchange is fired. (eg, use media queries + element + opacity)
-		if ( $.support.orientation ) {
-			// if the window orientation registers as 0 or 180 degrees report
-			// portrait, otherwise landscape
-			isPortrait = portrait_map[ window.orientation ];
-		} else {
-			isPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1;
-		}
-
-		return isPortrait ? "portrait" : "landscape";
-	};
-
-	$.fn[ event_name ] = function( fn ) {
-		return fn ? this.bind( event_name, fn ) : this.trigger( event_name );
-	};
-
-	// jQuery < 1.8
-	if ( $.attrFn ) {
-		$.attrFn[ event_name ] = true;
-	}
-
-}( jQuery, this ));
-
-
-
-
-(function( $, undefined ) {
-
-	// existing base tag?
-	var baseElement = $( "head" ).children( "base" ),
-
-	// base element management, defined depending on dynamic base tag support
-	// TODO move to external widget
-	base = {
-
-		// define base element, for use in routing asset urls that are referenced
-		// in Ajax-requested markup
-		element: ( baseElement.length ? baseElement :
-			$( "<base>", { href: $.mobile.path.documentBase.hrefNoHash } ).prependTo( $( "head" ) ) ),
-
-		linkSelector: "[src], link[href], a[rel='external'], :jqmData(ajax='false'), a[target]",
-
-		// set the generated BASE element's href to a new page's base path
-		set: function( href ) {
-
-			// we should do nothing if the user wants to manage their url base
-			// manually
-			if ( !$.mobile.dynamicBaseEnabled ) {
-				return;
-			}
-
-			// we should use the base tag if we can manipulate it dynamically
-			if ( $.support.dynamicBaseTag ) {
-				base.element.attr( "href",
-					$.mobile.path.makeUrlAbsolute( href, $.mobile.path.documentBase ) );
-			}
-		},
-
-		rewrite: function( href, page ) {
-			var newPath = $.mobile.path.get( href );
-
-			page.find( base.linkSelector ).each(function( i, link ) {
-				var thisAttr = $( link ).is( "[href]" ) ? "href" :
-					$( link ).is( "[src]" ) ? "src" : "action",
-				thisUrl = $( link ).attr( thisAttr );
-
-				// XXX_jblas: We need to fix this so that it removes the document
-				//            base URL, and then prepends with the new page URL.
-				// if full path exists and is same, chop it - helps IE out
-				thisUrl = thisUrl.replace( location.protocol + "//" +
-					location.host + location.pathname, "" );
-
-				if ( !/^(\w+:|#|\/)/.test( thisUrl ) ) {
-					$( link ).attr( thisAttr, newPath + thisUrl );
-				}
-			});
-		},
-
-		// set the generated BASE element's href to a new page's base path
-		reset: function(/* href */) {
-			base.element.attr( "href", $.mobile.path.documentBase.hrefNoSearch );
-		}
-	};
-
-	$.mobile.base = base;
-
-})( jQuery );
-
-
-(function( $, undefined ) {
-$.mobile.widgets = {};
-
-var originalWidget = $.widget,
-
-	// Record the original, non-mobileinit-modified version of $.mobile.keepNative
-	// so we can later determine whether someone has modified $.mobile.keepNative
-	keepNativeFactoryDefault = $.mobile.keepNative;
-
-$.widget = (function( orig ) {
-	return function() {
-		var constructor = orig.apply( this, arguments ),
-			name = constructor.prototype.widgetName;
-
-		constructor.initSelector = ( ( constructor.prototype.initSelector !== undefined ) ?
-			constructor.prototype.initSelector : ":jqmData(role='" + name + "')" );
-
-		$.mobile.widgets[ name ] = constructor;
-
-		return constructor;
-	};
-})( $.widget );
-
-// Make sure $.widget still has bridge and extend methods
-$.extend( $.widget, originalWidget );
-
-// For backcompat remove in 1.5
-$.mobile.document.on( "create", function( event ) {
-	$( event.target ).enhanceWithin();
-});
-
-$.widget( "mobile.page", {
-	options: {
-		theme: "a",
-		domCache: false,
-
-		// Deprecated in 1.4 remove in 1.5
-		keepNativeDefault: $.mobile.keepNative,
-
-		// Deprecated in 1.4 remove in 1.5
-		contentTheme: null,
-		enhanced: false
-	},
-
-	// DEPRECATED for > 1.4
-	// TODO remove at 1.5
-	_createWidget: function() {
-		$.Widget.prototype._createWidget.apply( this, arguments );
-		this._trigger( "init" );
-	},
-
-	_create: function() {
-		// If false is returned by the callbacks do not create the page
-		if ( this._trigger( "beforecreate" ) === false ) {
-			return false;
-		}
-
-		if ( !this.options.enhanced ) {
-			this._enhance();
-		}
-
-		this._on( this.element, {
-			pagebeforehide: "removeContainerBackground",
-			pagebeforeshow: "_handlePageBeforeShow"
-		});
-
-		this.element.enhanceWithin();
-		// Dialog widget is deprecated in 1.4 remove this in 1.5
-		if ( $.mobile.getAttribute( this.element[0], "role" ) === "dialog" && $.mobile.dialog ) {
-			this.element.dialog();
-		}
-	},
-
-	_enhance: function () {
-		var attrPrefix = "data-" + $.mobile.ns,
-			self = this;
-
-		if ( this.options.role ) {
-			this.element.attr( "data-" + $.mobile.ns + "role", this.options.role );
-		}
-
-		this.element
-			.attr( "tabindex", "0" )
-			.addClass( "ui-page ui-page-theme-" + this.options.theme );
-
-		// Manipulation of content os Deprecated as of 1.4 remove in 1.5
-		this.element.find( "[" + attrPrefix + "role='content']" ).each( function() {
-			var $this = $( this ),
-				theme = this.getAttribute( attrPrefix + "theme" ) || undefined;
-				self.options.contentTheme = theme || self.options.contentTheme || ( self.options.dialog && self.options.theme ) || ( self.element.jqmData("role") === "dialog" &&  self.options.theme );
-				$this.addClass( "ui-content" );
-				if ( self.options.contentTheme ) {
-					$this.addClass( "ui-body-" + ( self.options.contentTheme ) );
-				}
-				// Add ARIA role
-				$this.attr( "role", "main" ).addClass( "ui-content" );
-		});
-	},
-
-	bindRemove: function( callback ) {
-		var page = this.element;
-
-		// when dom caching is not enabled or the page is embedded bind to remove the page on hide
-		if ( !page.data( "mobile-page" ).options.domCache &&
-			page.is( ":jqmData(external-page='true')" ) ) {
-
-			// TODO use _on - that is, sort out why it doesn't work in this case
-			page.bind( "pagehide.remove", callback || function( e, data ) {
-
-				//check if this is a same page transition and if so don't remove the page
-				if( !data.samePage ){
-					var $this = $( this ),
-						prEvent = new $.Event( "pageremove" );
-
-					$this.trigger( prEvent );
-
-					if ( !prEvent.isDefaultPrevented() ) {
-						$this.removeWithDependents();
-					}
-				}
-			});
-		}
-	},
-
-	_setOptions: function( o ) {
-		if ( o.theme !== undefined ) {
-			this.element.removeClass( "ui-page-theme-" + this.options.theme ).addClass( "ui-page-theme-" + o.theme );
-		}
-
-		if ( o.contentTheme !== undefined ) {
-			this.element.find( "[data-" + $.mobile.ns + "='content']" ).removeClass( "ui-body-" + this.options.contentTheme )
-				.addClass( "ui-body-" + o.contentTheme );
-		}
-	},
-
-	_handlePageBeforeShow: function(/* e */) {
-		this.setContainerBackground();
-	},
-	// Deprecated in 1.4 remove in 1.5
-	removeContainerBackground: function() {
-		this.element.closest( ":mobile-pagecontainer" ).pagecontainer({ "theme": "none" });
-	},
-	// Deprecated in 1.4 remove in 1.5
-	// set the page container background to the page theme
-	setContainerBackground: function( theme ) {
-		this.element.parent().pagecontainer( { "theme": theme || this.options.theme } );
-	},
-	// Deprecated in 1.4 remove in 1.5
-	keepNativeSelector: function() {
-		var options = this.options,
-			keepNative = $.trim( options.keepNative || "" ),
-			globalValue = $.trim( $.mobile.keepNative ),
-			optionValue = $.trim( options.keepNativeDefault ),
-
-			// Check if $.mobile.keepNative has changed from the factory default
-			newDefault = ( keepNativeFactoryDefault === globalValue ?
-				"" : globalValue ),
-
-			// If $.mobile.keepNative has not changed, use options.keepNativeDefault
-			oldDefault = ( newDefault === "" ? optionValue : "" );
-
-		// Concatenate keepNative selectors from all sources where the value has
-		// changed or, if nothing has changed, return the default
-		return ( ( keepNative ? [ keepNative ] : [] )
-			.concat( newDefault ? [ newDefault ] : [] )
-			.concat( oldDefault ? [ oldDefault ] : [] )
-			.join( ", " ) );
-	}
-});
-})( jQuery );
-
-(function( $, undefined ) {
-
-	$.widget( "mobile.pagecontainer", {
-		options: {
-			theme: "a"
-		},
-
-		initSelector: false,
-
-		_create: function() {
-			this.setLastScrollEnabled = true;
-
-			this._on( this.window, {
-				// disable an scroll setting when a hashchange has been fired,
-				// this only works because the recording of the scroll position
-				// is delayed for 100ms after the browser might have changed the
-				// position because of the hashchange
-				navigate: "_disableRecordScroll",
-
-				// bind to scrollstop for the first page, "pagechange" won't be
-				// fired in that case
-				scrollstop: "_delayedRecordScroll"
-			});
-
-			// TODO consider moving the navigation handler OUT of widget into
-			//      some other object as glue between the navigate event and the
-			//      content widget load and change methods
-			this._on( this.window, { navigate: "_filterNavigateEvents" });
-
-			// TODO move from page* events to content* events
-			this._on({ pagechange: "_afterContentChange" });
-
-			// handle initial hashchange from chrome :(
-			this.window.one( "navigate", $.proxy(function() {
-				this.setLastScrollEnabled = true;
-			}, this));
-		},
-
-		_setOptions: function( options ) {
-			if ( options.theme !== undefined && options.theme !== "none" ) {
-				this.element.removeClass( "ui-overlay-" + this.options.theme )
-					.addClass( "ui-overlay-" + options.theme );
-			} else if ( options.theme !== undefined ) {
-				this.element.removeClass( "ui-overlay-" + this.options.theme );
-			}
-
-			this._super( options );
-		},
-
-		_disableRecordScroll: function() {
-			this.setLastScrollEnabled = false;
-		},
-
-		_enableRecordScroll: function() {
-			this.setLastScrollEnabled = true;
-		},
-
-		// TODO consider the name here, since it's purpose specific
-		_afterContentChange: function() {
-			// once the page has changed, re-enable the scroll recording
-			this.setLastScrollEnabled = true;
-
-			// remove any binding that previously existed on the get scroll
-			// which may or may not be different than the scroll element
-			// determined for this page previously
-			this._off( this.window, "scrollstop" );
-
-			// determine and bind to the current scoll element which may be the
-			// window or in the case of touch overflow the element touch overflow
-			this._on( this.window, { scrollstop: "_delayedRecordScroll" });
-		},
-
-		_recordScroll: function() {
-			// this barrier prevents setting the scroll value based on
-			// the browser scrolling the window based on a hashchange
-			if ( !this.setLastScrollEnabled ) {
-				return;
-			}
-
-			var active = this._getActiveHistory(),
-				currentScroll, minScroll, defaultScroll;
-
-			if ( active ) {
-				currentScroll = this._getScroll();
-				minScroll = this._getMinScroll();
-				defaultScroll = this._getDefaultScroll();
-
-				// Set active page's lastScroll prop. If the location we're
-				// scrolling to is less than minScrollBack, let it go.
-				active.lastScroll = currentScroll < minScroll ? defaultScroll : currentScroll;
-			}
-		},
-
-		_delayedRecordScroll: function() {
-			setTimeout( $.proxy(this, "_recordScroll"), 100 );
-		},
-
-		_getScroll: function() {
-			return this.window.scrollTop();
-		},
-
-		_getMinScroll: function() {
-			return $.mobile.minScrollBack;
-		},
-
-		_getDefaultScroll: function() {
-			return $.mobile.defaultHomeScroll;
-		},
-
-		_filterNavigateEvents: function( e, data ) {
-			var url;
-
-			if ( e.originalEvent && e.originalEvent.isDefaultPrevented() ) {
-				return;
-			}
-
-			url = e.originalEvent.type.indexOf( "hashchange" ) > -1 ? data.state.hash : data.state.url;
-
-			if ( !url ) {
-				url = this._getHash();
-			}
-
-			if ( !url || url === "#" || url.indexOf( "#" + $.mobile.path.uiStateKey ) === 0 ) {
-				url = location.href;
-			}
-
-			this._handleNavigate( url, data.state );
-		},
-
-		_getHash: function() {
-			return $.mobile.path.parseLocation().hash;
-		},
-
-		// TODO active page should be managed by the container (ie, it should be a property)
-		getActivePage: function() {
-			return this.activePage;
-		},
-
-		// TODO the first page should be a property set during _create using the logic
-		//      that currently resides in init
-		_getInitialContent: function() {
-			return $.mobile.firstPage;
-		},
-
-		// TODO each content container should have a history object
-		_getHistory: function() {
-			return $.mobile.navigate.history;
-		},
-
-		// TODO use _getHistory
-		_getActiveHistory: function() {
-			return $.mobile.navigate.history.getActive();
-		},
-
-		// TODO the document base should be determined at creation
-		_getDocumentBase: function() {
-			return $.mobile.path.documentBase;
-		},
-
-		back: function() {
-			this.go( -1 );
-		},
-
-		forward: function() {
-			this.go( 1 );
-		},
-
-		go: function( steps ) {
-
-			//if hashlistening is enabled use native history method
-			if ( $.mobile.hashListeningEnabled ) {
-				window.history.go( steps );
-			} else {
-
-				//we are not listening to the hash so handle history internally
-				var activeIndex = $.mobile.navigate.history.activeIndex,
-					index = activeIndex + parseInt( steps, 10 ),
-					url = $.mobile.navigate.history.stack[ index ].url,
-					direction = ( steps >= 1 )? "forward" : "back";
-
-				//update the history object
-				$.mobile.navigate.history.activeIndex = index;
-				$.mobile.navigate.history.previousIndex = activeIndex;
-
-				//change to the new page
-				this.change( url, { direction: direction, changeHash: false, fromHashChange: true } );
-			}
-		},
-
-		// TODO rename _handleDestination
-		_handleDestination: function( to ) {
-			var history;
-
-			// clean the hash for comparison if it's a url
-			if ( $.type(to) === "string" ) {
-				to = $.mobile.path.stripHash( to );
-			}
-
-			if ( to ) {
-				history = this._getHistory();
-
-				// At this point, 'to' can be one of 3 things, a cached page
-				// element from a history stack entry, an id, or site-relative /
-				// absolute URL. If 'to' is an id, we need to resolve it against
-				// the documentBase, not the location.href, since the hashchange
-				// could've been the result of a forward/backward navigation
-				// that crosses from an external page/dialog to an internal
-				// page/dialog.
-				//
-				// TODO move check to history object or path object?
-				to = !$.mobile.path.isPath( to ) ? ( $.mobile.path.makeUrlAbsolute( "#" + to, this._getDocumentBase() ) ) : to;
-
-				// If we're about to go to an initial URL that contains a
-				// reference to a non-existent internal page, go to the first
-				// page instead. We know that the initial hash refers to a
-				// non-existent page, because the initial hash did not end
-				// up in the initial history entry
-				// TODO move check to history object?
-				if ( to === $.mobile.path.makeUrlAbsolute( "#" + history.initialDst, this._getDocumentBase() ) &&
-					history.stack.length &&
-					history.stack[0].url !== history.initialDst.replace( $.mobile.dialogHashKey, "" ) ) {
-					to = this._getInitialContent();
-				}
-			}
-			return to || this._getInitialContent();
-		},
-
-		_handleDialog: function( changePageOptions, data ) {
-			var to, active, activeContent = this.getActivePage();
-
-			// If current active page is not a dialog skip the dialog and continue
-			// in the same direction
-			if ( activeContent && !activeContent.hasClass( "ui-dialog" ) ) {
-				// determine if we're heading forward or backward and continue
-				// accordingly past the current dialog
-				if ( data.direction === "back" ) {
-					this.back();
-				} else {
-					this.forward();
-				}
-
-				// prevent changePage call
-				return false;
-			} else {
-				// if the current active page is a dialog and we're navigating
-				// to a dialog use the dialog objected saved in the stack
-				to = data.pageUrl;
-				active = this._getActiveHistory();
-
-				// make sure to set the role, transition and reversal
-				// as most of this is lost by the domCache cleaning
-				$.extend( changePageOptions, {
-					role: active.role,
-					transition: active.transition,
-					reverse: data.direction === "back"
-				});
-			}
-
-			return to;
-		},
-
-		_handleNavigate: function( url, data ) {
-			//find first page via hash
-			// TODO stripping the hash twice with handleUrl
-			var to = $.mobile.path.stripHash( url ), history = this._getHistory(),
-
-				// transition is false if it's the first page, undefined
-				// otherwise (and may be overridden by default)
-				transition = history.stack.length === 0 ? "none" : undefined,
-
-				// default options for the changPage calls made after examining
-				// the current state of the page and the hash, NOTE that the
-				// transition is derived from the previous history entry
-				changePageOptions = {
-					changeHash: false,
-					fromHashChange: true,
-					reverse: data.direction === "back"
-				};
-
-			$.extend( changePageOptions, data, {
-				transition: ( history.getLast() || {} ).transition || transition
-			});
-
-			// TODO move to _handleDestination ?
-			// If this isn't the first page, if the current url is a dialog hash
-			// key, and the initial destination isn't equal to the current target
-			// page, use the special dialog handling
-			if ( history.activeIndex > 0 &&
-				to.indexOf( $.mobile.dialogHashKey ) > -1 &&
-				history.initialDst !== to ) {
-
-				to = this._handleDialog( changePageOptions, data );
-
-				if ( to === false ) {
-					return;
-				}
-			}
-
-			this._changeContent( this._handleDestination( to ), changePageOptions );
-		},
-
-		_changeContent: function( to, opts ) {
-			$.mobile.changePage( to, opts );
-		},
-
-		_getBase: function() {
-			return $.mobile.base;
-		},
-
-		_getNs: function() {
-			return $.mobile.ns;
-		},
-
-		_enhance: function( content, role ) {
-			// TODO consider supporting a custom callback, and passing in
-			// the settings which includes the role
-			return content.page({ role: role });
-		},
-
-		_include: function( page, settings ) {
-			// append to page and enhance
-			page.appendTo( this.element );
-
-			// use the page widget to enhance
-			this._enhance( page, settings.role );
-
-			// remove page on hide
-			page.page( "bindRemove" );
-		},
-
-		_find: function( absUrl ) {
-			// TODO consider supporting a custom callback
-			var fileUrl = this._createFileUrl( absUrl ),
-				dataUrl = this._createDataUrl( absUrl ),
-				page, initialContent = this._getInitialContent();
-
-			// Check to see if the page already exists in the DOM.
-			// NOTE do _not_ use the :jqmData pseudo selector because parenthesis
-			//      are a valid url char and it breaks on the first occurence
-			page = this.element
-				.children( "[data-" + this._getNs() +"url='" + dataUrl + "']" );
-
-			// If we failed to find the page, check to see if the url is a
-			// reference to an embedded page. If so, it may have been dynamically
-			// injected by a developer, in which case it would be lacking a
-			// data-url attribute and in need of enhancement.
-			if ( page.length === 0 && dataUrl && !$.mobile.path.isPath( dataUrl ) ) {
-				page = this.element.children( $.mobile.path.hashToSelector("#" + dataUrl) )
-					.attr( "data-" + this._getNs() + "url", dataUrl )
-					.jqmData( "url", dataUrl );
-			}
-
-			// If we failed to find a page in the DOM, check the URL to see if it
-			// refers to the first page in the application. Also check to make sure
-			// our cached-first-page is actually in the DOM. Some user deployed
-			// apps are pruning the first page from the DOM for various reasons.
-			// We check for this case here because we don't want a first-page with
-			// an id falling through to the non-existent embedded page error case.
-			if ( page.length === 0 &&
-				$.mobile.path.isFirstPageUrl( fileUrl ) &&
-				initialContent &&
-				initialContent.parent().length ) {
-				page = $( initialContent );
-			}
-
-			return page;
-		},
-
-		_getLoader: function() {
-			return $.mobile.loading();
-		},
-
-		_showLoading: function( delay, theme, msg, textonly ) {
-			// This configurable timeout allows cached pages a brief
-			// delay to load without showing a message
-			if ( this._loadMsg ) {
-				return;
-			}
-
-			this._loadMsg = setTimeout($.proxy(function() {
-				this._getLoader().loader( "show", theme, msg, textonly );
-				this._loadMsg = 0;
-			}, this), delay );
-		},
-
-		_hideLoading: function() {
-			// Stop message show timer
-			clearTimeout( this._loadMsg );
-			this._loadMsg = 0;
-
-			// Hide loading message
-			this._getLoader().loader( "hide" );
-		},
-
-		_showError: function() {
-			// make sure to remove the current loading message
-			this._hideLoading();
-
-			// show the error message
-			this._showLoading( 0, $.mobile.pageLoadErrorMessageTheme, $.mobile.pageLoadErrorMessage, true );
-
-			// hide the error message after a delay
-			// TODO configuration
-			setTimeout( $.proxy(this, "_hideLoading"), 1500 );
-		},
-
-		_parse: function( html, fileUrl ) {
-			// TODO consider allowing customization of this method. It's very JQM specific
-			var page, all = $( "<div></div>" );
-
-			//workaround to allow scripts to execute when included in page divs
-			all.get( 0 ).innerHTML = html;
-
-			page = all.find( ":jqmData(role='page'), :jqmData(role='dialog')" ).first();
-
-			//if page elem couldn't be found, create one and insert the body element's contents
-			if ( !page.length ) {
-				page = $( "<div data-" + this._getNs() + "role='page'>" +
-					( html.split( /<\/?body[^>]*>/gmi )[1] || "" ) +
-					"</div>" );
-			}
-
-			// TODO tagging a page with external to make sure that embedded pages aren't
-			// removed by the various page handling code is bad. Having page handling code
-			// in many places is bad. Solutions post 1.0
-			page.attr( "data-" + this._getNs() + "url", $.mobile.path.convertUrlToDataUrl(fileUrl) )
-				.attr( "data-" + this._getNs() + "external-page", true );
-
-			return page;
-		},
-
-		_setLoadedTitle: function( page, html ) {
-			//page title regexp
-			var newPageTitle = html.match( /<title[^>]*>([^<]*)/ ) && RegExp.$1;
-
-			if ( newPageTitle && !page.jqmData("title") ) {
-				newPageTitle = $( "<div>" + newPageTitle + "</div>" ).text();
-				page.jqmData( "title", newPageTitle );
-			}
-		},
-
-		_isRewritableBaseTag: function() {
-			return $.mobile.dynamicBaseEnabled && !$.support.dynamicBaseTag;
-		},
-
-		_createDataUrl: function( absoluteUrl ) {
-			return $.mobile.path.convertUrlToDataUrl( absoluteUrl );
-		},
-
-		_createFileUrl: function( absoluteUrl ) {
-			return $.mobile.path.getFilePath( absoluteUrl );
-		},
-
-		_triggerWithDeprecated: function( name, data, page ) {
-			var deprecatedEvent = $.Event( "page" + name ),
-				newEvent = $.Event( this.widgetName + name );
-
-			// DEPRECATED
-			// trigger the old deprecated event on the page if it's provided
-			( page || this.element ).trigger( deprecatedEvent, data );
-
-			// use the widget trigger method for the new content* event
-			this.element.trigger( newEvent, data );
-
-			return {
-				deprecatedEvent: deprecatedEvent,
-				event: newEvent
-			};
-		},
-
-		// TODO it would be nice to split this up more but everything appears to be "one off"
-		//      or require ordering such that other bits are sprinkled in between parts that
-		//      could be abstracted out as a group
-		_loadSuccess: function( absUrl, triggerData, settings, deferred ) {
-			var fileUrl = this._createFileUrl( absUrl ),
-				dataUrl = this._createDataUrl( absUrl );
-
-			return $.proxy(function( html, textStatus, xhr ) {
-				//pre-parse html to check for a data-url,
-				//use it as the new fileUrl, base path, etc
-				var content,
-
-					// TODO handle dialogs again
-					pageElemRegex = new RegExp( "(<[^>]+\\bdata-" + this._getNs() + "role=[\"']?page[\"']?[^>]*>)" ),
-
-					dataUrlRegex = new RegExp( "\\bdata-" + this._getNs() + "url=[\"']?([^\"'>]*)[\"']?" );
-
-				// data-url must be provided for the base tag so resource requests
-				// can be directed to the correct url. loading into a temprorary
-				// element makes these requests immediately
-				if ( pageElemRegex.test( html ) &&
-					RegExp.$1 &&
-					dataUrlRegex.test( RegExp.$1 ) &&
-					RegExp.$1 ) {
-					fileUrl = $.mobile.path.getFilePath( $("<div>" + RegExp.$1 + "</div>").text() );
-				}
-
-				//dont update the base tag if we are prefetching
-				if ( settings.prefetch === undefined ) {
-					this._getBase().set( fileUrl );
-				}
-
-				content = this._parse( html, fileUrl );
-
-				this._setLoadedTitle( content, html );
-
-				// Add the content reference and xhr to our triggerData.
-				triggerData.xhr = xhr;
-				triggerData.textStatus = textStatus;
-
-				// DEPRECATED
-				triggerData.page = content;
-
-				triggerData.content = content;
-
-				// If the default behavior is prevented, stop here!
-				// Note that it is the responsibility of the listener/handler
-				// that called preventDefault(), to resolve/reject the
-				// deferred object within the triggerData.
-				if ( !this._trigger( "load", undefined, triggerData ) ) {
-					return;
-				}
-
-				// rewrite src and href attrs to use a base url if the base tag won't work
-				if ( this._isRewritableBaseTag() && content ) {
-					this._getBase().rewrite( fileUrl, content );
-				}
-
-				this._include( content, settings );
-
-				// Enhancing the content may result in new dialogs/sub content being inserted
-				// into the DOM. If the original absUrl refers to a sub-content, that is the
-				// real content we are interested in.
-				if ( absUrl.indexOf( "&" + $.mobile.subPageUrlKey ) > -1 ) {
-					content = this.element.children( "[data-" + this._getNs() +"url='" + dataUrl + "']" );
-				}
-
-				// Remove loading message.
-				if ( settings.showLoadMsg ) {
-					this._hideLoading();
-				}
-
-				// BEGIN DEPRECATED ---------------------------------------------------
-				// Let listeners know the content loaded successfully.
-				this.element.trigger( "pageload" );
-				// END DEPRECATED -----------------------------------------------------
-
-				deferred.resolve( absUrl, settings, content );
-			}, this);
-		},
-
-		_loadDefaults: {
-			type: "get",
-			data: undefined,
-
-			// DEPRECATED
-			reloadPage: false,
-
-			reload: false,
-
-			// By default we rely on the role defined by the @data-role attribute.
-			role: undefined,
-
-			showLoadMsg: false,
-
-			// This delay allows loads that pull from browser cache to
-			// occur without showing the loading message.
-			loadMsgDelay: 50
-		},
-
-		load: function( url, options ) {
-			// This function uses deferred notifications to let callers
-			// know when the content is done loading, or if an error has occurred.
-			var deferred = ( options && options.deferred ) || $.Deferred(),
-
-				// The default load options with overrides specified by the caller.
-				settings = $.extend( {}, this._loadDefaults, options ),
-
-				// The DOM element for the content after it has been loaded.
-				content = null,
-
-				// The absolute version of the URL passed into the function. This
-				// version of the URL may contain dialog/subcontent params in it.
-				absUrl = $.mobile.path.makeUrlAbsolute( url, this._findBaseWithDefault() ),
-				fileUrl, dataUrl, pblEvent, triggerData;
-
-			// DEPRECATED reloadPage
-			settings.reload = settings.reloadPage;
-
-			// If the caller provided data, and we're using "get" request,
-			// append the data to the URL.
-			if ( settings.data && settings.type === "get" ) {
-				absUrl = $.mobile.path.addSearchParams( absUrl, settings.data );
-				settings.data = undefined;
-			}
-
-			// If the caller is using a "post" request, reload must be true
-			if ( settings.data && settings.type === "post" ) {
-				settings.reload = true;
-			}
-
-			// The absolute version of the URL minus any dialog/subcontent params.
-			// In otherwords the real URL of the content to be loaded.
-			fileUrl = this._createFileUrl( absUrl );
-
-			// The version of the Url actually stored in the data-url attribute of
-			// the content. For embedded content, it is just the id of the page. For
-			// content within the same domain as the document base, it is the site
-			// relative path. For cross-domain content (Phone Gap only) the entire
-			// absolute Url is used to load the content.
-			dataUrl = this._createDataUrl( absUrl );
-
-			content = this._find( absUrl );
-
-			// If it isn't a reference to the first content and refers to missing
-			// embedded content reject the deferred and return
-			if ( content.length === 0 &&
-				$.mobile.path.isEmbeddedPage(fileUrl) &&
-				!$.mobile.path.isFirstPageUrl(fileUrl) ) {
-				deferred.reject( absUrl, settings );
-				return;
-			}
-
-			// Reset base to the default document base
-			// TODO figure out why we doe this
-			this._getBase().reset();
-
-			// If the content we are interested in is already in the DOM,
-			// and the caller did not indicate that we should force a
-			// reload of the file, we are done. Resolve the deferrred so that
-			// users can bind to .done on the promise
-			if ( content.length && !settings.reload ) {
-				this._enhance( content, settings.role );
-				deferred.resolve( absUrl, settings, content );
-
-				//if we are reloading the content make sure we update
-				// the base if its not a prefetch
-				if ( !settings.prefetch ) {
-					this._getBase().set(url);
-				}
-
-				return;
-			}
-
-			triggerData = {
-				url: url,
-				absUrl: absUrl,
-				dataUrl: dataUrl,
-				deferred: deferred,
-				options: settings
-			};
-
-			// Let listeners know we're about to load content.
-			pblEvent = this._triggerWithDeprecated( "beforeload", triggerData );
-
-			// If the default behavior is prevented, stop here!
-			if ( pblEvent.deprecatedEvent.isDefaultPrevented() ||
-				pblEvent.event.isDefaultPrevented() ) {
-				return;
-			}
-
-			if ( settings.showLoadMsg ) {
-				this._showLoading( settings.loadMsgDelay );
-			}
-
-			// Reset base to the default document base.
-			// only reset if we are not prefetching
-			if ( settings.prefetch === undefined ) {
-				this._getBase().reset();
-			}
-
-			if ( !( $.mobile.allowCrossDomainPages ||
-				$.mobile.path.isSameDomain($.mobile.path.documentUrl, absUrl ) ) ) {
-				deferred.reject( absUrl, settings );
-				return;
-			}
-
-			// Load the new content.
-			$.ajax({
-				url: fileUrl,
-				type: settings.type,
-				data: settings.data,
-				contentType: settings.contentType,
-				dataType: "html",
-				success: this._loadSuccess( absUrl, triggerData, settings, deferred ),
-				error: this._loadError( absUrl, triggerData, settings, deferred )
-			});
-		},
-
-		_loadError: function( absUrl, triggerData, settings, deferred ) {
-			return $.proxy(function( xhr, textStatus, errorThrown ) {
-				//set base back to current path
-				this._getBase().set( $.mobile.path.get() );
-
-				// Add error info to our triggerData.
-				triggerData.xhr = xhr;
-				triggerData.textStatus = textStatus;
-				triggerData.errorThrown = errorThrown;
-
-				// Let listeners know the page load failed.
-				var plfEvent = this._triggerWithDeprecated( "loadfailed", triggerData );
-
-				// If the default behavior is prevented, stop here!
-				// Note that it is the responsibility of the listener/handler
-				// that called preventDefault(), to resolve/reject the
-				// deferred object within the triggerData.
-				if ( plfEvent.deprecatedEvent.isDefaultPrevented() ||
-					plfEvent.event.isDefaultPrevented() ) {
-					return;
-				}
-
-				// Remove loading message.
-				if ( settings.showLoadMsg ) {
-					this._showError();
-				}
-
-				deferred.reject( absUrl, settings );
-			}, this);
-		},
-
-		_getTransitionHandler: function( transition ) {
-			transition = $.mobile._maybeDegradeTransition( transition );
-
-			//find the transition handler for the specified transition. If there
-			//isn't one in our transitionHandlers dictionary, use the default one.
-			//call the handler immediately to kick-off the transition.
-			return $.mobile.transitionHandlers[ transition ] || $.mobile.defaultTransitionHandler;
-		},
-
-		// TODO move into transition handlers?
-		_triggerCssTransitionEvents: function( to, from, prefix ) {
-			var samePage = false;
-
-			prefix = prefix || "";
-
-			// TODO decide if these events should in fact be triggered on the container
-			if ( from ) {
-
-				//Check if this is a same page transition and tell the handler in page
-				if( to[0] === from[0] ){
-					samePage = true;
-				}
-
-				//trigger before show/hide events
-				// TODO deprecate nextPage in favor of next
-				this._triggerWithDeprecated( prefix + "hide", { nextPage: to, samePage: samePage }, from );
-			}
-
-			// TODO deprecate prevPage in favor of previous
-			this._triggerWithDeprecated( prefix + "show", { prevPage: from || $( "" ) }, to );
-		},
-
-		// TODO make private once change has been defined in the widget
-		_cssTransition: function( to, from, options ) {
-			var transition = options.transition,
-				reverse = options.reverse,
-				deferred = options.deferred,
-				TransitionHandler,
-				promise;
-
-			this._triggerCssTransitionEvents( to, from, "before" );
-
-			// TODO put this in a binding to events *outside* the widget
-			this._hideLoading();
-
-			TransitionHandler = this._getTransitionHandler( transition );
-
-			promise = ( new TransitionHandler( transition, reverse, to, from ) ).transition();
-
-			// TODO temporary accomodation of argument deferred
-			promise.done(function() {
-				deferred.resolve.apply( deferred, arguments );
-			});
-
-			promise.done($.proxy(function() {
-				this._triggerCssTransitionEvents( to, from );
-			}, this));
-		},
-
-		_releaseTransitionLock: function() {
-			//release transition lock so navigation is free again
-			isPageTransitioning = false;
-			if ( pageTransitionQueue.length > 0 ) {
-				$.mobile.changePage.apply( null, pageTransitionQueue.pop() );
-			}
-		},
-
-		_removeActiveLinkClass: function( force ) {
-			//clear out the active button state
-			$.mobile.removeActiveLinkClass( force );
-		},
-
-		_loadUrl: function( to, triggerData, settings ) {
-			// preserve the original target as the dataUrl value will be
-			// simplified eg, removing ui-state, and removing query params
-			// from the hash this is so that users who want to use query
-			// params have access to them in the event bindings for the page
-			// life cycle See issue #5085
-			settings.target = to;
-			settings.deferred = $.Deferred();
-
-			this.load( to, settings );
-
-			settings.deferred.done($.proxy(function( url, options, content ) {
-				isPageTransitioning = false;
-
-				// store the original absolute url so that it can be provided
-				// to events in the triggerData of the subsequent changePage call
-				options.absUrl = triggerData.absUrl;
-
-				this.transition( content, triggerData, options );
-			}, this));
-
-			settings.deferred.fail($.proxy(function(/* url, options */) {
-				this._removeActiveLinkClass( true );
-				this._releaseTransitionLock();
-				this._triggerWithDeprecated( "changefailed", triggerData );
-			}, this));
-		},
-
-		_triggerPageBeforeChange: function( to, triggerData, settings ) {
-			var pbcEvent = new $.Event( "pagebeforechange" );
-
-			$.extend(triggerData, { toPage: to, options: settings });
-
-			// NOTE: preserve the original target as the dataUrl value will be
-			// simplified eg, removing ui-state, and removing query params from
-			// the hash this is so that users who want to use query params have
-			// access to them in the event bindings for the page life cycle
-			// See issue #5085
-			if ( $.type(to) === "string" ) {
-				// if the toPage is a string simply convert it
-				triggerData.absUrl = $.mobile.path.makeUrlAbsolute( to, this._findBaseWithDefault() );
-			} else {
-				// if the toPage is a jQuery object grab the absolute url stored
-				// in the loadPage callback where it exists
-				triggerData.absUrl = settings.absUrl;
-			}
-
-			// Let listeners know we're about to change the current page.
-			this.element.trigger( pbcEvent, triggerData );
-
-			// If the default behavior is prevented, stop here!
-			if ( pbcEvent.isDefaultPrevented() ) {
-				return false;
-			}
-
-			return true;
-		},
-
-		change: function( to, options ) {
-			// If we are in the midst of a transition, queue the current request.
-			// We'll call changePage() once we're done with the current transition
-			// to service the request.
-			if ( isPageTransitioning ) {
-				pageTransitionQueue.unshift( arguments );
-				return;
-			}
-
-			var settings = $.extend( {}, $.mobile.changePage.defaults, options ),
-				triggerData = {};
-
-			// Make sure we have a fromPage.
-			settings.fromPage = settings.fromPage || this.activePage;
-
-			// if the page beforechange default is prevented return early
-			if ( !this._triggerPageBeforeChange(to, triggerData, settings) ) {
-				return;
-			}
-
-			// We allow "pagebeforechange" observers to modify the to in
-			// the trigger data to allow for redirects. Make sure our to is
-			// updated. We also need to re-evaluate whether it is a string,
-			// because an object can also be replaced by a string
-			to = triggerData.toPage;
-
-			// If the caller passed us a url, call loadPage()
-			// to make sure it is loaded into the DOM. We'll listen
-			// to the promise object it returns so we know when
-			// it is done loading or if an error ocurred.
-			if ( $.type(to) === "string" ) {
-				// Set the isPageTransitioning flag to prevent any requests from
-				// entering this method while we are in the midst of loading a page
-				// or transitioning.
-				isPageTransitioning = true;
-
-				this._loadUrl( to, triggerData, settings );
-			} else {
-				this.transition( to, triggerData, settings );
-			}
-		},
-
-		transition: function( toPage, triggerData, settings ) {
-			var fromPage, url, pageUrl, fileUrl,
-				active, activeIsInitialPage,
-				historyDir, pageTitle, isDialog,
-				alreadyThere, newPageTitle,
-				params,	cssTransitionDeferred,
-				beforeTransition;
-
-			// If we are in the midst of a transition, queue the current request.
-			// We'll call changePage() once we're done with the current transition
-			// to service the request.
-			if ( isPageTransitioning ) {
-				// make sure to only queue the to and settings values so the arguments
-				// work with a call to the change method
-				pageTransitionQueue.unshift( [toPage, settings] );
-				return;
-			}
-
-			// DEPRECATED - this call only, in favor of the before transition
-			// if the page beforechange default is prevented return early
-			if ( !this._triggerPageBeforeChange(toPage, triggerData, settings) ) {
-				return;
-			}
-
-			// if the (content|page)beforetransition default is prevented return early
-			// Note, we have to check for both the deprecated and new events
-			beforeTransition = this._triggerWithDeprecated( "beforetransition", triggerData );
-			if (beforeTransition.deprecatedEvent.isDefaultPrevented() ||
-				beforeTransition.event.isDefaultPrevented() ) {
-				return;
-			}
-
-			// Set the isPageTransitioning flag to prevent any requests from
-			// entering this method while we are in the midst of loading a page
-			// or transitioning.
-			isPageTransitioning = true;
-
-			// If we are going to the first-page of the application, we need to make
-			// sure settings.dataUrl is set to the application document url. This allows
-			// us to avoid generating a document url with an id hash in the case where the
-			// first-page of the document has an id attribute specified.
-			if ( toPage[ 0 ] === $.mobile.firstPage[ 0 ] && !settings.dataUrl ) {
-				settings.dataUrl = $.mobile.path.documentUrl.hrefNoHash;
-			}
-
-			// The caller passed us a real page DOM element. Update our
-			// internal state and then trigger a transition to the page.
-			fromPage = settings.fromPage;
-			url = ( settings.dataUrl && $.mobile.path.convertUrlToDataUrl(settings.dataUrl) ) ||
-				toPage.jqmData( "url" );
-
-			// The pageUrl var is usually the same as url, except when url is obscured
-			// as a dialog url. pageUrl always contains the file path
-			pageUrl = url;
-			fileUrl = $.mobile.path.getFilePath( url );
-			active = $.mobile.navigate.history.getActive();
-			activeIsInitialPage = $.mobile.navigate.history.activeIndex === 0;
-			historyDir = 0;
-			pageTitle = document.title;
-			isDialog = ( settings.role === "dialog" ||
-				toPage.jqmData( "role" ) === "dialog" ) &&
-				toPage.jqmData( "dialog" ) !== true;
-
-			// By default, we prevent changePage requests when the fromPage and toPage
-			// are the same element, but folks that generate content
-			// manually/dynamically and reuse pages want to be able to transition to
-			// the same page. To allow this, they will need to change the default
-			// value of allowSamePageTransition to true, *OR*, pass it in as an
-			// option when they manually call changePage(). It should be noted that
-			// our default transition animations assume that the formPage and toPage
-			// are different elements, so they may behave unexpectedly. It is up to
-			// the developer that turns on the allowSamePageTransitiona option to
-			// either turn off transition animations, or make sure that an appropriate
-			// animation transition is used.
-			if ( fromPage && fromPage[0] === toPage[0] &&
-				!settings.allowSamePageTransition ) {
-
-				isPageTransitioning = false;
-				this._triggerWithDeprecated( "transition", triggerData );
-				this.element.trigger( "pagechange", triggerData );
-
-				// Even if there is no page change to be done, we should keep the
-				// urlHistory in sync with the hash changes
-				if ( settings.fromHashChange ) {
-					$.mobile.navigate.history.direct({ url: url });
-				}
-
-				return;
-			}
-
-			// We need to make sure the page we are given has already been enhanced.
-			toPage.page({ role: settings.role });
-
-			// If the changePage request was sent from a hashChange event, check to
-			// see if the page is already within the urlHistory stack. If so, we'll
-			// assume the user hit the forward/back button and will try to match the
-			// transition accordingly.
-			if ( settings.fromHashChange ) {
-				historyDir = settings.direction === "back" ? -1 : 1;
-			}
-
-			// Kill the keyboard.
-			// XXX_jblas: We need to stop crawling the entire document to kill focus.
-			//            Instead, we should be tracking focus with a delegate()
-			//            handler so we already have the element in hand at this
-			//            point.
-			// Wrap this in a try/catch block since IE9 throw "Unspecified error" if
-			// document.activeElement is undefined when we are in an IFrame.
-			try {
-				if ( document.activeElement &&
-					document.activeElement.nodeName.toLowerCase() !== "body" ) {
-
-					$( document.activeElement ).blur();
-				} else {
-					$( "input:focus, textarea:focus, select:focus" ).blur();
-				}
-			} catch( e ) {}
-
-			// Record whether we are at a place in history where a dialog used to be -
-			// if so, do not add a new history entry and do not change the hash either
-			alreadyThere = false;
-
-			// If we're displaying the page as a dialog, we don't want the url
-			// for the dialog content to be used in the hash. Instead, we want
-			// to append the dialogHashKey to the url of the current page.
-			if ( isDialog && active ) {
-				// on the initial page load active.url is undefined and in that case
-				// should be an empty string. Moving the undefined -> empty string back
-				// into urlHistory.addNew seemed imprudent given undefined better
-				// represents the url state
-
-				// If we are at a place in history that once belonged to a dialog, reuse
-				// this state without adding to urlHistory and without modifying the
-				// hash. However, if a dialog is already displayed at this point, and
-				// we're about to display another dialog, then we must add another hash
-				// and history entry on top so that one may navigate back to the
-				// original dialog
-				if ( active.url &&
-					active.url.indexOf( $.mobile.dialogHashKey ) > -1 &&
-					this.activePage &&
-					!this.activePage.hasClass( "ui-dialog" ) &&
-					$.mobile.navigate.history.activeIndex > 0 ) {
-
-					settings.changeHash = false;
-					alreadyThere = true;
-				}
-
-				// Normally, we tack on a dialog hash key, but if this is the location
-				// of a stale dialog, we reuse the URL from the entry
-				url = ( active.url || "" );
-
-				// account for absolute urls instead of just relative urls use as hashes
-				if ( !alreadyThere && url.indexOf("#") > -1 ) {
-					url += $.mobile.dialogHashKey;
-				} else {
-					url += "#" + $.mobile.dialogHashKey;
-				}
-
-				// tack on another dialogHashKey if this is the same as the initial hash
-				// this makes sure that a history entry is created for this dialog
-				if ( $.mobile.navigate.history.activeIndex === 0 && url === $.mobile.navigate.history.initialDst ) {
-					url += $.mobile.dialogHashKey;
-				}
-			}
-
-			// if title element wasn't found, try the page div data attr too
-			// If this is a deep-link or a reload ( active === undefined ) then just
-			// use pageTitle
-			newPageTitle = ( !active ) ? pageTitle : toPage.jqmData( "title" ) ||
-				toPage.children( ":jqmData(role='header')" ).find( ".ui-title" ).text();
-			if ( !!newPageTitle && pageTitle === document.title ) {
-				pageTitle = newPageTitle;
-			}
-			if ( !toPage.jqmData( "title" ) ) {
-				toPage.jqmData( "title", pageTitle );
-			}
-
-			// Make sure we have a transition defined.
-			settings.transition = settings.transition ||
-				( ( historyDir && !activeIsInitialPage ) ? active.transition : undefined ) ||
-				( isDialog ? $.mobile.defaultDialogTransition : $.mobile.defaultPageTransition );
-
-			//add page to history stack if it's not back or forward
-			if ( !historyDir && alreadyThere ) {
-				$.mobile.navigate.history.getActive().pageUrl = pageUrl;
-			}
-
-			// Set the location hash.
-			if ( url && !settings.fromHashChange ) {
-
-				// rebuilding the hash here since we loose it earlier on
-				// TODO preserve the originally passed in path
-				if ( !$.mobile.path.isPath( url ) && url.indexOf( "#" ) < 0 ) {
-					url = "#" + url;
-				}
-
-				// TODO the property names here are just silly
-				params = {
-					transition: settings.transition,
-					title: pageTitle,
-					pageUrl: pageUrl,
-					role: settings.role
-				};
-
-				if ( settings.changeHash !== false && $.mobile.hashListeningEnabled ) {
-					$.mobile.navigate( url, params, true);
-				} else if ( toPage[ 0 ] !== $.mobile.firstPage[ 0 ] ) {
-					$.mobile.navigate.history.add( url, params );
-				}
-			}
-
-			//set page title
-			document.title = pageTitle;
-
-			//set "toPage" as activePage deprecated in 1.4 remove in 1.5
-			$.mobile.activePage = toPage;
-
-			//new way to handle activePage
-			this.activePage = toPage;
-
-			// If we're navigating back in the URL history, set reverse accordingly.
-			settings.reverse = settings.reverse || historyDir < 0;
-
-			cssTransitionDeferred = $.Deferred();
-
-			this._cssTransition(toPage, fromPage, {
-				transition: settings.transition,
-				reverse: settings.reverse,
-				deferred: cssTransitionDeferred
-			});
-
-			cssTransitionDeferred.done($.proxy(function( name, reverse, $to, $from, alreadyFocused ) {
-				$.mobile.removeActiveLinkClass();
-
-				//if there's a duplicateCachedPage, remove it from the DOM now that it's hidden
-				if ( settings.duplicateCachedPage ) {
-					settings.duplicateCachedPage.remove();
-				}
-
-				// despite visibility: hidden addresses issue #2965
-				// https://github.com/jquery/jquery-mobile/issues/2965
-				if ( !alreadyFocused ) {
-					$.mobile.focusPage( toPage );
-				}
-
-				this._releaseTransitionLock();
-				this.element.trigger( "pagechange", triggerData );
-				this._triggerWithDeprecated( "transition", triggerData );
-			}, this));
-		},
-
-		// determine the current base url
-		_findBaseWithDefault: function() {
-			var closestBase = ( this.activePage &&
-			$.mobile.getClosestBaseUrl( this.activePage ) );
-		return closestBase || $.mobile.path.documentBase.hrefNoHash;
-		}
-	});
-
-	// The following handlers should be bound after mobileinit has been triggered
-	// the following deferred is resolved in the init file
-	$.mobile.navreadyDeferred = $.Deferred();
-
-	//these variables make all page containers use the same queue and only navigate one at a time
-	// queue to hold simultanious page transitions
-	var pageTransitionQueue = [],
-
-		// indicates whether or not page is in process of transitioning
-		isPageTransitioning = false;
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-		// resolved on domready
-	var domreadyDeferred = $.Deferred(),
-
-		// resolved and nulled on window.load()
-		loadDeferred = $.Deferred(),
-		documentUrl = $.mobile.path.documentUrl,
-
-		// used to track last vclicked element to make sure its value is added to form data
-		$lastVClicked = null;
-
-	/* Event Bindings - hashchange, submit, and click */
-	function findClosestLink( ele )	{
-		while ( ele ) {
-			// Look for the closest element with a nodeName of "a".
-			// Note that we are checking if we have a valid nodeName
-			// before attempting to access it. This is because the
-			// node we get called with could have originated from within
-			// an embedded SVG document where some symbol instance elements
-			// don't have nodeName defined on them, or strings are of type
-			// SVGAnimatedString.
-			if ( ( typeof ele.nodeName === "string" ) && ele.nodeName.toLowerCase() === "a" ) {
-				break;
-			}
-			ele = ele.parentNode;
-		}
-		return ele;
-	}
-
-	$.mobile.loadPage = function( url, opts ) {
-		var container;
-
-		opts = opts || {};
-		container = ( opts.pageContainer || $.mobile.pageContainer );
-
-		// create the deferred that will be supplied to loadPage callers
-		// and resolved by the content widget's load method
-		opts.deferred = $.Deferred();
-
-		// Preferring to allow exceptions for uninitialized opts.pageContainer
-		// widgets so we know if we need to force init here for users
-		container.pagecontainer( "load", url, opts );
-
-		// provide the deferred
-		return opts.deferred.promise();
-	};
-
-	//define vars for interal use
-
-	/* internal utility functions */
-
-	// NOTE Issue #4950 Android phonegap doesn't navigate back properly
-	//      when a full page refresh has taken place. It appears that hashchange
-	//      and replacestate history alterations work fine but we need to support
-	//      both forms of history traversal in our code that uses backward history
-	//      movement
-	$.mobile.back = function() {
-		var nav = window.navigator;
-
-		// if the setting is on and the navigator object is
-		// available use the phonegap navigation capability
-		if ( this.phonegapNavigationEnabled &&
-			nav &&
-			nav.app &&
-			nav.app.backHistory ) {
-			nav.app.backHistory();
-		} else {
-			$.mobile.pageContainer.pagecontainer( "back" );
-		}
-	};
-
-	// Direct focus to the page title, or otherwise first focusable element
-	$.mobile.focusPage = function ( page ) {
-		var autofocus = page.find( "[autofocus]" ),
-			pageTitle = page.find( ".ui-title:eq(0)" );
-
-		if ( autofocus.length ) {
-			autofocus.focus();
-			return;
-		}
-
-		if ( pageTitle.length ) {
-			pageTitle.focus();
-		} else{
-			page.focus();
-		}
-	};
-
-	// No-op implementation of transition degradation
-	$.mobile._maybeDegradeTransition = $.mobile._maybeDegradeTransition || function( transition ) {
-		return transition;
-	};
-
-	// Exposed $.mobile methods
-
-	$.mobile.changePage = function( to, options ) {
-		$.mobile.pageContainer.pagecontainer( "change", to, options );
-	};
-
-	$.mobile.changePage.defaults = {
-		transition: undefined,
-		reverse: false,
-		changeHash: true,
-		fromHashChange: false,
-		role: undefined, // By default we rely on the role defined by the @data-role attribute.
-		duplicateCachedPage: undefined,
-		pageContainer: undefined,
-		showLoadMsg: true, //loading message shows by default when pages are being fetched during changePage
-		dataUrl: undefined,
-		fromPage: undefined,
-		allowSamePageTransition: false
-	};
-
-	$.mobile._registerInternalEvents = function() {
-		var getAjaxFormData = function( $form, calculateOnly ) {
-			var url, ret = true, formData, vclickedName, method;
-			if ( !$.mobile.ajaxEnabled ||
-					// test that the form is, itself, ajax false
-					$form.is( ":jqmData(ajax='false')" ) ||
-					// test that $.mobile.ignoreContentEnabled is set and
-					// the form or one of it's parents is ajax=false
-					!$form.jqmHijackable().length ||
-					$form.attr( "target" ) ) {
-				return false;
-			}
-
-			url = ( $lastVClicked && $lastVClicked.attr( "formaction" ) ) ||
-				$form.attr( "action" );
-			method = ( $form.attr( "method" ) || "get" ).toLowerCase();
-
-			// If no action is specified, browsers default to using the
-			// URL of the document containing the form. Since we dynamically
-			// pull in pages from external documents, the form should submit
-			// to the URL for the source document of the page containing
-			// the form.
-			if ( !url ) {
-				// Get the @data-url for the page containing the form.
-				url = $.mobile.getClosestBaseUrl( $form );
-
-				// NOTE: If the method is "get", we need to strip off the query string
-				// because it will get replaced with the new form data. See issue #5710.
-				if ( method === "get" ) {
-					url = $.mobile.path.parseUrl( url ).hrefNoSearch;
-				}
-
-				if ( url === $.mobile.path.documentBase.hrefNoHash ) {
-					// The url we got back matches the document base,
-					// which means the page must be an internal/embedded page,
-					// so default to using the actual document url as a browser
-					// would.
-					url = documentUrl.hrefNoSearch;
-				}
-			}
-
-			url = $.mobile.path.makeUrlAbsolute(  url, $.mobile.getClosestBaseUrl( $form ) );
-
-			if ( ( $.mobile.path.isExternal( url ) && !$.mobile.path.isPermittedCrossDomainRequest( documentUrl, url ) ) ) {
-				return false;
-			}
-
-			if ( !calculateOnly ) {
-				formData = $form.serializeArray();
-
-				if ( $lastVClicked && $lastVClicked[ 0 ].form === $form[ 0 ] ) {
-					vclickedName = $lastVClicked.attr( "name" );
-					if ( vclickedName ) {
-						// Make sure the last clicked element is included in the form
-						$.each( formData, function( key, value ) {
-							if ( value.name === vclickedName ) {
-								// Unset vclickedName - we've found it in the serialized data already
-								vclickedName = "";
-								return false;
-							}
-						});
-						if ( vclickedName ) {
-							formData.push( { name: vclickedName, value: $lastVClicked.attr( "value" ) } );
-						}
-					}
-				}
-
-				ret = {
-					url: url,
-					options: {
-						type:		method,
-						data:		$.param( formData ),
-						transition:	$form.jqmData( "transition" ),
-						reverse:	$form.jqmData( "direction" ) === "reverse",
-						reloadPage:	true
-					}
-				};
-			}
-
-			return ret;
-		};
-
-		//bind to form submit events, handle with Ajax
-		$.mobile.document.delegate( "form", "submit", function( event ) {
-			var formData;
-
-			if ( !event.isDefaultPrevented() ) {
-				formData = getAjaxFormData( $( this ) );
-				if ( formData ) {
-					$.mobile.changePage( formData.url, formData.options );
-					event.preventDefault();
-				}
-			}
-		});
-
-		//add active state on vclick
-		$.mobile.document.bind( "vclick", function( event ) {
-			var $btn, btnEls, target = event.target, needClosest = false;
-			// if this isn't a left click we don't care. Its important to note
-			// that when the virtual event is generated it will create the which attr
-			if ( event.which > 1 || !$.mobile.linkBindingEnabled ) {
-				return;
-			}
-
-			// Record that this element was clicked, in case we need it for correct
-			// form submission during the "submit" handler above
-			$lastVClicked = $( target );
-
-			// Try to find a target element to which the active class will be applied
-			if ( $.data( target, "mobile-button" ) ) {
-				// If the form will not be submitted via AJAX, do not add active class
-				if ( !getAjaxFormData( $( target ).closest( "form" ), true ) ) {
-					return;
-				}
-				// We will apply the active state to this button widget - the parent
-				// of the input that was clicked will have the associated data
-				if ( target.parentNode ) {
-					target = target.parentNode;
-				}
-			} else {
-				target = findClosestLink( target );
-				if ( !( target && $.mobile.path.parseUrl( target.getAttribute( "href" ) || "#" ).hash !== "#" ) ) {
-					return;
-				}
-
-				// TODO teach $.mobile.hijackable to operate on raw dom elements so the
-				// link wrapping can be avoided
-				if ( !$( target ).jqmHijackable().length ) {
-					return;
-				}
-			}
-
-			// Avoid calling .closest by using the data set during .buttonMarkup()
-			// List items have the button data in the parent of the element clicked
-			if ( !!~target.className.indexOf( "ui-link-inherit" ) ) {
-				if ( target.parentNode ) {
-					btnEls = $.data( target.parentNode, "buttonElements" );
-				}
-			// Otherwise, look for the data on the target itself
-			} else {
-				btnEls = $.data( target, "buttonElements" );
-			}
-			// If found, grab the button's outer element
-			if ( btnEls ) {
-				target = btnEls.outer;
-			} else {
-				needClosest = true;
-			}
-
-			$btn = $( target );
-			// If the outer element wasn't found by the our heuristics, use .closest()
-			if ( needClosest ) {
-				$btn = $btn.closest( ".ui-btn" );
-			}
-
-			if ( $btn.length > 0 &&
-				!( $btn.hasClass( "ui-state-disabled" ||
-
-					// DEPRECATED as of 1.4.0 - remove after 1.4.0 release
-					// only ui-state-disabled should be present thereafter
-					$btn.hasClass( "ui-disabled" ) ) ) ) {
-				$.mobile.removeActiveLinkClass( true );
-				$.mobile.activeClickedLink = $btn;
-				$.mobile.activeClickedLink.addClass( $.mobile.activeBtnClass );
-			}
-		});
-
-		// click routing - direct to HTTP or Ajax, accordingly
-		$.mobile.document.bind( "click", function( event ) {
-			if ( !$.mobile.linkBindingEnabled || event.isDefaultPrevented() ) {
-				return;
-			}
-
-			var link = findClosestLink( event.target ),
-				$link = $( link ),
-
-				//remove active link class if external (then it won't be there if you come back)
-				httpCleanup = function() {
-					window.setTimeout(function() { $.mobile.removeActiveLinkClass( true ); }, 200 );
-				},
-				baseUrl, href,
-				useDefaultUrlHandling, isExternal,
-				transition, reverse, role;
-
-			// If a button was clicked, clean up the active class added by vclick above
-			if ( $.mobile.activeClickedLink &&
-				$.mobile.activeClickedLink[ 0 ] === event.target.parentNode ) {
-				httpCleanup();
-			}
-
-			// If there is no link associated with the click or its not a left
-			// click we want to ignore the click
-			// TODO teach $.mobile.hijackable to operate on raw dom elements so the link wrapping
-			// can be avoided
-			if ( !link || event.which > 1 || !$link.jqmHijackable().length ) {
-				return;
-			}
-
-			//if there's a data-rel=back attr, go back in history
-			if ( $link.is( ":jqmData(rel='back')" ) ) {
-				$.mobile.back();
-				return false;
-			}
-
-			baseUrl = $.mobile.getClosestBaseUrl( $link );
-
-			//get href, if defined, otherwise default to empty hash
-			href = $.mobile.path.makeUrlAbsolute( $link.attr( "href" ) || "#", baseUrl );
-
-			//if ajax is disabled, exit early
-			if ( !$.mobile.ajaxEnabled && !$.mobile.path.isEmbeddedPage( href ) ) {
-				httpCleanup();
-				//use default click handling
-				return;
-			}
-
-			// XXX_jblas: Ideally links to application pages should be specified as
-			//            an url to the application document with a hash that is either
-			//            the site relative path or id to the page. But some of the
-			//            internal code that dynamically generates sub-pages for nested
-			//            lists and select dialogs, just write a hash in the link they
-			//            create. This means the actual URL path is based on whatever
-			//            the current value of the base tag is at the time this code
-			//            is called. For now we are just assuming that any url with a
-			//            hash in it is an application page reference.
-			if ( href.search( "#" ) !== -1 ) {
-				href = href.replace( /[^#]*#/, "" );
-				if ( !href ) {
-					//link was an empty hash meant purely
-					//for interaction, so we ignore it.
-					event.preventDefault();
-					return;
-				} else if ( $.mobile.path.isPath( href ) ) {
-					//we have apath so make it the href we want to load.
-					href = $.mobile.path.makeUrlAbsolute( href, baseUrl );
-				} else {
-					//we have a simple id so use the documentUrl as its base.
-					href = $.mobile.path.makeUrlAbsolute( "#" + href, documentUrl.hrefNoHash );
-				}
-			}
-
-			// Should we handle this link, or let the browser deal with it?
-			useDefaultUrlHandling = $link.is( "[rel='external']" ) || $link.is( ":jqmData(ajax='false')" ) || $link.is( "[target]" );
-
-			// Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR
-			// requests if the document doing the request was loaded via the file:// protocol.
-			// This is usually to allow the application to "phone home" and fetch app specific
-			// data. We normally let the browser handle external/cross-domain urls, but if the
-			// allowCrossDomainPages option is true, we will allow cross-domain http/https
-			// requests to go through our page loading logic.
-
-			//check for protocol or rel and its not an embedded page
-			//TODO overlap in logic from isExternal, rel=external check should be
-			//     moved into more comprehensive isExternalLink
-			isExternal = useDefaultUrlHandling || ( $.mobile.path.isExternal( href ) && !$.mobile.path.isPermittedCrossDomainRequest( documentUrl, href ) );
-
-			if ( isExternal ) {
-				httpCleanup();
-				//use default click handling
-				return;
-			}
-
-			//use ajax
-			transition = $link.jqmData( "transition" );
-			reverse = $link.jqmData( "direction" ) === "reverse" ||
-						// deprecated - remove by 1.0
-						$link.jqmData( "back" );
-
-			//this may need to be more specific as we use data-rel more
-			role = $link.attr( "data-" + $.mobile.ns + "rel" ) || undefined;
-
-			$.mobile.changePage( href, { transition: transition, reverse: reverse, role: role, link: $link } );
-			event.preventDefault();
-		});
-
-		//prefetch pages when anchors with data-prefetch are encountered
-		$.mobile.document.delegate( ".ui-page", "pageshow.prefetch", function() {
-			var urls = [];
-			$( this ).find( "a:jqmData(prefetch)" ).each(function() {
-				var $link = $( this ),
-					url = $link.attr( "href" );
-
-				if ( url && $.inArray( url, urls ) === -1 ) {
-					urls.push( url );
-
-					$.mobile.loadPage( url, { role: $link.attr( "data-" + $.mobile.ns + "rel" ),prefetch: true } );
-				}
-			});
-		});
-
-		// TODO ensure that the navigate binding in the content widget happens at the right time
-		$.mobile.pageContainer.pagecontainer();
-
-		//set page min-heights to be device specific
-		$.mobile.document.bind( "pageshow", function() {
-
-			// We need to wait for window.load to make sure that styles have already been rendered,
-			// otherwise heights of external toolbars will have the wrong value
-			if ( loadDeferred ) {
-				loadDeferred.done( $.mobile.resetActivePageHeight );
-			} else {
-				$.mobile.resetActivePageHeight();
-			}
-		});
-		$.mobile.window.bind( "throttledresize", $.mobile.resetActivePageHeight );
-
-	};//navreadyDeferred done callback
-
-	$( function() { domreadyDeferred.resolve(); } );
-
-	$.mobile.window.load( function() {
-
-		// Resolve and null the deferred
-		loadDeferred.resolve();
-		loadDeferred = null;
-	});
-
-	$.when( domreadyDeferred, $.mobile.navreadyDeferred ).done( function() { $.mobile._registerInternalEvents(); } );
-})( jQuery );
-
-
-(function( $, window, undefined ) {
-
-	// TODO remove direct references to $.mobile and properties, we should
-	//      favor injection with params to the constructor
-	$.mobile.Transition = function() {
-		this.init.apply( this, arguments );
-	};
-
-	$.extend($.mobile.Transition.prototype, {
-		toPreClass: " ui-page-pre-in",
-
-		init: function( name, reverse, $to, $from ) {
-			$.extend(this, {
-				name: name,
-				reverse: reverse,
-				$to: $to,
-				$from: $from,
-				deferred: new $.Deferred()
-			});
-		},
-
-		cleanFrom: function() {
-			this.$from
-				.removeClass( $.mobile.activePageClass + " out in reverse " + this.name )
-				.height( "" );
-		},
-
-		// NOTE overridden by child object prototypes, noop'd here as defaults
-		beforeDoneIn: function() {},
-		beforeDoneOut: function() {},
-		beforeStartOut: function() {},
-
-		doneIn: function() {
-			this.beforeDoneIn();
-
-			this.$to.removeClass( "out in reverse " + this.name ).height( "" );
-
-			this.toggleViewportClass();
-
-			// In some browsers (iOS5), 3D transitions block the ability to scroll to the desired location during transition
-			// This ensures we jump to that spot after the fact, if we aren't there already.
-			if ( $.mobile.window.scrollTop() !== this.toScroll ) {
-				this.scrollPage();
-			}
-			if ( !this.sequential ) {
-				this.$to.addClass( $.mobile.activePageClass );
-			}
-			this.deferred.resolve( this.name, this.reverse, this.$to, this.$from, true );
-		},
-
-		doneOut: function( screenHeight, reverseClass, none, preventFocus ) {
-			this.beforeDoneOut();
-			this.startIn( screenHeight, reverseClass, none, preventFocus );
-		},
-
-		hideIn: function( callback ) {
-			// Prevent flickering in phonegap container: see comments at #4024 regarding iOS
-			this.$to.css( "z-index", -10 );
-			callback.call( this );
-			this.$to.css( "z-index", "" );
-		},
-
-		scrollPage: function() {
-			// By using scrollTo instead of silentScroll, we can keep things better in order
-			// Just to be precautios, disable scrollstart listening like silentScroll would
-			$.event.special.scrollstart.enabled = false;
-			//if we are hiding the url bar or the page was previously scrolled scroll to hide or return to position
-			if ( $.mobile.hideUrlBar || this.toScroll !== $.mobile.defaultHomeScroll ) {
-				window.scrollTo( 0, this.toScroll );
-			}
-
-			// reenable scrollstart listening like silentScroll would
-			setTimeout( function() {
-				$.event.special.scrollstart.enabled = true;
-			}, 150 );
-		},
-
-		startIn: function( screenHeight, reverseClass, none, preventFocus ) {
-			this.hideIn(function() {
-				this.$to.addClass( $.mobile.activePageClass + this.toPreClass );
-
-				// Send focus to page as it is now display: block
-				if ( !preventFocus ) {
-					$.mobile.focusPage( this.$to );
-				}
-
-				// Set to page height
-				this.$to.height( screenHeight + this.toScroll );
-
-                if ( !none ) {
-                    this.scrollPage();
-                }
-			});
-
-			this.$to
-				.removeClass( this.toPreClass )
-				.addClass( this.name + " in " + reverseClass );
-
-			if ( !none ) {
-				this.$to.animationComplete( $.proxy(function() {
-					this.doneIn();
-				}, this ));
-			} else {
-				this.doneIn();
-			}
-
-		},
-
-		startOut: function( screenHeight, reverseClass, none ) {
-			this.beforeStartOut( screenHeight, reverseClass, none );
-
-			// Set the from page's height and start it transitioning out
-			// Note: setting an explicit height helps eliminate tiling in the transitions
-			this.$from
-				.height( screenHeight + $.mobile.window.scrollTop() )
-				.addClass( this.name + " out" + reverseClass );
-		},
-
-		toggleViewportClass: function() {
-			$.mobile.pageContainer.toggleClass( "ui-mobile-viewport-transitioning viewport-" + this.name );
-		},
-
-		transition: function() {
-			// NOTE many of these could be calculated/recorded in the constructor, it's my
-			//      opinion that binding them as late as possible has value with regards to
-			//      better transitions with fewer bugs. Ie, it's not guaranteed that the
-			//      object will be created and transition will be run immediately after as
-			//      it is today. So we wait until transition is invoked to gather the following
-			var none,
-				reverseClass = this.reverse ? " reverse" : "",
-				screenHeight = $.mobile.getScreenHeight(),
-				maxTransitionOverride = $.mobile.maxTransitionWidth !== false &&
-					$.mobile.window.width() > $.mobile.maxTransitionWidth;
-
-			this.toScroll = $.mobile.navigate.history.getActive().lastScroll || $.mobile.defaultHomeScroll;
-
-			none = !$.support.cssTransitions || !$.support.cssAnimations ||
-				maxTransitionOverride || !this.name || this.name === "none" ||
-				Math.max( $.mobile.window.scrollTop(), this.toScroll ) >
-					$.mobile.getMaxScrollForTransition();
-
-			this.toggleViewportClass();
-
-			if ( this.$from && !none ) {
-				this.startOut( screenHeight, reverseClass, none );
-			} else {
-				this.doneOut( screenHeight, reverseClass, none, true );
-			}
-
-			return this.deferred.promise();
-		}
-	});
-})( jQuery, this );
-
-
-(function( $ ) {
-
-	$.mobile.SerialTransition = function() {
-		this.init.apply(this, arguments);
-	};
-
-	$.extend($.mobile.SerialTransition.prototype, $.mobile.Transition.prototype, {
-		sequential: true,
-
-		beforeDoneOut: function() {
-			if ( this.$from ) {
-				this.cleanFrom();
-			}
-		},
-
-		beforeStartOut: function( screenHeight, reverseClass, none ) {
-			this.$from.animationComplete($.proxy(function() {
-				this.doneOut( screenHeight, reverseClass, none );
-			}, this ));
-		}
-	});
-
-})( jQuery );
-
-
-(function( $ ) {
-
-	$.mobile.ConcurrentTransition = function() {
-		this.init.apply(this, arguments);
-	};
-
-	$.extend($.mobile.ConcurrentTransition.prototype, $.mobile.Transition.prototype, {
-		sequential: false,
-
-		beforeDoneIn: function() {
-			if ( this.$from ) {
-				this.cleanFrom();
-			}
-		},
-
-		beforeStartOut: function( screenHeight, reverseClass, none ) {
-			this.doneOut( screenHeight, reverseClass, none );
-		}
-	});
-
-})( jQuery );
-
-
-(function( $ ) {
-
-	// generate the handlers from the above
-	var defaultGetMaxScrollForTransition = function() {
-		return $.mobile.getScreenHeight() * 3;
-	};
-
-	//transition handler dictionary for 3rd party transitions
-	$.mobile.transitionHandlers = {
-		"sequential": $.mobile.SerialTransition,
-		"simultaneous": $.mobile.ConcurrentTransition
-	};
-
-	// Make our transition handler the public default.
-	$.mobile.defaultTransitionHandler = $.mobile.transitionHandlers.sequential;
-
-	$.mobile.transitionFallbacks = {};
-
-	// If transition is defined, check if css 3D transforms are supported, and if not, if a fallback is specified
-	$.mobile._maybeDegradeTransition = function( transition ) {
-		if ( transition && !$.support.cssTransform3d && $.mobile.transitionFallbacks[ transition ] ) {
-			transition = $.mobile.transitionFallbacks[ transition ];
-		}
-
-		return transition;
-	};
-
-	// Set the getMaxScrollForTransition to default if no implementation was set by user
-	$.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defaultGetMaxScrollForTransition;
-
-})( jQuery );
-
-/*
-* fallback transition for flip in non-3D supporting browsers (which tend to handle complex transitions poorly in general
-*/
-
-(function( $, window, undefined ) {
-
-$.mobile.transitionFallbacks.flip = "fade";
-
-})( jQuery, this );
-
-/*
-* fallback transition for flow in non-3D supporting browsers (which tend to handle complex transitions poorly in general
-*/
-
-(function( $, window, undefined ) {
-
-$.mobile.transitionFallbacks.flow = "fade";
-
-})( jQuery, this );
-
-/*
-* fallback transition for pop in non-3D supporting browsers (which tend to handle complex transitions poorly in general
-*/
-
-(function( $, window, undefined ) {
-
-$.mobile.transitionFallbacks.pop = "fade";
-
-})( jQuery, this );
-
-/*
-* fallback transition for slide in non-3D supporting browsers (which tend to handle complex transitions poorly in general
-*/
-
-(function( $, window, undefined ) {
-
-// Use the simultaneous transitions handler for slide transitions
-$.mobile.transitionHandlers.slide = $.mobile.transitionHandlers.simultaneous;
-
-// Set the slide transitions's fallback to "fade"
-$.mobile.transitionFallbacks.slide = "fade";
-
-})( jQuery, this );
-
-/*
-* fallback transition for slidedown in non-3D supporting browsers (which tend to handle complex transitions poorly in general
-*/
-
-(function( $, window, undefined ) {
-
-$.mobile.transitionFallbacks.slidedown = "fade";
-
-})( jQuery, this );
-
-/*
-* fallback transition for slidefade in non-3D supporting browsers (which tend to handle complex transitions poorly in general
-*/
-
-(function( $, window, undefined ) {
-
-// Set the slide transitions's fallback to "fade"
-$.mobile.transitionFallbacks.slidefade = "fade";
-
-})( jQuery, this );
-
-/*
-* fallback transition for slideup in non-3D supporting browsers (which tend to handle complex transitions poorly in general
-*/
-
-(function( $, window, undefined ) {
-
-$.mobile.transitionFallbacks.slideup = "fade";
-
-})( jQuery, this );
-
-/*
-* fallback transition for turn in non-3D supporting browsers (which tend to handle complex transitions poorly in general
-*/
-
-(function( $, window, undefined ) {
-
-$.mobile.transitionFallbacks.turn = "fade";
-
-})( jQuery, this );
-
-
-(function( $, undefined ) {
-
-$.mobile.degradeInputs = {
-	color: false,
-	date: false,
-	datetime: false,
-	"datetime-local": false,
-	email: false,
-	month: false,
-	number: false,
-	range: "number",
-	search: "text",
-	tel: false,
-	time: false,
-	url: false,
-	week: false
-};
-// Backcompat remove in 1.5
-$.mobile.page.prototype.options.degradeInputs = $.mobile.degradeInputs;
-
-// Auto self-init widgets
-$.mobile.degradeInputsWithin = function( target ) {
-
-	target = $( target );
-
-	// Degrade inputs to avoid poorly implemented native functionality
-	target.find( "input" ).not( $.mobile.page.prototype.keepNativeSelector() ).each(function() {
-		var element = $( this ),
-			type = this.getAttribute( "type" ),
-			optType = $.mobile.degradeInputs[ type ] || "text",
-			html, hasType, findstr, repstr;
-
-		if ( $.mobile.degradeInputs[ type ] ) {
-			html = $( "<div>" ).html( element.clone() ).html();
-			// In IE browsers, the type sometimes doesn't exist in the cloned markup, so we replace the closing tag instead
-			hasType = html.indexOf( " type=" ) > -1;
-			findstr = hasType ? /\s+type=["']?\w+['"]?/ : /\/?>/;
-			repstr = " type=\"" + optType + "\" data-" + $.mobile.ns + "type=\"" + type + "\"" + ( hasType ? "" : ">" );
-
-			element.replaceWith( html.replace( findstr, repstr ) );
-		}
-	});
-
-};
-
-})( jQuery );
-
-(function( $, window, undefined ) {
-
-$.widget( "mobile.page", $.mobile.page, {
-	options: {
-
-		// Accepts left, right and none
-		closeBtn: "left",
-		closeBtnText: "Close",
-		overlayTheme: "a",
-		corners: true,
-		dialog: false
-	},
-
-	_create: function() {
-		this._super();
-		if ( this.options.dialog ) {
-
-			$.extend( this, {
-				_inner: this.element.children(),
-				_headerCloseButton: null
-			});
-
-			if ( !this.options.enhanced ) {
-				this._setCloseBtn( this.options.closeBtn );
-			}
-		}
-	},
-
-	_enhance: function() {
-		this._super();
-
-		// Class the markup for dialog styling and wrap interior
-		if ( this.options.dialog ) {
-			this.element.addClass( "ui-dialog" )
-				.wrapInner( $( "<div/>", {
-
-					// ARIA role
-					"role" : "dialog",
-					"class" : "ui-dialog-contain ui-overlay-shadow" +
-						( this.options.corners ? " ui-corner-all" : "" )
-				}));
-		}
-	},
-
-	_setOptions: function( options ) {
-		var closeButtonLocation, closeButtonText,
-			currentOpts = this.options;
-
-		if ( options.corners !== undefined ) {
-			this._inner.toggleClass( "ui-corner-all", !!options.corners );
-		}
-
-		if ( options.overlayTheme !== undefined ) {
-			if ( $.mobile.activePage[ 0 ] === this.element[ 0 ] ) {
-				currentOpts.overlayTheme = options.overlayTheme;
-				this._handlePageBeforeShow();
-			}
-		}
-
-		if ( options.closeBtnText !== undefined ) {
-			closeButtonLocation = currentOpts.closeBtn;
-			closeButtonText = options.closeBtnText;
-		}
-
-		if ( options.closeBtn !== undefined ) {
-			closeButtonLocation = options.closeBtn;
-		}
-
-		if ( closeButtonLocation ) {
-			this._setCloseBtn( closeButtonLocation, closeButtonText );
-		}
-
-		this._super( options );
-	},
-
-	_handlePageBeforeShow: function () {
-		if ( this.options.overlayTheme && this.options.dialog ) {
-			this.removeContainerBackground();
-			this.setContainerBackground( this.options.overlayTheme );
-		} else {
-			this._super();
-		}
-	},
-
-	_setCloseBtn: function( location, text ) {
-		var dst,
-			btn = this._headerCloseButton;
-
-		// Sanitize value
-		location = "left" === location ? "left" : "right" === location ? "right" : "none";
-
-		if ( "none" === location ) {
-			if ( btn ) {
-				btn.remove();
-				btn = null;
-			}
-		} else if ( btn ) {
-			btn.removeClass( "ui-btn-left ui-btn-right" ).addClass( "ui-btn-" + location );
-			if ( text ) {
-				btn.text( text );
-			}
-		} else {
-			dst = this._inner.find( ":jqmData(role='header')" ).first();
-			btn = $( "<a></a>", {
-					"href": "#",
-					"class": "ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-" + location
-				})
-				.attr( "data-" + $.mobile.ns + "rel", "back" )
-				.text( text || this.options.closeBtnText || "" )
-				.prependTo( dst );
-		}
-
-		this._headerCloseButton = btn;
-	}
-});
-
-})( jQuery, this );
-
-(function( $, window, undefined ) {
-
-$.widget( "mobile.dialog", {
-	options: {
-
-		// Accepts left, right and none
-		closeBtn: "left",
-		closeBtnText: "Close",
-		overlayTheme: "a",
-		corners: true
-	},
-
-	// Override the theme set by the page plugin on pageshow
-	_handlePageBeforeShow: function() {
-		this._isCloseable = true;
-		if ( this.options.overlayTheme ) {
-			this.element
-				.page( "removeContainerBackground" )
-				.page( "setContainerBackground", this.options.overlayTheme );
-		}
-	},
-
-	_handlePageBeforeHide: function() {
-		this._isCloseable = false;
-	},
-
-	// click and submit events:
-	// - clicks and submits should use the closing transition that the dialog
-	//   opened with unless a data-transition is specified on the link/form
-	// - if the click was on the close button, or the link has a data-rel="back"
-	//   it'll go back in history naturally
-	_handleVClickSubmit: function( event ) {
-		var attrs,
-			$target = $( event.target ).closest( event.type === "vclick" ? "a" : "form" );
-
-		if ( $target.length && !$target.jqmData( "transition" ) ) {
-			attrs = {};
-			attrs[ "data-" + $.mobile.ns + "transition" ] =
-				( $.mobile.navigate.history.getActive() || {} )[ "transition" ] ||
-				$.mobile.defaultDialogTransition;
-			attrs[ "data-" + $.mobile.ns + "direction" ] = "reverse";
-			$target.attr( attrs );
-		}
-	},
-
-	_create: function() {
-		var elem = this.element,
-			opts = this.options;
-
-		// Class the markup for dialog styling and wrap interior
-		elem.addClass( "ui-dialog" )
-			.wrapInner( $( "<div/>", {
-
-				// ARIA role
-				"role" : "dialog",
-				"class" : "ui-dialog-contain ui-overlay-shadow" +
-					( !!opts.corners ? " ui-corner-all" : "" )
-			}));
-
-		$.extend( this, {
-			_isCloseable: false,
-			_inner: elem.children(),
-			_headerCloseButton: null
-		});
-
-		this._on( elem, {
-			vclick: "_handleVClickSubmit",
-			submit: "_handleVClickSubmit",
-			pagebeforeshow: "_handlePageBeforeShow",
-			pagebeforehide: "_handlePageBeforeHide"
-		});
-
-		this._setCloseBtn( opts.closeBtn );
-	},
-
-	_setOptions: function( options ) {
-		var closeButtonLocation, closeButtonText,
-			currentOpts = this.options;
-
-		if ( options.corners !== undefined ) {
-			this._inner.toggleClass( "ui-corner-all", !!options.corners );
-		}
-
-		if ( options.overlayTheme !== undefined ) {
-			if ( $.mobile.activePage[ 0 ] === this.element[ 0 ] ) {
-				currentOpts.overlayTheme = options.overlayTheme;
-				this._handlePageBeforeShow();
-			}
-		}
-
-		if ( options.closeBtnText !== undefined ) {
-			closeButtonLocation = currentOpts.closeBtn;
-			closeButtonText = options.closeBtnText;
-		}
-
-		if ( options.closeBtn !== undefined ) {
-			closeButtonLocation = options.closeBtn;
-		}
-
-		if ( closeButtonLocation ) {
-			this._setCloseBtn( closeButtonLocation, closeButtonText );
-		}
-
-		this._super( options );
-	},
-
-	_setCloseBtn: function( location, text ) {
-		var dst,
-			btn = this._headerCloseButton;
-
-		// Sanitize value
-		location = "left" === location ? "left" : "right" === location ? "right" : "none";
-
-		if ( "none" === location ) {
-			if ( btn ) {
-				btn.remove();
-				btn = null;
-			}
-		} else if ( btn ) {
-			btn.removeClass( "ui-btn-left ui-btn-right" ).addClass( "ui-btn-" + location );
-			if ( text ) {
-				btn.text( text );
-			}
-		} else {
-			dst = this._inner.find( ":jqmData(role='header')" ).first();
-			btn = $( "<a></a>", {
-					"role": "button",
-					"href": "#",
-					"class": "ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-" + location
-				})
-				.text( text || this.options.closeBtnText || "" )
-				.prependTo( dst );
-			this._on( btn, { click: "close" } );
-		}
-
-		this._headerCloseButton = btn;
-	},
-
-	// Close method goes back in history
-	close: function() {
-		var hist = $.mobile.navigate.history;
-
-		if ( this._isCloseable ) {
-			this._isCloseable = false;
-			// If the hash listening is enabled and there is at least one preceding history
-			// entry it's ok to go back. Initial pages with the dialog hash state are an example
-			// where the stack check is necessary
-			if ( $.mobile.hashListeningEnabled && hist.activeIndex > 0 ) {
-				$.mobile.back();
-			} else {
-				$.mobile.pageContainer.pagecontainer( "back" );
-			}
-		}
-	}
-});
-
-})( jQuery, this );
-
-(function( $, undefined ) {
-
-var rInitialLetter = /([A-Z])/g,
-
-	// Construct iconpos class from iconpos value
-	iconposClass = function( iconpos ) {
-		return ( "ui-btn-icon-" + ( iconpos === null ? "left" : iconpos ) );
-	};
-
-$.widget( "mobile.collapsible", {
-	options: {
-		enhanced: false,
-		expandCueText: null,
-		collapseCueText: null,
-		collapsed: true,
-		heading: "h1,h2,h3,h4,h5,h6,legend",
-		collapsedIcon: null,
-		expandedIcon: null,
-		iconpos: null,
-		theme: null,
-		contentTheme: null,
-		inset: null,
-		corners: null,
-		mini: null
-	},
-
-	_create: function() {
-		var elem = this.element,
-			ui = {
-				accordion: elem
-					.closest( ":jqmData(role='collapsible-set')," +
-						":jqmData(role='collapsibleset')" +
-						( $.mobile.collapsibleset ? ", :mobile-collapsibleset" :
-							"" ) )
-					.addClass( "ui-collapsible-set" )
-			};
-
-		this._ui = ui;
-		this._renderedOptions = this._getOptions( this.options );
-
-		if ( this.options.enhanced ) {
-			ui.heading = $( ".ui-collapsible-heading", this.element[ 0 ] );
-			ui.content = ui.heading.next();
-			ui.anchor = $( "a", ui.heading[ 0 ] ).first();
-			ui.status = ui.anchor.children( ".ui-collapsible-heading-status" );
-		} else {
-			this._enhance( elem, ui );
-		}
-
-		this._on( ui.heading, {
-			"tap": function() {
-				ui.heading.find( "a" ).first().addClass( $.mobile.activeBtnClass );
-			},
-
-			"click": function( event ) {
-				this._handleExpandCollapse( !ui.heading.hasClass( "ui-collapsible-heading-collapsed" ) );
-				event.preventDefault();
-				event.stopPropagation();
-			}
-		});
-	},
-
-	// Adjust the keys inside options for inherited values
-	_getOptions: function( options ) {
-		var key,
-			accordion = this._ui.accordion,
-			accordionWidget = this._ui.accordionWidget;
-
-		// Copy options
-		options = $.extend( {}, options );
-
-		if ( accordion.length && !accordionWidget ) {
-			this._ui.accordionWidget =
-			accordionWidget = accordion.data( "mobile-collapsibleset" );
-		}
-
-		for ( key in options ) {
-
-			// Retrieve the option value first from the options object passed in and, if
-			// null, from the parent accordion or, if that's null too, or if there's no
-			// parent accordion, then from the defaults.
-			options[ key ] =
-				( options[ key ] != null ) ? options[ key ] :
-				( accordionWidget ) ? accordionWidget.options[ key ] :
-				accordion.length ? $.mobile.getAttribute( accordion[ 0 ],
-					key.replace( rInitialLetter, "-$1" ).toLowerCase() ):
-				null;
-
-			if ( null == options[ key ] ) {
-				options[ key ] = $.mobile.collapsible.defaults[ key ];
-			}
-		}
-
-		return options;
-	},
-
-	_themeClassFromOption: function( prefix, value ) {
-		return ( value ? ( value === "none" ? "" : prefix + value ) : "" );
-	},
-
-	_enhance: function( elem, ui ) {
-		var iconclass,
-			opts = this._renderedOptions,
-			contentThemeClass = this._themeClassFromOption( "ui-body-", opts.contentTheme );
-
-		elem.addClass( "ui-collapsible " +
-			( opts.inset ? "ui-collapsible-inset " : "" ) +
-			( opts.inset && opts.corners ? "ui-corner-all " : "" ) +
-			( contentThemeClass ? "ui-collapsible-themed-content " : "" ) );
-		ui.originalHeading = elem.children( this.options.heading ).first(),
-		ui.content = elem
-			.wrapInner( "<div " +
-				"class='ui-collapsible-content " +
-				contentThemeClass + "'></div>" )
-			.children( ".ui-collapsible-content" ),
-		ui.heading = ui.originalHeading;
-
-		// Replace collapsibleHeading if it's a legend
-		if ( ui.heading.is( "legend" ) ) {
-			ui.heading = $( "<div role='heading'>"+ ui.heading.html() +"</div>" );
-			ui.placeholder = $( "<div><!-- placeholder for legend --></div>" ).insertBefore( ui.originalHeading );
-			ui.originalHeading.remove();
-		}
-
-		iconclass = ( opts.collapsed ? ( opts.collapsedIcon ? "ui-icon-" + opts.collapsedIcon : "" ):
-			( opts.expandedIcon ? "ui-icon-" + opts.expandedIcon : "" ) );
-
-		ui.status = $( "<span class='ui-collapsible-heading-status'></span>" );
-		ui.anchor = ui.heading
-			.detach()
-			//modify markup & attributes
-			.addClass( "ui-collapsible-heading" )
-			.append( ui.status )
-			.wrapInner( "<a href='#' class='ui-collapsible-heading-toggle'></a>" )
-			.find( "a" )
-				.first()
-				.addClass( "ui-btn " +
-					( iconclass ? iconclass + " " : "" ) +
-					( iconclass ? iconposClass( opts.iconpos ) +
-						" " : "" ) +
-					this._themeClassFromOption( "ui-btn-", opts.theme ) + " " +
-					( opts.mini ? "ui-mini " : "" ) );
-
-		//drop heading in before content
-		ui.heading.insertBefore( ui.content );
-
-		this._handleExpandCollapse( this.options.collapsed );
-
-		return ui;
-	},
-
-	refresh: function() {
-		this._applyOptions( this.options );
-		this._renderedOptions = this._getOptions( this.options );
-	},
-
-	_applyOptions: function( options ) {
-		var isCollapsed, newTheme, oldTheme, hasCorners, hasIcon,
-			elem = this.element,
-			currentOpts = this._renderedOptions,
-			ui = this._ui,
-			anchor = ui.anchor,
-			status = ui.status,
-			opts = this._getOptions( options );
-
-		// First and foremost we need to make sure the collapsible is in the proper
-		// state, in case somebody decided to change the collapsed option at the
-		// same time as another option
-		if ( options.collapsed !== undefined ) {
-			this._handleExpandCollapse( options.collapsed );
-		}
-
-		isCollapsed = elem.hasClass( "ui-collapsible-collapsed" );
-
-		// We only need to apply the cue text for the current state right away.
-		// The cue text for the alternate state will be stored in the options
-		// and applied the next time the collapsible's state is toggled
-		if ( isCollapsed ) {
-			if ( opts.expandCueText !== undefined ) {
-				status.text( opts.expandCueText );
-			}
-		} else {
-			if ( opts.collapseCueText !== undefined ) {
-				status.text( opts.collapseCueText );
-			}
-		}
-
-		// Update icon
-
-		// Is it supposed to have an icon?
-		hasIcon =
-
-			// If the collapsedIcon is being set, consult that
-			( opts.collapsedIcon !== undefined ? opts.collapsedIcon !== false :
-
-				// Otherwise consult the existing option value
-				currentOpts.collapsedIcon !== false );
-
-
-		// If any icon-related options have changed, make sure the new icon
-		// state is reflected by first removing all icon-related classes
-		// reflecting the current state and then adding all icon-related
-		// classes for the new state
-		if ( !( opts.iconpos === undefined &&
-			opts.collapsedIcon === undefined &&
-			opts.expandedIcon === undefined ) ) {
-
-			// Remove all current icon-related classes
-			anchor.removeClass( [ iconposClass( currentOpts.iconpos ) ]
-				.concat( ( currentOpts.expandedIcon ?
-					[ "ui-icon-" + currentOpts.expandedIcon ] : [] ) )
-				.concat( ( currentOpts.collapsedIcon ?
-					[ "ui-icon-" + currentOpts.collapsedIcon ] : [] ) )
-				.join( " " ) );
-
-			// Add new classes if an icon is supposed to be present
-			if ( hasIcon ) {
-				anchor.addClass(
-					[ iconposClass( opts.iconpos !== undefined ?
-						opts.iconpos : currentOpts.iconpos ) ]
-						.concat( isCollapsed ?
-							[ "ui-icon-" + ( opts.collapsedIcon !== undefined ?
-								opts.collapsedIcon :
-								currentOpts.collapsedIcon ) ] :
-							[ "ui-icon-" + ( opts.expandedIcon !== undefined ?
-								opts.expandedIcon :
-								currentOpts.expandedIcon ) ] )
-						.join( " " ) );
-			}
-		}
-
-		if ( opts.theme !== undefined ) {
-			oldTheme = this._themeClassFromOption( "ui-btn-", currentOpts.theme );
-			newTheme = this._themeClassFromOption( "ui-btn-", opts.theme );
-			anchor.removeClass( oldTheme ).addClass( newTheme );
-		}
-
-		if ( opts.contentTheme !== undefined ) {
-			oldTheme = this._themeClassFromOption( "ui-body-",
-				currentOpts.contentTheme );
-			newTheme = this._themeClassFromOption( "ui-body-",
-				opts.contentTheme );
-			ui.content.removeClass( oldTheme ).addClass( newTheme );
-		}
-
-		if ( opts.inset !== undefined ) {
-			elem.toggleClass( "ui-collapsible-inset", opts.inset );
-			hasCorners = !!( opts.inset && ( opts.corners || currentOpts.corners ) );
-		}
-
-		if ( opts.corners !== undefined ) {
-			hasCorners = !!( opts.corners && ( opts.inset || currentOpts.inset ) );
-		}
-
-		if ( hasCorners !== undefined ) {
-			elem.toggleClass( "ui-corner-all", hasCorners );
-		}
-
-		if ( opts.mini !== undefined ) {
-			anchor.toggleClass( "ui-mini", opts.mini );
-		}
-	},
-
-	_setOptions: function( options ) {
-		this._applyOptions( options );
-		this._super( options );
-		this._renderedOptions = this._getOptions( this.options );
-	},
-
-	_handleExpandCollapse: function( isCollapse ) {
-		var opts = this._renderedOptions,
-			ui = this._ui;
-
-		ui.status.text( isCollapse ? opts.expandCueText : opts.collapseCueText );
-		ui.heading
-			.toggleClass( "ui-collapsible-heading-collapsed", isCollapse )
-			.find( "a" ).first()
-			.toggleClass( "ui-icon-" + opts.expandedIcon, !isCollapse )
-
-			// logic or cause same icon for expanded/collapsed state would remove the ui-icon-class
-			.toggleClass( "ui-icon-" + opts.collapsedIcon, ( isCollapse || opts.expandedIcon === opts.collapsedIcon ) )
-			.removeClass( $.mobile.activeBtnClass );
-
-		this.element.toggleClass( "ui-collapsible-collapsed", isCollapse );
-		ui.content
-			.toggleClass( "ui-collapsible-content-collapsed", isCollapse )
-			.attr( "aria-hidden", isCollapse )
-			.trigger( "updatelayout" );
-		this.options.collapsed = isCollapse;
-		this._trigger( isCollapse ? "collapse" : "expand" );
-	},
-
-	expand: function() {
-		this._handleExpandCollapse( false );
-	},
-
-	collapse: function() {
-		this._handleExpandCollapse( true );
-	},
-
-	_destroy: function() {
-		var ui = this._ui,
-			opts = this.options;
-
-		if ( opts.enhanced ) {
-			return;
-		}
-
-		if ( ui.placeholder ) {
-			ui.originalHeading.insertBefore( ui.placeholder );
-			ui.placeholder.remove();
-			ui.heading.remove();
-		} else {
-			ui.status.remove();
-			ui.heading
-				.removeClass( "ui-collapsible-heading ui-collapsible-heading-collapsed" )
-				.children()
-					.contents()
-						.unwrap();
-		}
-
-		ui.anchor.contents().unwrap();
-		ui.content.contents().unwrap();
-		this.element
-			.removeClass( "ui-collapsible ui-collapsible-collapsed " +
-				"ui-collapsible-themed-content ui-collapsible-inset ui-corner-all" );
-	}
-});
-
-// Defaults to be used by all instances of collapsible if per-instance values
-// are unset or if nothing is specified by way of inheritance from an accordion.
-// Note that this hash does not contain options "collapsed" or "heading",
-// because those are not inheritable.
-$.mobile.collapsible.defaults = {
-	expandCueText: " click to expand contents",
-	collapseCueText: " click to collapse contents",
-	collapsedIcon: "plus",
-	contentTheme: "inherit",
-	expandedIcon: "minus",
-	iconpos: "left",
-	inset: true,
-	corners: true,
-	theme: "inherit",
-	mini: false
-};
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.mobile.behaviors.addFirstLastClasses = {
-	_getVisibles: function( $els, create ) {
-		var visibles;
-
-		if ( create ) {
-			visibles = $els.not( ".ui-screen-hidden" );
-		} else {
-			visibles = $els.filter( ":visible" );
-			if ( visibles.length === 0 ) {
-				visibles = $els.not( ".ui-screen-hidden" );
-			}
-		}
-
-		return visibles;
-	},
-
-	_addFirstLastClasses: function( $els, $visibles, create ) {
-		$els.removeClass( "ui-first-child ui-last-child" );
-		$visibles.eq( 0 ).addClass( "ui-first-child" ).end().last().addClass( "ui-last-child" );
-		if ( !create ) {
-			this.element.trigger( "updatelayout" );
-		}
-	},
-
-	_removeFirstLastClasses: function( $els ) {
-		$els.removeClass( "ui-first-child ui-last-child" );
-	}
-};
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-var childCollapsiblesSelector = ":mobile-collapsible, " + $.mobile.collapsible.initSelector;
-
-$.widget( "mobile.collapsibleset", $.extend( {
-
-	// The initSelector is deprecated as of 1.4.0. In 1.5.0 we will use
-	// :jqmData(role='collapsibleset') which will allow us to get rid of the line
-	// below altogether, because the autoinit will generate such an initSelector
-	initSelector: ":jqmData(role='collapsible-set'),:jqmData(role='collapsibleset')",
-
-	options: $.extend( {
-		enhanced: false
-	}, $.mobile.collapsible.defaults ),
-
-	_handleCollapsibleExpand: function( event ) {
-		var closestCollapsible = $( event.target ).closest( ".ui-collapsible" );
-
-		if ( closestCollapsible.parent().is( ":mobile-collapsibleset, :jqmData(role='collapsible-set')" ) ) {
-			closestCollapsible
-				.siblings( ".ui-collapsible:not(.ui-collapsible-collapsed)" )
-				.collapsible( "collapse" );
-		}
-	},
-
-	_create: function() {
-		var elem = this.element,
-			opts = this.options;
-
-		$.extend( this, {
-			_classes: ""
-		});
-
-		if ( !opts.enhanced ) {
-			elem.addClass( "ui-collapsible-set " +
-				this._themeClassFromOption( "ui-group-theme-", opts.theme ) + " " +
-				( opts.corners && opts.inset ? "ui-corner-all " : "" ) );
-			this.element.find( $.mobile.collapsible.initSelector ).collapsible();
-		}
-
-		this._on( elem, { collapsibleexpand: "_handleCollapsibleExpand" } );
-	},
-
-	_themeClassFromOption: function( prefix, value ) {
-		return ( value ? ( value === "none" ? "" : prefix + value ) : "" );
-	},
-
-	_init: function() {
-		this._refresh( true );
-
-		// Because the corners are handled by the collapsible itself and the default state is collapsed
-		// That was causing https://github.com/jquery/jquery-mobile/issues/4116
-		this.element
-			.children( childCollapsiblesSelector )
-			.filter( ":jqmData(collapsed='false')" )
-			.collapsible( "expand" );
-	},
-
-	_setOptions: function( options ) {
-		var ret, hasCorners,
-			elem = this.element,
-			themeClass = this._themeClassFromOption( "ui-group-theme-", options.theme );
-
-		if ( themeClass ) {
-			elem
-				.removeClass( this._themeClassFromOption( "ui-group-theme-", this.options.theme ) )
-				.addClass( themeClass );
-		}
-
-		if ( options.inset !== undefined ) {
-			hasCorners = !!( options.inset && ( options.corners || this.options.corners ) );
-		}
-
-		if ( options.corners !== undefined ) {
-			hasCorners = !!( options.corners && ( options.inset || this.options.inset ) );
-		}
-
-		if ( hasCorners !== undefined ) {
-			elem.toggleClass( "ui-corner-all", hasCorners );
-		}
-
-		ret = this._super( options );
-		this.element.children( ":mobile-collapsible" ).collapsible( "refresh" );
-		return ret;
-	},
-
-	_destroy: function() {
-		var el = this.element;
-
-		this._removeFirstLastClasses( el.children( childCollapsiblesSelector ) );
-		el
-			.removeClass( "ui-collapsible-set ui-corner-all " +
-				this._themeClassFromOption( "ui-group-theme-", this.options.theme ) )
-			.children( ":mobile-collapsible" )
-			.collapsible( "destroy" );
-	},
-
-	_refresh: function( create ) {
-		var collapsiblesInSet = this.element.children( childCollapsiblesSelector );
-
-		this.element.find( $.mobile.collapsible.initSelector ).not( ".ui-collapsible" ).collapsible();
-
-		this._addFirstLastClasses( collapsiblesInSet, this._getVisibles( collapsiblesInSet, create ), create );
-	},
-
-	refresh: function() {
-		this._refresh( false );
-	}
-}, $.mobile.behaviors.addFirstLastClasses ) );
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-// Deprecated in 1.4
-$.fn.fieldcontain = function(/* options */) {
-	return this.addClass( "ui-field-contain" );
-};
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.fn.grid = function( options ) {
-	return this.each(function() {
-
-		var $this = $( this ),
-			o = $.extend({
-				grid: null
-			}, options ),
-			$kids = $this.children(),
-			gridCols = { solo:1, a:2, b:3, c:4, d:5 },
-			grid = o.grid,
-			iterator,
-			letter;
-
-			if ( !grid ) {
-				if ( $kids.length <= 5 ) {
-					for ( letter in gridCols ) {
-						if ( gridCols[ letter ] === $kids.length ) {
-							grid = letter;
-						}
-					}
-				} else {
-					grid = "a";
-					$this.addClass( "ui-grid-duo" );
-				}
-			}
-			iterator = gridCols[grid];
-
-		$this.addClass( "ui-grid-" + grid );
-
-		$kids.filter( ":nth-child(" + iterator + "n+1)" ).addClass( "ui-block-a" );
-
-		if ( iterator > 1 ) {
-			$kids.filter( ":nth-child(" + iterator + "n+2)" ).addClass( "ui-block-b" );
-		}
-		if ( iterator > 2 ) {
-			$kids.filter( ":nth-child(" + iterator + "n+3)" ).addClass( "ui-block-c" );
-		}
-		if ( iterator > 3 ) {
-			$kids.filter( ":nth-child(" + iterator + "n+4)" ).addClass( "ui-block-d" );
-		}
-		if ( iterator > 4 ) {
-			$kids.filter( ":nth-child(" + iterator + "n+5)" ).addClass( "ui-block-e" );
-		}
-	});
-};
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.widget( "mobile.navbar", {
-	options: {
-		iconpos: "top",
-		grid: null
-	},
-
-	_create: function() {
-
-		var $navbar = this.element,
-			$navbtns = $navbar.find( "a" ),
-			iconpos = $navbtns.filter( ":jqmData(icon)" ).length ? this.options.iconpos : undefined;
-
-		$navbar.addClass( "ui-navbar" )
-			.attr( "role", "navigation" )
-			.find( "ul" )
-			.jqmEnhanceable()
-			.grid({ grid: this.options.grid });
-
-		$navbtns
-			.each( function() {
-				var icon = $.mobile.getAttribute( this, "icon" ),
-					theme = $.mobile.getAttribute( this, "theme" ),
-					classes = "ui-btn";
-
-				if ( theme ) {
-					classes += " ui-btn-" + theme;
-				}
-				if ( icon ) {
-					classes += " ui-icon-" + icon + " ui-btn-icon-" + iconpos;
-				}
-				$( this ).addClass( classes );
-			});
-
-		$navbar.delegate( "a", "vclick", function( /* event */ ) {
-			var activeBtn = $( this );
-
-			if ( !( activeBtn.hasClass( "ui-state-disabled" ) ||
-
-				// DEPRECATED as of 1.4.0 - remove after 1.4.0 release
-				// only ui-state-disabled should be present thereafter
-				activeBtn.hasClass( "ui-disabled" ) ||
-				activeBtn.hasClass( $.mobile.activeBtnClass ) ) ) {
-
-				$navbtns.removeClass( $.mobile.activeBtnClass );
-				activeBtn.addClass( $.mobile.activeBtnClass );
-
-				// The code below is a workaround to fix #1181
-				$( document ).one( "pagehide", function() {
-					activeBtn.removeClass( $.mobile.activeBtnClass );
-				});
-			}
-		});
-
-		// Buttons in the navbar with ui-state-persist class should regain their active state before page show
-		$navbar.closest( ".ui-page" ).bind( "pagebeforeshow", function() {
-			$navbtns.filter( ".ui-state-persist" ).addClass( $.mobile.activeBtnClass );
-		});
-	}
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-var getAttr = $.mobile.getAttribute;
-
-$.widget( "mobile.listview", $.extend( {
-
-	options: {
-		theme: null,
-		countTheme: null, /* Deprecated in 1.4 */
-		dividerTheme: null,
-		icon: "carat-r",
-		splitIcon: "carat-r",
-		splitTheme: null,
-		corners: true,
-		shadow: true,
-		inset: false
-	},
-
-	_create: function() {
-		var t = this,
-			listviewClasses = "";
-
-		listviewClasses += t.options.inset ? " ui-listview-inset" : "";
-
-		if ( !!t.options.inset ) {
-			listviewClasses += t.options.corners ? " ui-corner-all" : "";
-			listviewClasses += t.options.shadow ? " ui-shadow" : "";
-		}
-
-		// create listview markup
-		t.element.addClass( " ui-listview" + listviewClasses );
-
-		t.refresh( true );
-	},
-
-	// TODO: Remove in 1.5
-	_findFirstElementByTagName: function( ele, nextProp, lcName, ucName ) {
-		var dict = {};
-		dict[ lcName ] = dict[ ucName ] = true;
-		while ( ele ) {
-			if ( dict[ ele.nodeName ] ) {
-				return ele;
-			}
-			ele = ele[ nextProp ];
-		}
-		return null;
-	},
-	// TODO: Remove in 1.5
-	_addThumbClasses: function( containers ) {
-		var i, img, len = containers.length;
-		for ( i = 0; i < len; i++ ) {
-			img = $( this._findFirstElementByTagName( containers[ i ].firstChild, "nextSibling", "img", "IMG" ) );
-			if ( img.length ) {
-				$( this._findFirstElementByTagName( img[ 0 ].parentNode, "parentNode", "li", "LI" ) ).addClass( img.hasClass( "ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );
-			}
-		}
-	},
-
-	_getChildrenByTagName: function( ele, lcName, ucName ) {
-		var results = [],
-			dict = {};
-		dict[ lcName ] = dict[ ucName ] = true;
-		ele = ele.firstChild;
-		while ( ele ) {
-			if ( dict[ ele.nodeName ] ) {
-				results.push( ele );
-			}
-			ele = ele.nextSibling;
-		}
-		return $( results );
-	},
-
-	_beforeListviewRefresh: $.noop,
-	_afterListviewRefresh: $.noop,
-
-	refresh: function( create ) {
-		var buttonClass, pos, numli, item, itemClass, itemTheme, itemIcon, icon, a,
-			isDivider, startCount, newStartCount, value, last, splittheme, splitThemeClass, spliticon,
-			altButtonClass, dividerTheme, li,
-			o = this.options,
-			$list = this.element,
-			ol = !!$.nodeName( $list[ 0 ], "ol" ),
-			start = $list.attr( "start" ),
-			itemClassDict = {},
-			countBubbles = $list.find( ".ui-li-count" ),
-			countTheme = getAttr( $list[ 0 ], "counttheme" ) || this.options.countTheme,
-			countThemeClass = countTheme ? "ui-body-" + countTheme : "ui-body-inherit";
-
-		if ( o.theme ) {
-			$list.addClass( "ui-group-theme-" + o.theme );
-		}
-
-		// Check if a start attribute has been set while taking a value of 0 into account
-		if ( ol && ( start || start === 0 ) ) {
-			startCount = parseInt( start, 10 ) - 1;
-			$list.css( "counter-reset", "listnumbering " + startCount );
-		}
-
-		this._beforeListviewRefresh();
-
-		li = this._getChildrenByTagName( $list[ 0 ], "li", "LI" );
-
-		for ( pos = 0, numli = li.length; pos < numli; pos++ ) {
-			item = li.eq( pos );
-			itemClass = "";
-
-			if ( create || item[ 0 ].className.search( /\bui-li-static\b|\bui-li-divider\b/ ) < 0 ) {
-				a = this._getChildrenByTagName( item[ 0 ], "a", "A" );
-				isDivider = ( getAttr( item[ 0 ], "role" ) === "list-divider" );
-				value = item.attr( "value" );
-				itemTheme = getAttr( item[ 0 ], "theme" );
-
-				if ( a.length && a[ 0 ].className.search( /\bui-btn\b/ ) < 0 && !isDivider ) {
-					itemIcon = getAttr( item[ 0 ], "icon" );
-					icon = ( itemIcon === false ) ? false : ( itemIcon || o.icon );
-
-					// TODO: Remove in 1.5 together with links.js (links.js / .ui-link deprecated in 1.4)
-					a.removeClass( "ui-link" );
-
-					buttonClass = "ui-btn";
-
-					if ( itemTheme ) {
-						buttonClass += " ui-btn-" + itemTheme;
-					}
-
-					if ( a.length > 1 ) {
-						itemClass = "ui-li-has-alt";
-
-						last = a.last();
-						splittheme = getAttr( last[ 0 ], "theme" ) || o.splitTheme || getAttr( item[ 0 ], "theme", true );
-						splitThemeClass = splittheme ? " ui-btn-" + splittheme : "";
-						spliticon = getAttr( last[ 0 ], "icon" ) || getAttr( item[ 0 ], "icon" ) || o.splitIcon;
-						altButtonClass = "ui-btn ui-btn-icon-notext ui-icon-" + spliticon + splitThemeClass;
-
-						last
-							.attr( "title", $.trim( last.getEncodedText() ) )
-							.addClass( altButtonClass )
-							.empty();
-					} else if ( icon ) {
-						buttonClass += " ui-btn-icon-right ui-icon-" + icon;
-					}
-
-					a.first().addClass( buttonClass );
-				} else if ( isDivider ) {
-					dividerTheme = ( getAttr( item[ 0 ], "theme" ) || o.dividerTheme || o.theme );
-
-					itemClass = "ui-li-divider ui-bar-" + ( dividerTheme ? dividerTheme : "inherit" );
-
-					item.attr( "role", "heading" );
-				} else if ( a.length <= 0 ) {
-					itemClass = "ui-li-static ui-body-" + ( itemTheme ? itemTheme : "inherit" );
-				}
-				if ( ol && value ) {
-					newStartCount = parseInt( value , 10 ) - 1;
-
-					item.css( "counter-reset", "listnumbering " + newStartCount );
-				}
-			}
-
-			// Instead of setting item class directly on the list item
-			// at this point in time, push the item into a dictionary
-			// that tells us what class to set on it so we can do this after this
-			// processing loop is finished.
-
-			if ( !itemClassDict[ itemClass ] ) {
-				itemClassDict[ itemClass ] = [];
-			}
-
-			itemClassDict[ itemClass ].push( item[ 0 ] );
-		}
-
-		// Set the appropriate listview item classes on each list item.
-		// The main reason we didn't do this
-		// in the for-loop above is because we can eliminate per-item function overhead
-		// by calling addClass() and children() once or twice afterwards. This
-		// can give us a significant boost on platforms like WP7.5.
-
-		for ( itemClass in itemClassDict ) {
-			$( itemClassDict[ itemClass ] ).addClass( itemClass );
-		}
-
-		countBubbles.each( function() {
-			$( this ).closest( "li" ).addClass( "ui-li-has-count" );
-		});
-		if ( countThemeClass ) {
-			countBubbles.addClass( countThemeClass );
-		}
-
-		// Deprecated in 1.4. From 1.5 you have to add class ui-li-has-thumb or ui-li-has-icon to the LI.
-		this._addThumbClasses( li );
-		this._addThumbClasses( li.find( ".ui-btn" ) );
-
-		this._afterListviewRefresh();
-
-		this._addFirstLastClasses( li, this._getVisibles( li, create ), create );
-	}
-}, $.mobile.behaviors.addFirstLastClasses ) );
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-function defaultAutodividersSelector( elt ) {
-	// look for the text in the given element
-	var text = $.trim( elt.text() ) || null;
-
-	if ( !text ) {
-		return null;
-	}
-
-	// create the text for the divider (first uppercased letter)
-	text = text.slice( 0, 1 ).toUpperCase();
-
-	return text;
-}
-
-$.widget( "mobile.listview", $.mobile.listview, {
-	options: {
-		autodividers: false,
-		autodividersSelector: defaultAutodividersSelector
-	},
-
-	_beforeListviewRefresh: function() {
-		if ( this.options.autodividers ) {
-			this._replaceDividers();
-			this._superApply( arguments );
-		}
-	},
-
-	_replaceDividers: function() {
-		var i, lis, li, dividerText,
-			lastDividerText = null,
-			list = this.element,
-			divider;
-
-		list.children( "li:jqmData(role='list-divider')" ).remove();
-
-		lis = list.children( "li" );
-
-		for ( i = 0; i < lis.length ; i++ ) {
-			li = lis[ i ];
-			dividerText = this.options.autodividersSelector( $( li ) );
-
-			if ( dividerText && lastDividerText !== dividerText ) {
-				divider = document.createElement( "li" );
-				divider.appendChild( document.createTextNode( dividerText ) );
-				divider.setAttribute( "data-" + $.mobile.ns + "role", "list-divider" );
-				li.parentNode.insertBefore( divider, li );
-			}
-
-			lastDividerText = dividerText;
-		}
-	}
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-var rdivider = /(^|\s)ui-li-divider($|\s)/,
-	rhidden = /(^|\s)ui-screen-hidden($|\s)/;
-
-$.widget( "mobile.listview", $.mobile.listview, {
-	options: {
-		hideDividers: false
-	},
-
-	_afterListviewRefresh: function() {
-		var items, idx, item, hideDivider = true;
-
-		this._superApply( arguments );
-
-		if ( this.options.hideDividers ) {
-			items = this._getChildrenByTagName( this.element[ 0 ], "li", "LI" );
-			for ( idx = items.length - 1 ; idx > -1 ; idx-- ) {
-				item = items[ idx ];
-				if ( item.className.match( rdivider ) ) {
-					if ( hideDivider ) {
-						item.className = item.className + " ui-screen-hidden";
-					}
-					hideDivider = true;
-				} else {
-					if ( !item.className.match( rhidden ) ) {
-						hideDivider = false;
-					}
-				}
-			}
-		}
-	}
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.mobile.nojs = function( target ) {
-	$( ":jqmData(role='nojs')", target ).addClass( "ui-nojs" );
-};
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.mobile.behaviors.formReset = {
-	_handleFormReset: function() {
-		this._on( this.element.closest( "form" ), {
-			reset: function() {
-				this._delay( "_reset" );
-			}
-		});
-	}
-};
-
-})( jQuery );
-
-/*
-* "checkboxradio" plugin
-*/
-
-(function( $, undefined ) {
-
-var escapeId = $.mobile.path.hashToSelector;
-
-$.widget( "mobile.checkboxradio", $.extend( {
-
-	initSelector: "input:not( :jqmData(role='flipswitch' ) )[type='checkbox'],input[type='radio']:not( :jqmData(role='flipswitch' ))",
-
-	options: {
-		theme: "inherit",
-		mini: false,
-		wrapperClass: null,
-		enhanced: false,
-		iconpos: "left"
-
-	},
-	_create: function() {
-		var input = this.element,
-			o = this.options,
-			inheritAttr = function( input, dataAttr ) {
-				return input.jqmData( dataAttr ) ||
-					input.closest( "form, fieldset" ).jqmData( dataAttr );
-			},
-			// NOTE: Windows Phone could not find the label through a selector
-			// filter works though.
-			parentLabel = input.closest( "label" ),
-			label = parentLabel.length ? parentLabel :
-				input
-					.closest( "form, fieldset, :jqmData(role='page'), :jqmData(role='dialog')" )
-					.find( "label" )
-					.filter( "[for='" + escapeId( input[0].id ) + "']" )
-					.first(),
-			inputtype = input[0].type,
-			checkedClass = "ui-" + inputtype + "-on",
-			uncheckedClass = "ui-" + inputtype + "-off";
-
-		if ( inputtype !== "checkbox" && inputtype !== "radio" ) {
-			return;
-		}
-
-		if ( this.element[0].disabled ) {
-			this.options.disabled = true;
-		}
-
-		o.iconpos = inheritAttr( input, "iconpos" ) || label.attr( "data-" + $.mobile.ns + "iconpos" ) || o.iconpos,
-
-		// Establish options
-		o.mini = inheritAttr( input, "mini" ) || o.mini;
-
-		// Expose for other methods
-		$.extend( this, {
-			input: input,
-			label: label,
-			parentLabel: parentLabel,
-			inputtype: inputtype,
-			checkedClass: checkedClass,
-			uncheckedClass: uncheckedClass
-		});
-
-		if ( !this.options.enhanced ) {
-			this._enhance();
-		}
-
-		this._on( label, {
-			vmouseover: "_handleLabelVMouseOver",
-			vclick: "_handleLabelVClick"
-		});
-
-		this._on( input, {
-			vmousedown: "_cacheVals",
-			vclick: "_handleInputVClick",
-			focus: "_handleInputFocus",
-			blur: "_handleInputBlur"
-		});
-
-		this._handleFormReset();
-		this.refresh();
-	},
-
-	_enhance: function() {
-		this.label.addClass( "ui-btn ui-corner-all");
-
-		if ( this.parentLabel.length > 0 ) {
-			this.input.add( this.label ).wrapAll( this._wrapper() );
-		} else {
-			//this.element.replaceWith( this.input.add( this.label ).wrapAll( this._wrapper() ) );
-			this.element.wrap( this._wrapper() );
-			this.element.parent().prepend( this.label );
-		}
-
-		// Wrap the input + label in a div
-
-		this._setOptions({
-			"theme": this.options.theme,
-			"iconpos": this.options.iconpos,
-			"mini": this.options.mini
-		});
-
-	},
-
-	_wrapper: function() {
-		return $( "<div class='"  +
-			( this.options.wrapperClass ? this.options.wrapperClass : "" ) +
-			" ui-" + this.inputtype +
-			( this.options.disabled ? " ui-state-disabled" : "" ) + "' ></div>" );
-	},
-
-	_handleInputFocus: function() {
-		this.label.addClass( $.mobile.focusClass );
-	},
-
-	_handleInputBlur: function() {
-		this.label.removeClass( $.mobile.focusClass );
-	},
-
-	_handleInputVClick: function() {
-		// Adds checked attribute to checked input when keyboard is used
-		this.element.prop( "checked", this.element.is( ":checked" ) );
-		this._getInputSet().not( this.element ).prop( "checked", false );
-		this._updateAll();
-	},
-
-	_handleLabelVMouseOver: function( event ) {
-		if ( this.label.parent().hasClass( "ui-state-disabled" ) ) {
-			event.stopPropagation();
-		}
-	},
-
-	_handleLabelVClick: function( event ) {
-		var input = this.element;
-
-		if ( input.is( ":disabled" ) ) {
-			event.preventDefault();
-			return;
-		}
-
-		this._cacheVals();
-
-		input.prop( "checked", this.inputtype === "radio" && true || !input.prop( "checked" ) );
-
-		// trigger click handler's bound directly to the input as a substitute for
-		// how label clicks behave normally in the browsers
-		// TODO: it would be nice to let the browser's handle the clicks and pass them
-		//       through to the associate input. we can swallow that click at the parent
-		//       wrapper element level
-		input.triggerHandler( "click" );
-
-		// Input set for common radio buttons will contain all the radio
-		// buttons, but will not for checkboxes. clearing the checked status
-		// of other radios ensures the active button state is applied properly
-		this._getInputSet().not( input ).prop( "checked", false );
-
-		this._updateAll();
-		return false;
-	},
-
-	_cacheVals: function() {
-		this._getInputSet().each( function() {
-			$( this ).attr("data-" + $.mobile.ns + "cacheVal", this.checked );
-		});
-	},
-
-	// Returns those radio buttons that are supposed to be in the same group as
-	// this radio button. In the case of a checkbox or a radio lacking a name
-	// attribute, it returns this.element.
-	_getInputSet: function() {
-		var selector, formId,
-			radio = this.element[ 0 ],
-			name = radio.name,
-			form = radio.form,
-			doc = this.element.parents().last().get( 0 ),
-
-			// A radio is always a member of its own group
-			radios = this.element;
-
-		// Only start running selectors if this is an attached radio button with a name
-		if ( name && this.inputtype === "radio" && doc ) {
-			selector = "input[type='radio'][name='" + escapeId( name ) + "']";
-
-			// If we're inside a form
-			if ( form ) {
-				formId = form.id;
-
-				// If the form has an ID, collect radios scattered throught the document which
-				// nevertheless are part of the form by way of the value of their form attribute
-				if ( formId ) {
-					radios = $( selector + "[form='" + escapeId( formId ) + "']", doc );
-				}
-
-				// Also add to those the radios in the form itself
-				radios = $( form ).find( selector ).filter( function() {
-
-					// Some radios inside the form may belong to some other form by virtue of
-					// having a form attribute defined on them, so we must filter them out here
-					return ( this.form === form );
-				}).add( radios );
-
-			// If we're outside a form
-			} else {
-
-				// Collect all those radios which are also outside of a form and match our name
-				radios = $( selector, doc ).filter( function() {
-					return !this.form;
-				});
-			}
-		}
-		return radios;
-	},
-
-	_updateAll: function() {
-		var self = this;
-
-		this._getInputSet().each( function() {
-			var $this = $( this );
-
-			if ( this.checked || self.inputtype === "checkbox" ) {
-				$this.trigger( "change" );
-			}
-		})
-		.checkboxradio( "refresh" );
-	},
-
-	_reset: function() {
-		this.refresh();
-	},
-
-	// Is the widget supposed to display an icon?
-	_hasIcon: function() {
-		var controlgroup, controlgroupWidget,
-			controlgroupConstructor = $.mobile.controlgroup;
-
-		// If the controlgroup widget is defined ...
-		if ( controlgroupConstructor ) {
-			controlgroup = this.element.closest(
-				":mobile-controlgroup," +
-				controlgroupConstructor.prototype.initSelector );
-
-			// ... and the checkbox is in a controlgroup ...
-			if ( controlgroup.length > 0 ) {
-
-				// ... look for a controlgroup widget instance, and ...
-				controlgroupWidget = $.data( controlgroup[ 0 ], "mobile-controlgroup" );
-
-				// ... if found, decide based on the option value, ...
-				return ( ( controlgroupWidget ? controlgroupWidget.options.type :
-
-					// ... otherwise decide based on the "type" data attribute.
-					controlgroup.attr( "data-" + $.mobile.ns + "type" ) ) !== "horizontal" );
-			}
-		}
-
-		// Normally, the widget displays an icon.
-		return true;
-	},
-
-	refresh: function() {
-		var hasIcon = this._hasIcon(),
-			isChecked = this.element[ 0 ].checked,
-			active = $.mobile.activeBtnClass,
-			iconposClass = "ui-btn-icon-" + this.options.iconpos,
-			addClasses = [],
-			removeClasses = [];
-
-		if ( hasIcon ) {
-			removeClasses.push( active );
-			addClasses.push( iconposClass );
-		} else {
-			removeClasses.push( iconposClass );
-			( isChecked ? addClasses : removeClasses ).push( active );
-		}
-
-		if ( isChecked ) {
-			addClasses.push( this.checkedClass );
-			removeClasses.push( this.uncheckedClass );
-		} else {
-			addClasses.push( this.uncheckedClass );
-			removeClasses.push( this.checkedClass );
-		}
-
-		this.label
-			.addClass( addClasses.join( " " ) )
-			.removeClass( removeClasses.join( " " ) );
-	},
-
-	widget: function() {
-		return this.label.parent();
-	},
-
-	_setOptions: function( options ) {
-		var label = this.label,
-			currentOptions = this.options,
-			outer = this.widget(),
-			hasIcon = this._hasIcon();
-
-		if ( options.disabled !== undefined ) {
-			this.input.prop( "disabled", !!options.disabled );
-			outer.toggleClass( "ui-state-disabled", !!options.disabled );
-		}
-		if ( options.mini !== undefined ) {
-			outer.toggleClass( "ui-mini", !!options.mini );
-		}
-		if ( options.theme !== undefined ) {
-			label
-				.removeClass( "ui-btn-" + currentOptions.theme )
-				.addClass( "ui-btn-" + options.theme );
-		}
-		if ( options.wrapperClass !== undefined ) {
-			outer
-				.removeClass( currentOptions.wrapperClass )
-				.addClass( options.wrapperClass );
-		}
-		if ( options.iconpos !== undefined && hasIcon ) {
-			label.removeClass( "ui-btn-icon-" + currentOptions.iconpos ).addClass( "ui-btn-icon-" + options.iconpos );
-		} else if ( !hasIcon ) {
-			label.removeClass( "ui-btn-icon-" + currentOptions.iconpos );
-		}
-		this._super( options );
-	}
-
-}, $.mobile.behaviors.formReset ) );
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.widget( "mobile.button", {
-
-	initSelector: "input[type='button'], input[type='submit'], input[type='reset']",
-
-	options: {
-		theme: null,
-		icon: null,
-		iconpos: "left",
-		iconshadow: false, /* TODO: Deprecated in 1.4, remove in 1.5. */
-		corners: true,
-		shadow: true,
-		inline: null,
-		mini: null,
-		wrapperClass: null,
-		enhanced: false
-	},
-
-	_create: function() {
-
-		if ( this.element.is( ":disabled" ) ) {
-			this.options.disabled = true;
-		}
-
-		if ( !this.options.enhanced ) {
-			this._enhance();
-		}
-
-		$.extend( this, {
-			wrapper: this.element.parent()
-		});
-
-		this._on( {
-			focus: function() {
-				this.widget().addClass( $.mobile.focusClass );
-			},
-
-			blur: function() {
-				this.widget().removeClass( $.mobile.focusClass );
-			}
-		});
-
-		this.refresh( true );
-	},
-
-	_enhance: function() {
-		this.element.wrap( this._button() );
-	},
-
-	_button: function() {
-		var options = this.options,
-			iconClasses = this._getIconClasses( this.options );
-
-		return $("<div class='ui-btn ui-input-btn" +
-			( options.wrapperClass ? " " + options.wrapperClass : "" ) +
-			( options.theme ? " ui-btn-" + options.theme : "" ) +
-			( options.corners ? " ui-corner-all" : "" ) +
-			( options.shadow ? " ui-shadow" : "" ) +
-			( options.inline ? " ui-btn-inline" : "" ) +
-			( options.mini ? " ui-mini" : "" ) +
-			( options.disabled ? " ui-state-disabled" : "" ) +
-			( iconClasses ? ( " " + iconClasses ) : "" ) +
-			"' >" + this.element.val() + "</div>" );
-	},
-
-	widget: function() {
-		return this.wrapper;
-	},
-
-	_destroy: function() {
-			this.element.insertBefore( this.button );
-			this.button.remove();
-	},
-
-	_getIconClasses: function( options ) {
-		return ( options.icon ? ( "ui-icon-" + options.icon +
-			( options.iconshadow ? " ui-shadow-icon" : "" ) + /* TODO: Deprecated in 1.4, remove in 1.5. */
-			" ui-btn-icon-" + options.iconpos ) : "" );
-	},
-
-	_setOptions: function( options ) {
-		var outer = this.widget();
-
-		if ( options.theme !== undefined ) {
-			outer
-				.removeClass( this.options.theme )
-				.addClass( "ui-btn-" + options.theme );
-		}
-		if ( options.corners !== undefined ) {
-			outer.toggleClass( "ui-corner-all", options.corners );
-		}
-		if ( options.shadow !== undefined ) {
-			outer.toggleClass( "ui-shadow", options.shadow );
-		}
-		if ( options.inline !== undefined ) {
-			outer.toggleClass( "ui-btn-inline", options.inline );
-		}
-		if ( options.mini !== undefined ) {
-			outer.toggleClass( "ui-mini", options.mini );
-		}
-		if ( options.disabled !== undefined ) {
-			this.element.prop( "disabled", options.disabled );
-			outer.toggleClass( "ui-state-disabled", options.disabled );
-		}
-
-		if ( options.icon !== undefined ||
-				options.iconshadow !== undefined || /* TODO: Deprecated in 1.4, remove in 1.5. */
-				options.iconpos !== undefined ) {
-			outer
-				.removeClass( this._getIconClasses( this.options ) )
-				.addClass( this._getIconClasses(
-					$.extend( {}, this.options, options ) ) );
-		}
-
-		this._super( options );
-	},
-
-	refresh: function( create ) {
-		var originalElement,
-			isDisabled = this.element.prop( "disabled" );
-
-		if ( this.options.icon && this.options.iconpos === "notext" && this.element.attr( "title" ) ) {
-			this.element.attr( "title", this.element.val() );
-		}
-		if ( !create ) {
-			originalElement = this.element.detach();
-			$( this.wrapper ).text( this.element.val() ).append( originalElement );
-		}
-		if ( this.options.disabled !== isDisabled ) {
-			this._setOptions({ disabled: isDisabled });
-		}
-	}
-});
-
-})( jQuery );
-
-(function( $ ) {
-	var	meta = $( "meta[name=viewport]" ),
-		initialContent = meta.attr( "content" ),
-		disabledZoom = initialContent + ",maximum-scale=1, user-scalable=no",
-		enabledZoom = initialContent + ",maximum-scale=10, user-scalable=yes",
-		disabledInitially = /(user-scalable[\s]*=[\s]*no)|(maximum-scale[\s]*=[\s]*1)[$,\s]/.test( initialContent );
-
-	$.mobile.zoom = $.extend( {}, {
-		enabled: !disabledInitially,
-		locked: false,
-		disable: function( lock ) {
-			if ( !disabledInitially && !$.mobile.zoom.locked ) {
-				meta.attr( "content", disabledZoom );
-				$.mobile.zoom.enabled = false;
-				$.mobile.zoom.locked = lock || false;
-			}
-		},
-		enable: function( unlock ) {
-			if ( !disabledInitially && ( !$.mobile.zoom.locked || unlock === true ) ) {
-				meta.attr( "content", enabledZoom );
-				$.mobile.zoom.enabled = true;
-				$.mobile.zoom.locked = false;
-			}
-		},
-		restore: function() {
-			if ( !disabledInitially ) {
-				meta.attr( "content", initialContent );
-				$.mobile.zoom.enabled = true;
-			}
-		}
-	});
-
-}( jQuery ));
-
-(function( $, undefined ) {
-
-$.widget( "mobile.textinput", {
-	initSelector: "input[type='text']," +
-		"input[type='search']," +
-		":jqmData(type='search')," +
-		"input[type='number']," +
-		":jqmData(type='number')," +
-		"input[type='password']," +
-		"input[type='email']," +
-		"input[type='url']," +
-		"input[type='tel']," +
-		"textarea," +
-		"input[type='time']," +
-		"input[type='date']," +
-		"input[type='month']," +
-		"input[type='week']," +
-		"input[type='datetime']," +
-		"input[type='datetime-local']," +
-		"input[type='color']," +
-		"input:not([type])," +
-		"input[type='file']",
-
-	options: {
-		theme: null,
-		corners: true,
-		mini: false,
-		// This option defaults to true on iOS devices.
-		preventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( "AppleWebKit" ) > -1,
-		wrapperClass: "",
-		enhanced: false
-	},
-
-	_create: function() {
-
-		var options = this.options,
-			isSearch = this.element.is( "[type='search'], :jqmData(type='search')" ),
-			isTextarea = this.element[ 0 ].tagName === "TEXTAREA",
-			isRange = this.element.is( "[data-" + ( $.mobile.ns || "" ) + "type='range']" ),
-			inputNeedsWrap = ( (this.element.is( "input" ) ||
-				this.element.is( "[data-" + ( $.mobile.ns || "" ) + "type='search']" ) ) &&
-					!isRange );
-
-		if ( this.element.prop( "disabled" ) ) {
-			options.disabled = true;
-		}
-
-		$.extend( this, {
-			classes: this._classesFromOptions(),
-			isSearch: isSearch,
-			isTextarea: isTextarea,
-			isRange: isRange,
-			inputNeedsWrap: inputNeedsWrap
-		});
-
-		this._autoCorrect();
-
-		if ( !options.enhanced ) {
-			this._enhance();
-		}
-
-		this._on( {
-			"focus": "_handleFocus",
-			"blur": "_handleBlur"
-		});
-
-	},
-
-	refresh: function() {
-		this.setOptions({
-			"disabled" : this.element.is( ":disabled" )
-		});
-	},
-
-	_enhance: function() {
-		var elementClasses = [];
-
-		if ( this.isTextarea ) {
-			elementClasses.push( "ui-input-text" );
-		}
-
-		if ( this.isTextarea || this.isRange ) {
-			elementClasses.push( "ui-shadow-inset" );
-		}
-
-		//"search" and "text" input widgets
-		if ( this.inputNeedsWrap ) {
-			this.element.wrap( this._wrap() );
-		} else {
-			elementClasses = elementClasses.concat( this.classes );
-		}
-
-		this.element.addClass( elementClasses.join( " " ) );
-	},
-
-	widget: function() {
-		return ( this.inputNeedsWrap ) ? this.element.parent() : this.element;
-	},
-
-	_classesFromOptions: function() {
-		var options = this.options,
-			classes = [];
-
-		classes.push( "ui-body-" + ( ( options.theme === null ) ? "inherit" : options.theme ) );
-		if ( options.corners ) {
-			classes.push( "ui-corner-all" );
-		}
-		if ( options.mini ) {
-			classes.push( "ui-mini" );
-		}
-		if ( options.disabled ) {
-			classes.push( "ui-state-disabled" );
-		}
-		if ( options.wrapperClass ) {
-			classes.push( options.wrapperClass );
-		}
-
-		return classes;
-	},
-
-	_wrap: function() {
-		return $( "<div class='" +
-			( this.isSearch ? "ui-input-search " : "ui-input-text " ) +
-			this.classes.join( " " ) + " " +
-			"ui-shadow-inset'></div>" );
-	},
-
-	_autoCorrect: function() {
-		// XXX: Temporary workaround for issue 785 (Apple bug 8910589).
-		//      Turn off autocorrect and autocomplete on non-iOS 5 devices
-		//      since the popup they use can't be dismissed by the user. Note
-		//      that we test for the presence of the feature by looking for
-		//      the autocorrect property on the input element. We currently
-		//      have no test for iOS 5 or newer so we're temporarily using
-		//      the touchOverflow support flag for jQM 1.0. Yes, I feel dirty.
-		//      - jblas
-		if ( typeof this.element[0].autocorrect !== "undefined" &&
-			!$.support.touchOverflow ) {
-
-			// Set the attribute instead of the property just in case there
-			// is code that attempts to make modifications via HTML.
-			this.element[0].setAttribute( "autocorrect", "off" );
-			this.element[0].setAttribute( "autocomplete", "off" );
-		}
-	},
-
-	_handleBlur: function() {
-		this.widget().removeClass( $.mobile.focusClass );
-		if ( this.options.preventFocusZoom ) {
-			$.mobile.zoom.enable( true );
-		}
-	},
-
-	_handleFocus: function() {
-		// In many situations, iOS will zoom into the input upon tap, this
-		// prevents that from happening
-		if ( this.options.preventFocusZoom ) {
-			$.mobile.zoom.disable( true );
-		}
-		this.widget().addClass( $.mobile.focusClass );
-	},
-
-	_setOptions: function ( options ) {
-		var outer = this.widget();
-
-		this._super( options );
-
-		if ( !( options.disabled === undefined &&
-			options.mini === undefined &&
-			options.corners === undefined &&
-			options.theme === undefined &&
-			options.wrapperClass === undefined ) ) {
-
-			outer.removeClass( this.classes.join( " " ) );
-			this.classes = this._classesFromOptions();
-			outer.addClass( this.classes.join( " " ) );
-		}
-
-		if ( options.disabled !== undefined ) {
-			this.element.prop( "disabled", !!options.disabled );
-		}
-	},
-
-	_destroy: function() {
-		if ( this.options.enhanced ) {
-			return;
-		}
-		if ( this.inputNeedsWrap ) {
-			this.element.unwrap();
-		}
-		this.element.removeClass( "ui-input-text " + this.classes.join( " " ) );
-	}
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.widget( "mobile.slider", $.extend( {
-	initSelector: "input[type='range'], :jqmData(type='range'), :jqmData(role='slider')",
-
-	widgetEventPrefix: "slide",
-
-	options: {
-		theme: null,
-		trackTheme: null,
-		corners: true,
-		mini: false,
-		highlight: false
-	},
-
-	_create: function() {
-
-		// TODO: Each of these should have comments explain what they're for
-		var self = this,
-			control = this.element,
-			trackTheme = this.options.trackTheme || $.mobile.getAttribute( control[ 0 ], "theme" ),
-			trackThemeClass = trackTheme ? " ui-bar-" + trackTheme : " ui-bar-inherit",
-			cornerClass = ( this.options.corners || control.jqmData( "corners" ) ) ? " ui-corner-all" : "",
-			miniClass = ( this.options.mini || control.jqmData( "mini" ) ) ? " ui-mini" : "",
-			cType = control[ 0 ].nodeName.toLowerCase(),
-			isToggleSwitch = ( cType === "select" ),
-			isRangeslider = control.parent().is( ":jqmData(role='rangeslider')" ),
-			selectClass = ( isToggleSwitch ) ? "ui-slider-switch" : "",
-			controlID = control.attr( "id" ),
-			$label = $( "[for='" + controlID + "']" ),
-			labelID = $label.attr( "id" ) || controlID + "-label",
-			min = !isToggleSwitch ? parseFloat( control.attr( "min" ) ) : 0,
-			max =  !isToggleSwitch ? parseFloat( control.attr( "max" ) ) : control.find( "option" ).length-1,
-			step = window.parseFloat( control.attr( "step" ) || 1 ),
-			domHandle = document.createElement( "a" ),
-			handle = $( domHandle ),
-			domSlider = document.createElement( "div" ),
-			slider = $( domSlider ),
-			valuebg = this.options.highlight && !isToggleSwitch ? (function() {
-				var bg = document.createElement( "div" );
-				bg.className = "ui-slider-bg " + $.mobile.activeBtnClass;
-				return $( bg ).prependTo( slider );
-			})() : false,
-			options,
-			wrapper,
-			j, length,
-			i, optionsCount, origTabIndex,
-			side, activeClass, sliderImg;
-
-		$label.attr( "id", labelID );
-		this.isToggleSwitch = isToggleSwitch;
-
-		domHandle.setAttribute( "href", "#" );
-		domSlider.setAttribute( "role", "application" );
-		domSlider.className = [ this.isToggleSwitch ? "ui-slider ui-slider-track ui-shadow-inset " : "ui-slider-track ui-shadow-inset ", selectClass, trackThemeClass, cornerClass, miniClass ].join( "" );
-		domHandle.className = "ui-slider-handle";
-		domSlider.appendChild( domHandle );
-
-		handle.attr({
-			"role": "slider",
-			"aria-valuemin": min,
-			"aria-valuemax": max,
-			"aria-valuenow": this._value(),
-			"aria-valuetext": this._value(),
-			"title": this._value(),
-			"aria-labelledby": labelID
-		});
-
-		$.extend( this, {
-			slider: slider,
-			handle: handle,
-			control: control,
-			type: cType,
-			step: step,
-			max: max,
-			min: min,
-			valuebg: valuebg,
-			isRangeslider: isRangeslider,
-			dragging: false,
-			beforeStart: null,
-			userModified: false,
-			mouseMoved: false
-		});
-
-		if ( isToggleSwitch ) {
-			// TODO: restore original tabindex (if any) in a destroy method
-			origTabIndex = control.attr( "tabindex" );
-			if ( origTabIndex ) {
-				handle.attr( "tabindex", origTabIndex );
-			}
-			control.attr( "tabindex", "-1" ).focus(function() {
-				$( this ).blur();
-				handle.focus();
-			});
-
-			wrapper = document.createElement( "div" );
-			wrapper.className = "ui-slider-inneroffset";
-
-			for ( j = 0, length = domSlider.childNodes.length; j < length; j++ ) {
-				wrapper.appendChild( domSlider.childNodes[j] );
-			}
-
-			domSlider.appendChild( wrapper );
-
-			// slider.wrapInner( "<div class='ui-slider-inneroffset'></div>" );
-
-			// make the handle move with a smooth transition
-			handle.addClass( "ui-slider-handle-snapping" );
-
-			options = control.find( "option" );
-
-			for ( i = 0, optionsCount = options.length; i < optionsCount; i++ ) {
-				side = !i ? "b" : "a";
-				activeClass = !i ? "" : " " + $.mobile.activeBtnClass;
-				sliderImg = document.createElement( "span" );
-
-				sliderImg.className = [ "ui-slider-label ui-slider-label-", side, activeClass ].join( "" );
-				sliderImg.setAttribute( "role", "img" );
-				sliderImg.appendChild( document.createTextNode( options[i].innerHTML ) );
-				$( sliderImg ).prependTo( slider );
-			}
-
-			self._labels = $( ".ui-slider-label", slider );
-
-		}
-
-		// monitor the input for updated values
-		control.addClass( isToggleSwitch ? "ui-slider-switch" : "ui-slider-input" );
-
-		this._on( control, {
-			"change": "_controlChange",
-			"keyup": "_controlKeyup",
-			"blur": "_controlBlur",
-			"vmouseup": "_controlVMouseUp"
-		});
-
-		slider.bind( "vmousedown", $.proxy( this._sliderVMouseDown, this ) )
-			.bind( "vclick", false );
-
-		// We have to instantiate a new function object for the unbind to work properly
-		// since the method itself is defined in the prototype (causing it to unbind everything)
-		this._on( document, { "vmousemove": "_preventDocumentDrag" });
-		this._on( slider.add( document ), { "vmouseup": "_sliderVMouseUp" });
-
-		slider.insertAfter( control );
-
-		// wrap in a div for styling purposes
-		if ( !isToggleSwitch && !isRangeslider ) {
-			wrapper = this.options.mini ? "<div class='ui-slider ui-mini'>" : "<div class='ui-slider'>";
-
-			control.add( slider ).wrapAll( wrapper );
-		}
-
-		// bind the handle event callbacks and set the context to the widget instance
-		this._on( this.handle, {
-			"vmousedown": "_handleVMouseDown",
-			"keydown": "_handleKeydown",
-			"keyup": "_handleKeyup"
-		});
-
-		this.handle.bind( "vclick", false );
-
-		this._handleFormReset();
-
-		this.refresh( undefined, undefined, true );
-	},
-
-	_setOptions: function( options ) {
-		if ( options.theme !== undefined ) {
-			this._setTheme( options.theme );
-		}
-
-		if ( options.trackTheme !== undefined ) {
-			this._setTrackTheme( options.trackTheme );
-		}
-
-		if ( options.corners !== undefined ) {
-			this._setCorners( options.corners );
-		}
-
-		if ( options.mini !== undefined ) {
-			this._setMini( options.mini );
-		}
-
-		if ( options.highlight !== undefined ) {
-			this._setHighlight( options.highlight );
-		}
-
-		if ( options.disabled !== undefined ) {
-			this._setDisabled( options.disabled );
-		}
-		this._super( options );
-	},
-
-	_controlChange: function( event ) {
-		// if the user dragged the handle, the "change" event was triggered from inside refresh(); don't call refresh() again
-		if ( this._trigger( "controlchange", event ) === false ) {
-			return false;
-		}
-		if ( !this.mouseMoved ) {
-			this.refresh( this._value(), true );
-		}
-	},
-
-	_controlKeyup: function(/* event */) { // necessary?
-		this.refresh( this._value(), true, true );
-	},
-
-	_controlBlur: function(/* event */) {
-		this.refresh( this._value(), true );
-	},
-
-	// it appears the clicking the up and down buttons in chrome on
-	// range/number inputs doesn't trigger a change until the field is
-	// blurred. Here we check thif the value has changed and refresh
-	_controlVMouseUp: function(/* event */) {
-		this._checkedRefresh();
-	},
-
-	// NOTE force focus on handle
-	_handleVMouseDown: function(/* event */) {
-		this.handle.focus();
-	},
-
-	_handleKeydown: function( event ) {
-		var index = this._value();
-		if ( this.options.disabled ) {
-			return;
-		}
-
-		// In all cases prevent the default and mark the handle as active
-		switch ( event.keyCode ) {
-			case $.mobile.keyCode.HOME:
-			case $.mobile.keyCode.END:
-			case $.mobile.keyCode.PAGE_UP:
-			case $.mobile.keyCode.PAGE_DOWN:
-			case $.mobile.keyCode.UP:
-			case $.mobile.keyCode.RIGHT:
-			case $.mobile.keyCode.DOWN:
-			case $.mobile.keyCode.LEFT:
-				event.preventDefault();
-
-				if ( !this._keySliding ) {
-					this._keySliding = true;
-					this.handle.addClass( "ui-state-active" ); /* TODO: We don't use this class for styling. Do we need to add it? */
-				}
-
-				break;
-		}
-
-		// move the slider according to the keypress
-		switch ( event.keyCode ) {
-			case $.mobile.keyCode.HOME:
-				this.refresh( this.min );
-				break;
-			case $.mobile.keyCode.END:
-				this.refresh( this.max );
-				break;
-			case $.mobile.keyCode.PAGE_UP:
-			case $.mobile.keyCode.UP:
-			case $.mobile.keyCode.RIGHT:
-				this.refresh( index + this.step );
-				break;
-			case $.mobile.keyCode.PAGE_DOWN:
-			case $.mobile.keyCode.DOWN:
-			case $.mobile.keyCode.LEFT:
-				this.refresh( index - this.step );
-				break;
-		}
-	}, // remove active mark
-
-	_handleKeyup: function(/* event */) {
-		if ( this._keySliding ) {
-			this._keySliding = false;
-			this.handle.removeClass( "ui-state-active" ); /* See comment above. */
-		}
-	},
-
-	_sliderVMouseDown: function( event ) {
-		// NOTE: we don't do this in refresh because we still want to
-		//       support programmatic alteration of disabled inputs
-		if ( this.options.disabled || !( event.which === 1 || event.which === 0 || event.which === undefined ) ) {
-			return false;
-		}
-		if ( this._trigger( "beforestart", event ) === false ) {
-			return false;
-		}
-		this.dragging = true;
-		this.userModified = false;
-		this.mouseMoved = false;
-
-		if ( this.isToggleSwitch ) {
-			this.beforeStart = this.element[0].selectedIndex;
-		}
-
-		this.refresh( event );
-		this._trigger( "start" );
-		return false;
-	},
-
-	_sliderVMouseUp: function() {
-		if ( this.dragging ) {
-			this.dragging = false;
-
-			if ( this.isToggleSwitch ) {
-				// make the handle move with a smooth transition
-				this.handle.addClass( "ui-slider-handle-snapping" );
-
-				if ( this.mouseMoved ) {
-					// this is a drag, change the value only if user dragged enough
-					if ( this.userModified ) {
-						this.refresh( this.beforeStart === 0 ? 1 : 0 );
-					} else {
-						this.refresh( this.beforeStart );
-					}
-				} else {
-					// this is just a click, change the value
-					this.refresh( this.beforeStart === 0 ? 1 : 0 );
-				}
-			}
-
-			this.mouseMoved = false;
-			this._trigger( "stop" );
-			return false;
-		}
-	},
-
-	_preventDocumentDrag: function( event ) {
-			// NOTE: we don't do this in refresh because we still want to
-			//       support programmatic alteration of disabled inputs
-			if ( this._trigger( "drag", event ) === false) {
-				return false;
-			}
-			if ( this.dragging && !this.options.disabled ) {
-
-				// this.mouseMoved must be updated before refresh() because it will be used in the control "change" event
-				this.mouseMoved = true;
-
-				if ( this.isToggleSwitch ) {
-					// make the handle move in sync with the mouse
-					this.handle.removeClass( "ui-slider-handle-snapping" );
-				}
-
-				this.refresh( event );
-
-				// only after refresh() you can calculate this.userModified
-				this.userModified = this.beforeStart !== this.element[0].selectedIndex;
-				return false;
-			}
-		},
-
-	_checkedRefresh: function() {
-		if ( this.value !== this._value() ) {
-			this.refresh( this._value() );
-		}
-	},
-
-	_value: function() {
-		return  this.isToggleSwitch ? this.element[0].selectedIndex : parseFloat( this.element.val() ) ;
-	},
-
-	_reset: function() {
-		this.refresh( undefined, false, true );
-	},
-
-	refresh: function( val, isfromControl, preventInputUpdate ) {
-		// NOTE: we don't return here because we want to support programmatic
-		//       alteration of the input value, which should still update the slider
-
-		var self = this,
-			parentTheme = $.mobile.getAttribute( this.element[ 0 ], "theme" ),
-			theme = this.options.theme || parentTheme,
-			themeClass =  theme ? " ui-btn-" + theme : "",
-			trackTheme = this.options.trackTheme || parentTheme,
-			trackThemeClass = trackTheme ? " ui-bar-" + trackTheme : " ui-bar-inherit",
-			cornerClass = this.options.corners ? " ui-corner-all" : "",
-			miniClass = this.options.mini ? " ui-mini" : "",
-			left, width, data, tol,
-			pxStep, percent,
-			control, isInput, optionElements, min, max, step,
-			newval, valModStep, alignValue, percentPerStep,
-			handlePercent, aPercent, bPercent,
-			valueChanged;
-
-		self.slider[0].className = [ this.isToggleSwitch ? "ui-slider ui-slider-switch ui-slider-track ui-shadow-inset" : "ui-slider-track ui-shadow-inset", trackThemeClass, cornerClass, miniClass ].join( "" );
-		if ( this.options.disabled || this.element.prop( "disabled" ) ) {
-			this.disable();
-		}
-
-		// set the stored value for comparison later
-		this.value = this._value();
-		if ( this.options.highlight && !this.isToggleSwitch && this.slider.find( ".ui-slider-bg" ).length === 0 ) {
-			this.valuebg = (function() {
-				var bg = document.createElement( "div" );
-				bg.className = "ui-slider-bg " + $.mobile.activeBtnClass;
-				return $( bg ).prependTo( self.slider );
-			})();
-		}
-		this.handle.addClass( "ui-btn" + themeClass + " ui-shadow" );
-
-		control = this.element;
-		isInput = !this.isToggleSwitch;
-		optionElements = isInput ? [] : control.find( "option" );
-		min =  isInput ? parseFloat( control.attr( "min" ) ) : 0;
-		max = isInput ? parseFloat( control.attr( "max" ) ) : optionElements.length - 1;
-		step = ( isInput && parseFloat( control.attr( "step" ) ) > 0 ) ? parseFloat( control.attr( "step" ) ) : 1;
-
-		if ( typeof val === "object" ) {
-			data = val;
-			// a slight tolerance helped get to the ends of the slider
-			tol = 8;
-
-			left = this.slider.offset().left;
-			width = this.slider.width();
-			pxStep = width/((max-min)/step);
-			if ( !this.dragging ||
-					data.pageX < left - tol ||
-					data.pageX > left + width + tol ) {
-				return;
-			}
-			if ( pxStep > 1 ) {
-				percent = ( ( data.pageX - left ) / width ) * 100;
-			} else {
-				percent = Math.round( ( ( data.pageX - left ) / width ) * 100 );
-			}
-		} else {
-			if ( val == null ) {
-				val = isInput ? parseFloat( control.val() || 0 ) : control[0].selectedIndex;
-			}
-			percent = ( parseFloat( val ) - min ) / ( max - min ) * 100;
-		}
-
-		if ( isNaN( percent ) ) {
-			return;
-		}
-
-		newval = ( percent / 100 ) * ( max - min ) + min;
-
-		//from jQuery UI slider, the following source will round to the nearest step
-		valModStep = ( newval - min ) % step;
-		alignValue = newval - valModStep;
-
-		if ( Math.abs( valModStep ) * 2 >= step ) {
-			alignValue += ( valModStep > 0 ) ? step : ( -step );
-		}
-
-		percentPerStep = 100/((max-min)/step);
-		// Since JavaScript has problems with large floats, round
-		// the final value to 5 digits after the decimal point (see jQueryUI: #4124)
-		newval = parseFloat( alignValue.toFixed(5) );
-
-		if ( typeof pxStep === "undefined" ) {
-			pxStep = width / ( (max-min) / step );
-		}
-		if ( pxStep > 1 && isInput ) {
-			percent = ( newval - min ) * percentPerStep * ( 1 / step );
-		}
-		if ( percent < 0 ) {
-			percent = 0;
-		}
-
-		if ( percent > 100 ) {
-			percent = 100;
-		}
-
-		if ( newval < min ) {
-			newval = min;
-		}
-
-		if ( newval > max ) {
-			newval = max;
-		}
-
-		this.handle.css( "left", percent + "%" );
-
-		this.handle[0].setAttribute( "aria-valuenow", isInput ? newval : optionElements.eq( newval ).attr( "value" ) );
-
-		this.handle[0].setAttribute( "aria-valuetext", isInput ? newval : optionElements.eq( newval ).getEncodedText() );
-
-		this.handle[0].setAttribute( "title", isInput ? newval : optionElements.eq( newval ).getEncodedText() );
-
-		if ( this.valuebg ) {
-			this.valuebg.css( "width", percent + "%" );
-		}
-
-		// drag the label widths
-		if ( this._labels ) {
-			handlePercent = this.handle.width() / this.slider.width() * 100;
-			aPercent = percent && handlePercent + ( 100 - handlePercent ) * percent / 100;
-			bPercent = percent === 100 ? 0 : Math.min( handlePercent + 100 - aPercent, 100 );
-
-			this._labels.each(function() {
-				var ab = $( this ).hasClass( "ui-slider-label-a" );
-				$( this ).width( ( ab ? aPercent : bPercent  ) + "%" );
-			});
-		}
-
-		if ( !preventInputUpdate ) {
-			valueChanged = false;
-
-			// update control"s value
-			if ( isInput ) {
-				valueChanged = control.val() !== newval;
-				control.val( newval );
-			} else {
-				valueChanged = control[ 0 ].selectedIndex !== newval;
-				control[ 0 ].selectedIndex = newval;
-			}
-			if ( this._trigger( "beforechange", val ) === false) {
-					return false;
-			}
-			if ( !isfromControl && valueChanged ) {
-				control.trigger( "change" );
-			}
-		}
-	},
-
-	_setHighlight: function( value ) {
-		value = !!value;
-		if ( value ) {
-			this.options.highlight = !!value;
-			this.refresh();
-		} else if ( this.valuebg ) {
-			this.valuebg.remove();
-			this.valuebg = false;
-		}
-	},
-
-	_setTheme: function( value ) {
-		this.handle
-			.removeClass( "ui-btn-" + this.options.theme )
-			.addClass( "ui-btn-" + value );
-
-		var currentTheme = this.options.theme ? this.options.theme : "inherit",
-			newTheme = value ? value : "inherit";
-
-		this.control
-			.removeClass( "ui-body-" + currentTheme )
-			.addClass( "ui-body-" + newTheme );
-	},
-
-	_setTrackTheme: function( value ) {
-		var currentTrackTheme = this.options.trackTheme ? this.options.trackTheme : "inherit",
-			newTrackTheme = value ? value : "inherit";
-
-		this.slider
-			.removeClass( "ui-body-" + currentTrackTheme )
-			.addClass( "ui-body-" + newTrackTheme );
-	},
-
-	_setMini: function( value ) {
-		value = !!value;
-		if ( !this.isToggleSwitch && !this.isRangeslider ) {
-			this.slider.parent().toggleClass( "ui-mini", value );
-			this.element.toggleClass( "ui-mini", value );
-		}
-		this.slider.toggleClass( "ui-mini", value );
-	},
-
-	_setCorners: function( value ) {
-		this.slider.toggleClass( "ui-corner-all", value );
-
-		if ( !this.isToggleSwitch ) {
-			this.control.toggleClass( "ui-corner-all", value );
-		}
-	},
-
-	_setDisabled: function( value ) {
-		value = !!value;
-		this.element.prop( "disabled", value );
-		this.slider
-			.toggleClass( "ui-state-disabled", value )
-			.attr( "aria-disabled", value );
-	}
-
-}, $.mobile.behaviors.formReset ) );
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-var popup;
-
-function getPopup() {
-	if ( !popup ) {
-		popup = $( "<div></div>", {
-			"class": "ui-slider-popup ui-shadow ui-corner-all"
-		});
-	}
-	return popup.clone();
-}
-
-$.widget( "mobile.slider", $.mobile.slider, {
-	options: {
-		popupEnabled: false,
-		showValue: false
-	},
-
-	_create: function() {
-		this._super();
-
-		$.extend( this, {
-			_currentValue: null,
-			_popup: null,
-			_popupVisible: false
-		});
-
-		this._setOption( "popupEnabled", this.options.popupEnabled );
-
-		this._on( this.handle, { "vmousedown" : "_showPopup" } );
-		this._on( this.slider.add( this.document ), { "vmouseup" : "_hidePopup" } );
-		this._refresh();
-	},
-
-	// position the popup centered 5px above the handle
-	_positionPopup: function() {
-		var dstOffset = this.handle.offset();
-
-		this._popup.offset( {
-			left: dstOffset.left + ( this.handle.width() - this._popup.width() ) / 2,
-			top: dstOffset.top - this._popup.outerHeight() - 5
-		});
-	},
-
-	_setOption: function( key, value ) {
-		this._super( key, value );
-
-		if ( key === "showValue" ) {
-			this.handle.html( value && !this.options.mini ? this._value() : "" );
-		} else if ( key === "popupEnabled" ) {
-			if ( value && !this._popup ) {
-				this._popup = getPopup()
-					.addClass( "ui-body-" + ( this.options.theme || "a" ) )
-					.hide()
-					.insertBefore( this.element );
-			}
-		}
-	},
-
-	// show value on the handle and in popup
-	refresh: function() {
-		this._super.apply( this, arguments );
-		this._refresh();
-	},
-
-	_refresh: function() {
-		var o = this.options, newValue;
-
-		if ( o.popupEnabled ) {
-			// remove the title attribute from the handle (which is
-			// responsible for the annoying tooltip); NB we have
-			// to do it here as the jqm slider sets it every time
-			// the slider's value changes :(
-			this.handle.removeAttr( "title" );
-		}
-
-		newValue = this._value();
-		if ( newValue === this._currentValue ) {
-			return;
-		}
-		this._currentValue = newValue;
-
-		if ( o.popupEnabled && this._popup ) {
-			this._positionPopup();
-			this._popup.html( newValue );
-		} else if ( o.showValue && !this.options.mini ) {
-			this.handle.html( newValue );
-		}
-	},
-
-	_showPopup: function() {
-		if ( this.options.popupEnabled && !this._popupVisible ) {
-			this.handle.html( "" );
-			this._popup.show();
-			this._positionPopup();
-			this._popupVisible = true;
-		}
-	},
-
-	_hidePopup: function() {
-		var o = this.options;
-
-		if ( o.popupEnabled && this._popupVisible ) {
-			if ( o.showValue && !o.mini ) {
-				this.handle.html( this._value() );
-			}
-			this._popup.hide();
-			this._popupVisible = false;
-		}
-	}
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.widget( "mobile.flipswitch", $.extend({
-
-	options: {
-		onText: "On",
-		offText: "Off",
-		theme: null,
-		enhanced: false,
-		wrapperClass: null,
-		corners: true,
-		mini: false
-	},
-
-	_create: function() {
-			if ( !this.options.enhanced ) {
-				this._enhance();
-			} else {
-				$.extend( this, {
-					flipswitch: this.element.parent(),
-					on: this.element.find( ".ui-flipswitch-on" ).eq( 0 ),
-					off: this.element.find( ".ui-flipswitch-off" ).eq(0),
-					type: this.element.get( 0 ).tagName
-				});
-			}
-
-			this._handleFormReset();
-
-			// Transfer tabindex to "on" element and make input unfocusable
-			this._originalTabIndex = this.element.attr( "tabindex" );
-			if ( this._originalTabIndex != null ) {
-				this.on.attr( "tabindex", this._originalTabIndex );
-			}
-			this.element.attr( "tabindex", "-1" );
-			this._on({
-				"focus" : "_handleInputFocus"
-			});
-
-			if ( this.element.is( ":disabled" ) ) {
-				this._setOptions({
-					"disabled": true
-				});
-			}
-
-			this._on( this.flipswitch, {
-				"click": "_toggle",
-				"swipeleft": "_left",
-				"swiperight": "_right"
-			});
-
-			this._on( this.on, {
-				"keydown": "_keydown"
-			});
-
-			this._on( {
-				"change": "refresh"
-			});
-	},
-
-	_handleInputFocus: function() {
-		this.on.focus();
-	},
-
-	widget: function() {
-		return this.flipswitch;
-	},
-
-	_left: function() {
-		this.flipswitch.removeClass( "ui-flipswitch-active" );
-		if ( this.type === "SELECT" ) {
-			this.element.get( 0 ).selectedIndex = 0;
-		} else {
-			this.element.prop( "checked", false );
-		}
-		this.element.trigger( "change" );
-	},
-
-	_right: function() {
-		this.flipswitch.addClass( "ui-flipswitch-active" );
-		if ( this.type === "SELECT" ) {
-			this.element.get( 0 ).selectedIndex = 1;
-		} else {
-			this.element.prop( "checked", true );
-		}
-		this.element.trigger( "change" );
-	},
-
-	_enhance: function() {
-		var flipswitch = $( "<div>" ),
-			options = this.options,
-			element = this.element,
-			theme = options.theme ? options.theme : "inherit",
-
-			// The "on" button is an anchor so it's focusable
-			on = $( "<a></a>", {
-				"href": "#"
-			}),
-			off = $( "<span></span>" ),
-			type = element.get( 0 ).tagName,
-			onText = ( type === "INPUT" ) ?
-				options.onText : element.find( "option" ).eq( 1 ).text(),
-			offText = ( type === "INPUT" ) ?
-				options.offText : element.find( "option" ).eq( 0 ).text();
-
-			on
-				.addClass( "ui-flipswitch-on ui-btn ui-shadow ui-btn-inherit" )
-				.text( onText );
-			off
-				.addClass( "ui-flipswitch-off" )
-				.text( offText );
-
-			flipswitch
-				.addClass( "ui-flipswitch ui-shadow-inset " +
-					"ui-bar-" + theme + " " +
-					( options.wrapperClass ? options.wrapperClass : "" ) + " " +
-					( ( element.is( ":checked" ) ||
-						element
-							.find( "option" )
-							.eq( 1 )
-							.is( ":selected" ) ) ? "ui-flipswitch-active" : "" ) +
-					( element.is(":disabled") ? " ui-state-disabled": "") +
-					( options.corners ? " ui-corner-all": "" ) +
-					( options.mini ? " ui-mini": "" ) )
-				.append( on, off );
-
-			element
-				.addClass( "ui-flipswitch-input" )
-				.after( flipswitch )
-				.appendTo( flipswitch );
-
-		$.extend( this, {
-			flipswitch: flipswitch,
-			on: on,
-			off: off,
-			type: type
-		});
-	},
-
-	_reset: function() {
-		this.refresh();
-	},
-
-	refresh: function() {
-		var direction,
-			existingDirection = this.flipswitch.hasClass( "ui-flipswitch-active" ) ? "_right" : "_left";
-
-		if ( this.type === "SELECT" ) {
-			direction = ( this.element.get( 0 ).selectedIndex > 0 ) ? "_right": "_left";
-		} else {
-			direction = this.element.prop( "checked" ) ? "_right": "_left";
-		}
-
-		if ( direction !== existingDirection ) {
-			this[ direction ]();
-		}
-	},
-
-	_toggle: function() {
-		var direction = this.flipswitch.hasClass( "ui-flipswitch-active" ) ? "_left" : "_right";
-
-		this[ direction ]();
-	},
-
-	_keydown: function( e ) {
-		if ( e.which === $.mobile.keyCode.LEFT ) {
-			this._left();
-		} else if ( e.which === $.mobile.keyCode.RIGHT ) {
-			this._right();
-		} else if ( e.which === $.mobile.keyCode.SPACE ) {
-			this._toggle();
-			e.preventDefault();
-		}
-	},
-
-	_setOptions: function( options ) {
-		if ( options.theme !== undefined ) {
-			var currentTheme = options.theme ? options.theme : "inherit",
-				newTheme = options.theme ? options.theme : "inherit";
-
-			this.widget()
-				.removeClass( "ui-bar-" + currentTheme )
-				.addClass( "ui-bar-" + newTheme );
-		}
-		if ( options.onText !== undefined ) {
-			this.on.text( options.onText );
-		}
-		if ( options.offText !== undefined ) {
-			this.off.text( options.offText );
-		}
-		if ( options.disabled !== undefined ) {
-			this.widget().toggleClass( "ui-state-disabled", options.disabled );
-		}
-		if ( options.mini !== undefined ) {
-			this.widget().toggleClass( "ui-mini", options.mini );
-		}
-		if ( options.corners !== undefined ) {
-			this.widget().toggleClass( "ui-corner-all", options.corners );
-		}
-
-		this._super( options );
-	},
-
-	_destroy: function() {
-		if ( this.options.enhanced ) {
-			return;
-		}
-		if ( this._originalTabIndex != null ) {
-			this.element.attr( "tabindex", this._originalTabIndex );
-		} else {
-			this.element.removeAttr( "tabindex" );
-		}
-		this.on.remove();
-		this.off.remove();
-		this.element.unwrap();
-		this.flipswitch.remove();
-		this.removeClass( "ui-flipswitch-input" );
-	}
-
-}, $.mobile.behaviors.formReset ) );
-
-})( jQuery );
-
-(function( $, undefined ) {
-	$.widget( "mobile.rangeslider", $.extend( {
-
-		options: {
-			theme: null,
-			trackTheme: null,
-			corners: true,
-			mini: false,
-			highlight: true
-		},
-
-		_create: function() {
-			var $el = this.element,
-			elClass = this.options.mini ? "ui-rangeslider ui-mini" : "ui-rangeslider",
-			_inputFirst = $el.find( "input" ).first(),
-			_inputLast = $el.find( "input" ).last(),
-			_label = $el.find( "label" ).first(),
-			_sliderWidgetFirst = $.data( _inputFirst.get( 0 ), "mobile-slider" ) ||
-				$.data( _inputFirst.slider().get( 0 ), "mobile-slider" ),
-			_sliderWidgetLast = $.data( _inputLast.get(0), "mobile-slider" ) ||
-				$.data( _inputLast.slider().get( 0 ), "mobile-slider" ),
-			_sliderFirst = _sliderWidgetFirst.slider,
-			_sliderLast = _sliderWidgetLast.slider,
-			firstHandle = _sliderWidgetFirst.handle,
-			_sliders = $( "<div class='ui-rangeslider-sliders' />" ).appendTo( $el );
-
-			_inputFirst.addClass( "ui-rangeslider-first" );
-			_inputLast.addClass( "ui-rangeslider-last" );
-			$el.addClass( elClass );
-
-			_sliderFirst.appendTo( _sliders );
-			_sliderLast.appendTo( _sliders );
-			_label.insertBefore( $el );
-			firstHandle.prependTo( _sliderLast );
-
-			$.extend( this, {
-				_inputFirst: _inputFirst,
-				_inputLast: _inputLast,
-				_sliderFirst: _sliderFirst,
-				_sliderLast: _sliderLast,
-				_label: _label,
-				_targetVal: null,
-				_sliderTarget: false,
-				_sliders: _sliders,
-				_proxy: false
-			});
-
-			this.refresh();
-			this._on( this.element.find( "input.ui-slider-input" ), {
-				"slidebeforestart": "_slidebeforestart",
-				"slidestop": "_slidestop",
-				"slidedrag": "_slidedrag",
-				"slidebeforechange": "_change",
-				"blur": "_change",
-				"keyup": "_change"
-			});
-			this._on({
-				"mousedown":"_change"
-			});
-			this._on( this.element.closest( "form" ), {
-				"reset":"_handleReset"
-			});
-			this._on( firstHandle, {
-				"vmousedown": "_dragFirstHandle"
-			});
-		},
-		_handleReset: function() {
-			var self = this;
-			//we must wait for the stack to unwind before updateing other wise sliders will not have updated yet
-			setTimeout( function() {
-				self._updateHighlight();
-			},0);
-		},
-
-		_dragFirstHandle: function( event ) {
-			//if the first handle is dragged send the event to the first slider
-			$.data( this._inputFirst.get(0), "mobile-slider" ).dragging = true;
-			$.data( this._inputFirst.get(0), "mobile-slider" ).refresh( event );
-			return false;
-		},
-
-		_slidedrag: function( event ) {
-			var first = $( event.target ).is( this._inputFirst ),
-				otherSlider = ( first ) ? this._inputLast : this._inputFirst;
-
-			this._sliderTarget = false;
-			//if the drag was initiated on an extreme and the other handle is focused send the events to
-			//the closest handle
-			if ( ( this._proxy === "first" && first ) || ( this._proxy === "last" && !first ) ) {
-				$.data( otherSlider.get(0), "mobile-slider" ).dragging = true;
-				$.data( otherSlider.get(0), "mobile-slider" ).refresh( event );
-				return false;
-			}
-		},
-
-		_slidestop: function( event ) {
-			var first = $( event.target ).is( this._inputFirst );
-
-			this._proxy = false;
-			//this stops dragging of the handle and brings the active track to the front
-			//this makes clicks on the track go the the last handle used
-			this.element.find( "input" ).trigger( "vmouseup" );
-			this._sliderFirst.css( "z-index", first ? 1 : "" );
-		},
-
-		_slidebeforestart: function( event ) {
-			this._sliderTarget = false;
-			//if the track is the target remember this and the original value
-			if ( $( event.originalEvent.target ).hasClass( "ui-slider-track" ) ) {
-				this._sliderTarget = true;
-				this._targetVal = $( event.target ).val();
-			}
-		},
-
-		_setOptions: function( options ) {
-			if ( options.theme !== undefined ) {
-				this._setTheme( options.theme );
-			}
-
-			if ( options.trackTheme !== undefined ) {
-				this._setTrackTheme( options.trackTheme );
-			}
-
-			if ( options.mini !== undefined ) {
-				this._setMini( options.mini );
-			}
-
-			if ( options.highlight !== undefined ) {
-				this._setHighlight( options.highlight );
-			}
-			this._super( options );
-			this.refresh();
-		},
-
-		refresh: function() {
-			var $el = this.element,
-				o = this.options;
-
-			if ( this._inputFirst.is( ":disabled" ) || this._inputLast.is( ":disabled" ) ) {
-				this.options.disabled = true;
-			}
-
-			$el.find( "input" ).slider({
-				theme: o.theme,
-				trackTheme: o.trackTheme,
-				disabled: o.disabled,
-				corners: o.corners,
-				mini: o.mini,
-				highlight: o.highlight
-			}).slider( "refresh" );
-			this._updateHighlight();
-		},
-
-		_change: function( event ) {
-			if ( event.type === "keyup" ) {
-				this._updateHighlight();
-				return false;
-			}
-
-			var self = this,
-				min = parseFloat( this._inputFirst.val(), 10 ),
-				max = parseFloat( this._inputLast.val(), 10 ),
-				first = $( event.target ).hasClass( "ui-rangeslider-first" ),
-				thisSlider = first ? this._inputFirst : this._inputLast,
-				otherSlider = first ? this._inputLast : this._inputFirst;
-
-			if ( ( this._inputFirst.val() > this._inputLast.val() && event.type === "mousedown" && !$(event.target).hasClass("ui-slider-handle")) ) {
-				thisSlider.blur();
-			} else if ( event.type === "mousedown" ) {
-				return;
-			}
-			if ( min > max && !this._sliderTarget ) {
-				//this prevents min from being greater then max
-				thisSlider.val( first ? max: min ).slider( "refresh" );
-				this._trigger( "normalize" );
-			} else if ( min > max ) {
-				//this makes it so clicks on the target on either extreme go to the closest handle
-				thisSlider.val( this._targetVal ).slider( "refresh" );
-
-				//You must wait for the stack to unwind so first slider is updated before updating second
-				setTimeout( function() {
-					otherSlider.val( first ? min: max ).slider( "refresh" );
-					$.data( otherSlider.get(0), "mobile-slider" ).handle.focus();
-					self._sliderFirst.css( "z-index", first ? "" : 1 );
-					self._trigger( "normalize" );
-				}, 0 );
-				this._proxy = ( first ) ? "first" : "last";
-			}
-			//fixes issue where when both _sliders are at min they cannot be adjusted
-			if ( min === max ) {
-				$.data( thisSlider.get(0), "mobile-slider" ).handle.css( "z-index", 1 );
-				$.data( otherSlider.get(0), "mobile-slider" ).handle.css( "z-index", 0 );
-			} else {
-				$.data( otherSlider.get(0), "mobile-slider" ).handle.css( "z-index", "" );
-				$.data( thisSlider.get(0), "mobile-slider" ).handle.css( "z-index", "" );
-			}
-
-			this._updateHighlight();
-
-			if ( min >= max ) {
-				return false;
-			}
-		},
-
-		_updateHighlight: function() {
-			var min = parseInt( $.data( this._inputFirst.get(0), "mobile-slider" ).handle.get(0).style.left, 10 ),
-				max = parseInt( $.data( this._inputLast.get(0), "mobile-slider" ).handle.get(0).style.left, 10 ),
-				width = (max - min);
-
-			this.element.find( ".ui-slider-bg" ).css({
-				"margin-left": min + "%",
-				"width": width + "%"
-			});
-		},
-
-		_setTheme: function( value ) {
-			this._inputFirst.slider( "option", "theme", value );
-			this._inputLast.slider( "option", "theme", value );
-		},
-
-		_setTrackTheme: function( value ) {
-			this._inputFirst.slider( "option", "trackTheme", value );
-			this._inputLast.slider( "option", "trackTheme", value );
-		},
-
-		_setMini: function( value ) {
-			this._inputFirst.slider( "option", "mini", value );
-			this._inputLast.slider( "option", "mini", value );
-			this.element.toggleClass( "ui-mini", !!value );
-		},
-
-		_setHighlight: function( value ) {
-			this._inputFirst.slider( "option", "highlight", value );
-			this._inputLast.slider( "option", "highlight", value );
-		},
-
-		_destroy: function() {
-			this._label.prependTo( this.element );
-			this.element.removeClass( "ui-rangeslider ui-mini" );
-			this._inputFirst.after( this._sliderFirst );
-			this._inputLast.after( this._sliderLast );
-			this._sliders.remove();
-			this.element.find( "input" ).removeClass( "ui-rangeslider-first ui-rangeslider-last" ).slider( "destroy" );
-		}
-
-	}, $.mobile.behaviors.formReset ) );
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-	$.widget( "mobile.textinput", $.mobile.textinput, {
-		options: {
-			clearBtn: false,
-			clearBtnText: "Clear text"
-		},
-
-		_create: function() {
-			this._super();
-
-			if ( !!this.options.clearBtn || this.isSearch ) {
-				this._addClearBtn();
-			}
-		},
-
-		clearButton: function() {
-
-			return $( "<a href='#' class='ui-input-clear ui-btn ui-icon-delete ui-btn-icon-notext ui-corner-all" +
-    "' title='" + this.options.clearBtnText + "'>" + this.options.clearBtnText + "</a>" );
-
-		},
-
-		_clearBtnClick: function( event ) {
-			this.element.val( "" )
-					.focus()
-					.trigger( "change" );
-
-			this._clearBtn.addClass( "ui-input-clear-hidden" );
-			event.preventDefault();
-		},
-
-		_addClearBtn: function() {
-
-			if ( !this.options.enhanced ) {
-				this._enhanceClear();
-			}
-
-			$.extend( this, {
-				_clearBtn: this.widget().find("a.ui-input-clear")
-			});
-
-			this._bindClearEvents();
-
-			this._toggleClear();
-
-		},
-
-		_enhanceClear: function() {
-
-			this.clearButton().appendTo( this.widget() );
-			this.widget().addClass( "ui-input-has-clear" );
-
-		},
-
-		_bindClearEvents: function() {
-
-			this._on( this._clearBtn, {
-				"click": "_clearBtnClick"
-			});
-
-			this._on({
-				"keyup": "_toggleClear",
-				"change": "_toggleClear",
-				"input": "_toggleClear",
-				"focus": "_toggleClear",
-				"blur": "_toggleClear",
-				"cut": "_toggleClear",
-				"paste": "_toggleClear"
-
-			});
-
-		},
-
-		_unbindClear: function() {
-			this._off( this._clearBtn, "click");
-			this._off( this.element, "keyup change input focus blur cut paste" );
-		},
-
-		_setOptions: function( options ) {
-			this._super( options );
-
-			if ( options.clearBtn !== undefined &&
-				!this.element.is( "textarea, :jqmData(type='range')" ) ) {
-				if ( options.clearBtn ) {
-					this._addClearBtn();
-				} else {
-					this._destroyClear();
-				}
-			}
-
-			if ( options.clearBtnText !== undefined && this._clearBtn !== undefined ) {
-				this._clearBtn.text( options.clearBtnText )
-					.attr("title", options.clearBtnText);
-			}
-		},
-
-		_toggleClear: function() {
-			this._delay( "_toggleClearClass", 0 );
-		},
-
-		_toggleClearClass: function() {
-			this._clearBtn.toggleClass( "ui-input-clear-hidden", !this.element.val() );
-		},
-
-		_destroyClear: function() {
-			this.widget().removeClass( "ui-input-has-clear" );
-			this._unbindClear();
-			this._clearBtn.remove();
-		},
-
-		_destroy: function() {
-			this._super();
-			this._destroyClear();
-		}
-
-	});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-	$.widget( "mobile.textinput", $.mobile.textinput, {
-		options: {
-			autogrow:true,
-			keyupTimeoutBuffer: 100
-		},
-
-		_create: function() {
-			this._super();
-
-			if ( this.options.autogrow && this.isTextarea ) {
-				this._autogrow();
-			}
-		},
-
-		_autogrow: function() {
-			this.element.addClass( "ui-textinput-autogrow" );
-
-			this._on({
-				"keyup": "_timeout",
-				"change": "_timeout",
-				"input": "_timeout",
-				"paste": "_timeout"
-			});
-
-			// Attach to the various you-have-become-visible notifications that the
-			// various framework elements emit.
-			// TODO: Remove all but the updatelayout handler once #6426 is fixed.
-			this._on( true, this.document, {
-
-				// TODO: Move to non-deprecated event
-				"pageshow": "_handleShow",
-				"popupbeforeposition": "_handleShow",
-				"updatelayout": "_handleShow",
-				"panelopen": "_handleShow"
-			});
-		},
-
-		// Synchronously fix the widget height if this widget's parents are such
-		// that they show/hide content at runtime. We still need to check whether
-		// the widget is actually visible in case it is contained inside multiple
-		// such containers. For example: panel contains collapsible contains
-		// autogrow textinput. The panel may emit "panelopen" indicating that its
-		// content has become visible, but the collapsible is still collapsed, so
-		// the autogrow textarea is still not visible.
-		_handleShow: function( event ) {
-			if ( $.contains( event.target, this.element[ 0 ] ) &&
-				this.element.is( ":visible" ) ) {
-
-				if ( event.type !== "popupbeforeposition" ) {
-					this.element
-						.addClass( "ui-textinput-autogrow-resize" )
-						.animationComplete(
-							$.proxy( function() {
-								this.element.removeClass( "ui-textinput-autogrow-resize" );
-							}, this ),
-						"transition" );
-				}
-				this._timeout();
-			}
-		},
-
-		_unbindAutogrow: function() {
-			this.element.removeClass( "ui-textinput-autogrow" );
-			this._off( this.element, "keyup change input paste" );
-			this._off( this.document,
-				"pageshow popupbeforeposition updatelayout panelopen" );
-		},
-
-		keyupTimeout: null,
-
-		_prepareHeightUpdate: function( delay ) {
-			if ( this.keyupTimeout ) {
-				clearTimeout( this.keyupTimeout );
-			}
-			if ( delay === undefined ) {
-				this._updateHeight();
-			} else {
-				this.keyupTimeout = this._delay( "_updateHeight", delay );
-			}
-		},
-
-		_timeout: function() {
-			this._prepareHeightUpdate( this.options.keyupTimeoutBuffer );
-		},
-
-		_updateHeight: function() {
-			var paddingTop, paddingBottom, paddingHeight, scrollHeight, clientHeight,
-				borderTop, borderBottom, borderHeight, height,
-				scrollTop = this.window.scrollTop();
-			this.keyupTimeout = 0;
-
-			// IE8 textareas have the onpage property - others do not
-			if ( !( "onpage" in this.element[ 0 ] ) ) {
-				this.element.css({
-					"height": 0,
-					"min-height": 0,
-					"max-height": 0
-				});
-			}
-
-			scrollHeight = this.element[ 0 ].scrollHeight;
-			clientHeight = this.element[ 0 ].clientHeight;
-			borderTop = parseFloat( this.element.css( "border-top-width" ) );
-			borderBottom = parseFloat( this.element.css( "border-bottom-width" ) );
-			borderHeight = borderTop + borderBottom;
-			height = scrollHeight + borderHeight + 15;
-
-			// Issue 6179: Padding is not included in scrollHeight and
-			// clientHeight by Firefox if no scrollbar is visible. Because
-			// textareas use the border-box box-sizing model, padding should be
-			// included in the new (assigned) height. Because the height is set
-			// to 0, clientHeight == 0 in Firefox. Therefore, we can use this to
-			// check if padding must be added.
-			if ( clientHeight === 0 ) {
-				paddingTop = parseFloat( this.element.css( "padding-top" ) );
-				paddingBottom = parseFloat( this.element.css( "padding-bottom" ) );
-				paddingHeight = paddingTop + paddingBottom;
-
-				height += paddingHeight;
-			}
-
-			this.element.css({
-				"height": height,
-				"min-height": "",
-				"max-height": ""
-			});
-
-			this.window.scrollTop( scrollTop );
-		},
-
-		refresh: function() {
-			if ( this.options.autogrow && this.isTextarea ) {
-				this._updateHeight();
-			}
-		},
-
-		_setOptions: function( options ) {
-
-			this._super( options );
-
-			if ( options.autogrow !== undefined && this.isTextarea ) {
-				if ( options.autogrow ) {
-					this._autogrow();
-				} else {
-					this._unbindAutogrow();
-				}
-			}
-		}
-
-	});
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.widget( "mobile.selectmenu", $.extend( {
-	initSelector: "select:not( :jqmData(role='slider')):not( :jqmData(role='flipswitch') )",
-
-	options: {
-		theme: null,
-		icon: "carat-d",
-		iconpos: "right",
-		inline: false,
-		corners: true,
-		shadow: true,
-		iconshadow: false, /* TODO: Deprecated in 1.4, remove in 1.5. */
-		overlayTheme: null,
-		dividerTheme: null,
-		hidePlaceholderMenuItems: true,
-		closeText: "Close",
-		nativeMenu: true,
-		// This option defaults to true on iOS devices.
-		preventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( "AppleWebKit" ) > -1,
-		mini: false
-	},
-
-	_button: function() {
-		return $( "<div/>" );
-	},
-
-	_setDisabled: function( value ) {
-		this.element.attr( "disabled", value );
-		this.button.attr( "aria-disabled", value );
-		return this._setOption( "disabled", value );
-	},
-
-	_focusButton : function() {
-		var self = this;
-
-		setTimeout( function() {
-			self.button.focus();
-		}, 40);
-	},
-
-	_selectOptions: function() {
-		return this.select.find( "option" );
-	},
-
-	// setup items that are generally necessary for select menu extension
-	_preExtension: function() {
-		var inline = this.options.inline || this.element.jqmData( "inline" ),
-			mini = this.options.mini || this.element.jqmData( "mini" ),
-			classes = "";
-		// TODO: Post 1.1--once we have time to test thoroughly--any classes manually applied to the original element should be carried over to the enhanced element, with an `-enhanced` suffix. See https://github.com/jquery/jquery-mobile/issues/3577
-		/* if ( $el[0].className.length ) {
-			classes = $el[0].className;
-		} */
-		if ( !!~this.element[0].className.indexOf( "ui-btn-left" ) ) {
-			classes = " ui-btn-left";
-		}
-
-		if (  !!~this.element[0].className.indexOf( "ui-btn-right" ) ) {
-			classes = " ui-btn-right";
-		}
-
-		if ( inline ) {
-			classes += " ui-btn-inline";
-		}
-		if ( mini ) {
-			classes += " ui-mini";
-		}
-
-		this.select = this.element.removeClass( "ui-btn-left ui-btn-right" ).wrap( "<div class='ui-select" + classes + "'>" );
-		this.selectId  = this.select.attr( "id" ) || ( "select-" + this.uuid );
-		this.buttonId = this.selectId + "-button";
-		this.label = $( "label[for='"+ this.selectId +"']" );
-		this.isMultiple = this.select[ 0 ].multiple;
-	},
-
-	_destroy: function() {
-		var wrapper = this.element.parents( ".ui-select" );
-		if ( wrapper.length > 0 ) {
-			if ( wrapper.is( ".ui-btn-left, .ui-btn-right" ) ) {
-				this.element.addClass( wrapper.hasClass( "ui-btn-left" ) ? "ui-btn-left" : "ui-btn-right" );
-			}
-			this.element.insertAfter( wrapper );
-			wrapper.remove();
-		}
-	},
-
-	_create: function() {
-		this._preExtension();
-
-		this.button = this._button();
-
-		var self = this,
-
-			options = this.options,
-
-			iconpos = options.icon ? ( options.iconpos || this.select.jqmData( "iconpos" ) ) : false,
-
-			button = this.button
-				.insertBefore( this.select )
-				.attr( "id", this.buttonId )
-				.addClass( "ui-btn" +
-					( options.icon ? ( " ui-icon-" + options.icon + " ui-btn-icon-" + iconpos +
-					( options.iconshadow ? " ui-shadow-icon" : "" ) ) :	"" ) + /* TODO: Remove in 1.5. */
-					( options.theme ? " ui-btn-" + options.theme : "" ) +
-					( options.corners ? " ui-corner-all" : "" ) +
-					( options.shadow ? " ui-shadow" : "" ) );
-
-		this.setButtonText();
-
-		// Opera does not properly support opacity on select elements
-		// In Mini, it hides the element, but not its text
-		// On the desktop,it seems to do the opposite
-		// for these reasons, using the nativeMenu option results in a full native select in Opera
-		if ( options.nativeMenu && window.opera && window.opera.version ) {
-			button.addClass( "ui-select-nativeonly" );
-		}
-
-		// Add counter for multi selects
-		if ( this.isMultiple ) {
-			this.buttonCount = $( "<span>" )
-				.addClass( "ui-li-count ui-body-inherit" )
-				.hide()
-				.appendTo( button.addClass( "ui-li-has-count" ) );
-		}
-
-		// Disable if specified
-		if ( options.disabled || this.element.attr( "disabled" )) {
-			this.disable();
-		}
-
-		// Events on native select
-		this.select.change(function() {
-			self.refresh();
-
-			if ( !!options.nativeMenu ) {
-				this.blur();
-			}
-		});
-
-		this._handleFormReset();
-
-		this._on( this.button, {
-			keydown: "_handleKeydown"
-		});
-
-		this.build();
-	},
-
-	build: function() {
-		var self = this;
-
-		this.select
-			.appendTo( self.button )
-			.bind( "vmousedown", function() {
-				// Add active class to button
-				self.button.addClass( $.mobile.activeBtnClass );
-			})
-			.bind( "focus", function() {
-				self.button.addClass( $.mobile.focusClass );
-			})
-			.bind( "blur", function() {
-				self.button.removeClass( $.mobile.focusClass );
-			})
-			.bind( "focus vmouseover", function() {
-				self.button.trigger( "vmouseover" );
-			})
-			.bind( "vmousemove", function() {
-				// Remove active class on scroll/touchmove
-				self.button.removeClass( $.mobile.activeBtnClass );
-			})
-			.bind( "change blur vmouseout", function() {
-				self.button.trigger( "vmouseout" )
-					.removeClass( $.mobile.activeBtnClass );
-			});
-
-		// In many situations, iOS will zoom into the select upon tap, this prevents that from happening
-		self.button.bind( "vmousedown", function() {
-			if ( self.options.preventFocusZoom ) {
-					$.mobile.zoom.disable( true );
-			}
-		});
-		self.label.bind( "click focus", function() {
-			if ( self.options.preventFocusZoom ) {
-					$.mobile.zoom.disable( true );
-			}
-		});
-		self.select.bind( "focus", function() {
-			if ( self.options.preventFocusZoom ) {
-					$.mobile.zoom.disable( true );
-			}
-		});
-		self.button.bind( "mouseup", function() {
-			if ( self.options.preventFocusZoom ) {
-				setTimeout(function() {
-					$.mobile.zoom.enable( true );
-				}, 0 );
-			}
-		});
-		self.select.bind( "blur", function() {
-			if ( self.options.preventFocusZoom ) {
-				$.mobile.zoom.enable( true );
-			}
-		});
-
-	},
-
-	selected: function() {
-		return this._selectOptions().filter( ":selected" );
-	},
-
-	selectedIndices: function() {
-		var self = this;
-
-		return this.selected().map(function() {
-			return self._selectOptions().index( this );
-		}).get();
-	},
-
-	setButtonText: function() {
-		var self = this,
-			selected = this.selected(),
-			text = this.placeholder,
-			span = $( document.createElement( "span" ) );
-
-		this.button.children( "span" ).not( ".ui-li-count" ).remove().end().end().prepend( (function() {
-			if ( selected.length ) {
-				text = selected.map(function() {
-					return $( this ).text();
-				}).get().join( ", " );
-			} else {
-				text = self.placeholder;
-			}
-
-			if ( text ) {
-				span.text( text );
-			} else {
-
-				// Set the contents to &nbsp; which we write as &#160; to be XHTML compliant - see gh-6699
-				span.html( "&#160;" );
-			}
-
-			// TODO possibly aggregate multiple select option classes
-			return span
-				.addClass( self.select.attr( "class" ) )
-				.addClass( selected.attr( "class" ) )
-				.removeClass( "ui-screen-hidden" );
-		})());
-	},
-
-	setButtonCount: function() {
-		var selected = this.selected();
-
-		// multiple count inside button
-		if ( this.isMultiple ) {
-			this.buttonCount[ selected.length > 1 ? "show" : "hide" ]().text( selected.length );
-		}
-	},
-
-	_handleKeydown: function( /* event */ ) {
-		this._delay( "_refreshButton" );
-	},
-
-	_reset: function() {
-		this.refresh();
-	},
-
-	_refreshButton: function() {
-		this.setButtonText();
-		this.setButtonCount();
-	},
-
-	refresh: function() {
-		this._refreshButton();
-	},
-
-	// open and close preserved in native selects
-	// to simplify users code when looping over selects
-	open: $.noop,
-	close: $.noop,
-
-	disable: function() {
-		this._setDisabled( true );
-		this.button.addClass( "ui-state-disabled" );
-	},
-
-	enable: function() {
-		this._setDisabled( false );
-		this.button.removeClass( "ui-state-disabled" );
-	}
-}, $.mobile.behaviors.formReset ) );
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.mobile.links = function( target ) {
-
-	//links within content areas, tests included with page
-	$( target )
-		.find( "a" )
-		.jqmEnhanceable()
-		.filter( ":jqmData(rel='popup')[href][href!='']" )
-		.each( function() {
-			// Accessibility info for popups
-			var element = this,
-				idref = element.getAttribute( "href" ).substring( 1 );
-
-			if ( idref ) {
-				element.setAttribute( "aria-haspopup", true );
-				element.setAttribute( "aria-owns", idref );
-				element.setAttribute( "aria-expanded", false );
-			}
-		})
-		.end()
-		.not( ".ui-btn, :jqmData(role='none'), :jqmData(role='nojs')" )
-		.addClass( "ui-link" );
-
-};
-
-})( jQuery );
-
-
-(function( $, undefined ) {
-
-function fitSegmentInsideSegment( windowSize, segmentSize, offset, desired ) {
-	var returnValue = desired;
-
-	if ( windowSize < segmentSize ) {
-		// Center segment if it's bigger than the window
-		returnValue = offset + ( windowSize - segmentSize ) / 2;
-	} else {
-		// Otherwise center it at the desired coordinate while keeping it completely inside the window
-		returnValue = Math.min( Math.max( offset, desired - segmentSize / 2 ), offset + windowSize - segmentSize );
-	}
-
-	return returnValue;
-}
-
-function getWindowCoordinates( theWindow ) {
-	return {
-		x: theWindow.scrollLeft(),
-		y: theWindow.scrollTop(),
-		cx: ( theWindow[ 0 ].innerWidth || theWindow.width() ),
-		cy: ( theWindow[ 0 ].innerHeight || theWindow.height() )
-	};
-}
-
-$.widget( "mobile.popup", {
-	options: {
-		wrapperClass: null,
-		theme: null,
-		overlayTheme: null,
-		shadow: true,
-		corners: true,
-		transition: "none",
-		positionTo: "origin",
-		tolerance: null,
-		closeLinkSelector: "a:jqmData(rel='back')",
-		closeLinkEvents: "click.popup",
-		navigateEvents: "navigate.popup",
-		closeEvents: "navigate.popup pagebeforechange.popup",
-		dismissible: true,
-		enhanced: false,
-
-		// NOTE Windows Phone 7 has a scroll position caching issue that
-		//      requires us to disable popup history management by default
-		//      https://github.com/jquery/jquery-mobile/issues/4784
-		//
-		// NOTE this option is modified in _create!
-		history: !$.mobile.browser.oldIE
-	},
-
-	_create: function() {
-		var theElement = this.element,
-			myId = theElement.attr( "id" ),
-			currentOptions = this.options;
-
-		// We need to adjust the history option to be false if there's no AJAX nav.
-		// We can't do it in the option declarations because those are run before
-		// it is determined whether there shall be AJAX nav.
-		currentOptions.history = currentOptions.history && $.mobile.ajaxEnabled && $.mobile.hashListeningEnabled;
-
-		// Define instance variables
-		$.extend( this, {
-			_scrollTop: 0,
-			_page: theElement.closest( ".ui-page" ),
-			_ui: null,
-			_fallbackTransition: "",
-			_currentTransition: false,
-			_prerequisites: null,
-			_isOpen: false,
-			_tolerance: null,
-			_resizeData: null,
-			_ignoreResizeTo: 0,
-			_orientationchangeInProgress: false
-		});
-
-		if ( this._page.length === 0 ) {
-			this._page = $( "body" );
-		}
-
-		if ( currentOptions.enhanced ) {
-			this._ui = {
-				container: theElement.parent(),
-				screen: theElement.parent().prev(),
-				placeholder: $( this.document[ 0 ].getElementById( myId + "-placeholder" ) )
-			};
-		} else {
-			this._ui = this._enhance( theElement, myId );
-			this._applyTransition( currentOptions.transition );
-		}
-		this
-			._setTolerance( currentOptions.tolerance )
-			._ui.focusElement = this._ui.container;
-
-		// Event handlers
-		this._on( this._ui.screen, { "vclick": "_eatEventAndClose" } );
-		this._on( this.window, {
-			orientationchange: $.proxy( this, "_handleWindowOrientationchange" ),
-			resize: $.proxy( this, "_handleWindowResize" ),
-			keyup: $.proxy( this, "_handleWindowKeyUp" )
-		});
-		this._on( this.document, { "focusin": "_handleDocumentFocusIn" } );
-	},
-
-	_enhance: function( theElement, myId ) {
-		var currentOptions = this.options,
-			wrapperClass = currentOptions.wrapperClass,
-			ui = {
-				screen: $( "<div class='ui-screen-hidden ui-popup-screen " +
-				this._themeClassFromOption( "ui-overlay-", currentOptions.overlayTheme ) + "'></div>" ),
-				placeholder: $( "<div style='display: none;'><!-- placeholder --></div>" ),
-				container: $( "<div class='ui-popup-container ui-popup-hidden ui-popup-truncate" +
-					( wrapperClass ? ( " " + wrapperClass ) : "" ) + "'></div>" )
-			},
-			fragment = this.document[ 0 ].createDocumentFragment();
-
-		fragment.appendChild( ui.screen[ 0 ] );
-		fragment.appendChild( ui.container[ 0 ] );
-
-		if ( myId ) {
-			ui.screen.attr( "id", myId + "-screen" );
-			ui.container.attr( "id", myId + "-popup" );
-			ui.placeholder
-				.attr( "id", myId + "-placeholder" )
-				.html( "<!-- placeholder for " + myId + " -->" );
-		}
-
-		// Apply the proto
-		this._page[ 0 ].appendChild( fragment );
-		// Leave a placeholder where the element used to be
-		ui.placeholder.insertAfter( theElement );
-		theElement
-			.detach()
-			.addClass( "ui-popup " +
-				this._themeClassFromOption( "ui-body-", currentOptions.theme ) + " " +
-				( currentOptions.shadow ? "ui-overlay-shadow " : "" ) +
-				( currentOptions.corners ? "ui-corner-all " : "" ) )
-			.appendTo( ui.container );
-
-		return ui;
-	},
-
-	_eatEventAndClose: function( theEvent ) {
-		theEvent.preventDefault();
-		theEvent.stopImmediatePropagation();
-		if ( this.options.dismissible ) {
-			this.close();
-		}
-		return false;
-	},
-
-	// Make sure the screen covers the entire document - CSS is sometimes not
-	// enough to accomplish this.
-	_resizeScreen: function() {
-		var screen = this._ui.screen,
-			popupHeight = this._ui.container.outerHeight( true ),
-			screenHeight = screen.removeAttr( "style" ).height(),
-
-			// Subtracting 1 here is necessary for an obscure Andrdoid 4.0 bug where
-			// the browser hangs if the screen covers the entire document :/
-			documentHeight = this.document.height() - 1;
-
-		if ( screenHeight < documentHeight ) {
-			screen.height( documentHeight );
-		} else if ( popupHeight > screenHeight ) {
-			screen.height( popupHeight );
-		}
-	},
-
-	_handleWindowKeyUp: function( theEvent ) {
-		if ( this._isOpen && theEvent.keyCode === $.mobile.keyCode.ESCAPE ) {
-			return this._eatEventAndClose( theEvent );
-		}
-	},
-
-	_expectResizeEvent: function() {
-		var windowCoordinates = getWindowCoordinates( this.window );
-
-		if ( this._resizeData ) {
-			if ( windowCoordinates.x === this._resizeData.windowCoordinates.x &&
-				windowCoordinates.y === this._resizeData.windowCoordinates.y &&
-				windowCoordinates.cx === this._resizeData.windowCoordinates.cx &&
-				windowCoordinates.cy === this._resizeData.windowCoordinates.cy ) {
-				// timeout not refreshed
-				return false;
-			} else {
-				// clear existing timeout - it will be refreshed below
-				clearTimeout( this._resizeData.timeoutId );
-			}
-		}
-
-		this._resizeData = {
-			timeoutId: this._delay( "_resizeTimeout", 200 ),
-			windowCoordinates: windowCoordinates
-		};
-
-		return true;
-	},
-
-	_resizeTimeout: function() {
-		if ( this._isOpen ) {
-			if ( !this._expectResizeEvent() ) {
-				if ( this._ui.container.hasClass( "ui-popup-hidden" ) ) {
-					// effectively rapid-open the popup while leaving the screen intact
-					this._ui.container.removeClass( "ui-popup-hidden ui-popup-truncate" );
-					this.reposition( { positionTo: "window" } );
-					this._ignoreResizeEvents();
-				}
-
-				this._resizeScreen();
-				this._resizeData = null;
-				this._orientationchangeInProgress = false;
-			}
-		} else {
-			this._resizeData = null;
-			this._orientationchangeInProgress = false;
-		}
-	},
-
-	_stopIgnoringResizeEvents: function() {
-		this._ignoreResizeTo = 0;
-	},
-
-	_ignoreResizeEvents: function() {
-		if ( this._ignoreResizeTo ) {
-			clearTimeout( this._ignoreResizeTo );
-		}
-		this._ignoreResizeTo = this._delay( "_stopIgnoringResizeEvents", 1000 );
-	},
-
-	_handleWindowResize: function(/* theEvent */) {
-		if ( this._isOpen && this._ignoreResizeTo === 0 ) {
-			if ( ( this._expectResizeEvent() || this._orientationchangeInProgress ) &&
-				!this._ui.container.hasClass( "ui-popup-hidden" ) ) {
-				// effectively rapid-close the popup while leaving the screen intact
-				this._ui.container
-					.addClass( "ui-popup-hidden ui-popup-truncate" )
-					.removeAttr( "style" );
-			}
-		}
-	},
-
-	_handleWindowOrientationchange: function(/* theEvent */) {
-		if ( !this._orientationchangeInProgress && this._isOpen && this._ignoreResizeTo === 0 ) {
-			this._expectResizeEvent();
-			this._orientationchangeInProgress = true;
-		}
-	},
-
-	// When the popup is open, attempting to focus on an element that is not a
-	// child of the popup will redirect focus to the popup
-	_handleDocumentFocusIn: function( theEvent ) {
-		var target,
-			targetElement = theEvent.target,
-			ui = this._ui;
-
-		if ( !this._isOpen ) {
-			return;
-		}
-
-		if ( targetElement !== ui.container[ 0 ] ) {
-			target = $( targetElement );
-			if ( 0 === target.parents().filter( ui.container[ 0 ] ).length ) {
-				$( this.document[ 0 ].activeElement ).one( "focus", function(/* theEvent */) {
-					target.blur();
-				});
-				ui.focusElement.focus();
-				theEvent.preventDefault();
-				theEvent.stopImmediatePropagation();
-				return false;
-			} else if ( ui.focusElement[ 0 ] === ui.container[ 0 ] ) {
-				ui.focusElement = target;
-			}
-		}
-
-		this._ignoreResizeEvents();
-	},
-
-	_themeClassFromOption: function( prefix, value ) {
-		return ( value ? ( value === "none" ? "" : ( prefix + value ) ) : ( prefix + "inherit" ) );
-	},
-
-	_applyTransition: function( value ) {
-		if ( value ) {
-			this._ui.container.removeClass( this._fallbackTransition );
-			if ( value !== "none" ) {
-				this._fallbackTransition = $.mobile._maybeDegradeTransition( value );
-				if ( this._fallbackTransition === "none" ) {
-					this._fallbackTransition = "";
-				}
-				this._ui.container.addClass( this._fallbackTransition );
-			}
-		}
-
-		return this;
-	},
-
-	_setOptions: function( newOptions ) {
-		var currentOptions = this.options,
-			theElement = this.element,
-			screen = this._ui.screen;
-
-		if ( newOptions.wrapperClass !== undefined ) {
-			this._ui.container
-				.removeClass( currentOptions.wrapperClass )
-				.addClass( newOptions.wrapperClass );
-		}
-
-		if ( newOptions.theme !== undefined ) {
-			theElement
-				.removeClass( this._themeClassFromOption( "ui-body-", currentOptions.theme ) )
-				.addClass( this._themeClassFromOption( "ui-body-", newOptions.theme ) );
-		}
-
-		if ( newOptions.overlayTheme !== undefined ) {
-			screen
-				.removeClass( this._themeClassFromOption( "ui-overlay-", currentOptions.overlayTheme ) )
-				.addClass( this._themeClassFromOption( "ui-overlay-", newOptions.overlayTheme ) );
-
-			if ( this._isOpen ) {
-				screen.addClass( "in" );
-			}
-		}
-
-		if ( newOptions.shadow !== undefined ) {
-			theElement.toggleClass( "ui-overlay-shadow", newOptions.shadow );
-		}
-
-		if ( newOptions.corners !== undefined ) {
-			theElement.toggleClass( "ui-corner-all", newOptions.corners );
-		}
-
-		if ( newOptions.transition !== undefined ) {
-			if ( !this._currentTransition ) {
-				this._applyTransition( newOptions.transition );
-			}
-		}
-
-		if ( newOptions.tolerance !== undefined ) {
-			this._setTolerance( newOptions.tolerance );
-		}
-
-		if ( newOptions.disabled !== undefined ) {
-			if ( newOptions.disabled ) {
-				this.close();
-			}
-		}
-
-		return this._super( newOptions );
-	},
-
-	_setTolerance: function( value ) {
-		var tol = { t: 30, r: 15, b: 30, l: 15 },
-			ar;
-
-		if ( value !== undefined ) {
-			ar = String( value ).split( "," );
-
-			$.each( ar, function( idx, val ) { ar[ idx ] = parseInt( val, 10 ); } );
-
-			switch( ar.length ) {
-				// All values are to be the same
-				case 1:
-					if ( !isNaN( ar[ 0 ] ) ) {
-						tol.t = tol.r = tol.b = tol.l = ar[ 0 ];
-					}
-					break;
-
-				// The first value denotes top/bottom tolerance, and the second value denotes left/right tolerance
-				case 2:
-					if ( !isNaN( ar[ 0 ] ) ) {
-						tol.t = tol.b = ar[ 0 ];
-					}
-					if ( !isNaN( ar[ 1 ] ) ) {
-						tol.l = tol.r = ar[ 1 ];
-					}
-					break;
-
-				// The array contains values in the order top, right, bottom, left
-				case 4:
-					if ( !isNaN( ar[ 0 ] ) ) {
-						tol.t = ar[ 0 ];
-					}
-					if ( !isNaN( ar[ 1 ] ) ) {
-						tol.r = ar[ 1 ];
-					}
-					if ( !isNaN( ar[ 2 ] ) ) {
-						tol.b = ar[ 2 ];
-					}
-					if ( !isNaN( ar[ 3 ] ) ) {
-						tol.l = ar[ 3 ];
-					}
-					break;
-
-				default:
-					break;
-			}
-		}
-
-		this._tolerance = tol;
-		return this;
-	},
-
-	_clampPopupWidth: function( infoOnly ) {
-		var menuSize,
-			windowCoordinates = getWindowCoordinates( this.window ),
-			// rectangle within which the popup must fit
-			rectangle = {
-				x: this._tolerance.l,
-				y: windowCoordinates.y + this._tolerance.t,
-				cx: windowCoordinates.cx - this._tolerance.l - this._tolerance.r,
-				cy: windowCoordinates.cy - this._tolerance.t - this._tolerance.b
-			};
-
-		if ( !infoOnly ) {
-			// Clamp the width of the menu before grabbing its size
-			this._ui.container.css( "max-width", rectangle.cx );
-		}
-
-		menuSize = {
-			cx: this._ui.container.outerWidth( true ),
-			cy: this._ui.container.outerHeight( true )
-		};
-
-		return { rc: rectangle, menuSize: menuSize };
-	},
-
-	_calculateFinalLocation: function( desired, clampInfo ) {
-		var returnValue,
-			rectangle = clampInfo.rc,
-			menuSize = clampInfo.menuSize;
-
-		// Center the menu over the desired coordinates, while not going outside
-		// the window tolerances. This will center wrt. the window if the popup is
-		// too large.
-		returnValue = {
-			left: fitSegmentInsideSegment( rectangle.cx, menuSize.cx, rectangle.x, desired.x ),
-			top: fitSegmentInsideSegment( rectangle.cy, menuSize.cy, rectangle.y, desired.y )
-		};
-
-		// Make sure the top of the menu is visible
-		returnValue.top = Math.max( 0, returnValue.top );
-
-		// If the height of the menu is smaller than the height of the document
-		// align the bottom with the bottom of the document
-
-		returnValue.top -= Math.min( returnValue.top,
-			Math.max( 0, returnValue.top + menuSize.cy - this.document.height() ) );
-
-		return returnValue;
-	},
-
-	// Try and center the overlay over the given coordinates
-	_placementCoords: function( desired ) {
-		return this._calculateFinalLocation( desired, this._clampPopupWidth() );
-	},
-
-	_createPrerequisites: function( screenPrerequisite, containerPrerequisite, whenDone ) {
-		var prerequisites,
-			self = this;
-
-		// It is important to maintain both the local variable prerequisites and
-		// self._prerequisites. The local variable remains in the closure of the
-		// functions which call the callbacks passed in. The comparison between the
-		// local variable and self._prerequisites is necessary, because once a
-		// function has been passed to .animationComplete() it will be called next
-		// time an animation completes, even if that's not the animation whose end
-		// the function was supposed to catch (for example, if an abort happens
-		// during the opening animation, the .animationComplete handler is not
-		// called for that animation anymore, but the handler remains attached, so
-		// it is called the next time the popup is opened - making it stale.
-		// Comparing the local variable prerequisites to the widget-level variable
-		// self._prerequisites ensures that callbacks triggered by a stale
-		// .animationComplete will be ignored.
-
-		prerequisites = {
-			screen: $.Deferred(),
-			container: $.Deferred()
-		};
-
-		prerequisites.screen.then( function() {
-			if ( prerequisites === self._prerequisites ) {
-				screenPrerequisite();
-			}
-		});
-
-		prerequisites.container.then( function() {
-			if ( prerequisites === self._prerequisites ) {
-				containerPrerequisite();
-			}
-		});
-
-		$.when( prerequisites.screen, prerequisites.container ).done( function() {
-			if ( prerequisites === self._prerequisites ) {
-				self._prerequisites = null;
-				whenDone();
-			}
-		});
-
-		self._prerequisites = prerequisites;
-	},
-
-	_animate: function( args ) {
-		// NOTE before removing the default animation of the screen
-		//      this had an animate callback that would resolve the deferred
-		//      now the deferred is resolved immediately
-		// TODO remove the dependency on the screen deferred
-		this._ui.screen
-			.removeClass( args.classToRemove )
-			.addClass( args.screenClassToAdd );
-
-		args.prerequisites.screen.resolve();
-
-		if ( args.transition && args.transition !== "none" ) {
-			if ( args.applyTransition ) {
-				this._applyTransition( args.transition );
-			}
-			if ( this._fallbackTransition ) {
-				this._ui.container
-					.addClass( args.containerClassToAdd )
-					.removeClass( args.classToRemove )
-					.animationComplete( $.proxy( args.prerequisites.container, "resolve" ) );
-				return;
-			}
-		}
-		this._ui.container.removeClass( args.classToRemove );
-		args.prerequisites.container.resolve();
-	},
-
-	// The desired coordinates passed in will be returned untouched if no reference element can be identified via
-	// desiredPosition.positionTo. Nevertheless, this function ensures that its return value always contains valid
-	// x and y coordinates by specifying the center middle of the window if the coordinates are absent.
-	// options: { x: coordinate, y: coordinate, positionTo: string: "origin", "window", or jQuery selector
-	_desiredCoords: function( openOptions ) {
-		var offset,
-			dst = null,
-			windowCoordinates = getWindowCoordinates( this.window ),
-			x = openOptions.x,
-			y = openOptions.y,
-			pTo = openOptions.positionTo;
-
-		// Establish which element will serve as the reference
-		if ( pTo && pTo !== "origin" ) {
-			if ( pTo === "window" ) {
-				x = windowCoordinates.cx / 2 + windowCoordinates.x;
-				y = windowCoordinates.cy / 2 + windowCoordinates.y;
-			} else {
-				try {
-					dst = $( pTo );
-				} catch( err ) {
-					dst = null;
-				}
-				if ( dst ) {
-					dst.filter( ":visible" );
-					if ( dst.length === 0 ) {
-						dst = null;
-					}
-				}
-			}
-		}
-
-		// If an element was found, center over it
-		if ( dst ) {
-			offset = dst.offset();
-			x = offset.left + dst.outerWidth() / 2;
-			y = offset.top + dst.outerHeight() / 2;
-		}
-
-		// Make sure x and y are valid numbers - center over the window
-		if ( $.type( x ) !== "number" || isNaN( x ) ) {
-			x = windowCoordinates.cx / 2 + windowCoordinates.x;
-		}
-		if ( $.type( y ) !== "number" || isNaN( y ) ) {
-			y = windowCoordinates.cy / 2 + windowCoordinates.y;
-		}
-
-		return { x: x, y: y };
-	},
-
-	_reposition: function( openOptions ) {
-		// We only care about position-related parameters for repositioning
-		openOptions = {
-			x: openOptions.x,
-			y: openOptions.y,
-			positionTo: openOptions.positionTo
-		};
-		this._trigger( "beforeposition", undefined, openOptions );
-		this._ui.container.offset( this._placementCoords( this._desiredCoords( openOptions ) ) );
-	},
-
-	reposition: function( openOptions ) {
-		if ( this._isOpen ) {
-			this._reposition( openOptions );
-		}
-	},
-
-	_openPrerequisitesComplete: function() {
-		var id = this.element.attr( "id" );
-
-		this._ui.container.addClass( "ui-popup-active" );
-		this._isOpen = true;
-		this._resizeScreen();
-		this._ui.container.attr( "tabindex", "0" ).focus();
-		this._ignoreResizeEvents();
-		if ( id ) {
-			this.document.find( "[aria-haspopup='true'][aria-owns='" +  id + "']" ).attr( "aria-expanded", true );
-		}
-		this._trigger( "afteropen" );
-	},
-
-	_open: function( options ) {
-		var openOptions = $.extend( {}, this.options, options ),
-			// TODO move blacklist to private method
-			androidBlacklist = ( function() {
-				var ua = navigator.userAgent,
-					// Rendering engine is Webkit, and capture major version
-					wkmatch = ua.match( /AppleWebKit\/([0-9\.]+)/ ),
-					wkversion = !!wkmatch && wkmatch[ 1 ],
-					androidmatch = ua.match( /Android (\d+(?:\.\d+))/ ),
-					andversion = !!androidmatch && androidmatch[ 1 ],
-					chromematch = ua.indexOf( "Chrome" ) > -1;
-
-				// Platform is Android, WebKit version is greater than 534.13 ( Android 3.2.1 ) and not Chrome.
-				if ( androidmatch !== null && andversion === "4.0" && wkversion && wkversion > 534.13 && !chromematch ) {
-					return true;
-				}
-				return false;
-			}());
-
-		// Count down to triggering "popupafteropen" - we have two prerequisites:
-		// 1. The popup window animation completes (container())
-		// 2. The screen opacity animation completes (screen())
-		this._createPrerequisites(
-			$.noop,
-			$.noop,
-			$.proxy( this, "_openPrerequisitesComplete" ) );
-
-		this._currentTransition = openOptions.transition;
-		this._applyTransition( openOptions.transition );
-
-		this._ui.screen.removeClass( "ui-screen-hidden" );
-		this._ui.container.removeClass( "ui-popup-truncate" );
-
-		// Give applications a chance to modify the contents of the container before it appears
-		this._reposition( openOptions );
-
-		this._ui.container.removeClass( "ui-popup-hidden" );
-
-		if ( this.options.overlayTheme && androidBlacklist ) {
-			/* TODO: The native browser on Android 4.0.X ("Ice Cream Sandwich") suffers from an issue where the popup overlay appears to be z-indexed above the popup itself when certain other styles exist on the same page -- namely, any element set to `position: fixed` and certain types of input. These issues are reminiscent of previously uncovered bugs in older versions of Android's native browser: https://github.com/scottjehl/Device-Bugs/issues/3
-			This fix closes the following bugs ( I use "closes" with reluctance, and stress that this issue should be revisited as soon as possible ):
-			https://github.com/jquery/jquery-mobile/issues/4816
-			https://github.com/jquery/jquery-mobile/issues/4844
-			https://github.com/jquery/jquery-mobile/issues/4874
-			*/
-
-			// TODO sort out why this._page isn't working
-			this.element.closest( ".ui-page" ).addClass( "ui-popup-open" );
-		}
-		this._animate({
-			additionalCondition: true,
-			transition: openOptions.transition,
-			classToRemove: "",
-			screenClassToAdd: "in",
-			containerClassToAdd: "in",
-			applyTransition: false,
-			prerequisites: this._prerequisites
-		});
-	},
-
-	_closePrerequisiteScreen: function() {
-		this._ui.screen
-			.removeClass( "out" )
-			.addClass( "ui-screen-hidden" );
-	},
-
-	_closePrerequisiteContainer: function() {
-		this._ui.container
-			.removeClass( "reverse out" )
-			.addClass( "ui-popup-hidden ui-popup-truncate" )
-			.removeAttr( "style" );
-	},
-
-	_closePrerequisitesDone: function() {
-		var container = this._ui.container,
-			id = this.element.attr( "id" );
-
-		container.removeAttr( "tabindex" );
-
-		// remove the global mutex for popups
-		$.mobile.popup.active = undefined;
-
-		// Blur elements inside the container, including the container
-		$( ":focus", container[ 0 ] ).add( container[ 0 ] ).blur();
-
-		if ( id ) {
-			this.document.find( "[aria-haspopup='true'][aria-owns='" +  id + "']" ).attr( "aria-expanded", false );
-		}
-
-		// alert users that the popup is closed
-		this._trigger( "afterclose" );
-	},
-
-	_close: function( immediate ) {
-		this._ui.container.removeClass( "ui-popup-active" );
-		this._page.removeClass( "ui-popup-open" );
-
-		this._isOpen = false;
-
-		// Count down to triggering "popupafterclose" - we have two prerequisites:
-		// 1. The popup window reverse animation completes (container())
-		// 2. The screen opacity animation completes (screen())
-		this._createPrerequisites(
-			$.proxy( this, "_closePrerequisiteScreen" ),
-			$.proxy( this, "_closePrerequisiteContainer" ),
-			$.proxy( this, "_closePrerequisitesDone" ) );
-
-		this._animate( {
-			additionalCondition: this._ui.screen.hasClass( "in" ),
-			transition: ( immediate ? "none" : ( this._currentTransition ) ),
-			classToRemove: "in",
-			screenClassToAdd: "out",
-			containerClassToAdd: "reverse out",
-			applyTransition: true,
-			prerequisites: this._prerequisites
-		});
-	},
-
-	_unenhance: function() {
-		if ( this.options.enhanced ) {
-			return;
-		}
-
-		// Put the element back to where the placeholder was and remove the "ui-popup" class
-		this._setOptions( { theme: $.mobile.popup.prototype.options.theme } );
-		this.element
-			// Cannot directly insertAfter() - we need to detach() first, because
-			// insertAfter() will do nothing if the payload div was not attached
-			// to the DOM at the time the widget was created, and so the payload
-			// will remain inside the container even after we call insertAfter().
-			// If that happens and we remove the container a few lines below, we
-			// will cause an infinite recursion - #5244
-			.detach()
-			.insertAfter( this._ui.placeholder )
-			.removeClass( "ui-popup ui-overlay-shadow ui-corner-all ui-body-inherit" );
-		this._ui.screen.remove();
-		this._ui.container.remove();
-		this._ui.placeholder.remove();
-	},
-
-	_destroy: function() {
-		if ( $.mobile.popup.active === this ) {
-			this.element.one( "popupafterclose", $.proxy( this, "_unenhance" ) );
-			this.close();
-		} else {
-			this._unenhance();
-		}
-
-		return this;
-	},
-
-	_closePopup: function( theEvent, data ) {
-		var parsedDst, toUrl,
-			currentOptions = this.options,
-			immediate = false;
-
-		if ( ( theEvent && theEvent.isDefaultPrevented() ) || $.mobile.popup.active !== this ) {
-			return;
-		}
-
-		// restore location on screen
-		window.scrollTo( 0, this._scrollTop );
-
-		if ( theEvent && theEvent.type === "pagebeforechange" && data ) {
-			// Determine whether we need to rapid-close the popup, or whether we can
-			// take the time to run the closing transition
-			if ( typeof data.toPage === "string" ) {
-				parsedDst = data.toPage;
-			} else {
-				parsedDst = data.toPage.jqmData( "url" );
-			}
-			parsedDst = $.mobile.path.parseUrl( parsedDst );
-			toUrl = parsedDst.pathname + parsedDst.search + parsedDst.hash;
-
-			if ( this._myUrl !== $.mobile.path.makeUrlAbsolute( toUrl ) ) {
-				// Going to a different page - close immediately
-				immediate = true;
-			} else {
-				theEvent.preventDefault();
-			}
-		}
-
-		// remove nav bindings
-		this.window.off( currentOptions.closeEvents );
-		// unbind click handlers added when history is disabled
-		this.element.undelegate( currentOptions.closeLinkSelector, currentOptions.closeLinkEvents );
-
-		this._close( immediate );
-	},
-
-	// any navigation event after a popup is opened should close the popup
-	// NOTE the pagebeforechange is bound to catch navigation events that don't
-	//      alter the url (eg, dialogs from popups)
-	_bindContainerClose: function() {
-		this.window
-			.on( this.options.closeEvents, $.proxy( this, "_closePopup" ) );
-	},
-
-	widget: function() {
-		return this._ui.container;
-	},
-
-	// TODO no clear deliniation of what should be here and
-	// what should be in _open. Seems to be "visual" vs "history" for now
-	open: function( options ) {
-		var url, hashkey, activePage, currentIsDialog, hasHash, urlHistory,
-			self = this,
-			currentOptions = this.options;
-
-		// make sure open is idempotent
-		if ( $.mobile.popup.active || currentOptions.disabled ) {
-			return this;
-		}
-
-		// set the global popup mutex
-		$.mobile.popup.active = this;
-		this._scrollTop = this.window.scrollTop();
-
-		// if history alteration is disabled close on navigate events
-		// and leave the url as is
-		if ( !( currentOptions.history ) ) {
-			self._open( options );
-			self._bindContainerClose();
-
-			// When histoy is disabled we have to grab the data-rel
-			// back link clicks so we can close the popup instead of
-			// relying on history to do it for us
-			self.element
-				.delegate( currentOptions.closeLinkSelector, currentOptions.closeLinkEvents, function( theEvent ) {
-					self.close();
-					theEvent.preventDefault();
-				});
-
-			return this;
-		}
-
-		// cache some values for min/readability
-		urlHistory = $.mobile.navigate.history;
-		hashkey = $.mobile.dialogHashKey;
-		activePage = $.mobile.activePage;
-		currentIsDialog = ( activePage ? activePage.hasClass( "ui-dialog" ) : false );
-		this._myUrl = url = urlHistory.getActive().url;
-		hasHash = ( url.indexOf( hashkey ) > -1 ) && !currentIsDialog && ( urlHistory.activeIndex > 0 );
-
-		if ( hasHash ) {
-			self._open( options );
-			self._bindContainerClose();
-			return this;
-		}
-
-		// if the current url has no dialog hash key proceed as normal
-		// otherwise, if the page is a dialog simply tack on the hash key
-		if ( url.indexOf( hashkey ) === -1 && !currentIsDialog ) {
-			url = url + (url.indexOf( "#" ) > -1 ? hashkey : "#" + hashkey);
-		} else {
-			url = $.mobile.path.parseLocation().hash + hashkey;
-		}
-
-		// Tack on an extra hashkey if this is the first page and we've just reconstructed the initial hash
-		if ( urlHistory.activeIndex === 0 && url === urlHistory.initialDst ) {
-			url += hashkey;
-		}
-
-		// swallow the the initial navigation event, and bind for the next
-		this.window.one( "beforenavigate", function( theEvent ) {
-			theEvent.preventDefault();
-			self._open( options );
-			self._bindContainerClose();
-		});
-
-		this.urlAltered = true;
-		$.mobile.navigate( url, { role: "dialog" } );
-
-		return this;
-	},
-
-	close: function() {
-		// make sure close is idempotent
-		if ( $.mobile.popup.active !== this ) {
-			return this;
-		}
-
-		this._scrollTop = this.window.scrollTop();
-
-		if ( this.options.history && this.urlAltered ) {
-			$.mobile.back();
-			this.urlAltered = false;
-		} else {
-			// simulate the nav bindings having fired
-			this._closePopup();
-		}
-
-		return this;
-	}
-});
-
-// TODO this can be moved inside the widget
-$.mobile.popup.handleLink = function( $link ) {
-	var offset,
-		path = $.mobile.path,
-
-		// NOTE make sure to get only the hash from the href because ie7 (wp7)
-		//      returns the absolute href in this case ruining the element selection
-		popup = $( path.hashToSelector( path.parseUrl( $link.attr( "href" ) ).hash ) ).first();
-
-	if ( popup.length > 0 && popup.data( "mobile-popup" ) ) {
-		offset = $link.offset();
-		popup.popup( "open", {
-			x: offset.left + $link.outerWidth() / 2,
-			y: offset.top + $link.outerHeight() / 2,
-			transition: $link.jqmData( "transition" ),
-			positionTo: $link.jqmData( "position-to" )
-		});
-	}
-
-	//remove after delay
-	setTimeout( function() {
-		$link.removeClass( $.mobile.activeBtnClass );
-	}, 300 );
-};
-
-// TODO move inside _create
-$.mobile.document.on( "pagebeforechange", function( theEvent, data ) {
-	if ( data.options.role === "popup" ) {
-		$.mobile.popup.handleLink( data.options.link );
-		theEvent.preventDefault();
-	}
-});
-
-})( jQuery );
-
-/*
-* custom "selectmenu" plugin
-*/
-
-(function( $, undefined ) {
-
-var unfocusableItemSelector = ".ui-disabled,.ui-state-disabled,.ui-li-divider,.ui-screen-hidden,:jqmData(role='placeholder')",
-	goToAdjacentItem = function( item, target, direction ) {
-		var adjacent = item[ direction + "All" ]()
-			.not( unfocusableItemSelector )
-			.first();
-
-		// if there's a previous option, focus it
-		if ( adjacent.length ) {
-			target
-				.blur()
-				.attr( "tabindex", "-1" );
-
-			adjacent.find( "a" ).first().focus();
-		}
-	};
-
-$.widget( "mobile.selectmenu", $.mobile.selectmenu, {
-	_create: function() {
-		var o = this.options;
-
-		// Custom selects cannot exist inside popups, so revert the "nativeMenu"
-		// option to true if a parent is a popup
-		o.nativeMenu = o.nativeMenu || ( this.element.parents( ":jqmData(role='popup'),:mobile-popup" ).length > 0 );
-
-		return this._super();
-	},
-
-	_handleSelectFocus: function() {
-		this.element.blur();
-		this.button.focus();
-	},
-
-	_handleKeydown: function( event ) {
-		this._super( event );
-		this._handleButtonVclickKeydown( event );
-	},
-
-	_handleButtonVclickKeydown: function( event ) {
-		if ( this.options.disabled || this.isOpen ) {
-			return;
-		}
-
-		if (event.type === "vclick" ||
-				event.keyCode && (event.keyCode === $.mobile.keyCode.ENTER || event.keyCode === $.mobile.keyCode.SPACE)) {
-
-			this._decideFormat();
-			if ( this.menuType === "overlay" ) {
-				this.button.attr( "href", "#" + this.popupId ).attr( "data-" + ( $.mobile.ns || "" ) + "rel", "popup" );
-			} else {
-				this.button.attr( "href", "#" + this.dialogId ).attr( "data-" + ( $.mobile.ns || "" ) + "rel", "dialog" );
-			}
-			this.isOpen = true;
-			// Do not prevent default, so the navigation may have a chance to actually open the chosen format
-		}
-	},
-
-	_handleListFocus: function( e ) {
-		var params = ( e.type === "focusin" ) ?
-			{ tabindex: "0", event: "vmouseover" }:
-			{ tabindex: "-1", event: "vmouseout" };
-
-		$( e.target )
-			.attr( "tabindex", params.tabindex )
-			.trigger( params.event );
-	},
-
-	_handleListKeydown: function( event ) {
-		var target = $( event.target ),
-			li = target.closest( "li" );
-
-		// switch logic based on which key was pressed
-		switch ( event.keyCode ) {
-			// up or left arrow keys
-		case 38:
-			goToAdjacentItem( li, target, "prev" );
-			return false;
-			// down or right arrow keys
-		case 40:
-			goToAdjacentItem( li, target, "next" );
-			return false;
-			// If enter or space is pressed, trigger click
-		case 13:
-		case 32:
-			target.trigger( "click" );
-			return false;
-		}
-	},
-
-	_handleMenuPageHide: function() {
-		// TODO centralize page removal binding / handling in the page plugin.
-		// Suggestion from @jblas to do refcounting
-		//
-		// TODO extremely confusing dependency on the open method where the pagehide.remove
-		// bindings are stripped to prevent the parent page from disappearing. The way
-		// we're keeping pages in the DOM right now sucks
-		//
-		// rebind the page remove that was unbound in the open function
-		// to allow for the parent page removal from actions other than the use
-		// of a dialog sized custom select
-		//
-		// doing this here provides for the back button on the custom select dialog
-		this.thisPage.page( "bindRemove" );
-	},
-
-	_handleHeaderCloseClick: function() {
-		if ( this.menuType === "overlay" ) {
-			this.close();
-			return false;
-		}
-	},
-
-	build: function() {
-		var selectId, popupId, dialogId, label, thisPage, isMultiple, menuId,
-			themeAttr, overlayTheme, overlayThemeAttr, dividerThemeAttr,
-			menuPage, listbox, list, header, headerTitle, menuPageContent,
-			menuPageClose, headerClose, self,
-			o = this.options;
-
-		if ( o.nativeMenu ) {
-			return this._super();
-		}
-
-		self = this;
-		selectId = this.selectId;
-		popupId = selectId + "-listbox";
-		dialogId = selectId + "-dialog";
-		label = this.label;
-		thisPage = this.element.closest( ".ui-page" );
-		isMultiple = this.element[ 0 ].multiple;
-		menuId = selectId + "-menu";
-		themeAttr = o.theme ? ( " data-" + $.mobile.ns + "theme='" + o.theme + "'" ) : "";
-		overlayTheme = o.overlayTheme || o.theme || null;
-		overlayThemeAttr = overlayTheme ? ( " data-" + $.mobile.ns +
-			"overlay-theme='" + overlayTheme + "'" ) : "";
-		dividerThemeAttr = ( o.dividerTheme && isMultiple ) ? ( " data-" + $.mobile.ns + "divider-theme='" + o.dividerTheme + "'" ) : "";
-		menuPage = $( "<div data-" + $.mobile.ns + "role='dialog' class='ui-selectmenu' id='" + dialogId + "'" + themeAttr + overlayThemeAttr + ">" +
-			"<div data-" + $.mobile.ns + "role='header'>" +
-			"<div class='ui-title'>" + label.getEncodedText() + "</div>"+
-			"</div>"+
-			"<div data-" + $.mobile.ns + "role='content'></div>"+
-			"</div>" );
-		listbox = $( "<div id='" + popupId + "' class='ui-selectmenu'></div>" ).insertAfter( this.select ).popup({ theme: o.overlayTheme });
-		list = $( "<ul class='ui-selectmenu-list' id='" + menuId + "' role='listbox' aria-labelledby='" + this.buttonId + "'" + themeAttr + dividerThemeAttr + "></ul>" ).appendTo( listbox );
-		header = $( "<div class='ui-header ui-bar-" + ( o.theme ? o.theme : "inherit" ) + "'></div>" ).prependTo( listbox );
-		headerTitle = $( "<h1 class='ui-title'></h1>" ).appendTo( header );
-
-		if ( this.isMultiple ) {
-			headerClose = $( "<a>", {
-				"role": "button",
-				"text": o.closeText,
-				"href": "#",
-				"class": "ui-btn ui-corner-all ui-btn-left ui-btn-icon-notext ui-icon-delete"
-			}).appendTo( header );
-		}
-
-		$.extend( this, {
-			selectId: selectId,
-			menuId: menuId,
-			popupId: popupId,
-			dialogId: dialogId,
-			thisPage: thisPage,
-			menuPage: menuPage,
-			label: label,
-			isMultiple: isMultiple,
-			theme: o.theme,
-			listbox: listbox,
-			list: list,
-			header: header,
-			headerTitle: headerTitle,
-			headerClose: headerClose,
-			menuPageContent: menuPageContent,
-			menuPageClose: menuPageClose,
-			placeholder: ""
-		});
-
-		// Create list from select, update state
-		this.refresh();
-
-		if ( this._origTabIndex === undefined ) {
-			// Map undefined to false, because this._origTabIndex === undefined
-			// indicates that we have not yet checked whether the select has
-			// originally had a tabindex attribute, whereas false indicates that
-			// we have checked the select for such an attribute, and have found
-			// none present.
-			this._origTabIndex = ( this.select[ 0 ].getAttribute( "tabindex" ) === null ) ? false : this.select.attr( "tabindex" );
-		}
-		this.select.attr( "tabindex", "-1" );
-		this._on( this.select, { focus : "_handleSelectFocus" } );
-
-		// Button events
-		this._on( this.button, {
-			vclick: "_handleButtonVclickKeydown"
-		});
-
-		// Events for list items
-		this.list.attr( "role", "listbox" );
-		this._on( this.list, {
-			focusin : "_handleListFocus",
-			focusout : "_handleListFocus",
-			keydown: "_handleListKeydown"
-		});
-		this.list
-			.delegate( "li:not(.ui-disabled,.ui-state-disabled,.ui-li-divider)", "click", function( event ) {
-
-				// index of option tag to be selected
-				var oldIndex = self.select[ 0 ].selectedIndex,
-					newIndex = $.mobile.getAttribute( this, "option-index" ),
-					option = self._selectOptions().eq( newIndex )[ 0 ];
-
-				// toggle selected status on the tag for multi selects
-				option.selected = self.isMultiple ? !option.selected : true;
-
-				// toggle checkbox class for multiple selects
-				if ( self.isMultiple ) {
-					$( this ).find( "a" )
-						.toggleClass( "ui-checkbox-on", option.selected )
-						.toggleClass( "ui-checkbox-off", !option.selected );
-				}
-
-				// trigger change if value changed
-				if ( self.isMultiple || oldIndex !== newIndex ) {
-					self.select.trigger( "change" );
-				}
-
-				// hide custom select for single selects only - otherwise focus clicked item
-				// We need to grab the clicked item the hard way, because the list may have been rebuilt
-				if ( self.isMultiple ) {
-					self.list.find( "li:not(.ui-li-divider)" ).eq( newIndex )
-						.find( "a" ).first().focus();
-				}
-				else {
-					self.close();
-				}
-
-				event.preventDefault();
-			});
-
-		// button refocus ensures proper height calculation
-		// by removing the inline style and ensuring page inclusion
-		this._on( this.menuPage, { pagehide: "_handleMenuPageHide" } );
-
-		// Events on the popup
-		this._on( this.listbox, { popupafterclose: "close" } );
-
-		// Close button on small overlays
-		if ( this.isMultiple ) {
-			this._on( this.headerClose, { click: "_handleHeaderCloseClick" } );
-		}
-
-		return this;
-	},
-
-	_isRebuildRequired: function() {
-		var list = this.list.find( "li" ),
-			options = this._selectOptions().not( ".ui-screen-hidden" );
-
-		// TODO exceedingly naive method to determine difference
-		// ignores value changes etc in favor of a forcedRebuild
-		// from the user in the refresh method
-		return options.text() !== list.text();
-	},
-
-	selected: function() {
-		return this._selectOptions().filter( ":selected:not( :jqmData(placeholder='true') )" );
-	},
-
-	refresh: function( force ) {
-		var self, indices;
-
-		if ( this.options.nativeMenu ) {
-			return this._super( force );
-		}
-
-		self = this;
-		if ( force || this._isRebuildRequired() ) {
-			self._buildList();
-		}
-
-		indices = this.selectedIndices();
-
-		self.setButtonText();
-		self.setButtonCount();
-
-		self.list.find( "li:not(.ui-li-divider)" )
-			.find( "a" ).removeClass( $.mobile.activeBtnClass ).end()
-			.attr( "aria-selected", false )
-			.each(function( i ) {
-
-				if ( $.inArray( i, indices ) > -1 ) {
-					var item = $( this );
-
-					// Aria selected attr
-					item.attr( "aria-selected", true );
-
-					// Multiple selects: add the "on" checkbox state to the icon
-					if ( self.isMultiple ) {
-						item.find( "a" ).removeClass( "ui-checkbox-off" ).addClass( "ui-checkbox-on" );
-					} else {
-						if ( item.hasClass( "ui-screen-hidden" ) ) {
-							item.next().find( "a" ).addClass( $.mobile.activeBtnClass );
-						} else {
-							item.find( "a" ).addClass( $.mobile.activeBtnClass );
-						}
-					}
-				}
-			});
-	},
-
-	close: function() {
-		if ( this.options.disabled || !this.isOpen ) {
-			return;
-		}
-
-		var self = this;
-
-		if ( self.menuType === "page" ) {
-			self.menuPage.dialog( "close" );
-			self.list.appendTo( self.listbox );
-		} else {
-			self.listbox.popup( "close" );
-		}
-
-		self._focusButton();
-		// allow the dialog to be closed again
-		self.isOpen = false;
-	},
-
-	open: function() {
-		this.button.click();
-	},
-
-	_focusMenuItem: function() {
-		var selector = this.list.find( "a." + $.mobile.activeBtnClass );
-		if ( selector.length === 0 ) {
-			selector = this.list.find( "li:not(" + unfocusableItemSelector + ") a.ui-btn" );
-		}
-		selector.first().focus();
-	},
-
-	_decideFormat: function() {
-		var self = this,
-			$window = this.window,
-			selfListParent = self.list.parent(),
-			menuHeight = selfListParent.outerHeight(),
-			scrollTop = $window.scrollTop(),
-			btnOffset = self.button.offset().top,
-			screenHeight = $window.height();
-
-		if ( menuHeight > screenHeight - 80 || !$.support.scrollTop ) {
-
-			self.menuPage.appendTo( $.mobile.pageContainer ).page();
-			self.menuPageContent = self.menuPage.find( ".ui-content" );
-			self.menuPageClose = self.menuPage.find( ".ui-header a" );
-
-			// prevent the parent page from being removed from the DOM,
-			// otherwise the results of selecting a list item in the dialog
-			// fall into a black hole
-			self.thisPage.unbind( "pagehide.remove" );
-
-			//for WebOS/Opera Mini (set lastscroll using button offset)
-			if ( scrollTop === 0 && btnOffset > screenHeight ) {
-				self.thisPage.one( "pagehide", function() {
-					$( this ).jqmData( "lastScroll", btnOffset );
-				});
-			}
-
-			self.menuPage.one( {
-				pageshow: $.proxy( this, "_focusMenuItem" ),
-				pagehide: $.proxy( this, "close" )
-			});
-
-			self.menuType = "page";
-			self.menuPageContent.append( self.list );
-			self.menuPage.find( "div .ui-title" ).text( self.label.text() );
-		} else {
-			self.menuType = "overlay";
-
-			self.listbox.one( { popupafteropen: $.proxy( this, "_focusMenuItem" ) } );
-		}
-	},
-
-	_buildList: function() {
-		var self = this,
-			o = this.options,
-			placeholder = this.placeholder,
-			needPlaceholder = true,
-			dataIcon = "false",
-			$options, numOptions, select,
-			dataPrefix = "data-" + $.mobile.ns,
-			dataIndexAttr = dataPrefix + "option-index",
-			dataIconAttr = dataPrefix + "icon",
-			dataRoleAttr = dataPrefix + "role",
-			dataPlaceholderAttr = dataPrefix + "placeholder",
-			fragment = document.createDocumentFragment(),
-			isPlaceholderItem = false,
-			optGroup,
-			i,
-			option, $option, parent, text, anchor, classes,
-			optLabel, divider, item;
-
-		self.list.empty().filter( ".ui-listview" ).listview( "destroy" );
-		$options = this._selectOptions();
-		numOptions = $options.length;
-		select = this.select[ 0 ];
-
-		for ( i = 0; i < numOptions;i++, isPlaceholderItem = false) {
-			option = $options[i];
-			$option = $( option );
-
-			// Do not create options based on ui-screen-hidden select options
-			if ( $option.hasClass( "ui-screen-hidden" ) ) {
-				continue;
-			}
-
-			parent = option.parentNode;
-			text = $option.text();
-			anchor  = document.createElement( "a" );
-			classes = [];
-
-			anchor.setAttribute( "href", "#" );
-			anchor.appendChild( document.createTextNode( text ) );
-
-			// Are we inside an optgroup?
-			if ( parent !== select && parent.nodeName.toLowerCase() === "optgroup" ) {
-				optLabel = parent.getAttribute( "label" );
-				if ( optLabel !== optGroup ) {
-					divider = document.createElement( "li" );
-					divider.setAttribute( dataRoleAttr, "list-divider" );
-					divider.setAttribute( "role", "option" );
-					divider.setAttribute( "tabindex", "-1" );
-					divider.appendChild( document.createTextNode( optLabel ) );
-					fragment.appendChild( divider );
-					optGroup = optLabel;
-				}
-			}
-
-			if ( needPlaceholder && ( !option.getAttribute( "value" ) || text.length === 0 || $option.jqmData( "placeholder" ) ) ) {
-				needPlaceholder = false;
-				isPlaceholderItem = true;
-
-				// If we have identified a placeholder, record the fact that it was
-				// us who have added the placeholder to the option and mark it
-				// retroactively in the select as well
-				if ( null === option.getAttribute( dataPlaceholderAttr ) ) {
-					this._removePlaceholderAttr = true;
-				}
-				option.setAttribute( dataPlaceholderAttr, true );
-				if ( o.hidePlaceholderMenuItems ) {
-					classes.push( "ui-screen-hidden" );
-				}
-				if ( placeholder !== text ) {
-					placeholder = self.placeholder = text;
-				}
-			}
-
-			item = document.createElement( "li" );
-			if ( option.disabled ) {
-				classes.push( "ui-state-disabled" );
-				item.setAttribute( "aria-disabled", true );
-			}
-			item.setAttribute( dataIndexAttr, i );
-			item.setAttribute( dataIconAttr, dataIcon );
-			if ( isPlaceholderItem ) {
-				item.setAttribute( dataPlaceholderAttr, true );
-			}
-			item.className = classes.join( " " );
-			item.setAttribute( "role", "option" );
-			anchor.setAttribute( "tabindex", "-1" );
-			if ( this.isMultiple ) {
-				$( anchor ).addClass( "ui-btn ui-checkbox-off ui-btn-icon-right" );
-			}
-
-			item.appendChild( anchor );
-			fragment.appendChild( item );
-		}
-
-		self.list[0].appendChild( fragment );
-
-		// Hide header if it's not a multiselect and there's no placeholder
-		if ( !this.isMultiple && !placeholder.length ) {
-			this.header.addClass( "ui-screen-hidden" );
-		} else {
-			this.headerTitle.text( this.placeholder );
-		}
-
-		// Now populated, create listview
-		self.list.listview();
-	},
-
-	_button: function() {
-		return this.options.nativeMenu ?
-			this._super() :
-			$( "<a>", {
-				"href": "#",
-				"role": "button",
-				// TODO value is undefined at creation
-				"id": this.buttonId,
-				"aria-haspopup": "true",
-
-				// TODO value is undefined at creation
-				"aria-owns": this.menuId
-			});
-	},
-
-	_destroy: function() {
-
-		if ( !this.options.nativeMenu ) {
-			this.close();
-
-			// Restore the tabindex attribute to its original value
-			if ( this._origTabIndex !== undefined ) {
-				if ( this._origTabIndex !== false ) {
-					this.select.attr( "tabindex", this._origTabIndex );
-				} else {
-					this.select.removeAttr( "tabindex" );
-				}
-			}
-
-			// Remove the placeholder attribute if we were the ones to add it
-			if ( this._removePlaceholderAttr ) {
-				this._selectOptions().removeAttr( "data-" + $.mobile.ns + "placeholder" );
-			}
-
-			// Remove the popup
-			this.listbox.remove();
-
-			// Remove the dialog
-			this.menuPage.remove();
-		}
-
-		// Chain up
-		this._super();
-	}
-});
-
-})( jQuery );
-
-
-// buttonMarkup is deprecated as of 1.4.0 and will be removed in 1.5.0.
-
-(function( $, undefined ) {
-
-// General policy: Do not access data-* attributes except during enhancement.
-// In all other cases we determine the state of the button exclusively from its
-// className. That's why optionsToClasses expects a full complement of options,
-// and the jQuery plugin completes the set of options from the default values.
-
-// Map classes to buttonMarkup boolean options - used in classNameToOptions()
-var reverseBoolOptionMap = {
-		"ui-shadow" : "shadow",
-		"ui-corner-all" : "corners",
-		"ui-btn-inline" : "inline",
-		"ui-shadow-icon" : "iconshadow", /* TODO: Remove in 1.5 */
-		"ui-mini" : "mini"
-	},
-	getAttrFixed = function() {
-		var ret = $.mobile.getAttribute.apply( this, arguments );
-
-		return ( ret == null ? undefined : ret );
-	},
-	capitalLettersRE = /[A-Z]/g;
-
-// optionsToClasses:
-// @options: A complete set of options to convert to class names.
-// @existingClasses: extra classes to add to the result
-//
-// Converts @options to buttonMarkup classes and returns the result as an array
-// that can be converted to an element's className with .join( " " ). All
-// possible options must be set inside @options. Use $.fn.buttonMarkup.defaults
-// to get a complete set and use $.extend to override your choice of options
-// from that set.
-function optionsToClasses( options, existingClasses ) {
-	var classes = existingClasses ? existingClasses : [];
-
-	// Add classes to the array - first ui-btn
-	classes.push( "ui-btn" );
-
-	// If there is a theme
-	if ( options.theme ) {
-		classes.push( "ui-btn-" + options.theme );
-	}
-
-	// If there's an icon, add the icon-related classes
-	if ( options.icon ) {
-		classes = classes.concat([
-			"ui-icon-" + options.icon,
-			"ui-btn-icon-" + options.iconpos
-		]);
-		if ( options.iconshadow ) {
-			classes.push( "ui-shadow-icon" ); /* TODO: Remove in 1.5 */
-		}
-	}
-
-	// Add the appropriate class for each boolean option
-	if ( options.inline ) {
-		classes.push( "ui-btn-inline" );
-	}
-	if ( options.shadow ) {
-		classes.push( "ui-shadow" );
-	}
-	if ( options.corners ) {
-		classes.push( "ui-corner-all" );
-	}
-	if ( options.mini ) {
-		classes.push( "ui-mini" );
-	}
-
-	// Create a string from the array and return it
-	return classes;
-}
-
-// classNameToOptions:
-// @classes: A string containing a .className-style space-separated class list
-//
-// Loops over @classes and calculates an options object based on the
-// buttonMarkup-related classes it finds. It records unrecognized classes in an
-// array.
-//
-// Returns: An object containing the following items:
-//
-// "options": buttonMarkup options found to be present because of the
-// presence/absence of corresponding classes
-//
-// "unknownClasses": a string containing all the non-buttonMarkup-related
-// classes found in @classes
-//
-// "alreadyEnhanced": A boolean indicating whether the ui-btn class was among
-// those found to be present
-function classNameToOptions( classes ) {
-	var idx, map, unknownClass,
-		alreadyEnhanced = false,
-		noIcon = true,
-		o = {
-			icon: "",
-			inline: false,
-			shadow: false,
-			corners: false,
-			iconshadow: false,
-			mini: false
-		},
-		unknownClasses = [];
-
-	classes = classes.split( " " );
-
-	// Loop over the classes
-	for ( idx = 0 ; idx < classes.length ; idx++ ) {
-
-		// Assume it's an unrecognized class
-		unknownClass = true;
-
-		// Recognize boolean options from the presence of classes
-		map = reverseBoolOptionMap[ classes[ idx ] ];
-		if ( map !== undefined ) {
-			unknownClass = false;
-			o[ map ] = true;
-
-		// Recognize the presence of an icon and establish the icon position
-		} else if ( classes[ idx ].indexOf( "ui-btn-icon-" ) === 0 ) {
-			unknownClass = false;
-			noIcon = false;
-			o.iconpos = classes[ idx ].substring( 12 );
-
-		// Establish which icon is present
-		} else if ( classes[ idx ].indexOf( "ui-icon-" ) === 0 ) {
-			unknownClass = false;
-			o.icon = classes[ idx ].substring( 8 );
-
-		// Establish the theme - this recognizes one-letter theme swatch names
-		} else if ( classes[ idx ].indexOf( "ui-btn-" ) === 0 && classes[ idx ].length === 8 ) {
-			unknownClass = false;
-			o.theme = classes[ idx ].substring( 7 );
-
-		// Recognize that this element has already been buttonMarkup-enhanced
-		} else if ( classes[ idx ] === "ui-btn" ) {
-			unknownClass = false;
-			alreadyEnhanced = true;
-		}
-
-		// If this class has not been recognized, add it to the list
-		if ( unknownClass ) {
-			unknownClasses.push( classes[ idx ] );
-		}
-	}
-
-	// If a "ui-btn-icon-*" icon position class is absent there cannot be an icon
-	if ( noIcon ) {
-		o.icon = "";
-	}
-
-	return {
-		options: o,
-		unknownClasses: unknownClasses,
-		alreadyEnhanced: alreadyEnhanced
-	};
-}
-
-function camelCase2Hyphenated( c ) {
-	return "-" + c.toLowerCase();
-}
-
-// $.fn.buttonMarkup:
-// DOM: gets/sets .className
-//
-// @options: options to apply to the elements in the jQuery object
-// @overwriteClasses: boolean indicating whether to honour existing classes
-//
-// Calculates the classes to apply to the elements in the jQuery object based on
-// the options passed in. If @overwriteClasses is true, it sets the className
-// property of each element in the jQuery object to the buttonMarkup classes
-// it calculates based on the options passed in.
-//
-// If you wish to preserve any classes that are already present on the elements
-// inside the jQuery object, including buttonMarkup-related classes that were
-// added by a previous call to $.fn.buttonMarkup() or during page enhancement
-// then you should omit @overwriteClasses or set it to false.
-$.fn.buttonMarkup = function( options, overwriteClasses ) {
-	var idx, data, el, retrievedOptions, optionKey,
-		defaults = $.fn.buttonMarkup.defaults;
-
-	for ( idx = 0 ; idx < this.length ; idx++ ) {
-		el = this[ idx ];
-		data = overwriteClasses ?
-
-			// Assume this element is not enhanced and ignore its classes
-			{ alreadyEnhanced: false, unknownClasses: [] } :
-
-			// Otherwise analyze existing classes to establish existing options and
-			// classes
-			classNameToOptions( el.className );
-
-		retrievedOptions = $.extend( {},
-
-			// If the element already has the class ui-btn, then we assume that
-			// it has passed through buttonMarkup before - otherwise, the options
-			// returned by classNameToOptions do not correctly reflect the state of
-			// the element
-			( data.alreadyEnhanced ? data.options : {} ),
-
-			// Finally, apply the options passed in
-			options );
-
-		// If this is the first call on this element, retrieve remaining options
-		// from the data-attributes
-		if ( !data.alreadyEnhanced ) {
-			for ( optionKey in defaults ) {
-				if ( retrievedOptions[ optionKey ] === undefined ) {
-					retrievedOptions[ optionKey ] = getAttrFixed( el,
-						optionKey.replace( capitalLettersRE, camelCase2Hyphenated )
-					);
-				}
-			}
-		}
-
-		el.className = optionsToClasses(
-
-			// Merge all the options and apply them as classes
-			$.extend( {},
-
-				// The defaults form the basis
-				defaults,
-
-				// Add the computed options
-				retrievedOptions
-			),
-
-			// ... and re-apply any unrecognized classes that were found
-			data.unknownClasses ).join( " " );
-		if ( el.tagName.toLowerCase() !== "button" ) {
-			el.setAttribute( "role", "button" );
-		}
-	}
-
-	return this;
-};
-
-// buttonMarkup defaults. This must be a complete set, i.e., a value must be
-// given here for all recognized options
-$.fn.buttonMarkup.defaults = {
-	icon: "",
-	iconpos: "left",
-	theme: null,
-	inline: false,
-	shadow: true,
-	corners: true,
-	iconshadow: false, /* TODO: Remove in 1.5. Option deprecated in 1.4. */
-	mini: false
-};
-
-$.extend( $.fn.buttonMarkup, {
-	initSelector: "a:jqmData(role='button'), .ui-bar > a, .ui-bar > :jqmData(role='controlgroup') > a, button"
-});
-
-})( jQuery );
-
-
-(function( $, undefined ) {
-
-$.widget( "mobile.controlgroup", $.extend( {
-	options: {
-		enhanced: false,
-		theme: null,
-		shadow: false,
-		corners: true,
-		excludeInvisible: true,
-		type: "vertical",
-		mini: false
-	},
-
-	_create: function() {
-		var elem = this.element,
-			opts = this.options;
-
-		// Run buttonmarkup
-		if ( $.fn.buttonMarkup ) {
-			this.element.find( $.fn.buttonMarkup.initSelector ).buttonMarkup();
-		}
-		// Enhance child widgets
-		$.each( this._childWidgets, $.proxy( function( number, widgetName ) {
-			if ( $.mobile[ widgetName ] ) {
-				this.element.find( $.mobile[ widgetName ].initSelector ).not( $.mobile.page.prototype.keepNativeSelector() )[ widgetName ]();
-			}
-		}, this ));
-
-		$.extend( this, {
-			_ui: null,
-			_initialRefresh: true
-		});
-
-		if ( opts.enhanced ) {
-			this._ui = {
-				groupLegend: elem.children( ".ui-controlgroup-label" ).children(),
-				childWrapper: elem.children( ".ui-controlgroup-controls" )
-			};
-		} else {
-			this._ui = this._enhance();
-		}
-
-	},
-
-	_childWidgets: [ "checkboxradio", "selectmenu", "button" ],
-
-	_themeClassFromOption: function( value ) {
-		return ( value ? ( value === "none" ? "" : "ui-group-theme-" + value ) : "" );
-	},
-
-	_enhance: function() {
-		var elem = this.element,
-			opts = this.options,
-			ui = {
-				groupLegend: elem.children( "legend" ),
-				childWrapper: elem
-					.addClass( "ui-controlgroup " +
-						"ui-controlgroup-" +
-							( opts.type === "horizontal" ? "horizontal" : "vertical" ) + " " +
-						this._themeClassFromOption( opts.theme ) + " " +
-						( opts.corners ? "ui-corner-all " : "" ) +
-						( opts.mini ? "ui-mini " : "" ) )
-					.wrapInner( "<div " +
-						"class='ui-controlgroup-controls " +
-							( opts.shadow === true ? "ui-shadow" : "" ) + "'></div>" )
-					.children()
-			};
-
-		if ( ui.groupLegend.length > 0 ) {
-			$( "<div role='heading' class='ui-controlgroup-label'></div>" )
-				.append( ui.groupLegend )
-				.prependTo( elem );
-		}
-
-		return ui;
-	},
-
-	_init: function() {
-		this.refresh();
-	},
-
-	_setOptions: function( options ) {
-		var callRefresh, returnValue,
-			elem = this.element;
-
-		// Must have one of horizontal or vertical
-		if ( options.type !== undefined ) {
-			elem
-				.removeClass( "ui-controlgroup-horizontal ui-controlgroup-vertical" )
-				.addClass( "ui-controlgroup-" + ( options.type === "horizontal" ? "horizontal" : "vertical" ) );
-			callRefresh = true;
-		}
-
-		if ( options.theme !== undefined ) {
-			elem
-				.removeClass( this._themeClassFromOption( this.options.theme ) )
-				.addClass( this._themeClassFromOption( options.theme ) );
-		}
-
-		if ( options.corners !== undefined ) {
-			elem.toggleClass( "ui-corner-all", options.corners );
-		}
-
-		if ( options.mini !== undefined ) {
-			elem.toggleClass( "ui-mini", options.mini );
-		}
-
-		if ( options.shadow !== undefined ) {
-			this._ui.childWrapper.toggleClass( "ui-shadow", options.shadow );
-		}
-
-		if ( options.excludeInvisible !== undefined ) {
-			this.options.excludeInvisible = options.excludeInvisible;
-			callRefresh = true;
-		}
-
-		returnValue = this._super( options );
-
-		if ( callRefresh ) {
-			this.refresh();
-		}
-
-		return returnValue;
-	},
-
-	container: function() {
-		return this._ui.childWrapper;
-	},
-
-	refresh: function() {
-		var $el = this.container(),
-			els = $el.find( ".ui-btn" ).not( ".ui-slider-handle" ),
-			create = this._initialRefresh;
-		if ( $.mobile.checkboxradio ) {
-			$el.find( ":mobile-checkboxradio" ).checkboxradio( "refresh" );
-		}
-		this._addFirstLastClasses( els,
-			this.options.excludeInvisible ? this._getVisibles( els, create ) : els,
-			create );
-		this._initialRefresh = false;
-	},
-
-	// Caveat: If the legend is not the first child of the controlgroup at enhance
-	// time, it will be after _destroy().
-	_destroy: function() {
-		var ui, buttons,
-			opts = this.options;
-
-		if ( opts.enhanced ) {
-			return this;
-		}
-
-		ui = this._ui;
-		buttons = this.element
-			.removeClass( "ui-controlgroup " +
-				"ui-controlgroup-horizontal ui-controlgroup-vertical ui-corner-all ui-mini " +
-				this._themeClassFromOption( opts.theme ) )
-			.find( ".ui-btn" )
-			.not( ".ui-slider-handle" );
-
-		this._removeFirstLastClasses( buttons );
-
-		ui.groupLegend.unwrap();
-		ui.childWrapper.children().unwrap();
-	}
-}, $.mobile.behaviors.addFirstLastClasses ) );
-
-})(jQuery);
-
-(function( $, undefined ) {
-
-	$.widget( "mobile.toolbar", {
-		initSelector: ":jqmData(role='footer'), :jqmData(role='header')",
-
-		options: {
-			theme: null,
-			addBackBtn: false,
-			backBtnTheme: null,
-			backBtnText: "Back"
-		},
-
-		_create: function() {
-			var leftbtn, rightbtn,
-				role =  this.element.is( ":jqmData(role='header')" ) ? "header" : "footer",
-				page = this.element.closest( ".ui-page" );
-			if ( page.length === 0 ) {
-				page = false;
-				this._on( this.document, {
-					"pageshow": "refresh"
-				});
-			}
-			$.extend( this, {
-				role: role,
-				page: page,
-				leftbtn: leftbtn,
-				rightbtn: rightbtn
-			});
-			this.element.attr( "role", role === "header" ? "banner" : "contentinfo" ).addClass( "ui-" + role );
-			this.refresh();
-			this._setOptions( this.options );
-		},
-		_setOptions: function( o ) {
-			if ( o.addBackBtn !== undefined ) {
-				if ( this.options.addBackBtn &&
-					this.role === "header" &&
-					$( ".ui-page" ).length > 1 &&
-					this.page[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) !== $.mobile.path.stripHash( location.hash ) &&
-					!this.leftbtn ) {
-						this._addBackButton();
-				} else {
-					this.element.find( ".ui-toolbar-back-btn" ).remove();
-				}
-			}
-			if ( o.backBtnTheme != null ) {
-				this.element
-					.find( ".ui-toolbar-back-btn" )
-					.addClass( "ui-btn ui-btn-" + o.backBtnTheme );
-			}
-			if ( o.backBtnText !== undefined ) {
-				this.element.find( ".ui-toolbar-back-btn .ui-btn-text" ).text( o.backBtnText );
-			}
-			if ( o.theme !== undefined ) {
-				var currentTheme = this.options.theme ? this.options.theme : "inherit",
-					newTheme = o.theme ? o.theme : "inherit";
-
-				this.element.removeClass( "ui-bar-" + currentTheme ).addClass( "ui-bar-" + newTheme );
-			}
-
-			this._super( o );
-		},
-		refresh: function() {
-			if ( this.role === "header" ) {
-				this._addHeaderButtonClasses();
-			}
-			if ( !this.page ) {
-				this._setRelative();
-				if ( this.role === "footer" ) {
-					this.element.appendTo( "body" );
-				}
-			}
-			this._addHeadingClasses();
-			this._btnMarkup();
-		},
-
-		//we only want this to run on non fixed toolbars so make it easy to override
-		_setRelative: function() {
-			$( "[data-"+ $.mobile.ns + "role='page']" ).css({ "position": "relative" });
-		},
-
-		// Deprecated in 1.4. As from 1.5 button classes have to be present in the markup.
-		_btnMarkup: function() {
-			this.element
-				.children( "a" )
-				.filter( ":not([data-" + $.mobile.ns + "role='none'])" )
-				.attr( "data-" + $.mobile.ns + "role", "button" );
-			this.element.trigger( "create" );
-		},
-		// Deprecated in 1.4. As from 1.5 ui-btn-left/right classes have to be present in the markup.
-		_addHeaderButtonClasses: function() {
-			var $headeranchors = this.element.children( "a, button" );
-			this.leftbtn = $headeranchors.hasClass( "ui-btn-left" );
-			this.rightbtn = $headeranchors.hasClass( "ui-btn-right" );
-
-			this.leftbtn = this.leftbtn || $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
-
-			this.rightbtn = this.rightbtn || $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;
-
-		},
-		_addBackButton: function() {
-			var options = this.options,
-				theme = options.backBtnTheme || options.theme;
-
-			$( "<a role='button' href='javascript:void(0);' " +
-				"class='ui-btn ui-corner-all ui-shadow ui-btn-left " +
-					( theme ? "ui-btn-" + theme + " " : "" ) +
-					"ui-toolbar-back-btn ui-icon-carat-l ui-btn-icon-left' " +
-				"data-" + $.mobile.ns + "rel='back'>" + options.backBtnText + "</a>" )
-					.prependTo( this.element );
-		},
-		_addHeadingClasses: function() {
-			this.element.children( "h1, h2, h3, h4, h5, h6" )
-				.addClass( "ui-title" )
-				// Regardless of h element number in src, it becomes h1 for the enhanced page
-				.attr({
-					"role": "heading",
-					"aria-level": "1"
-				});
-		}
-	});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-	$.widget( "mobile.toolbar", $.mobile.toolbar, {
-		options: {
-			position:null,
-			visibleOnPageShow: true,
-			disablePageZoom: true,
-			transition: "slide", //can be none, fade, slide (slide maps to slideup or slidedown)
-			fullscreen: false,
-			tapToggle: true,
-			tapToggleBlacklist: "a, button, input, select, textarea, .ui-header-fixed, .ui-footer-fixed, .ui-flipswitch, .ui-popup, .ui-panel, .ui-panel-dismiss-open",
-			hideDuringFocus: "input, textarea, select",
-			updatePagePadding: true,
-			trackPersistentToolbars: true,
-
-			// Browser detection! Weeee, here we go...
-			// Unfortunately, position:fixed is costly, not to mention probably impossible, to feature-detect accurately.
-			// Some tests exist, but they currently return false results in critical devices and browsers, which could lead to a broken experience.
-			// Testing fixed positioning is also pretty obtrusive to page load, requiring injected elements and scrolling the window
-			// The following function serves to rule out some popular browsers with known fixed-positioning issues
-			// This is a plugin option like any other, so feel free to improve or overwrite it
-			supportBlacklist: function() {
-				return !$.support.fixedPosition;
-			}
-		},
-
-		_create: function() {
-			this._super();
-			if ( this.options.position === "fixed" && !this.options.supportBlacklist() ) {
-				this._makeFixed();
-			}
-		},
-
-		_makeFixed: function() {
-			this.element.addClass( "ui-"+ this.role +"-fixed" );
-			this.updatePagePadding();
-			this._addTransitionClass();
-			this._bindPageEvents();
-			this._bindToggleHandlers();
-		},
-
-		_setOptions: function( o ) {
-			if ( o.position === "fixed" && this.options.position !== "fixed" ) {
-				this._makeFixed();
-			}
-			if ( this.options.position === "fixed" && !this.options.supportBlacklist() ) {
-				var $page = ( !!this.page )? this.page: ( $(".ui-page-active").length > 0 )? $(".ui-page-active"): $(".ui-page").eq(0);
-
-				if ( o.fullscreen !== undefined) {
-					if ( o.fullscreen ) {
-						this.element.addClass( "ui-"+ this.role +"-fullscreen" );
-						$page.addClass( "ui-page-" + this.role + "-fullscreen" );
-					}
-					// If not fullscreen, add class to page to set top or bottom padding
-					else {
-						this.element.removeClass( "ui-"+ this.role +"-fullscreen" );
-						$page.removeClass( "ui-page-" + this.role + "-fullscreen" ).addClass( "ui-page-" + this.role+ "-fixed" );
-					}
-				}
-			}
-			this._super(o);
-		},
-
-		_addTransitionClass: function() {
-			var tclass = this.options.transition;
-
-			if ( tclass && tclass !== "none" ) {
-				// use appropriate slide for header or footer
-				if ( tclass === "slide" ) {
-					tclass = this.element.hasClass( "ui-header" ) ? "slidedown" : "slideup";
-				}
-
-				this.element.addClass( tclass );
-			}
-		},
-
-		_bindPageEvents: function() {
-			var page = ( !!this.page )? this.element.closest( ".ui-page" ): this.document;
-			//page event bindings
-			// Fixed toolbars require page zoom to be disabled, otherwise usability issues crop up
-			// This method is meant to disable zoom while a fixed-positioned toolbar page is visible
-			this._on( page , {
-				"pagebeforeshow": "_handlePageBeforeShow",
-				"webkitAnimationStart":"_handleAnimationStart",
-				"animationstart":"_handleAnimationStart",
-				"updatelayout": "_handleAnimationStart",
-				"pageshow": "_handlePageShow",
-				"pagebeforehide": "_handlePageBeforeHide"
-			});
-		},
-
-		_handlePageBeforeShow: function( ) {
-			var o = this.options;
-			if ( o.disablePageZoom ) {
-				$.mobile.zoom.disable( true );
-			}
-			if ( !o.visibleOnPageShow ) {
-				this.hide( true );
-			}
-		},
-
-		_handleAnimationStart: function() {
-			if ( this.options.updatePagePadding ) {
-				this.updatePagePadding( ( !!this.page )? this.page: ".ui-page-active" );
-			}
-		},
-
-		_handlePageShow: function() {
-			this.updatePagePadding( ( !!this.page )? this.page: ".ui-page-active" );
-			if ( this.options.updatePagePadding ) {
-				this._on( this.window, { "throttledresize": "updatePagePadding" } );
-			}
-		},
-
-		_handlePageBeforeHide: function( e, ui ) {
-			var o = this.options,
-				thisFooter, thisHeader, nextFooter, nextHeader;
-
-			if ( o.disablePageZoom ) {
-				$.mobile.zoom.enable( true );
-			}
-			if ( o.updatePagePadding ) {
-				this._off( this.window, "throttledresize" );
-			}
-
-			if ( o.trackPersistentToolbars ) {
-				thisFooter = $( ".ui-footer-fixed:jqmData(id)", this.page );
-				thisHeader = $( ".ui-header-fixed:jqmData(id)", this.page );
-				nextFooter = thisFooter.length && ui.nextPage && $( ".ui-footer-fixed:jqmData(id='" + thisFooter.jqmData( "id" ) + "')", ui.nextPage ) || $();
-				nextHeader = thisHeader.length && ui.nextPage && $( ".ui-header-fixed:jqmData(id='" + thisHeader.jqmData( "id" ) + "')", ui.nextPage ) || $();
-
-				if ( nextFooter.length || nextHeader.length ) {
-
-					nextFooter.add( nextHeader ).appendTo( $.mobile.pageContainer );
-
-					ui.nextPage.one( "pageshow", function() {
-						nextHeader.prependTo( this );
-						nextFooter.appendTo( this );
-					});
-				}
-			}
-		},
-
-		_visible: true,
-
-		// This will set the content element's top or bottom padding equal to the toolbar's height
-		updatePagePadding: function( tbPage ) {
-			var $el = this.element,
-				header = ( this.role ==="header" ),
-				pos = parseFloat( $el.css( header ? "top" : "bottom" ) );
-
-			// This behavior only applies to "fixed", not "fullscreen"
-			if ( this.options.fullscreen ) { return; }
-			// tbPage argument can be a Page object or an event, if coming from throttled resize.
-			tbPage = ( tbPage && tbPage.type === undefined && tbPage ) || this.page || $el.closest( ".ui-page" );
-			tbPage = ( !!this.page )? this.page: ".ui-page-active";
-			$( tbPage ).css( "padding-" + ( header ? "top" : "bottom" ), $el.outerHeight() + pos );
-		},
-
-		_useTransition: function( notransition ) {
-			var $win = this.window,
-				$el = this.element,
-				scroll = $win.scrollTop(),
-				elHeight = $el.height(),
-				pHeight = ( !!this.page )? $el.closest( ".ui-page" ).height():$(".ui-page-active").height(),
-				viewportHeight = $.mobile.getScreenHeight();
-
-			return !notransition &&
-				( this.options.transition && this.options.transition !== "none" &&
-				(
-					( this.role === "header" && !this.options.fullscreen && scroll > elHeight ) ||
-					( this.role === "footer" && !this.options.fullscreen && scroll + viewportHeight < pHeight - elHeight )
-				) || this.options.fullscreen
-				);
-		},
-
-		show: function( notransition ) {
-			var hideClass = "ui-fixed-hidden",
-				$el = this.element;
-
-			if ( this._useTransition( notransition ) ) {
-				$el
-					.removeClass( "out " + hideClass )
-					.addClass( "in" )
-					.animationComplete(function () {
-						$el.removeClass( "in" );
-					});
-			}
-			else {
-				$el.removeClass( hideClass );
-			}
-			this._visible = true;
-		},
-
-		hide: function( notransition ) {
-			var hideClass = "ui-fixed-hidden",
-				$el = this.element,
-				// if it's a slide transition, our new transitions need the reverse class as well to slide outward
-				outclass = "out" + ( this.options.transition === "slide" ? " reverse" : "" );
-
-			if ( this._useTransition( notransition ) ) {
-				$el
-					.addClass( outclass )
-					.removeClass( "in" )
-					.animationComplete(function() {
-						$el.addClass( hideClass ).removeClass( outclass );
-					});
-			}
-			else {
-				$el.addClass( hideClass ).removeClass( outclass );
-			}
-			this._visible = false;
-		},
-
-		toggle: function() {
-			this[ this._visible ? "hide" : "show" ]();
-		},
-
-		_bindToggleHandlers: function() {
-			var self = this,
-				o = self.options,
-				delayShow, delayHide,
-				isVisible = true,
-				page = ( !!this.page )? this.page: $(".ui-page");
-
-			// tap toggle
-			page
-				.bind( "vclick", function( e ) {
-					if ( o.tapToggle && !$( e.target ).closest( o.tapToggleBlacklist ).length ) {
-						self.toggle();
-					}
-				})
-				.bind( "focusin focusout", function( e ) {
-					//this hides the toolbars on a keyboard pop to give more screen room and prevent ios bug which
-					//positions fixed toolbars in the middle of the screen on pop if the input is near the top or
-					//bottom of the screen addresses issues #4410 Footer navbar moves up when clicking on a textbox in an Android environment
-					//and issue #4113 Header and footer change their position after keyboard popup - iOS
-					//and issue #4410 Footer navbar moves up when clicking on a textbox in an Android environment
-					if ( screen.width < 1025 && $( e.target ).is( o.hideDuringFocus ) && !$( e.target ).closest( ".ui-header-fixed, .ui-footer-fixed" ).length ) {
-						//Fix for issue #4724 Moving through form in Mobile Safari with "Next" and "Previous" system
-						//controls causes fixed position, tap-toggle false Header to reveal itself
-						// isVisible instead of self._visible because the focusin and focusout events fire twice at the same time
-						// Also use a delay for hiding the toolbars because on Android native browser focusin is direclty followed
-						// by a focusout when a native selects opens and the other way around when it closes.
-						if ( e.type === "focusout" && !isVisible ) {
-							isVisible = true;
-							//wait for the stack to unwind and see if we have jumped to another input
-							clearTimeout( delayHide );
-							delayShow = setTimeout( function() {
-								self.show();
-							}, 0 );
-						} else if ( e.type === "focusin" && !!isVisible ) {
-							//if we have jumped to another input clear the time out to cancel the show.
-							clearTimeout( delayShow );
-							isVisible = false;
-							delayHide = setTimeout( function() {
-								self.hide();
-							}, 0 );
-						}
-					}
-				});
-		},
-
-		_setRelative: function() {
-			if( this.options.position !== "fixed" ){
-				$( "[data-"+ $.mobile.ns + "role='page']" ).css({ "position": "relative" });
-			}
-		},
-
-		_destroy: function() {
-			var $el = this.element,
-				header = $el.hasClass( "ui-header" );
-
-			$el.closest( ".ui-page" ).css( "padding-" + ( header ? "top" : "bottom" ), "" );
-			$el.removeClass( "ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden" );
-			$el.closest( ".ui-page" ).removeClass( "ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen" );
-		}
-
-	});
-})( jQuery );
-
-(function( $, undefined ) {
-	$.widget( "mobile.toolbar", $.mobile.toolbar, {
-
-		_makeFixed: function() {
-			this._super();
-			this._workarounds();
-		},
-
-		//check the browser and version and run needed workarounds
-		_workarounds: function() {
-			var ua = navigator.userAgent,
-			platform = navigator.platform,
-			// Rendering engine is Webkit, and capture major version
-			wkmatch = ua.match( /AppleWebKit\/([0-9]+)/ ),
-			wkversion = !!wkmatch && wkmatch[ 1 ],
-			os = null,
-			self = this;
-			//set the os we are working in if it dosent match one with workarounds return
-			if ( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1  || platform.indexOf( "iPod" ) > -1 ) {
-				os = "ios";
-			} else if ( ua.indexOf( "Android" ) > -1 ) {
-				os = "android";
-			} else {
-				return;
-			}
-			//check os version if it dosent match one with workarounds return
-			if ( os === "ios" ) {
-				//iOS  workarounds
-				self._bindScrollWorkaround();
-			} else if ( os === "android" && wkversion && wkversion < 534 ) {
-				//Android 2.3 run all Android 2.3 workaround
-				self._bindScrollWorkaround();
-				self._bindListThumbWorkaround();
-			} else {
-				return;
-			}
-		},
-
-		//Utility class for checking header and footer positions relative to viewport
-		_viewportOffset: function() {
-			var $el = this.element,
-				header = $el.hasClass( "ui-header" ),
-				offset = Math.abs( $el.offset().top - this.window.scrollTop() );
-			if ( !header ) {
-				offset = Math.round( offset - this.window.height() + $el.outerHeight() ) - 60;
-			}
-			return offset;
-		},
-
-		//bind events for _triggerRedraw() function
-		_bindScrollWorkaround: function() {
-			var self = this;
-			//bind to scrollstop and check if the toolbars are correctly positioned
-			this._on( this.window, { scrollstop: function() {
-				var viewportOffset = self._viewportOffset();
-				//check if the header is visible and if its in the right place
-				if ( viewportOffset > 2 && self._visible ) {
-					self._triggerRedraw();
-				}
-			}});
-		},
-
-		//this addresses issue #4250 Persistent footer instability in v1.1 with long select lists in Android 2.3.3
-		//and issue #3748 Android 2.x: Page transitions broken when fixed toolbars used
-		//the absolutely positioned thumbnail in a list view causes problems with fixed position buttons above in a nav bar
-		//setting the li's to -webkit-transform:translate3d(0,0,0); solves this problem to avoide potential issues in other
-		//platforms we scope this with the class ui-android-2x-fix
-		_bindListThumbWorkaround: function() {
-			this.element.closest( ".ui-page" ).addClass( "ui-android-2x-fixed" );
-		},
-		//this addresses issues #4337 Fixed header problem after scrolling content on iOS and Android
-		//and device bugs project issue #1 Form elements can lose click hit area in position: fixed containers.
-		//this also addresses not on fixed toolbars page in docs
-		//adding 1px of padding to the bottom then removing it causes a "redraw"
-		//which positions the toolbars correctly (they will always be visually correct)
-		_triggerRedraw: function() {
-			var paddingBottom = parseFloat( $( ".ui-page-active" ).css( "padding-bottom" ) );
-			//trigger page redraw to fix incorrectly positioned fixed elements
-			$( ".ui-page-active" ).css( "padding-bottom", ( paddingBottom + 1 ) + "px" );
-			//if the padding is reset with out a timeout the reposition will not occure.
-			//this is independant of JQM the browser seems to need the time to react.
-			setTimeout( function() {
-				$( ".ui-page-active" ).css( "padding-bottom", paddingBottom + "px" );
-			}, 0 );
-		},
-
-		destroy: function() {
-			this._super();
-			//Remove the class we added to the page previously in android 2.x
-			this.element.closest( ".ui-page-active" ).removeClass( "ui-android-2x-fix" );
-		}
-	});
-
-})( jQuery );
-
-
-( function( $, undefined ) {
-
-var ieHack = ( $.mobile.browser.oldIE && $.mobile.browser.oldIE <= 8 ),
-	uiTemplate = $(
-		"<div class='ui-popup-arrow-guide'></div>" +
-		"<div class='ui-popup-arrow-container" + ( ieHack ? " ie" : "" ) + "'>" +
-			"<div class='ui-popup-arrow'></div>" +
-		"</div>"
-	);
-
-function getArrow() {
-	var clone = uiTemplate.clone(),
-		gd = clone.eq( 0 ),
-		ct = clone.eq( 1 ),
-		ar = ct.children();
-
-	return { arEls: ct.add( gd ), gd: gd, ct: ct, ar: ar };
-}
-
-$.widget( "mobile.popup", $.mobile.popup, {
-	options: {
-
-		arrow: ""
-	},
-
-	_create: function() {
-		var ar,
-			ret = this._super();
-
-		if ( this.options.arrow ) {
-			this._ui.arrow = ar = this._addArrow();
-		}
-
-		return ret;
-	},
-
-	_addArrow: function() {
-		var theme,
-			opts = this.options,
-			ar = getArrow();
-
-		theme = this._themeClassFromOption( "ui-body-", opts.theme );
-		ar.ar.addClass( theme + ( opts.shadow ? " ui-overlay-shadow" : "" ) );
-		ar.arEls.hide().appendTo( this.element );
-
-		return ar;
-	},
-
-	_unenhance: function() {
-		var ar = this._ui.arrow;
-
-		if ( ar ) {
-			ar.arEls.remove();
-		}
-
-		return this._super();
-	},
-
-	// Pretend to show an arrow described by @p and @dir and calculate the
-	// distance from the desired point. If a best-distance is passed in, return
-	// the minimum of the one passed in and the one calculated.
-	_tryAnArrow: function( p, dir, desired, s, best ) {
-		var result, r, diff, desiredForArrow = {}, tip = {};
-
-		// If the arrow has no wiggle room along the edge of the popup, it cannot
-		// be displayed along the requested edge without it sticking out.
-		if ( s.arFull[ p.dimKey ] > s.guideDims[ p.dimKey ] ) {
-			return best;
-		}
-
-		desiredForArrow[ p.fst ] = desired[ p.fst ] +
-			( s.arHalf[ p.oDimKey ] + s.menuHalf[ p.oDimKey ] ) * p.offsetFactor -
-			s.contentBox[ p.fst ] + ( s.clampInfo.menuSize[ p.oDimKey ] - s.contentBox[ p.oDimKey ] ) * p.arrowOffsetFactor;
-		desiredForArrow[ p.snd ] = desired[ p.snd ];
-
-		result = s.result || this._calculateFinalLocation( desiredForArrow, s.clampInfo );
-		r = { x: result.left, y: result.top };
-
-		tip[ p.fst ] = r[ p.fst ] + s.contentBox[ p.fst ] + p.tipOffset;
-		tip[ p.snd ] = Math.max( result[ p.prop ] + s.guideOffset[ p.prop ] + s.arHalf[ p.dimKey ],
-			Math.min( result[ p.prop ] + s.guideOffset[ p.prop ] + s.guideDims[ p.dimKey ] - s.arHalf[ p.dimKey ],
-				desired[ p.snd ] ) );
-
-		diff = Math.abs( desired.x - tip.x ) + Math.abs( desired.y - tip.y );
-		if ( !best || diff < best.diff ) {
-			// Convert tip offset to coordinates inside the popup
-			tip[ p.snd ] -= s.arHalf[ p.dimKey ] + result[ p.prop ] + s.contentBox[ p.snd ];
-			best = { dir: dir, diff: diff, result: result, posProp: p.prop, posVal: tip[ p.snd ] };
-		}
-
-		return best;
-	},
-
-	_getPlacementState: function( clamp ) {
-		var offset, gdOffset,
-			ar = this._ui.arrow,
-			state = {
-				clampInfo: this._clampPopupWidth( !clamp ),
-				arFull: { cx: ar.ct.width(), cy: ar.ct.height() },
-				guideDims: { cx: ar.gd.width(), cy: ar.gd.height() },
-				guideOffset: ar.gd.offset()
-			};
-
-		offset = this.element.offset();
-
-		ar.gd.css( { left: 0, top: 0, right: 0, bottom: 0 } );
-		gdOffset = ar.gd.offset();
-		state.contentBox = {
-			x: gdOffset.left - offset.left,
-			y: gdOffset.top - offset.top,
-			cx: ar.gd.width(),
-			cy: ar.gd.height()
-		};
-		ar.gd.removeAttr( "style" );
-
-		// The arrow box moves between guideOffset and guideOffset + guideDims - arFull
-		state.guideOffset = { left: state.guideOffset.left - offset.left, top: state.guideOffset.top - offset.top };
-		state.arHalf = { cx: state.arFull.cx / 2, cy: state.arFull.cy / 2 };
-		state.menuHalf = { cx: state.clampInfo.menuSize.cx / 2, cy: state.clampInfo.menuSize.cy / 2 };
-
-		return state;
-	},
-
-	_placementCoords: function( desired ) {
-		var state, best, params, elOffset, bgRef,
-			optionValue = this.options.arrow,
-			ar = this._ui.arrow;
-
-		if ( !ar ) {
-			return this._super( desired );
-		}
-
-		ar.arEls.show();
-
-		bgRef = {};
-		state = this._getPlacementState( true );
-		params = {
-			"l": { fst: "x", snd: "y", prop: "top", dimKey: "cy", oDimKey: "cx", offsetFactor: 1, tipOffset:  -state.arHalf.cx, arrowOffsetFactor: 0 },
-			"r": { fst: "x", snd: "y", prop: "top", dimKey: "cy", oDimKey: "cx", offsetFactor: -1, tipOffset: state.arHalf.cx + state.contentBox.cx, arrowOffsetFactor: 1 },
-			"b": { fst: "y", snd: "x", prop: "left", dimKey: "cx", oDimKey: "cy", offsetFactor: -1, tipOffset: state.arHalf.cy + state.contentBox.cy, arrowOffsetFactor: 1 },
-			"t": { fst: "y", snd: "x", prop: "left", dimKey: "cx", oDimKey: "cy", offsetFactor: 1, tipOffset: -state.arHalf.cy, arrowOffsetFactor: 0 }
-		};
-
-		// Try each side specified in the options to see on which one the arrow
-		// should be placed such that the distance between the tip of the arrow and
-		// the desired coordinates is the shortest.
-		$.each( ( optionValue === true ? "l,t,r,b" : optionValue ).split( "," ),
-			$.proxy( function( key, value ) {
-				best = this._tryAnArrow( params[ value ], value, desired, state, best );
-			}, this ) );
-
-		// Could not place the arrow along any of the edges - behave as if showing
-		// the arrow was turned off.
-		if ( !best ) {
-			ar.arEls.hide();
-			return this._super( desired );
-		}
-
-		// Move the arrow into place
-		ar.ct
-			.removeClass( "ui-popup-arrow-l ui-popup-arrow-t ui-popup-arrow-r ui-popup-arrow-b" )
-			.addClass( "ui-popup-arrow-" + best.dir )
-			.removeAttr( "style" ).css( best.posProp, best.posVal )
-			.show();
-
-		// Do not move/size the background div on IE, because we use the arrow div for background as well.
-		if ( !ieHack ) {
-			elOffset = this.element.offset();
-			bgRef[ params[ best.dir ].fst ] = ar.ct.offset();
-			bgRef[ params[ best.dir ].snd ] = {
-				left: elOffset.left + state.contentBox.x,
-				top: elOffset.top + state.contentBox.y
-			};
-		}
-
-		return best.result;
-	},
-
-	_setOptions: function( opts ) {
-		var newTheme,
-			oldTheme = this.options.theme,
-			ar = this._ui.arrow,
-			ret = this._super( opts );
-
-		if ( opts.arrow !== undefined ) {
-			if ( !ar && opts.arrow ) {
-				this._ui.arrow = this._addArrow();
-
-				// Important to return here so we don't set the same options all over
-				// again below.
-				return;
-			} else if ( ar && !opts.arrow ) {
-				ar.arEls.remove();
-				this._ui.arrow = null;
-			}
-		}
-
-		// Reassign with potentially new arrow
-		ar = this._ui.arrow;
-
-		if ( ar ) {
-			if ( opts.theme !== undefined ) {
-				oldTheme = this._themeClassFromOption( "ui-body-", oldTheme );
-				newTheme = this._themeClassFromOption( "ui-body-", opts.theme );
-				ar.ar.removeClass( oldTheme ).addClass( newTheme );
-			}
-
-			if ( opts.shadow !== undefined ) {
-				ar.ar.toggleClass( "ui-overlay-shadow", opts.shadow );
-			}
-		}
-
-		return ret;
-	},
-
-	_destroy: function() {
-		var ar = this._ui.arrow;
-
-		if ( ar ) {
-			ar.arEls.remove();
-		}
-
-		return this._super();
-	}
-});
-
-})( jQuery );
-
-
-(function( $, undefined ) {
-
-$.widget( "mobile.panel", {
-	options: {
-		classes: {
-			panel: "ui-panel",
-			panelOpen: "ui-panel-open",
-			panelClosed: "ui-panel-closed",
-			panelFixed: "ui-panel-fixed",
-			panelInner: "ui-panel-inner",
-			modal: "ui-panel-dismiss",
-			modalOpen: "ui-panel-dismiss-open",
-			pageContainer: "ui-panel-page-container",
-			pageWrapper: "ui-panel-wrapper",
-			pageFixedToolbar: "ui-panel-fixed-toolbar",
-			pageContentPrefix: "ui-panel-page-content", /* Used for wrapper and fixed toolbars position, display and open classes. */
-			animate: "ui-panel-animate"
-		},
-		animate: true,
-		theme: null,
-		position: "left",
-		dismissible: true,
-		display: "reveal", //accepts reveal, push, overlay
-		swipeClose: true,
-		positionFixed: false
-	},
-
-	_closeLink: null,
-	_parentPage: null,
-	_page: null,
-	_modal: null,
-	_panelInner: null,
-	_wrapper: null,
-	_fixedToolbars: null,
-
-	_create: function() {
-		var el = this.element,
-			parentPage = el.closest( ".ui-page, :jqmData(role='page')" );
-
-		// expose some private props to other methods
-		$.extend( this, {
-			_closeLink: el.find( ":jqmData(rel='close')" ),
-			_parentPage: ( parentPage.length > 0 ) ? parentPage : false,
-			_openedPage: null,
-			_page: this._getPage,
-			_panelInner: this._getPanelInner(),
-			_fixedToolbars: this._getFixedToolbars
-		});
-		if ( this.options.display !== "overlay" ){
-			this._getWrapper();
-		}
-		this._addPanelClasses();
-
-		// if animating, add the class to do so
-		if ( $.support.cssTransform3d && !!this.options.animate ) {
-			this.element.addClass( this.options.classes.animate );
-		}
-
-		this._bindUpdateLayout();
-		this._bindCloseEvents();
-		this._bindLinkListeners();
-		this._bindPageEvents();
-
-		if ( !!this.options.dismissible ) {
-			this._createModal();
-		}
-
-		this._bindSwipeEvents();
-	},
-
-	_getPanelInner: function() {
-		var panelInner = this.element.find( "." + this.options.classes.panelInner );
-
-		if ( panelInner.length === 0 ) {
-			panelInner = this.element.children().wrapAll( "<div class='" + this.options.classes.panelInner + "' />" ).parent();
-		}
-
-		return panelInner;
-	},
-
-	_createModal: function() {
-		var self = this,
-			target = self._parentPage ? self._parentPage.parent() : self.element.parent();
-
-		self._modal = $( "<div class='" + self.options.classes.modal + "'></div>" )
-			.on( "mousedown", function() {
-				self.close();
-			})
-			.appendTo( target );
-	},
-
-	_getPage: function() {
-		var page = this._openedPage || this._parentPage || $( "." + $.mobile.activePageClass );
-
-		return page;
-	},
-
-	_getWrapper: function() {
-		var wrapper = this._page().find( "." + this.options.classes.pageWrapper );
-		if ( wrapper.length === 0 ) {
-			wrapper = this._page().children( ".ui-header:not(.ui-header-fixed), .ui-content:not(.ui-popup), .ui-footer:not(.ui-footer-fixed)" )
-				.wrapAll( "<div class='" + this.options.classes.pageWrapper + "'></div>" )
-				.parent();
-		}
-
-		this._wrapper = wrapper;
-	},
-
-	_getFixedToolbars: function() {
-		var extFixedToolbars = $( "body" ).children( ".ui-header-fixed, .ui-footer-fixed" ),
-			intFixedToolbars = this._page().find( ".ui-header-fixed, .ui-footer-fixed" ),
-			fixedToolbars = extFixedToolbars.add( intFixedToolbars ).addClass( this.options.classes.pageFixedToolbar );
-
-		return fixedToolbars;
-	},
-
-	_getPosDisplayClasses: function( prefix ) {
-		return prefix + "-position-" + this.options.position + " " + prefix + "-display-" + this.options.display;
-	},
-
-	_getPanelClasses: function() {
-		var panelClasses = this.options.classes.panel +
-			" " + this._getPosDisplayClasses( this.options.classes.panel ) +
-			" " + this.options.classes.panelClosed +
-			" " + "ui-body-" + ( this.options.theme ? this.options.theme : "inherit" );
-
-		if ( !!this.options.positionFixed ) {
-			panelClasses += " " + this.options.classes.panelFixed;
-		}
-
-		return panelClasses;
-	},
-
-	_addPanelClasses: function() {
-		this.element.addClass( this._getPanelClasses() );
-	},
-
-	_handleCloseClickAndEatEvent: function( event ) {
-		if ( !event.isDefaultPrevented() ) {
-			event.preventDefault();
-			this.close();
-			return false;
-		}
-	},
-
-	_handleCloseClick: function( event ) {
-		if ( !event.isDefaultPrevented() ) {
-			this.close();
-		}
-	},
-
-	_bindCloseEvents: function() {
-		this._on( this._closeLink, {
-			"click": "_handleCloseClick"
-		});
-
-		this._on({
-			"click a:jqmData(ajax='false')": "_handleCloseClick"
-		});
-	},
-
-	_positionPanel: function( scrollToTop ) {
-		var self = this,
-			panelInnerHeight = self._panelInner.outerHeight(),
-			expand = panelInnerHeight > $.mobile.getScreenHeight();
-
-		if ( expand || !self.options.positionFixed ) {
-			if ( expand ) {
-				self._unfixPanel();
-				$.mobile.resetActivePageHeight( panelInnerHeight );
-			}
-			if ( scrollToTop ) {
-				this.window[ 0 ].scrollTo( 0, $.mobile.defaultHomeScroll );
-			}
-		} else {
-			self._fixPanel();
-		}
-	},
-
-	_bindFixListener: function() {
-		this._on( $( window ), { "throttledresize": "_positionPanel" });
-	},
-
-	_unbindFixListener: function() {
-		this._off( $( window ), "throttledresize" );
-	},
-
-	_unfixPanel: function() {
-		if ( !!this.options.positionFixed && $.support.fixedPosition ) {
-			this.element.removeClass( this.options.classes.panelFixed );
-		}
-	},
-
-	_fixPanel: function() {
-		if ( !!this.options.positionFixed && $.support.fixedPosition ) {
-			this.element.addClass( this.options.classes.panelFixed );
-		}
-	},
-
-	_bindUpdateLayout: function() {
-		var self = this;
-
-		self.element.on( "updatelayout", function(/* e */) {
-			if ( self._open ) {
-				self._positionPanel();
-			}
-		});
-	},
-
-	_bindLinkListeners: function() {
-		this._on( "body", {
-			"click a": "_handleClick"
-		});
-
-	},
-
-	_handleClick: function( e ) {
-		var link,
-			panelId = this.element.attr( "id" );
-
-		if ( e.currentTarget.href.split( "#" )[ 1 ] === panelId && panelId !== undefined ) {
-
-			e.preventDefault();
-			link = $( e.target );
-			if ( link.hasClass( "ui-btn" ) ) {
-				link.addClass( $.mobile.activeBtnClass );
-				this.element.one( "panelopen panelclose", function() {
-					link.removeClass( $.mobile.activeBtnClass );
-				});
-			}
-			this.toggle();
-			return false;
-		}
-	},
-
-	_bindSwipeEvents: function() {
-		var self = this,
-			area = self._modal ? self.element.add( self._modal ) : self.element;
-
-		// on swipe, close the panel
-		if ( !!self.options.swipeClose ) {
-			if ( self.options.position === "left" ) {
-				area.on( "swipeleft.panel", function(/* e */) {
-					self.close();
-				});
-			} else {
-				area.on( "swiperight.panel", function(/* e */) {
-					self.close();
-				});
-			}
-		}
-	},
-
-	_bindPageEvents: function() {
-		var self = this;
-
-		this.document
-			// Close the panel if another panel on the page opens
-			.on( "panelbeforeopen", function( e ) {
-				if ( self._open && e.target !== self.element[ 0 ] ) {
-					self.close();
-				}
-			})
-			// On escape, close? might need to have a target check too...
-			.on( "keyup.panel", function( e ) {
-				if ( e.keyCode === 27 && self._open ) {
-					self.close();
-				}
-			});
-		if ( !this._parentPage && this.options.display !== "overlay" ) {
-			this._on( this.document, {
-				"pageshow": "_getWrapper"
-			});
-		}
-		// Clean up open panels after page hide
-		if ( self._parentPage ) {
-			this.document.on( "pagehide", ":jqmData(role='page')", function() {
-				if ( self._open ) {
-					self.close( true );
-				}
-			});
-		} else {
-			this.document.on( "pagebeforehide", function() {
-				if ( self._open ) {
-					self.close( true );
-				}
-			});
-		}
-	},
-
-	// state storage of open or closed
-	_open: false,
-	_pageContentOpenClasses: null,
-	_modalOpenClasses: null,
-
-	open: function( immediate ) {
-		if ( !this._open ) {
-			var self = this,
-				o = self.options,
-
-				_openPanel = function() {
-					self.document.off( "panelclose" );
-					self._page().jqmData( "panel", "open" );
-
-					if ( $.support.cssTransform3d && !!o.animate && o.display !== "overlay" ) {
-						self._wrapper.addClass( o.classes.animate );
-						self._fixedToolbars().addClass( o.classes.animate );
-					}
-
-					if ( !immediate && $.support.cssTransform3d && !!o.animate ) {
-						self.element.animationComplete( complete, "transition" );
-					} else {
-						setTimeout( complete, 0 );
-					}
-
-					if ( o.theme && o.display !== "overlay" ) {
-						self._page().parent()
-							.addClass( o.classes.pageContainer + "-themed " + o.classes.pageContainer + "-" + o.theme );
-					}
-
-					self.element
-						.removeClass( o.classes.panelClosed )
-						.addClass( o.classes.panelOpen );
-
-					self._positionPanel( true );
-
-					self._pageContentOpenClasses = self._getPosDisplayClasses( o.classes.pageContentPrefix );
-
-					if ( o.display !== "overlay" ) {
-						self._page().parent().addClass( o.classes.pageContainer );
-						self._wrapper.addClass( self._pageContentOpenClasses );
-						self._fixedToolbars().addClass( self._pageContentOpenClasses );
-					}
-
-					self._modalOpenClasses = self._getPosDisplayClasses( o.classes.modal ) + " " + o.classes.modalOpen;
-					if ( self._modal ) {
-						self._modal
-							.addClass( self._modalOpenClasses )
-							.height( Math.max( self._modal.height(), self.document.height() ) );
-					}
-				},
-				complete = function() {
-
-					if ( o.display !== "overlay" ) {
-						self._wrapper.addClass( o.classes.pageContentPrefix + "-open" );
-						self._fixedToolbars().addClass( o.classes.pageContentPrefix + "-open" );
-					}
-
-					self._bindFixListener();
-
-					self._trigger( "open" );
-
-					self._openedPage = self._page();
-				};
-
-			self._trigger( "beforeopen" );
-
-			if ( self._page().jqmData( "panel" ) === "open" ) {
-				self.document.on( "panelclose", function() {
-					_openPanel();
-				});
-			} else {
-				_openPanel();
-			}
-
-			self._open = true;
-		}
-	},
-
-	close: function( immediate ) {
-		if ( this._open ) {
-			var self = this,
-				o = this.options,
-
-				_closePanel = function() {
-
-					self.element.removeClass( o.classes.panelOpen );
-
-					if ( o.display !== "overlay" ) {
-						self._wrapper.removeClass( self._pageContentOpenClasses );
-						self._fixedToolbars().removeClass( self._pageContentOpenClasses );
-					}
-
-					if ( !immediate && $.support.cssTransform3d && !!o.animate ) {
-						self.element.animationComplete( complete, "transition" );
-					} else {
-						setTimeout( complete, 0 );
-					}
-
-					if ( self._modal ) {
-						self._modal.removeClass( self._modalOpenClasses );
-					}
-				},
-				complete = function() {
-					if ( o.theme && o.display !== "overlay" ) {
-						self._page().parent().removeClass( o.classes.pageContainer + "-themed " + o.classes.pageContainer + "-" + o.theme );
-					}
-
-					self.element.addClass( o.classes.panelClosed );
-
-					if ( o.display !== "overlay" ) {
-						self._page().parent().removeClass( o.classes.pageContainer );
-						self._wrapper.removeClass( o.classes.pageContentPrefix + "-open" );
-						self._fixedToolbars().removeClass( o.classes.pageContentPrefix + "-open" );
-					}
-
-					if ( $.support.cssTransform3d && !!o.animate && o.display !== "overlay" ) {
-						self._wrapper.removeClass( o.classes.animate );
-						self._fixedToolbars().removeClass( o.classes.animate );
-					}
-
-					self._fixPanel();
-					self._unbindFixListener();
-					$.mobile.resetActivePageHeight();
-
-					self._page().jqmRemoveData( "panel" );
-
-					self._trigger( "close" );
-
-					self._openedPage = null;
-				};
-
-			self._trigger( "beforeclose" );
-
-			_closePanel();
-
-			self._open = false;
-		}
-	},
-
-	toggle: function() {
-		this[ this._open ? "close" : "open" ]();
-	},
-
-	_destroy: function() {
-		var otherPanels,
-		o = this.options,
-		multiplePanels = ( $( "body > :mobile-panel" ).length + $.mobile.activePage.find( ":mobile-panel" ).length ) > 1;
-
-		if ( o.display !== "overlay" ) {
-
-			//  remove the wrapper if not in use by another panel
-			otherPanels = $( "body > :mobile-panel" ).add( $.mobile.activePage.find( ":mobile-panel" ) );
-			if ( otherPanels.not( ".ui-panel-display-overlay" ).not( this.element ).length === 0 ) {
-				this._wrapper.children().unwrap();
-			}
-
-			if ( this._open ) {
-
-				this._fixedToolbars().removeClass( o.classes.pageContentPrefix + "-open" );
-
-				if ( $.support.cssTransform3d && !!o.animate ) {
-					this._fixedToolbars().removeClass( o.classes.animate );
-				}
-
-				this._page().parent().removeClass( o.classes.pageContainer );
-
-				if ( o.theme ) {
-					this._page().parent().removeClass( o.classes.pageContainer + "-themed " + o.classes.pageContainer + "-" + o.theme );
-				}
-			}
-		}
-
-		if ( !multiplePanels ) {
-
-			this.document.off( "panelopen panelclose" );
-
-		}
-
-		if ( this._open ) {
-			this._page().jqmRemoveData( "panel" );
-		}
-
-		this._panelInner.children().unwrap();
-
-		this.element
-			.removeClass( [ this._getPanelClasses(), o.classes.panelOpen, o.classes.animate ].join( " " ) )
-			.off( "swipeleft.panel swiperight.panel" )
-			.off( "panelbeforeopen" )
-			.off( "panelhide" )
-			.off( "keyup.panel" )
-			.off( "updatelayout" );
-
-		if ( this._modal ) {
-			this._modal.remove();
-		}
-	}
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.widget( "mobile.table", {
-	options: {
-		classes: {
-			table: "ui-table"
-		},
-		enhanced: false
-	},
-
-	_create: function() {
-		if ( !this.options.enhanced ) {
-			this.element.addClass( this.options.classes.table );
-		}
-
-		// extend here, assign on refresh > _setHeaders
-		$.extend( this, {
-
-			// Expose headers and allHeaders properties on the widget
-			// headers references the THs within the first TR in the table
-			headers: undefined,
-
-			// allHeaders references headers, plus all THs in the thead, which may
-			// include several rows, or not
-			allHeaders: undefined
-		});
-
-		this._refresh( true );
-	},
-
-	_setHeaders: function() {
-		var trs = this.element.find( "thead tr" );
-
-		this.headers = this.element.find( "tr:eq(0)" ).children();
-		this.allHeaders = this.headers.add( trs.children() );
-	},
-
-	refresh: function() {
-		this._refresh();
-	},
-
-	rebuild: $.noop,
-
-	_refresh: function( /* create */ ) {
-		var table = this.element,
-			trs = table.find( "thead tr" );
-
-		// updating headers on refresh (fixes #5880)
-		this._setHeaders();
-
-		// Iterate over the trs
-		trs.each( function() {
-			var columnCount = 0;
-
-			// Iterate over the children of the tr
-			$( this ).children().each( function() {
-				var span = parseInt( this.getAttribute( "colspan" ), 10 ),
-					selector = ":nth-child(" + ( columnCount + 1 ) + ")",
-					j;
-
-				this.setAttribute( "data-" + $.mobile.ns + "colstart", columnCount + 1 );
-
-				if ( span ) {
-					for( j = 0; j < span - 1; j++ ) {
-						columnCount++;
-						selector += ", :nth-child(" + ( columnCount + 1 ) + ")";
-					}
-				}
-
-				// Store "cells" data on header as a reference to all cells in the
-				// same column as this TH
-				$( this ).jqmData( "cells", table.find( "tr" ).not( trs.eq( 0 ) ).not( this ).children( selector ) );
-
-				columnCount++;
-			});
-		});
-	}
-});
-
-})( jQuery );
-
-
-(function( $, undefined ) {
-
-$.widget( "mobile.table", $.mobile.table, {
-	options: {
-		mode: "columntoggle",
-		columnBtnTheme: null,
-		columnPopupTheme: null,
-		columnBtnText: "Columns...",
-		classes: $.extend( $.mobile.table.prototype.options.classes, {
-			popup: "ui-table-columntoggle-popup",
-			columnBtn: "ui-table-columntoggle-btn",
-			priorityPrefix: "ui-table-priority-",
-			columnToggleTable: "ui-table-columntoggle"
-		})
-	},
-
-	_create: function() {
-		this._super();
-
-		if ( this.options.mode !== "columntoggle" ) {
-			return;
-		}
-
-		$.extend( this, {
-			_menu: null
-		});
-
-		if ( this.options.enhanced ) {
-			this._menu = $( this.document[ 0 ].getElementById( this._id() + "-popup" ) ).children().first();
-			this._addToggles( this._menu, true );
-		} else {
-			this._menu = this._enhanceColToggle();
-			this.element.addClass( this.options.classes.columnToggleTable );
-		}
-
-		this._setupEvents();
-
-		this._setToggleState();
-	},
-
-	_id: function() {
-		return ( this.element.attr( "id" ) || ( this.widgetName + this.uuid ) );
-	},
-
-	_setupEvents: function() {
-		//NOTE: inputs are bound in bindToggles,
-		// so it can be called on refresh, too
-
-		// update column toggles on resize
-		this._on( this.window, {
-			throttledresize: "_setToggleState"
-		});
-		this._on( this._menu, {
-			"change input": "_menuInputChange"
-		});
-	},
-
-	_addToggles: function( menu, keep ) {
-		var inputs,
-			checkboxIndex = 0,
-			opts = this.options,
-			container = menu.controlgroup( "container" );
-
-		// allow update of menu on refresh (fixes #5880)
-		if ( keep ) {
-			inputs = menu.find( "input" );
-		} else {
-			container.empty();
-		}
-
-		// create the hide/show toggles
-		this.headers.not( "td" ).each( function() {
-			var header = $( this ),
-				priority = $.mobile.getAttribute( this, "priority" ),
-				cells = header.add( header.jqmData( "cells" ) );
-
-			if ( priority ) {
-				cells.addClass( opts.classes.priorityPrefix + priority );
-
-				( keep ? inputs.eq( checkboxIndex++ ) :
-					$("<label><input type='checkbox' checked />" +
-						( header.children( "abbr" ).first().attr( "title" ) ||
-							header.text() ) +
-						"</label>" )
-						.appendTo( container )
-						.children( 0 )
-						.checkboxradio( {
-							theme: opts.columnPopupTheme
-						}) )
-					.jqmData( "cells", cells );
-			}
-		});
-
-		// set bindings here
-		if ( !keep ) {
-			menu.controlgroup( "refresh" );
-		}
-	},
-
-	_menuInputChange: function( evt ) {
-		var input = $( evt.target ),
-			checked = input[ 0 ].checked;
-
-		input.jqmData( "cells" )
-			.toggleClass( "ui-table-cell-hidden", !checked )
-			.toggleClass( "ui-table-cell-visible", checked );
-
-		if ( input[ 0 ].getAttribute( "locked" ) ) {
-			input.removeAttr( "locked" );
-
-			this._unlockCells( input.jqmData( "cells" ) );
-		} else {
-			input.attr( "locked", true );
-		}
-	},
-
-	_unlockCells: function( cells ) {
-		// allow hide/show via CSS only = remove all toggle-locks
-		cells.removeClass( "ui-table-cell-hidden ui-table-cell-visible");
-	},
-
-	_enhanceColToggle: function() {
-		var id , menuButton, popup, menu,
-			table = this.element,
-			opts = this.options,
-			ns = $.mobile.ns,
-			fragment = this.document[ 0 ].createDocumentFragment();
-
-		id = this._id() + "-popup";
-		menuButton = $( "<a href='#" + id + "' " +
-			"class='" + opts.classes.columnBtn + " ui-btn " +
-			"ui-btn-" + ( opts.columnBtnTheme || "a" ) +
-			" ui-corner-all ui-shadow ui-mini' " +
-			"data-" + ns + "rel='popup'>" + opts.columnBtnText + "</a>" );
-		popup = $( "<div class='" + opts.classes.popup + "' id='" + id + "'></div>" );
-		menu = $( "<fieldset></fieldset>" ).controlgroup();
-
-		// set extension here, send "false" to trigger build/rebuild
-		this._addToggles( menu, false );
-
-		menu.appendTo( popup );
-
-		fragment.appendChild( popup[ 0 ] );
-		fragment.appendChild( menuButton[ 0 ] );
-		table.before( fragment );
-
-		popup.popup();
-
-		return menu;
-	},
-
-	rebuild: function() {
-		this._super();
-
-		if ( this.options.mode === "columntoggle" ) {
-			// NOTE: rebuild passes "false", while refresh passes "undefined"
-			// both refresh the table, but inside addToggles, !false will be true,
-			// so a rebuild call can be indentified
-			this._refresh( false );
-		}
-	},
-
-	_refresh: function( create ) {
-		this._super( create );
-
-		if ( !create && this.options.mode === "columntoggle" ) {
-			// columns not being replaced must be cleared from input toggle-locks
-			this._unlockCells( this.element.find( ".ui-table-cell-hidden, " +
-				".ui-table-cell-visible" ) );
-
-			// update columntoggles and cells
-			this._addToggles( this._menu, create );
-
-			// check/uncheck
-			this._setToggleState();
-		}
-	},
-
-	_setToggleState: function() {
-		this._menu.find( "input" ).each( function() {
-			var checkbox = $( this );
-
-			this.checked = checkbox.jqmData( "cells" ).eq( 0 ).css( "display" ) === "table-cell";
-			checkbox.checkboxradio( "refresh" );
-		});
-	},
-
-	_destroy: function() {
-		this._super();
-	}
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-$.widget( "mobile.table", $.mobile.table, {
-	options: {
-		mode: "reflow",
-		classes: $.extend( $.mobile.table.prototype.options.classes, {
-			reflowTable: "ui-table-reflow",
-			cellLabels: "ui-table-cell-label"
-		})
-	},
-
-	_create: function() {
-		this._super();
-
-		// If it's not reflow mode, return here.
-		if ( this.options.mode !== "reflow" ) {
-			return;
-		}
-
-		if ( !this.options.enhanced ) {
-			this.element.addClass( this.options.classes.reflowTable );
-
-			this._updateReflow();
-		}
-	},
-
-	rebuild: function() {
-		this._super();
-
-		if ( this.options.mode === "reflow" ) {
-			this._refresh( false );
-		}
-	},
-
-	_refresh: function( create ) {
-		this._super( create );
-		if ( !create && this.options.mode === "reflow" ) {
-			this._updateReflow( );
-		}
-	},
-
-	_updateReflow: function() {
-		var table = this,
-			opts = this.options;
-
-		// get headers in reverse order so that top-level headers are appended last
-		$( table.allHeaders.get().reverse() ).each( function() {
-			var cells = $( this ).jqmData( "cells" ),
-				colstart = $.mobile.getAttribute( this, "colstart" ),
-				hierarchyClass = cells.not( this ).filter( "thead th" ).length && " ui-table-cell-label-top",
-				text = $( this ).text(),
-				iteration, filter;
-
-				if ( text !== ""  ) {
-
-					if ( hierarchyClass ) {
-						iteration = parseInt( this.getAttribute( "colspan" ), 10 );
-						filter = "";
-
-						if ( iteration ) {
-							filter = "td:nth-child("+ iteration +"n + " + ( colstart ) +")";
-						}
-
-						table._addLabels( cells.filter( filter ), opts.classes.cellLabels + hierarchyClass, text );
-					} else {
-						table._addLabels( cells, opts.classes.cellLabels, text );
-					}
-
-				}
-		});
-	},
-
-	_addLabels: function( cells, label, text ) {
-		// .not fixes #6006
-		cells.not( ":has(b." + label + ")" ).prepend( "<b class='" + label + "'>" + text + "</b>"  );
-	}
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-// TODO rename filterCallback/deprecate and default to the item itself as the first argument
-var defaultFilterCallback = function( index, searchValue ) {
-	return ( ( "" + ( $.mobile.getAttribute( this, "filtertext" ) || $( this ).text() ) )
-		.toLowerCase().indexOf( searchValue ) === -1 );
-};
-
-$.widget( "mobile.filterable", {
-
-	initSelector: ":jqmData(filter='true')",
-
-	options: {
-		filterReveal: false,
-		filterCallback: defaultFilterCallback,
-		enhanced: false,
-		input: null,
-		children: "> li, > option, > optgroup option, > tbody tr, > .ui-controlgroup-controls > .ui-btn, > .ui-controlgroup-controls > .ui-checkbox, > .ui-controlgroup-controls > .ui-radio"
-	},
-
-	_create: function() {
-		var opts = this.options;
-
-		$.extend( this, {
-			_search: null,
-			_timer: 0
-		});
-
-		this._setInput( opts.input );
-		if ( !opts.enhanced ) {
-			this._filterItems( ( ( this._search && this._search.val() ) || "" ).toLowerCase() );
-		}
-	},
-
-	_onKeyUp: function() {
-		var val, lastval,
-			search = this._search;
-
-		if ( search ) {
-			val = search.val().toLowerCase(),
-			lastval = $.mobile.getAttribute( search[ 0 ], "lastval" ) + "";
-
-			if ( lastval && lastval === val ) {
-				// Execute the handler only once per value change
-				return;
-			}
-
-			if ( this._timer ) {
-				window.clearTimeout( this._timer );
-				this._timer = 0;
-			}
-
-			this._timer = this._delay( function() {
-				this._trigger( "beforefilter", null, { input: search } );
-
-				// Change val as lastval for next execution
-				search[ 0 ].setAttribute( "data-" + $.mobile.ns + "lastval", val );
-
-				this._filterItems( val );
-				this._timer = 0;
-			}, 250 );
-		}
-	},
-
-	_getFilterableItems: function() {
-		var elem = this.element,
-			children = this.options.children,
-			items = !children ? { length: 0 }:
-				$.isFunction( children ) ? children():
-				children.nodeName ? $( children ):
-				children.jquery ? children:
-				this.element.find( children );
-
-		if ( items.length === 0 ) {
-			items = elem.children();
-		}
-
-		return items;
-	},
-
-	_filterItems: function( val ) {
-		var idx, callback, length, dst,
-			show = [],
-			hide = [],
-			opts = this.options,
-			filterItems = this._getFilterableItems();
-
-		if ( val != null ) {
-			callback = opts.filterCallback || defaultFilterCallback;
-			length = filterItems.length;
-
-			// Partition the items into those to be hidden and those to be shown
-			for ( idx = 0 ; idx < length ; idx++ ) {
-				dst = ( callback.call( filterItems[ idx ], idx, val ) ) ? hide : show;
-				dst.push( filterItems[ idx ] );
-			}
-		}
-
-		// If nothing is hidden, then the decision whether to hide or show the items
-		// is based on the "filterReveal" option.
-		if ( hide.length === 0 ) {
-			filterItems[ opts.filterReveal ? "addClass" : "removeClass" ]( "ui-screen-hidden" );
-		} else {
-			$( hide ).addClass( "ui-screen-hidden" );
-			$( show ).removeClass( "ui-screen-hidden" );
-		}
-
-		this._refreshChildWidget();
-
-		this._trigger( "filter", null, {
-			items: filterItems
-		});
-	},
-
-	// The Default implementation of _refreshChildWidget attempts to call
-	// refresh on collapsibleset, controlgroup, selectmenu, or listview
-	_refreshChildWidget: function() {
-		var widget, idx,
-			recognizedWidgets = [ "collapsibleset", "selectmenu", "controlgroup", "listview" ];
-
-		for ( idx = recognizedWidgets.length - 1 ; idx > -1 ; idx-- ) {
-			widget = recognizedWidgets[ idx ];
-			if ( $.mobile[ widget ] ) {
-				widget = this.element.data( "mobile-" + widget );
-				if ( widget && $.isFunction( widget.refresh ) ) {
-					widget.refresh();
-				}
-			}
-		}
-	},
-
-	// TODO: When the input is not internal, do not even store it in this._search
-	_setInput: function ( selector ) {
-		var search = this._search;
-
-		// Stop a pending filter operation
-		if ( this._timer ) {
-			window.clearTimeout( this._timer );
-			this._timer = 0;
-		}
-
-		if ( search ) {
-			this._off( search, "keyup change input" );
-			search = null;
-		}
-
-		if ( selector ) {
-			search = selector.jquery ? selector:
-				selector.nodeName ? $( selector ):
-				this.document.find( selector );
-
-			this._on( search, {
-				keyup: "_onKeyUp",
-				change: "_onKeyUp",
-				input: "_onKeyUp"
-			});
-		}
-
-		this._search = search;
-	},
-
-	_setOptions: function( options ) {
-		var refilter = !( ( options.filterReveal === undefined ) &&
-				( options.filterCallback === undefined ) &&
-				( options.children === undefined ) );
-
-		this._super( options );
-
-		if ( options.input !== undefined ) {
-			this._setInput( options.input );
-			refilter = true;
-		}
-
-		if ( refilter ) {
-			this.refresh();
-		}
-	},
-
-	_destroy: function() {
-		var opts = this.options,
-			items = this._getFilterableItems();
-
-		if ( opts.enhanced ) {
-			items.toggleClass( "ui-screen-hidden", opts.filterReveal );
-		} else {
-			items.removeClass( "ui-screen-hidden" );
-		}
-	},
-
-	refresh: function() {
-		if ( this._timer ) {
-			window.clearTimeout( this._timer );
-			this._timer = 0;
-		}
-		this._filterItems( ( ( this._search && this._search.val() ) || "" ).toLowerCase() );
-	}
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-// Create a function that will replace the _setOptions function of a widget,
-// and will pass the options on to the input of the filterable.
-var replaceSetOptions = function( self, orig ) {
-		return function( options ) {
-			orig.call( this, options );
-			self._syncTextInputOptions( options );
-		};
-	},
-	rDividerListItem = /(^|\s)ui-li-divider(\s|$)/,
-	origDefaultFilterCallback = $.mobile.filterable.prototype.options.filterCallback;
-
-// Override the default filter callback with one that does not hide list dividers
-$.mobile.filterable.prototype.options.filterCallback = function( index, searchValue ) {
-	return !this.className.match( rDividerListItem ) &&
-		origDefaultFilterCallback.call( this, index, searchValue );
-};
-
-$.widget( "mobile.filterable", $.mobile.filterable, {
-	options: {
-		filterPlaceholder: "Filter items...",
-		filterTheme: null
-	},
-
-	_create: function() {
-		var idx, widgetName,
-			elem = this.element,
-			recognizedWidgets = [ "collapsibleset", "selectmenu", "controlgroup", "listview" ],
-			createHandlers = {};
-
-		this._super();
-
-		$.extend( this, {
-			_widget: null
-		});
-
-		for ( idx = recognizedWidgets.length - 1 ; idx > -1 ; idx-- ) {
-			widgetName = recognizedWidgets[ idx ];
-			if ( $.mobile[ widgetName ] ) {
-				if ( this._setWidget( elem.data( "mobile-" + widgetName ) ) ) {
-					break;
-				} else {
-					createHandlers[ widgetName + "create" ] = "_handleCreate";
-				}
-			}
-		}
-
-		if ( !this._widget ) {
-			this._on( elem, createHandlers );
-		}
-	},
-
-	_handleCreate: function( evt ) {
-		this._setWidget( this.element.data( "mobile-" + evt.type.substring( 0, evt.type.length - 6 ) ) );
-	},
-
-	_trigger: function( type, event, data ) {
-		if ( this._widget && this._widget.widgetFullName === "mobile-listview" &&
-			type === "beforefilter" ) {
-
-			// Also trigger listviewbeforefilter if this widget is also a listview
-			this._widget._trigger( "beforefilter", event, data );
-		}
-		this._super( type, event, data );
-	},
-
-	_setWidget: function( widget ) {
-		if ( !this._widget && widget ) {
-			this._widget = widget;
-			this._widget._setOptions = replaceSetOptions( this, this._widget._setOptions );
-		}
-
-		if ( !!this._widget ) {
-			this._syncTextInputOptions( this._widget.options );
-			if ( this._widget.widgetName === "listview" ) {
-				this._widget.options.hideDividers = true;
-				this._widget.element.listview( "refresh" );
-			}
-		}
-
-		return !!this._widget;
-	},
-
-	_isSearchInternal: function() {
-		return ( this._search && this._search.jqmData( "ui-filterable-" + this.uuid + "-internal" ) );
-	},
-
-	_setInput: function( selector ) {
-		var opts = this.options,
-			updatePlaceholder = true,
-			textinputOpts = {};
-
-		if ( !selector ) {
-			if ( this._isSearchInternal() ) {
-
-				// Ignore the call to set a new input if the selector goes to falsy and
-				// the current textinput is already of the internally generated variety.
-				return;
-			} else {
-
-				// Generating a new textinput widget. No need to set the placeholder
-				// further down the function.
-				updatePlaceholder = false;
-				selector = $( "<input " +
-					"data-" + $.mobile.ns + "type='search' " +
-					"placeholder='" + opts.filterPlaceholder + "'></input>" )
-					.jqmData( "ui-filterable-" + this.uuid + "-internal", true );
-				$( "<form class='ui-filterable'></form>" )
-					.append( selector )
-					.submit( function( evt ) {
-						evt.preventDefault();
-						selector.blur();
-					})
-					.insertBefore( this.element );
-				if ( $.mobile.textinput ) {
-					if ( this.options.filterTheme != null ) {
-						textinputOpts[ "theme" ] = opts.filterTheme;
-					}
-
-					selector.textinput( textinputOpts );
-				}
-			}
-		}
-
-		this._super( selector );
-
-		if ( this._isSearchInternal() && updatePlaceholder ) {
-			this._search.attr( "placeholder", this.options.filterPlaceholder );
-		}
-	},
-
-	_setOptions: function( options ) {
-		var ret = this._super( options );
-
-		// Need to set the filterPlaceholder after having established the search input
-		if ( options.filterPlaceholder !== undefined ) {
-			if ( this._isSearchInternal() ) {
-				this._search.attr( "placeholder", options.filterPlaceholder );
-			}
-		}
-
-		if ( options.filterTheme !== undefined && this._search && $.mobile.textinput ) {
-			this._search.textinput( "option", "theme", options.filterTheme );
-		}
-
-		return ret;
-	},
-
-	_destroy: function() {
-		if ( this._isSearchInternal() ) {
-			this._search.remove();
-		}
-		this._super();
-	},
-
-	_syncTextInputOptions: function( options ) {
-		var idx,
-			textinputOptions = {};
-
-		// We only sync options if the filterable's textinput is of the internally
-		// generated variety, rather than one specified by the user.
-		if ( this._isSearchInternal() && $.mobile.textinput ) {
-
-			// Apply only the options understood by textinput
-			for ( idx in $.mobile.textinput.prototype.options ) {
-				if ( options[ idx ] !== undefined ) {
-					if ( idx === "theme" && this.options.filterTheme != null ) {
-						textinputOptions[ idx ] = this.options.filterTheme;
-					} else {
-						textinputOptions[ idx ] = options[ idx ];
-					}
-				}
-			}
-			this._search.textinput( "option", textinputOptions );
-		}
-	}
-});
-
-})( jQuery );
-
-/*!
- * jQuery UI Tabs fadf2b312a05040436451c64bbfaf4814bc62c56
- * http://jqueryui.com
- *
- * Copyright 2013 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://api.jqueryui.com/tabs/
- *
- * Depends:
- *	jquery.ui.core.js
- *	jquery.ui.widget.js
- */
-(function( $, undefined ) {
-
-var tabId = 0,
-	rhash = /#.*$/;
-
-function getNextTabId() {
-	return ++tabId;
-}
-
-function isLocal( anchor ) {
-	return anchor.hash.length > 1 &&
-		decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
-			decodeURIComponent( location.href.replace( rhash, "" ) );
-}
-
-$.widget( "ui.tabs", {
-	version: "fadf2b312a05040436451c64bbfaf4814bc62c56",
-	delay: 300,
-	options: {
-		active: null,
-		collapsible: false,
-		event: "click",
-		heightStyle: "content",
-		hide: null,
-		show: null,
-
-		// callbacks
-		activate: null,
-		beforeActivate: null,
-		beforeLoad: null,
-		load: null
-	},
-
-	_create: function() {
-		var that = this,
-			options = this.options;
-
-		this.running = false;
-
-		this.element
-			.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
-			.toggleClass( "ui-tabs-collapsible", options.collapsible )
-			// Prevent users from focusing disabled tabs via click
-			.delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
-				if ( $( this ).is( ".ui-state-disabled" ) ) {
-					event.preventDefault();
-				}
-			})
-			// support: IE <9
-			// Preventing the default action in mousedown doesn't prevent IE
-			// from focusing the element, so if the anchor gets focused, blur.
-			// We don't have to worry about focusing the previously focused
-			// element since clicking on a non-focusable element should focus
-			// the body anyway.
-			.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
-				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
-					this.blur();
-				}
-			});
-
-		this._processTabs();
-		options.active = this._initialActive();
-
-		// Take disabling tabs via class attribute from HTML
-		// into account and update option properly.
-		if ( $.isArray( options.disabled ) ) {
-			options.disabled = $.unique( options.disabled.concat(
-				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
-					return that.tabs.index( li );
-				})
-			) ).sort();
-		}
-
-		// check for length avoids error when initializing empty list
-		if ( this.options.active !== false && this.anchors.length ) {
-			this.active = this._findActive( options.active );
-		} else {
-			this.active = $();
-		}
-
-		this._refresh();
-
-		if ( this.active.length ) {
-			this.load( options.active );
-		}
-	},
-
-	_initialActive: function() {
-		var active = this.options.active,
-			collapsible = this.options.collapsible,
-			locationHash = location.hash.substring( 1 );
-
-		if ( active === null ) {
-			// check the fragment identifier in the URL
-			if ( locationHash ) {
-				this.tabs.each(function( i, tab ) {
-					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
-						active = i;
-						return false;
-					}
-				});
-			}
-
-			// check for a tab marked active via a class
-			if ( active === null ) {
-				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
-			}
-
-			// no active tab, set to false
-			if ( active === null || active === -1 ) {
-				active = this.tabs.length ? 0 : false;
-			}
-		}
-
-		// handle numbers: negative, out of range
-		if ( active !== false ) {
-			active = this.tabs.index( this.tabs.eq( active ) );
-			if ( active === -1 ) {
-				active = collapsible ? false : 0;
-			}
-		}
-
-		// don't allow collapsible: false and active: false
-		if ( !collapsible && active === false && this.anchors.length ) {
-			active = 0;
-		}
-
-		return active;
-	},
-
-	_getCreateEventData: function() {
-		return {
-			tab: this.active,
-			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
-		};
-	},
-
-	_tabKeydown: function( event ) {
-		var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
-			selectedIndex = this.tabs.index( focusedTab ),
-			goingForward = true;
-
-		if ( this._handlePageNav( event ) ) {
-			return;
-		}
-
-		switch ( event.keyCode ) {
-			case $.ui.keyCode.RIGHT:
-			case $.ui.keyCode.DOWN:
-				selectedIndex++;
-				break;
-			case $.ui.keyCode.UP:
-			case $.ui.keyCode.LEFT:
-				goingForward = false;
-				selectedIndex--;
-				break;
-			case $.ui.keyCode.END:
-				selectedIndex = this.anchors.length - 1;
-				break;
-			case $.ui.keyCode.HOME:
-				selectedIndex = 0;
-				break;
-			case $.ui.keyCode.SPACE:
-				// Activate only, no collapsing
-				event.preventDefault();
-				clearTimeout( this.activating );
-				this._activate( selectedIndex );
-				return;
-			case $.ui.keyCode.ENTER:
-				// Toggle (cancel delayed activation, allow collapsing)
-				event.preventDefault();
-				clearTimeout( this.activating );
-				// Determine if we should collapse or activate
-				this._activate( selectedIndex === this.options.active ? false : selectedIndex );
-				return;
-			default:
-				return;
-		}
-
-		// Focus the appropriate tab, based on which key was pressed
-		event.preventDefault();
-		clearTimeout( this.activating );
-		selectedIndex = this._focusNextTab( selectedIndex, goingForward );
-
-		// Navigating with control key will prevent automatic activation
-		if ( !event.ctrlKey ) {
-			// Update aria-selected immediately so that AT think the tab is already selected.
-			// Otherwise AT may confuse the user by stating that they need to activate the tab,
-			// but the tab will already be activated by the time the announcement finishes.
-			focusedTab.attr( "aria-selected", "false" );
-			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
-
-			this.activating = this._delay(function() {
-				this.option( "active", selectedIndex );
-			}, this.delay );
-		}
-	},
-
-	_panelKeydown: function( event ) {
-		if ( this._handlePageNav( event ) ) {
-			return;
-		}
-
-		// Ctrl+up moves focus to the current tab
-		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
-			event.preventDefault();
-			this.active.focus();
-		}
-	},
-
-	// Alt+page up/down moves focus to the previous/next tab (and activates)
-	_handlePageNav: function( event ) {
-		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
-			this._activate( this._focusNextTab( this.options.active - 1, false ) );
-			return true;
-		}
-		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
-			this._activate( this._focusNextTab( this.options.active + 1, true ) );
-			return true;
-		}
-	},
-
-	_findNextTab: function( index, goingForward ) {
-		var lastTabIndex = this.tabs.length - 1;
-
-		function constrain() {
-			if ( index > lastTabIndex ) {
-				index = 0;
-			}
-			if ( index < 0 ) {
-				index = lastTabIndex;
-			}
-			return index;
-		}
-
-		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
-			index = goingForward ? index + 1 : index - 1;
-		}
-
-		return index;
-	},
-
-	_focusNextTab: function( index, goingForward ) {
-		index = this._findNextTab( index, goingForward );
-		this.tabs.eq( index ).focus();
-		return index;
-	},
-
-	_setOption: function( key, value ) {
-		if ( key === "active" ) {
-			// _activate() will handle invalid values and update this.options
-			this._activate( value );
-			return;
-		}
-
-		if ( key === "disabled" ) {
-			// don't use the widget factory's disabled handling
-			this._setupDisabled( value );
-			return;
-		}
-
-		this._super( key, value);
-
-		if ( key === "collapsible" ) {
-			this.element.toggleClass( "ui-tabs-collapsible", value );
-			// Setting collapsible: false while collapsed; open first panel
-			if ( !value && this.options.active === false ) {
-				this._activate( 0 );
-			}
-		}
-
-		if ( key === "event" ) {
-			this._setupEvents( value );
-		}
-
-		if ( key === "heightStyle" ) {
-			this._setupHeightStyle( value );
-		}
-	},
-
-	_tabId: function( tab ) {
-		return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
-	},
-
-	_sanitizeSelector: function( hash ) {
-		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
-	},
-
-	refresh: function() {
-		var options = this.options,
-			lis = this.tablist.children( ":has(a[href])" );
-
-		// get disabled tabs from class attribute from HTML
-		// this will get converted to a boolean if needed in _refresh()
-		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
-			return lis.index( tab );
-		});
-
-		this._processTabs();
-
-		// was collapsed or no tabs
-		if ( options.active === false || !this.anchors.length ) {
-			options.active = false;
-			this.active = $();
-		// was active, but active tab is gone
-		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
-			// all remaining tabs are disabled
-			if ( this.tabs.length === options.disabled.length ) {
-				options.active = false;
-				this.active = $();
-			// activate previous tab
-			} else {
-				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
-			}
-		// was active, active tab still exists
-		} else {
-			// make sure active index is correct
-			options.active = this.tabs.index( this.active );
-		}
-
-		this._refresh();
-	},
-
-	_refresh: function() {
-		this._setupDisabled( this.options.disabled );
-		this._setupEvents( this.options.event );
-		this._setupHeightStyle( this.options.heightStyle );
-
-		this.tabs.not( this.active ).attr({
-			"aria-selected": "false",
-			tabIndex: -1
-		});
-		this.panels.not( this._getPanelForTab( this.active ) )
-			.hide()
-			.attr({
-				"aria-expanded": "false",
-				"aria-hidden": "true"
-			});
-
-		// Make sure one tab is in the tab order
-		if ( !this.active.length ) {
-			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
-		} else {
-			this.active
-				.addClass( "ui-tabs-active ui-state-active" )
-				.attr({
-					"aria-selected": "true",
-					tabIndex: 0
-				});
-			this._getPanelForTab( this.active )
-				.show()
-				.attr({
-					"aria-expanded": "true",
-					"aria-hidden": "false"
-				});
-		}
-	},
-
-	_processTabs: function() {
-		var that = this;
-
-		this.tablist = this._getList()
-			.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
-			.attr( "role", "tablist" );
-
-		this.tabs = this.tablist.find( "> li:has(a[href])" )
-			.addClass( "ui-state-default ui-corner-top" )
-			.attr({
-				role: "tab",
-				tabIndex: -1
-			});
-
-		this.anchors = this.tabs.map(function() {
-				return $( "a", this )[ 0 ];
-			})
-			.addClass( "ui-tabs-anchor" )
-			.attr({
-				role: "presentation",
-				tabIndex: -1
-			});
-
-		this.panels = $();
-
-		this.anchors.each(function( i, anchor ) {
-			var selector, panel, panelId,
-				anchorId = $( anchor ).uniqueId().attr( "id" ),
-				tab = $( anchor ).closest( "li" ),
-				originalAriaControls = tab.attr( "aria-controls" );
-
-			// inline tab
-			if ( isLocal( anchor ) ) {
-				selector = anchor.hash;
-				panel = that.element.find( that._sanitizeSelector( selector ) );
-			// remote tab
-			} else {
-				panelId = that._tabId( tab );
-				selector = "#" + panelId;
-				panel = that.element.find( selector );
-				if ( !panel.length ) {
-					panel = that._createPanel( panelId );
-					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
-				}
-				panel.attr( "aria-live", "polite" );
-			}
-
-			if ( panel.length) {
-				that.panels = that.panels.add( panel );
-			}
-			if ( originalAriaControls ) {
-				tab.data( "ui-tabs-aria-controls", originalAriaControls );
-			}
-			tab.attr({
-				"aria-controls": selector.substring( 1 ),
-				"aria-labelledby": anchorId
-			});
-			panel.attr( "aria-labelledby", anchorId );
-		});
-
-		this.panels
-			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
-			.attr( "role", "tabpanel" );
-	},
-
-	// allow overriding how to find the list for rare usage scenarios (#7715)
-	_getList: function() {
-		return this.element.find( "ol,ul" ).eq( 0 );
-	},
-
-	_createPanel: function( id ) {
-		return $( "<div>" )
-			.attr( "id", id )
-			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
-			.data( "ui-tabs-destroy", true );
-	},
-
-	_setupDisabled: function( disabled ) {
-		if ( $.isArray( disabled ) ) {
-			if ( !disabled.length ) {
-				disabled = false;
-			} else if ( disabled.length === this.anchors.length ) {
-				disabled = true;
-			}
-		}
-
-		// disable tabs
-		for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
-			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
-				$( li )
-					.addClass( "ui-state-disabled" )
-					.attr( "aria-disabled", "true" );
-			} else {
-				$( li )
-					.removeClass( "ui-state-disabled" )
-					.removeAttr( "aria-disabled" );
-			}
-		}
-
-		this.options.disabled = disabled;
-	},
-
-	_setupEvents: function( event ) {
-		var events = {
-			click: function( event ) {
-				event.preventDefault();
-			}
-		};
-		if ( event ) {
-			$.each( event.split(" "), function( index, eventName ) {
-				events[ eventName ] = "_eventHandler";
-			});
-		}
-
-		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
-		this._on( this.anchors, events );
-		this._on( this.tabs, { keydown: "_tabKeydown" } );
-		this._on( this.panels, { keydown: "_panelKeydown" } );
-
-		this._focusable( this.tabs );
-		this._hoverable( this.tabs );
-	},
-
-	_setupHeightStyle: function( heightStyle ) {
-		var maxHeight,
-			parent = this.element.parent();
-
-		if ( heightStyle === "fill" ) {
-			maxHeight = parent.height();
-			maxHeight -= this.element.outerHeight() - this.element.height();
-
-			this.element.siblings( ":visible" ).each(function() {
-				var elem = $( this ),
-					position = elem.css( "position" );
-
-				if ( position === "absolute" || position === "fixed" ) {
-					return;
-				}
-				maxHeight -= elem.outerHeight( true );
-			});
-
-			this.element.children().not( this.panels ).each(function() {
-				maxHeight -= $( this ).outerHeight( true );
-			});
-
-			this.panels.each(function() {
-				$( this ).height( Math.max( 0, maxHeight -
-					$( this ).innerHeight() + $( this ).height() ) );
-			})
-			.css( "overflow", "auto" );
-		} else if ( heightStyle === "auto" ) {
-			maxHeight = 0;
-			this.panels.each(function() {
-				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
-			}).height( maxHeight );
-		}
-	},
-
-	_eventHandler: function( event ) {
-		var options = this.options,
-			active = this.active,
-			anchor = $( event.currentTarget ),
-			tab = anchor.closest( "li" ),
-			clickedIsActive = tab[ 0 ] === active[ 0 ],
-			collapsing = clickedIsActive && options.collapsible,
-			toShow = collapsing ? $() : this._getPanelForTab( tab ),
-			toHide = !active.length ? $() : this._getPanelForTab( active ),
-			eventData = {
-				oldTab: active,
-				oldPanel: toHide,
-				newTab: collapsing ? $() : tab,
-				newPanel: toShow
-			};
-
-		event.preventDefault();
-
-		if ( tab.hasClass( "ui-state-disabled" ) ||
-				// tab is already loading
-				tab.hasClass( "ui-tabs-loading" ) ||
-				// can't switch durning an animation
-				this.running ||
-				// click on active header, but not collapsible
-				( clickedIsActive && !options.collapsible ) ||
-				// allow canceling activation
-				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
-			return;
-		}
-
-		options.active = collapsing ? false : this.tabs.index( tab );
-
-		this.active = clickedIsActive ? $() : tab;
-		if ( this.xhr ) {
-			this.xhr.abort();
-		}
-
-		if ( !toHide.length && !toShow.length ) {
-			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
-		}
-
-		if ( toShow.length ) {
-			this.load( this.tabs.index( tab ), event );
-		}
-		this._toggle( event, eventData );
-	},
-
-	// handles show/hide for selecting tabs
-	_toggle: function( event, eventData ) {
-		var that = this,
-			toShow = eventData.newPanel,
-			toHide = eventData.oldPanel;
-
-		this.running = true;
-
-		function complete() {
-			that.running = false;
-			that._trigger( "activate", event, eventData );
-		}
-
-		function show() {
-			eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
-
-			if ( toShow.length && that.options.show ) {
-				that._show( toShow, that.options.show, complete );
-			} else {
-				toShow.show();
-				complete();
-			}
-		}
-
-		// start out by hiding, then showing, then completing
-		if ( toHide.length && this.options.hide ) {
-			this._hide( toHide, this.options.hide, function() {
-				eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
-				show();
-			});
-		} else {
-			eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
-			toHide.hide();
-			show();
-		}
-
-		toHide.attr({
-			"aria-expanded": "false",
-			"aria-hidden": "true"
-		});
-		eventData.oldTab.attr( "aria-selected", "false" );
-		// If we're switching tabs, remove the old tab from the tab order.
-		// If we're opening from collapsed state, remove the previous tab from the tab order.
-		// If we're collapsing, then keep the collapsing tab in the tab order.
-		if ( toShow.length && toHide.length ) {
-			eventData.oldTab.attr( "tabIndex", -1 );
-		} else if ( toShow.length ) {
-			this.tabs.filter(function() {
-				return $( this ).attr( "tabIndex" ) === 0;
-			})
-			.attr( "tabIndex", -1 );
-		}
-
-		toShow.attr({
-			"aria-expanded": "true",
-			"aria-hidden": "false"
-		});
-		eventData.newTab.attr({
-			"aria-selected": "true",
-			tabIndex: 0
-		});
-	},
-
-	_activate: function( index ) {
-		var anchor,
-			active = this._findActive( index );
-
-		// trying to activate the already active panel
-		if ( active[ 0 ] === this.active[ 0 ] ) {
-			return;
-		}
-
-		// trying to collapse, simulate a click on the current active header
-		if ( !active.length ) {
-			active = this.active;
-		}
-
-		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
-		this._eventHandler({
-			target: anchor,
-			currentTarget: anchor,
-			preventDefault: $.noop
-		});
-	},
-
-	_findActive: function( index ) {
-		return index === false ? $() : this.tabs.eq( index );
-	},
-
-	_getIndex: function( index ) {
-		// meta-function to give users option to provide a href string instead of a numerical index.
-		if ( typeof index === "string" ) {
-			index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
-		}
-
-		return index;
-	},
-
-	_destroy: function() {
-		if ( this.xhr ) {
-			this.xhr.abort();
-		}
-
-		this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
-
-		this.tablist
-			.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
-			.removeAttr( "role" );
-
-		this.anchors
-			.removeClass( "ui-tabs-anchor" )
-			.removeAttr( "role" )
-			.removeAttr( "tabIndex" )
-			.removeUniqueId();
-
-		this.tabs.add( this.panels ).each(function() {
-			if ( $.data( this, "ui-tabs-destroy" ) ) {
-				$( this ).remove();
-			} else {
-				$( this )
-					.removeClass( "ui-state-default ui-state-active ui-state-disabled " +
-						"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
-					.removeAttr( "tabIndex" )
-					.removeAttr( "aria-live" )
-					.removeAttr( "aria-busy" )
-					.removeAttr( "aria-selected" )
-					.removeAttr( "aria-labelledby" )
-					.removeAttr( "aria-hidden" )
-					.removeAttr( "aria-expanded" )
-					.removeAttr( "role" );
-			}
-		});
-
-		this.tabs.each(function() {
-			var li = $( this ),
-				prev = li.data( "ui-tabs-aria-controls" );
-			if ( prev ) {
-				li
-					.attr( "aria-controls", prev )
-					.removeData( "ui-tabs-aria-controls" );
-			} else {
-				li.removeAttr( "aria-controls" );
-			}
-		});
-
-		this.panels.show();
-
-		if ( this.options.heightStyle !== "content" ) {
-			this.panels.css( "height", "" );
-		}
-	},
-
-	enable: function( index ) {
-		var disabled = this.options.disabled;
-		if ( disabled === false ) {
-			return;
-		}
-
-		if ( index === undefined ) {
-			disabled = false;
-		} else {
-			index = this._getIndex( index );
-			if ( $.isArray( disabled ) ) {
-				disabled = $.map( disabled, function( num ) {
-					return num !== index ? num : null;
-				});
-			} else {
-				disabled = $.map( this.tabs, function( li, num ) {
-					return num !== index ? num : null;
-				});
-			}
-		}
-		this._setupDisabled( disabled );
-	},
-
-	disable: function( index ) {
-		var disabled = this.options.disabled;
-		if ( disabled === true ) {
-			return;
-		}
-
-		if ( index === undefined ) {
-			disabled = true;
-		} else {
-			index = this._getIndex( index );
-			if ( $.inArray( index, disabled ) !== -1 ) {
-				return;
-			}
-			if ( $.isArray( disabled ) ) {
-				disabled = $.merge( [ index ], disabled ).sort();
-			} else {
-				disabled = [ index ];
-			}
-		}
-		this._setupDisabled( disabled );
-	},
-
-	load: function( index, event ) {
-		index = this._getIndex( index );
-		var that = this,
-			tab = this.tabs.eq( index ),
-			anchor = tab.find( ".ui-tabs-anchor" ),
-			panel = this._getPanelForTab( tab ),
-			eventData = {
-				tab: tab,
-				panel: panel
-			};
-
-		// not remote
-		if ( isLocal( anchor[ 0 ] ) ) {
-			return;
-		}
-
-		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
-
-		// support: jQuery <1.8
-		// jQuery <1.8 returns false if the request is canceled in beforeSend,
-		// but as of 1.8, $.ajax() always returns a jqXHR object.
-		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
-			tab.addClass( "ui-tabs-loading" );
-			panel.attr( "aria-busy", "true" );
-
-			this.xhr
-				.success(function( response ) {
-					// support: jQuery <1.8
-					// http://bugs.jquery.com/ticket/11778
-					setTimeout(function() {
-						panel.html( response );
-						that._trigger( "load", event, eventData );
-					}, 1 );
-				})
-				.complete(function( jqXHR, status ) {
-					// support: jQuery <1.8
-					// http://bugs.jquery.com/ticket/11778
-					setTimeout(function() {
-						if ( status === "abort" ) {
-							that.panels.stop( false, true );
-						}
-
-						tab.removeClass( "ui-tabs-loading" );
-						panel.removeAttr( "aria-busy" );
-
-						if ( jqXHR === that.xhr ) {
-							delete that.xhr;
-						}
-					}, 1 );
-				});
-		}
-	},
-
-	_ajaxSettings: function( anchor, event, eventData ) {
-		var that = this;
-		return {
-			url: anchor.attr( "href" ),
-			beforeSend: function( jqXHR, settings ) {
-				return that._trigger( "beforeLoad", event,
-					$.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
-			}
-		};
-	},
-
-	_getPanelForTab: function( tab ) {
-		var id = $( tab ).attr( "aria-controls" );
-		return this.element.find( this._sanitizeSelector( "#" + id ) );
-	}
-});
-
-})( jQuery );
-
-(function( $, undefined ) {
-
-})( jQuery );
-
-(function( $, window ) {
-
-	$.mobile.iosorientationfixEnabled = true;
-
-	// This fix addresses an iOS bug, so return early if the UA claims it's something else.
-	var ua = navigator.userAgent,
-		zoom,
-		evt, x, y, z, aig;
-	if ( !( /iPhone|iPad|iPod/.test( navigator.platform ) && /OS [1-5]_[0-9_]* like Mac OS X/i.test( ua ) && ua.indexOf( "AppleWebKit" ) > -1 ) ) {
-		$.mobile.iosorientationfixEnabled = false;
-		return;
-	}
-
-	zoom = $.mobile.zoom;
-
-	function checkTilt( e ) {
-		evt = e.originalEvent;
-		aig = evt.accelerationIncludingGravity;
-
-		x = Math.abs( aig.x );
-		y = Math.abs( aig.y );
-		z = Math.abs( aig.z );
-
-		// If portrait orientation and in one of the danger zones
-		if ( !window.orientation && ( x > 7 || ( ( z > 6 && y < 8 || z < 8 && y > 6 ) && x > 5 ) ) ) {
-				if ( zoom.enabled ) {
-					zoom.disable();
-				}
-		}	else if ( !zoom.enabled ) {
-				zoom.enable();
-		}
-	}
-
-	$.mobile.document.on( "mobileinit", function() {
-		if ( $.mobile.iosorientationfixEnabled ) {
-			$.mobile.window
-				.bind( "orientationchange.iosorientationfix", zoom.enable )
-				.bind( "devicemotion.iosorientationfix", checkTilt );
-		}
-	});
-
-}( jQuery, this ));
-
-(function( $, window, undefined ) {
-	var	$html = $( "html" ),
-		$window = $.mobile.window;
-
-	//remove initial build class (only present on first pageshow)
-	function hideRenderingClass() {
-		$html.removeClass( "ui-mobile-rendering" );
-	}
-
-	// trigger mobileinit event - useful hook for configuring $.mobile settings before they're used
-	$( window.document ).trigger( "mobileinit" );
-
-	// support conditions
-	// if device support condition(s) aren't met, leave things as they are -> a basic, usable experience,
-	// otherwise, proceed with the enhancements
-	if ( !$.mobile.gradeA() ) {
-		return;
-	}
-
-	// override ajaxEnabled on platforms that have known conflicts with hash history updates
-	// or generally work better browsing in regular http for full page refreshes (BB5, Opera Mini)
-	if ( $.mobile.ajaxBlacklist ) {
-		$.mobile.ajaxEnabled = false;
-	}
-
-	// Add mobile, initial load "rendering" classes to docEl
-	$html.addClass( "ui-mobile ui-mobile-rendering" );
-
-	// This is a fallback. If anything goes wrong (JS errors, etc), or events don't fire,
-	// this ensures the rendering class is removed after 5 seconds, so content is visible and accessible
-	setTimeout( hideRenderingClass, 5000 );
-
-	$.extend( $.mobile, {
-		// find and enhance the pages in the dom and transition to the first page.
-		initializePage: function() {
-			// find present pages
-			var path = $.mobile.path,
-				$pages = $( ":jqmData(role='page'), :jqmData(role='dialog')" ),
-				hash = path.stripHash( path.stripQueryParams(path.parseLocation().hash) ),
-				hashPage = document.getElementById( hash );
-
-			// if no pages are found, create one with body's inner html
-			if ( !$pages.length ) {
-				$pages = $( "body" ).wrapInner( "<div data-" + $.mobile.ns + "role='page'></div>" ).children( 0 );
-			}
-
-			// add dialogs, set data-url attrs
-			$pages.each(function() {
-				var $this = $( this );
-
-				// unless the data url is already set set it to the pathname
-				if ( !$this[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) ) {
-					$this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) || location.pathname + location.search );
-				}
-			});
-
-			// define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)
-			$.mobile.firstPage = $pages.first();
-
-			// define page container
-			$.mobile.pageContainer = $.mobile.firstPage
-				.parent()
-				.addClass( "ui-mobile-viewport" )
-				.pagecontainer();
-
-			// initialize navigation events now, after mobileinit has occurred and the page container
-			// has been created but before the rest of the library is alerted to that fact
-			$.mobile.navreadyDeferred.resolve();
-
-			// alert listeners that the pagecontainer has been determined for binding
-			// to events triggered on it
-			$window.trigger( "pagecontainercreate" );
-
-			// cue page loading message
-			$.mobile.loading( "show" );
-
-			//remove initial build class (only present on first pageshow)
-			hideRenderingClass();
-
-			// if hashchange listening is disabled, there's no hash deeplink,
-			// the hash is not valid (contains more than one # or does not start with #)
-			// or there is no page with that hash, change to the first page in the DOM
-			// Remember, however, that the hash can also be a path!
-			if ( ! ( $.mobile.hashListeningEnabled &&
-				$.mobile.path.isHashValid( location.hash ) &&
-				( $( hashPage ).is( ":jqmData(role='page')" ) ||
-					$.mobile.path.isPath( hash ) ||
-					hash === $.mobile.dialogHashKey ) ) ) {
-
-				// Store the initial destination
-				if ( $.mobile.path.isHashValid( location.hash ) ) {
-					$.mobile.navigate.history.initialDst = hash.replace( "#", "" );
-				}
-
-				// make sure to set initial popstate state if it exists
-				// so that navigation back to the initial page works properly
-				if ( $.event.special.navigate.isPushStateEnabled() ) {
-					$.mobile.navigate.navigator.squash( path.parseLocation().href );
-				}
-
-				$.mobile.changePage( $.mobile.firstPage, {
-					transition: "none",
-					reverse: true,
-					changeHash: false,
-					fromHashChange: true
-				});
-			} else {
-				// trigger hashchange or navigate to squash and record the correct
-				// history entry for an initial hash path
-				if ( !$.event.special.navigate.isPushStateEnabled() ) {
-					$window.trigger( "hashchange", [true] );
-				} else {
-					// TODO figure out how to simplify this interaction with the initial history entry
-					// at the bottom js/navigate/navigate.js
-					$.mobile.navigate.history.stack = [];
-					$.mobile.navigate( $.mobile.path.isPath( location.hash ) ? location.hash : location.href );
-				}
-			}
-		}
-	});
-
-	$(function() {
-		//Run inlineSVG support test
-		$.support.inlineSVG();
-
-		// check which scrollTop value should be used by scrolling to 1 immediately at domready
-		// then check what the scroll top is. Android will report 0... others 1
-		// note that this initial scroll won't hide the address bar. It's just for the check.
-
-		// hide iOS browser chrome on load if hideUrlBar is true this is to try and do it as soon as possible
-		if ( $.mobile.hideUrlBar ) {
-			window.scrollTo( 0, 1 );
-		}
-
-		// if defaultHomeScroll hasn't been set yet, see if scrollTop is 1
-		// it should be 1 in most browsers, but android treats 1 as 0 (for hiding addr bar)
-		// so if it's 1, use 0 from now on
-		$.mobile.defaultHomeScroll = ( !$.support.scrollTop || $.mobile.window.scrollTop() === 1 ) ? 0 : 1;
-
-		//dom-ready inits
-		if ( $.mobile.autoInitializePage ) {
-			$.mobile.initializePage();
-		}
-
-		// window load event
-		// hide iOS browser chrome on load if hideUrlBar is true this is as fall back incase we were too early before
-		if ( $.mobile.hideUrlBar ) {
-			$window.load( $.mobile.silentScroll );
-		}
-
-		if ( !$.support.cssPointerEvents ) {
-			// IE and Opera don't support CSS pointer-events: none that we use to disable link-based buttons
-			// by adding the 'ui-disabled' class to them. Using a JavaScript workaround for those browser.
-			// https://github.com/jquery/jquery-mobile/issues/3558
-
-			// DEPRECATED as of 1.4.0 - remove ui-disabled after 1.4.0 release
-			// only ui-state-disabled should be present thereafter
-			$.mobile.document.delegate( ".ui-state-disabled,.ui-disabled", "vclick",
-				function( e ) {
-					e.preventDefault();
-					e.stopImmediatePropagation();
-				}
-			);
-		}
-	});
-}( jQuery, this ));
-
-
-}));
deleted file mode 100644
index e1a98e1580e465b08ca547ee1466977eb084ef0a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/js/src/jsapi-tests/binast/parser/tester/frameworks/mootools-1.4.js
+++ /dev/null
@@ -1,6447 +0,0 @@
-/*
----
-MooTools: the javascript framework
-
-web build:
- - http://mootools.net/core/76bf47062d6c1983d66ce47ad66aa0e0
-
-packager build:
- - packager build Core/Core Core/Array Core/String Core/Number Core/Function Core/Object Core/Event Core/Browser Core/Class Core/Class.Extras Core/Slick.Parser Core/Slick.Finder Core/Element Core/Element.Style Core/Element.Event Core/Element.Delegation Core/Element.Dimensions Core/Fx Core/Fx.CSS Core/Fx.Tween Core/Fx.Morph Core/Fx.Transitions Core/Request Core/Request.HTML Core/Request.JSON Core/Cookie Core/JSON Core/DOMReady Core/Swiff
-
-...
-*/
-
-/*
----
-
-name: Core
-
-description: The heart of MooTools.
-
-license: MIT-style license.
-
-copyright: Copyright (c) 2006-2012 [Valerio Proietti](http://mad4milk.net/).
-
-authors: The MooTools production team (http://mootools.net/developers/)
-
-inspiration:
-  - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)
-  - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)
-
-provides: [Core, MooTools, Type, typeOf, instanceOf, Native]
-
-...
-*/
-
-(function(){
-
-this.MooTools = {
-	version: '1.4.5',
-	build: 'ab8ea8824dc3b24b6666867a2c4ed58ebb762cf0'
-};
-
-// typeOf, instanceOf
-
-var typeOf = this.typeOf = function(item){
-	if (item == null) return 'null';
-	if (item.$family != null) return item.$family();
-
-	if (item.nodeName){
-		if (item.nodeType == 1) return 'element';
-		if (item.nodeType == 3) return (/\S/).test(item.nodeValue) ? 'textnode' : 'whitespace';
-	} else if (typeof item.length == 'number'){
-		if (item.callee) return 'arguments';
-		if ('item' in item) return 'collection';
-	}
-
-	return typeof item;
-};
-
-var instanceOf = this.instanceOf = function(item, object){
-	if (item == null) return false;
-	var constructor = item.$constructor || item.constructor;
-	while (constructor){
-		if (constructor === object) return true;
-		constructor = constructor.parent;
-	}
-	/*<ltIE8>*/
-	if (!item.hasOwnProperty) return false;
-	/*</ltIE8>*/
-	return item instanceof object;
-};
-
-// Function overloading
-
-var Function = this.Function;
-
-var enumerables = true;
-for (var i in {toString: 1}) enumerables = null;
-if (enumerables) enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'];
-
-Function.prototype.overloadSetter = function(usePlural){
-	var self = this;
-	return function(a, b){
-		if (a == null) return this;
-		if (usePlural || typeof a != 'string'){
-			for (var k in a) self.call(this, k, a[k]);
-			if (enumerables) for (var i = enumerables.length; i--;){
-				k = enumerables[i];
-				if (a.hasOwnProperty(k)) self.call(this, k, a[k]);
-			}
-		} else {
-			self.call(this, a, b);
-		}
-		return this;
-	};
-};
-
-Function.prototype.overloadGetter = function(usePlural){
-	var self = this;
-	return function(a){
-		var args, result;
-		if (typeof a != 'string') args = a;
-		else if (arguments.length > 1) args = arguments;
-		else if (usePlural) args = [a];
-		if (args){
-			result = {};
-			for (var i = 0; i < args.length; i++) result[args[i]] = self.call(this, args[i]);
-		} else {
-			result = self.call(this, a);
-		}
-		return result;
-	};
-};
-
-Function.prototype.extend = function(key, value){
-	this[key] = value;
-}.overloadSetter();
-
-Function.prototype.implement = function(key, value){
-	this.prototype[key] = value;
-}.overloadSetter();
-
-// From
-
-var slice = Array.prototype.slice;
-
-Function.from = function(item){
-	return (typeOf(item) == 'function') ? item : function(){
-		return item;
-	};
-};
-
-Array.from = function(item){
-	if (item == null) return [];
-	return (Type.isEnumerable(item) && typeof item != 'string') ? (typeOf(item) == 'array') ? item : slice.call(item) : [item];
-};
-
-Number.from = function(item){
-	var number = parseFloat(item);
-	return isFinite(number) ? number : null;
-};
-
-String.from = function(item){
-	return item + '';
-};
-
-// hide, protect
-
-Function.implement({
-
-	hide: function(){
-		this.$hidden = true;
-		return this;
-	},
-
-	protect: function(){
-		this.$protected = true;
-		return this;
-	}
-
-});
-
-// Type
-
-var Type = this.Type = function(name, object){
-	if (name){
-		var lower = name.toLowerCase();
-		var typeCheck = function(item){
-			return (typeOf(item) == lower);
-		};
-
-		Type['is' + name] = typeCheck;
-		if (object != null){
-			object.prototype.$family = (function(){
-				return lower;
-			}).hide();
-			//<1.2compat>
-			object.type = typeCheck;
-			//</1.2compat>
-		}
-	}
-
-	if (object == null) return null;
-
-	object.extend(this);
-	object.$constructor = Type;
-	object.prototype.$constructor = object;
-
-	return object;
-};
-
-var toString = Object.prototype.toString;
-
-Type.isEnumerable = function(item){
-	return (item != null && typeof item.length == 'number' && toString.call(item) != '[object Function]' );
-};
-
-var hooks = {};
-
-var hooksOf = function(object){
-	var type = typeOf(object.prototype);
-	return hooks[type] || (hooks[type] = []);
-};
-
-var implement = function(name, method){
-	if (method && method.$hidden) return;
-
-	var hooks = hooksOf(this);
-
-	for (var i = 0; i < hooks.length; i++){
-		var hook = hooks[i];
-		if (typeOf(hook) == 'type') implement.call(hook, name, method);
-		else hook.call(this, name, method);
-	}
-
-	var previous = this.prototype[name];
-	if (previous == null || !previous.$protected) this.prototype[name] = method;
-
-	if (this[name] == null && typeOf(method) == 'function') extend.call(this, name, function(item){
-		return method.apply(item, slice.call(arguments, 1));
-	});
-};
-
-var extend = function(name, method){
-	if (method && method.$hidden) return;
-	var previous = this[name];
-	if (previous == null || !previous.$protected) this[name] = method;
-};
-
-Type.implement({
-
-	implement: implement.overloadSetter(),
-
-	extend: extend.overloadSetter(),
-
-	alias: function(name, existing){
-		implement.call(this, name, this.prototype[existing]);
-	}.overloadSetter(),
-
-	mirror: function(hook){
-		hooksOf(this).push(hook);
-		return this;
-	}
-
-});
-
-new Type('Type', Type);
-
-// Default Types
-
-var force = function(name, object, methods){
-	var isType = (object != Object),
-		prototype = object.prototype;
-
-	if (isType) object = new Type(name, object);
-
-	for (var i = 0, l = methods.length; i < l; i++){
-		var key = methods[i],
-			generic = object[key],
-			proto = prototype[key];
-
-		if (generic) generic.protect();
-		if (isType && proto) object.implement(key, proto.protect());
-	}
-
-	if (isType){
-		var methodsEnumerable = prototype.propertyIsEnumerable(methods[0]);
-		object.forEachMethod = function(fn){
-			if (!methodsEnumerable) for (var i = 0, l = methods.length; i < l; i++){
-				fn.call(prototype, prototype[methods[i]], methods[i]);
-			}
-			for (var key in prototype) fn.call(prototype, prototype[key], key)
-		};
-	}
-
-	return force;
-};
-
-force('String', String, [
-	'charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'quote', 'replace', 'search',
-	'slice', 'split', 'substr', 'substring', 'trim', 'toLowerCase', 'toUpperCase'
-])('Array', Array, [
-	'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice',
-	'indexOf', 'lastIndexOf', 'filter', 'forEach', 'every', 'map', 'some', 'reduce', 'reduceRight'
-])('Number', Number, [
-	'toExponential', 'toFixed', 'toLocaleString', 'toPrecision'
-])('Function', Function, [
-	'apply', 'call', 'bind'
-])('RegExp', RegExp, [
-	'exec', 'test'
-])('Object', Object, [
-	'create', 'defineProperty', 'defineProperties', 'keys',
-	'getPrototypeOf', 'getOwnPropertyDescriptor', 'getOwnPropertyNames',
-	'preventExtensions', 'isExtensible', 'seal', 'isSealed', 'freeze', 'isFrozen'
-])('Date', Date, ['now']);
-
-Object.extend = extend.overloadSetter();
-
-Date.extend('now', function(){
-	return +(new Date);
-});
-
-new Type('Boolean', Boolean);
-
-// fixes NaN returning as Number
-
-Number.prototype.$family = function(){
-	return isFinite(this) ? 'number' : 'null';
-}.hide();
-
-// Number.random
-
-Number.extend('random', function(min, max){
-	return Math.floor(Math.random() * (max - min + 1) + min);
-});
-
-// forEach, each
-
-var hasOwnProperty = Object.prototype.hasOwnProperty;
-Object.extend('forEach', function(object, fn, bind){
-	for (var key in object){
-		if (hasOwnProperty.call(object, key)) fn.call(bind, object[key], key, object);
-	}
-});
-
-Object.each = Object.forEach;
-
-Array.implement({
-
-	forEach: function(fn, bind){
-		for (var i = 0, l = this.length; i < l; i++){
-			if (i in this) fn.call(bind, this[i], i, this);
-		}
-	},
-
-	each: function(fn, bind){
-		Array.forEach(this, fn, bind);
-		return this;
-	}
-
-});
-
-// Array & Object cloning, Object merging and appending
-
-var cloneOf = function(item){
-	switch (typeOf(item)){
-		case 'array': return item.clone();
-		case 'object': return Object.clone(item);
-		default: return item;
-	}
-};
-
-Array.implement('clone', function(){
-	var i = this.length, clone = new Array(i);
-	while (i--) clone[i] = cloneOf(this[i]);
-	return clone;
-});
-
-var mergeOne = function(source, key, current){
-	switch (typeOf(current)){
-		case 'object':
-			if (typeOf(source[key]) == 'object') Object.merge(source[key], current);
-			else source[key] = Object.clone(current);
-		break;
-		case 'array': source[key] = current.clone(); break;
-		default: source[key] = current;
-	}
-	return source;
-};
-
-Object.extend({
-
-	merge: function(source, k, v){
-		if (typeOf(k) == 'string') return mergeOne(source, k, v);
-		for (var i = 1, l = arguments.length; i < l; i++){
-			var object = arguments[i];
-			for (var key in object) mergeOne(source, key, object[key]);
-		}
-		return source;
-	},
-
-	clone: function(object){
-		var clone = {};
-		for (var key in object) clone[key] = cloneOf(object[key]);
-		return clone;
-	},
-
-	append: function(original){
-		for (var i = 1, l = arguments.length; i < l; i++){
-			var extended = arguments[i] || {};
-			for (var key in extended) original[key] = extended[key];
-		}
-		return original;
-	}
-
-});
-
-// Object-less types
-
-['Object', 'WhiteSpace', 'TextNode', 'Collection', 'Arguments'].each(function(name){
-	new Type(name);
-});
-
-// Unique ID
-
-var UID = Date.now();
-
-String.extend('uniqueID', function(){
-	return (UID++).toString(36);
-});
-
-//<1.2compat>
-
-var Hash = this.Hash = new Type('Hash', function(object){
-	if (typeOf(object) == 'hash') object = Object.clone(object.getClean());
-	for (var key in object) this[key] = object[key];
-	return this;
-});
-
-Hash.implement({
-
-	forEach: function(fn, bind){
-		Object.forEach(this, fn, bind);
-	},
-
-	getClean: function(){
-		var clean = {};
-		for (var key in this){
-			if (this.hasOwnProperty(key)) clean[key] = this[key];
-		}
-		return clean;
-	},
-
-	getLength: function(){
-		var length = 0;
-		for (var key in this){
-			if (this.hasOwnProperty(key)) length++;
-		}
-		return length;
-	}
-
-});
-
-Hash.alias('each', 'forEach');
-
-Object.type = Type.isObject;
-
-var Native = this.Native = function(properties){
-	return new Type(properties.name, properties.initialize);
-};
-
-Native.type = Type.type;
-
-Native.implement = function(objects, methods){
-	for (var i = 0; i < objects.length; i++) objects[i].implement(methods);
-	return Native;
-};
-
-var arrayType = Array.type;
-Array.type = function(item){
-	return instanceOf(item, Array) || arrayType(item);
-};
-
-this.$A = function(item){
-	return Array.from(item).slice();
-};
-
-this.$arguments = function(i){
-	return function(){
-		return arguments[i];
-	};
-};
-
-this.$chk = function(obj){
-	return !!(obj || obj === 0);
-};
-
-this.$clear = function(timer){
-	clearTimeout(timer);
-	clearInterval(timer);
-	return null;
-};
-
-this.$defined = function(obj){
-	return (obj != null);
-};
-
-this.$each = function(iterable, fn, bind){
-	var type = typeOf(iterable);
-	((type == 'arguments' || type == 'collection' || type == 'array' || type == 'elements') ? Array : Object).each(iterable, fn, bind);
-};
-
-this.$empty = function(){};
-
-this.$extend = function(original, extended){
-	return Object.append(original, extended);
-};
-
-this.$H = function(object){
-	return new Hash(object);
-};
-
-this.$merge = function(){
-	var args = Array.slice(arguments);
-	args.unshift({});
-	return Object.merge.apply(null, args);
-};
-
-this.$lambda = Function.from;
-this.$mixin = Object.merge;
-this.$random = Number.random;
-this.$splat = Array.from;
-this.$time = Date.now;
-
-this.$type = function(object){
-	var type = typeOf(object);
-	if (type == 'elements') return 'array';
-	return (type == 'null') ? false : type;
-};
-
-this.$unlink = function(object){
-	switch (typeOf(object)){
-		case 'object': return Object.clone(object);
-		case 'array': return Array.clone(object);
-		case 'hash': return new Hash(object);
-		default: return object;
-	}
-};
-
-//</1.2compat>
-
-})();
-
-
-/*
----
-
-name: Array
-
-description: Contains Array Prototypes like each, contains, and erase.
-
-license: MIT-style license.
-
-requires: Type
-
-provides: Array
-
-...
-*/
-
-Array.implement({
-
-	/*<!ES5>*/
-	every: function(fn, bind){
-		for (var i = 0, l = this.length >>> 0; i < l; i++){
-			if ((i in this) && !fn.call(bind, this[i], i, this)) return false;
-		}
-		return true;
-	},
-
-	filter: function(fn, bind){
-		var results = [];
-		for (var value, i = 0, l = this.length >>> 0; i < l; i++) if (i in this){
-			value = this[i];
-			if (fn.call(bind, value, i, this)) results.push(value);
-		}
-		return results;
-	},
-
-	indexOf: function(item, from){
-		var length = this.length >>> 0;
-		for (var i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++){
-			if (this[i] === item) return i;
-		}
-		return -1;
-	},
-
-	map: function(fn, bind){
-		var length = this.length >>> 0, results = Array(length);
-		for (var i = 0; i < length; i++){
-			if (i in this) results[i] = fn.call(bind, this[i], i, this);
-		}
-		return results;
-	},
-
-	some: function(fn, bind){
-		for (var i = 0, l = this.length >>> 0; i < l; i++){
-			if ((i in this) && fn.call(bind, this[i], i, this)) return true;
-		}
-		return false;
-	},
-	/*</!ES5>*/
-
-	clean: function(){
-		return this.filter(function(item){
-			return item != null;
-		});
-	},
-
-	invoke: function(methodName){
-		var args = Array.slice(arguments, 1);
-		return this.map(function(item){
-			return item[methodName].apply(item, args);
-		});
-	},
-
-	associate: function(keys){
-		var obj = {}, length = Math.min(this.length, keys.length);
-		for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
-		return obj;
-	},
-
-	link: function(object){
-		var result = {};
-		for (var i = 0, l = this.length; i < l; i++){
-			for (var key in object){
-				if (object[key](this[i])){
-					result[key] = this[i];
-					delete object[key];
-					break;
-				}
-			}
-		}
-		return result;
-	},
-
-	contains: function(item, from){
-		return this.indexOf(item, from) != -1;
-	},
-
-	append: function(array){
-		this.push.apply(this, array);
-		return this;
-	},
-
-	getLast: function(){
-		return (this.length) ? this[this.length - 1] : null;
-	},
-
-	getRandom: function(){
-		return (this.length) ? this[Number.random(0, this.length - 1)] : null;
-	},
-
-	include: function(item){
-		if (!this.contains(item)) this.push(item);
-		return this;
-	},
-
-	combine: function(array){
-		for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
-		return this;
-	},
-
-	erase: function(item){
-		for (var i = this.length; i--;){
-			if (this[i] === item) this.splice(i, 1);
-		}
-		return this;
-	},
-
-	empty: function(){
-		this.length = 0;
-		return this;
-	},
-
-	flatten: function(){
-		var array = [];
-		for (var i = 0, l = this.length; i < l; i++){
-			var type = typeOf(this[i]);
-			if (type == 'null') continue;
-			array = array.concat((type == 'array' || type == 'collection' || type == 'arguments' || instanceOf(this[i], Array)) ? Array.flatten(this[i]) : this[i]);
-		}
-		return array;
-	},
-
-	pick: function(){
-		for (var i = 0, l = this.length; i < l; i++){
-			if (this[i] != null) return this[i];
-		}
-		return null;
-	},
-
-	hexToRgb: function(array){
-		if (this.length != 3) return null;
-		var rgb = this.map(function(value){
-			if (value.length == 1) value += value;
-			return value.toInt(16);
-		});
-		return (array) ? rgb : 'rgb(' + rgb + ')';
-	},
-
-	rgbToHex: function(array){
-		if (this.length < 3) return null;
-		if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
-		var hex = [];
-		for (var i = 0; i < 3; i++){
-			var bit = (this[i] - 0).toString(16);
-			hex.push((bit.length == 1) ? '0' + bit : bit);
-		}
-		return (array) ? hex : '#' + hex.join('');
-	}
-
-});
-
-//<1.2compat>
-
-Array.alias('extend', 'append');
-
-var $pick = function(){
-	return Array.from(arguments).pick();
-};
-
-//</1.2compat>
-
-
-/*
----
-
-name: String
-
-description: Contains String Prototypes like camelCase, capitalize, test, and toInt.
-
-license: MIT-style license.
-
-requires: Type
-
-provides: String
-
-...
-*/
-
-String.implement({
-
-	test: function(regex, params){
-		return ((typeOf(regex) == 'regexp') ? regex : new RegExp('' + regex, params)).test(this);
-	},
-
-	contains: function(string, separator){
-		return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : String(this).indexOf(string) > -1;
-	},
-
-	trim: function(){
-		return String(this).replace(/^\s+|\s+$/g, '');
-	},
-
-	clean: function(){
-		return String(this).replace(/\s+/g, ' ').trim();
-	},
-
-	camelCase: function(){
-		return String(this).replace(/-\D/g, function(match){
-			return match.charAt(1).toUpperCase();
-		});
-	},
-
-	hyphenate: function(){
-		return String(this).replace(/[A-Z]/g, function(match){
-			return ('-' + match.charAt(0).toLowerCase());
-		});
-	},
-
-	capitalize: function(){
-		return String(this).replace(/\b[a-z]/g, function(match){
-			return match.toUpperCase();
-		});
-	},
-
-	escapeRegExp: function(){
-		return String(this).replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
-	},
-
-	toInt: function(base){
-		return parseInt(this, base || 10);
-	},
-
-	toFloat: function(){
-		return parseFloat(this);
-	},
-
-	hexToRgb: function(array){
-		var hex = String(this).match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
-		return (hex) ? hex.slice(1).hexToRgb(array) : null;
-	},
-
-	rgbToHex: function(array){
-		var rgb = String(this).match(/\d{1,3}/g);
-		return (rgb) ? rgb.rgbToHex(array) : null;
-	},
-
-	substitute: function(object, regexp){
-		return String(this).replace(regexp || (/\\?\{([^{}]+)\}/g), function(match, name){
-			if (match.charAt(0) == '\\') return match.slice(1);
-			return (object[name] != null) ? object[name] : '';
-		});
-	}
-
-});
-
-
-/*
----
-
-name: Number
-
-description: Contains Number Prototypes like limit, round, times, and ceil.
-
-license: MIT-style license.
-
-requires: Type
-
-provides: Number
-
-...
-*/
-
-Number.implement({
-
-	limit: function(min, max){
-		return Math.min(max, Math.max(min, this));
-	},
-
-	round: function(precision){
-		precision = Math.pow(10, precision || 0).toFixed(precision < 0 ? -precision : 0);
-		return Math.round(this * precision) / precision;
-	},
-
-	times: function(fn, bind){
-		for (var i = 0; i < this; i++) fn.call(bind, i, this);
-	},
-
-	toFloat: function(){
-		return parseFloat(this);
-	},
-
-	toInt: function(base){
-		return parseInt(this, base || 10);
-	}
-
-});
-
-Number.alias('each', 'times');
-
-(function(math){
-	var methods = {};
-	math.each(function(name){
-		if (!Number[name]) methods[name] = function(){
-			return Math[name].apply(null, [this].concat(Array.from(arguments)));
-		};
-	});
-	Number.implement(methods);
-})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
-
-
-/*
----
-
-name: Function
-
-description: Contains Function Prototypes like create, bind, pass, and delay.
-
-license: MIT-style license.
-
-requires: Type
-
-provides: Function
-
-...
-*/
-
-Function.extend({
-
-	attempt: function(){
-		for (var i = 0, l = arguments.length; i < l; i++){
-			try {
-				return arguments[i]();
-			} catch (e){}
-		}
-		return null;
-	}
-
-});
-
-Function.implement({
-
-	attempt: function(args, bind){
-		try {
-			return this.apply(bind, Array.from(args));
-		} catch (e){}
-
-		return null;
-	},
-
-	/*<!ES5-bind>*/
-	bind: function(that){
-		var self = this,
-			args = arguments.length > 1 ? Array.slice(arguments, 1) : null,
-			F = function(){};
-
-		var bound = function(){
-			var context = that, length = arguments.length;
-			if (this instanceof bound){
-				F.prototype = self.prototype;
-				context = new F;
-			}
-			var result = (!args && !length)
-				? self.call(context)
-				: self.apply(context, args && length ? args.concat(Array.slice(arguments)) : args || arguments);
-			return context == that ? result : context;
-		};
-		return bound;
-	},
-	/*</!ES5-bind>*/
-
-	pass: function(args, bind){
-		var self = this;
-		if (args != null) args = Array.from(args);
-		return function(){
-			return self.apply(bind, args || arguments);
-		};
-	},
-
-	delay: function(delay, bind, args){
-		return setTimeout(this.pass((args == null ? [] : args), bind), delay);
-	},
-
-	periodical: function(periodical, bind, args){
-		return setInterval(this.pass((args == null ? [] : args), bind), periodical);
-	}
-
-});
-
-//<1.2compat>
-
-delete Function.prototype.bind;
-
-Function.implement({
-
-	create: function(options){
-		var self = this;
-		options = options || {};
-		return function(event){
-			var args = options.arguments;
-			args = (args != null) ? Array.from(args) : Array.slice(arguments, (options.event) ? 1 : 0);
-			if (options.event) args = [event || window.event].extend(args);
-			var returns = function(){
-				return self.apply(options.bind || null, args);
-			};
-			if (options.delay) return setTimeout(returns, options.delay);
-			if (options.periodical) return setInterval(returns, options.periodical);
-			if (options.attempt) return Function.attempt(returns);
-			return returns();
-		};
-	},
-
-	bind: function(bind, args){
-		var self = this;
-		if (args != null) args = Array.from(args);
-		return function(){
-			return self.apply(bind, args || arguments);
-		};
-	},
-
-	bindWithEvent: function(bind, args){
-		var self = this;
-		if (args != null) args = Array.from(args);
-		return function(event){
-			return self.apply(bind, (args == null) ? arguments : [event].concat(args));
-		};
-	},
-
-	run: function(args, bind){
-		return this.apply(bind, Array.from(args));
-	}
-
-});
-
-if (Object.create == Function.prototype.create) Object.create = null;
-
-var $try = Function.attempt;
-
-//</1.2compat>
-
-
-/*
----
-
-name: Object
-
-description: Object generic methods
-
-license: MIT-style license.
-
-requires: Type
-
-provides: [Object, Hash]
-
-...
-*/
-
-(function(){
-
-var hasOwnProperty = Object.prototype.hasOwnProperty;
-
-Object.extend({
-
-	subset: function(object, keys){
-		var results = {};
-		for (var i = 0, l = keys.length; i < l; i++){
-			var k = keys[i];
-			if (k in object) results[k] = object[k];
-		}
-		return results;
-	},
-
-	map: function(object, fn, bind){
-		var results = {};
-		for (var key in object){
-			if (hasOwnProperty.call(object, key)) results[key] = fn.call(bind, object[key], key, object);
-		}
-		return results;
-	},
-
-	filter: function(object, fn, bind){
-		var results = {};
-		for (var key in object){
-			var value = object[key];
-			if (hasOwnProperty.call(object, key) && fn.call(bind, value, key, object)) results[key] = value;
-		}
-		return results;
-	},
-
-	every: function(object, fn, bind){
-		for (var key in object){
-			if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false;
-		}
-		return true;
-	},
-
-	some: function(object, fn, bind){
-		for (var key in object){
-			if (hasOwnProperty.call(object, key) && fn.call(bind, object[key], key)) return true;
-		}
-		return false;
-	},
-
-	keys: function(object){
-		var keys = [];
-		for (var key in object){
-			if (hasOwnProperty.call(object, key)) keys.push(key);
-		}
-		return keys;
-	},
-
-	values: function(object){
-		var values = [];
-		for (var key in object){
-			if (hasOwnProperty.call(object, key)) values.push(object[key]);
-		}
-		return values;
-	},
-
-	getLength: function(object){
-		return Object.keys(object).length;
-	},
-
-	keyOf: function(object, value){
-		for (var key in object){
-			if (hasOwnProperty.call(object, key) && object[key] === value) return key;
-		}
-		return null;
-	},
-
-	contains: function(object, value){
-		return Object.keyOf(object, value) != null;
-	},
-
-	toQueryString: function(object, base){
-		var queryString = [];
-
-		Object.each(object, function(value, key){
-			if (base) key = base + '[' + key + ']';
-			var result;
-			switch (typeOf(value)){
-				case 'object': result = Object.toQueryString(value, key); break;
-				case 'array':
-					var qs = {};
-					value.each(function(val, i){
-						qs[i] = val;
-					});
-					result = Object.toQueryString(qs, key);
-				break;
-				default: result = key + '=' + encodeURIComponent(value);
-			}
-			if (value != null) queryString.push(result);
-		});
-
-		return queryString.join('&');
-	}
-
-});
-
-})();
-
-//<1.2compat>
-
-Hash.implement({
-
-	has: Object.prototype.hasOwnProperty,
-
-	keyOf: function(value){
-		return Object.keyOf(this, value);
-	},
-
-	hasValue: function(value){
-		return Object.contains(this, value);
-	},
-
-	extend: function(properties){
-		Hash.each(properties || {}, function(value, key){
-			Hash.set(this, key, value);
-		}, this);
-		return this;
-	},
-
-	combine: function(properties){
-		Hash.each(properties || {}, function(value, key){
-			Hash.include(this, key, value);
-		}, this);
-		return this;
-	},
-
-	erase: function(key){
-		if (this.hasOwnProperty(key)) delete this[key];
-		return this;
-	},
-
-	get: function(key){
-		return (this.hasOwnProperty(key)) ? this[key] : null;
-	},
-
-	set: function(key, value){
-		if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
-		return this;
-	},
-
-	empty: function(){
-		Hash.each(this, function(value, key){
-			delete this[key];
-		}, this);
-		return this;
-	},
-
-	include: function(key, value){
-		if (this[key] == null) this[key] = value;
-		return this;
-	},
-
-	map: function(fn, bind){
-		return new Hash(Object.map(this, fn, bind));
-	},
-
-	filter: function(fn, bind){
-		return new Hash(Object.filter(this, fn, bind));
-	},
-
-	every: function(fn, bind){
-		return Object.every(this, fn, bind);
-	},
-
-	some: function(fn, bind){
-		return Object.some(this, fn, bind);
-	},
-
-	getKeys: function(){
-		return Object.keys(this);
-	},
-
-	getValues: function(){
-		return Object.values(this);
-	},
-
-	toQueryString: function(base){
-		return Object.toQueryString(this, base);
-	}
-
-});
-
-Hash.extend = Object.append;
-
-Hash.alias({indexOf: 'keyOf', contains: 'hasValue'});
-
-//</1.2compat>
-
-
-/*
----
-
-name: Browser
-
-description: The Browser Object. Contains Browser initialization, Window and Document, and the Browser Hash.
-
-license: MIT-style license.
-
-requires: [Array, Function, Number, String]
-
-provides: [Browser, Window, Document]
-
-...
-*/
-
-(function(){
-
-var document = this.document;
-var window = document.window = this;
-
-var ua = navigator.userAgent.toLowerCase(),
-	platform = navigator.platform.toLowerCase(),
-	UA = ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0],
-	mode = UA[1] == 'ie' && document.documentMode;
-
-var Browser = this.Browser = {
-
-	extend: Function.prototype.extend,
-
-	name: (UA[1] == 'version') ? UA[3] : UA[1],
-
-	version: mode || parseFloat((UA[1] == 'opera' && UA[4]) ? UA[4] : UA[2]),
-
-	Platform: {
-		name: ua.match(/ip(?:ad|od|hone)/) ? 'ios' : (ua.match(/(?:webos|android)/) || platform.match(/mac|win|linux/) || ['other'])[0]
-	},
-
-	Features: {
-		xpath: !!(document.evaluate),
-		air: !!(window.runtime),
-		query: !!(document.querySelector),
-		json: !!(window.JSON)
-	},
-
-	Plugins: {}
-
-};
-
-Browser[Browser.name] = true;
-Browser[Browser.name + parseInt(Browser.version, 10)] = true;
-Browser.Platform[Browser.Platform.name] = true;
-
-// Request
-
-Browser.Request = (function(){
-
-	var XMLHTTP = function(){
-		return new XMLHttpRequest();
-	};
-
-	var MSXML2 = function(){
-		return new ActiveXObject('MSXML2.XMLHTTP');
-	};
-
-	var MSXML = function(){
-		return new ActiveXObject('Microsoft.XMLHTTP');
-	};
-
-	return Function.attempt(function(){
-		XMLHTTP();
-		return XMLHTTP;
-	}, function(){
-		MSXML2();
-		return MSXML2;
-	}, function(){
-		MSXML();
-		return MSXML;
-	});
-
-})();
-
-Browser.Features.xhr = !!(Browser.Request);
-
-// Flash detection
-
-var version = (Function.attempt(function(){
-	return navigator.plugins['Shockwave Flash'].description;
-}, function(){
-	return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
-}) || '0 r0').match(/\d+/g);
-
-Browser.Plugins.Flash = {
-	version: Number(version[0] || '0.' + version[1]) || 0,
-	build: Number(version[2]) || 0
-};
-
-// String scripts
-
-Browser.exec = function(text){
-	if (!text) return text;
-	if (window.execScript){
-		window.execScript(text);
-	} else {
-		var script = document.createElement('script');
-		script.setAttribute('type', 'text/javascript');
-		script.text = text;
-		document.head.appendChild(script);
-		document.head.removeChild(script);
-	}
-	return text;
-};
-
-String.implement('stripScripts', function(exec){
-	var scripts = '';
-	var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(all, code){
-		scripts += code + '\n';
-		return '';
-	});
-	if (exec === true) Browser.exec(scripts);
-	else if (typeOf(exec) == 'function') exec(scripts, text);
-	return text;
-});
-
-// Window, Document
-
-Browser.extend({
-	Document: this.Document,
-	Window: this.Window,
-	Element: this.Element,
-	Event: this.Event
-});
-
-this.Window = this.$constructor = new Type('Window', function(){});
-
-this.$family = Function.from('window').hide();
-
-Window.mirror(function(name, method){
-	window[name] = method;
-});
-
-this.Document = document.$constructor = new Type('Document', function(){});
-
-document.$family = Function.from('document').hide();
-
-Document.mirror(function(name, method){
-	document[name] = method;
-});
-
-document.html = document.documentElement;
-if (!document.head) document.head = document.getElementsByTagName('head')[0];
-
-if (document.execCommand) try {
-	document.execCommand("BackgroundImageCache", false, true);
-} catch (e){}
-
-/*<ltIE9>*/
-if (this.attachEvent && !this.addEventListener){
-	var unloadEvent = function(){
-		this.detachEvent('onunload', unloadEvent);
-		document.head = document.html = document.window = null;
-	};
-	this.attachEvent('onunload', unloadEvent);
-}
-
-// IE fails on collections and <select>.options (refers to <select>)
-var arrayFrom = Array.from;
-try {
-	arrayFrom(document.html.childNodes);
-} catch(e){
-	Array.from = function(item){
-		if (typeof item != 'string' && Type.isEnumerable(item) && typeOf(item) != 'array'){
-			var i = item.length, array = new Array(i);
-			while (i--) array[i] = item[i];
-			return array;
-		}
-		return arrayFrom(item);
-	};
-
-	var prototype = Array.prototype,
-		slice = prototype.slice;
-	['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice'].each(function(name){
-		var method = prototype[name];
-		Array[name] = function(item){
-			return method.apply(Array.from(item), slice.call(arguments, 1));
-		};
-	});
-}
-/*</ltIE9>*/
-
-//<1.2compat>
-
-if (Browser.Platform.ios) Browser.Platform.ipod = true;
-
-Browser.Engine = {};
-
-var setEngine = function(name, version){
-	Browser.Engine.name = name;
-	Browser.Engine[name + version] = true;
-	Browser.Engine.version = version;
-};
-
-if (Browser.ie){
-	Browser.Engine.trident = true;
-
-	switch (Browser.version){
-		case 6: setEngine('trident', 4); break;
-		case 7: setEngine('trident', 5); break;
-		case 8: setEngine('trident', 6);
-	}
-}
-
-if (Browser.firefox){
-	Browser.Engine.gecko = true;
-
-	if (Browser.version >= 3) setEngine('gecko', 19);
-	else setEngine('gecko', 18);
-}
-
-if (Browser.safari || Browser.chrome){
-	Browser.Engine.webkit = true;
-
-	switch (Browser.version){
-		case 2: setEngine('webkit', 419); break;
-		case 3: setEngine('webkit', 420); break;
-		case 4: setEngine('webkit', 525);
-	}
-}
-
-if (Browser.opera){
-	Browser.Engine.presto = true;
-
-	if (Browser.version >= 9.6) setEngine('presto', 960);
-	else if (Browser.version >= 9.5) setEngine('presto', 950);
-	else setEngine('presto', 925);
-}
-
-if (Browser.name == 'unknown'){
-	switch ((ua.match(/(?:webkit|khtml|gecko)/) || [])[0]){
-		case 'webkit':
-		case 'khtml':
-			Browser.Engine.webkit = true;
-		break;
-		case 'gecko':
-			Browser.Engine.gecko = true;
-	}
-}
-
-this.$exec = Browser.exec;
-
-//</1.2compat>
-
-})();
-
-
-/*
----
-
-name: Event
-
-description: Contains the Event Type, to make the event object cross-browser.
-
-license: MIT-style license.
-
-requires: [Window, Document, Array, Function, String, Object]
-
-provides: Event
-
-...
-*/
-
-(function() {
-
-var _keys = {};
-
-var DOMEvent = this.DOMEvent = new Type('DOMEvent', function(event, win){
-	if (!win) win = window;
-	event = event || win.event;
-	if (event.$extended) return event;
-	this.event = event;
-	this.$extended = true;
-	this.shift = event.shiftKey;
-	this.control = event.ctrlKey;
-	this.alt = event.altKey;
-	this.meta = event.metaKey;
-	var type = this.type = event.type;
-	var target = event.target || event.srcElement;
-	while (target && target.nodeType == 3) target = target.parentNode;
-	this.target = document.id(target);
-
-	if (type.indexOf('key') == 0){
-		var code = this.code = (event.which || event.keyCode);
-		this.key = _keys[code]/*<1.3compat>*/ || Object.keyOf(Event.Keys, code)/*</1.3compat>*/;
-		if (type == 'keydown'){
-			if (code > 111 && code < 124) this.key = 'f' + (code - 111);
-			else if (code > 95 && code < 106) this.key = code - 96;
-		}
-		if (this.key == null) this.key = String.fromCharCode(code).toLowerCase();
-	} else if (type == 'click' || type == 'dblclick' || type == 'contextmenu' || type == 'DOMMouseScroll' || type.indexOf('mouse') == 0){
-		var doc = win.document;
-		doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
-		this.page = {
-			x: (event.pageX != null) ? event.pageX : event.clientX + doc.scrollLeft,
-			y: (event.pageY != null) ? event.pageY : event.clientY + doc.scrollTop
-		};
-		this.client = {
-			x: (event.pageX != null) ? event.pageX - win.pageXOffset : event.clientX,
-			y: (event.pageY != null) ? event.pageY - win.pageYOffset : event.clientY
-		};
-		if (type == 'DOMMouseScroll' || type == 'mousewheel')
-			this.wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
-
-		this.rightClick = (event.which == 3 || event.button == 2);
-		if (type == 'mouseover' || type == 'mouseout'){
-			var related = event.relatedTarget || event[(type == 'mouseover' ? 'from' : 'to') + 'Element'];
-			while (related && related.nodeType == 3) related = related.parentNode;
-			this.relatedTarget = document.id(related);
-		}
-	} else if (type.indexOf('touch') == 0 || type.indexOf('gesture') == 0){
-		this.rotation = event.rotation;
-		this.scale = event.scale;
-		this.targetTouches = event.targetTouches;
-		this.changedTouches = event.changedTouches;
-		var touches = this.touches = event.touches;
-		if (touches && touches[0]){
-			var touch = touches[0];
-			this.page = {x: touch.pageX, y: touch.pageY};
-			this.client = {x: touch.clientX, y: touch.clientY};
-		}
-	}
-
-	if (!this.client) this.client = {};
-	if (!this.page) this.page = {};
-});
-
-DOMEvent.implement({
-
-	stop: function(){
-		return this.preventDefault().stopPropagation();
-	},
-
-	stopPropagation: function(){
-		if (this.event.stopPropagation) this.event.stopPropagation();
-		else this.event.cancelBubble = true;
-		return this;
-	},
-
-	preventDefault: function(){
-		if (this.event.preventDefault) this.event.preventDefault();
-		else this.event.returnValue = false;
-		return this;
-	}
-
-});
-
-DOMEvent.defineKey = function(code, key){
-	_keys[code] = key;
-	return this;
-};
-
-DOMEvent.defineKeys = DOMEvent.defineKey.overloadSetter(true);
-
-DOMEvent.defineKeys({
-	'38': 'up', '40': 'down', '37': 'left', '39': 'right',
-	'27': 'esc', '32': 'space', '8': 'backspace', '9': 'tab',
-	'46': 'delete', '13': 'enter'
-});
-
-})();
-
-/*<1.3compat>*/
-var Event = DOMEvent;
-Event.Keys = {};
-/*</1.3compat>*/
-
-/*<1.2compat>*/
-
-Event.Keys = new Hash(Event.Keys);
-
-/*</1.2compat>*/
-
-
-/*
----
-
-name: Class
-
-description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
-
-license: MIT-style license.
-
-requires: [Array, String, Function, Number]
-
-provides: Class
-
-...
-*/
-
-(function(){
-
-var Class = this.Class = new Type('Class', function(params){
-	if (instanceOf(params, Function)) params = {initialize: params};
-
-	var newClass = function(){
-		reset(this);
-		if (newClass.$prototyping) return this;
-		this.$caller = null;
-		var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
-		this.$caller = this.caller = null;
-		return value;
-	}.extend(this).implement(params);
-
-	newClass.$constructor = Class;
-	newClass.prototype.$constructor = newClass;
-	newClass.prototype.parent = parent;
-
-	return newClass;
-});
-
-var parent = function(){
-	if (!this.$caller) throw new Error('The method "parent" cannot be called.');
-	var name = this.$caller.$name,
-		parent = this.$caller.$owner.parent,
-		previous = (parent) ? parent.prototype[name] : null;
-	if (!previous) throw new Error('The method "' + name + '" has no parent.');
-	return previous.apply(this, arguments);
-};
-
-var reset = function(object){
-	for (var key in object){
-		var value = object[key];
-		switch (typeOf(value)){
-			case 'object':
-				var F = function(){};
-				F.prototype = value;
-				object[key] = reset(new F);
-			break;
-			case 'array': object[key] = value.clone(); break;
-		}
-	}
-	return object;
-};
-
-var wrap = function(self, key, method){
-	if (method.$origin) method = method.$origin;
-	var wrapper = function(){
-		if (method.$protected && this.$caller == null) throw new Error('The method "' + key + '" cannot be called.');
-		var caller = this.caller, current = this.$caller;
-		this.caller = current; this.$caller = wrapper;
-		var result = method.apply(this, arguments);
-		this.$caller = current; this.caller = caller;
-		return result;
-	}.extend({$owner: self, $origin: method, $name: key});
-	return wrapper;
-};
-
-var implement = function(key, value, retain){
-	if (Class.Mutators.hasOwnProperty(key)){
-		value = Class.Mutators[key].call(this, value);
-		if (value == null) return this;
-	}
-
-	if (typeOf(value) == 'function'){
-		if (value.$hidden) return this;
-		this.prototype[key] = (retain) ? value : wrap(this, key, value);
-	} else {
-		Object.merge(this.prototype, key, value);
-	}
-
-	return this;
-};
-
-var getInstance = function(klass){
-	klass.$prototyping = true;
-	var proto = new klass;
-	delete klass.$prototyping;
-	return proto;
-};
-
-Class.implement('implement', implement.overloadSetter());
-
-Class.Mutators = {
-
-	Extends: function(parent){
-		this.parent = parent;
-		this.prototype = getInstance(parent);
-	},
-
-	Implements: function(items){
-		Array.from(items).each(function(item){
-			var instance = new item;
-			for (var key in instance) implement.call(this, key, instance[key], true);
-		}, this);
-	}
-};
-
-})();
-
-
-/*
----
-
-name: Class.Extras
-
-description: Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
-
-license: MIT-style license.
-
-requires: Class
-
-provides: [Class.Extras, Chain, Events, Options]
-
-...
-*/
-
-(function(){
-
-this.Chain = new Class({
-
-	$chain: [],
-
-	chain: function(){
-		this.$chain.append(Array.flatten(arguments));
-		return this;
-	},
-
-	callChain: function(){
-		return (this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
-	},
-
-	clearChain: function(){
-		this.$chain.empty();
-		return this;
-	}
-
-});
-
-var removeOn = function(string){
-	return string.replace(/^on([A-Z])/, function(full, first){
-		return first.toLowerCase();
-	});
-};
-
-this.Events = new Class({
-
-	$events: {},
-
-	addEvent: function(type, fn, internal){
-		type = removeOn(type);
-
-		/*<1.2compat>*/
-		if (fn == $empty) return this;
-		/*</1.2compat>*/
-
-		this.$events[type] = (this.$events[type] || []).include(fn);
-		if (internal) fn.internal = true;
-		return this;
-	},
-
-	addEvents: function(events){
-		for (var type in events) this.addEvent(type, events[type]);
-		return this;
-	},
-
-	fireEvent: function(type, args, delay){
-		type = removeOn(type);
-		var events = this.$events[type];
-		if (!events) return this;
-		args = Array.from(args);
-		events.each(function(fn){
-			if (delay) fn.delay(delay, this, args);
-			else fn.apply(this, args);
-		}, this);
-		return this;
-	},
-
-	removeEvent: function(type, fn){
-		type = removeOn(type);
-		var events = this.$events[type];
-		if (events && !fn.internal){
-			var index =  events.indexOf(fn);
-			if (index != -1) delete events[index];
-		}
-		return this;
-	},
-
-	removeEvents: function(events){
-		var type;
-		if (typeOf(events) == 'object'){
-			for (type in events) this.removeEvent(type, events[type]);
-			return this;
-		}
-		if (events) events = removeOn(events);
-		for (type in this.$events){
-			if (events && events != type) continue;
-			var fns = this.$events[type];
-			for (var i = fns.length; i--;) if (i in fns){
-				this.removeEvent(type, fns[i]);
-			}
-		}
-		return this;
-	}
-
-});
-
-this.Options = new Class({
-
-	setOptions: function(){
-		var options = this.options = Object.merge.apply(null, [{}, this.options].append(arguments));
-		if (this.addEvent) for (var option in options){
-			if (typeOf(options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
-			this.addEvent(option, options[option]);
-			delete options[option];
-		}
-		return this;
-	}
-
-});
-
-})();
-
-
-/*
----
-name: Slick.Parser
-description: Standalone CSS3 Selector parser
-provides: Slick.Parser
-...
-*/
-
-;(function(){
-
-var parsed,
-	separatorIndex,
-	combinatorIndex,
-	reversed,
-	cache = {},
-	reverseCache = {},
-	reUnescape = /\\/g;
-
-var parse = function(expression, isReversed){
-	if (expression == null) return null;
-	if (expression.Slick === true) return expression;
-	expression = ('' + expression).replace(/^\s+|\s+$/g, '');
-	reversed = !!isReversed;
-	var currentCache = (reversed) ? reverseCache : cache;
-	if (currentCache[expression]) return currentCache[expression];
-	parsed = {
-		Slick: true,
-		expressions: [],
-		raw: expression,
-		reverse: function(){
-			return parse(this.raw, true);
-		}
-	};
-	separatorIndex = -1;
-	while (expression != (expression = expression.replace(regexp, parser)));
-	parsed.length = parsed.expressions.length;
-	return currentCache[parsed.raw] = (reversed) ? reverse(parsed) : parsed;
-};
-
-var reverseCombinator = function(combinator){
-	if (combinator === '!') return ' ';
-	else if (combinator === ' ') return '!';
-	else if ((/^!/).test(combinator)) return combinator.replace(/^!/, '');
-	else return '!' + combinator;
-};
-
-var reverse = function(expression){
-	var expressions = expression.expressions;
-	for (var i = 0; i < expressions.length; i++){
-		var exp = expressions[i];
-		var last = {parts: [], tag: '*', combinator: reverseCombinator(exp[0].combinator)};
-
-		for (var j = 0; j < exp.length; j++){
-			var cexp = exp[j];
-			if (!cexp.reverseCombinator) cexp.reverseCombinator = ' ';
-			cexp.combinator = cexp.reverseCombinator;
-			delete cexp.reverseCombinator;
-		}
-
-		exp.reverse().push(last);
-	}
-	return expression;
-};
-
-var escapeRegExp = function(string){// Credit: XRegExp 0.6.1 (c) 2007-2008 Steven Levithan <http://stevenlevithan.com/regex/xregexp/> MIT License
-	return string.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, function(match){
-		return '\\' + match;
-	});
-};
-
-var regexp = new RegExp(
-/*
-#!/usr/bin/env ruby
-puts "\t\t" + DATA.read.gsub(/\(\?x\)|\s+#.*$|\s+|\\$|\\n/,'')
-__END__
-	"(?x)^(?:\
-	  \\s* ( , ) \\s*               # Separator          \n\
-	| \\s* ( <combinator>+ ) \\s*   # Combinator         \n\
-	|      ( \\s+ )                 # CombinatorChildren \n\
-	|      ( <unicode>+ | \\* )     # Tag                \n\
-	| \\#  ( <unicode>+       )     # ID                 \n\
-	| \\.  ( <unicode>+       )     # ClassName          \n\
-	|                               # Attribute          \n\
-	\\[  \
-		\\s* (<unicode1>+)  (?:  \
-			\\s* ([*^$!~|]?=)  (?:  \
-				\\s* (?:\
-					([\"']?)(.*?)\\9 \
-				)\
-			)  \
-		)?  \\s*  \
-	\\](?!\\]) \n\
-	|   :+ ( <unicode>+ )(?:\
-	\\( (?:\
-		(?:([\"'])([^\\12]*)\\12)|((?:\\([^)]+\\)|[^()]*)+)\
-	) \\)\
-	)?\
-	)"
-*/
-	"^(?:\\s*(,)\\s*|\\s*(<combinator>+)\\s*|(\\s+)|(<unicode>+|\\*)|\\#(<unicode>+)|\\.(<unicode>+)|\\[\\s*(<unicode1>+)(?:\\s*([*^$!~|]?=)(?:\\s*(?:([\"']?)(.*?)\\9)))?\\s*\\](?!\\])|(:+)(<unicode>+)(?:\\((?:(?:([\"'])([^\\13]*)\\13)|((?:\\([^)]+\\)|[^()]*)+))\\))?)"
-	.replace(/<combinator>/, '[' + escapeRegExp(">+~`!@$%^&={}\\;</") + ']')
-	.replace(/<unicode>/g, '(?:[\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
-	.replace(/<unicode1>/g, '(?:[:\\w\\u00a1-\\uFFFF-]|\\\\[^\\s0-9a-f])')
-);
-
-function parser(
-	rawMatch,
-
-	separator,
-	combinator,
-	combinatorChildren,
-
-	tagName,
-	id,
-	className,
-
-	attributeKey,
-	attributeOperator,
-	attributeQuote,
-	attributeValue,
-
-	pseudoMarker,
-	pseudoClass,
-	pseudoQuote,
-	pseudoClassQuotedValue,
-	pseudoClassValue
-){
-	if (separator || separatorIndex === -1){
-		parsed.expressions[++separatorIndex] = [];
-		combinatorIndex = -1;
-		if (separator) return '';
-	}
-
-	if (combinator || combinatorChildren || combinatorIndex === -1){
-		combinator = combinator || ' ';
-		var currentSeparator = parsed.expressions[separatorIndex];
-		if (reversed && currentSeparator[combinatorIndex])
-			currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator);
-		currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*'};
-	}
-
-	var currentParsed = parsed.expressions[separatorIndex][combinatorIndex];
-
-	if (tagName){
-		currentParsed.tag = tagName.replace(reUnescape, '');
-
-	} else if (id){
-		currentParsed.id = id.replace(reUnescape, '');
-
-	} else if (className){
-		className = className.replace(reUnescape, '');
-
-		if (!currentParsed.classList) currentParsed.classList = [];
-		if (!currentParsed.classes) currentParsed.classes = [];
-		currentParsed.classList.push(className);
-		currentParsed.classes.push({
-			value: className,
-			regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)')
-		});
-
-	} else if (pseudoClass){
-		pseudoClassValue = pseudoClassValue || pseudoClassQuotedValue;
-		pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null;
-
-		if (!currentParsed.pseudos) currentParsed.pseudos = [];
-		currentParsed.pseudos.push({
-			key: pseudoClass.replace(reUnescape, ''),
-			value: pseudoClassValue,
-			type: pseudoMarker.length == 1 ? 'class' : 'element'
-		});
-
-	} else if (attributeKey){
-		attributeKey = attributeKey.replace(reUnescape, '');
-		attributeValue = (attributeValue || '').replace(reUnescape, '');
-
-		var test, regexp;
-
-		switch (attributeOperator){
-			case '^=' : regexp = new RegExp(       '^'+ escapeRegExp(attributeValue)            ); break;
-			case '$=' : regexp = new RegExp(            escapeRegExp(attributeValue) +'$'       ); break;
-			case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break;
-			case '|=' : regexp = new RegExp(       '^'+ escapeRegExp(attributeValue) +'(-|$)'   ); break;
-			case  '=' : test = function(value){
-				return attributeValue == value;
-			}; break;
-			case '*=' : test = function(value){
-				return value && value.indexOf(attributeValue) > -1;
-			}; break;
-			case '!=' : test = function(value){
-				return attributeValue != value;
-			}; break;
-			default   : test = function(value){
-				return !!value;
-			};
-		}
-
-		if (attributeValue == '' && (/^[*$^]=$/).test(attributeOperator)) test = function(){
-			return false;
-		};
-
-		if (!test) test = function(value){
-			return value && regexp.test(value);
-		};
-
-		if (!currentParsed.attributes) currentParsed.attributes = [];
-		currentParsed.attributes.push({
-			key: attributeKey,
-			operator: attributeOperator,
-			value: attributeValue,
-			test: test
-		});
-
-	}
-
-	return '';
-};
-
-// Slick NS
-
-var Slick = (this.Slick || {});
-
-Slick.parse = function(expression){
-	return parse(expression);
-};
-
-Slick.escapeRegExp = escapeRegExp;
-
-if (!this.Slick) this.Slick = Slick;
-
-}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
-
-
-/*
----
-name: Slick.Finder
-description: The new, superfast css selector engine.
-provides: Slick.Finder
-requires: Slick.Parser
-...
-*/
-
-;(function(){
-
-var local = {},
-	featuresCache = {},
-	toString = Object.prototype.toString;
-
-// Feature / Bug detection
-
-local.isNativeCode = function(fn){
-	return (/\{\s*\[native code\]\s*\}/).test('' + fn);
-};
-
-local.isXML = function(document){
-	return (!!document.xmlVersion) || (!!document.xml) || (toString.call(document) == '[object XMLDocument]') ||
-	(document.nodeType == 9 && document.documentElement.nodeName != 'HTML');
-};
-
-local.setDocument = function(document){
-
-	// convert elements / window arguments to document. if document cannot be extrapolated, the function returns.
-	var nodeType = document.nodeType;
-	if (nodeType == 9); // document
-	else if (nodeType) document = document.ownerDocument; // node
-	else if (document.navigator) document = document.document; // window
-	else return;
-
-	// check if it's the old document
-
-	if (this.document === document) return;
-	this.document = document;
-
-	// check if we have done feature detection on this document before
-
-	var root = document.documentElement,
-		rootUid = this.getUIDXML(root),
-		features = featuresCache[rootUid],
-		feature;
-
-	if (features){
-		for (feature in features){
-			this[feature] = features[feature];
-		}
-		return;
-	}
-
-	features = featuresCache[rootUid] = {};
-
-	features.root = root;
-	features.isXMLDocument = this.isXML(document);
-
-	features.brokenStarGEBTN
-	= features.starSelectsClosedQSA
-	= features.idGetsName
-	= features.brokenMixedCaseQSA
-	= features.brokenGEBCN
-	= features.brokenCheckedQSA
-	= features.brokenEmptyAttributeQSA
-	= features.isHTMLDocument
-	= features.nativeMatchesSelector
-	= false;
-
-	var starSelectsClosed, starSelectsComments,
-		brokenSecondClassNameGEBCN, cachedGetElementsByClassName,
-		brokenFormAttributeGetter;
-
-	var selected, id = 'slick_uniqueid';
-	var testNode = document.createElement('div');
-
-	var testRoot = document.body || document.getElementsByTagName('body')[0] || root;
-	testRoot.appendChild(testNode);
-
-	// on non-HTML documents innerHTML and getElementsById doesnt work properly
-	try {
-		testNode.innerHTML = '<a id="'+id+'"></a>';
-		features.isHTMLDocument = !!document.getElementById(id);
-	} catch(e){};
-
-	if (features.isHTMLDocument){
-
-		testNode.style.display = 'none';
-
-		// IE returns comment nodes for getElementsByTagName('*') for some documents
-		testNode.appendChild(document.createComment(''));
-		starSelectsComments = (testNode.getElementsByTagName('*').length > 1);
-
-		// IE returns closed nodes (EG:"</foo>") for getElementsByTagName('*') for some documents
-		try {
-			testNode.innerHTML = 'foo</foo>';
-			selected = testNode.getElementsByTagName('*');
-			starSelectsClosed = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
-		} catch(e){};
-
-		features.brokenStarGEBTN = starSelectsComments || starSelectsClosed;
-
-		// IE returns elements with the name instead of just id for getElementsById for some documents
-		try {
-			testNode.innerHTML = '<a name="'+ id +'"></a><b id="'+ id +'"></b>';
-			features.idGetsName = document.getElementById(id) === testNode.firstChild;
-		} catch(e){};
-
-		if (testNode.getElementsByClassName){
-
-			// Safari 3.2 getElementsByClassName caches results
-			try {
-				testNode.innerHTML = '<a class="f"></a><a class="b"></a>';
-				testNode.getElementsByClassName('b').length;
-				testNode.firstChild.className = 'b';
-				cachedGetElementsByClassName = (testNode.getElementsByClassName('b').length != 2);
-			} catch(e){};
-
-			// Opera 9.6 getElementsByClassName doesnt detects the class if its not the first one
-			try {
-				testNode.innerHTML = '<a class="a"></a><a class="f b a"></a>';
-				brokenSecondClassNameGEBCN = (testNode.getElementsByClassName('a').length != 2);
-			} catch(e){};
-
-			features.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN;
-		}
-
-		if (testNode.querySelectorAll){
-			// IE 8 returns closed nodes (EG:"</foo>") for querySelectorAll('*') for some documents
-			try {
-				testNode.innerHTML = 'foo</foo>';
-				selected = testNode.querySelectorAll('*');
-				features.starSelectsClosedQSA = (selected && !!selected.length && selected[0].nodeName.charAt(0) == '/');
-			} catch(e){};
-
-			// Safari 3.2 querySelectorAll doesnt work with mixedcase on quirksmode
-			try {
-				testNode.innerHTML = '<a class="MiX"></a>';
-				features.brokenMixedCaseQSA = !testNode.querySelectorAll('.MiX').length;
-			} catch(e){};
-
-			// Webkit and Opera dont return selected options on querySelectorAll
-			try {
-				testNode.innerHTML = '<select><option selected="selected">a</option></select>';
-				features.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0);
-			} catch(e){};
-
-			// IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll
-			try {
-				testNode.innerHTML = '<a class=""></a>';
-				features.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0);
-			} catch(e){};
-
-		}
-
-		// IE6-7, if a form has an input of id x, form.getAttribute(x) returns a reference to the input
-		try {
-			testNode.innerHTML = '<form action="s"><input id="action"/></form>';
-			brokenFormAttributeGetter = (testNode.firstChild.getAttribute('action') != 's');
-		} catch(e){};
-
-		// native matchesSelector function
-
-		features.nativeMatchesSelector = root.matchesSelector || /*root.msMatchesSelector ||*/ root.mozMatchesSelector || root.webkitMatchesSelector;
-		if (features.nativeMatchesSelector) try {
-			// if matchesSelector trows errors on incorrect sintaxes we can use it
-			features.nativeMatchesSelector.call(root, ':slick');
-			features.nativeMatchesSelector = null;
-		} catch(e){};
-
-	}
-
-	try {
-		root.slick_expando = 1;
-		delete root.slick_expando;
-		features.getUID = this.getUIDHTML;
-	} catch(e) {
-		features.getUID = this.getUIDXML;
-	}
-
-	testRoot.removeChild(testNode);
-	testNode = selected = testRoot = null;
-
-	// getAttribute
-
-	features.getAttribute = (features.isHTMLDocument && brokenFormAttributeGetter) ? function(node, name){
-		var method = this.attributeGetters[name];
-		if (method) return method.call(node);
-		var attributeNode = node.getAttributeNode(name);
-		return (attributeNode) ? attributeNode.nodeValue : null;
-	} : function(node, name){
-		var method = this.attributeGetters[name];
-		return (method) ? method.call(node) : node.getAttribute(name);
-	};
-
-	// hasAttribute
-
-	features.hasAttribute = (root && this.isNativeCode(root.hasAttribute)) ? function(node, attribute) {
-		return node.hasAttribute(attribute);
-	} : function(node, attribute) {
-		node = node.getAttributeNode(attribute);
-		return !!(node && (node.specified || node.nodeValue));
-	};
-
-	// contains
-	// FIXME: Add specs: local.contains should be different for xml and html documents?
-	var nativeRootContains = root && this.isNativeCode(root.contains),
-		nativeDocumentContains = document && this.isNativeCode(document.contains);
-
-	features.contains = (nativeRootContains && nativeDocumentContains) ? function(context, node){
-		return context.contains(node);
-	} : (nativeRootContains && !nativeDocumentContains) ? function(context, node){
-		// IE8 does not have .contains on document.
-		return context === node || ((context === document) ? document.documentElement : context).contains(node);
-	} : (root && root.compareDocumentPosition) ? function(context, node){
-		return context === node || !!(context.compareDocumentPosition(node) & 16);
-	} : function(context, node){
-		if (node) do {
-			if (node === context) return true;
-		} while ((node = node.parentNode));
-		return false;
-	};
-
-	// document order sorting
-	// credits to Sizzle (http://sizzlejs.com/)
-
-	features.documentSorter = (root.compareDocumentPosition) ? function(a, b){
-		if (!a.compareDocumentPosition || !b.compareDocumentPosition) return 0;
-		return a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
-	} : ('sourceIndex' in root) ? function(a, b){
-		if (!a.sourceIndex || !b.sourceIndex) return 0;
-		return a.sourceIndex - b.sourceIndex;
-	} : (document.createRange) ? function(a, b){
-		if (!a.ownerDocument || !b.ownerDocument) return 0;
-		var aRange = a.ownerDocument.createRange(), bRange = b.ownerDocument.createRange();
-		aRange.setStart(a, 0);
-		aRange.setEnd(a, 0);
-		bRange.setStart(b, 0);
-		bRange.setEnd(b, 0);
-		return aRange.compareBoundaryPoints(Range.START_TO_END, bRange);
-	} : null ;
-
-	root = null;
-
-	for (feature in features){
-		this[feature] = features[feature];
-	}
-};
-
-// Main Method
-
-var reSimpleSelector = /^([#.]?)((?:[\w-]+|\*))$/,
-	reEmptyAttribute = /\[.+[*$^]=(?:""|'')?\]/,
-	qsaFailExpCache = {};
-
-local.search = function(context, expression, append, first){
-
-	var found = this.found = (first) ? null : (append || []);
-
-	if (!context) return found;
-	else if (context.navigator) context = context.document; // Convert the node from a window to a document
-	else if (!context.nodeType) return found;
-
-	// setup
-
-	var parsed, i,
-		uniques = this.uniques = {},
-		hasOthers = !!(append && append.length),
-		contextIsDocument = (context.nodeType == 9);
-
-	if (this.document !== (contextIsDocument ? context : context.ownerDocument)) this.setDocument(context);
-
-	// avoid duplicating items already in the append array
-	if (hasOthers) for (i = found.length; i--;) uniques[this.getUID(found[i])] = true;
-
-	// expression checks
-
-	if (typeof expression == 'string'){ // expression is a string
-
-		/*<simple-selectors-override>*/
-		var simpleSelector = expression.match(reSimpleSelector);
-		simpleSelectors: if (simpleSelector) {
-
-			var symbol = simpleSelector[1],
-				name = simpleSelector[2],
-				node, nodes;
-
-			if (!symbol){
-
-				if (name == '*' && this.brokenStarGEBTN) break simpleSelectors;
-				nodes = context.getElementsByTagName(name);
-				if (first) return nodes[0] || null;
-				for (i = 0; node = nodes[i++];){
-					if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
-				}
-
-			} else if (symbol == '#'){
-
-				if (!this.isHTMLDocument || !contextIsDocument) break simpleSelectors;
-				node = context.getElementById(name);
-				if (!node) return found;
-				if (this.idGetsName && node.getAttributeNode('id').nodeValue != name) break simpleSelectors;
-				if (first) return node || null;
-				if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
-
-			} else if (symbol == '.'){
-
-				if (!this.isHTMLDocument || ((!context.getElementsByClassName || this.brokenGEBCN) && context.querySelectorAll)) break simpleSelectors;
-				if (context.getElementsByClassName && !this.brokenGEBCN){
-					nodes = context.getElementsByClassName(name);
-					if (first) return nodes[0] || null;
-					for (i = 0; node = nodes[i++];){
-						if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
-					}
-				} else {
-					var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(name) +'(\\s|$)');
-					nodes = context.getElementsByTagName('*');
-					for (i = 0; node = nodes[i++];){
-						className = node.className;
-						if (!(className && matchClass.test(className))) continue;
-						if (first) return node;
-						if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
-					}
-				}
-
-			}
-
-			if (hasOthers) this.sort(found);
-			return (first) ? null : found;
-
-		}
-		/*</simple-selectors-override>*/
-
-		/*<query-selector-override>*/
-		querySelector: if (context.querySelectorAll) {
-
-			if (!this.isHTMLDocument
-				|| qsaFailExpCache[expression]
-				//TODO: only skip when expression is actually mixed case
-				|| this.brokenMixedCaseQSA
-				|| (this.brokenCheckedQSA && expression.indexOf(':checked') > -1)
-				|| (this.brokenEmptyAttributeQSA && reEmptyAttribute.test(expression))
-				|| (!contextIsDocument //Abort when !contextIsDocument and...
-					//  there are multiple expressions in the selector
-					//  since we currently only fix non-document rooted QSA for single expression selectors
-					&& expression.indexOf(',') > -1
-				)
-				|| Slick.disableQSA
-			) break querySelector;
-
-			var _expression = expression, _context = context;
-			if (!contextIsDocument){
-				// non-document rooted QSA
-				// credits to Andrew Dupont
-				var currentId = _context.getAttribute('id'), slickid = 'slickid__';
-				_context.setAttribute('id', slickid);
-				_expression = '#' + slickid + ' ' + _expression;
-				context = _context.parentNode;
-			}
-
-			try {
-				if (first) return context.querySelector(_expression) || null;
-				else nodes = context.querySelectorAll(_expression);
-			} catch(e) {
-				qsaFailExpCache[expression] = 1;
-				break querySelector;
-			} finally {
-				if (!contextIsDocument){
-					if (currentId) _context.setAttribute('id', currentId);
-					else _context.removeAttribute('id');
-					context = _context;
-				}
-			}
-
-			if (this.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){
-				if (node.nodeName > '@' && !(hasOthers && uniques[this.getUID(node)])) found.push(node);
-			} else for (i = 0; node = nodes[i++];){
-				if (!(hasOthers && uniques[this.getUID(node)])) found.push(node);
-			}
-
-			if (hasOthers) this.sort(found);
-			return found;
-
-		}
-		/*</query-selector-override>*/
-
-		parsed = this.Slick.parse(expression);
-		if (!parsed.length) return found;
-	} else if (expression == null){ // there is no expression
-		return found;
-	} else if (expression.Slick){ // expression is a parsed Slick object
-		parsed = expression;
-	} else if (this.contains(context.documentElement || context, expression)){ // expression is a node
-		(found) ? found.push(expression) : found = expression;
-		return found;
-	} else { // other junk
-		return found;
-	}
-
-	/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/
-
-	// cache elements for the nth selectors
-
-	this.posNTH = {};
-	this.posNTHLast = {};
-	this.posNTHType = {};
-	this.posNTHTypeLast = {};
-
-	/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/
-
-	// if append is null and there is only a single selector with one expression use pushArray, else use pushUID
-	this.push = (!hasOthers && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID;
-
-	if (found == null) found = [];
-
-	// default engine
-
-	var j, m, n;
-	var combinator, tag, id, classList, classes, attributes, pseudos;
-	var currentItems, currentExpression, currentBit, lastBit, expressions = parsed.expressions;
-
-	search: for (i = 0; (currentExpression = expressions[i]); i++) for (j = 0; (currentBit = currentExpression[j]); j++){
-
-		combinator = 'combinator:' + currentBit.combinator;
-		if (!this[combinator]) continue search;
-
-		tag        = (this.isXMLDocument) ? currentBit.tag : currentBit.tag.toUpperCase();
-		id         = currentBit.id;
-		classList  = currentBit.classList;
-		classes    = currentBit.classes;
-		attributes = currentBit.attributes;
-		pseudos    = currentBit.pseudos;
-		lastBit    = (j === (currentExpression.length - 1));
-
-		this.bitUniques = {};
-
-		if (lastBit){
-			this.uniques = uniques;
-			this.found = found;
-		} else {
-			this.uniques = {};
-			this.found = [];
-		}
-
-		if (j === 0){
-			this[combinator](context, tag, id, classes, attributes, pseudos, classList);
-			if (first && lastBit && found.length) break search;
-		} else {
-			if (first && lastBit) for (m = 0, n = currentItems.length; m < n; m++){
-				this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
-				if (found.length) break search;
-			} else for (m = 0, n = currentItems.length; m < n; m++) this[combinator](currentItems[m], tag, id, classes, attributes, pseudos, classList);
-		}
-
-		currentItems = this.found;
-	}
-
-	// should sort if there are nodes in append and if you pass multiple expressions.
-	if (hasOthers || (parsed.expressions.length > 1)) this.sort(found);
-
-	return (first) ? (found[0] || null) : found;
-};
-
-// Utils
-
-local.uidx = 1;
-local.uidk = 'slick-uniqueid';
-
-local.getUIDXML = function(node){
-	var uid = node.getAttribute(this.uidk);
-	if (!uid){
-		uid = this.uidx++;
-		node.setAttribute(this.uidk, uid);
-	}
-	return uid;
-};
-
-local.getUIDHTML = function(node){
-	return node.uniqueNumber || (node.uniqueNumber = this.uidx++);
-};
-
-// sort based on the setDocument documentSorter method.
-
-local.sort = function(results){
-	if (!this.documentSorter) return results;
-	results.sort(this.documentSorter);
-	return results;
-};
-
-/*<pseudo-selectors>*//*<nth-pseudo-selectors>*/
-
-local.cacheNTH = {};
-
-local.matchNTH = /^([+-]?\d*)?([a-z]+)?([+-]\d+)?$/;
-
-local.parseNTHArgument = function(argument){
-	var parsed = argument.match(this.matchNTH);
-	if (!parsed) return false;
-	var special = parsed[2] || false;
-	var a = parsed[1] || 1;
-	if (a == '-') a = -1;
-	var b = +parsed[3] || 0;
-	parsed =
-		(special == 'n')	? {a: a, b: b} :
-		(special == 'odd')	? {a: 2, b: 1} :
-		(special == 'even')	? {a: 2, b: 0} : {a: 0, b: a};
-
-	return (this.cacheNTH[argument] = parsed);
-};
-
-local.createNTHPseudo = function(child, sibling, positions, ofType){
-	return function(node, argument){
-		var uid = this.getUID(node);
-		if (!this[positions][uid]){
-			var parent = node.parentNode;
-			if (!parent) return false;
-			var el = parent[child], count = 1;
-			if (ofType){
-				var nodeName = node.nodeName;
-				do {
-					if (el.nodeName != nodeName) continue;
-					this[positions][this.getUID(el)] = count++;
-				} while ((el = el[sibling]));
-			} else {
-				do {
-					if (el.nodeType != 1) continue;
-					this[positions][this.getUID(el)] = count++;
-				} while ((el = el[sibling]));
-			}
-		}
-		argument = argument || 'n';
-		var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument);
-		if (!parsed) return false;
-		var a = parsed.a, b = parsed.b, pos = this[positions][uid];
-		if (a == 0) return b == pos;
-		if (a > 0){
-			if (pos < b) return false;
-		} else {
-			if (b < pos) return false;
-		}
-		return ((pos - b) % a) == 0;
-	};
-};
-
-/*</nth-pseudo-selectors>*//*</pseudo-selectors>*/
-
-local.pushArray = function(node, tag, id, classes, attributes, pseudos){
-	if (this.matchSelector(node, tag, id, classes, attributes, pseudos)) this.found.push(node);
-};
-
-local.pushUID = function(node, tag, id, classes, attributes, pseudos){
-	var uid = this.getUID(node);
-	if (!this.uniques[uid] && this.matchSelector(node, tag, id, classes, attributes, pseudos)){
-		this.uniques[uid] = true;
-		this.found.push(node);
-	}
-};
-
-local.matchNode = function(node, selector){
-	if (this.isHTMLDocument && this.nativeMatchesSelector){
-		try {
-			return this.nativeMatchesSelector.call(node, selector.replace(/\[([^=]+)=\s*([^'"\]]+?)\s*\]/g, '[$1="$2"]'));
-		} catch(matchError) {}
-	}
-
-	var parsed = this.Slick.parse(selector);
-	if (!parsed) return true;
-
-	// simple (single) selectors
-	var expressions = parsed.expressions, simpleExpCounter = 0, i;
-	for (i = 0; (currentExpression = expressions[i]); i++){
-		if (currentExpression.length == 1){
-			var exp = currentExpression[0];
-			if (this.matchSelector(node, (this.isXMLDocument) ? exp.tag : exp.tag.toUpperCase(), exp.id, exp.classes, exp.attributes, exp.pseudos)) return true;
-			simpleExpCounter++;
-		}
-	}
-
-	if (simpleExpCounter == parsed.length) return false;
-
-	var nodes = this.search(this.document, parsed), item;
-	for (i = 0; item = nodes[i++];){
-		if (item === node) return true;
-	}
-	return false;
-};
-
-local.matchPseudo = function(node, name, argument){
-	var pseudoName = 'pseudo:' + name;
-	if (this[pseudoName]) return this[pseudoName](node, argument);
-	var attribute = this.getAttribute(node, name);
-	return (argument) ? argument == attribute : !!attribute;
-};
-
-local.matchSelector = function(node, tag, id, classes, attributes, pseudos){
-	if (tag){
-		var nodeName = (this.isXMLDocument) ? node.nodeName : node.nodeName.toUpperCase();
-		if (tag == '*'){
-			if (nodeName < '@') return false; // Fix for comment nodes and closed nodes
-		} else {
-			if (nodeName != tag) return false;
-		}
-	}
-
-	if (id && node.getAttribute('id') != id) return false;
-
-	var i, part, cls;
-	if (classes) for (i = classes.length; i--;){
-		cls = this.getAttribute(node, 'class');
-		if (!(cls && classes[i].regexp.test(cls))) return false;
-	}
-	if (attributes) for (i = attributes.length; i--;){
-		part = attributes[i];
-		if (part.operator ? !part.test(this.getAttribute(node, part.key)) : !this.hasAttribute(node, part.key)) return false;
-	}
-	if (pseudos) for (i = pseudos.length; i--;){
-		part = pseudos[i];
-		if (!this.matchPseudo(node, part.key, part.value)) return false;
-	}
-	return true;
-};
-
-var combinators = {
-
-	' ': function(node, tag, id, classes, attributes, pseudos, classList){ // all child nodes, any level
-
-		var i, item, children;
-
-		if (this.isHTMLDocument){
-			getById: if (id){
-				item = this.document.getElementById(id);
-				if ((!item && node.all) || (this.idGetsName && item && item.getAttributeNode('id').nodeValue != id)){
-					// all[id] returns all the elements with that name or id inside node
-					// if theres just one it will return the element, else it will be a collection
-					children = node.all[id];
-					if (!children) return;
-					if (!children[0]) children = [children];
-					for (i = 0; item = children[i++];){
-						var idNode = item.getAttributeNode('id');
-						if (idNode && idNode.nodeValue == id){
-							this.push(item, tag, null, classes, attributes, pseudos);
-							break;
-						}
-					}
-					return;
-				}
-				if (!item){
-					// if the context is in the dom we return, else we will try GEBTN, breaking the getById label
-					if (this.contains(this.root, node)) return;
-					else break getById;
-				} else if (this.document !== node && !this.contains(node, item)) return;
-				this.push(item, tag, null, classes, attributes, pseudos);
-				return;
-			}
-			getByClass: if (classes && node.getElementsByClassName && !this.brokenGEBCN){
-				children = node.getElementsByClassName(classList.join(' '));
-				if (!(children && children.length)) break getByClass;
-				for (i = 0; item = children[i++];) this.push(item, tag, id, null, attributes, pseudos);
-				return;
-			}
-		}
-		getByTag: {
-			children = node.getElementsByTagName(tag);
-			if (!(children && children.length)) break getByTag;
-			if (!this.brokenStarGEBTN) tag = null;
-			for (i = 0; item = children[i++];) this.push(item, tag, id, classes, attributes, pseudos);
-		}
-	},
-
-	'>': function(node, tag, id, classes, attributes, pseudos){ // direct children
-		if ((node = node.firstChild)) do {
-			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
-		} while ((node = node.nextSibling));
-	},
-
-	'+': function(node, tag, id, classes, attributes, pseudos){ // next sibling
-		while ((node = node.nextSibling)) if (node.nodeType == 1){
-			this.push(node, tag, id, classes, attributes, pseudos);
-			break;
-		}
-	},
-
-	'^': function(node, tag, id, classes, attributes, pseudos){ // first child
-		node = node.firstChild;
-		if (node){
-			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
-			else this['combinator:+'](node, tag, id, classes, attributes, pseudos);
-		}
-	},
-
-	'~': function(node, tag, id, classes, attributes, pseudos){ // next siblings
-		while ((node = node.nextSibling)){
-			if (node.nodeType != 1) continue;
-			var uid = this.getUID(node);
-			if (this.bitUniques[uid]) break;
-			this.bitUniques[uid] = true;
-			this.push(node, tag, id, classes, attributes, pseudos);
-		}
-	},
-
-	'++': function(node, tag, id, classes, attributes, pseudos){ // next sibling and previous sibling
-		this['combinator:+'](node, tag, id, classes, attributes, pseudos);
-		this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
-	},
-
-	'~~': function(node, tag, id, classes, attributes, pseudos){ // next siblings and previous siblings
-		this['combinator:~'](node, tag, id, classes, attributes, pseudos);
-		this['combinator:!~'](node, tag, id, classes, attributes, pseudos);
-	},
-
-	'!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document
-		while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
-	},
-
-	'!>': function(node, tag, id, classes, attributes, pseudos){ // direct parent (one level)
-		node = node.parentNode;
-		if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
-	},
-
-	'!+': function(node, tag, id, classes, attributes, pseudos){ // previous sibling
-		while ((node = node.previousSibling)) if (node.nodeType == 1){
-			this.push(node, tag, id, classes, attributes, pseudos);
-			break;
-		}
-	},
-
-	'!^': function(node, tag, id, classes, attributes, pseudos){ // last child
-		node = node.lastChild;
-		if (node){
-			if (node.nodeType == 1) this.push(node, tag, id, classes, attributes, pseudos);
-			else this['combinator:!+'](node, tag, id, classes, attributes, pseudos);
-		}
-	},
-
-	'!~': function(node, tag, id, classes, attributes, pseudos){ // previous siblings
-		while ((node = node.previousSibling)){
-			if (node.nodeType != 1) continue;
-			var uid = this.getUID(node);
-			if (this.bitUniques[uid]) break;
-			this.bitUniques[uid] = true;
-			this.push(node, tag, id, classes, attributes, pseudos);
-		}
-	}
-
-};
-
-for (var c in combinators) local['combinator:' + c] = combinators[c];
-
-var pseudos = {
-
-	/*<pseudo-selectors>*/
-
-	'empty': function(node){
-		var child = node.firstChild;
-		return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length;
-	},
-
-	'not': function(node, expression){
-		return !this.matchNode(node, expression);
-	},
-
-	'contains': function(node, text){
-		return (node.innerText || node.textContent || '').indexOf(text) > -1;
-	},
-
-	'first-child': function(node){
-		while ((node = node.previousSibling)) if (node.nodeType == 1) return false;
-		return true;
-	},
-
-	'last-child': function(node){
-		while ((node = node.nextSibling)) if (node.nodeType == 1) return false;
-		return true;
-	},
-
-	'only-child': function(node){
-		var prev = node;
-		while ((prev = prev.previousSibling)) if (prev.nodeType == 1) return false;
-		var next = node;
-		while ((next = next.nextSibling)) if (next.nodeType == 1) return false;
-		return true;
-	},
-
-	/*<nth-pseudo-selectors>*/
-
-	'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'),
-
-	'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'),
-
-	'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true),
-
-	'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true),
-
-	'index': function(node, index){
-		return this['pseudo:nth-child'](node, '' + (index + 1));
-	},
-
-	'even': function(node){
-		return this['pseudo:nth-child'](node, '2n');
-	},
-
-	'odd': function(node){
-		return this['pseudo:nth-child'](node, '2n+1');
-	},
-
-	/*</nth-pseudo-selectors>*/
-
-	/*<of-type-pseudo-selectors>*/
-
-	'first-of-type': function(node){
-		var nodeName = node.nodeName;
-		while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false;
-		return true;
-	},
-
-	'last-of-type': function(node){
-		var nodeName = node.nodeName;
-		while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false;
-		return true;
-	},
-
-	'only-of-type': function(node){
-		var prev = node, nodeName = node.nodeName;
-		while ((prev = prev.previousSibling)) if (prev.nodeName == nodeName) return false;
-		var next = node;
-		while ((next = next.nextSibling)) if (next.nodeName == nodeName) return false;
-		return true;
-	},
-
-	/*</of-type-pseudo-selectors>*/
-
-	// custom pseudos
-
-	'enabled': function(node){
-		return !node.disabled;
-	},
-
-	'disabled': function(node){
-		return node.disabled;
-	},
-
-	'checked': function(node){
-		return node.checked || node.selected;
-	},
-
-	'focus': function(node){
-		return this.isHTMLDocument && this.document.activeElement === node && (node.href || node.type || this.hasAttribute(node, 'tabindex'));
-	},
-
-	'root': function(node){
-		return (node === this.root);
-	},
-
-	'selected': function(node){
-		return node.selected;
-	}
-
-	/*</pseudo-selectors>*/
-};
-
-for (var p in pseudos) local['pseudo:' + p] = pseudos[p];
-
-// attributes methods
-
-var attributeGetters = local.attributeGetters = {
-
-	'for': function(){
-		return ('htmlFor' in this) ? this.htmlFor : this.getAttribute('for');
-	},
-
-	'href': function(){
-		return ('href' in this) ? this.getAttribute('href', 2) : this.getAttribute('href');
-	},
-
-	'style': function(){
-		return (this.style) ? this.style.cssText : this.getAttribute('style');
-	},
-
-	'tabindex': function(){
-		var attributeNode = this.getAttributeNode('tabindex');
-		return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null;
-	},
-
-	'type': function(){
-		return this.getAttribute('type');
-	},
-
-	'maxlength': function(){
-		var attributeNode = this.getAttributeNode('maxLength');
-		return (attributeNode && attributeNode.specified) ? attributeNode.nodeValue : null;
-	}
-
-};
-
-attributeGetters.MAXLENGTH = attributeGetters.maxLength = attributeGetters.maxlength;
-
-// Slick
-
-var Slick = local.Slick = (this.Slick || {});
-
-Slick.version = '1.1.7';
-
-// Slick finder
-
-Slick.search = function(context, expression, append){
-	return local.search(context, expression, append);
-};
-
-Slick.find = function(context, expression){
-	return local.search(context, expression, null, true);
-};
-
-// Slick containment checker
-
-Slick.contains = function(container, node){
-	local.setDocument(container);
-	return local.contains(container, node);
-};
-
-// Slick attribute getter
-
-Slick.getAttribute = function(node, name){
-	local.setDocument(node);
-	return local.getAttribute(node, name);
-};
-
-Slick.hasAttribute = function(node, name){
-	local.setDocument(node);
-	return local.hasAttribute(node, name);
-};
-
-// Slick matcher
-
-Slick.match = function(node, selector){
-	if (!(node && selector)) return false;
-	if (!selector || selector === node) return true;
-	local.setDocument(node);
-	return local.matchNode(node, selector);
-};
-
-// Slick attribute accessor
-
-Slick.defineAttributeGetter = function(name, fn){
-	local.attributeGetters[name] = fn;
-	return this;
-};
-
-Slick.lookupAttributeGetter = function(name){
-	return local.attributeGetters[name];
-};
-
-// Slick pseudo accessor
-
-Slick.definePseudo = function(name, fn){
-	local['pseudo:' + name] = function(node, argument){
-		return fn.call(node, argument);
-	};
-	return this;
-};
-
-Slick.lookupPseudo = function(name){
-	var pseudo = local['pseudo:' + name];
-	if (pseudo) return function(argument){
-		return pseudo.call(this, argument);
-	};
-	return null;
-};
-
-// Slick overrides accessor
-
-Slick.override = function(regexp, fn){
-	local.override(regexp, fn);
-	return this;
-};
-
-Slick.isXML = local.isXML;
-
-Slick.uidOf = function(node){
-	return local.getUIDHTML(node);
-};
-
-if (!this.Slick) this.Slick = Slick;
-
-}).apply(/*<CommonJS>*/(typeof exports != 'undefined') ? exports : /*</CommonJS>*/this);
-
-
-/*
----
-
-name: Element
-
-description: One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser, time-saver methods to let you easily work with HTML Elements.
-
-license: MIT-style license.
-
-requires: [Window, Document, Array, String, Function, Object, Number, Slick.Parser, Slick.Finder]
-
-provides: [Element, Elements, $, $$, Iframe, Selectors]
-
-...
-*/
-
-var Element = function(tag, props){
-	var konstructor = Element.Constructors[tag];
-	if (konstructor) return konstructor(props);
-	if (typeof tag != 'string') return document.id(tag).set(props);
-
-	if (!props) props = {};
-
-	if (!(/^[\w-]+$/).test(tag)){
-		var parsed = Slick.parse(tag).expressions[0][0];
-		tag = (parsed.tag == '*') ? 'div' : parsed.tag;
-		if (parsed.id && props.id == null) props.id = parsed.id;
-
-		var attributes = parsed.attributes;
-		if (attributes) for (var attr, i = 0, l = attributes.length; i < l; i++){
-			attr = attributes[i];
-			if (props[attr.key] != null) continue;
-
-			if (attr.value != null && attr.operator == '=') props[attr.key] = attr.value;
-			else if (!attr.value && !attr.operator) props[attr.key] = true;
-		}
-
-		if (parsed.classList && props['class'] == null) props['class'] = parsed.classList.join(' ');
-	}
-
-	return document.newElement(tag, props);
-};
-
-
-if (Browser.Element){
-	Element.prototype = Browser.Element.prototype;
-	// IE8 and IE9 require the wrapping.
-	Element.prototype._fireEvent = (function(fireEvent){
-		return function(type, event){
-			return fireEvent.call(this, type, event);
-		};
-	})(Element.prototype.fireEvent);
-}
-
-new Type('Element', Element).mirror(function(name){
-	if (Array.prototype[name]) return;
-
-	var obj = {};
-	obj[name] = function(){
-		var results = [], args = arguments, elements = true;
-		for (var i = 0, l = this.length; i < l; i++){
-			var element = this[i], result = results[i] = element[name].apply(element, args);
-			elements = (elements && typeOf(result) == 'element');
-		}
-		return (elements) ? new Elements(results) : results;
-	};
-
-	Elements.implement(obj);
-});
-
-if (!Browser.Element){
-	Element.parent = Object;
-
-	Element.Prototype = {
-		'$constructor': Element,
-		'$family': Function.from('element').hide()
-	};
-
-	Element.mirror(function(name, method){
-		Element.Prototype[name] = method;
-	});
-}
-
-Element.Constructors = {};
-
-//<1.2compat>
-
-Element.Constructors = new Hash;
-
-//</1.2compat>
-
-var IFrame = new Type('IFrame', function(){
-	var params = Array.link(arguments, {
-		properties: Type.isObject,
-		iframe: function(obj){
-			return (obj != null);
-		}
-	});
-
-	var props = params.properties || {}, iframe;
-	if (params.iframe) iframe = document.id(params.iframe);
-	var onload = props.onload || function(){};
-	delete props.onload;
-	props.id = props.name = [props.id, props.name, iframe ? (iframe.id || iframe.name) : 'IFrame_' + String.uniqueID()].pick();
-	iframe = new Element(iframe || 'iframe', props);
-
-	var onLoad = function(){
-		onload.call(iframe.contentWindow);
-	};
-
-	if (window.frames[props.id]) onLoad();
-	else iframe.addListener('load', onLoad);
-	return iframe;
-});
-
-var Elements = this.Elements = function(nodes){
-	if (nodes && nodes.length){
-		var uniques = {}, node;
-		for (var i = 0; node = nodes[i++];){
-			var uid = Slick.uidOf(node);
-			if (!uniques[uid]){
-				uniques[uid] = true;
-				this.push(node);
-			}
-		}
-	}
-};
-
-Elements.prototype = {length: 0};
-Elements.parent = Array;
-
-new Type('Elements', Elements).implement({
-
-	filter: function(filter, bind){
-		if (!filter) return this;
-		return new Elements(Array.filter(this, (typeOf(filter) == 'string') ? function(item){
-			return item.match(filter);
-		} : filter, bind));
-	}.protect(),
-
-	push: function(){
-		var length = this.length;
-		for (var i = 0, l = arguments.length; i < l; i++){
-			var item = document.id(arguments[i]);
-			if (item) this[length++] = item;
-		}
-		return (this.length = length);
-	}.protect(),
-
-	unshift: function(){
-		var items = [];
-		for (var i = 0, l = arguments.length; i < l; i++){
-			var item = document.id(arguments[i]);
-			if (item) items.push(item);
-		}
-		return Array.prototype.unshift.apply(this, items);
-	}.protect(),
-
-	concat: function(){
-		var newElements = new Elements(this);
-		for (var i = 0, l = arguments.length; i < l; i++){
-			var item = arguments[i];
-			if (Type.isEnumerable(item)) newElements.append(item);
-			else newElements.push(item);
-		}
-		return newElements;
-	}.protect(),
-
-	append: function(collection){
-		for (var i = 0, l = collection.length; i < l; i++) this.push(collection[i]);
-		return this;
-	}.protect(),
-
-	empty: function(){
-		while (this.length) delete this[--this.length];
-		return this;
-	}.protect()
-
-});
-
-//<1.2compat>
-
-Elements.alias('extend', 'append');
-
-//</1.2compat>
-
-(function(){
-
-// FF, IE
-var splice = Array.prototype.splice, object = {'0': 0, '1': 1, length: 2};
-
-splice.call(object, 1, 1);
-if (object[1] == 1) Elements.implement('splice', function(){
-	var length = this.length;
-	var result = splice.apply(this, arguments);
-	while (length >= this.length) delete this[length--];
-	return result;
-}.protect());
-
-Array.forEachMethod(function(method, name){
-	Elements.implement(name, method);
-});
-
-Array.mirror(Elements);
-
-/*<ltIE8>*/
-var createElementAcceptsHTML;
-try {
-    createElementAcceptsHTML = (document.createElement('<input name=x>').name == 'x');
-} catch (e){}
-
-var escapeQuotes = function(html){
-	return ('' + html).replace(/&/g, '&amp;').replace(/"/g, '&quot;');
-};
-/*</ltIE8>*/
-
-Document.implement({
-
-	newElement: function(tag, props){
-		if (props && props.checked != null) props.defaultChecked = props.checked;
-		/*<ltIE8>*/// Fix for readonly name and type properties in IE < 8
-		if (createElementAcceptsHTML && props){
-			tag = '<' + tag;
-			if (props.name) tag += ' name="' + escapeQuotes(props.name) + '"';
-			if (props.type) tag += ' type="' + escapeQuotes(props.type) + '"';
-			tag += '>';
-			delete props.name;
-			delete props.type;
-		}
-		/*</ltIE8>*/
-		return this.id(this.createElement(tag)).set(props);
-	}
-
-});
-
-})();
-
-(function(){
-
-Slick.uidOf(window);
-Slick.uidOf(document);
-
-Document.implement({
-
-	newTextNode: function(text){
-		return this.createTextNode(text);
-	},
-
-	getDocument: function(){
-		return this;
-	},
-
-	getWindow: function(){
-		return this.window;
-	},
-
-	id: (function(){
-
-		var types = {
-
-			string: function(id, nocash, doc){
-				id = Slick.find(doc, '#' + id.replace(/(\W)/g, '\\$1'));
-				return (id) ? types.element(id, nocash) : null;
-			},
-
-			element: function(el, nocash){
-				Slick.uidOf(el);
-				if (!nocash && !el.$family && !(/^(?:object|embed)$/i).test(el.tagName)){
-					var fireEvent = el.fireEvent;
-					// wrapping needed in IE7, or else crash
-					el._fireEvent = function(type, event){
-						return fireEvent(type, event);
-					};
-					Object.append(el, Element.Prototype);
-				}
-				return el;
-			},
-
-			object: function(obj, nocash, doc){
-				if (obj.toElement) return types.element(obj.toElement(doc), nocash);
-				return null;
-			}
-
-		};
-
-		types.textnode = types.whitespace = types.window = types.document = function(zero){
-			return zero;
-		};
-
-		return function(el, nocash, doc){
-			if (el && el.$family && el.uniqueNumber) return el;
-			var type = typeOf(el);
-			return (types[type]) ? types[type](el, nocash, doc || document) : null;
-		};
-
-	})()
-
-});
-
-if (window.$ == null) Window.implement('$', function(el, nc){
-	return document.id(el, nc, this.document);
-});
-
-Window.implement({
-
-	getDocument: function(){
-		return this.document;
-	},
-
-	getWindow: function(){
-		return this;
-	}
-
-});
-
-[Document, Element].invoke('implement', {
-
-	getElements: function(expression){
-		return Slick.search(this, expression, new Elements);
-	},
-
-	getElement: function(expression){
-		return document.id(Slick.find(this, expression));
-	}
-
-});
-
-var contains = {contains: function(element){
-	return Slick.contains(this, element);
-}};
-
-if (!document.contains) Document.implement(contains);
-if (!document.createElement('div').contains) Element.implement(contains);
-
-//<1.2compat>
-
-Element.implement('hasChild', function(element){
-	return this !== element && this.contains(element);
-});
-
-(function(search, find, match){
-
-	this.Selectors = {};
-	var pseudos = this.Selectors.Pseudo = new Hash();
-
-	var addSlickPseudos = function(){
-		for (var name in pseudos) if (pseudos.hasOwnProperty(name)){
-			Slick.definePseudo(name, pseudos[name]);
-			delete pseudos[name];
-		}
-	};
-
-	Slick.search = function(context, expression, append){
-		addSlickPseudos();
-		return search.call(this, context, expression, append);
-	};
-
-	Slick.find = function(context, expression){
-		addSlickPseudos();
-		return find.call(this, context, expression);
-	};
-
-	Slick.match = function(node, selector){
-		addSlickPseudos();
-		return match.call(this, node, selector);
-	};
-
-})(Slick.search, Slick.find, Slick.match);
-
-//</1.2compat>
-
-// tree walking
-
-var injectCombinator = function(expression, combinator){
-	if (!expression) return combinator;
-
-	expression = Object.clone(Slick.parse(expression));
-
-	var expressions = expression.expressions;
-	for (var i = expressions.length; i--;)
-		expressions[i][0].combinator = combinator;
-
-	return expression;
-};
-
-Object.forEach({
-	getNext: '~',
-	getPrevious: '!~',
-	getParent: '!'
-}, function(combinator, method){
-	Element.implement(method, function(expression){
-		return this.getElement(injectCombinator(expression, combinator));
-	});
-});
-
-Object.forEach({
-	getAllNext: '~',
-	getAllPrevious: '!~',
-	getSiblings: '~~',
-	getChildren: '>',
-	getParents: '!'
-}, function(combinator, method){
-	Element.implement(method, function(expression){
-		return this.getElements(injectCombinator(expression, combinator));
-	});
-});
-
-Element.implement({
-
-	getFirst: function(expression){
-		return document.id(Slick.search(this, injectCombinator(expression, '>'))[0]);
-	},
-
-	getLast: function(expression){
-		return document.id(Slick.search(this, injectCombinator(expression, '>')).getLast());
-	},
-
-	getWindow: function(){
-		return this.ownerDocument.window;
-	},
-
-	getDocument: function(){
-		return this.ownerDocument;
-	},
-
-	getElementById: function(id){
-		return document.id(Slick.find(this, '#' + ('' + id).replace(/(\W)/g, '\\$1')));
-	},
-
-	match: function(expression){
-		return !expression || Slick.match(this, expression);
-	}
-
-});
-
-//<1.2compat>
-
-if (window.$$ == null) Window.implement('$$', function(selector){
-	var elements = new Elements;
-	if (arguments.length == 1 && typeof selector == 'string') return Slick.search(this.document, selector, elements);
-	var args = Array.flatten(arguments);
-	for (var i = 0, l = args.length; i < l; i++){
-		var item = args[i];
-		switch (typeOf(item)){
-			case 'element': elements.push(item); break;
-			case 'string': Slick.search(this.document, item, elements);
-		}
-	}
-	return elements;
-});
-
-//</1.2compat>
-
-if (window.$$ == null) Window.implement('$$', function(selector){
-	if (arguments.length == 1){
-		if (typeof selector == 'string') return Slick.search(this.document, selector, new Elements);
-		else if (Type.isEnumerable(selector)) return new Elements(selector);
-	}
-	return new Elements(arguments);
-});
-
-// Inserters
-
-var inserters = {
-
-	before: function(context, element){
-		var parent = element.parentNode;
-		if (parent) parent.insertBefore(context, element);
-	},
-
-	after: function(context, element){
-		var parent = element.parentNode;
-		if (parent) parent.insertBefore(context, element.nextSibling);
-	},
-
-	bottom: function(context, element){
-		element.appendChild(context);
-	},
-
-	top: function(context, element){
-		element.insertBefore(context, element.firstChild);
-	}
-
-};
-
-inserters.inside = inserters.bottom;
-
-//<1.2compat>
-
-Object.each(inserters, function(inserter, where){
-
-	where = where.capitalize();
-
-	var methods = {};
-
-	methods['inject' + where] = function(el){
-		inserter(this, document.id(el, true));
-		return this;
-	};
-
-	methods['grab' + where] = function(el){
-		inserter(document.id(el, true), this);
-		return this;
-	};
-
-	Element.implement(methods);
-
-});
-
-//</1.2compat>
-
-// getProperty / setProperty
-
-var propertyGetters = {}, propertySetters = {};
-
-// properties
-
-var properties = {};
-Array.forEach([
-	'type', 'value', 'defaultValue', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan',
-	'frameBorder', 'rowSpan', 'tabIndex', 'useMap'
-], function(property){
-	properties[property.toLowerCase()] = property;
-});
-
-properties.html = 'innerHTML';
-properties.text = (document.createElement('div').textContent == null) ? 'innerText': 'textContent';
-
-Object.forEach(properties, function(real, key){
-	propertySetters[key] = function(node, value){
-		node[real] = value;
-	};
-	propertyGetters[key] = function(node){
-		return node[real];
-	};
-});
-
-// Booleans
-
-var bools = [
-	'compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked',
-	'disabled', 'readOnly', 'multiple', 'selected', 'noresize',
-	'defer', 'defaultChecked', 'autofocus', 'controls', 'autoplay',
-	'loop'
-];
-
-var booleans = {};
-Array.forEach(bools, function(bool){
-	var lower = bool.toLowerCase();
-	booleans[lower] = bool;
-	propertySetters[lower] = function(node, value){
-		node[bool] = !!value;
-	};
-	propertyGetters[lower] = function(node){
-		return !!node[bool];
-	};
-});
-
-// Special cases
-
-Object.append(propertySetters, {
-
-	'class': function(node, value){
-		('className' in node) ? node.className = (value || '') : node.setAttribute('class', value);
-	},
-
-	'for': function(node, value){
-		('htmlFor' in node) ? node.htmlFor = value : node.setAttribute('for', value);
-	},
-
-	'style': function(node, value){
-		(node.style) ? node.style.cssText = value : node.setAttribute('style', value);
-	},
-
-	'value': function(node, value){
-		node.value = (value != null) ? value : '';
-	}
-
-});
-
-propertyGetters['class'] = function(node){
-	return ('className' in node) ? node.className || null : node.getAttribute('class');
-};
-
-/* <webkit> */
-var el = document.createElement('button');
-// IE sets type as readonly and throws
-try { el.type = 'button'; } catch(e){}
-if (el.type != 'button') propertySetters.type = function(node, value){
-	node.setAttribute('type', value);
-};
-el = null;
-/* </webkit> */
-
-/*<IE>*/
-var input = document.createElement('input');
-input.value = 't';
-input.type = 'submit';
-if (input.value != 't') propertySetters.type = function(node, type){
-	var value = node.value;
-	node.type = type;
-	node.value = value;
-};
-input = null;
-/*</IE>*/
-
-/* getProperty, setProperty */
-
-/* <ltIE9> */
-var pollutesGetAttribute = (function(div){
-	div.random = 'attribute';
-	return (div.getAttribute('random') == 'attribute');
-})(document.createElement('div'));
-
-/* <ltIE9> */
-
-Element.implement({
-
-	setProperty: function(name, value){
-		var setter = propertySetters[name.toLowerCase()];
-		if (setter){
-			setter(this, value);
-		} else {
-			/* <ltIE9> */
-			if (pollutesGetAttribute) var attributeWhiteList = this.retrieve('$attributeWhiteList', {});
-			/* </ltIE9> */
-
-			if (value == null){
-				this.removeAttribute(name);
-				/* <ltIE9> */
-				if (pollutesGetAttribute) delete attributeWhiteList[name];
-				/* </ltIE9> */
-			} else {
-				this.setAttribute(name, '' + value);
-				/* <ltIE9> */
-				if (pollutesGetAttribute) attributeWhiteList[name] = true;
-				/* </ltIE9> */
-			}
-		}
-		return this;
-	},
-
-	setProperties: function(attributes){
-		for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
-		return this;
-	},
-
-	getProperty: function(name){
-		var getter = propertyGetters[name.toLowerCase()];
-		if (getter) return getter(this);
-		/* <ltIE9> */
-		if (pollutesGetAttribute){
-			var attr = this.getAttributeNode(name), attributeWhiteList = this.retrieve('$attributeWhiteList', {});
-			if (!attr) return null;
-			if (attr.expando && !attributeWhiteList[name]){
-				var outer = this.outerHTML;
-				// segment by the opening tag and find mention of attribute name
-				if (outer.substr(0, outer.search(/\/?['"]?>(?![^<]*<['"])/)).indexOf(name) < 0) return null;
-				attributeWhiteList[name] = true;
-			}
-		}
-		/* </ltIE9> */
-		var result = Slick.getAttribute(this, name);
-		return (!result && !Slick.hasAttribute(this, name)) ? null : result;
-	},
-
-	getProperties: function(){
-		var args = Array.from(arguments);
-		return args.map(this.getProperty, this).associate(args);
-	},
-
-	removeProperty: function(name){
-		return this.setProperty(name, null);
-	},
-
-	removeProperties: function(){
-		Array.each(arguments, this.removeProperty, this);
-		return this;
-	},
-
-	set: function(prop, value){
-		var property = Element.Properties[prop];
-		(property && property.set) ? property.set.call(this, value) : this.setProperty(prop, value);
-	}.overloadSetter(),
-
-	get: function(prop){
-		var property = Element.Properties[prop];
-		return (property && property.get) ? property.get.apply(this) : this.getProperty(prop);
-	}.overloadGetter(),
-
-	erase: function(prop){
-		var property = Element.Properties[prop];
-		(property && property.erase) ? property.erase.apply(this) : this.removeProperty(prop);
-		return this;
-	},
-
-	hasClass: function(className){
-		return this.className.clean().contains(className, ' ');
-	},
-
-	addClass: function(className){
-		if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
-		return this;
-	},
-
-	removeClass: function(className){
-		this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
-		return this;
-	},
-
-	toggleClass: function(className, force){
-		if (force == null) force = !this.hasClass(className);
-		return (force) ? this.addClass(className) : this.removeClass(className);
-	},
-
-	adopt: function(){
-		var parent = this, fragment, elements = Array.flatten(arguments), length = elements.length;
-		if (length > 1) parent = fragment = document.createDocumentFragment();
-
-		for (var i = 0; i < length; i++){
-			var element = document.id(elements[i], true);
-			if (element) parent.appendChild(element);
-		}
-
-		if (fragment) this.appendChild(fragment);
-
-		return this;
-	},
-
-	appendText: function(text, where){
-		return this.grab(this.getDocument().newTextNode(text), where);
-	},
-
-	grab: function(el, where){
-		inserters[where || 'bottom'](document.id(el, true), this);
-		return this;
-	},
-
-	inject: function(el, where){
-		inserters[where || 'bottom'](this, document.id(el, true));
-		return this;
-	},
-
-	replaces: function(el){
-		el = document.id(el, true);
-		el.parentNode.replaceChild(this, el);
-		return this;
-	},
-
-	wraps: function(el, where){
-		el = document.id(el, true);
-		return this.replaces(el).grab(el, where);
-	},
-
-	getSelected: function(){
-		this.selectedIndex; // Safari 3.2.1
-		return new Elements(Array.from(this.options).filter(function(option){
-			return option.selected;
-		}));
-	},
-
-	toQueryString: function(){
-		var queryString = [];
-		this.getElements('input, select, textarea').each(function(el){
-			var type = el.type;
-			if (!el.name || el.disabled || type == 'submit' || type == 'reset' || type == 'file' || type == 'image') return;
-
-			var value = (el.get('tag') == 'select') ? el.getSelected().map(function(opt){
-				// IE
-				return document.id(opt).get('value');
-			}) : ((type == 'radio' || type == 'checkbox') && !el.checked) ? null : el.get('value');
-
-			Array.from(value).each(function(val){
-				if (typeof val != 'undefined') queryString.push(encodeURIComponent(el.name) + '=' + encodeURIComponent(val));
-			});
-		});
-		return queryString.join('&');
-	}
-
-});
-
-var collected = {}, storage = {};
-
-var get = function(uid){
-	return (storage[uid] || (storage[uid] = {}));
-};
-
-var clean = function(item){
-	var uid = item.uniqueNumber;
-	if (item.removeEvents) item.removeEvents();
-	if (item.clearAttributes) item.clearAttributes();
-	if (uid != null){
-		delete collected[uid];
-		delete storage[uid];
-	}
-	return item;
-};
-
-var formProps = {input: 'checked', option: 'selected', textarea: 'value'};
-
-Element.implement({
-
-	destroy: function(){
-		var children = clean(this).getElementsByTagName('*');
-		Array.each(children, clean);
-		Element.dispose(this);
-		return null;
-	},
-
-	empty: function(){
-		Array.from(this.childNodes).each(Element.dispose);
-		return this;
-	},
-
-	dispose: function(){
-		return (this.parentNode) ? this.parentNode.removeChild(this) : this;
-	},
-
-	clone: function(contents, keepid){
-		contents = contents !== false;
-		var clone = this.cloneNode(contents), ce = [clone], te = [this], i;
-
-		if (contents){
-			ce.append(Array.from(clone.getElementsByTagName('*')));
-			te.append(Array.from(this.getElementsByTagName('*')));
-		}
-
-		for (i = ce.length; i--;){
-			var node = ce[i], element = te[i];
-			if (!keepid) node.removeAttribute('id');
-			/*<ltIE9>*/
-			if (node.clearAttributes){
-				node.clearAttributes();
-				node.mergeAttributes(element);
-				node.removeAttribute('uniqueNumber');
-				if (node.options){
-					var no = node.options, eo = element.options;
-					for (var j = no.length; j--;) no[j].selected = eo[j].selected;
-				}
-			}
-			/*</ltIE9>*/
-			var prop = formProps[element.tagName.toLowerCase()];
-			if (prop && element[prop]) node[prop] = element[prop];
-		}
-
-		/*<ltIE9>*/
-		if (Browser.ie){
-			var co = clone.getElementsByTagName('object'), to = this.getElementsByTagName('object');
-			for (i = co.length; i--;) co[i].outerHTML = to[i].outerHTML;
-		}
-		/*</ltIE9>*/
-		return document.id(clone);
-	}
-
-});
-
-[Element, Window, Document].invoke('implement', {
-
-	addListener: function(type, fn){
-		if (type == 'unload'){
-			var old = fn, self = this;
-			fn = function(){
-				self.removeListener('unload', fn);
-				old();
-			};
-		} else {
-			collected[Slick.uidOf(this)] = this;
-		}
-		if (this.addEventListener) this.addEventListener(type, fn, !!arguments[2]);
-		else this.attachEvent('on' + type, fn);
-		return this;
-	},
-
-	removeListener: function(type, fn){
-		if (this.removeEventListener) this.removeEventListener(type, fn, !!arguments[2]);
-		else this.detachEvent('on' + type, fn);
-		return this;
-	},
-
-	retrieve: function(property, dflt){
-		var storage = get(Slick.uidOf(this)), prop = storage[property];
-		if (dflt != null && prop == null) prop = storage[property] = dflt;
-		return prop != null ? prop : null;
-	},
-
-	store: function(property, value){
-		var storage = get(Slick.uidOf(this));
-		storage[property] = value;
-		return this;
-	},
-
-	eliminate: function(property){
-		var storage = get(Slick.uidOf(this));
-		delete storage[property];
-		return this;
-	}
-
-});
-
-/*<ltIE9>*/
-if (window.attachEvent && !window.addEventListener) window.addListener('unload', function(){
-	Object.each(collected, clean);
-	if (window.CollectGarbage) CollectGarbage();
-});
-/*</ltIE9>*/
-
-Element.Properties = {};
-
-//<1.2compat>
-
-Element.Properties = new Hash;
-
-//</1.2compat>
-
-Element.Properties.style = {
-
-	set: function(style){
-		this.style.cssText = style;
-	},
-
-	get: function(){
-		return this.style.cssText;
-	},
-
-	erase: function(){
-		this.style.cssText = '';
-	}
-
-};
-
-Element.Properties.tag = {
-
-	get: function(){
-		return this.tagName.toLowerCase();
-	}
-
-};
-
-Element.Properties.html = {
-
-	set: function(html){
-		if (html == null) html = '';
-		else if (typeOf(html) == 'array') html = html.join('');
-		this.innerHTML = html;
-	},
-
-	erase: function(){
-		this.innerHTML = '';
-	}
-
-};
-
-/*<ltIE9>*/
-// technique by jdbarlett - http://jdbartlett.com/innershiv/
-var div = document.createElement('div');
-div.innerHTML = '<nav></nav>';
-var supportsHTML5Elements = (div.childNodes.length == 1);
-if (!supportsHTML5Elements){
-	var tags = 'abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' '),
-		fragment = document.createDocumentFragment(), l = tags.length;
-	while (l--) fragment.createElement(tags[l]);
-}
-div = null;
-/*</ltIE9>*/
-
-/*<IE>*/
-var supportsTableInnerHTML = Function.attempt(function(){
-	var table = document.createElement('table');
-	table.innerHTML = '<tr><td></td></tr>';
-	return true;
-});
-
-/*<ltFF4>*/
-var tr = document.createElement('tr'), html = '<td></td>';
-tr.innerHTML = html;
-var supportsTRInnerHTML = (tr.innerHTML == html);
-tr = null;
-/*</ltFF4>*/
-
-if (!supportsTableInnerHTML || !supportsTRInnerHTML || !supportsHTML5Elements){
-
-	Element.Properties.html.set = (function(set){
-
-		var translations = {
-			table: [1, '<table>', '</table>'],
-			select: [1, '<select>', '</select>'],
-			tbody: [2, '<table><tbody>', '</tbody></table>'],
-			tr: [3, '<table><tbody><tr>', '</tr></tbody></table>']
-		};
-
-		translations.thead = translations.tfoot = translations.tbody;
-
-		return function(html){
-			var wrap = translations[this.get('tag')];
-			if (!wrap && !supportsHTML5Elements) wrap = [0, '', ''];
-			if (!wrap) return set.call(this, html);
-
-			var level = wrap[0], wrapper = document.createElement('div'), target = wrapper;
-			if (!supportsHTML5Elements) fragment.appendChild(wrapper);
-			wrapper.innerHTML = [wrap[1], html, wrap[2]].flatten().join('');
-			while (level--) target = target.firstChild;
-			this.empty().adopt(target.childNodes);
-			if (!supportsHTML5Elements) fragment.removeChild(wrapper);
-			wrapper = null;
-		};
-
-	})(Element.Properties.html.set);
-}
-/*</IE>*/
-
-/*<ltIE9>*/
-var testForm = document.createElement('form');
-testForm.innerHTML = '<select><option>s</option></select>';
-
-if (testForm.firstChild.value != 's') Element.Properties.value = {
-
-	set: function(value){
-		var tag = this.get('tag');
-		if (tag != 'select') return this.setProperty('value', value);
-		var options = this.getElements('option');
-		for (var i = 0; i < options.length; i++){
-			var option = options[i],
-				attr = option.getAttributeNode('value'),
-				optionValue = (attr && attr.specified) ? option.value : option.get('text');
-			if (optionValue == value) return option.selected = true;
-		}
-	},
-
-	get: function(){
-		var option = this, tag = option.get('tag');
-
-		if (tag != 'select' && tag != 'option') return this.getProperty('value');
-
-		if (tag == 'select' && !(option = option.getSelected()[0])) return '';
-
-		var attr = option.getAttributeNode('value');
-		return (attr && attr.specified) ? option.value : option.get('text');
-	}
-
-};
-testForm = null;
-/*</ltIE9>*/
-
-/*<IE>*/
-if (document.createElement('div').getAttributeNode('id')) Element.Properties.id = {
-	set: function(id){
-		this.id = this.getAttributeNode('id').value = id;
-	},
-	get: function(){
-		return this.id || null;
-	},
-	erase: function(){
-		this.id = this.getAttributeNode('id').value = '';
-	}
-};
-/*</IE>*/
-
-})();
-
-
-/*
----
-
-name: Element.Style
-
-description: Contains methods for interacting with the styles of Elements in a fashionable way.
-
-license: MIT-style license.
-
-requires: Element
-
-provides: Element.Style
-
-...
-*/
-
-(function(){
-
-var html = document.html;
-
-//<ltIE9>
-// Check for oldIE, which does not remove styles when they're set to null
-var el = document.createElement('div');
-el.style.color = 'red';
-el.style.color = null;
-var doesNotRemoveStyles = el.style.color == 'red';
-el = null;
-//</ltIE9>
-
-Element.Properties.styles = {set: function(styles){
-	this.setStyles(styles);
-}};
-
-var hasOpacity = (html.style.opacity != null),
-	hasFilter = (html.style.filter != null),
-	reAlpha = /alpha\(opacity=([\d.]+)\)/i;
-
-var setVisibility = function(element, opacity){
-	element.store('$opacity', opacity);
-	element.style.visibility = opacity > 0 || opacity == null ? 'visible' : 'hidden';
-};
-
-var setOpacity = (hasOpacity ? function(element, opacity){
-	element.style.opacity = opacity;
-} : (hasFilter ? function(element, opacity){
-	var style = element.style;
-	if (!element.currentStyle || !element.currentStyle.hasLayout) style.zoom = 1;
-	if (opacity == null || opacity == 1) opacity = '';
-	else opacity = 'alpha(opacity=' + (opacity * 100).limit(0, 100).round() + ')';
-	var filter = style.filter || element.getComputedStyle('filter') || '';
-	style.filter = reAlpha.test(filter) ? filter.replace(reAlpha, opacity) : filter + opacity;
-	if (!style.filter) style.removeAttribute('filter');
-} : setVisibility));
-
-var getOpacity = (hasOpacity ? function(element){
-	var opacity = element.style.opacity || element.getComputedStyle('opacity');
-	return (opacity == '') ? 1 : opacity.toFloat();
-} : (hasFilter ? function(element){
-	var filter = (element.style.filter || element.getComputedStyle('filter')),
-		opacity;
-	if (filter) opacity = filter.match(reAlpha);
-	return (opacity == null || filter == null) ? 1 : (opacity[1] / 100);
-} : function(element){
-	var opacity = element.retrieve('$opacity');
-	if (opacity == null) opacity = (element.style.visibility == 'hidden' ? 0 : 1);
-	return opacity;
-}));
-
-var floatName = (html.style.cssFloat == null) ? 'styleFloat' : 'cssFloat';
-
-Element.implement({
-
-	getComputedStyle: function(property){
-		if (this.currentStyle) return this.currentStyle[property.camelCase()];
-		var defaultView = Element.getDocument(this).defaultView,
-			computed = defaultView ? defaultView.getComputedStyle(this, null) : null;
-		return (computed) ? computed.getPropertyValue((property == floatName) ? 'float' : property.hyphenate()) : null;
-	},
-
-	setStyle: function(property, value){
-		if (property == 'opacity'){
-			if (value != null) value = parseFloat(value);
-			setOpacity(this, value);
-			return this;
-		}
-		property = (property == 'float' ? floatName : property).camelCase();
-		if (typeOf(value) != 'string'){
-			var map = (Element.Styles[property] || '@').split(' ');
-			value = Array.from(value).map(function(val, i){
-				if (!map[i]) return '';
-				return (typeOf(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
-			}).join(' ');
-		} else if (value == String(Number(value))){
-			value = Math.round(value);
-		}
-		this.style[property] = value;
-		//<ltIE9>
-		if ((value == '' || value == null) && doesNotRemoveStyles && this.style.removeAttribute){
-			this.style.removeAttribute(property);
-		}
-		//</ltIE9>
-		return this;
-	},
-
-	getStyle: function(property){
-		if (property == 'opacity') return getOpacity(this);
-		property = (property == 'float' ? floatName : property).camelCase();
-		var result = this.style[property];
-		if (!result || property == 'zIndex'){
-			result = [];
-			for (var style in Element.ShortStyles){
-				if (property != style) continue;
-				for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
-				return result.join(' ');
-			}
-			result = this.getComputedStyle(property);
-		}
-		if (result){
-			result = String(result);
-			var color = result.match(/rgba?\([\d\s,]+\)/);
-			if (color) result = result.replace(color[0], color[0].rgbToHex());
-		}
-		if (Browser.opera || Browser.ie){
-			if ((/^(height|width)$/).test(property) && !(/px$/.test(result))){
-				var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
-				values.each(function(value){
-					size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
-				}, this);
-				return this['offset' + property.capitalize()] - size + 'px';
-			}
-			if (Browser.ie && (/^border(.+)Width|margin|padding/).test(property) && isNaN(parseFloat(result))){
-				return '0px';
-			}
-		}
-		return result;
-	},
-
-	setStyles: function(styles){
-		for (var style in styles) this.setStyle(style, styles[style]);
-		return this;
-	},
-
-	getStyles: function(){
-		var result = {};
-		Array.flatten(arguments).each(function(key){
-			result[key] = this.getStyle(key);
-		}, this);
-		return result;
-	}
-
-});
-
-Element.Styles = {
-	left: '@px', top: '@px', bottom: '@px', right: '@px',
-	width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',
-	backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
-	fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
-	margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
-	borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
-	zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'
-};
-
-//<1.3compat>
-
-Element.implement({
-
-	setOpacity: function(value){
-		setOpacity(this, value);
-		return this;
-	},
-
-	getOpacity: function(){
-		return getOpacity(this);
-	}
-
-});
-
-Element.Properties.opacity = {
-
-	set: function(opacity){
-		setOpacity(this, opacity);
-		setVisibility(this, opacity);
-	},
-
-	get: function(){
-		return getOpacity(this);
-	}
-
-};
-
-//</1.3compat>
-
-//<1.2compat>
-
-Element.Styles = new Hash(Element.Styles);
-
-//</1.2compat>
-
-Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};
-
-['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
-	var Short = Element.ShortStyles;
-	var All = Element.Styles;
-	['margin', 'padding'].each(function(style){
-		var sd = style + direction;
-		Short[style][sd] = All[sd] = '@px';
-	});
-	var bd = 'border' + direction;
-	Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
-	var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
-	Short[bd] = {};
-	Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
-	Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
-	Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
-});
-
-})();
-
-
-/*
----
-
-name: Element.Event
-
-description: Contains Element methods for dealing with events. This file also includes mouseenter and mouseleave custom Element Events, if necessary.
-
-license: MIT-style license.
-
-requires: [Element, Event]
-
-provides: Element.Event
-
-...
-*/
-
-(function(){
-
-Element.Properties.events = {set: function(events){
-	this.addEvents(events);
-}};
-
-[Element, Window, Document].invoke('implement', {
-
-	addEvent: function(type, fn){
-		var events = this.retrieve('events', {});
-		if (!events[type]) events[type] = {keys: [], values: []};
-		if (events[type].keys.contains(fn)) return this;
-		events[type].keys.push(fn);
-		var realType = type,
-			custom = Element.Events[type],
-			condition = fn,
-			self = this;
-		if (custom){
-			if (custom.onAdd) custom.onAdd.call(this, fn, type);
-			if (custom.condition){
-				condition = function(event){
-					if (custom.condition.call(this, event, type)) return fn.call(this, event);
-					return true;
-				};
-			}
-			if (custom.base) realType = Function.from(custom.base).call(this, type);
-		}
-		var defn = function(){
-			return fn.call(self);
-		};
-		var nativeEvent = Element.NativeEvents[realType];
-		if (nativeEvent){
-			if (nativeEvent == 2){
-				defn = function(event){
-					event = new DOMEvent(event, self.getWindow());
-					if (condition.call(self, event) === false) event.stop();
-				};
-			}
-			this.addListener(realType, defn, arguments[2]);
-		}
-		events[type].values.push(defn);
-		return this;
-	},
-
-	removeEvent: function(type, fn){
-		var events = this.retrieve('events');
-		if (!events || !events[type]) return this;
-		var list = events[type];
-		var index = list.keys.indexOf(fn);
-		if (index == -1) return this;
-		var value = list.values[index];
-		delete list.keys[index];
-		delete list.values[index];
-		var custom = Element.Events[type];
-		if (custom){
-			if (custom.onRemove) custom.onRemove.call(this, fn, type);
-			if (custom.base) type = Function.from(custom.base).call(this, type);
-		}
-		return (Element.NativeEvents[type]) ? this.removeListener(type, value, arguments[2]) : this;
-	},
-
-	addEvents: function(events){
-		for (var event in events) this.addEvent(event, events[event]);
-		return this;
-	},
-
-	removeEvents: function(events){
-		var type;
-		if (typeOf(events) == 'object'){
-			for (type in events) this.removeEvent(type, events[type]);
-			return this;
-		}
-		var attached = this.retrieve('events');
-		if (!attached) return this;
-		if (!events){
-			for (type in attached) this.removeEvents(type);
-			this.eliminate('events');
-		} else if (attached[events]){
-			attached[events].keys.each(function(fn){
-				this.removeEvent(events, fn);
-			}, this);
-			delete attached[events];
-		}
-		return this;
-	},
-
-	fireEvent: function(type, args, delay){
-		var events = this.retrieve('events');
-		if (!events || !events[type]) return this;
-		args = Array.from(args);
-
-		events[type].keys.each(function(fn){
-			if (delay) fn.delay(delay, this, args);
-			else fn.apply(this, args);
-		}, this);
-		return this;
-	},
-
-	cloneEvents: function(from, type){
-		from = document.id(from);
-		var events = from.retrieve('events');
-		if (!events) return this;
-		if (!type){
-			for (var eventType in events) this.cloneEvents(from, eventType);
-		} else if (events[type]){
-			events[type].keys.each(function(fn){
-				this.addEvent(type, fn);
-			}, this);
-		}
-		return this;
-	}
-
-});
-
-Element.NativeEvents = {
-	click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
-	mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
-	mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
-	keydown: 2, keypress: 2, keyup: 2, //keyboard
-	orientationchange: 2, // mobile
-	touchstart: 2, touchmove: 2, touchend: 2, touchcancel: 2, // touch
-	gesturestart: 2, gesturechange: 2, gestureend: 2, // gesture
-	focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, paste: 2, input: 2, //form elements
-	load: 2, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
-	error: 1, abort: 1, scroll: 1 //misc
-};
-
-Element.Events = {mousewheel: {
-	base: (Browser.firefox) ? 'DOMMouseScroll' : 'mousewheel'
-}};
-
-if ('onmouseenter' in document.documentElement){
-	Element.NativeEvents.mouseenter = Element.NativeEvents.mouseleave = 2;
-} else {
-	var check = function(event){
-		var related = event.relatedTarget;
-		if (related == null) return true;
-		if (!related) return false;
-		return (related != this && related.prefix != 'xul' && typeOf(this) != 'document' && !this.contains(related));
-	};
-
-	Element.Events.mouseenter = {
-		base: 'mouseover',
-		condition: check
-	};
-
-	Element.Events.mouseleave = {
-		base: 'mouseout',
-		condition: check
-	};
-}
-
-/*<ltIE9>*/
-if (!window.addEventListener){
-	Element.NativeEvents.propertychange = 2;
-	Element.Events.change = {
-		base: function(){
-			var type = this.type;
-			return (this.get('tag') == 'input' && (type == 'radio' || type == 'checkbox')) ? 'propertychange' : 'change'
-		},
-		condition: function(event){
-			return this.type != 'radio' || (event.event.propertyName == 'checked' && this.checked);
-		}
-	}
-}
-/*</ltIE9>*/
-
-//<1.2compat>
-
-Element.Events = new Hash(Element.Events);
-
-//</1.2compat>
-
-})();
-
-
-/*
----
-
-name: Element.Delegation
-
-description: Extends the Element native object to include the delegate method for more efficient event management.
-
-license: MIT-style license.
-
-requires: [Element.Event]
-
-provides: [Element.Delegation]
-
-...
-*/
-
-(function(){
-
-var eventListenerSupport = !!window.addEventListener;
-
-Element.NativeEvents.focusin = Element.NativeEvents.focusout = 2;
-
-var bubbleUp = function(self, match, fn, event, target){
-	while (target && target != self){
-		if (match(target, event)) return fn.call(target, event, target);
-		target = document.id(target.parentNode);
-	}
-};
-
-var map = {
-	mouseenter: {
-		base: 'mouseover'
-	},
-	mouseleave: {
-		base: 'mouseout'
-	},
-	focus: {
-		base: 'focus' + (eventListenerSupport ? '' : 'in'),
-		capture: true
-	},
-	blur: {
-		base: eventListenerSupport ? 'blur' : 'focusout',
-		capture: true
-	}
-};
-
-/*<ltIE9>*/
-var _key = '$delegation:';
-var formObserver = function(type){
-
-	return {
-
-		base: 'focusin',
-
-		remove: function(self, uid){
-			var list = self.retrieve(_key + type + 'listeners', {})[uid];
-			if (list && list.forms) for (var i = list.forms.length; i--;){
-				list.forms[i].removeEvent(type, list.fns[i]);
-			}
-		},
-
-		listen: function(self, match, fn, event, target, uid){
-			var form = (target.get('tag') == 'form') ? target : event.target.getParent('form');
-			if (!form) return;
-
-			var listeners = self.retrieve(_key + type + 'listeners', {}),
-				listener = listeners[uid] || {forms: [], fns: []},
-				forms = listener.forms, fns = listener.fns;
-
-			if (forms.indexOf(form) != -1) return;
-			forms.push(form);
-
-			var _fn = function(event){
-				bubbleUp(self, match, fn, event, target);
-			};
-			form.addEvent(type, _fn);
-			fns.push(_fn);
-
-			listeners[uid] = listener;
-			self.store(_key + type + 'listeners', listeners);
-		}
-	};
-};
-
-var inputObserver = function(type){
-	return {
-		base: 'focusin',
-		listen: function(self, match, fn, event, target){
-			var events = {blur: function(){
-				this.removeEvents(events);
-			}};
-			events[type] = function(event){
-				bubbleUp(self, match, fn, event, target);
-			};
-			event.target.addEvents(events);
-		}
-	};
-};
-
-if (!eventListenerSupport) Object.append(map, {
-	submit: formObserver('submit'),
-	reset: formObserver('reset'),
-	change: inputObserver('change'),
-	select: inputObserver('select')
-});
-/*</ltIE9>*/
-
-var proto = Element.prototype,
-	addEvent = proto.addEvent,
-	removeEvent = proto.removeEvent;
-
-var relay = function(old, method){
-	return function(type, fn, useCapture){
-		if (type.indexOf(':relay') == -1) return old.call(this, type, fn, useCapture);
-		var parsed = Slick.parse(type).expressions[0][0];
-		if (parsed.pseudos[0].key != 'relay') return old.call(this, type, fn, useCapture);
-		var newType = parsed.tag;
-		parsed.pseudos.slice(1).each(function(pseudo){
-			newType += ':' + pseudo.key + (pseudo.value ? '(' + pseudo.value + ')' : '');
-		});
-		old.call(this, type, fn);
-		return method.call(this, newType, parsed.pseudos[0].value, fn);
-	};
-};
-
-var delegation = {
-
-	addEvent: function(type, match, fn){
-		var storage = this.retrieve('$delegates', {}), stored = storage[type];
-		if (stored) for (var _uid in stored){
-			if (stored[_uid].fn == fn && stored[_uid].match == match) return this;
-		}
-
-		var _type = type, _match = match, _fn = fn, _map = map[type] || {};
-		type = _map.base || _type;
-
-		match = function(target){
-			return Slick.match(target, _match);
-		};
-
-		var elementEvent = Element.Events[_type];
-		if (elementEvent && elementEvent.condition){
-			var __match = match, condition = elementEvent.condition;
-			match = function(target, event){
-				return __match(target, event) && condition.call(target, event, type);
-			};
-		}
-
-		var self = this, uid = String.uniqueID();
-		var delegator = _map.listen ? function(event, target){
-			if (!target && event && event.target) target = event.target;
-			if (target) _map.listen(self, match, fn, event, target, uid);
-		} : function(event, target){
-			if (!target && event && event.target) target = event.target;
-			if (target) bubbleUp(self, match, fn, event, target);
-		};
-
-		if (!stored) stored = {};
-		stored[uid] = {
-			match: _match,
-			fn: _fn,
-			delegator: delegator
-		};
-		storage[_type] = stored;
-		return addEvent.call(this, type, delegator, _map.capture);
-	},
-
-	removeEvent: function(type, match, fn, _uid){
-		var storage = this.retrieve('$delegates', {}), stored = storage[type];
-		if (!stored) return this;
-
-		if (_uid){
-			var _type = type, delegator = stored[_uid].delegator, _map = map[type] || {};
-			type = _map.base || _type;
-			if (_map.remove) _map.remove(this, _uid);
-			delete stored[_uid];
-			storage[_type] = stored;
-			return removeEvent.call(this, type, delegator);
-		}
-
-		var __uid, s;
-		if (fn) for (__uid in stored){
-			s = stored[__uid];
-			if (s.match == match && s.fn == fn) return delegation.removeEvent.call(this, type, match, fn, __uid);
-		} else for (__uid in stored){
-			s = stored[__uid];
-			if (s.match == match) delegation.removeEvent.call(this, type, match, s.fn, __uid);
-		}
-		return this;
-	}
-
-};
-
-[Element, Window, Document].invoke('implement', {
-	addEvent: relay(addEvent, delegation.addEvent),
-	removeEvent: relay(removeEvent, delegation.removeEvent)
-});
-
-})();
-
-
-/*
----
-
-name: Element.Dimensions
-
-description: Contains methods to work with size, scroll, or positioning of Elements and the window object.
-
-license: MIT-style license.
-
-credits:
-  - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html).
-  - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html).
-
-requires: [Element, Element.Style]
-
-provides: [Element.Dimensions]
-
-...
-*/
-
-(function(){
-
-var element = document.createElement('div'),
-	child = document.createElement('div');
-element.style.height = '0';
-element.appendChild(child);
-var brokenOffsetParent = (child.offsetParent === element);
-element = child = null;
-
-var isOffset = function(el){
-	return styleString(el, 'position') != 'static' || isBody(el);
-};
-
-var isOffsetStatic = function(el){
-	return isOffset(el) || (/^(?:table|td|th)$/i).test(el.tagName);
-};
-
-Element.implement({
-
-	scrollTo: function(x, y){
-		if (isBody(this)){
-			this.getWindow().scrollTo(x, y);
-		} else {
-			this.scrollLeft = x;
-			this.scrollTop = y;
-		}
-		return this;
-	},
-
-	getSize: function(){
-		if (isBody(this)) return this.getWindow().getSize();
-		return {x: this.offsetWidth, y: this.offsetHeight};
-	},
-
-	getScrollSize: function(){
-		if (isBody(this)) return this.getWindow().getScrollSize();
-		return {x: this.scrollWidth, y: this.scrollHeight};
-	},
-
-	getScroll: function(){
-		if (isBody(this)) return this.getWindow().getScroll();
-		return {x: this.scrollLeft, y: this.scrollTop};
-	},
-
-	getScrolls: function(){
-		var element = this.parentNode, position = {x: 0, y: 0};
-		while (element && !isBody(element)){
-			position.x += element.scrollLeft;
-			position.y += element.scrollTop;
-			element = element.parentNode;
-		}
-		return position;
-	},
-
-	getOffsetParent: brokenOffsetParent ? function(){
-		var element = this;
-		if (isBody(element) || styleString(element, 'position') == 'fixed') return null;
-
-		var isOffsetCheck = (styleString(element, 'position') == 'static') ? isOffsetStatic : isOffset;
-		while ((element = element.parentNode)){
-			if (isOffsetCheck(element)) return element;
-		}
-		return null;
-	} : function(){
-		var element = this;
-		if (isBody(element) || styleString(element, 'position') == 'fixed') return null;
-
-		try {
-			return element.offsetParent;
-		} catch(e) {}
-		return null;
-	},
-
-	getOffsets: function(){
-		if (this.getBoundingClientRect && !Browser.Platform.ios){
-			var bound = this.getBoundingClientRect(),
-				html = document.id(this.getDocument().documentElement),
-				htmlScroll = html.getScroll(),
-				elemScrolls = this.getScrolls(),
-				isFixed = (styleString(this, 'position') == 'fixed');
-
-			return {
-				x: bound.left.toInt() + elemScrolls.x + ((isFixed) ? 0 : htmlScroll.x) - html.clientLeft,
-				y: bound.top.toInt()  + elemScrolls.y + ((isFixed) ? 0 : htmlScroll.y) - html.clientTop
-			};
-		}
-
-		var element = this, position = {x: 0, y: 0};
-		if (isBody(this)) return position;
-
-		while (element && !isBody(element)){
-			position.x += element.offsetLeft;
-			position.y += element.offsetTop;
-
-			if (Browser.firefox){
-				if (!borderBox(element)){
-					position.x += leftBorder(element);
-					position.y += topBorder(element);
-				}
-				var parent = element.parentNode;
-				if (parent && styleString(parent, 'overflow') != 'visible'){
-					position.x += leftBorder(parent);
-					position.y += topBorder(parent);
-				}
-			} else if (element != this && Browser.safari){
-				position.x += leftBorder(element);
-				position.y += topBorder(element);
-			}
-
-			element = element.offsetParent;
-		}
-		if (Browser.firefox && !borderBox(this)){
-			position.x -= leftBorder(this);
-			position.y -= topBorder(this);
-		}
-		return position;
-	},
-
-	getPosition: function(relative){
-		var offset = this.getOffsets(),
-			scroll = this.getScrolls();
-		var position = {
-			x: offset.x - scroll.x,
-			y: offset.y - scroll.y
-		};
-
-		if (relative && (relative = document.id(relative))){
-			var relativePosition = relative.getPosition();
-			return {x: position.x - relativePosition.x - leftBorder(relative), y: position.y - relativePosition.y - topBorder(relative)};
-		}
-		return position;
-	},
-
-	getCoordinates: function(element){
-		if (isBody(this)) return this.getWindow().getCoordinates();
-		var position = this.getPosition(element),
-			size = this.getSize();
-		var obj = {
-			left: position.x,
-			top: position.y,
-			width: size.x,
-			height: size.y
-		};
-		obj.right = obj.left + obj.width;
-		obj.bottom = obj.top + obj.height;
-		return obj;
-	},
-
-	computePosition: function(obj){
-		return {
-			left: obj.x - styleNumber(this, 'margin-left'),
-			top: obj.y - styleNumber(this, 'margin-top')
-		};
-	},
-
-	setPosition: function(obj){
-		return this.setStyles(this.computePosition(obj));
-	}
-
-});
-
-
-[Document, Window].invoke('implement', {
-
-	getSize: function(){
-		var doc = getCompatElement(this);
-		return {x: doc.clientWidth, y: doc.clientHeight};
-	},
-
-	getScroll: function(){
-		var win = this.getWindow(), doc = getCompatElement(this);
-		return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
-	},
-
-	getScrollSize: function(){
-		var doc = getCompatElement(this),
-			min = this.getSize(),
-			body = this.getDocument().body;
-
-		return {x: Math.max(doc.scrollWidth, body.scrollWidth, min.x), y: Math.max(doc.scrollHeight, body.scrollHeight, min.y)};
-	},
-
-	getPosition: function(){
-		return {x: 0, y: 0};
-	},
-
-	getCoordinates: function(){
-		var size = this.getSize();
-		return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
-	}
-
-});
-
-// private methods
-
-var styleString = Element.getComputedStyle;
-
-function styleNumber(element, style){
-	return styleString(element, style).toInt() || 0;
-}
-
-function borderBox(element){
-	return styleString(element, '-moz-box-sizing') == 'border-box';
-}
-
-function topBorder(element){
-	return styleNumber(element, 'border-top-width');
-}
-
-function leftBorder(element){
-	return styleNumber(element, 'border-left-width');
-}
-
-function isBody(element){
-	return (/^(?:body|html)$/i).test(element.tagName);
-}
-
-function getCompatElement(element){
-	var doc = element.getDocument();
-	return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
-}
-
-})();
-
-//aliases
-Element.alias({position: 'setPosition'}); //compatability
-
-[Window, Document, Element].invoke('implement', {
-
-	getHeight: function(){
-		return this.getSize().y;
-	},
-
-	getWidth: function(){
-		return this.getSize().x;
-	},
-
-	getScrollTop: function(){
-		return this.getScroll().y;
-	},
-
-	getScrollLeft: function(){
-		return this.getScroll().x;
-	},
-
-	getScrollHeight: function(){
-		return this.getScrollSize().y;
-	},
-
-	getScrollWidth: function(){
-		return this.getScrollSize().x;
-	},
-
-	getTop: function(){
-		return this.getPosition().y;
-	},
-
-	getLeft: function(){
-		return this.getPosition().x;
-	}
-
-});
-
-
-/*
----
-
-name: Fx
-
-description: Contains the basic animation logic to be extended by all other Fx Classes.
-
-license: MIT-style license.
-
-requires: [Chain, Events, Options]
-
-provides: Fx
-
-...
-*/
-
-(function(){
-
-var Fx = this.Fx = new Class({
-
-	Implements: [Chain, Events, Options],
-
-	options: {
-		/*
-		onStart: nil,
-		onCancel: nil,
-		onComplete: nil,
-		*/
-		fps: 60,
-		unit: false,
-		duration: 500,
-		frames: null,
-		frameSkip: true,
-		link: 'ignore'
-	},
-
-	initialize: function(options){
-		this.subject = this.subject || this;
-		this.setOptions(options);
-	},
-
-	getTransition: function(){
-		return function(p){
-			return -(Math.cos(Math.PI * p) - 1) / 2;
-		};
-	},
-
-	step: function(now){
-		if (this.options.frameSkip){
-			var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval;
-			this.time = now;
-			this.frame += frames;
-		} else {
-			this.frame++;
-		}
-
-		if (this.frame < this.frames){
-			var delta = this.transition(this.frame / this.frames);
-			this.set(this.compute(this.from, this.to, delta));
-		} else {
-			this.frame = this.frames;
-			this.set(this.compute(this.from, this.to, 1));
-			this.stop();
-		}
-	},
-
-	set: function(now){
-		return now;
-	},
-
-	compute: function(from, to, delta){
-		return Fx.compute(from, to, delta);
-	},
-
-	check: function(){
-		if (!this.isRunning()) return true;
-		switch (this.options.link){
-			case 'cancel': this.cancel(); return true;
-			case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
-		}
-		return false;
-	},
-
-	start: function(from, to){
-		if (!this.check(from, to)) return this;
-		this.from = from;
-		this.to = to;
-		this.frame = (this.options.frameSkip) ? 0 : -1;
-		this.time = null;
-		this.transition = this.getTransition();
-		var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration;
-		this.duration = Fx.Durations[duration] || duration.toInt();
-		this.frameInterval = 1000 / fps;
-		this.frames = frames || Math.round(this.duration / this.frameInterval);
-		this.fireEvent('start', this.subject);
-		pushInstance.call(this, fps);
-		return this;
-	},
-
-	stop: function(){
-		if (this.isRunning()){
-			this.time = null;
-			pullInstance.call(this, this.options.fps);
-			if (this.frames == this.frame){
-				this.fireEvent('complete', this.subject);
-				if (!this.callChain()) this.fireEvent('chainComplete', this.subject);
-			} else {
-				this.fireEvent('stop', this.subject);
-			}
-		}
-		return this;
-	},
-
-	cancel: function(){
-		if (this.isRunning()){
-			this.time = null;
-			pullInstance.call(this, this.options.fps);
-			this.frame = this.frames;
-			this.fireEvent('cancel', this.subject).clearChain();
-		}
-		return this;
-	},
-
-	pause: function(){
-		if (this.isRunning()){
-			this.time = null;
-			pullInstance.call(this, this.options.fps);
-		}
-		return this;
-	},
-
-	resume: function(){
-		if ((this.frame < this.frames) && !this.isRunning()) pushInstance.call(this, this.options.fps);
-		return this;
-	},
-
-	isRunning: function(){
-		var list = instances[this.options.fps];
-		return list && list.contains(this);
-	}
-
-});
-
-Fx.compute = function(from, to, delta){
-	return (to - from) * delta + from;
-};
-
-Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};
-
-// global timers
-
-var instances = {}, timers = {};
-
-var loop = function(){
-	var now = Date.now();
-	for (var i = this.length; i--;){
-		var instance = this[i];
-		if (instance) instance.step(now);
-	}
-};
-
-var pushInstance = function(fps){
-	var list = instances[fps] || (instances[fps] = []);
-	list.push(this);
-	if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list);
-};
-
-var pullInstance = function(fps){
-	var list = instances[fps];
-	if (list){
-		list.erase(this);
-		if (!list.length && timers[fps]){
-			delete instances[fps];
-			timers[fps] = clearInterval(timers[fps]);
-		}
-	}
-};
-
-})();
-
-
-/*
----
-
-name: Fx.CSS
-
-description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.
-
-license: MIT-style license.
-
-requires: [Fx, Element.Style]
-
-provides: Fx.CSS
-
-...
-*/
-
-Fx.CSS = new Class({
-
-	Extends: Fx,
-
-	//prepares the base from/to object
-
-	prepare: function(element, property, values){
-		values = Array.from(values);
-		var from = values[0], to = values[1];
-		if (to == null){
-			to = from;
-			from = element.getStyle(property);
-			var unit = this.options.unit;
-			// adapted from: https://github.com/ryanmorr/fx/blob/master/fx.js#L299
-			if (unit && from.slice(-unit.length) != unit && parseFloat(from) != 0){
-				element.setStyle(property, to + unit);
-				var value = element.getComputedStyle(property);
-				// IE and Opera support pixelLeft or pixelWidth
-				if (!(/px$/.test(value))){
-					value = element.style[('pixel-' + property).camelCase()];
-					if (value == null){
-						// adapted from Dean Edwards' http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
-						var left = element.style.left;
-						element.style.left = to + unit;
-						value = element.style.pixelLeft;
-						element.style.left = left;
-					}
-				}
-				from = (to || 1) / (parseFloat(value) || 1) * (parseFloat(from) || 0);
-				element.setStyle(property, from + unit);
-			}
-		}
-		return {from: this.parse(from), to: this.parse(to)};
-	},
-
-	//parses a value into an array
-
-	parse: function(value){
-		value = Function.from(value)();
-		value = (typeof value == 'string') ? value.split(' ') : Array.from(value);
-		return value.map(function(val){
-			val = String(val);
-			var found = false;
-			Object.each(Fx.CSS.Parsers, function(parser, key){
-				if (found) return;
-				var parsed = parser.parse(val);
-				if (parsed || parsed === 0) found = {value: parsed, parser: parser};
-			});
-			found = found || {value: val, parser: Fx.CSS.Parsers.String};
-			return found;
-		});
-	},
-
-	//computes by a from and to prepared objects, using their parsers.
-
-	compute: function(from, to, delta){
-		var computed = [];
-		(Math.min(from.length, to.length)).times(function(i){
-			computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
-		});
-		computed.$family = Function.from('fx:css:value');
-		return computed;
-	},
-
-	//serves the value as settable
-
-	serve: function(value, unit){
-		if (typeOf(value) != 'fx:css:value') value = this.parse(value);
-		var returned = [];
-		value.each(function(bit){
-			returned = returned.concat(bit.parser.serve(bit.value, unit));
-		});
-		return returned;
-	},
-
-	//renders the change to an element
-
-	render: function(element, property, value, unit){
-		element.setStyle(property, this.serve(value, unit));
-	},
-
-	//searches inside the page css to find the values for a selector
-
-	search: function(selector){
-		if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
-		var to = {}, selectorTest = new RegExp('^' + selector.escapeRegExp() + '$');
-		Array.each(document.styleSheets, function(sheet, j){
-			var href = sheet.href;
-			if (href && href.contains('://') && !href.contains(document.domain)) return;
-			var rules = sheet.rules || sheet.cssRules;
-			Array.each(rules, function(rule, i){
-				if (!rule.style) return;
-				var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){
-					return m.toLowerCase();
-				}) : null;
-				if (!selectorText || !selectorTest.test(selectorText)) return;
-				Object.each(Element.Styles, function(value, style){
-					if (!rule.style[style] || Element.ShortStyles[style]) return;
-					value = String(rule.style[style]);
-					to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value;
-				});
-			});
-		});
-		return Fx.CSS.Cache[selector] = to;
-	}
-
-});
-
-Fx.CSS.Cache = {};
-
-Fx.CSS.Parsers = {
-
-	Color: {
-		parse: function(value){
-			if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
-			return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
-		},
-		compute: function(from, to, delta){
-			return from.map(function(value, i){
-				return Math.round(Fx.compute(from[i], to[i], delta));
-			});
-		},
-		serve: function(value){
-			return value.map(Number);
-		}
-	},
-
-	Number: {
-		parse: parseFloat,
-		compute: Fx.compute,
-		serve: function(value, unit){
-			return (unit) ? value + unit : value;
-		}
-	},
-
-	String: {
-		parse: Function.from(false),
-		compute: function(zero, one){
-			return one;
-		},
-		serve: function(zero){
-			return zero;
-		}
-	}
-
-};
-
-//<1.2compat>
-
-Fx.CSS.Parsers = new Hash(Fx.CSS.Parsers);
-
-//</1.2compat>
-
-
-/*
----
-
-name: Fx.Tween
-
-description: Formerly Fx.Style, effect to transition any CSS property for an element.
-
-license: MIT-style license.
-
-requires: Fx.CSS
-
-provides: [Fx.Tween, Element.fade, Element.highlight]
-
-...
-*/
-
-Fx.Tween = new Class({
-
-	Extends: Fx.CSS,
-
-	initialize: function(element, options){
-		this.element = this.subject = document.id(element);
-		this.parent(options);
-	},
-
-	set: function(property, now){
-		if (arguments.length == 1){
-			now = property;
-			property = this.property || this.options.property;
-		}
-		this.render(this.element, property, now, this.options.unit);
-		return this;
-	},
-
-	start: function(property, from, to){
-		if (!this.check(property, from, to)) return this;
-		var args = Array.flatten(arguments);
-		this.property = this.options.property || args.shift();
-		var parsed = this.prepare(this.element, this.property, args);
-		return this.parent(parsed.from, parsed.to);
-	}
-
-});
-
-Element.Properties.tween = {
-
-	set: function(options){
-		this.get('tween').cancel().setOptions(options);
-		return this;
-	},
-
-	get: function(){
-		var tween = this.retrieve('tween');
-		if (!tween){
-			tween = new Fx.Tween(this, {link: 'cancel'});
-			this.store('tween', tween);
-		}
-		return tween;
-	}
-
-};
-
-Element.implement({
-
-	tween: function(property, from, to){
-		this.get('tween').start(property, from, to);
-		return this;
-	},
-
-	fade: function(how){
-		var fade = this.get('tween'), method, args = ['opacity'].append(arguments), toggle;
-		if (args[1] == null) args[1] = 'toggle';
-		switch (args[1]){
-			case 'in': method = 'start'; args[1] = 1; break;
-			case 'out': method = 'start'; args[1] = 0; break;
-			case 'show': method = 'set'; args[1] = 1; break;
-			case 'hide': method = 'set'; args[1] = 0; break;
-			case 'toggle':
-				var flag = this.retrieve('fade:flag', this.getStyle('opacity') == 1);
-				method = 'start';
-				args[1] = flag ? 0 : 1;
-				this.store('fade:flag', !flag);
-				toggle = true;
-			break;
-			default: method = 'start';
-		}
-		if (!toggle) this.eliminate('fade:flag');
-		fade[method].apply(fade, args);
-		var to = args[args.length - 1];
-		if (method == 'set' || to != 0) this.setStyle('visibility', to == 0 ? 'hidden' : 'visible');
-		else fade.chain(function(){
-			this.element.setStyle('visibility', 'hidden');
-			this.callChain();
-		});
-		return this;
-	},
-
-	highlight: function(start, end){
-		if (!end){
-			end = this.retrieve('highlight:original', this.getStyle('background-color'));
-			end = (end == 'transparent') ? '#fff' : end;
-		}
-		var tween = this.get('tween');
-		tween.start('background-color', start || '#ffff88', end).chain(function(){
-			this.setStyle('background-color', this.retrieve('highlight:original'));
-			tween.callChain();
-		}.bind(this));
-		return this;
-	}
-
-});
-
-
-/*
----
-
-name: Fx.Morph
-
-description: Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules.
-
-license: MIT-style license.
-
-requires: Fx.CSS
-
-provides: Fx.Morph
-
-...
-*/
-
-Fx.Morph = new Class({
-
-	Extends: Fx.CSS,
-
-	initialize: function(element, options){
-		this.element = this.subject = document.id(element);
-		this.parent(options);
-	},
-
-	set: function(now){
-		if (typeof now == 'string') now = this.search(now);
-		for (var p in now) this.render(this.element, p, now[p], this.options.unit);
-		return this;
-	},
-
-	compute: function(from, to, delta){
-		var now = {};
-		for (var p in from) now[p] = this.parent(from[p], to[p], delta);
-		return now;
-	},
-
-	start: function(properties){
-		if (!this.check(properties)) return this;
-		if (typeof properties == 'string') properties = this.search(properties);
-		var from = {}, to = {};
-		for (var p in properties){
-			var parsed = this.prepare(this.element, p, properties[p]);
-			from[p] = parsed.from;
-			to[p] = parsed.to;
-		}
-		return this.parent(from, to);
-	}
-
-});
-
-Element.Properties.morph = {
-
-	set: function(options){
-		this.get('morph').cancel().setOptions(options);
-		return this;
-	},
-
-	get: function(){
-		var morph = this.retrieve('morph');
-		if (!morph){
-			morph = new Fx.Morph(this, {link: 'cancel'});
-			this.store('morph', morph);
-		}
-		return morph;
-	}
-
-};
-
-Element.implement({
-
-	morph: function(props){
-		this.get('morph').start(props);
-		return this;
-	}
-
-});
-
-
-/*
----
-
-name: Fx.Transitions
-
-description: Contains a set of advanced transitions to be used with any of the Fx Classes.
-
-license: MIT-style license.
-
-credits:
-  - Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.
-
-requires: Fx
-
-provides: Fx.Transitions
-
-...
-*/
-
-Fx.implement({
-
-	getTransition: function(){
-		var trans = this.options.transition || Fx.Transitions.Sine.easeInOut;
-		if (typeof trans == 'string'){
-			var data = trans.split(':');
-			trans = Fx.Transitions;
-			trans = trans[data[0]] || trans[data[0].capitalize()];
-			if (data[1]) trans = trans['ease' + data[1].capitalize() + (data[2] ? data[2].capitalize() : '')];
-		}
-		return trans;
-	}
-
-});
-
-Fx.Transition = function(transition, params){
-	params = Array.from(params);
-	var easeIn = function(pos){
-		return transition(pos, params);
-	};
-	return Object.append(easeIn, {
-		easeIn: easeIn,
-		easeOut: function(pos){
-			return 1 - transition(1 - pos, params);
-		},
-		easeInOut: function(pos){
-			return (pos <= 0.5 ? transition(2 * pos, params) : (2 - transition(2 * (1 - pos), params))) / 2;
-		}
-	});
-};
-
-Fx.Transitions = {
-
-	linear: function(zero){
-		return zero;
-	}
-
-};
-
-//<1.2compat>
-
-Fx.Transitions = new Hash(Fx.Transitions);
-
-//</1.2compat>
-
-Fx.Transitions.extend = function(transitions){
-	for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
-};
-
-Fx.Transitions.extend({
-
-	Pow: function(p, x){
-		return Math.pow(p, x && x[0] || 6);
-	},
-
-	Expo: function(p){
-		return Math.pow(2, 8 * (p - 1));
-	},
-
-	Circ: function(p){
-		return 1 - Math.sin(Math.acos(p));
-	},
-
-	Sine: function(p){
-		return 1 - Math.cos(p * Math.PI / 2);
-	},
-
-	Back: function(p, x){
-		x = x && x[0] || 1.618;
-		return Math.pow(p, 2) * ((x + 1) * p - x);
-	},
-
-	Bounce: function(p){
-		var value;
-		for (var a = 0, b = 1; 1; a += b, b /= 2){
-			if (p >= (7 - 4 * a) / 11){
-				value = b * b - Math.pow((11 - 6 * a - 11 * p) / 4, 2);
-				break;
-			}
-		}
-		return value;
-	},
-
-	Elastic: function(p, x){
-		return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x && x[0] || 1) / 3);
-	}
-
-});
-
-['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
-	Fx.Transitions[transition] = new Fx.Transition(function(p){
-		return Math.pow(p, i + 2);
-	});
-});
-
-
-/*
----
-
-name: Request
-
-description: Powerful all purpose Request Class. Uses XMLHTTPRequest.
-
-license: MIT-style license.
-
-requires: [Object, Element, Chain, Events, Options, Browser]
-
-provides: Request
-
-...
-*/
-
-(function(){
-
-var empty = function(){},
-	progressSupport = ('onprogress' in new Browser.Request);
-
-var Request = this.Request = new Class({
-
-	Implements: [Chain, Events, Options],
-
-	options: {/*
-		onRequest: function(){},
-		onLoadstart: function(event, xhr){},
-		onProgress: function(event, xhr){},
-		onComplete: function(){},
-		onCancel: function(){},
-		onSuccess: function(responseText, responseXML){},
-		onFailure: function(xhr){},
-		onException: function(headerName, value){},
-		onTimeout: function(){},
-		user: '',
-		password: '',*/
-		url: '',
-		data: '',
-		headers: {
-			'X-Requested-With': 'XMLHttpRequest',
-			'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
-		},
-		async: true,
-		format: false,
-		method: 'post',
-		link: 'ignore',
-		isSuccess: null,
-		emulation: true,
-		urlEncoded: true,
-		encoding: 'utf-8',
-		evalScripts: false,
-		evalResponse: false,
-		timeout: 0,
-		noCache: false
-	},
-
-	initialize: function(options){
-		this.xhr = new Browser.Request();
-		this.setOptions(options);
-		this.headers = this.options.headers;
-	},
-
-	onStateChange: function(){
-		var xhr = this.xhr;
-		if (xhr.readyState != 4 || !this.running) return;
-		this.running = false;
-		this.status = 0;
-		Function.attempt(function(){
-			var status = xhr.status;
-			this.status = (status == 1223) ? 204 : status;
-		}.bind(this));
-		xhr.onreadystatechange = empty;
-		if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
-		clearTimeout(this.timer);
-
-		this.response = {text: this.xhr.responseText || '', xml: this.xhr.responseXML};
-		if (this.options.isSuccess.call(this, this.status))
-			this.success(this.response.text, this.response.xml);
-		else
-			this.failure();
-	},
-
-	isSuccess: function(){
-		var status = this.status;
-		return (status >= 200 && status < 300);
-	},
-
-	isRunning: function(){
-		return !!this.running;
-	},
-
-	processScripts: function(text){
-		if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return Browser.exec(text);
-		return text.stripScripts(this.options.evalScripts);
-	},
-
-	success: function(text, xml){
-		this.onSuccess(this.processScripts(text), xml);
-	},
-
-	onSuccess: function(){
-		this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain();
-	},
-
-	failure: function(){
-		this.onFailure();
-	},
-
-	onFailure: function(){
-		this.fireEvent('complete').fireEvent('failure', this.xhr);
-	},
-
-	loadstart: function(event){
-		this.fireEvent('loadstart', [event, this.xhr]);
-	},
-
-	progress: function(event){
-		this.fireEvent('progress', [event, this.xhr]);
-	},
-
-	timeout: function(){
-		this.fireEvent('timeout', this.xhr);
-	},
-
-	setHeader: function(name, value){
-		this.headers[name] = value;
-		return this;
-	},
-
-	getHeader: function(name){
-		return Function.attempt(function(){
-			return this.xhr.getResponseHeader(name);
-		}.bind(this));
-	},
-
-	check: function(){
-		if (!this.running) return true;
-		switch (this.options.link){
-			case 'cancel': this.cancel(); return true;
-			case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
-		}
-		return false;
-	},
-
-	send: function(options){
-		if (!this.check(options)) return this;
-
-		this.options.isSuccess = this.options.isSuccess || this.isSuccess;
-		this.running = true;
-
-		var type = typeOf(options);
-		if (type == 'string' || type == 'element') options = {data: options};
-
-		var old = this.options;
-		options = Object.append({data: old.data, url: old.url, method: old.method}, options);
-		var data = options.data, url = String(options.url), method = options.method.toLowerCase();
-
-		switch (typeOf(data)){
-			case 'element': data = document.id(data).toQueryString(); break;
-			case 'object': case 'hash': data = Object.toQueryString(data);
-		}
-
-		if (this.options.format){
-			var format = 'format=' + this.options.format;
-			data = (data) ? format + '&' + data : format;
-		}
-
-		if (this.options.emulation && !['get', 'post'].contains(method)){
-			var _method = '_method=' + method;
-			data = (data) ? _method + '&' + data : _method;
-			method = 'post';
-		}
-
-		if (this.options.urlEncoded && ['post', 'put'].contains(method)){
-			var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
-			this.headers['Content-type'] = 'application/x-www-form-urlencoded' + encoding;
-		}
-
-		if (!url) url = document.location.pathname;
-
-		var trimPosition = url.lastIndexOf('/');
-		if (trimPosition > -1 && (trimPosition = url.indexOf('#')) > -1) url = url.substr(0, trimPosition);
-
-		if (this.options.noCache)
-			url += (url.contains('?') ? '&' : '?') + String.uniqueID();
-
-		if (data && method == 'get'){
-			url += (url.contains('?') ? '&' : '?') + data;
-			data = null;
-		}
-
-		var xhr = this.xhr;
-		if (progressSupport){
-			xhr.onloadstart = this.loadstart.bind(this);
-			xhr.onprogress = this.progress.bind(this);
-		}
-
-		xhr.open(method.toUpperCase(), url, this.options.async, this.options.user, this.options.password);
-		if (this.options.user && 'withCredentials' in xhr) xhr.withCredentials = true;
-
-		xhr.onreadystatechange = this.onStateChange.bind(this);
-
-		Object.each(this.headers, function(value, key){
-			try {
-				xhr.setRequestHeader(key, value);
-			} catch (e){
-				this.fireEvent('exception', [key, value]);
-			}
-		}, this);
-
-		this.fireEvent('request');
-		xhr.send(data);
-		if (!this.options.async) this.onStateChange();
-		else if (this.options.timeout) this.timer = this.timeout.delay(this.options.timeout, this);
-		return this;
-	},
-
-	cancel: function(){
-		if (!this.running) return this;
-		this.running = false;
-		var xhr = this.xhr;
-		xhr.abort();
-		clearTimeout(this.timer);
-		xhr.onreadystatechange = empty;
-		if (progressSupport) xhr.onprogress = xhr.onloadstart = empty;
-		this.xhr = new Browser.Request();
-		this.fireEvent('cancel');
-		return this;
-	}
-
-});
-
-var methods = {};
-['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){
-	methods[method] = function(data){
-		var object = {
-			method: method
-		};
-		if (data != null) object.data = data;
-		return this.send(object);
-	};
-});
-
-Request.implement(methods);
-
-Element.Properties.send = {
-
-	set: function(options){
-		var send = this.get('send').cancel();
-		send.setOptions(options);
-		return this;
-	},
-
-	get: function(){
-		var send = this.retrieve('send');
-		if (!send){
-			send = new Request({
-				data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
-			});
-			this.store('send', send);
-		}
-		return send;
-	}
-
-};
-
-Element.implement({
-
-	send: function(url){
-		var sender = this.get('send');
-		sender.send({data: this, url: url || sender.options.url});
-		return this;
-	}
-
-});
-
-})();
-
-
-/*
----
-
-name: Request.HTML
-
-description: Extends the basic Request Class with additional methods for interacting with HTML responses.
-
-license: MIT-style license.
-
-requires: [Element, Request]
-
-provides: Request.HTML
-
-...
-*/
-
-Request.HTML = new Class({
-
-	Extends: Request,
-
-	options: {
-		update: false,
-		append: false,
-		evalScripts: true,
-		filter: false,
-		headers: {
-			Accept: 'text/html, application/xml, text/xml, */*'
-		}
-	},
-
-	success: function(text){
-		var options = this.options, response = this.response;
-
-		response.html = text.stripScripts(function(script){
-			response.javascript = script;
-		});
-
-		var match = response.html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
-		if (match) response.html = match[1];
-		var temp = new Element('div').set('html', response.html);
-
-		response.tree = temp.childNodes;
-		response.elements = temp.getElements(options.filter || '*');
-
-		if (options.filter) response.tree = response.elements;
-		if (options.update){
-			var update = document.id(options.update).empty();
-			if (options.filter) update.adopt(response.elements);
-			else update.set('html', response.html);
-		} else if (options.append){
-			var append = document.id(options.append);
-			if (options.filter) response.elements.reverse().inject(append);
-			else append.adopt(temp.getChildren());
-		}
-		if (options.evalScripts) Browser.exec(response.javascript);
-
-		this.onSuccess(response.tree, response.elements, response.html, response.javascript);
-	}
-
-});
-
-Element.Properties.load = {
-
-	set: function(options){
-		var load = this.get('load').cancel();
-		load.setOptions(options);
-		return this;
-	},
-
-	get: function(){
-		var load = this.retrieve('load');
-		if (!load){
-			load = new Request.HTML({data: this, link: 'cancel', update: this, method: 'get'});
-			this.store('load', load);
-		}
-		return load;
-	}
-
-};
-
-Element.implement({
-
-	load: function(){
-		this.get('load').send(Array.link(arguments, {data: Type.isObject, url: Type.isString}));
-		return this;
-	}
-
-});
-
-
-/*
----
-
-name: JSON
-
-description: JSON encoder and decoder.
-
-license: MIT-style license.
-
-SeeAlso: <http://www.json.org/>
-
-requires: [Array, String, Number, Function]
-
-provides: JSON
-
-...
-*/
-
-if (typeof JSON == 'undefined') this.JSON = {};
-
-//<1.2compat>
-
-JSON = new Hash({
-	stringify: JSON.stringify,
-	parse: JSON.parse
-});
-
-//</1.2compat>
-
-(function(){
-
-var special = {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'};
-
-var escape = function(chr){
-	return special[chr] || '\\u' + ('0000' + chr.charCodeAt(0).toString(16)).slice(-4);
-};
-
-JSON.validate = function(string){
-	string = string.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
-					replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
-					replace(/(?:^|:|,)(?:\s*\[)+/g, '');
-
-	return (/^[\],:{}\s]*$/).test(string);
-};
-
-JSON.encode = JSON.stringify ? function(obj){
-	return JSON.stringify(obj);
-} : function(obj){
-	if (obj && obj.toJSON) obj = obj.toJSON();
-
-	switch (typeOf(obj)){
-		case 'string':
-			return '"' + obj.replace(/[\x00-\x1f\\"]/g, escape) + '"';
-		case 'array':
-			return '[' + obj.map(JSON.encode).clean() + ']';
-		case 'object': case 'hash':
-			var string = [];
-			Object.each(obj, function(value, key){
-				var json = JSON.encode(value);
-				if (json) string.push(JSON.encode(key) + ':' + json);
-			});
-			return '{' + string + '}';
-		case 'number': case 'boolean': return '' + obj;
-		case 'null': return 'null';
-	}
-
-	return null;
-};
-
-JSON.decode = function(string, secure){
-	if (!string || typeOf(string) != 'string') return null;
-
-	if (secure || JSON.secure){
-		if (JSON.parse) return JSON.parse(string);
-		if (!JSON.validate(string)) throw new Error('JSON could not decode the input; security is enabled and the value is not secure.');
-	}
-
-	return eval('(' + string + ')');
-};
-
-})();
-
-
-/*
----
-
-name: Request.JSON
-
-description: Extends the basic Request Class with additional methods for sending and receiving JSON data.
-
-license: MIT-style license.
-
-requires: [Request, JSON]
-
-provides: Request.JSON
-
-...
-*/
-
-Request.JSON = new Class({
-
-	Extends: Request,
-
-	options: {
-		/*onError: function(text, error){},*/
-		secure: true
-	},
-
-	initialize: function(options){
-		this.parent(options);
-		Object.append(this.headers, {
-			'Accept': 'application/json',
-			'X-Request': 'JSON'
-		});
-	},
-
-	success: function(text){
-		var json;
-		try {
-			json = this.response.json = JSON.decode(text, this.options.secure);
-		} catch (error){
-			this.fireEvent('error', [text, error]);
-			return;
-		}
-		if (json == null) this.onFailure();
-		else this.onSuccess(json, text);
-	}
-
-});
-
-
-/*
----
-
-name: Cookie
-
-description: Class for creating, reading, and deleting browser Cookies.
-
-license: MIT-style license.
-
-credits:
-  - Based on the functions by Peter-Paul Koch (http://quirksmode.org).
-
-requires: [Options, Browser]
-
-provides: Cookie
-
-...
-*/
-
-var Cookie = new Class({
-
-	Implements: Options,
-
-	options: {
-		path: '/',
-		domain: false,
-		duration: false,
-		secure: false,
-		document: document,
-		encode: true
-	},
-
-	initialize: function(key, options){
-		this.key = key;
-		this.setOptions(options);
-	},
-
-	write: function(value){
-		if (this.options.encode) value = encodeURIComponent(value);
-		if (this.options.domain) value += '; domain=' + this.options.domain;
-		if (this.options.path) value += '; path=' + this.options.path;
-		if (this.options.duration){
-			var date = new Date();
-			date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
-			value += '; expires=' + date.toGMTString();
-		}
-		if (this.options.secure) value += '; secure';
-		this.options.document.cookie = this.key + '=' + value;
-		return this;
-	},
-
-	read: function(){
-		var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
-		return (value) ? decodeURIComponent(value[1]) : null;
-	},
-
-	dispose: function(){
-		new Cookie(this.key, Object.merge({}, this.options, {duration: -1})).write('');
-		return this;
-	}
-
-});
-
-Cookie.write = function(key, value, options){
-	return new Cookie(key, options).write(value);
-};
-
-Cookie.read = function(key){
-	return new Cookie(key).read();
-};
-
-Cookie.dispose = function(key, options){
-	return new Cookie(key, options).dispose();
-};
-
-
-/*
----
-
-name: DOMReady
-
-description: Contains the custom event domready.
-
-license: MIT-style license.
-
-requires: [Browser, Element, Element.Event]
-
-provides: [DOMReady, DomReady]
-
-...
-*/
-
-(function(window, document){
-
-var ready,
-	loaded,
-	checks = [],
-	shouldPoll,
-	timer,
-	testElement = document.createElement('div');
-
-var domready = function(){
-	clearTimeout(timer);
-	if (ready) return;
-	Browser.loaded = ready = true;
-	document.removeListener('DOMContentLoaded', domready).removeListener('readystatechange', check);
-
-	document.fireEvent('domready');
-	window.fireEvent('domready');
-};
-
-var check = function(){
-	for (var i = checks.length; i--;) if (checks[i]()){
-		domready();
-		return true;
-	}
-	return false;
-};
-
-var poll = function(){
-	clearTimeout(timer);
-	if (!check()) timer = setTimeout(poll, 10);
-};
-
-document.addListener('DOMContentLoaded', domready);
-
-/*<ltIE8>*/
-// doScroll technique by Diego Perini http://javascript.nwbox.com/IEContentLoaded/
-// testElement.doScroll() throws when the DOM is not ready, only in the top window
-var doScrollWorks = function(){
-	try {
-		testElement.doScroll();
-		return true;
-	} catch (e){}
-	return false;
-};
-// If doScroll works already, it can't be used to determine domready
-//   e.g. in an iframe
-if (testElement.doScroll && !doScrollWorks()){
-	checks.push(doScrollWorks);
-	shouldPoll = true;
-}
-/*</ltIE8>*/
-
-if (document.readyState) checks.push(function(){
-	var state = document.readyState;
-	return (state == 'loaded' || state == 'complete');
-});
-
-if ('onreadystatechange' in document) document.addListener('readystatechange', check);
-else shouldPoll = true;
-
-if (shouldPoll) poll();
-
-Element.Events.domready = {
-	onAdd: function(fn){
-		if (ready) fn.call(this);
-	}
-};
-
-// Make sure that domready fires before load
-Element.Events.load = {
-	base: 'load',
-	onAdd: function(fn){
-		if (loaded && this == window) fn.call(this);
-	},
-	condition: function(){
-		if (this == window){
-			domready();
-			delete Element.Events.load;
-		}
-		return true;
-	}
-};
-
-// This is based on the custom load event
-window.addEvent('load', function(){
-	loaded = true;
-});
-
-})(window, document);
-
-
-/*
----
-
-name: Swiff
-
-description: Wrapper for embedding SWF movies. Supports External Interface Communication.
-
-license: MIT-style license.
-
-credits:
-  - Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject.
-
-requires: [Options, Object, Element]
-
-provides: Swiff
-
-...
-*/
-
-(function(){
-
-var Swiff = this.Swiff = new Class({
-
-	Implements: Options,
-
-	options: {
-		id: null,
-		height: 1,
-		width: 1,
-		container: null,
-		properties: {},
-		params: {
-			quality: 'high',
-			allowScriptAccess: 'always',
-			wMode: 'window',
-			swLiveConnect: true
-		},
-		callBacks: {},
-		vars: {}
-	},
-
-	toElement: function(){
-		return this.object;
-	},
-
-	initialize: function(path, options){
-		this.instance = 'Swiff_' + String.uniqueID();
-
-		this.setOptions(options);
-		options = this.options;
-		var id = this.id = options.id || this.instance;
-		var container = document.id(options.container);
-
-		Swiff.CallBacks[this.instance] = {};
-
-		var params = options.params, vars = options.vars, callBacks = options.callBacks;
-		var properties = Object.append({height: options.height, width: options.width}, options.properties);
-
-		var self = this;
-
-		for (var callBack in callBacks){
-			Swiff.CallBacks[this.instance][callBack] = (function(option){
-				return function(){
-					return option.apply(self.object, arguments);
-				};
-			})(callBacks[callBack]);
-			vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack;
-		}
-
-		params.flashVars = Object.toQueryString(vars);
-		if (Browser.ie){
-			properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
-			params.movie = path;
-		} else {
-			properties.type = 'application/x-shockwave-flash';
-		}
-		properties.data = path;
-
-		var build = '<object id="' + id + '"';
-		for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
-		build += '>';
-		for (var param in params){
-			if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />';
-		}
-		build += '</object>';
-		this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild;
-	},
-
-	replaces: function(element){
-		element = document.id(element, true);
-		element.parentNode.replaceChild(this.toElement(), element);
-		return this;
-	},
-
-	inject: function(element){
-		document.id(element, true).appendChild(this.toElement());
-		return this;
-	},
-
-	remote: function(){
-		return Swiff.remote.apply(Swiff, [this.toElement()].append(arguments));
-	}
-
-});
-
-Swiff.CallBacks = {};
-
-Swiff.remote = function(obj, fn){
-	var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
-	return eval(rs);
-};
-
-})();
-
deleted file mode 100644
index 98ac4a54818a74ededaeed76adad802034071c41..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/js/src/jsapi-tests/binast/parser/tester/frameworks/underscore-1.5.js
+++ /dev/null
@@ -1,1276 +0,0 @@
-//     Underscore.js 1.5.2
-//     http://underscorejs.org
-//     (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
-//     Underscore may be freely distributed under the MIT license.
-
-(function() {
-
-  // Baseline setup
-  // --------------
-
-  // Establish the root object, `window` in the browser, or `exports` on the server.
-  var root = this;
-
-  // Save the previous value of the `_` variable.
-  var previousUnderscore = root._;
-
-  // Establish the object that gets returned to break out of a loop iteration.
-  var breaker = {};
-
-  // Save bytes in the minified (but not gzipped) version:
-  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
-
-  // Create quick reference variables for speed access to core prototypes.
-  var
-    push             = ArrayProto.push,
-    slice            = ArrayProto.slice,
-    concat           = ArrayProto.concat,
-    toString         = ObjProto.toString,
-    hasOwnProperty   = ObjProto.hasOwnProperty;
-
-  // All **ECMAScript 5** native function implementations that we hope to use
-  // are declared here.
-  var
-    nativeForEach      = ArrayProto.forEach,
-    nativeMap          = ArrayProto.map,
-    nativeReduce       = ArrayProto.reduce,
-    nativeReduceRight  = ArrayProto.reduceRight,
-    nativeFilter       = ArrayProto.filter,
-    nativeEvery        = ArrayProto.every,
-    nativeSome         = ArrayProto.some,
-    nativeIndexOf      = ArrayProto.indexOf,
-    nativeLastIndexOf  = ArrayProto.lastIndexOf,
-    nativeIsArray      = Array.isArray,
-    nativeKeys         = Object.keys,
-    nativeBind         = FuncProto.bind;
-
-  // Create a safe reference to the Underscore object for use below.
-  var _ = function(obj) {
-    if (obj instanceof _) return obj;
-    if (!(this instanceof _)) return new _(obj);
-    this._wrapped = obj;
-  };
-
-  // Export the Underscore object for **Node.js**, with
-  // backwards-compatibility for the old `require()` API. If we're in
-  // the browser, add `_` as a global object via a string identifier,
-  // for Closure Compiler "advanced" mode.
-  if (typeof exports !== 'undefined') {
-    if (typeof module !== 'undefined' && module.exports) {
-      exports = module.exports = _;
-    }
-    exports._ = _;
-  } else {
-    root._ = _;
-  }
-
-  // Current version.
-  _.VERSION = '1.5.2';
-
-  // Collection Functions
-  // --------------------
-
-  // The cornerstone, an `each` implementation, aka `forEach`.
-  // Handles objects with the built-in `forEach`, arrays, and raw objects.
-  // Delegates to **ECMAScript 5**'s native `forEach` if available.
-  var each = _.each = _.forEach = function(obj, iterator, context) {
-    if (obj == null) return;
-    if (nativeForEach && obj.forEach === nativeForEach) {
-      obj.forEach(iterator, context);
-    } else if (obj.length === +obj.length) {
-      for (var i = 0, length = obj.length; i < length; i++) {
-        if (iterator.call(context, obj[i], i, obj) === breaker) return;
-      }
-    } else {
-      var keys = _.keys(obj);
-      for (var i = 0, length = keys.length; i < length; i++) {
-        if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
-      }
-    }
-  };
-
-  // Return the results of applying the iterator to each element.
-  // Delegates to **ECMAScript 5**'s native `map` if available.
-  _.map = _.collect = function(obj, iterator, context) {
-    var results = [];
-    if (obj == null) return results;
-    if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
-    each(obj, function(value, index, list) {
-      results.push(iterator.call(context, value, index, list));
-    });
-    return results;
-  };
-
-  var reduceError = 'Reduce of empty array with no initial value';
-
-  // **Reduce** builds up a single result from a list of values, aka `inject`,
-  // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
-  _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
-    var initial = arguments.length > 2;
-    if (obj == null) obj = [];
-    if (nativeReduce && obj.reduce === nativeReduce) {
-      if (context) iterator = _.bind(iterator, context);
-      return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
-    }
-    each(obj, function(value, index, list) {
-      if (!initial) {
-        memo = value;
-        initial = true;
-      } else {
-        memo = iterator.call(context, memo, value, index, list);
-      }
-    });
-    if (!initial) throw new TypeError(reduceError);
-    return memo;
-  };
-
-  // The right-associative version of reduce, also known as `foldr`.
-  // Delegates to **ECMAScript 5**'s native `reduceRight` if available.
-  _.reduceRight = _.foldr = function(obj, iterator, memo, context) {
-    var initial = arguments.length > 2;
-    if (obj == null) obj = [];
-    if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
-      if (context) iterator = _.bind(iterator, context);
-      return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
-    }
-    var length = obj.length;
-    if (length !== +length) {
-      var keys = _.keys(obj);
-      length = keys.length;
-    }
-    each(obj, function(value, index, list) {
-      index = keys ? keys[--length] : --length;
-      if (!initial) {
-        memo = obj[index];
-        initial = true;
-      } else {
-        memo = iterator.call(context, memo, obj[index], index, list);
-      }
-    });
-    if (!initial) throw new TypeError(reduceError);
-    return memo;
-  };
-
-  // Return the first value which passes a truth test. Aliased as `detect`.
-  _.find = _.detect = function(obj, iterator, context) {
-    var result;
-    any(obj, function(value, index, list) {
-      if (iterator.call(context, value, index, list)) {
-        result = value;
-        return true;
-      }
-    });
-    return result;
-  };
-
-  // Return all the elements that pass a truth test.
-  // Delegates to **ECMAScript 5**'s native `filter` if available.
-  // Aliased as `select`.
-  _.filter = _.select = function(obj, iterator, context) {
-    var results = [];
-    if (obj == null) return results;
-    if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
-    each(obj, function(value, index, list) {
-      if (iterator.call(context, value, index, list)) results.push(value);
-    });
-    return results;
-  };
-
-  // Return all the elements for which a truth test fails.
-  _.reject = function(obj, iterator, context) {
-    return _.filter(obj, function(value, index, list) {
-      return !iterator.call(context, value, index, list);
-    }, context);
-  };
-
-  // Determine whether all of the elements match a truth test.
-  // Delegates to **ECMAScript 5**'s native `every` if available.
-  // Aliased as `all`.
-  _.every = _.all = function(obj, iterator, context) {
-    iterator || (iterator = _.identity);
-    var result = true;
-    if (obj == null) return result;
-    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
-    each(obj, function(value, index, list) {
-      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
-    });
-    return !!result;
-  };
-
-  // Determine if at least one element in the object matches a truth test.
-  // Delegates to **ECMAScript 5**'s native `some` if available.
-  // Aliased as `any`.
-  var any = _.some = _.any = function(obj, iterator, context) {
-    iterator || (iterator = _.identity);
-    var result = false;
-    if (obj == null) return result;
-    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
-    each(obj, function(value, index, list) {
-      if (result || (result = iterator.call(context, value, index, list))) return breaker;
-    });
-    return !!result;
-  };
-
-  // Determine if the array or object contains a given value (using `===`).
-  // Aliased as `include`.
-  _.contains = _.include = function(obj, target) {
-    if (obj == null) return false;
-    if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
-    return any(obj, function(value) {
-      return value === target;
-    });
-  };
-
-  // Invoke a method (with arguments) on every item in a collection.
-  _.invoke = function(obj, method) {
-    var args = slice.call(arguments, 2);
-    var isFunc = _.isFunction(method);
-    return _.map(obj, function(value) {
-      return (isFunc ? method : value[method]).apply(value, args);
-    });
-  };
-
-  // Convenience version of a common use case of `map`: fetching a property.
-  _.pluck = function(obj, key) {
-    return _.map(obj, function(value){ return value[key]; });
-  };
-
-  // Convenience version of a common use case of `filter`: selecting only objects
-  // containing specific `key:value` pairs.
-  _.where = function(obj, attrs, first) {
-    if (_.isEmpty(attrs)) return first ? void 0 : [];
-    return _[first ? 'find' : 'filter'](obj, function(value) {
-      for (var key in attrs) {
-        if (attrs[key] !== value[key]) return false;
-      }
-      return true;
-    });
-  };
-
-  // Convenience version of a common use case of `find`: getting the first object
-  // containing specific `key:value` pairs.
-  _.findWhere = function(obj, attrs) {
-    return _.where(obj, attrs, true);
-  };
-
-  // Return the maximum element or (element-based computation).
-  // Can't optimize arrays of integers longer than 65,535 elements.
-  // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
-  _.max = function(obj, iterator, context) {
-    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
-      return Math.max.apply(Math, obj);
-    }
-    if (!iterator && _.isEmpty(obj)) return -Infinity;
-    var result = {computed : -Infinity, value: -Infinity};
-    each(obj, function(value, index, list) {
-      var computed = iterator ? iterator.call(context, value, index, list) : value;
-      computed > result.computed && (result = {value : value, computed : computed});
-    });
-    return result.value;
-  };
-
-  // Return the minimum element (or element-based computation).
-  _.min = function(obj, iterator, context) {
-    if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
-      return Math.min.apply(Math, obj);
-    }
-    if (!iterator && _.isEmpty(obj)) return Infinity;
-    var result = {computed : Infinity, value: Infinity};
-    each(obj, function(value, index, list) {
-      var computed = iterator ? iterator.call(context, value, index, list) : value;
-      computed < result.computed && (result = {value : value, computed : computed});
-    });
-    return result.value;
-  };
-
-  // Shuffle an array, using the modern version of the 
-  // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
-  _.shuffle = function(obj) {
-    var rand;
-    var index = 0;
-    var shuffled = [];
-    each(obj, function(value) {
-      rand = _.random(index++);
-      shuffled[index - 1] = shuffled[rand];
-      shuffled[rand] = value;
-    });
-    return shuffled;
-  };
-
-  // Sample **n** random values from an array.
-  // If **n** is not specified, returns a single random element from the array.
-  // The internal `guard` argument allows it to work with `map`.
-  _.sample = function(obj, n, guard) {
-    if (arguments.length < 2 || guard) {
-      return obj[_.random(obj.length - 1)];
-    }
-    return _.shuffle(obj).slice(0, Math.max(0, n));
-  };
-
-  // An internal function to generate lookup iterators.
-  var lookupIterator = function(value) {
-    return _.isFunction(value) ? value : function(obj){ return obj[value]; };
-  };
-
-  // Sort the object's values by a criterion produced by an iterator.
-  _.sortBy = function(obj, value, context) {
-    var iterator = lookupIterator(value);
-    return _.pluck(_.map(obj, function(value, index, list) {
-      return {
-        value: value,
-        index: index,
-        criteria: iterator.call(context, value, index, list)
-      };
-    }).sort(function(left, right) {
-      var a = left.criteria;
-      var b = right.criteria;
-      if (a !== b) {
-        if (a > b || a === void 0) return 1;
-        if (a < b || b === void 0) return -1;
-      }
-      return left.index - right.index;
-    }), 'value');
-  };
-
-  // An internal function used for aggregate "group by" operations.
-  var group = function(behavior) {
-    return function(obj, value, context) {
-      var result = {};
-      var iterator = value == null ? _.identity : lookupIterator(value);
-      each(obj, function(value, index) {
-        var key = iterator.call(context, value, index, obj);
-        behavior(result, key, value);
-      });
-      return result;
-    };
-  };
-
-  // Groups the object's values by a criterion. Pass either a string attribute
-  // to group by, or a function that returns the criterion.
-  _.groupBy = group(function(result, key, value) {
-    (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
-  });
-
-  // Indexes the object's values by a criterion, similar to `groupBy`, but for
-  // when you know that your index values will be unique.
-  _.indexBy = group(function(result, key, value) {
-    result[key] = value;
-  });
-
-  // Counts instances of an object that group by a certain criterion. Pass
-  // either a string attribute to count by, or a function that returns the
-  // criterion.
-  _.countBy = group(function(result, key) {
-    _.has(result, key) ? result[key]++ : result[key] = 1;
-  });
-
-  // Use a comparator function to figure out the smallest index at which
-  // an object should be inserted so as to maintain order. Uses binary search.
-  _.sortedIndex = function(array, obj, iterator, context) {
-    iterator = iterator == null ? _.identity : lookupIterator(iterator);
-    var value = iterator.call(context, obj);
-    var low = 0, high = array.length;
-    while (low < high) {
-      var mid = (low + high) >>> 1;
-      iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
-    }
-    return low;
-  };
-
-  // Safely create a real, live array from anything iterable.
-  _.toArray = function(obj) {
-    if (!obj) return [];
-    if (_.isArray(obj)) return slice.call(obj);
-    if (obj.length === +obj.length) return _.map(obj, _.identity);
-    return _.values(obj);
-  };
-
-  // Return the number of elements in an object.
-  _.size = function(obj) {
-    if (obj == null) return 0;
-    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
-  };
-
-  // Array Functions
-  // ---------------
-
-  // Get the first element of an array. Passing **n** will return the first N
-  // values in the array. Aliased as `head` and `take`. The **guard** check
-  // allows it to work with `_.map`.
-  _.first = _.head = _.take = function(array, n, guard) {
-    if (array == null) return void 0;
-    return (n == null) || guard ? array[0] : slice.call(array, 0, n);
-  };
-
-  // Returns everything but the last entry of the array. Especially useful on
-  // the arguments object. Passing **n** will return all the values in
-  // the array, excluding the last N. The **guard** check allows it to work with
-  // `_.map`.
-  _.initial = function(array, n, guard) {
-    return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
-  };
-
-  // Get the last element of an array. Passing **n** will return the last N
-  // values in the array. The **guard** check allows it to work with `_.map`.
-  _.last = function(array, n, guard) {
-    if (array == null) return void 0;
-    if ((n == null) || guard) {
-      return array[array.length - 1];
-    } else {
-      return slice.call(array, Math.max(array.length - n, 0));
-    }
-  };
-
-  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
-  // Especially useful on the arguments object. Passing an **n** will return
-  // the rest N values in the array. The **guard**
-  // check allows it to work with `_.map`.
-  _.rest = _.tail = _.drop = function(array, n, guard) {
-    return slice.call(array, (n == null) || guard ? 1 : n);
-  };
-
-  // Trim out all falsy values from an array.
-  _.compact = function(array) {
-    return _.filter(array, _.identity);
-  };
-
-  // Internal implementation of a recursive `flatten` function.
-  var flatten = function(input, shallow, output) {
-    if (shallow && _.every(input, _.isArray)) {
-      return concat.apply(output, input);
-    }
-    each(input, function(value) {
-      if (_.isArray(value) || _.isArguments(value)) {
-        shallow ? push.apply(output, value) : flatten(value, shallow, output);
-      } else {
-        output.push(value);
-      }
-    });
-    return output;
-  };
-
-  // Flatten out an array, either recursively (by default), or just one level.
-  _.flatten = function(array, shallow) {
-    return flatten(array, shallow, []);
-  };
-
-  // Return a version of the array that does not contain the specified value(s).
-  _.without = function(array) {
-    return _.difference(array, slice.call(arguments, 1));
-  };
-
-  // Produce a duplicate-free version of the array. If the array has already
-  // been sorted, you have the option of using a faster algorithm.
-  // Aliased as `unique`.
-  _.uniq = _.unique = function(array, isSorted, iterator, context) {
-    if (_.isFunction(isSorted)) {
-      context = iterator;
-      iterator = isSorted;
-      isSorted = false;
-    }
-    var initial = iterator ? _.map(array, iterator, context) : array;
-    var results = [];
-    var seen = [];
-    each(initial, function(value, index) {
-      if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
-        seen.push(value);
-        results.push(array[index]);
-      }
-    });
-    return results;
-  };
-
-  // Produce an array that contains the union: each distinct element from all of
-  // the passed-in arrays.
-  _.union = function() {
-    return _.uniq(_.flatten(arguments, true));
-  };
-
-  // Produce an array that contains every item shared between all the
-  // passed-in arrays.
-  _.intersection = function(array) {
-    var rest = slice.call(arguments, 1);
-    return _.filter(_.uniq(array), function(item) {
-      return _.every(rest, function(other) {
-        return _.indexOf(other, item) >= 0;
-      });
-    });
-  };
-
-  // Take the difference between one array and a number of other arrays.
-  // Only the elements present in just the first array will remain.
-  _.difference = function(array) {
-    var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
-    return _.filter(array, function(value){ return !_.contains(rest, value); });
-  };
-
-  // Zip together multiple lists into a single array -- elements that share
-  // an index go together.
-  _.zip = function() {
-    var length = _.max(_.pluck(arguments, "length").concat(0));
-    var results = new Array(length);
-    for (var i = 0; i < length; i++) {
-      results[i] = _.pluck(arguments, '' + i);
-    }
-    return results;
-  };
-
-  // Converts lists into objects. Pass either a single array of `[key, value]`
-  // pairs, or two parallel arrays of the same length -- one of keys, and one of
-  // the corresponding values.
-  _.object = function(list, values) {
-    if (list == null) return {};
-    var result = {};
-    for (var i = 0, length = list.length; i < length; i++) {
-      if (values) {
-        result[list[i]] = values[i];
-      } else {
-        result[list[i][0]] = list[i][1];
-      }
-    }
-    return result;
-  };
-
-  // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
-  // we need this function. Return the position of the first occurrence of an
-  // item in an array, or -1 if the item is not included in the array.
-  // Delegates to **ECMAScript 5**'s native `indexOf` if available.
-  // If the array is large and already in sort order, pass `true`
-  // for **isSorted** to use binary search.
-  _.indexOf = function(array, item, isSorted) {
-    if (array == null) return -1;
-    var i = 0, length = array.length;
-    if (isSorted) {
-      if (typeof isSorted == 'number') {
-        i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
-      } else {
-        i = _.sortedIndex(array, item);
-        return array[i] === item ? i : -1;
-      }
-    }
-    if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
-    for (; i < length; i++) if (array[i] === item) return i;
-    return -1;
-  };
-
-  // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
-  _.lastIndexOf = function(array, item, from) {
-    if (array == null) return -1;
-    var hasIndex = from != null;
-    if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
-      return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
-    }
-    var i = (hasIndex ? from : array.length);
-    while (i--) if (array[i] === item) return i;
-    return -1;
-  };
-
-  // Generate an integer Array containing an arithmetic progression. A port of
-  // the native Python `range()` function. See
-  // [the Python documentation](http://docs.python.org/library/functions.html#range).
-  _.range = function(start, stop, step) {
-    if (arguments.length <= 1) {
-      stop = start || 0;
-      start = 0;
-    }
-    step = arguments[2] || 1;
-
-    var length = Math.max(Math.ceil((stop - start) / step), 0);
-    var idx = 0;
-    var range = new Array(length);
-
-    while(idx < length) {
-      range[idx++] = start;
-      start += step;
-    }
-
-    return range;
-  };
-
-  // Function (ahem) Functions
-  // ------------------
-
-  // Reusable constructor function for prototype setting.
-  var ctor = function(){};
-
-  // Create a function bound to a given object (assigning `this`, and arguments,
-  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
-  // available.
-  _.bind = function(func, context) {
-    var args, bound;
-    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
-    if (!_.isFunction(func)) throw new TypeError;
-    args = slice.call(arguments, 2);
-    return bound = function() {
-      if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
-      ctor.prototype = func.prototype;
-      var self = new ctor;
-      ctor.prototype = null;
-      var result = func.apply(self, args.concat(slice.call(arguments)));
-      if (Object(result) === result) return result;
-      return self;
-    };
-  };
-
-  // Partially apply a function by creating a version that has had some of its
-  // arguments pre-filled, without changing its dynamic `this` context.
-  _.partial = function(func) {
-    var args = slice.call(arguments, 1);
-    return function() {
-      return func.apply(this, args.concat(slice.call(arguments)));
-    };
-  };
-
-  // Bind all of an object's methods to that object. Useful for ensuring that
-  // all callbacks defined on an object belong to it.
-  _.bindAll = function(obj) {
-    var funcs = slice.call(arguments, 1);
-    if (funcs.length === 0) throw new Error("bindAll must be passed function names");
-    each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
-    return obj;
-  };
-
-  // Memoize an expensive function by storing its results.
-  _.memoize = function(func, hasher) {
-    var memo = {};
-    hasher || (hasher = _.identity);
-    return function() {
-      var key = hasher.apply(this, arguments);
-      return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
-    };
-  };
-
-  // Delays a function for the given number of milliseconds, and then calls
-  // it with the arguments supplied.
-  _.delay = function(func, wait) {
-    var args = slice.call(arguments, 2);
-    return setTimeout(function(){ return func.apply(null, args); }, wait);
-  };
-
-  // Defers a function, scheduling it to run after the current call stack has
-  // cleared.
-  _.defer = function(func) {
-    return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
-  };
-
-  // Returns a function, that, when invoked, will only be triggered at most once
-  // during a given window of time. Normally, the throttled function will run
-  // as much as it can, without ever going more than once per `wait` duration;
-  // but if you'd like to disable the execution on the leading edge, pass
-  // `{leading: false}`. To disable execution on the trailing edge, ditto.
-  _.throttle = function(func, wait, options) {
-    var context, args, result;
-    var timeout = null;
-    var previous = 0;
-    options || (options = {});
-    var later = function() {
-      previous = options.leading === false ? 0 : new Date;
-      timeout = null;
-      result = func.apply(context, args);
-    };
-    return function() {
-      var now = new Date;
-      if (!previous && options.leading === false) previous = now;
-      var remaining = wait - (now - previous);
-      context = this;
-      args = arguments;
-      if (remaining <= 0) {
-        clearTimeout(timeout);
-        timeout = null;
-        previous = now;
-        result = func.apply(context, args);
-      } else if (!timeout && options.trailing !== false) {
-        timeout = setTimeout(later, remaining);
-      }
-      return result;
-    };
-  };
-
-  // Returns a function, that, as long as it continues to be invoked, will not
-  // be triggered. The function will be called after it stops being called for
-  // N milliseconds. If `immediate` is passed, trigger the function on the
-  // leading edge, instead of the trailing.
-  _.debounce = function(func, wait, immediate) {
-    var timeout, args, context, timestamp, result;
-    return function() {
-      context = this;
-      args = arguments;
-      timestamp = new Date();
-      var later = function() {
-        var last = (new Date()) - timestamp;
-        if (last < wait) {
-          timeout = setTimeout(later, wait - last);
-        } else {
-          timeout = null;
-          if (!immediate) result = func.apply(context, args);
-        }
-      };
-      var callNow = immediate && !timeout;
-      if (!timeout) {
-        timeout = setTimeout(later, wait);
-      }
-      if (callNow) result = func.apply(context, args);
-      return result;
-    };
-  };
-
-  // Returns a function that will be executed at most one time, no matter how
-  // often you call it. Useful for lazy initialization.
-  _.once = function(func) {
-    var ran = false, memo;
-    return function() {
-      if (ran) return memo;
-      ran = true;
-      memo = func.apply(this, arguments);
-      func = null;
-      return memo;
-    };
-  };
-
-  // Returns the first function passed as an argument to the second,
-  // allowing you to adjust arguments, run code before and after, and
-  // conditionally execute the original function.
-  _.wrap = function(func, wrapper) {
-    return function() {
-      var args = [func];
-      push.apply(args, arguments);
-      return wrapper.apply(this, args);
-    };
-  };
-
-  // Returns a function that is the composition of a list of functions, each
-  // consuming the return value of the function that follows.
-  _.compose = function() {
-    var funcs = arguments;
-    return function() {
-      var args = arguments;
-      for (var i = funcs.length - 1; i >= 0; i--) {
-        args = [funcs[i].apply(this, args)];
-      }
-      return args[0];
-    };
-  };
-
-  // Returns a function that will only be executed after being called N times.
-  _.after = function(times, func) {
-    return function() {
-      if (--times < 1) {
-        return func.apply(this, arguments);
-      }
-    };
-  };
-
-  // Object Functions
-  // ----------------
-
-  // Retrieve the names of an object's properties.
-  // Delegates to **ECMAScript 5**'s native `Object.keys`
-  _.keys = nativeKeys || function(obj) {
-    if (obj !== Object(obj)) throw new TypeError('Invalid object');
-    var keys = [];
-    for (var key in obj) if (_.has(obj, key)) keys.push(key);
-    return keys;
-  };
-
-  // Retrieve the values of an object's properties.
-  _.values = function(obj) {
-    var keys = _.keys(obj);
-    var length = keys.length;
-    var values = new Array(length);
-    for (var i = 0; i < length; i++) {
-      values[i] = obj[keys[i]];
-    }
-    return values;
-  };
-
-  // Convert an object into a list of `[key, value]` pairs.
-  _.pairs = function(obj) {
-    var keys = _.keys(obj);
-    var length = keys.length;
-    var pairs = new Array(length);
-    for (var i = 0; i < length; i++) {
-      pairs[i] = [keys[i], obj[keys[i]]];
-    }
-    return pairs;
-  };
-
-  // Invert the keys and values of an object. The values must be serializable.
-  _.invert = function(obj) {
-    var result = {};
-    var keys = _.keys(obj);
-    for (var i = 0, length = keys.length; i < length; i++) {
-      result[obj[keys[i]]] = keys[i];
-    }
-    return result;
-  };
-
-  // Return a sorted list of the function names available on the object.
-  // Aliased as `methods`
-  _.functions = _.methods = function(obj) {
-    var names = [];
-    for (var key in obj) {
-      if (_.isFunction(obj[key])) names.push(key);
-    }
-    return names.sort();
-  };
-
-  // Extend a given object with all the properties in passed-in object(s).
-  _.extend = function(obj) {
-    each(slice.call(arguments, 1), function(source) {
-      if (source) {
-        for (var prop in source) {
-          obj[prop] = source[prop];
-        }
-      }
-    });
-    return obj;
-  };
-
-  // Return a copy of the object only containing the whitelisted properties.
-  _.pick = function(obj) {
-    var copy = {};
-    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
-    each(keys, function(key) {
-      if (key in obj) copy[key] = obj[key];
-    });
-    return copy;
-  };
-
-   // Return a copy of the object without the blacklisted properties.
-  _.omit = function(obj) {
-    var copy = {};
-    var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
-    for (var key in obj) {
-      if (!_.contains(keys, key)) copy[key] = obj[key];
-    }
-    return copy;
-  };
-
-  // Fill in a given object with default properties.
-  _.defaults = function(obj) {
-    each(slice.call(arguments, 1), function(source) {
-      if (source) {
-        for (var prop in source) {
-          if (obj[prop] === void 0) obj[prop] = source[prop];
-        }
-      }
-    });
-    return obj;
-  };
-
-  // Create a (shallow-cloned) duplicate of an object.
-  _.clone = function(obj) {
-    if (!_.isObject(obj)) return obj;
-    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
-  };
-
-  // Invokes interceptor with the obj, and then returns obj.
-  // The primary purpose of this method is to "tap into" a method chain, in
-  // order to perform operations on intermediate results within the chain.
-  _.tap = function(obj, interceptor) {
-    interceptor(obj);
-    return obj;
-  };
-
-  // Internal recursive comparison function for `isEqual`.
-  var eq = function(a, b, aStack, bStack) {
-    // Identical objects are equal. `0 === -0`, but they aren't identical.
-    // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
-    if (a === b) return a !== 0 || 1 / a == 1 / b;
-    // A strict comparison is necessary because `null == undefined`.
-    if (a == null || b == null) return a === b;
-    // Unwrap any wrapped objects.
-    if (a instanceof _) a = a._wrapped;
-    if (b instanceof _) b = b._wrapped;
-    // Compare `[[Class]]` names.
-    var className = toString.call(a);
-    if (className != toString.call(b)) return false;
-    switch (className) {
-      // Strings, numbers, dates, and booleans are compared by value.
-      case '[object String]':
-        // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
-        // equivalent to `new String("5")`.
-        return a == String(b);
-      case '[object Number]':
-        // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
-        // other numeric values.
-        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
-      case '[object Date]':
-      case '[object Boolean]':
-        // Coerce dates and booleans to numeric primitive values. Dates are compared by their
-        // millisecond representations. Note that invalid dates with millisecond representations
-        // of `NaN` are not equivalent.
-        return +a == +b;
-      // RegExps are compared by their source patterns and flags.
-      case '[object RegExp]':
-        return a.source == b.source &&
-               a.global == b.global &&
-               a.multiline == b.multiline &&
-               a.ignoreCase == b.ignoreCase;
-    }
-    if (typeof a != 'object' || typeof b != 'object') return false;
-    // Assume equality for cyclic structures. The algorithm for detecting cyclic
-    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
-    var length = aStack.length;
-    while (length--) {
-      // Linear search. Performance is inversely proportional to the number of
-      // unique nested structures.
-      if (aStack[length] == a) return bStack[length] == b;
-    }
-    // Objects with different constructors are not equivalent, but `Object`s
-    // from different frames are.
-    var aCtor = a.constructor, bCtor = b.constructor;
-    if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
-                             _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
-      return false;
-    }
-    // Add the first object to the stack of traversed objects.
-    aStack.push(a);
-    bStack.push(b);
-    var size = 0, result = true;
-    // Recursively compare objects and arrays.
-    if (className == '[object Array]') {
-      // Compare array lengths to determine if a deep comparison is necessary.
-      size = a.length;
-      result = size == b.length;
-      if (result) {
-        // Deep compare the contents, ignoring non-numeric properties.
-        while (size--) {
-          if (!(result = eq(a[size], b[size], aStack, bStack))) break;
-        }
-      }
-    } else {
-      // Deep compare objects.
-      for (var key in a) {
-        if (_.has(a, key)) {
-          // Count the expected number of properties.
-          size++;
-          // Deep compare each member.
-          if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
-        }
-      }
-      // Ensure that both objects contain the same number of properties.
-      if (result) {
-        for (key in b) {
-          if (_.has(b, key) && !(size--)) break;
-        }
-        result = !size;
-      }
-    }
-    // Remove the first object from the stack of traversed objects.
-    aStack.pop();
-    bStack.pop();
-    return result;
-  };
-
-  // Perform a deep comparison to check if two objects are equal.
-  _.isEqual = function(a, b) {
-    return eq(a, b, [], []);
-  };
-
-  // Is a given array, string, or object empty?
-  // An "empty" object has no enumerable own-properties.
-  _.isEmpty = function(obj) {
-    if (obj == null) return true;
-    if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
-    for (var key in obj) if (_.has(obj, key)) return false;
-    return true;
-  };
-
-  // Is a given value a DOM element?
-  _.isElement = function(obj) {
-    return !!(obj && obj.nodeType === 1);
-  };
-
-  // Is a given value an array?
-  // Delegates to ECMA5's native Array.isArray
-  _.isArray = nativeIsArray || function(obj) {
-    return toString.call(obj) == '[object Array]';
-  };
-
-  // Is a given variable an object?
-  _.isObject = function(obj) {
-    return obj === Object(obj);
-  };
-
-  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
-  each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
-    _['is' + name] = function(obj) {
-      return toString.call(obj) == '[object ' + name + ']';
-    };
-  });
-
-  // Define a fallback version of the method in browsers (ahem, IE), where
-  // there isn't any inspectable "Arguments" type.
-  if (!_.isArguments(arguments)) {
-    _.isArguments = function(obj) {
-      return !!(obj && _.has(obj, 'callee'));
-    };
-  }
-
-  // Optimize `isFunction` if appropriate.
-  if (typeof (/./) !== 'function') {
-    _.isFunction = function(obj) {
-      return typeof obj === 'function';
-    };
-  }
-
-  // Is a given object a finite number?
-  _.isFinite = function(obj) {
-    return isFinite(obj) && !isNaN(parseFloat(obj));
-  };
-
-  // Is the given value `NaN`? (NaN is the only number which does not equal itself).
-  _.isNaN = function(obj) {
-    return _.isNumber(obj) && obj != +obj;
-  };
-
-  // Is a given value a boolean?
-  _.isBoolean = function(obj) {
-    return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
-  };
-
-  // Is a given value equal to null?
-  _.isNull = function(obj) {
-    return obj === null;
-  };
-
-  // Is a given variable undefined?
-  _.isUndefined = function(obj) {
-    return obj === void 0;
-  };
-
-  // Shortcut function for checking if an object has a given property directly
-  // on itself (in other words, not on a prototype).
-  _.has = function(obj, key) {
-    return hasOwnProperty.call(obj, key);
-  };
-
-  // Utility Functions
-  // -----------------
-
-  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
-  // previous owner. Returns a reference to the Underscore object.
-  _.noConflict = function() {
-    root._ = previousUnderscore;
-    return this;
-  };
-
-  // Keep the identity function around for default iterators.
-  _.identity = function(value) {
-    return value;
-  };
-
-  // Run a function **n** times.
-  _.times = function(n, iterator, context) {
-    var accum = Array(Math.max(0, n));
-    for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i);
-    return accum;
-  };
-
-  // Return a random integer between min and max (inclusive).
-  _.random = function(min, max) {
-    if (max == null) {
-      max = min;
-      min = 0;
-    }
-    return min + Math.floor(Math.random() * (max - min + 1));
-  };
-
-  // List of HTML entities for escaping.
-  var entityMap = {
-    escape: {
-      '&': '&amp;',
-      '<': '&lt;',
-      '>': '&gt;',
-      '"': '&quot;',
-      "'": '&#x27;'
-    }
-  };
-  entityMap.unescape = _.invert(entityMap.escape);
-
-  // Regexes containing the keys and values listed immediately above.
-  var entityRegexes = {
-    escape:   new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
-    unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
-  };
-
-  // Functions for escaping and unescaping strings to/from HTML interpolation.
-  _.each(['escape', 'unescape'], function(method) {
-    _[method] = function(string) {
-      if (string == null) return '';
-      return ('' + string).replace(entityRegexes[method], function(match) {
-        return entityMap[method][match];
-      });
-    };
-  });
-
-  // If the value of the named `property` is a function then invoke it with the
-  // `object` as context; otherwise, return it.
-  _.result = function(object, property) {
-    if (object == null) return void 0;
-    var value = object[property];
-    return _.isFunction(value) ? value.call(object) : value;
-  };
-
-  // Add your own custom functions to the Underscore object.
-  _.mixin = function(obj) {
-    each(_.functions(obj), function(name) {
-      var func = _[name] = obj[name];
-      _.prototype[name] = function() {
-        var args = [this._wrapped];
-        push.apply(args, arguments);
-        return result.call(this, func.apply(_, args));
-      };
-    });
-  };
-
-  // Generate a unique integer id (unique within the entire client session).
-  // Useful for temporary DOM ids.
-  var idCounter = 0;
-  _.uniqueId = function(prefix) {
-    var id = ++idCounter + '';
-    return prefix ? prefix + id : id;
-  };
-
-  // By default, Underscore uses ERB-style template delimiters, change the
-  // following template settings to use alternative delimiters.
-  _.templateSettings = {
-    evaluate    : /<%([\s\S]+?)%>/g,
-    interpolate : /<%=([\s\S]+?)%>/g,
-    escape      : /<%-([\s\S]+?)%>/g
-  };
-
-  // When customizing `templateSettings`, if you don't want to define an
-  // interpolation, evaluation or escaping regex, we need one that is
-  // guaranteed not to match.
-  var noMatch = /(.)^/;
-
-  // Certain characters need to be escaped so that they can be put into a
-  // string literal.
-  var escapes = {
-    "'":      "'",
-    '\\':     '\\',
-    '\r':     'r',
-    '\n':     'n',
-    '\t':     't',
-    '\u2028': 'u2028',
-    '\u2029': 'u2029'
-  };
-
-  var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
-
-  // JavaScript micro-templating, similar to John Resig's implementation.
-  // Underscore templating handles arbitrary delimiters, preserves whitespace,
-  // and correctly escapes quotes within interpolated code.
-  _.template = function(text, data, settings) {
-    var render;
-    settings = _.defaults({}, settings, _.templateSettings);
-
-    // Combine delimiters into one regular expression via alternation.
-    var matcher = new RegExp([
-      (settings.escape || noMatch).source,
-      (settings.interpolate || noMatch).source,
-      (settings.evaluate || noMatch).source
-    ].join('|') + '|$', 'g');
-
-    // Compile the template source, escaping string literals appropriately.
-    var index = 0;
-    var source = "__p+='";
-    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
-      source += text.slice(index, offset)
-        .replace(escaper, function(match) { return '\\' + escapes[match]; });
-
-      if (escape) {
-        source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
-      }
-      if (interpolate) {
-        source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
-      }
-      if (evaluate) {
-        source += "';\n" + evaluate + "\n__p+='";
-      }
-      index = offset + match.length;
-      return match;
-    });
-    source += "';\n";
-
-    // If a variable is not specified, place data values in local scope.
-    if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
-
-    source = "var __t,__p='',__j=Array.prototype.join," +
-      "print=function(){__p+=__j.call(arguments,'');};\n" +
-      source + "return __p;\n";
-
-    try {
-      render = new Function(settings.variable || 'obj', '_', source);
-    } catch (e) {
-      e.source = source;
-      throw e;
-    }
-
-    if (data) return render(data, _);
-    var template = function(data) {
-      return render.call(this, data, _);
-    };
-
-    // Provide the compiled function source as a convenience for precompilation.
-    template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
-
-    return template;
-  };
-
-  // Add a "chain" function, which will delegate to the wrapper.
-  _.chain = function(obj) {
-    return _(obj).chain();
-  };
-
-  // OOP
-  // ---------------
-  // If Underscore is called as a function, it returns a wrapped object that
-  // can be used OO-style. This wrapper holds altered versions of all the
-  // underscore functions. Wrapped objects may be chained.
-
-  // Helper function to continue chaining intermediate results.
-  var result = function(obj) {
-    return this._chain ? _(obj).chain() : obj;
-  };
-
-  // Add all of the Underscore functions to the wrapper object.
-  _.mixin(_);
-
-  // Add all mutator Array functions to the wrapper.
-  each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
-    var method = ArrayProto[name];
-    _.prototype[name] = function() {
-      var obj = this._wrapped;
-      method.apply(obj, arguments);
-      if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
-      return result.call(this, obj);
-    };
-  });
-
-  // Add all accessor Array functions to the wrapper.
-  each(['concat', 'join', 'slice'], function(name) {
-    var method = ArrayProto[name];
-    _.prototype[name] = function() {
-      return result.call(this, method.apply(this._wrapped, arguments));
-    };
-  });
-
-  _.extend(_.prototype, {
-
-    // Start chaining a wrapped Underscore object.
-    chain: function() {
-      this._chain = true;
-      return this;
-    },
-
-    // Extracts the result from a wrapped and chained object.
-    value: function() {
-      return this._wrapped;
-    }
-
-  });
-
-}).call(this);
deleted file mode 100644
index da1ed9f2c90797cd9cbd5739247d23d93f617816..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/js/src/jsapi-tests/binast/parser/tester/frameworks/yui-3.12.js
+++ /dev/null
@@ -1,11542 +0,0 @@
-/*
-YUI 3.12.0 (build 8655935)
-Copyright 2013 Yahoo! Inc. All rights reserved.
-Licensed under the BSD License.
-http://yuilibrary.com/license/
-*/
-
-/**
-The YUI module contains the components required for building the YUI seed file.
-This includes the script loading mechanism, a simple queue, and the core
-utilities for the library.
-
-@module yui
-@main yui
-@submodule yui-base
-**/
-
-/*jshint eqeqeq: false*/
-if (typeof YUI != 'undefined') {
-    YUI._YUI = YUI;
-}
-
-/**
-The YUI global namespace object. This is the constructor for all YUI instances.
-
-This is a self-instantiable factory function, meaning you don't need to precede
-it with the `new` operator. You can invoke it directly like this:
-
-    YUI().use('*', function (Y) {
-        // Y is a new YUI instance.
-    });
-
-But it also works like this:
-
-    var Y = YUI();
-
-The `YUI` constructor accepts an optional config object, like this:
-
-    YUI({
-        debug: true,
-        combine: false
-    }).use('node', function (Y) {
-        // Y.Node is ready to use.
-    });
-
-See the API docs for the <a href="config.html">Config</a> class for the complete
-list of supported configuration properties accepted by the YUI constuctor.
-
-If a global `YUI` object is already defined, the existing YUI object will not be
-overwritten, to ensure that defined namespaces are preserved.
-
-Each YUI instance has full custom event support, but only if the event system is
-available.
-
-@class YUI
-@uses EventTarget
-@constructor
-@global
-@param {Object} [config]* Zero or more optional configuration objects. Config
-    values are stored in the `Y.config` property. See the
-    <a href="config.html">Config</a> docs for the list of supported properties.
-**/
-
-    /*global YUI*/
-    /*global YUI_config*/
-    var YUI = function() {
-        var i = 0,
-            Y = this,
-            args = arguments,
-            l = args.length,
-            instanceOf = function(o, type) {
-                return (o && o.hasOwnProperty && (o instanceof type));
-            },
-            gconf = (typeof YUI_config !== 'undefined') && YUI_config;
-
-        if (!(instanceOf(Y, YUI))) {
-            Y = new YUI();
-        } else {
-            // set up the core environment
-            Y._init();
-
-            /**
-            Master configuration that might span multiple contexts in a non-
-            browser environment. It is applied first to all instances in all
-            contexts.
-
-            @example
-
-                YUI.GlobalConfig = {
-                    filter: 'debug'
-                };
-
-                YUI().use('node', function (Y) {
-                    // debug files used here
-                });
-
-                YUI({
-                    filter: 'min'
-                }).use('node', function (Y) {
-                    // min files used here
-                });
-
-            @property {Object} GlobalConfig
-            @global
-            @static
-            **/
-            if (YUI.GlobalConfig) {
-                Y.applyConfig(YUI.GlobalConfig);
-            }
-
-            /**
-            Page-level config applied to all YUI instances created on the
-            current page. This is applied after `YUI.GlobalConfig` and before
-            any instance-level configuration.
-
-            @example
-
-                // Single global var to include before YUI seed file
-                YUI_config = {
-                    filter: 'debug'
-                };
-
-                YUI().use('node', function (Y) {
-                    // debug files used here
-                });
-
-                YUI({
-                    filter: 'min'
-                }).use('node', function (Y) {
-                    // min files used here
-                });
-
-            @property {Object} YUI_config
-            @global
-            **/
-            if (gconf) {
-                Y.applyConfig(gconf);
-            }
-
-            // bind the specified additional modules for this instance
-            if (!l) {
-                Y._setup();
-            }
-        }
-
-        if (l) {
-            // Each instance can accept one or more configuration objects.
-            // These are applied after YUI.GlobalConfig and YUI_Config,
-            // overriding values set in those config files if there is a
-            // matching property.
-            for (; i < l; i++) {
-                Y.applyConfig(args[i]);
-            }
-
-            Y._setup();
-        }
-
-        Y.instanceOf = instanceOf;
-
-        return Y;
-    };
-
-(function() {
-
-    var proto, prop,
-        VERSION = '3.12.0',
-        PERIOD = '.',
-        BASE = 'http://yui.yahooapis.com/',
-        /*
-            These CSS class names can't be generated by
-            getClassName since it is not available at the
-            time they are being used.
-        */
-        DOC_LABEL = 'yui3-js-enabled',
-        CSS_STAMP_EL = 'yui3-css-stamp',
-        NOOP = function() {},
-        SLICE = Array.prototype.slice,
-        APPLY_TO_AUTH = { 'io.xdrReady': 1,   // the functions applyTo
-                          'io.xdrResponse': 1,   // can call. this should
-                          'SWF.eventHandler': 1 }, // be done at build time
-        hasWin = (typeof window != 'undefined'),
-        win = (hasWin) ? window : null,
-        doc = (hasWin) ? win.document : null,
-        docEl = doc && doc.documentElement,
-        docClass = docEl && docEl.className,
-        instances = {},
-        time = new Date().getTime(),
-        add = function(el, type, fn, capture) {
-            if (el && el.addEventListener) {
-                el.addEventListener(type, fn, capture);
-            } else if (el && el.attachEvent) {
-                el.attachEvent('on' + type, fn);
-            }
-        },
-        remove = function(el, type, fn, capture) {
-            if (el && el.removeEventListener) {
-                // this can throw an uncaught exception in FF
-                try {
-                    el.removeEventListener(type, fn, capture);
-                } catch (ex) {}
-            } else if (el && el.detachEvent) {
-                el.detachEvent('on' + type, fn);
-            }
-        },
-        handleLoad = function() {
-            YUI.Env.windowLoaded = true;
-            YUI.Env.DOMReady = true;
-            if (hasWin) {
-                remove(window, 'load', handleLoad);
-            }
-        },
-        getLoader = function(Y, o) {
-            var loader = Y.Env._loader,
-                lCore = [ 'loader-base' ],
-                G_ENV = YUI.Env,
-                mods = G_ENV.mods;
-
-            if (loader) {
-                //loader._config(Y.config);
-                loader.ignoreRegistered = false;
-                loader.onEnd = null;
-                loader.data = null;
-                loader.required = [];
-                loader.loadType = null;
-            } else {
-                loader = new Y.Loader(Y.config);
-                Y.Env._loader = loader;
-            }
-            if (mods && mods.loader) {
-                lCore = [].concat(lCore, YUI.Env.loaderExtras);
-            }
-            YUI.Env.core = Y.Array.dedupe([].concat(YUI.Env.core, lCore));
-
-            return loader;
-        },
-
-        clobber = function(r, s) {
-            for (var i in s) {
-                if (s.hasOwnProperty(i)) {
-                    r[i] = s[i];
-                }
-            }
-        },
-
-        ALREADY_DONE = { success: true };
-
-//  Stamp the documentElement (HTML) with a class of "yui-loaded" to
-//  enable styles that need to key off of JS being enabled.
-if (docEl && docClass.indexOf(DOC_LABEL) == -1) {
-    if (docClass) {
-        docClass += ' ';
-    }
-    docClass += DOC_LABEL;
-    docEl.className = docClass;
-}
-
-if (VERSION.indexOf('@') > -1) {
-    VERSION = '3.5.0'; // dev time hack for cdn test
-}
-
-proto = {
-    /**
-    Applies a new configuration object to the config of this YUI instance. This
-    will merge new group/module definitions, and will also update the loader
-    cache if necessary. Updating `Y.config` directly will not update the cache.
-
-    @method applyConfig
-    @param {Object} o the configuration object.
-    @since 3.2.0
-    **/
-    applyConfig: function(o) {
-
-        o = o || NOOP;
-
-        var attr,
-            name,
-            // detail,
-            config = this.config,
-            mods = config.modules,
-            groups = config.groups,
-            aliases = config.aliases,
-            loader = this.Env._loader;
-
-        for (name in o) {
-            if (o.hasOwnProperty(name)) {
-                attr = o[name];
-                if (mods && name == 'modules') {
-                    clobber(mods, attr);
-                } else if (aliases && name == 'aliases') {
-                    clobber(aliases, attr);
-                } else if (groups && name == 'groups') {
-                    clobber(groups, attr);
-                } else if (name == 'win') {
-                    config[name] = (attr && attr.contentWindow) || attr;
-                    config.doc = config[name] ? config[name].document : null;
-                } else if (name == '_yuid') {
-                    // preserve the guid
-                } else {
-                    config[name] = attr;
-                }
-            }
-        }
-
-        if (loader) {
-            loader._config(o);
-        }
-
-    },
-
-    /**
-    Old way to apply a config to this instance (calls `applyConfig` under the
-    hood).
-
-    @private
-    @method _config
-    @param {Object} o The config to apply
-    **/
-    _config: function(o) {
-        this.applyConfig(o);
-    },
-
-    /**
-    Initializes this YUI instance.
-
-    @private
-    @method _init
-    **/
-    _init: function() {
-        var filter, el,
-            Y = this,
-            G_ENV = YUI.Env,
-            Env = Y.Env,
-            prop;
-
-        /**
-        The version number of this YUI instance.
-
-        This value is typically updated by a script when a YUI release is built,
-        so it may not reflect the correct version number when YUI is run from
-        the development source tree.
-
-        @property {String} version
-        **/
-        Y.version = VERSION;
-
-        if (!Env) {
-            Y.Env = {
-                core: ['get', 'features', 'intl-base', 'yui-log', 'yui-later', 'loader-base', 'loader-rollup', 'loader-yui3'],
-                loaderExtras: ['loader-rollup', 'loader-yui3'],
-                mods: {}, // flat module map
-                versions: {}, // version module map
-                base: BASE,
-                cdn: BASE + VERSION + '/build/',
-                // bootstrapped: false,
-                _idx: 0,
-                _used: {},
-                _attached: {},
-                _missed: [],
-                _yidx: 0,
-                _uidx: 0,
-                _guidp: 'y',
-                _loaded: {},
-                // serviced: {},
-                // Regex in English:
-                // I'll start at the \b(simpleyui).
-                // 1. Look in the test string for "simpleyui" or "yui" or
-                //    "yui-base" or "yui-davglass" or "yui-foobar" that comes after a word break.  That is, it
-                //    can't match "foyui" or "i_heart_simpleyui". This can be anywhere in the string.
-                // 2. After #1 must come a forward slash followed by the string matched in #1, so
-                //    "yui-base/yui-base" or "simpleyui/simpleyui" or "yui-pants/yui-pants".
-                // 3. The second occurence of the #1 token can optionally be followed by "-debug" or "-min",
-                //    so "yui/yui-min", "yui/yui-debug", "yui-base/yui-base-debug". NOT "yui/yui-tshirt".
-                // 4. This is followed by ".js", so "yui/yui.js", "simpleyui/simpleyui-min.js"
-                // 0. Going back to the beginning, now. If all that stuff in 1-4 comes after a "?" in the string,
-                //    then capture the junk between the LAST "&" and the string in 1-4.  So
-                //    "blah?foo/yui/yui.js" will capture "foo/" and "blah?some/thing.js&3.3.0/build/yui-davglass/yui-davglass.js"
-                //    will capture "3.3.0/build/"
-                //
-                // Regex Exploded:
-                // (?:\?             Find a ?
-                //   (?:[^&]*&)      followed by 0..n characters followed by an &
-                //   *               in fact, find as many sets of characters followed by a & as you can
-                //   ([^&]*)         capture the stuff after the last & in \1
-                // )?                but it's ok if all this ?junk&more_junk stuff isn't even there
-                // \b(simpleyui|     after a word break find either the string "simpleyui" or
-                //    yui(?:-\w+)?   the string "yui" optionally followed by a -, then more characters
-                // )                 and store the simpleyui or yui-* string in \2
-                // \/\2              then comes a / followed by the simpleyui or yui-* string in \2
-                // (?:-(min|debug))? optionally followed by "-min" or "-debug"
-                // .js               and ending in ".js"
-                _BASE_RE: /(?:\?(?:[^&]*&)*([^&]*))?\b(simpleyui|yui(?:-\w+)?)\/\2(?:-(min|debug))?\.js/,
-                parseBasePath: function(src, pattern) {
-                    var match = src.match(pattern),
-                        path, filter;
-
-                    if (match) {
-                        path = RegExp.leftContext || src.slice(0, src.indexOf(match[0]));
-
-                        // this is to set up the path to the loader.  The file
-                        // filter for loader should match the yui include.
-                        filter = match[3];
-
-                        // extract correct path for mixed combo urls
-                        // http://yuilibrary.com/projects/yui3/ticket/2528423
-                        if (match[1]) {
-                            path += '?' + match[1];
-                        }
-                        path = {
-                            filter: filter,
-                            path: path
-                        };
-                    }
-                    return path;
-                },
-                getBase: G_ENV && G_ENV.getBase ||
-                        function(pattern) {
-                            var nodes = (doc && doc.getElementsByTagName('script')) || [],
-                                path = Env.cdn, parsed,
-                                i, len, src;
-
-                            for (i = 0, len = nodes.length; i < len; ++i) {
-                                src = nodes[i].src;
-                                if (src) {
-                                    parsed = Y.Env.parseBasePath(src, pattern);
-                                    if (parsed) {
-                                        filter = parsed.filter;
-                                        path = parsed.path;
-                                        break;
-                                    }
-                                }
-                            }
-
-                            // use CDN default
-                            return path;
-                        }
-
-            };
-
-            Env = Y.Env;
-
-            Env._loaded[VERSION] = {};
-
-            if (G_ENV && Y !== YUI) {
-                Env._yidx = ++G_ENV._yidx;
-                Env._guidp = ('yui_' + VERSION + '_' +
-                             Env._yidx + '_' + time).replace(/[^a-z0-9_]+/g, '_');
-            } else if (YUI._YUI) {
-
-                G_ENV = YUI._YUI.Env;
-                Env._yidx += G_ENV._yidx;
-                Env._uidx += G_ENV._uidx;
-
-                for (prop in G_ENV) {
-                    if (!(prop in Env)) {
-                        Env[prop] = G_ENV[prop];
-                    }
-                }
-
-                delete YUI._YUI;
-            }
-
-            Y.id = Y.stamp(Y);
-            instances[Y.id] = Y;
-
-        }
-
-        Y.constructor = YUI;
-
-        // configuration defaults
-        Y.config = Y.config || {
-            bootstrap: true,
-            cacheUse: true,
-            debug: true,
-            doc: doc,
-            fetchCSS: true,
-            throwFail: true,
-            useBrowserConsole: true,
-            useNativeES5: true,
-            win: win,
-            global: Function('return this')()
-        };
-
-        //Register the CSS stamp element
-        if (doc && !doc.getElementById(CSS_STAMP_EL)) {
-            el = doc.createElement('div');
-            el.innerHTML = '<div id="' + CSS_STAMP_EL + '" style="position: absolute !important; visibility: hidden !important"></div>';
-            YUI.Env.cssStampEl = el.firstChild;
-            if (doc.body) {
-                doc.body.appendChild(YUI.Env.cssStampEl);
-            } else {
-                docEl.insertBefore(YUI.Env.cssStampEl, docEl.firstChild);
-            }
-        } else if (doc && doc.getElementById(CSS_STAMP_EL) && !YUI.Env.cssStampEl) {
-            YUI.Env.cssStampEl = doc.getElementById(CSS_STAMP_EL);
-        }
-
-        Y.config.lang = Y.config.lang || 'en-US';
-
-        Y.config.base = YUI.config.base || Y.Env.getBase(Y.Env._BASE_RE);
-
-        if (!filter || (!('mindebug').indexOf(filter))) {
-            filter = 'min';
-        }
-        filter = (filter) ? '-' + filter : filter;
-        Y.config.loaderPath = YUI.config.loaderPath || 'loader/loader' + filter + '.js';
-
-    },
-
-    /**
-    Finishes the instance setup. Attaches whatever YUI modules were defined
-    at the time that this instance was created.
-
-    @method _setup
-    @private
-    **/
-    _setup: function() {
-        var i, Y = this,
-            core = [],
-            mods = YUI.Env.mods,
-            extras = Y.config.core || [].concat(YUI.Env.core); //Clone it..
-
-        for (i = 0; i < extras.length; i++) {
-            if (mods[extras[i]]) {
-                core.push(extras[i]);
-            }
-        }
-
-        Y._attach(['yui-base']);
-        Y._attach(core);
-
-        if (Y.Loader) {
-            getLoader(Y);
-        }
-
-    },
-
-    /**
-    Executes the named method on the specified YUI instance if that method is
-    whitelisted.
-
-    @method applyTo
-    @param {String} id YUI instance id.
-    @param {String} method Name of the method to execute. For example:
-        'Object.keys'.
-    @param {Array} args Arguments to apply to the method.
-    @return {Mixed} Return value from the applied method, or `null` if the
-        specified instance was not found or the method was not whitelisted.
-    **/
-    applyTo: function(id, method, args) {
-        if (!(method in APPLY_TO_AUTH)) {
-            this.log(method + ': applyTo not allowed', 'warn', 'yui');
-            return null;
-        }
-
-        var instance = instances[id], nest, m, i;
-        if (instance) {
-            nest = method.split('.');
-            m = instance;
-            for (i = 0; i < nest.length; i = i + 1) {
-                m = m[nest[i]];
-                if (!m) {
-                    this.log('applyTo not found: ' + method, 'warn', 'yui');
-                }
-            }
-            return m && m.apply(instance, args);
-        }
-
-        return null;
-    },
-
-/**
-Registers a YUI module and makes it available for use in a `YUI().use()` call or
-as a dependency for other modules.
-
-The easiest way to create a first-class YUI module is to use
-<a href="http://yui.github.com/shifter/">Shifter</a>, the YUI component build
-tool.
-
-Shifter will automatically wrap your module code in a `YUI.add()` call along
-with any configuration info required for the module.
-
-@example
-
-    YUI.add('davglass', function (Y) {
-        Y.davglass = function () {
-        };
-    }, '3.4.0', {
-        requires: ['harley-davidson', 'mt-dew']
-    });
-
-@method add
-@param {String} name Module name.
-@param {Function} fn Function containing module code. This function will be
-    executed whenever the module is attached to a specific YUI instance.
-
-    @param {YUI} fn.Y The YUI instance to which this module is attached.
-    @param {String} fn.name Name of the module
-
-@param {String} version Module version number. This is currently used only for
-    informational purposes, and is not used internally by YUI.
-
-@param {Object} [config] Module config.
-    @param {Array} [config.requires] Array of other module names that must be
-        attached before this module can be attached.
-    @param {Array} [config.optional] Array of optional module names that should
-        be attached before this module is attached if they've already been
-        loaded. If the `loadOptional` YUI option is `true`, optional modules
-        that have not yet been loaded will be loaded just as if they were hard
-        requirements.
-    @param {Array} [config.use] Array of module names that are included within
-        or otherwise provided by this module, and which should be attached
-        automatically when this module is attached. This makes it possible to
-        create "virtual rollup" modules that simply attach a collection of other
-        modules or submodules.
-
-@return {YUI} This YUI instance.
-**/
-    add: function(name, fn, version, details) {
-        details = details || {};
-        var env = YUI.Env,
-            mod = {
-                name: name,
-                fn: fn,
-                version: version,
-                details: details
-            },
-            //Instance hash so we don't apply it to the same instance twice
-            applied = {},
-            loader, inst,
-            i, versions = env.versions;
-
-        env.mods[name] = mod;
-        versions[version] = versions[version] || {};
-        versions[version][name] = mod;
-
-        for (i in instances) {
-            if (instances.hasOwnProperty(i)) {
-                inst = instances[i];
-                if (!applied[inst.id]) {
-                    applied[inst.id] = true;
-                    loader = inst.Env._loader;
-                    if (loader) {
-                        if (!loader.moduleInfo[name] || loader.moduleInfo[name].temp) {
-                            loader.addModule(details, name);
-                        }
-                    }
-                }
-            }
-        }
-
-        return this;
-    },
-
-    /**
-    Executes the callback function associated with each required module,
-    attaching the module to this YUI instance.
-
-    @method _attach
-    @param {Array} r The array of modules to attach
-    @param {Boolean} [moot=false] If `true`, don't throw a warning if the module
-        is not attached.
-    @private
-    **/
-    _attach: function(r, moot) {
-        var i, name, mod, details, req, use, after,
-            mods = YUI.Env.mods,
-            aliases = YUI.Env.aliases,
-            Y = this, j,
-            cache = YUI.Env._renderedMods,
-            loader = Y.Env._loader,
-            done = Y.Env._attached,
-            len = r.length, loader, def, go,
-            c = [];
-
-        //Check for conditional modules (in a second+ instance) and add their requirements
-        //TODO I hate this entire method, it needs to be fixed ASAP (3.5.0) ^davglass
-        for (i = 0; i < len; i++) {
-            name = r[i];
-            mod = mods[name];
-            c.push(name);
-            if (loader && loader.conditions[name]) {
-                for (j in loader.conditions[name]) {
-                    if (loader.conditions[name].hasOwnProperty(j)) {
-                        def = loader.conditions[name][j];
-                        go = def && ((def.ua && Y.UA[def.ua]) || (def.test && def.test(Y)));
-                        if (go) {
-                            c.push(def.name);
-                        }
-                    }
-                }
-            }
-        }
-        r = c;
-        len = r.length;
-
-        for (i = 0; i < len; i++) {
-            if (!done[r[i]]) {
-                name = r[i];
-                mod = mods[name];
-
-                if (aliases && aliases[name] && !mod) {
-                    Y._attach(aliases[name]);
-                    continue;
-                }
-                if (!mod) {
-                    if (loader && loader.moduleInfo[name]) {
-                        mod = loader.moduleInfo[name];
-                        moot = true;
-                    }
-
-
-                    //if (!loader || !loader.moduleInfo[name]) {
-                    //if ((!loader || !loader.moduleInfo[name]) && !moot) {
-                    if (!moot && name) {
-                        if ((name.indexOf('skin-') === -1) && (name.indexOf('css') === -1)) {
-                            Y.Env._missed.push(name);
-                            Y.Env._missed = Y.Array.dedupe(Y.Env._missed);
-                            Y.message('NOT loaded: ' + name, 'warn', 'yui');
-                        }
-                    }
-                } else {
-                    done[name] = true;
-                    //Don't like this, but in case a mod was asked for once, then we fetch it
-                    //We need to remove it from the missed list ^davglass
-                    for (j = 0; j < Y.Env._missed.length; j++) {
-                        if (Y.Env._missed[j] === name) {
-                            Y.message('Found: ' + name + ' (was reported as missing earlier)', 'warn', 'yui');
-                            Y.Env._missed.splice(j, 1);
-                        }
-                    }
-                    /*
-                        If it's a temp module, we need to redo it's requirements if it's already loaded
-                        since it may have been loaded by another instance and it's dependencies might
-                        have been redefined inside the fetched file.
-                    */
-                    if (loader && cache && cache[name] && cache[name].temp) {
-                        loader.getRequires(cache[name]);
-                        req = [];
-                        for (j in loader.moduleInfo[name].expanded_map) {
-                            if (loader.moduleInfo[name].expanded_map.hasOwnProperty(j)) {
-                                req.push(j);
-                            }
-                        }
-                        Y._attach(req);
-                    }
-
-                    details = mod.details;
-                    req = details.requires;
-                    use = details.use;
-                    after = details.after;
-                    //Force Intl load if there is a language (Loader logic) @todo fix this shit
-                    if (details.lang) {
-                        req = req || [];
-                        req.unshift('intl');
-                    }
-
-                    if (req) {
-                        for (j = 0; j < req.length; j++) {
-                            if (!done[req[j]]) {
-                                if (!Y._attach(req)) {
-                                    return false;
-                                }
-                                break;
-                            }
-                        }
-                    }
-
-                    if (after) {
-                        for (j = 0; j < after.length; j++) {
-                            if (!done[after[j]]) {
-                                if (!Y._attach(after, true)) {
-                                    return false;
-                                }
-                                break;
-                            }
-                        }
-                    }
-
-                    if (mod.fn) {
-                            if (Y.config.throwFail) {
-                                mod.fn(Y, name);
-                            } else {
-                                try {
-                                    mod.fn(Y, name);
-                                } catch (e) {
-                                    Y.error('Attach error: ' + name, e, name);
-                                return false;
-                            }
-                        }
-                    }
-
-                    if (use) {
-                        for (j = 0; j < use.length; j++) {
-                            if (!done[use[j]]) {
-                                if (!Y._attach(use)) {
-                                    return false;
-                                }
-                                break;
-                            }
-                        }
-                    }
-
-
-
-                }
-            }
-        }
-
-        return true;
-    },
-
-    /**
-    Delays the `use` callback until another event has taken place such as
-    `window.onload`, `domready`, `contentready`, or `available`.
-
-    @private
-    @method _delayCallback
-    @param {Function} cb The original `use` callback.
-    @param {String|Object} until Either an event name ('load', 'domready', etc.)
-        or an object containing event/args keys for contentready/available.
-    @return {Function}
-    **/
-    _delayCallback: function(cb, until) {
-
-        var Y = this,
-            mod = ['event-base'];
-
-        until = (Y.Lang.isObject(until) ? until : { event: until });
-
-        if (until.event === 'load') {
-            mod.push('event-synthetic');
-        }
-
-        return function() {
-            var args = arguments;
-            Y._use(mod, function() {
-                Y.on(until.event, function() {
-                    args[1].delayUntil = until.event;
-                    cb.apply(Y, args);
-                }, until.args);
-            });
-        };
-    },
-
-    /**
-    Attaches one or more modules to this YUI instance. When this is executed,
-    the requirements of the desired modules are analyzed, and one of several
-    things can happen:
-
-
-      * All required modules have already been loaded, and just need to be
-        attached to this YUI instance. In this case, the `use()` callback will
-        be executed synchronously after the modules are attached.
-
-      * One or more modules have not yet been loaded, or the Get utility is not
-        available, or the `bootstrap` config option is `false`. In this case,
-        a warning is issued indicating that modules are missing, but all
-        available modules will still be attached and the `use()` callback will
-        be executed synchronously.
-
-      * One or more modules are missing and the Loader is not available but the
-        Get utility is, and `bootstrap` is not `false`. In this case, the Get
-        utility will be used to load the Loader, and we will then proceed to
-        the following state:
-
-      * One or more modules are missing and the Loader is available. In this
-        case, the Loader will be used to resolve the dependency tree for the
-        missing modules and load them and their dependencies. When the Loader is
-        finished loading modules, the `use()` callback will be executed
-        asynchronously.
-
-    @example
-
-        // Loads and attaches dd and its dependencies.
-        YUI().use('dd', function (Y) {
-            // ...
-        });
-
-        // Loads and attaches dd and node as well as all of their dependencies.
-        YUI().use(['dd', 'node'], function (Y) {
-            // ...
-        });
-
-        // Attaches all modules that have already been loaded.
-        YUI().use('*', function (Y) {
-            // ...
-        });
-
-        // Attaches a gallery module.
-        YUI().use('gallery-yql', function (Y) {
-            // ...
-        });
-
-        // Attaches a YUI 2in3 module.
-        YUI().use('yui2-datatable', function (Y) {
-            // ...
-        });
-
-    @method use
-    @param {String|Array} modules* One or more module names to attach.
-    @param {Function} [callback] Callback function to be executed once all
-        specified modules and their dependencies have been attached.
-    @param {YUI} callback.Y The YUI instance created for this sandbox.
-    @param {Object} callback.status Object containing `success`, `msg` and
-        `data` properties.
-    @chainable
-    **/
-    use: function() {
-        var args = SLICE.call(arguments, 0),
-            callback = args[args.length - 1],
-            Y = this,
-            i = 0,
-            name,
-            Env = Y.Env,
-            provisioned = true;
-
-        // The last argument supplied to use can be a load complete callback
-        if (Y.Lang.isFunction(callback)) {
-            args.pop();
-            if (Y.config.delayUntil) {
-                callback = Y._delayCallback(callback, Y.config.delayUntil);
-            }
-        } else {
-            callback = null;
-        }
-        if (Y.Lang.isArray(args[0])) {
-            args = args[0];
-        }
-
-        if (Y.config.cacheUse) {
-            while ((name = args[i++])) {
-                if (!Env._attached[name]) {
-                    provisioned = false;
-                    break;
-                }
-            }
-
-            if (provisioned) {
-                if (args.length) {
-                }
-                Y._notify(callback, ALREADY_DONE, args);
-                return Y;
-            }
-        }
-
-        if (Y._loading) {
-            Y._useQueue = Y._useQueue || new Y.Queue();
-            Y._useQueue.add([args, callback]);
-        } else {
-            Y._use(args, function(Y, response) {
-                Y._notify(callback, response, args);
-            });
-        }
-
-        return Y;
-    },
-
-    /**
-    Handles Loader notifications about attachment/load errors.
-
-    @method _notify
-    @param {Function} callback Callback to pass to `Y.config.loadErrorFn`.
-    @param {Object} response Response returned from Loader.
-    @param {Array} args Arguments passed from Loader.
-    @private
-    **/
-    _notify: function(callback, response, args) {
-        if (!response.success && this.config.loadErrorFn) {
-            this.config.loadErrorFn.call(this, this, callback, response, args);
-        } else if (callback) {
-            if (this.Env._missed && this.Env._missed.length) {
-                response.msg = 'Missing modules: ' + this.Env._missed.join();
-                response.success = false;
-            }
-            if (this.config.throwFail) {
-                callback(this, response);
-            } else {
-                try {
-                    callback(this, response);
-                } catch (e) {
-                    this.error('use callback error', e, args);
-                }
-            }
-        }
-    },
-
-    /**
-    Called from the `use` method queue to ensure that only one set of loading
-    logic is performed at a time.
-
-    @method _use
-    @param {String} args* One or more modules to attach.
-    @param {Function} [callback] Function to call once all required modules have
-        been attached.
-    @private
-    **/
-    _use: function(args, callback) {
-
-        if (!this.Array) {
-            this._attach(['yui-base']);
-        }
-
-        var len, loader, handleBoot,
-            Y = this,
-            G_ENV = YUI.Env,
-            mods = G_ENV.mods,
-            Env = Y.Env,
-            used = Env._used,
-            aliases = G_ENV.aliases,
-            queue = G_ENV._loaderQueue,
-            firstArg = args[0],
-            YArray = Y.Array,
-            config = Y.config,
-            boot = config.bootstrap,
-            missing = [],
-            i,
-            r = [],
-            ret = true,
-            fetchCSS = config.fetchCSS,
-            process = function(names, skip) {
-
-                var i = 0, a = [], name, len, m, req, use;
-
-                if (!names.length) {
-                    return;
-                }
-
-                if (aliases) {
-                    len = names.length;
-                    for (i = 0; i < len; i++) {
-                        if (aliases[names[i]] && !mods[names[i]]) {
-                            a = [].concat(a, aliases[names[i]]);
-                        } else {
-                            a.push(names[i]);
-                        }
-                    }
-                    names = a;
-                }
-
-                len = names.length;
-
-                for (i = 0; i < len; i++) {
-                    name = names[i];
-                    if (!skip) {
-                        r.push(name);
-                    }
-
-                    // only attach a module once
-                    if (used[name]) {
-                        continue;
-                    }
-
-                    m = mods[name];
-                    req = null;
-                    use = null;
-
-                    if (m) {
-                        used[name] = true;
-                        req = m.details.requires;
-                        use = m.details.use;
-                    } else {
-                        // CSS files don't register themselves, see if it has
-                        // been loaded
-                        if (!G_ENV._loaded[VERSION][name]) {
-                            missing.push(name);
-                        } else {
-                            used[name] = true; // probably css
-                        }
-                    }
-
-                    // make sure requirements are attached
-                    if (req && req.length) {
-                        process(req);
-                    }
-
-                    // make sure we grab the submodule dependencies too
-                    if (use && use.length) {
-                        process(use, 1);
-                    }
-                }
-
-            },
-
-            handleLoader = function(fromLoader) {
-                var response = fromLoader || {
-                        success: true,
-                        msg: 'not dynamic'
-                    },
-                    redo, origMissing,
-                    ret = true,
-                    data = response.data;
-
-                Y._loading = false;
-
-                if (data) {
-                    origMissing = missing;
-                    missing = [];
-                    r = [];
-                    process(data);
-                    redo = missing.length;
-                    if (redo) {
-                        if ([].concat(missing).sort().join() ==
-                                origMissing.sort().join()) {
-                            redo = false;
-                        }
-                    }
-                }
-
-                if (redo && data) {
-                    Y._loading = true;
-                    Y._use(missing, function() {
-                        if (Y._attach(data)) {
-                            Y._notify(callback, response, data);
-                        }
-                    });
-                } else {
-                    if (data) {
-                        ret = Y._attach(data);
-                    }
-                    if (ret) {
-                        Y._notify(callback, response, args);
-                    }
-                }
-
-                if (Y._useQueue && Y._useQueue.size() && !Y._loading) {
-                    Y._use.apply(Y, Y._useQueue.next());
-                }
-
-            };
-
-
-        // YUI().use('*'); // bind everything available
-        if (firstArg === '*') {
-            args = [];
-            for (i in mods) {
-                if (mods.hasOwnProperty(i)) {
-                    args.push(i);
-                }
-            }
-            ret = Y._attach(args);
-            if (ret) {
-                handleLoader();
-            }
-            return Y;
-        }
-
-        if ((mods.loader || mods['loader-base']) && !Y.Loader) {
-            Y._attach(['loader' + ((!mods.loader) ? '-base' : '')]);
-        }
-
-
-        // use loader to expand dependencies and sort the
-        // requirements if it is available.
-        if (boot && Y.Loader && args.length) {
-            loader = getLoader(Y);
-            loader.require(args);
-            loader.ignoreRegistered = true;
-            loader._boot = true;
-            loader.calculate(null, (fetchCSS) ? null : 'js');
-            args = loader.sorted;
-            loader._boot = false;
-        }
-
-        process(args);
-
-        len = missing.length;
-
-
-        if (len) {
-            missing = YArray.dedupe(missing);
-            len = missing.length;
-        }
-
-
-        // dynamic load
-        if (boot && len && Y.Loader) {
-            Y._loading = true;
-            loader = getLoader(Y);
-            loader.onEnd = handleLoader;
-            loader.context = Y;
-            loader.data = args;
-            loader.ignoreRegistered = false;
-            loader.require(missing);
-            loader.insert(null, (fetchCSS) ? null : 'js');
-
-        } else if (boot && len && Y.Get && !Env.bootstrapped) {
-
-            Y._loading = true;
-
-            handleBoot = function() {
-                Y._loading = false;
-                queue.running = false;
-                Env.bootstrapped = true;
-                G_ENV._bootstrapping = false;
-                if (Y._attach(['loader'])) {
-                    Y._use(args, callback);
-                }
-            };
-
-            if (G_ENV._bootstrapping) {
-                queue.add(handleBoot);
-            } else {
-                G_ENV._bootstrapping = true;
-                Y.Get.script(config.base + config.loaderPath, {
-                    onEnd: handleBoot
-                });
-            }
-
-        } else {
-            ret = Y._attach(args);
-            if (ret) {
-                handleLoader();
-            }
-        }
-
-        return Y;
-    },
-
-
-    /**
-    Utility method for safely creating namespaces if they don't already exist.
-    May be called statically on the YUI global object or as a method on a YUI
-    instance.
-
-    When called statically, a namespace will be created on the YUI global
-    object:
-
-        // Create `YUI.your.namespace.here` as nested objects, preserving any
-        // objects that already exist instead of overwriting them.
-        YUI.namespace('your.namespace.here');
-
-    When called as a method on a YUI instance, a namespace will be created on
-    that instance:
-
-        // Creates `Y.property.package`.
-        Y.namespace('property.package');
-
-    Dots in the input string cause `namespace` to create nested objects for each
-    token. If any part of the requested namespace already exists, the current
-    object will be left in place and will not be overwritten. This allows
-    multiple calls to `namespace` to preserve existing namespaced properties.
-
-    If the first token in the namespace string is "YAHOO", that token is
-    discarded. This is legacy behavior for backwards compatibility with YUI 2.
-
-    Be careful with namespace tokens. Reserved words may work in some browsers
-    and not others. For instance, the following will fail in some browsers
-    because the supported version of JavaScript reserves the word "long":
-
-        Y.namespace('really.long.nested.namespace');
-
-    Note: If you pass multiple arguments to create multiple namespaces, only the
-    last one created is returned from this function.
-
-    @method namespace
-    @param {String} namespace* One or more namespaces to create.
-    @return {Object} Reference to the last namespace object created.
-    **/
-    namespace: function() {
-        var a = arguments, o, i = 0, j, d, arg;
-
-        for (; i < a.length; i++) {
-            o = this; //Reset base object per argument or it will get reused from the last
-            arg = a[i];
-            if (arg.indexOf(PERIOD) > -1) { //Skip this if no "." is present
-                d = arg.split(PERIOD);
-                for (j = (d[0] == 'YAHOO') ? 1 : 0; j < d.length; j++) {
-                    o[d[j]] = o[d[j]] || {};
-                    o = o[d[j]];
-                }
-            } else {
-                o[arg] = o[arg] || {};
-                o = o[arg]; //Reset base object to the new object so it's returned
-            }
-        }
-        return o;
-    },
-
-    // this is replaced if the log module is included
-    log: NOOP,
-    message: NOOP,
-    // this is replaced if the dump module is included
-    dump: function (o) { return ''+o; },
-
-    /**
-    Reports an error.
-
-    The reporting mechanism is controlled by the `throwFail` configuration
-    attribute. If `throwFail` is falsy, the message is logged. If `throwFail` is
-    truthy, a JS exception is thrown.
-
-    If an `errorFn` is specified in the config it must return `true` to indicate
-    that the exception was handled and keep it from being thrown.
-
-    @method error
-    @param {String} msg Error message.
-    @param {Error|String} [e] JavaScript error object or an error string.
-    @param {String} [src] Source of the error (such as the name of the module in
-        which the error occurred).
-    @chainable
-    **/
-    error: function(msg, e, src) {
-        //TODO Add check for window.onerror here
-
-        var Y = this, ret;
-
-        if (Y.config.errorFn) {
-            ret = Y.config.errorFn.apply(Y, arguments);
-        }
-
-        if (!ret) {
-            throw (e || new Error(msg));
-        } else {
-            Y.message(msg, 'error', ''+src); // don't scrub this one
-        }
-
-        return Y;
-    },
-
-    /**
-    Generates an id string that is unique among all YUI instances in this
-    execution context.
-
-    @method guid
-    @param {String} [pre] Prefix.
-    @return {String} Unique id.
-    **/
-    guid: function(pre) {
-        var id = this.Env._guidp + '_' + (++this.Env._uidx);
-        return (pre) ? (pre + id) : id;
-    },
-
-    /**
-    Returns a unique id associated with the given object and (if *readOnly* is
-    falsy) stamps the object with that id so it can be identified in the future.
-
-    Stamping an object involves adding a `_yuid` property to it that contains
-    the object's id. One exception to this is that in Internet Explorer, DOM
-    nodes have a `uniqueID` property that contains a browser-generated unique
-    id, which will be used instead of a YUI-generated id when available.
-
-    @method stamp
-    @param {Object} o Object to stamp.
-    @param {Boolean} readOnly If truthy and the given object has not already
-        been stamped, the object will not be modified and `null` will be
-        returned.
-    @return {String} Object's unique id, or `null` if *readOnly* was truthy and
-        the given object was not already stamped.
-    **/
-    stamp: function(o, readOnly) {
-        var uid;
-        if (!o) {
-            return o;
-        }
-
-        // IE generates its own unique ID for dom nodes
-        // The uniqueID property of a document node returns a new ID
-        if (o.uniqueID && o.nodeType && o.nodeType !== 9) {
-            uid = o.uniqueID;
-        } else {
-            uid = (typeof o === 'string') ? o : o._yuid;
-        }
-
-        if (!uid) {
-            uid = this.guid();
-            if (!readOnly) {
-                try {
-                    o._yuid = uid;
-                } catch (e) {
-                    uid = null;
-                }
-            }
-        }
-        return uid;
-    },
-
-    /**
-    Destroys this YUI instance.
-
-    @method destroy
-    @since 3.3.0
-    **/
-    destroy: function() {
-        var Y = this;
-        if (Y.Event) {
-            Y.Event._unload();
-        }
-        delete instances[Y.id];
-        delete Y.Env;
-        delete Y.config;
-    }
-
-    /**
-    Safe `instanceof` wrapper that works around a memory leak in IE when the
-    object being tested is `window` or `document`.
-
-    Unless you are testing objects that may be `window` or `document`, you
-    should use the native `instanceof` operator instead of this method.
-
-    @method instanceOf
-    @param {Object} o Object to check.
-    @param {Object} type Class to check against.
-    @since 3.3.0
-    **/
-};
-
-    YUI.prototype = proto;
-
-    // inheritance utilities are not available yet
-    for (prop in proto) {
-        if (proto.hasOwnProperty(prop)) {
-            YUI[prop] = proto[prop];
-        }
-    }
-
-    /**
-    Applies a configuration to all YUI instances in this execution context.
-
-    The main use case for this method is in "mashups" where several third-party
-    scripts need to write to a global YUI config, but cannot share a single
-    centrally-managed config object. This way they can all call
-    `YUI.applyConfig({})` instead of overwriting the single global config.
-
-    @example
-
-        YUI.applyConfig({
-            modules: {
-                davglass: {
-                    fullpath: './davglass.js'
-                }
-            }
-        });
-
-        YUI.applyConfig({
-            modules: {
-                foo: {
-                    fullpath: './foo.js'
-                }
-            }
-        });
-
-        YUI().use('davglass', function (Y) {
-            // Module davglass will be available here.
-        });
-
-    @method applyConfig
-    @param {Object} o Configuration object to apply.
-    @static
-    @since 3.5.0
-    **/
-    YUI.applyConfig = function(o) {
-        if (!o) {
-            return;
-        }
-        //If there is a GlobalConfig, apply it first to set the defaults
-        if (YUI.GlobalConfig) {
-            this.prototype.applyConfig.call(this, YUI.GlobalConfig);
-        }
-        //Apply this config to it
-        this.prototype.applyConfig.call(this, o);
-        //Reset GlobalConfig to the combined config
-        YUI.GlobalConfig = this.config;
-    };
-
-    // set up the environment
-    YUI._init();
-
-    if (hasWin) {
-        // add a window load event at load time so we can capture
-        // the case where it fires before dynamic loading is
-        // complete.
-        add(window, 'load', handleLoad);
-    } else {
-        handleLoad();
-    }
-
-    YUI.Env.add = add;
-    YUI.Env.remove = remove;
-
-    /*global exports*/
-    // Support the CommonJS method for exporting our single global
-    if (typeof exports == 'object') {
-        exports.YUI = YUI;
-        /**
-        * Set a method to be called when `Get.script` is called in Node.js
-        * `Get` will open the file, then pass it's content and it's path
-        * to this method before attaching it. Commonly used for code coverage
-        * instrumentation. <strong>Calling this multiple times will only
-        * attach the last hook method</strong>. This method is only
-        * available in Node.js.
-        * @method setLoadHook
-        * @static
-        * @param {Function} fn The function to set
-        * @param {String} fn.data The content of the file
-        * @param {String} fn.path The file path of the file
-        */
-        YUI.setLoadHook = function(fn) {
-            YUI._getLoadHook = fn;
-        };
-        /**
-        * Load hook for `Y.Get.script` in Node.js, see `YUI.setLoadHook`
-        * @method _getLoadHook
-        * @private
-        * @param {String} data The content of the file
-        * @param {String} path The file path of the file
-        */
-        YUI._getLoadHook = null;
-    }
-
-    YUI.Env[VERSION] = {};
-}());
-
-
-/**
-Config object that contains all of the configuration options for
-this `YUI` instance.
-
-This object is supplied by the implementer when instantiating YUI. Some
-properties have default values if they are not supplied by the implementer.
-
-This object should not be updated directly because some values are cached. Use
-`applyConfig()` to update the config object on a YUI instance that has already
-been configured.
-
-@class config
-@static
-**/
-
-/**
-If `true` (the default), YUI will "bootstrap" the YUI Loader and module metadata
-if they're needed to load additional dependencies and aren't already available.
-
-Setting this to `false` will prevent YUI from automatically loading the Loader
-and module metadata, so you will need to manually ensure that they're available
-or handle dependency resolution yourself.
-
-@property {Boolean} bootstrap
-@default true
-**/
-
-/**
-
-@property {Object} aliases
-**/
-
-/**
-A hash of module group definitions.
-
-For each group you can specify a list of modules and the base path and
-combo spec to use when dynamically loading the modules.
-
-@example
-
-    groups: {
-        yui2: {
-            // specify whether or not this group has a combo service
-            combine: true,
-
-            // The comboSeperator to use with this group's combo handler
-            comboSep: ';',
-
-            // The maxURLLength for this server
-            maxURLLength: 500,
-
-            // the base path for non-combo paths
-            base: 'http://yui.yahooapis.com/2.8.0r4/build/',
-
-            // the path to the combo service
-            comboBase: 'http://yui.yahooapis.com/combo?',
-
-            // a fragment to prepend to the path attribute when
-            // when building combo urls
-            root: '2.8.0r4/build/',
-
-            // the module definitions
-            modules:  {
-                yui2_yde: {
-                    path: "yahoo-dom-event/yahoo-dom-event.js"
-                },
-                yui2_anim: {
-                    path: "animation/animation.js",
-                    requires: ['yui2_yde']
-                }
-            }
-        }
-    }
-
-@property {Object} groups
-**/
-
-/**
-Path to the Loader JS file, relative to the `base` path.
-
-This is used to dynamically bootstrap the Loader when it's needed and isn't yet
-available.
-
-@property {String} loaderPath
-@default "loader/loader-min.js"
-**/
-
-/**
-If `true`, YUI will attempt to load CSS dependencies and skins. Set this to
-`false` to prevent YUI from loading any CSS, or set it to the string `"force"`
-to force CSS dependencies to be loaded even if their associated JS modules are
-already loaded.
-
-@property {Boolean|String} fetchCSS
-@default true
-**/
-
-/**
-Default gallery version used to build gallery module urls.
-
-@property {String} gallery
-@since 3.1.0
-**/
-
-/**
-Default YUI 2 version used to build YUI 2 module urls.
-
-This is used for intrinsic YUI 2 support via the 2in3 project. Also see the
-`2in3` config for pulling different revisions of the wrapped YUI 2 modules.
-
-@property {String} yui2
-@default "2.9.0"
-@since 3.1.0
-**/
-
-/**
-Revision number of YUI 2in3 modules that should be used when loading YUI 2in3.
-
-@property {String} 2in3
-@default "4"
-@since 3.1.0
-**/
-
-/**
-Alternate console log function that should be used in environments without a
-supported native console. This function is executed with the YUI instance as its
-`this` object.
-
-@property {Function} logFn
-@since 3.1.0
-**/
-
-/**
-The minimum log level to log messages for. Log levels are defined
-incrementally. Messages greater than or equal to the level specified will
-be shown. All others will be discarded. The order of log levels in
-increasing priority is:
-
-    debug
-    info
-    warn
-    error
-
-@property {String} logLevel
-@default 'debug'
-@since 3.10.0
-**/
-
-/**
-Callback to execute when `Y.error()` is called. It receives the error message
-and a JavaScript error object if one was provided.
-
-This function is executed with the YUI instance as its `this` object.
-
-Returning `true` from this function will prevent an exception from being thrown.
-
-@property {Function} errorFn
-@param {String} errorFn.msg Error message
-@param {Object} [errorFn.err] Error object (if one was provided).
-@since 3.2.0
-**/
-
-/**
-A callback to execute when Loader fails to load one or more resources.
-
-This could be because of a script load failure. It could also be because a
-module fails to register itself when the `requireRegistration` config is `true`.
-
-If this function is defined, the `use()` callback will only be called when the
-loader succeeds. Otherwise, `use()` will always executes unless there was a
-JavaScript error when attaching a module.
-
-@property {Function} loadErrorFn
-@since 3.3.0
-**/
-
-/**
-If `true`, Loader will expect all loaded scripts to be first-class YUI modules
-that register themselves with the YUI global, and will trigger a failure if a
-loaded script does not register a YUI module.
-
-@property {Boolean} requireRegistration
-@default false
-@since 3.3.0
-**/
-
-/**
-Cache serviced use() requests.
-
-@property {Boolean} cacheUse
-@default true
-@since 3.3.0
-@deprecated No longer used.
-**/
-
-/**
-Whether or not YUI should use native ES5 functionality when available for
-features like `Y.Array.each()`, `Y.Object()`, etc.
-
-When `false`, YUI will always use its own fallback implementations instead of
-relying on ES5 functionality, even when ES5 functionality is available.
-
-@property {Boolean} useNativeES5
-@default true
-@since 3.5.0
-**/
-
-/**
- * Leverage native JSON stringify if the browser has a native
- * implementation.  In general, this is a good idea.  See the Known Issues
- * section in the JSON user guide for caveats.  The default value is true
- * for browsers with native JSON support.
- *
- * @property useNativeJSONStringify
- * @type Boolean
- * @default true
- * @since 3.8.0
- */
-
- /**
- * Leverage native JSON parse if the browser has a native implementation.
- * In general, this is a good idea.  See the Known Issues section in the
- * JSON user guide for caveats.  The default value is true for browsers with
- * native JSON support.
- *
- * @property useNativeJSONParse
- * @type Boolean
- * @default true
- * @since 3.8.0
- */
-
-/**
-Delay the `use` callback until a specific event has passed (`load`, `domready`, `contentready` or `available`)
-
-@property {Object|String} delayUntil
-@since 3.6.0
-@example
-
-You can use `load` or `domready` strings by default:
-
-    YUI({
-        delayUntil: 'domready'
-    }, function (Y) {
-        // This will not execute until 'domeready' occurs.
-    });
-
-Or you can delay until a node is available (with `available` or `contentready`):
-
-    YUI({
-        delayUntil: {
-            event: 'available',
-            args : '#foo'
-        }
-    }, function (Y) {
-        // This will not execute until a node matching the selector "#foo" is
-        // available in the DOM.
-    });
-
-**/
-YUI.add('yui-base', function (Y, NAME) {
-
-/*
- * YUI stub
- * @module yui
- * @submodule yui-base
- */
-/**
- * The YUI module contains the components required for building the YUI
- * seed file.  This includes the script loading mechanism, a simple queue,
- * and the core utilities for the library.
- * @module yui
- * @submodule yui-base
- */
-
-/**
- * Provides core language utilites and extensions used throughout YUI.
- *
- * @class Lang
- * @static
- */
-
-var L = Y.Lang || (Y.Lang = {}),
-
-STRING_PROTO = String.prototype,
-TOSTRING     = Object.prototype.toString,
-
-TYPES = {
-    'undefined'        : 'undefined',
-    'number'           : 'number',
-    'boolean'          : 'boolean',
-    'string'           : 'string',
-    '[object Function]': 'function',
-    '[object RegExp]'  : 'regexp',
-    '[object Array]'   : 'array',
-    '[object Date]'    : 'date',
-    '[object Error]'   : 'error'
-},
-
-SUBREGEX         = /\{\s*([^|}]+?)\s*(?:\|([^}]*))?\s*\}/g,
-
-WHITESPACE       = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF",
-WHITESPACE_CLASS = "[\x09-\x0D\x20\xA0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]+",
-TRIM_LEFT_REGEX  = new RegExp("^" + WHITESPACE_CLASS),
-TRIM_RIGHT_REGEX = new RegExp(WHITESPACE_CLASS + "$"),
-TRIMREGEX        = new RegExp(TRIM_LEFT_REGEX.source + "|" + TRIM_RIGHT_REGEX.source, "g"),
-
-NATIVE_FN_REGEX  = /\{\s*\[(?:native code|function)\]\s*\}/i;
-
-// -- Protected Methods --------------------------------------------------------
-
-/**
-Returns `true` if the given function appears to be implemented in native code,
-`false` otherwise. Will always return `false` -- even in ES5-capable browsers --
-if the `useNativeES5` YUI config option is set to `false`.
-
-This isn't guaranteed to be 100% accurate and won't work for anything other than
-functions, but it can be useful for determining whether a function like
-`Array.prototype.forEach` is native or a JS shim provided by another library.
-
-There's a great article by @kangax discussing certain flaws with this technique:
-<http://perfectionkills.com/detecting-built-in-host-methods/>
-
-While his points are valid, it's still possible to benefit from this function
-as long as it's used carefully and sparingly, and in such a way that false
-negatives have minimal consequences. It's used internally to avoid using
-potentially broken non-native ES5 shims that have been added to the page by
-other libraries.
-
-@method _isNative
-@param {Function} fn Function to test.
-@return {Boolean} `true` if _fn_ appears to be native, `false` otherwise.
-@static
-@protected
-@since 3.5.0
-**/
-L._isNative = function (fn) {
-    return !!(Y.config.useNativeES5 && fn && NATIVE_FN_REGEX.test(fn));
-};
-
-// -- Public Methods -----------------------------------------------------------
-
-/**
- * Determines whether or not the provided item is an array.
- *
- * Returns `false` for array-like collections such as the function `arguments`
- * collection or `HTMLElement` collections. Use `Y.Array.test()` if you want to
- * test for an array-like collection.
- *
- * @method isArray
- * @param o The object to test.
- * @return {boolean} true if o is an array.
- * @static
- */
-L.isArray = L._isNative(Array.isArray) ? Array.isArray : function (o) {
-    return L.type(o) === 'array';
-};
-
-/**
- * Determines whether or not the provided item is a boolean.
- * @method isBoolean
- * @static
- * @param o The object to test.
- * @return {boolean} true if o is a boolean.
- */
-L.isBoolean = function(o) {
-    return typeof o === 'boolean';
-};
-
-/**
- * Determines whether or not the supplied item is a date instance.
- * @method isDate
- * @static
- * @param o The object to test.
- * @return {boolean} true if o is a date.
- */
-L.isDate = function(o) {
-    return L.type(o) === 'date' && o.toString() !== 'Invalid Date' && !isNaN(o);
-};
-
-/**
- * <p>
- * Determines whether or not the provided item is a function.
- * Note: Internet Explorer thinks certain functions are objects:
- * </p>
- *
- * <pre>
- * var obj = document.createElement("object");
- * Y.Lang.isFunction(obj.getAttribute) // reports false in IE
- * &nbsp;
- * var input = document.createElement("input"); // append to body
- * Y.Lang.isFunction(input.focus) // reports false in IE
- * </pre>
- *
- * <p>
- * You will have to implement additional tests if these functions
- * matter to you.
- * </p>
- *
- * @method isFunction
- * @static
- * @param o The object to test.
- * @return {boolean} true if o is a function.
- */
-L.isFunction = function(o) {
-    return L.type(o) === 'function';
-};
-
-/**
- * Determines whether or not the provided item is null.
- * @method isNull
- * @static
- * @param o The object to test.
- * @return {boolean} true if o is null.
- */
-L.isNull = function(o) {
-    return o === null;
-};
-
-/**
- * Determines whether or not the provided item is a legal number.
- * @method isNumber
- * @static
- * @param o The object to test.
- * @return {boolean} true if o is a number.
- */
-L.isNumber = function(o) {
-    return typeof o === 'number' && isFinite(o);
-};
-
-/**
- * Determines whether or not the provided item is of type object
- * or function. Note that arrays are also objects, so
- * <code>Y.Lang.isObject([]) === true</code>.
- * @method isObject
- * @static
- * @param o The object to test.
- * @param failfn {boolean} fail if the input is a function.
- * @return {boolean} true if o is an object.
- * @see isPlainObject
- */
-L.isObject = function(o, failfn) {
-    var t = typeof o;
-    return (o && (t === 'object' ||
-        (!failfn && (t === 'function' || L.isFunction(o))))) || false;
-};
-
-/**
- * Determines whether or not the provided item is a string.
- * @method isString
- * @static
- * @param o The object to test.
- * @return {boolean} true if o is a string.
- */
-L.isString = function(o) {
-    return typeof o === 'string';
-};
-
-/**
- * Determines whether or not the provided item is undefined.
- * @method isUndefined
- * @static
- * @param o The object to test.
- * @return {boolean} true if o is undefined.
- */
-L.isUndefined = function(o) {
-    return typeof o === 'undefined';
-};
-
-/**
- * A convenience method for detecting a legitimate non-null value.
- * Returns false for null/undefined/NaN, true for other values,
- * including 0/false/''
- * @method isValue
- * @static
- * @param o The item to test.
- * @return {boolean} true if it is not null/undefined/NaN || false.
- */
-L.isValue = function(o) {
-    var t = L.type(o);
-
-    switch (t) {
-        case 'number':
-            return isFinite(o);
-
-        case 'null': // fallthru
-        case 'undefined':
-            return false;
-
-        default:
-            return !!t;
-    }
-};
-
-/**
- * Returns the current time in milliseconds.
- *
- * @method now
- * @return {Number} Current time in milliseconds.
- * @static
- * @since 3.3.0
- */
-L.now = Date.now || function () {
-    return new Date().getTime();
-};
-
-/**
- * Lightweight version of <code>Y.substitute</code>. Uses the same template
- * structure as <code>Y.substitute</code>, but doesn't support recursion,
- * auto-object coersion, or formats.
- * @method sub
- * @param {string} s String to be modified.
- * @param {object} o Object containing replacement values.
- * @return {string} the substitute result.
- * @static
- * @since 3.2.0
- */
-L.sub = function(s, o) {
-    return s.replace ? s.replace(SUBREGEX, function (match, key) {
-        return L.isUndefined(o[key]) ? match : o[key];
-    }) : s;
-};
-
-/**
- * Returns a string without any leading or trailing whitespace.  If
- * the input is not a string, the input will be returned untouched.
- * @method trim
- * @static
- * @param s {string} the string to trim.
- * @return {string} the trimmed string.
- */
-L.trim = L._isNative(STRING_PROTO.trim) && !WHITESPACE.trim() ? function(s) {
-    return s && s.trim ? s.trim() : s;
-} : function (s) {
-    try {
-        return s.replace(TRIMREGEX, '');
-    } catch (e) {
-        return s;
-    }
-};
-
-/**
- * Returns a string without any leading whitespace.
- * @method trimLeft
- * @static
- * @param s {string} the string to trim.
- * @return {string} the trimmed string.
- */
-L.trimLeft = L._isNative(STRING_PROTO.trimLeft) && !WHITESPACE.trimLeft() ? function (s) {
-    return s.trimLeft();
-} : function (s) {
-    return s.replace(TRIM_LEFT_REGEX, '');
-};
-
-/**
- * Returns a string without any trailing whitespace.
- * @method trimRight
- * @static
- * @param s {string} the string to trim.
- * @return {string} the trimmed string.
- */
-L.trimRight = L._isNative(STRING_PROTO.trimRight) && !WHITESPACE.trimRight() ? function (s) {
-    return s.trimRight();
-} : function (s) {
-    return s.replace(TRIM_RIGHT_REGEX, '');
-};
-
-/**
-Returns one of the following strings, representing the type of the item passed
-in:
-
- * "array"
- * "boolean"
- * "date"
- * "error"
- * "function"
- * "null"
- * "number"
- * "object"
- * "regexp"
- * "string"
- * "undefined"
-
-Known issues:
-
- * `typeof HTMLElementCollection` returns function in Safari, but
-    `Y.Lang.type()` reports "object", which could be a good thing --
-    but it actually caused the logic in <code>Y.Lang.isObject</code> to fail.
-
-@method type
-@param o the item to test.
-@return {string} the detected type.
-@static
-**/
-L.type = function(o) {
-    return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
-};
-/**
-@module yui
-@submodule yui-base
-*/
-
-var Lang   = Y.Lang,
-    Native = Array.prototype,
-
-    hasOwn = Object.prototype.hasOwnProperty;
-
-/**
-Provides utility methods for working with arrays. Additional array helpers can
-be found in the `collection` and `array-extras` modules.
-
-`Y.Array(thing)` returns a native array created from _thing_. Depending on
-_thing_'s type, one of the following will happen:
-
-  * Arrays are returned unmodified unless a non-zero _startIndex_ is
-    specified.
-  * Array-like collections (see `Array.test()`) are converted to arrays.
-  * For everything else, a new array is created with _thing_ as the sole
-    item.
-
-Note: elements that are also collections, such as `<form>` and `<select>`
-elements, are not automatically converted to arrays. To force a conversion,
-pass `true` as the value of the _force_ parameter.
-
-@class Array
-@constructor
-@param {Any} thing The thing to arrayify.
-@param {Number} [startIndex=0] If non-zero and _thing_ is an array or array-like
-  collection, a subset of items starting at the specified index will be
-  returned.
-@param {Boolean} [force=false] If `true`, _thing_ will be treated as an
-  array-like collection no matter what.
-@return {Array} A native array created from _thing_, according to the rules
-  described above.
-**/
-function YArray(thing, startIndex, force) {
-    var len, result;
-
-    /*jshint expr: true*/
-    startIndex || (startIndex = 0);
-
-    if (force || YArray.test(thing)) {
-        // IE throws when trying to slice HTMLElement collections.
-        try {
-            return Native.slice.call(thing, startIndex);
-        } catch (ex) {
-            result = [];
-
-            for (len = thing.length; startIndex < len; ++startIndex) {
-                result.push(thing[startIndex]);
-            }
-
-            return result;
-        }
-    }
-
-    return [thing];
-}
-
-Y.Array = YArray;
-
-/**
-Dedupes an array of strings, returning an array that's guaranteed to contain
-only one copy of a given string.
-
-This method differs from `Array.unique()` in that it's optimized for use only
-with arrays consisting entirely of strings or entirely of numbers, whereas
-`unique` may be used with other value types (but is slower).
-
-Using `dedupe()` with values other than strings or numbers, or with arrays
-containing a mix of strings and numbers, may result in unexpected behavior.
-
-@method dedupe
-@param {String[]|Number[]} array Array of strings or numbers to dedupe.
-@return {Array} Copy of _array_ containing no duplicate values.
-@static
-@since 3.4.0
-**/
-YArray.dedupe = Lang._isNative(Object.create) ? function (array) {
-    var hash    = Object.create(null),
-        results = [],
-        i, item, len;
-
-    for (i = 0, len = array.length; i < len; ++i) {
-        item = array[i];
-
-        if (!hash[item]) {
-            hash[item] = 1;
-            results.push(item);
-        }
-    }
-
-    return results;
-} : function (array) {
-    var hash    = {},
-        results = [],
-        i, item, len;
-
-    for (i = 0, len = array.length; i < len; ++i) {
-        item = array[i];
-
-        if (!hasOwn.call(hash, item)) {
-            hash[item] = 1;
-            results.push(item);
-        }
-    }
-
-    return results;
-};
-
-/**
-Executes the supplied function on each item in the array. This method wraps
-the native ES5 `Array.forEach()` method if available.
-
-@method each
-@param {Array} array Array to iterate.
-@param {Function} fn Function to execute on each item in the array. The function
-  will receive the following arguments:
-    @param {Any} fn.item Current array item.
-    @param {Number} fn.index Current array index.
-    @param {Array} fn.array Array being iterated.
-@param {Object} [thisObj] `this` object to use when calling _fn_.
-@return {YUI} The YUI instance.
-@static
-**/
-YArray.each = YArray.forEach = Lang._isNative(Native.forEach) ? function (array, fn, thisObj) {
-    Native.forEach.call(array || [], fn, thisObj || Y);
-    return Y;
-} : function (array, fn, thisObj) {
-    for (var i = 0, len = (array && array.length) || 0; i < len; ++i) {
-        if (i in array) {
-            fn.call(thisObj || Y, array[i], i, array);
-        }
-    }
-
-    return Y;
-};
-
-/**
-Alias for `each()`.
-
-@method forEach
-@static
-**/
-
-/**
-Returns an object using the first array as keys and the second as values. If
-the second array is not provided, or if it doesn't contain the same number of
-values as the first array, then `true` will be used in place of the missing
-values.
-
-@example
-
-    Y.Array.hash(['a', 'b', 'c'], ['foo', 'bar']);
-    // => {a: 'foo', b: 'bar', c: true}
-
-@method hash
-@param {String[]} keys Array of strings to use as keys.
-@param {Array} [values] Array to use as values.
-@return {Object} Hash using the first array as keys and the second as values.
-@static
-**/
-YArray.hash = function (keys, values) {
-    var hash = {},
-        vlen = (values && values.length) || 0,
-        i, len;
-
-    for (i = 0, len = keys.length; i < len; ++i) {
-        if (i in keys) {
-            hash[keys[i]] = vlen > i && i in values ? values[i] : true;
-        }
-    }
-
-    return hash;
-};
-
-/**
-Returns the index of the first item in the array that's equal (using a strict
-equality check) to the specified _value_, or `-1` if the value isn't found.
-
-This method wraps the native ES5 `Array.indexOf()` method if available.
-
-@method indexOf
-@param {Array} array Array to search.
-@param {Any} value Value to search for.
-@param {Number} [from=0] The index at which to begin the search.
-@return {Number} Index of the item strictly equal to _value_, or `-1` if not
-    found.
-@static
-**/
-YArray.indexOf = Lang._isNative(Native.indexOf) ? function (array, value, from) {
-    return Native.indexOf.call(array, value, from);
-} : function (array, value, from) {
-    // http://es5.github.com/#x15.4.4.14
-    var len = array.length;
-
-    from = +from || 0;
-    from = (from > 0 || -1) * Math.floor(Math.abs(from));
-
-    if (from < 0) {
-        from += len;
-
-        if (from < 0) {
-            from = 0;
-        }
-    }
-
-    for (; from < len; ++from) {
-        if (from in array && array[from] === value) {
-            return from;
-        }
-    }
-
-    return -1;
-};
-
-/**
-Numeric sort convenience function.
-
-The native `Array.prototype.sort()` function converts values to strings and
-sorts them in lexicographic order, which is unsuitable for sorting numeric
-values. Provide `Array.numericSort` as a custom sort function when you want
-to sort values in numeric order.
-
-@example
-
-    [42, 23, 8, 16, 4, 15].sort(Y.Array.numericSort);
-    // => [4, 8, 15, 16, 23, 42]
-
-@method numericSort
-@param {Number} a First value to compare.
-@param {Number} b Second value to compare.
-@return {Number} Difference between _a_ and _b_.
-@static
-**/
-YArray.numericSort = function (a, b) {
-    return a - b;
-};
-
-/**
-Executes the supplied function on each item in the array. Returning a truthy
-value from the function will stop the processing of remaining items.
-
-@method some
-@param {Array} array Array to iterate over.
-@param {Function} fn Function to execute on each item. The function will receive
-  the following arguments:
-    @param {Any} fn.value Current array item.
-    @param {Number} fn.index Current array index.
-    @param {Array} fn.array Array being iterated over.
-@param {Object} [thisObj] `this` object to use when calling _fn_.
-@return {Boolean} `true` if the function returns a truthy value on any of the
-  items in the array; `false` otherwise.
-@static
-**/
-YArray.some = Lang._isNative(Native.some) ? function (array, fn, thisObj) {
-    return Native.some.call(array, fn, thisObj);
-} : function (array, fn, thisObj) {
-    for (var i = 0, len = array.length; i < len; ++i) {
-        if (i in array && fn.call(thisObj, array[i], i, array)) {
-            return true;
-        }
-    }
-
-    return false;
-};
-
-/**
-Evaluates _obj_ to determine if it's an array, an array-like collection, or
-something else. This is useful when working with the function `arguments`
-collection and `HTMLElement` collections.
-
-Note: This implementation doesn't consider elements that are also
-collections, such as `<form>` and `<select>`, to be array-like.
-
-@method test
-@param {Object} obj Object to test.
-@return {Number} A number indicating the results of the test:
-
-  * 0: Neither an array nor an array-like collection.
-  * 1: Real array.
-  * 2: Array-like collection.
-
-@static
-**/
-YArray.test = function (obj) {
-    var result = 0;
-
-    if (Lang.isArray(obj)) {
-        result = 1;
-    } else if (Lang.isObject(obj)) {
-        try {
-            // indexed, but no tagName (element) or scrollTo/document (window. From DOM.isWindow test which we can't use here),
-            // or functions without apply/call (Safari
-            // HTMLElementCollection bug).
-            if ('length' in obj && !obj.tagName && !(obj.scrollTo && obj.document) && !obj.apply) {
-                result = 2;
-            }
-        } catch (ex) {}
-    }
-
-    return result;
-};
-/**
- * The YUI module contains the components required for building the YUI
- * seed file.  This includes the script loading mechanism, a simple queue,
- * and the core utilities for the library.
- * @module yui
- * @submodule yui-base
- */
-
-/**
- * A simple FIFO queue.  Items are added to the Queue with add(1..n items) and
- * removed using next().
- *
- * @class Queue
- * @constructor
- * @param {MIXED} item* 0..n items to seed the queue.
- */
-function Queue() {
-    this._init();
-    this.add.apply(this, arguments);
-}
-
-Queue.prototype = {
-    /**
-     * Initialize the queue
-     *
-     * @method _init
-     * @protected
-     */
-    _init: function() {
-        /**
-         * The collection of enqueued items
-         *
-         * @property _q
-         * @type Array
-         * @protected
-         */
-        this._q = [];
-    },
-
-    /**
-     * Get the next item in the queue. FIFO support
-     *
-     * @method next
-     * @return {MIXED} the next item in the queue.
-     */
-    next: function() {
-        return this._q.shift();
-    },
-
-    /**
-     * Get the last in the queue. LIFO support.
-     *
-     * @method last
-     * @return {MIXED} the last item in the queue.
-     */
-    last: function() {
-        return this._q.pop();
-    },
-
-    /**
-     * Add 0..n items to the end of the queue.
-     *
-     * @method add
-     * @param {MIXED} item* 0..n items.
-     * @return {object} this queue.
-     */
-    add: function() {
-        this._q.push.apply(this._q, arguments);
-
-        return this;
-    },
-
-    /**
-     * Returns the current number of queued items.
-     *
-     * @method size
-     * @return {Number} The size.
-     */
-    size: function() {
-        return this._q.length;
-    }
-};
-
-Y.Queue = Queue;
-
-YUI.Env._loaderQueue = YUI.Env._loaderQueue || new Queue();
-
-/**
-The YUI module contains the components required for building the YUI seed file.
-This includes the script loading mechanism, a simple queue, and the core
-utilities for the library.
-
-@module yui
-@submodule yui-base
-**/
-
-var CACHED_DELIMITER = '__',
-
-    hasOwn   = Object.prototype.hasOwnProperty,
-    isObject = Y.Lang.isObject;
-
-/**
-Returns a wrapper for a function which caches the return value of that function,
-keyed off of the combined string representation of the argument values provided
-when the wrapper is called.
-
-Calling this function again with the same arguments will return the cached value
-rather than executing the wrapped function.
-
-Note that since the cache is keyed off of the string representation of arguments
-passed to the wrapper function, arguments that aren't strings and don't provide
-a meaningful `toString()` method may result in unexpected caching behavior. For
-example, the objects `{}` and `{foo: 'bar'}` would both be converted to the
-string `[object Object]` when used as a cache key.
-
-@method cached
-@param {Function} source The function to memoize.
-@param {Object} [cache={}] Object in which to store cached values. You may seed
-  this object with pre-existing cached values if desired.
-@param {any} [refetch] If supplied, this value is compared with the cached value
-  using a `==` comparison. If the values are equal, the wrapped function is
-  executed again even though a cached value exists.
-@return {Function} Wrapped function.
-@for YUI
-**/
-Y.cached = function (source, cache, refetch) {
-    /*jshint expr: true*/
-    cache || (cache = {});
-
-    return function (arg) {
-        var key = arguments.length > 1 ?
-                Array.prototype.join.call(arguments, CACHED_DELIMITER) :
-                String(arg);
-        
-        /*jshint eqeqeq: false*/
-        if (!(key in cache) || (refetch && cache[key] == refetch)) {
-            cache[key] = source.apply(source, arguments);
-        }
-
-        return cache[key];
-    };
-};
-
-/**
-Returns the `location` object from the window/frame in which this YUI instance
-operates, or `undefined` when executing in a non-browser environment
-(e.g. Node.js).
-
-It is _not_ recommended to hold references to the `window.location` object
-outside of the scope of a function in which its properties are being accessed or
-its methods are being called. This is because of a nasty bug/issue that exists
-in both Safari and MobileSafari browsers:
-[WebKit Bug 34679](https://bugs.webkit.org/show_bug.cgi?id=34679).
-
-@method getLocation
-@return {location} The `location` object from the window/frame in which this YUI
-    instance operates.
-@since 3.5.0
-**/
-Y.getLocation = function () {
-    // It is safer to look this up every time because yui-base is attached to a
-    // YUI instance before a user's config is applied; i.e. `Y.config.win` does
-    // not point the correct window object when this file is loaded.
-    var win = Y.config.win;
-
-    // It is not safe to hold a reference to the `location` object outside the
-    // scope in which it is being used. The WebKit engine used in Safari and
-    // MobileSafari will "disconnect" the `location` object from the `window`
-    // when a page is restored from back/forward history cache.
-    return win && win.location;
-};
-
-/**
-Returns a new object containing all of the properties of all the supplied
-objects. The properties from later objects will overwrite those in earlier
-objects.
-
-Passing in a single object will create a shallow copy of it. For a deep copy,
-use `clone()`.
-
-@method merge
-@param {Object} objects* One or more objects to merge.
-@return {Object} A new merged object.
-**/
-Y.merge = function () {
-    var i      = 0,
-        len    = arguments.length,
-        result = {},
-        key,
-        obj;
-
-    for (; i < len; ++i) {
-        obj = arguments[i];
-
-        for (key in obj) {
-            if (hasOwn.call(obj, key)) {
-                result[key] = obj[key];
-            }
-        }
-    }
-
-    return result;
-};
-
-/**
-Mixes _supplier_'s properties into _receiver_.
-
-Properties on _receiver_ or _receiver_'s prototype will not be overwritten or
-shadowed unless the _overwrite_ parameter is `true`, and will not be merged
-unless the _merge_ parameter is `true`.
-
-In the default mode (0), only properties the supplier owns are copied (prototype
-properties are not copied). The following copying modes are available:
-
-  * `0`: _Default_. Object to object.
-  * `1`: Prototype to prototype.
-  * `2`: Prototype to prototype and object to object.
-  * `3`: Prototype to object.
-  * `4`: Object to prototype.
-
-@method mix
-@param {Function|Object} receiver The object or function to receive the mixed
-  properties.
-@param {Function|Object} supplier The object or function supplying the
-  properties to be mixed.
-@param {Boolean} [overwrite=false] If `true`, properties that already exist
-  on the receiver will be overwritten with properties from the supplier.
-@param {String[]} [whitelist] An array of property names to copy. If
-  specified, only the whitelisted properties will be copied, and all others
-  will be ignored.
-@param {Number} [mode=0] Mix mode to use. See above for available modes.
-@param {Boolean} [merge=false] If `true`, objects and arrays that already
-  exist on the receiver will have the corresponding object/array from the
-  supplier merged into them, rather than being skipped or overwritten. When
-  both _overwrite_ and _merge_ are `true`, _merge_ takes precedence.
-@return {Function|Object|YUI} The receiver, or the YUI instance if the
-  specified receiver is falsy.
-**/
-Y.mix = function(receiver, supplier, overwrite, whitelist, mode, merge) {
-    var alwaysOverwrite, exists, from, i, key, len, to;
-
-    // If no supplier is given, we return the receiver. If no receiver is given,
-    // we return Y. Returning Y doesn't make much sense to me, but it's
-    // grandfathered in for backcompat reasons.
-    if (!receiver || !supplier) {
-        return receiver || Y;
-    }
-
-    if (mode) {
-        // In mode 2 (prototype to prototype and object to object), we recurse
-        // once to do the proto to proto mix. The object to object mix will be
-        // handled later on.
-        if (mode === 2) {
-            Y.mix(receiver.prototype, supplier.prototype, overwrite,
-                    whitelist, 0, merge);
-        }
-
-        // Depending on which mode is specified, we may be copying from or to
-        // the prototypes of the supplier and receiver.
-        from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
-        to   = mode === 1 || mode === 4 ? receiver.prototype : receiver;
-
-        // If either the supplier or receiver doesn't actually have a
-        // prototype property, then we could end up with an undefined `from`
-        // or `to`. If that happens, we abort and return the receiver.
-        if (!from || !to) {
-            return receiver;
-        }
-    } else {
-        from = supplier;
-        to   = receiver;
-    }
-
-    // If `overwrite` is truthy and `merge` is falsy, then we can skip a
-    // property existence check on each iteration and save some time.
-    alwaysOverwrite = overwrite && !merge;
-
-    if (whitelist) {
-        for (i = 0, len = whitelist.length; i < len; ++i) {
-            key = whitelist[i];
-
-            // We call `Object.prototype.hasOwnProperty` instead of calling
-            // `hasOwnProperty` on the object itself, since the object's
-            // `hasOwnProperty` method may have been overridden or removed.
-            // Also, some native objects don't implement a `hasOwnProperty`
-            // method.
-            if (!hasOwn.call(from, key)) {
-                continue;
-            }
-
-            // The `key in to` check here is (sadly) intentional for backwards
-            // compatibility reasons. It prevents undesired shadowing of
-            // prototype members on `to`.
-            exists = alwaysOverwrite ? false : key in to;
-
-            if (merge && exists && isObject(to[key], true)
-                    && isObject(from[key], true)) {
-                // If we're in merge mode, and the key is present on both
-                // objects, and the value on both objects is either an object or
-                // an array (but not a function), then we recurse to merge the
-                // `from` value into the `to` value instead of overwriting it.
-                //
-                // Note: It's intentional that the whitelist isn't passed to the
-                // recursive call here. This is legacy behavior that lots of
-                // code still depends on.
-                Y.mix(to[key], from[key], overwrite, null, 0, merge);
-            } else if (overwrite || !exists) {
-                // We're not in merge mode, so we'll only copy the `from` value
-                // to the `to` value if we're in overwrite mode or if the
-                // current key doesn't exist on the `to` object.
-                to[key] = from[key];
-            }
-        }
-    } else {
-        for (key in from) {
-            // The code duplication here is for runtime performance reasons.
-            // Combining whitelist and non-whitelist operations into a single
-            // loop or breaking the shared logic out into a function both result
-            // in worse performance, and Y.mix is critical enough that the byte
-            // tradeoff is worth it.
-            if (!hasOwn.call(from, key)) {
-                continue;
-            }
-
-            // The `key in to` check here is (sadly) intentional for backwards
-            // compatibility reasons. It prevents undesired shadowing of
-            // prototype members on `to`.
-            exists = alwaysOverwrite ? false : key in to;
-
-            if (merge && exists && isObject(to[key], true)
-                    && isObject(from[key], true)) {
-                Y.mix(to[key], from[key], overwrite, null, 0, merge);
-            } else if (overwrite || !exists) {
-                to[key] = from[key];
-            }
-        }
-
-        // If this is an IE browser with the JScript enumeration bug, force
-        // enumeration of the buggy properties by making a recursive call with
-        // the buggy properties as the whitelist.
-        if (Y.Object._hasEnumBug) {
-            Y.mix(to, from, overwrite, Y.Object._forceEnum, mode, merge);
-        }
-    }
-
-    return receiver;
-};
-/**
- * The YUI module contains the components required for building the YUI
- * seed file.  This includes the script loading mechanism, a simple queue,
- * and the core utilities for the library.
- * @module yui
- * @submodule yui-base
- */
-
-/**
- * Adds utilities to the YUI instance for working with objects.
- *
- * @class Object
- */
-
-var Lang   = Y.Lang,
-    hasOwn = Object.prototype.hasOwnProperty,
-
-    UNDEFINED, // <-- Note the comma. We're still declaring vars.
-
-/**
- * Returns a new object that uses _obj_ as its prototype. This method wraps the
- * native ES5 `Object.create()` method if available, but doesn't currently
- * pass through `Object.create()`'s second argument (properties) in order to
- * ensure compatibility with older browsers.
- *
- * @method ()
- * @param {Object} obj Prototype object.
- * @return {Object} New object using _obj_ as its prototype.
- * @static
- */
-O = Y.Object = Lang._isNative(Object.create) ? function (obj) {
-    // We currently wrap the native Object.create instead of simply aliasing it
-    // to ensure consistency with our fallback shim, which currently doesn't
-    // support Object.create()'s second argument (properties). Once we have a
-    // safe fallback for the properties arg, we can stop wrapping
-    // Object.create().
-    return Object.create(obj);
-} : (function () {
-    // Reusable constructor function for the Object.create() shim.
-    function F() {}
-
-    // The actual shim.
-    return function (obj) {
-        F.prototype = obj;
-        return new F();
-    };
-}()),
-
-/**
- * Property names that IE doesn't enumerate in for..in loops, even when they
- * should be enumerable. When `_hasEnumBug` is `true`, it's necessary to
- * manually enumerate these properties.
- *
- * @property _forceEnum
- * @type String[]
- * @protected
- * @static
- */
-forceEnum = O._forceEnum = [
-    'hasOwnProperty',
-    'isPrototypeOf',
-    'propertyIsEnumerable',
-    'toString',
-    'toLocaleString',
-    'valueOf'
-],
-
-/**
- * `true` if this browser has the JScript enumeration bug that prevents
- * enumeration of the properties named in the `_forceEnum` array, `false`
- * otherwise.
- *
- * See:
- *   - <https://developer.mozilla.org/en/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug>
- *   - <http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation>
- *
- * @property _hasEnumBug
- * @type Boolean
- * @protected
- * @static
- */
-hasEnumBug = O._hasEnumBug = !{valueOf: 0}.propertyIsEnumerable('valueOf'),
-
-/**
- * `true` if this browser incorrectly considers the `prototype` property of
- * functions to be enumerable. Currently known to affect Opera 11.50 and Android 2.3.x.
- *
- * @property _hasProtoEnumBug
- * @type Boolean
- * @protected
- * @static
- */
-hasProtoEnumBug = O._hasProtoEnumBug = (function () {}).propertyIsEnumerable('prototype'),
-
-/**
- * Returns `true` if _key_ exists on _obj_, `false` if _key_ doesn't exist or
- * exists only on _obj_'s prototype. This is essentially a safer version of
- * `obj.hasOwnProperty()`.
- *
- * @method owns
- * @param {Object} obj Object to test.
- * @param {String} key Property name to look for.
- * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
- * @static
- */
-owns = O.owns = function (obj, key) {
-    return !!obj && hasOwn.call(obj, key);
-}; // <-- End of var declarations.
-
-/**
- * Alias for `owns()`.
- *
- * @method hasKey
- * @param {Object} obj Object to test.
- * @param {String} key Property name to look for.
- * @return {Boolean} `true` if _key_ exists on _obj_, `false` otherwise.
- * @static
- */
-O.hasKey = owns;
-
-/**
- * Returns an array containing the object's enumerable keys. Does not include
- * prototype keys or non-enumerable keys.
- *
- * Note that keys are returned in enumeration order (that is, in the same order
- * that they would be enumerated by a `for-in` loop), which may not be the same
- * as the order in which they were defined.
- *
- * This method is an alias for the native ES5 `Object.keys()` method if
- * available and non-buggy. The Opera 11.50 and Android 2.3.x versions of 
- * `Object.keys()` have an inconsistency as they consider `prototype` to be 
- * enumerable, so a non-native shim is used to rectify the difference.
- *
- * @example
- *
- *     Y.Object.keys({a: 'foo', b: 'bar', c: 'baz'});
- *     // => ['a', 'b', 'c']
- *
- * @method keys
- * @param {Object} obj An object.
- * @return {String[]} Array of keys.
- * @static
- */
-O.keys = Lang._isNative(Object.keys) && !hasProtoEnumBug ? Object.keys : function (obj) {
-    if (!Lang.isObject(obj)) {
-        throw new TypeError('Object.keys called on a non-object');
-    }
-
-    var keys = [],
-        i, key, len;
-
-    if (hasProtoEnumBug && typeof obj === 'function') {
-        for (key in obj) {
-            if (owns(obj, key) && key !== 'prototype') {
-                keys.push(key);
-            }
-        }
-    } else {
-        for (key in obj) {
-            if (owns(obj, key)) {
-                keys.push(key);
-            }
-        }
-    }
-
-    if (hasEnumBug) {
-        for (i = 0, len = forceEnum.length; i < len; ++i) {
-            key = forceEnum[i];
-
-            if (owns(obj, key)) {
-                keys.push(key);
-            }
-        }
-    }
-
-    return keys;
-};
-
-/**
- * Returns an array containing the values of the object's enumerable keys.
- *
- * Note that values are returned in enumeration order (that is, in the same
- * order that they would be enumerated by a `for-in` loop), which may not be the
- * same as the order in which they were defined.
- *
- * @example
- *
- *     Y.Object.values({a: 'foo', b: 'bar', c: 'baz'});
- *     // => ['foo', 'bar', 'baz']
- *
- * @method values
- * @param {Object} obj An object.
- * @return {Array} Array of values.
- * @static
- */
-O.values = function (obj) {
-    var keys   = O.keys(obj),
-        i      = 0,
-        len    = keys.length,
-        values = [];
-
-    for (; i < len; ++i) {
-        values.push(obj[keys[i]]);
-    }
-
-    return values;
-};
-
-/**
- * Returns the number of enumerable keys owned by an object.
- *
- * @method size
- * @param {Object} obj An object.
- * @return {Number} The object's size.
- * @static
- */
-O.size = function (obj) {
-    try {
-        return O.keys(obj).length;
-    } catch (ex) {
-        return 0; // Legacy behavior for non-objects.
-    }
-};
-
-/**
- * Returns `true` if the object owns an enumerable property with the specified
- * value.
- *
- * @method hasValue
- * @param {Object} obj An object.
- * @param {any} value The value to search for.
- * @return {Boolean} `true` if _obj_ contains _value_, `false` otherwise.
- * @static
- */
-O.hasValue = function (obj, value) {
-    return Y.Array.indexOf(O.values(obj), value) > -1;
-};
-
-/**
- * Executes a function on each enumerable property in _obj_. The function
- * receives the value, the key, and the object itself as parameters (in that
- * order).
- *
- * By default, only properties owned by _obj_ are enumerated. To include
- * prototype properties, set the _proto_ parameter to `true`.
- *
- * @method each
- * @param {Object} obj Object to enumerate.
- * @param {Function} fn Function to execute on each enumerable property.
- *   @param {mixed} fn.value Value of the current property.
- *   @param {String} fn.key Key of the current property.
- *   @param {Object} fn.obj Object being enumerated.
- * @param {Object} [thisObj] `this` object to use when calling _fn_.
- * @param {Boolean} [proto=false] Include prototype properties.
- * @return {YUI} the YUI instance.
- * @chainable
- * @static
- */
-O.each = function (obj, fn, thisObj, proto) {
-    var key;
-
-    for (key in obj) {
-        if (proto || owns(obj, key)) {
-            fn.call(thisObj || Y, obj[key], key, obj);
-        }
-    }
-
-    return Y;
-};
-
-/**
- * Executes a function on each enumerable property in _obj_, but halts if the
- * function returns a truthy value. The function receives the value, the key,
- * and the object itself as paramters (in that order).
- *
- * By default, only properties owned by _obj_ are enumerated. To include
- * prototype properties, set the _proto_ parameter to `true`.
- *
- * @method some
- * @param {Object} obj Object to enumerate.
- * @param {Function} fn Function to execute on each enumerable property.
- *   @param {mixed} fn.value Value of the current property.
- *   @param {String} fn.key Key of the current property.
- *   @param {Object} fn.obj Object being enumerated.
- * @param {Object} [thisObj] `this` object to use when calling _fn_.
- * @param {Boolean} [proto=false] Include prototype properties.
- * @return {Boolean} `true` if any execution of _fn_ returns a truthy value,
- *   `false` otherwise.
- * @static
- */
-O.some = function (obj, fn, thisObj, proto) {
-    var key;
-
-    for (key in obj) {
-        if (proto || owns(obj, key)) {
-            if (fn.call(thisObj || Y, obj[key], key, obj)) {
-                return true;
-            }
-        }
-    }
-
-    return false;
-};
-
-/**
- * Retrieves the sub value at the provided path,
- * from the value object provided.
- *
- * @method getValue
- * @static
- * @param o The object from which to extract the property value.
- * @param path {Array} A path array, specifying the object traversal path
- * from which to obtain the sub value.
- * @return {Any} The value stored in the path, undefined if not found,
- * undefined if the source is not an object.  Returns the source object
- * if an empty path is provided.
- */
-O.getValue = function(o, path) {
-    if (!Lang.isObject(o)) {
-        return UNDEFINED;
-    }
-
-    var i,
-        p = Y.Array(path),
-        l = p.length;
-
-    for (i = 0; o !== UNDEFINED && i < l; i++) {
-        o = o[p[i]];
-    }
-
-    return o;
-};
-
-/**
- * Sets the sub-attribute value at the provided path on the
- * value object.  Returns the modified value object, or
- * undefined if the path is invalid.
- *
- * @method setValue
- * @static
- * @param o             The object on which to set the sub value.
- * @param path {Array}  A path array, specifying the object traversal path
- *                      at which to set the sub value.
- * @param val {Any}     The new value for the sub-attribute.
- * @return {Object}     The modified object, with the new sub value set, or
- *                      undefined, if the path was invalid.
- */
-O.setValue = function(o, path, val) {
-    var i,
-        p = Y.Array(path),
-        leafIdx = p.length - 1,
-        ref = o;
-
-    if (leafIdx >= 0) {
-        for (i = 0; ref !== UNDEFINED && i < leafIdx; i++) {
-            ref = ref[p[i]];
-        }
-
-        if (ref !== UNDEFINED) {
-            ref[p[i]] = val;
-        } else {
-            return UNDEFINED;
-        }
-    }
-
-    return o;
-};
-
-/**
- * Returns `true` if the object has no enumerable properties of its own.
- *
- * @method isEmpty
- * @param {Object} obj An object.
- * @return {Boolean} `true` if the object is empty.
- * @static
- * @since 3.2.0
- */
-O.isEmpty = function (obj) {
-    return !O.keys(Object(obj)).length;
-};
-/**
- * The YUI module contains the components required for building the YUI seed
- * file.  This includes the script loading mechanism, a simple queue, and the
- * core utilities for the library.
- * @module yui
- * @submodule yui-base
- */
-
-/**
- * YUI user agent detection.
- * Do not fork for a browser if it can be avoided.  Use feature detection when
- * you can.  Use the user agent as a last resort.  For all fields listed
- * as @type float, UA stores a version number for the browser engine,
- * 0 otherwise.  This value may or may not map to the version number of
- * the browser using the engine.  The value is presented as a float so
- * that it can easily be used for boolean evaluation as well as for
- * looking for a particular range of versions.  Because of this,
- * some of the granularity of the version info may be lost.  The fields that
- * are @type string default to null.  The API docs list the values that
- * these fields can have.
- * @class UA
- * @static
- */
-
-/**
-* Static method on `YUI.Env` for parsing a UA string.  Called at instantiation
-* to populate `Y.UA`.
-*
-* @static
-* @method parseUA
-* @param {String} [subUA=navigator.userAgent] UA string to parse
-* @return {Object} The Y.UA object
-*/
-YUI.Env.parseUA = function(subUA) {
-
-    var numberify = function(s) {
-            var c = 0;
-            return parseFloat(s.replace(/\./g, function() {
-                return (c++ === 1) ? '' : '.';
-            }));
-        },
-
-        win = Y.config.win,
-
-        nav = win && win.navigator,
-
-        o = {
-
-        /**
-         * Internet Explorer version number or 0.  Example: 6
-         * @property ie
-         * @type float
-         * @static
-         */
-        ie: 0,
-
-        /**
-         * Opera version number or 0.  Example: 9.2
-         * @property opera
-         * @type float
-         * @static
-         */
-        opera: 0,
-
-        /**
-         * Gecko engine revision number.  Will evaluate to 1 if Gecko
-         * is detected but the revision could not be found. Other browsers
-         * will be 0.  Example: 1.8
-         * <pre>
-         * Firefox 1.0.0.4: 1.7.8   <-- Reports 1.7
-         * Firefox 1.5.0.9: 1.8.0.9 <-- 1.8
-         * Firefox 2.0.0.3: 1.8.1.3 <-- 1.81
-         * Firefox 3.0   <-- 1.9
-         * Firefox 3.5   <-- 1.91
-         * </pre>
-         * @property gecko
-         * @type float
-         * @static
-         */
-        gecko: 0,
-
-        /**
-         * AppleWebKit version.  KHTML browsers that are not WebKit browsers
-         * will evaluate to 1, other browsers 0.  Example: 418.9
-         * <pre>
-         * Safari 1.3.2 (312.6): 312.8.1 <-- Reports 312.8 -- currently the
-         *                                   latest available for Mac OSX 10.3.
-         * Safari 2.0.2:         416     <-- hasOwnProperty introduced
-         * Safari 2.0.4:         418     <-- preventDefault fixed
-         * Safari 2.0.4 (419.3): 418.9.1 <-- One version of Safari may run
-         *                                   different versions of webkit
-         * Safari 2.0.4 (419.3): 419     <-- Tiger installations that have been
-         *                                   updated, but not updated
-         *                                   to the latest patch.
-         * Webkit 212 nightly:   522+    <-- Safari 3.0 precursor (with native
-         * SVG and many major issues fixed).
-         * Safari 3.0.4 (523.12) 523.12  <-- First Tiger release - automatic
-         * update from 2.x via the 10.4.11 OS patch.
-         * Webkit nightly 1/2008:525+    <-- Supports DOMContentLoaded event.
-         *                                   yahoo.com user agent hack removed.
-         * </pre>
-         * http://en.wikipedia.org/wiki/Safari_version_history
-         * @property webkit
-         * @type float
-         * @static
-         */
-        webkit: 0,
-
-        /**
-         * Safari will be detected as webkit, but this property will also
-         * be populated with the Safari version number
-         * @property safari
-         * @type float
-         * @static
-         */
-        safari: 0,
-
-        /**
-         * Chrome will be detected as webkit, but this property will also
-         * be populated with the Chrome version number
-         * @property chrome
-         * @type float
-         * @static
-         */
-        chrome: 0,
-
-        /**
-         * The mobile property will be set to a string containing any relevant
-         * user agent information when a modern mobile browser is detected.
-         * Currently limited to Safari on the iPhone/iPod Touch, Nokia N-series
-         * devices with the WebKit-based browser, and Opera Mini.
-         * @property mobile
-         * @type string
-         * @default null
-         * @static
-         */
-        mobile: null,
-
-        /**
-         * Adobe AIR version number or 0.  Only populated if webkit is detected.
-         * Example: 1.0
-         * @property air
-         * @type float
-         */
-        air: 0,
-        /**
-         * PhantomJS version number or 0.  Only populated if webkit is detected.
-         * Example: 1.0
-         * @property phantomjs
-         * @type float
-         */
-        phantomjs: 0,
-        /**
-         * Detects Apple iPad's OS version
-         * @property ipad
-         * @type float
-         * @static
-         */
-        ipad: 0,
-        /**
-         * Detects Apple iPhone's OS version
-         * @property iphone
-         * @type float
-         * @static
-         */
-        iphone: 0,
-        /**
-         * Detects Apples iPod's OS version
-         * @property ipod
-         * @type float
-         * @static
-         */
-        ipod: 0,
-        /**
-         * General truthy check for iPad, iPhone or iPod
-         * @property ios
-         * @type Boolean
-         * @default null
-         * @static
-         */
-        ios: null,
-        /**
-         * Detects Googles Android OS version
-         * @property android
-         * @type float
-         * @static
-         */
-        android: 0,
-        /**
-         * Detects Kindle Silk
-         * @property silk
-         * @type float
-         * @static
-         */
-        silk: 0,
-        /**
-         * Detects Kindle Silk Acceleration
-         * @property accel
-         * @type Boolean
-         * @static
-         */
-        accel: false,
-        /**
-         * Detects Palms WebOS version
-         * @property webos
-         * @type float
-         * @static
-         */
-        webos: 0,
-
-        /**
-         * Google Caja version number or 0.
-         * @property caja
-         * @type float
-         */
-        caja: nav && nav.cajaVersion,
-
-        /**
-         * Set to true if the page appears to be in SSL
-         * @property secure
-         * @type boolean
-         * @static
-         */
-        secure: false,
-
-        /**
-         * The operating system.  Currently only detecting windows or macintosh
-         * @property os
-         * @type string
-         * @default null
-         * @static
-         */
-        os: null,
-
-        /**
-         * The Nodejs Version
-         * @property nodejs
-         * @type float
-         * @default 0
-         * @static
-         */
-        nodejs: 0,
-        /**
-        * Window8/IE10 Application host environment
-        * @property winjs
-        * @type Boolean
-        * @static
-        */
-        winjs: !!((typeof Windows !== "undefined") && Windows.System),
-        /**
-        * Are touch/msPointer events available on this device
-        * @property touchEnabled
-        * @type Boolean
-        * @static
-        */
-        touchEnabled: false
-    },
-
-    ua = subUA || nav && nav.userAgent,
-
-    loc = win && win.location,
-
-    href = loc && loc.href,
-
-    m;
-
-    /**
-    * The User Agent string that was parsed
-    * @property userAgent
-    * @type String
-    * @static
-    */
-    o.userAgent = ua;
-
-
-    o.secure = href && (href.toLowerCase().indexOf('https') === 0);
-
-    if (ua) {
-
-        if ((/windows|win32/i).test(ua)) {
-            o.os = 'windows';
-        } else if ((/macintosh|mac_powerpc/i).test(ua)) {
-            o.os = 'macintosh';
-        } else if ((/android/i).test(ua)) {
-            o.os = 'android';
-        } else if ((/symbos/i).test(ua)) {
-            o.os = 'symbos';
-        } else if ((/linux/i).test(ua)) {
-            o.os = 'linux';
-        } else if ((/rhino/i).test(ua)) {
-            o.os = 'rhino';
-        }
-
-        // Modern KHTML browsers should qualify as Safari X-Grade
-        if ((/KHTML/).test(ua)) {
-            o.webkit = 1;
-        }
-        if ((/IEMobile|XBLWP7/).test(ua)) {
-            o.mobile = 'windows';
-        }
-        if ((/Fennec/).test(ua)) {
-            o.mobile = 'gecko';
-        }
-        // Modern WebKit browsers are at least X-Grade
-        m = ua.match(/AppleWebKit\/([^\s]*)/);
-        if (m && m[1]) {
-            o.webkit = numberify(m[1]);
-            o.safari = o.webkit;
-
-            if (/PhantomJS/.test(ua)) {
-                m = ua.match(/PhantomJS\/([^\s]*)/);
-                if (m && m[1]) {
-                    o.phantomjs = numberify(m[1]);
-                }
-            }
-
-            // Mobile browser check
-            if (/ Mobile\//.test(ua) || (/iPad|iPod|iPhone/).test(ua)) {
-                o.mobile = 'Apple'; // iPhone or iPod Touch
-
-                m = ua.match(/OS ([^\s]*)/);
-                if (m && m[1]) {
-                    m = numberify(m[1].replace('_', '.'));
-                }
-                o.ios = m;
-                o.os = 'ios';
-                o.ipad = o.ipod = o.iphone = 0;
-
-                m = ua.match(/iPad|iPod|iPhone/);
-                if (m && m[0]) {
-                    o[m[0].toLowerCase()] = o.ios;
-                }
-            } else {
-                m = ua.match(/NokiaN[^\/]*|webOS\/\d\.\d/);
-                if (m) {
-                    // Nokia N-series, webOS, ex: NokiaN95
-                    o.mobile = m[0];
-                }
-                if (/webOS/.test(ua)) {
-                    o.mobile = 'WebOS';
-                    m = ua.match(/webOS\/([^\s]*);/);
-                    if (m && m[1]) {
-                        o.webos = numberify(m[1]);
-                    }
-                }
-                if (/ Android/.test(ua)) {
-                    if (/Mobile/.test(ua)) {
-                        o.mobile = 'Android';
-                    }
-                    m = ua.match(/Android ([^\s]*);/);
-                    if (m && m[1]) {
-                        o.android = numberify(m[1]);
-                    }
-
-                }
-                if (/Silk/.test(ua)) {
-                    m = ua.match(/Silk\/([^\s]*)\)/);
-                    if (m && m[1]) {
-                        o.silk = numberify(m[1]);
-                    }
-                    if (!o.android) {
-                        o.android = 2.34; //Hack for desktop mode in Kindle
-                        o.os = 'Android';
-                    }
-                    if (/Accelerated=true/.test(ua)) {
-                        o.accel = true;
-                    }
-                }
-            }
-
-            m = ua.match(/OPR\/(\d+\.\d+)/);
-
-            if (m && m[1]) {
-                // Opera 15+ with Blink (pretends to be both Chrome and Safari)
-                o.opera = numberify(m[1]);
-            } else {
-                m = ua.match(/(Chrome|CrMo|CriOS)\/([^\s]*)/);
-
-                if (m && m[1] && m[2]) {
-                    o.chrome = numberify(m[2]); // Chrome
-                    o.safari = 0; //Reset safari back to 0
-                    if (m[1] === 'CrMo') {
-                        o.mobile = 'chrome';
-                    }
-                } else {
-                    m = ua.match(/AdobeAIR\/([^\s]*)/);
-                    if (m) {
-                        o.air = m[0]; // Adobe AIR 1.0 or better
-                    }
-                }
-            }
-        }
-
-        if (!o.webkit) { // not webkit
-// @todo check Opera/8.01 (J2ME/MIDP; Opera Mini/2.0.4509/1316; fi; U; ssr)
-            if (/Opera/.test(ua)) {
-                m = ua.match(/Opera[\s\/]([^\s]*)/);
-                if (m && m[1]) {
-                    o.opera = numberify(m[1]);
-                }
-                m = ua.match(/Version\/([^\s]*)/);
-                if (m && m[1]) {
-                    o.opera = numberify(m[1]); // opera 10+
-                }
-
-                if (/Opera Mobi/.test(ua)) {
-                    o.mobile = 'opera';
-                    m = ua.replace('Opera Mobi', '').match(/Opera ([^\s]*)/);
-                    if (m && m[1]) {
-                        o.opera = numberify(m[1]);
-                    }
-                }
-                m = ua.match(/Opera Mini[^;]*/);
-
-                if (m) {
-                    o.mobile = m[0]; // ex: Opera Mini/2.0.4509/1316
-                }
-            } else { // not opera or webkit
-                m = ua.match(/MSIE ([^;]*)|Trident.*; rv:([0-9.]+)/);
-
-                if (m && (m[1] || m[2])) {
-                    o.ie = numberify(m[1] || m[2]);
-                } else { // not opera, webkit, or ie
-                    m = ua.match(/Gecko\/([^\s]*)/);
-
-                    if (m) {
-                        o.gecko = 1; // Gecko detected, look for revision
-                        m = ua.match(/rv:([^\s\)]*)/);
-                        if (m && m[1]) {
-                            o.gecko = numberify(m[1]);
-                            if (/Mobile|Tablet/.test(ua)) {
-                                o.mobile = "ffos";
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    //Check for known properties to tell if touch events are enabled on this device or if
-    //the number of MSPointer touchpoints on this device is greater than 0.
-    if (win && nav && !(o.chrome && o.chrome < 6)) {
-        o.touchEnabled = (("ontouchstart" in win) || (("msMaxTouchPoints" in nav) && (nav.msMaxTouchPoints > 0)));
-    }
-
-    //It was a parsed UA, do not assign the global value.
-    if (!subUA) {
-
-        if (typeof process === 'object') {
-
-            if (process.versions && process.versions.node) {
-                //NodeJS
-                o.os = process.platform;
-                o.nodejs = numberify(process.versions.node);
-            }
-        }
-
-        YUI.Env.UA = o;
-
-    }
-
-    return o;
-};
-
-
-Y.UA = YUI.Env.UA || YUI.Env.parseUA();
-
-/**
-Performs a simple comparison between two version numbers, accounting for
-standard versioning logic such as the fact that "535.8" is a lower version than
-"535.24", even though a simple numerical comparison would indicate that it's
-greater. Also accounts for cases such as "1.1" vs. "1.1.0", which are
-considered equivalent.
-
-Returns -1 if version _a_ is lower than version _b_, 0 if they're equivalent,
-1 if _a_ is higher than _b_.
-
-Versions may be numbers or strings containing numbers and dots. For example,
-both `535` and `"535.8.10"` are acceptable. A version string containing
-non-numeric characters, like `"535.8.beta"`, may produce unexpected results.
-
-@method compareVersions
-@param {Number|String} a First version number to compare.
-@param {Number|String} b Second version number to compare.
-@return -1 if _a_ is lower than _b_, 0 if they're equivalent, 1 if _a_ is
-    higher than _b_.
-**/
-Y.UA.compareVersions = function (a, b) {
-    var aPart, aParts, bPart, bParts, i, len;
-
-    if (a === b) {
-        return 0;
-    }
-
-    aParts = (a + '').split('.');
-    bParts = (b + '').split('.');
-
-    for (i = 0, len = Math.max(aParts.length, bParts.length); i < len; ++i) {
-        aPart = parseInt(aParts[i], 10);
-        bPart = parseInt(bParts[i], 10);
-
-        /*jshint expr: true*/
-        isNaN(aPart) && (aPart = 0);
-        isNaN(bPart) && (bPart = 0);
-
-        if (aPart < bPart) {
-            return -1;
-        }
-
-        if (aPart > bPart) {
-            return 1;
-        }
-    }
-
-    return 0;
-};
-YUI.Env.aliases = {
-    "anim": ["anim-base","anim-color","anim-curve","anim-easing","anim-node-plugin","anim-scroll","anim-xy"],
-    "anim-shape-transform": ["anim-shape"],
-    "app": ["app-base","app-content","app-transitions","lazy-model-list","model","model-list","model-sync-rest","router","view","view-node-map"],
-    "attribute": ["attribute-base","attribute-complex"],
-    "attribute-events": ["attribute-observable"],
-    "autocomplete": ["autocomplete-base","autocomplete-sources","autocomplete-list","autocomplete-plugin"],
-    "axes": ["axis-numeric","axis-category","axis-time","axis-stacked"],
-    "axes-base": ["axis-numeric-base","axis-category-base","axis-time-base","axis-stacked-base"],
-    "base": ["base-base","base-pluginhost","base-build"],
-    "cache": ["cache-base","cache-offline","cache-plugin"],
-    "charts": ["charts-base"],
-    "collection": ["array-extras","arraylist","arraylist-add","arraylist-filter","array-invoke"],
-    "color": ["color-base","color-hsl","color-harmony"],
-    "controller": ["router"],
-    "dataschema": ["dataschema-base","dataschema-json","dataschema-xml","dataschema-array","dataschema-text"],
-    "datasource": ["datasource-local","datasource-io","datasource-get","datasource-function","datasource-cache","datasource-jsonschema","datasource-xmlschema","datasource-arrayschema","datasource-textschema","datasource-polling"],
-    "datatable": ["datatable-core","datatable-table","datatable-head","datatable-body","datatable-base","datatable-column-widths","datatable-message","datatable-mutable","datatable-sort","datatable-datasource"],
-    "datatype": ["datatype-date","datatype-number","datatype-xml"],
-    "datatype-date": ["datatype-date-parse","datatype-date-format","datatype-date-math"],
-    "datatype-number": ["datatype-number-parse","datatype-number-format"],
-    "datatype-xml": ["datatype-xml-parse","datatype-xml-format"],
-    "dd": ["dd-ddm-base","dd-ddm","dd-ddm-drop","dd-drag","dd-proxy","dd-constrain","dd-drop","dd-scroll","dd-delegate"],
-    "dom": ["dom-base","dom-screen","dom-style","selector-native","selector"],
-    "editor": ["frame","editor-selection","exec-command","editor-base","editor-para","editor-br","editor-bidi","editor-tab","createlink-base"],
-    "event": ["event-base","event-delegate","event-synthetic","event-mousewheel","event-mouseenter","event-key","event-focus","event-resize","event-hover","event-outside","event-touch","event-move","event-flick","event-valuechange","event-tap"],
-    "event-custom": ["event-custom-base","event-custom-complex"],
-    "event-gestures": ["event-flick","event-move"],
-    "handlebars": ["handlebars-compiler"],
-    "highlight": ["highlight-base","highlight-accentfold"],
-    "history": ["history-base","history-hash","history-hash-ie","history-html5"],
-    "io": ["io-base","io-xdr","io-form","io-upload-iframe","io-queue"],
-    "json": ["json-parse","json-stringify"],
-    "loader": ["loader-base","loader-rollup","loader-yui3"],
-    "node": ["node-base","node-event-delegate","node-pluginhost","node-screen","node-style"],
-    "pluginhost": ["pluginhost-base","pluginhost-config"],
-    "querystring": ["querystring-parse","querystring-stringify"],
-    "recordset": ["recordset-base","recordset-sort","recordset-filter","recordset-indexer"],
-    "resize": ["resize-base","resize-proxy","resize-constrain"],
-    "slider": ["slider-base","slider-value-range","clickable-rail","range-slider"],
-    "template": ["template-base","template-micro"],
-    "text": ["text-accentfold","text-wordbreak"],
-    "widget": ["widget-base","widget-htmlparser","widget-skin","widget-uievents"]
-};
-
-
-}, '3.12.0', {
-    "use": [
-        "yui-base",
-        "get",
-        "features",
-        "intl-base",
-        "yui-log",
-        "yui-later",
-        "loader-base",
-        "loader-rollup",
-        "loader-yui3"
-    ]
-});
-YUI.add('get', function (Y, NAME) {
-
-/*jslint boss:true, expr:true, laxbreak: true */
-
-/**
-Provides dynamic loading of remote JavaScript and CSS resources.
-
-@module get
-@class Get
-@static
-**/
-
-var Lang = Y.Lang,
-
-    CUSTOM_ATTRS, // defined lazily in Y.Get.Transaction._createNode()
-
-    Get, Transaction;
-
-Y.Get = Get = {
-    // -- Public Properties ----------------------------------------------------
-
-    /**
-    Default options for CSS requests. Options specified here will override
-    global defaults for CSS requests.
-
-    See the `options` property for all available options.
-
-    @property cssOptions
-    @type Object
-    @static
-    @since 3.5.0
-    **/
-    cssOptions: {
-        attributes: {
-            rel: 'stylesheet'
-        },
-
-        doc         : Y.config.linkDoc || Y.config.doc,
-        pollInterval: 50
-    },
-
-    /**
-    Default options for JS requests. Options specified here will override global
-    defaults for JS requests.
-
-    See the `options` property for all available options.
-
-    @property jsOptions
-    @type Object
-    @static
-    @since 3.5.0
-    **/
-    jsOptions: {
-        autopurge: true,
-        doc      : Y.config.scriptDoc || Y.config.doc
-    },
-
-    /**
-    Default options to use for all requests.
-
-    Note that while all available options are documented here for ease of
-    discovery, some options (like callback functions) only make sense at the
-    transaction level.
-
-    Callback functions specified via the options object or the `options`
-    parameter of the `css()`, `js()`, or `load()` methods will receive the
-    transaction object as a parameter. See `Y.Get.Transaction` for details on
-    the properties and methods available on transactions.
-
-    @static
-    @since 3.5.0
-    @property {Object} options
-
-    @property {Boolean} [options.async=false] Whether or not to load scripts
-        asynchronously, meaning they're requested in parallel and execution
-        order is not guaranteed. Has no effect on CSS, since CSS is always
-        loaded asynchronously.
-
-    @property {Object} [options.attributes] HTML attribute name/value pairs that
-        should be added to inserted nodes. By default, the `charset` attribute
-        will be set to "utf-8" and nodes will be given an auto-generated `id`
-        attribute, but you can override these with your own values if desired.
-
-    @property {Boolean} [options.autopurge] Whether or not to automatically
-        purge inserted nodes after the purge threshold is reached. This is
-        `true` by default for JavaScript, but `false` for CSS since purging a
-        CSS node will also remove any styling applied by the referenced file.
-
-    @property {Object} [options.context] `this` object to use when calling
-        callback functions. Defaults to the transaction object.
-
-    @property {Mixed} [options.data] Arbitrary data object to pass to "on*"
-        callbacks.
-
-    @property {Document} [options.doc] Document into which nodes should be
-        inserted. By default, the current document is used.
-
-    @property {HTMLElement|String} [options.insertBefore] HTML element or id
-        string of an element before which all generated nodes should be
-        inserted. If not specified, Get will automatically determine the best
-        place to insert nodes for maximum compatibility.
-
-    @property {Function} [options.onEnd] Callback to execute after a transaction
-        is complete, regardless of whether it succeeded or failed.
-
-    @property {Function} [options.onFailure] Callback to execute after a
-        transaction fails, times out, or is aborted.
-
-    @property {Function} [options.onProgress] Callback to execute after each
-        individual request in a transaction either succeeds or fails.
-
-    @property {Function} [options.onSuccess] Callback to execute after a
-        transaction completes successfully with no errors. Note that in browsers
-        that don't support the `error` event on CSS `<link>` nodes, a failed CSS
-        request may still be reported as a success because in these browsers
-        it can be difficult or impossible to distinguish between success and
-        failure for CSS resources.
-
-    @property {Function} [options.onTimeout] Callback to execute after a
-        transaction times out.
-
-    @property {Number} [options.pollInterval=50] Polling interval (in
-        milliseconds) for detecting CSS load completion in browsers that don't
-        support the `load` event on `<link>` nodes. This isn't used for
-        JavaScript.
-
-    @property {Number} [options.purgethreshold=20] Number of nodes to insert
-        before triggering an automatic purge when `autopurge` is `true`.
-
-    @property {Number} [options.timeout] Number of milliseconds to wait before
-        aborting a transaction. When a timeout occurs, the `onTimeout` callback
-        is called, followed by `onFailure` and finally `onEnd`. By default,
-        there is no timeout.
-
-    @property {String} [options.type] Resource type ("css" or "js"). This option
-        is set automatically by the `css()` and `js()` functions and will be
-        ignored there, but may be useful when using the `load()` function. If
-        not specified, the type will be inferred from the URL, defaulting to
-        "js" if the URL doesn't contain a recognizable file extension.
-    **/
-    options: {
-        attributes: {
-            charset: 'utf-8'
-        },
-
-        purgethreshold: 20
-    },
-
-    // -- Protected Properties -------------------------------------------------
-
-    /**
-    Regex that matches a CSS URL. Used to guess the file type when it's not
-    specified.
-
-    @property REGEX_CSS
-    @type RegExp
-    @final
-    @protected
-    @static
-    @since 3.5.0
-    **/
-    REGEX_CSS: /\.css(?:[?;].*)?$/i,
-
-    /**
-    Regex that matches a JS URL. Used to guess the file type when it's not
-    specified.
-
-    @property REGEX_JS
-    @type RegExp
-    @final
-    @protected
-    @static
-    @since 3.5.0
-    **/
-    REGEX_JS : /\.js(?:[?;].*)?$/i,
-
-    /**
-    Contains information about the current environment, such as what script and
-    link injection features it supports.
-
-    This object is created and populated the first time the `_getEnv()` method
-    is called.
-
-    @property _env
-    @type Object
-    @protected
-    @static
-    @since 3.5.0
-    **/
-
-    /**
-    Mapping of document _yuid strings to <head> or <base> node references so we
-    don't have to look the node up each time we want to insert a request node.
-
-    @property _insertCache
-    @type Object
-    @protected
-    @static
-    @since 3.5.0
-    **/
-    _insertCache: {},
-
-    /**
-    Information about the currently pending transaction, if any.
-
-    This is actually an object with two properties: `callback`, containing the
-    optional callback passed to `css()`, `load()`, or `js()`; and `transaction`,
-    containing the actual transaction instance.
-
-    @property _pending
-    @type Object
-    @protected
-    @static
-    @since 3.5.0
-    **/
-    _pending: null,
-
-    /**
-    HTML nodes eligible to be purged next time autopurge is triggered.
-
-    @property _purgeNodes
-    @type HTMLElement[]
-    @protected
-    @static
-    @since 3.5.0
-    **/
-    _purgeNodes: [],
-
-    /**
-    Queued transactions and associated callbacks.
-
-    @property _queue
-    @type Object[]
-    @protected
-    @static
-    @since 3.5.0
-    **/
-    _queue: [],
-
-    // -- Public Methods -------------------------------------------------------
-
-    /**
-    Aborts the specified transaction.
-
-    This will cause the transaction's `onFailure` callback to be called and
-    will prevent any new script and link nodes from being added to the document,
-    but any resources that have already been requested will continue loading
-    (there's no safe way to prevent this, unfortunately).
-
-    *Note:* This method is deprecated as of 3.5.0, and will be removed in a
-    future version of YUI. Use the transaction-level `abort()` method instead.
-
-    @method abort
-    @param {Get.Transaction} transaction Transaction to abort.
-    @deprecated Use the `abort()` method on the transaction instead.
-    @static
-    **/
-    abort: function (transaction) {
-        var i, id, item, len, pending;
-
-
-        if (!transaction.abort) {
-            id          = transaction;
-            pending     = this._pending;
-            transaction = null;
-
-            if (pending && pending.transaction.id === id) {
-                transaction   = pending.transaction;
-                this._pending = null;
-            } else {
-                for (i = 0, len = this._queue.length; i < len; ++i) {
-                    item = this._queue[i].transaction;
-
-                    if (item.id === id) {
-                        transaction = item;
-                        this._queue.splice(i, 1);
-                        break;
-                    }
-                }
-            }
-        }
-
-        transaction && transaction.abort();
-    },
-
-    /**
-    Loads one or more CSS files.
-
-    The _urls_ parameter may be provided as a URL string, a request object,
-    or an array of URL strings and/or request objects.
-
-    A request object is just an object that contains a `url` property and zero
-    or more options that should apply specifically to that request.
-    Request-specific options take priority over transaction-level options and
-    default options.
-
-    URLs may be relative or absolute, and do not have to have the same origin
-    as the current page.
-
-    The `options` parameter may be omitted completely and a callback passed in
-    its place, if desired.
-
-    @example
-
-        // Load a single CSS file and log a message on completion.
-        Y.Get.css('foo.css', function (err) {
-            if (err) {
-            } else {
-            }
-        });
-
-        // Load multiple CSS files and log a message when all have finished
-        // loading.
-        var urls = ['foo.css', 'http://example.com/bar.css', 'baz/quux.css'];
-
-        Y.Get.css(urls, function (err) {
-            if (err) {
-            } else {
-            }
-        });
-
-        // Specify transaction-level options, which will apply to all requests
-        // within the transaction.
-        Y.Get.css(urls, {
-            attributes: {'class': 'my-css'},
-            timeout   : 5000
-        });
-
-        // Specify per-request options, which override transaction-level and
-        // default options.
-        Y.Get.css([
-            {url: 'foo.css', attributes: {id: 'foo'}},
-            {url: 'bar.css', attributes: {id: 'bar', charset: 'iso-8859-1'}}
-        ]);
-
-    @method css
-    @param {String|Object|Array} urls URL string, request object, or array
-        of URLs and/or request objects to load.
-    @param {Object} [options] Options for this transaction. See the
-        `Y.Get.options` property for a complete list of available options.
-    @param {Function} [callback] Callback function to be called on completion.
-        This is a general callback and will be called before any more granular
-        callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
-        object.
-
-        @param {Array|null} callback.err Array of errors that occurred during
-            the transaction, or `null` on success.
-        @param {Get.Transaction} callback.transaction Transaction object.
-
-    @return {Get.Transaction} Transaction object.
-    @static
-    **/
-    css: function (urls, options, callback) {
-        return this._load('css', urls, options, callback);
-    },
-
-    /**
-    Loads one or more JavaScript resources.
-
-    The _urls_ parameter may be provided as a URL string, a request object,
-    or an array of URL strings and/or request objects.
-
-    A request object is just an object that contains a `url` property and zero
-    or more options that should apply specifically to that request.
-    Request-specific options take priority over transaction-level options and
-    default options.
-
-    URLs may be relative or absolute, and do not have to have the same origin
-    as the current page.
-
-    The `options` parameter may be omitted completely and a callback passed in
-    its place, if desired.
-
-    Scripts will be executed in the order they're specified unless the `async`
-    option is `true`, in which case they'll be loaded in parallel and executed
-    in whatever order they finish loading.
-
-    @example
-
-        // Load a single JS file and log a message on completion.
-        Y.Get.js('foo.js', function (err) {
-            if (err) {
-            } else {
-            }
-        });
-
-        // Load multiple JS files, execute them in order, and log a message when
-        // all have finished loading.
-        var urls = ['foo.js', 'http://example.com/bar.js', 'baz/quux.js'];
-
-        Y.Get.js(urls, function (err) {
-            if (err) {
-            } else {
-            }
-        });
-
-        // Specify transaction-level options, which will apply to all requests
-        // within the transaction.
-        Y.Get.js(urls, {
-            attributes: {'class': 'my-js'},
-            timeout   : 5000
-        });
-
-        // Specify per-request options, which override transaction-level and
-        // default options.
-        Y.Get.js([
-            {url: 'foo.js', attributes: {id: 'foo'}},
-            {url: 'bar.js', attributes: {id: 'bar', charset: 'iso-8859-1'}}
-        ]);
-
-    @method js
-    @param {String|Object|Array} urls URL string, request object, or array
-        of URLs and/or request objects to load.
-    @param {Object} [options] Options for this transaction. See the
-        `Y.Get.options` property for a complete list of available options.
-    @param {Function} [callback] Callback function to be called on completion.
-        This is a general callback and will be called before any more granular
-        callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
-        object.
-
-        @param {Array|null} callback.err Array of errors that occurred during
-            the transaction, or `null` on success.
-        @param {Get.Transaction} callback.transaction Transaction object.
-
-    @return {Get.Transaction} Transaction object.
-    @since 3.5.0
-    @static
-    **/
-    js: function (urls, options, callback) {
-        return this._load('js', urls, options, callback);
-    },
-
-    /**
-    Loads one or more CSS and/or JavaScript resources in the same transaction.
-
-    Use this method when you want to load both CSS and JavaScript in a single
-    transaction and be notified when all requested URLs have finished loading,
-    regardless of type.
-
-    Behavior and options are the same as for the `css()` and `js()` methods. If
-    a resource type isn't specified in per-request options or transaction-level
-    options, Get will guess the file type based on the URL's extension (`.css`
-    or `.js`, with or without a following query string). If the file type can't
-    be guessed from the URL, a warning will be logged and Get will assume the
-    URL is a JavaScript resource.
-
-    @example
-
-        // Load both CSS and JS files in a single transaction, and log a message
-        // when all files have finished loading.
-        Y.Get.load(['foo.css', 'bar.js', 'baz.css'], function (err) {
-            if (err) {
-            } else {
-            }
-        });
-
-    @method load
-    @param {String|Object|Array} urls URL string, request object, or array
-        of URLs and/or request objects to load.
-    @param {Object} [options] Options for this transaction. See the
-        `Y.Get.options` property for a complete list of available options.
-    @param {Function} [callback] Callback function to be called on completion.
-        This is a general callback and will be called before any more granular
-        callbacks (`onSuccess`, `onFailure`, etc.) specified in the `options`
-        object.
-
-        @param {Array|null} err Array of errors that occurred during the
-            transaction, or `null` on success.
-        @param {Get.Transaction} Transaction object.
-
-    @return {Get.Transaction} Transaction object.
-    @since 3.5.0
-    @static
-    **/
-    load: function (urls, options, callback) {
-        return this._load(null, urls, options, callback);
-    },
-
-    // -- Protected Methods ----------------------------------------------------
-
-    /**
-    Triggers an automatic purge if the purge threshold has been reached.
-
-    @method _autoPurge
-    @param {Number} threshold Purge threshold to use, in milliseconds.
-    @protected
-    @since 3.5.0
-    @static
-    **/
-    _autoPurge: function (threshold) {
-        if (threshold && this._purgeNodes.length >= threshold) {
-            this._purge(this._purgeNodes);
-        }
-    },
-
-    /**
-    Populates the `_env` property with information about the current
-    environment.
-
-    @method _getEnv
-    @return {Object} Environment information.
-    @protected
-    @since 3.5.0
-    @static
-    **/
-    _getEnv: function () {
-        var doc = Y.config.doc,
-            ua  = Y.UA;
-
-        // Note: some of these checks require browser sniffs since it's not
-        // feasible to load test files on every pageview just to perform a
-        // feature test. I'm sorry if this makes you sad.
-        return (this._env = {
-
-            // True if this is a browser that supports disabling async mode on
-            // dynamically created script nodes. See
-            // https://developer.mozilla.org/En/HTML/Element/Script#Attributes
-
-            // IE10 doesn't return true for the MDN feature test, so setting it explicitly,
-            // because it is async by default, and allows you to disable async by setting it to false
-            async: (doc && doc.createElement('script').async === true) || (ua.ie >= 10),
-
-            // True if this browser fires an event when a dynamically injected
-            // link node fails to load. This is currently true for Firefox 9+
-            // and WebKit 535.24+
-            cssFail: ua.gecko >= 9 || ua.compareVersions(ua.webkit, 535.24) >= 0,
-
-            // True if this browser fires an event when a dynamically injected
-            // link node finishes loading. This is currently true for IE, Opera,
-            // Firefox 9+, and WebKit 535.24+. Note that IE versions <9 fire the
-            // DOM 0 "onload" event, but not "load". All versions of IE fire
-            // "onload".
-            // davglass: Seems that Chrome on Android needs this to be false.
-            cssLoad: (
-                    (!ua.gecko && !ua.webkit) || ua.gecko >= 9 ||
-                    ua.compareVersions(ua.webkit, 535.24) >= 0
-                ) && !(ua.chrome && ua.chrome <= 18),
-
-            // True if this browser preserves script execution order while
-            // loading scripts in parallel as long as the script node's `async`
-            // attribute is set to false to explicitly disable async execution.
-            preservesScriptOrder: !!(ua.gecko || ua.opera || (ua.ie && ua.ie >= 10))
-        });
-    },
-
-    _getTransaction: function (urls, options) {
-        var requests = [],
-            i, len, req, url;
-
-        if (!Lang.isArray(urls)) {
-            urls = [urls];
-        }
-
-        options = Y.merge(this.options, options);
-
-        // Clone the attributes object so we don't end up modifying it by ref.
-        options.attributes = Y.merge(this.options.attributes,
-                options.attributes);
-
-        for (i = 0, len = urls.length; i < len; ++i) {
-            url = urls[i];
-            req = {attributes: {}};
-
-            // If `url` is a string, we create a URL object for it, then mix in
-            // global options and request-specific options. If it's an object
-            // with a "url" property, we assume it's a request object containing
-            // URL-specific options.
-            if (typeof url === 'string') {
-                req.url = url;
-            } else if (url.url) {
-                // URL-specific options override both global defaults and
-                // request-specific options.
-                Y.mix(req, url, false, null, 0, true);
-                url = url.url; // Make url a string so we can use it later.
-            } else {
-                continue;
-            }
-
-            Y.mix(req, options, false, null, 0, true);
-
-            // If we didn't get an explicit type for this URL either in the
-            // request options or the URL-specific options, try to determine
-            // one from the file extension.
-            if (!req.type) {
-                if (this.REGEX_CSS.test(url)) {
-                    req.type = 'css';
-                } else {
-                    if (!this.REGEX_JS.test(url)) {
-                    }
-
-                    req.type = 'js';
-                }
-            }
-
-            // Mix in type-specific default options, but don't overwrite any
-            // options that have already been set.
-            Y.mix(req, req.type === 'js' ? this.jsOptions : this.cssOptions,
-                false, null, 0, true);
-
-            // Give the node an id attribute if it doesn't already have one.
-            req.attributes.id || (req.attributes.id = Y.guid());
-
-            // Backcompat for <3.5.0 behavior.
-            if (req.win) {
-                req.doc = req.win.document;
-            } else {
-                req.win = req.doc.defaultView || req.doc.parentWindow;
-            }
-
-            if (req.charset) {
-                req.attributes.charset = req.charset;
-            }
-
-            requests.push(req);
-        }
-
-        return new Transaction(requests, options);
-    },
-
-    _load: function (type, urls, options, callback) {
-        var transaction;
-
-        // Allow callback as third param.
-        if (typeof options === 'function') {
-            callback = options;
-            options  = {};
-        }
-
-        options || (options = {});
-        options.type = type;
-
-        options._onFinish = Get._onTransactionFinish;
-
-        if (!this._env) {
-            this._getEnv();
-        }
-
-        transaction = this._getTransaction(urls, options);
-
-        this._queue.push({
-            callback   : callback,
-            transaction: transaction
-        });
-
-        this._next();
-
-        return transaction;
-    },
-
-    _onTransactionFinish : function() {
-        Get._pending = null;
-        Get._next();
-    },
-
-    _next: function () {
-        var item;
-
-        if (this._pending) {
-            return;
-        }
-
-        item = this._queue.shift();
-
-        if (item) {
-            this._pending = item;
-            item.transaction.execute(item.callback);
-        }
-    },
-
-    _purge: function (nodes) {
-        var purgeNodes    = this._purgeNodes,
-            isTransaction = nodes !== purgeNodes,
-            index, node;
-
-        while (node = nodes.pop()) { // assignment
-            // Don't purge nodes that haven't finished loading (or errored out),
-            // since this can hang the transaction.
-            if (!node._yuiget_finished) {
-                continue;
-            }
-
-            node.parentNode && node.parentNode.removeChild(node);
-
-            // If this is a transaction-level purge and this node also exists in
-            // the Get-level _purgeNodes array, we need to remove it from
-            // _purgeNodes to avoid creating a memory leak. The indexOf lookup
-            // sucks, but until we get WeakMaps, this is the least troublesome
-            // way to do this (we can't just hold onto node ids because they may
-            // not be in the same document).
-            if (isTransaction) {
-                index = Y.Array.indexOf(purgeNodes, node);
-
-                if (index > -1) {
-                    purgeNodes.splice(index, 1);
-                }
-            }
-        }
-    }
-};
-
-/**
-Alias for `js()`.
-
-@method script
-@static
-**/
-Get.script = Get.js;
-
-/**
-Represents a Get transaction, which may contain requests for one or more JS or
-CSS files.
-
-This class should not be instantiated manually. Instances will be created and
-returned as needed by Y.Get's `css()`, `js()`, and `load()` methods.
-
-@class Get.Transaction
-@constructor
-@since 3.5.0
-**/
-Get.Transaction = Transaction = function (requests, options) {
-    var self = this;
-
-    self.id       = Transaction._lastId += 1;
-    self.data     = options.data;
-    self.errors   = [];
-    self.nodes    = [];
-    self.options  = options;
-    self.requests = requests;
-
-    self._callbacks = []; // callbacks to call after execution finishes
-    self._queue     = [];
-    self._reqsWaiting   = 0;
-
-    // Deprecated pre-3.5.0 properties.
-    self.tId = self.id; // Use `id` instead.
-    self.win = options.win || Y.config.win;
-};
-
-/**
-Arbitrary data object associated with this transaction.
-
-This object comes from the options passed to `Get.css()`, `Get.js()`, or
-`Get.load()`, and will be `undefined` if no data object was specified.
-
-@property {Object} data
-**/
-
-/**
-Array of errors that have occurred during this transaction, if any.
-
-@since 3.5.0
-@property {Object[]} errors
-@property {String} errors.error Error message.
-@property {Object} errors.request Request object related to the error.
-**/
-
-/**
-Numeric id for this transaction, unique among all transactions within the same
-YUI sandbox in the current pageview.
-
-@property {Number} id
-@since 3.5.0
-**/
-
-/**
-HTMLElement nodes (native ones, not YUI Node instances) that have been inserted
-during the current transaction.
-
-@property {HTMLElement[]} nodes
-**/
-
-/**
-Options associated with this transaction.
-
-See `Get.options` for the full list of available options.
-
-@property {Object} options
-@since 3.5.0
-**/
-
-/**
-Request objects contained in this transaction. Each request object represents
-one CSS or JS URL that will be (or has been) requested and loaded into the page.
-
-@property {Object} requests
-@since 3.5.0
-**/
-
-/**
-Id of the most recent transaction.
-
-@property _lastId
-@type Number
-@protected
-@static
-**/
-Transaction._lastId = 0;
-
-Transaction.prototype = {
-    // -- Public Properties ----------------------------------------------------
-
-    /**
-    Current state of this transaction. One of "new", "executing", or "done".
-
-    @property _state
-    @type String
-    @protected
-    **/
-    _state: 'new', // "new", "executing", or "done"
-
-    // -- Public Methods -------------------------------------------------------
-
-    /**
-    Aborts this transaction.
-
-    This will cause the transaction's `onFailure` callback to be called and
-    will prevent any new script and link nodes from being added to the document,
-    but any resources that have already been requested will continue loading
-    (there's no safe way to prevent this, unfortunately).
-
-    @method abort
-    @param {String} [msg="Aborted."] Optional message to use in the `errors`
-        array describing why the transaction was aborted.
-    **/
-    abort: function (msg) {
-        this._pending    = null;
-        this._pendingCSS = null;
-        this._pollTimer  = clearTimeout(this._pollTimer);
-        this._queue      = [];
-        this._reqsWaiting    = 0;
-
-        this.errors.push({error: msg || 'Aborted'});
-        this._finish();
-    },
-
-    /**
-    Begins execting the transaction.
-
-    There's usually no reason to call this manually, since Get will call it
-    automatically when other pending transactions have finished. If you really
-    want to execute your transaction before Get does, you can, but be aware that
-    this transaction's scripts may end up executing before the scripts in other
-    pending transactions.
-
-    If the transaction is already executing, the specified callback (if any)
-    will be queued and called after execution finishes. If the transaction has
-    already finished, the callback will be called immediately (the transaction
-    will not be executed again).
-
-    @method execute
-    @param {Function} callback Callback function to execute after all requests
-        in the transaction are complete, or after the transaction is aborted.
-    **/
-    execute: function (callback) {
-        var self     = this,
-            requests = self.requests,
-            state    = self._state,
-            i, len, queue, req;
-
-        if (state === 'done') {
-            callback && callback(self.errors.length ? self.errors : null, self);
-            return;
-        } else {
-            callback && self._callbacks.push(callback);
-
-            if (state === 'executing') {
-                return;
-            }
-        }
-
-        self._state = 'executing';
-        self._queue = queue = [];
-
-        if (self.options.timeout) {
-            self._timeout = setTimeout(function () {
-                self.abort('Timeout');
-            }, self.options.timeout);
-        }
-
-        self._reqsWaiting = requests.length;
-
-        for (i = 0, len = requests.length; i < len; ++i) {
-            req = requests[i];
-
-            if (req.async || req.type === 'css') {
-                // No need to queue CSS or fully async JS.
-                self._insert(req);
-            } else {
-                queue.push(req);
-            }
-        }
-
-        self._next();
-    },
-
-    /**
-    Manually purges any `<script>` or `<link>` nodes this transaction has
-    created.
-
-    Be careful when purging a transaction that contains CSS requests, since
-    removing `<link>` nodes will also remove any styles they applied.
-
-    @method purge
-    **/
-    purge: function () {
-        Get._purge(this.nodes);
-    },
-
-    // -- Protected Methods ----------------------------------------------------
-    _createNode: function (name, attrs, doc) {
-        var node = doc.createElement(name),
-            attr, testEl;
-
-        if (!CUSTOM_ATTRS) {
-            // IE6 and IE7 expect property names rather than attribute names for
-            // certain attributes. Rather than sniffing, we do a quick feature
-            // test the first time _createNode() runs to determine whether we
-            // need to provide a workaround.
-            testEl = doc.createElement('div');
-            testEl.setAttribute('class', 'a');
-
-            CUSTOM_ATTRS = testEl.className === 'a' ? {} : {
-                'for'  : 'htmlFor',
-                'class': 'className'
-            };
-        }
-
-        for (attr in attrs) {
-            if (attrs.hasOwnProperty(attr)) {
-                node.setAttribute(CUSTOM_ATTRS[attr] || attr, attrs[attr]);
-            }
-        }
-
-        return node;
-    },
-
-    _finish: function () {
-        var errors  = this.errors.length ? this.errors : null,
-            options = this.options,
-            thisObj = options.context || this,
-            data, i, len;
-
-        if (this._state === 'done') {
-            return;
-        }
-
-        this._state = 'done';
-
-        for (i = 0, len = this._callbacks.length; i < len; ++i) {
-            this._callbacks[i].call(thisObj, errors, this);
-        }
-
-        data = this._getEventData();
-
-        if (errors) {
-            if (options.onTimeout && errors[errors.length - 1].error === 'Timeout') {
-                options.onTimeout.call(thisObj, data);
-            }
-
-            if (options.onFailure) {
-                options.onFailure.call(thisObj, data);
-            }
-        } else if (options.onSuccess) {
-            options.onSuccess.call(thisObj, data);
-        }
-
-        if (options.onEnd) {
-            options.onEnd.call(thisObj, data);
-        }
-
-        if (options._onFinish) {
-            options._onFinish();
-        }
-    },
-
-    _getEventData: function (req) {
-        if (req) {
-            // This merge is necessary for backcompat. I hate it.
-            return Y.merge(this, {
-                abort  : this.abort, // have to copy these because the prototype isn't preserved
-                purge  : this.purge,
-                request: req,
-                url    : req.url,
-                win    : req.win
-            });
-        } else {
-            return this;
-        }
-    },
-
-    _getInsertBefore: function (req) {
-        var doc = req.doc,
-            el  = req.insertBefore,
-            cache, docStamp;
-
-        if (el) {
-            return typeof el === 'string' ? doc.getElementById(el) : el;
-        }
-
-        cache    = Get._insertCache;
-        docStamp = Y.stamp(doc);
-
-        if ((el = cache[docStamp])) { // assignment
-            return el;
-        }
-
-        // Inserting before a <base> tag apparently works around an IE bug
-        // (according to a comment from pre-3.5.0 Y.Get), but I'm not sure what
-        // bug that is, exactly. Better safe than sorry?
-        if ((el = doc.getElementsByTagName('base')[0])) { // assignment
-            return (cache[docStamp] = el);
-        }
-
-        // Look for a <head> element.
-        el = doc.head || doc.getElementsByTagName('head')[0];
-
-        if (el) {
-            // Create a marker node at the end of <head> to use as an insertion
-            // point. Inserting before this node will ensure that all our CSS
-            // gets inserted in the correct order, to maintain style precedence.
-            el.appendChild(doc.createTextNode(''));
-            return (cache[docStamp] = el.lastChild);
-        }
-
-        // If all else fails, just insert before the first script node on the
-        // page, which is virtually guaranteed to exist.
-        return (cache[docStamp] = doc.getElementsByTagName('script')[0]);
-    },
-
-    _insert: function (req) {
-        var env          = Get._env,
-            insertBefore = this._getInsertBefore(req),
-            isScript     = req.type === 'js',
-            node         = req.node,
-            self         = this,
-            ua           = Y.UA,
-            cssTimeout, nodeType;
-
-        if (!node) {
-            if (isScript) {
-                nodeType = 'script';
-            } else if (!env.cssLoad && ua.gecko) {
-                nodeType = 'style';
-            } else {
-                nodeType = 'link';
-            }
-
-            node = req.node = this._createNode(nodeType, req.attributes,
-                req.doc);
-        }
-
-        function onError() {
-            self._progress('Failed to load ' + req.url, req);
-        }
-
-        function onLoad() {
-            if (cssTimeout) {
-                clearTimeout(cssTimeout);
-            }
-
-            self._progress(null, req);
-        }
-
-        // Deal with script asynchronicity.
-        if (isScript) {
-            node.setAttribute('src', req.url);
-
-            if (req.async) {
-                // Explicitly indicate that we want the browser to execute this
-                // script asynchronously. This is necessary for older browsers
-                // like Firefox <4.
-                node.async = true;
-            } else {
-                if (env.async) {
-                    // This browser treats injected scripts as async by default
-                    // (standard HTML5 behavior) but asynchronous loading isn't
-                    // desired, so tell the browser not to mark this script as
-                    // async.
-                    node.async = false;
-                }
-
-                // If this browser doesn't preserve script execution order based
-                // on insertion order, we'll need to avoid inserting other
-                // scripts until this one finishes loading.
-                if (!env.preservesScriptOrder) {
-                    this._pending = req;
-                }
-            }
-        } else {
-            if (!env.cssLoad && ua.gecko) {
-                // In Firefox <9, we can import the requested URL into a <style>
-                // node and poll for the existence of node.sheet.cssRules. This
-                // gives us a reliable way to determine CSS load completion that
-                // also works for cross-domain stylesheets.
-                //
-                // Props to Zach Leatherman for calling my attention to this
-                // technique.
-                node.innerHTML = (req.attributes.charset ?
-                    '@charset "' + req.attributes.charset + '";' : '') +
-                    '@import "' + req.url + '";';
-            } else {
-                node.setAttribute('href', req.url);
-            }
-        }
-
-        // Inject the node.
-        if (isScript && ua.ie && (ua.ie < 9 || (document.documentMode && document.documentMode < 9))) {
-            // Script on IE < 9, and IE 9+ when in IE 8 or older modes, including quirks mode.
-            node.onreadystatechange = function () {
-                if (/loaded|complete/.test(node.readyState)) {
-                    node.onreadystatechange = null;
-                    onLoad();
-                }
-            };
-        } else if (!isScript && !env.cssLoad) {
-            // CSS on Firefox <9 or WebKit.
-            this._poll(req);
-        } else {
-            // Script or CSS on everything else. Using DOM 0 events because that
-            // evens the playing field with older IEs.
-
-            if (ua.ie >= 10) {
-
-                // We currently need to introduce a timeout for IE10, since it
-                // calls onerror/onload synchronously for 304s - messing up existing
-                // program flow.
-
-                // Remove this block if the following bug gets fixed by GA
-                /*jshint maxlen: 1500 */
-                // https://connect.microsoft.com/IE/feedback/details/763871/dynamically-loaded-scripts-with-304s-responses-interrupt-the-currently-executing-js-thread-onload
-                node.onerror = function() { setTimeout(onError, 0); };
-                node.onload  = function() { setTimeout(onLoad, 0); };
-            } else {
-                node.onerror = onError;
-                node.onload  = onLoad;
-            }
-
-            // If this browser doesn't fire an event when CSS fails to load,
-            // fail after a timeout to avoid blocking the transaction queue.
-            if (!env.cssFail && !isScript) {
-                cssTimeout = setTimeout(onError, req.timeout || 3000);
-            }
-        }
-
-        this.nodes.push(node);
-        insertBefore.parentNode.insertBefore(node, insertBefore);
-    },
-
-    _next: function () {
-        if (this._pending) {
-            return;
-        }
-
-        // If there are requests in the queue, insert the next queued request.
-        // Otherwise, if we're waiting on already-inserted requests to finish,
-        // wait longer. If there are no queued requests and we're not waiting
-        // for anything to load, then we're done!
-        if (this._queue.length) {
-            this._insert(this._queue.shift());
-        } else if (!this._reqsWaiting) {
-            this._finish();
-        }
-    },
-
-    _poll: function (newReq) {
-        var self       = this,
-            pendingCSS = self._pendingCSS,
-            isWebKit   = Y.UA.webkit,
-            i, hasRules, j, nodeHref, req, sheets;
-
-        if (newReq) {
-            pendingCSS || (pendingCSS = self._pendingCSS = []);
-            pendingCSS.push(newReq);
-
-            if (self._pollTimer) {
-                // A poll timeout is already pending, so no need to create a
-                // new one.
-                return;
-            }
-        }
-
-        self._pollTimer = null;
-
-        // Note: in both the WebKit and Gecko hacks below, a CSS URL that 404s
-        // will still be treated as a success. There's no good workaround for
-        // this.
-
-        for (i = 0; i < pendingCSS.length; ++i) {
-            req = pendingCSS[i];
-
-            if (isWebKit) {
-                // Look for a stylesheet matching the pending URL.
-                sheets   = req.doc.styleSheets;
-                j        = sheets.length;
-                nodeHref = req.node.href;
-
-                while (--j >= 0) {
-                    if (sheets[j].href === nodeHref) {
-                        pendingCSS.splice(i, 1);
-                        i -= 1;
-                        self._progress(null, req);
-                        break;
-                    }
-                }
-            } else {
-                // Many thanks to Zach Leatherman for calling my attention to
-                // the @import-based cross-domain technique used here, and to
-                // Oleg Slobodskoi for an earlier same-domain implementation.
-                //
-                // See Zach's blog for more details:
-                // http://www.zachleat.com/web/2010/07/29/load-css-dynamically/
-                try {
-                    // We don't really need to store this value since we never
-                    // use it again, but if we don't store it, Closure Compiler
-                    // assumes the code is useless and removes it.
-                    hasRules = !!req.node.sheet.cssRules;
-
-                    // If we get here, the stylesheet has loaded.
-                    pendingCSS.splice(i, 1);
-                    i -= 1;
-                    self._progress(null, req);
-                } catch (ex) {
-                    // An exception means the stylesheet is still loading.
-                }
-            }
-        }
-
-        if (pendingCSS.length) {
-            self._pollTimer = setTimeout(function () {
-                self._poll.call(self);
-            }, self.options.pollInterval);
-        }
-    },
-
-    _progress: function (err, req) {
-        var options = this.options;
-
-        if (err) {
-            req.error = err;
-
-            this.errors.push({
-                error  : err,
-                request: req
-            });
-
-        }
-
-        req.node._yuiget_finished = req.finished = true;
-
-        if (options.onProgress) {
-            options.onProgress.call(options.context || this,
-                this._getEventData(req));
-        }
-
-        if (req.autopurge) {
-            // Pre-3.5.0 Get always excludes the most recent node from an
-            // autopurge. I find this odd, but I'm keeping that behavior for
-            // the sake of backcompat.
-            Get._autoPurge(this.options.purgethreshold);
-            Get._purgeNodes.push(req.node);
-        }
-
-        if (this._pending === req) {
-            this._pending = null;
-        }
-
-        this._reqsWaiting -= 1;
-
-        this._next();
-    }
-};
-
-
-}, '3.12.0', {"requires": ["yui-base"]});
-YUI.add('features', function (Y, NAME) {
-
-var feature_tests = {};
-
-/**
-Contains the core of YUI's feature test architecture.
-@module features
-*/
-
-/**
-* Feature detection
-* @class Features
-* @static
-*/
-
-Y.mix(Y.namespace('Features'), {
-
-    /**
-    * Object hash of all registered feature tests
-    * @property tests
-    * @type Object
-    */
-    tests: feature_tests,
-
-    /**
-    * Add a test to the system
-    *
-    *   ```
-    *   Y.Features.add("load", "1", {});
-    *   ```
-    *
-    * @method add
-    * @param {String} cat The category, right now only 'load' is supported
-    * @param {String} name The number sequence of the test, how it's reported in the URL or config: 1, 2, 3
-    * @param {Object} o Object containing test properties
-    * @param {String} o.name The name of the test
-    * @param {Function} o.test The test function to execute, the only argument to the function is the `Y` instance
-    * @param {String} o.trigger The module that triggers this test.
-    */
-    add: function(cat, name, o) {
-        feature_tests[cat] = feature_tests[cat] || {};
-        feature_tests[cat][name] = o;
-    },
-    /**
-    * Execute all tests of a given category and return the serialized results
-    *
-    *   ```
-    *   caps=1:1;2:1;3:0
-    *   ```
-    * @method all
-    * @param {String} cat The category to execute
-    * @param {Array} args The arguments to pass to the test function
-    * @return {String} A semi-colon separated string of tests and their success/failure: 1:1;2:1;3:0
-    */
-    all: function(cat, args) {
-        var cat_o = feature_tests[cat],
-            // results = {};
-            result = [];
-        if (cat_o) {
-            Y.Object.each(cat_o, function(v, k) {
-                result.push(k + ':' + (Y.Features.test(cat, k, args) ? 1 : 0));
-            });
-        }
-
-        return (result.length) ? result.join(';') : '';
-    },
-    /**
-    * Run a sepecific test and return a Boolean response.
-    *
-    *   ```
-    *   Y.Features.test("load", "1");
-    *   ```
-    *
-    * @method test
-    * @param {String} cat The category of the test to run
-    * @param {String} name The name of the test to run
-    * @param {Array} args The arguments to pass to the test function
-    * @return {Boolean} True or false if the test passed/failed.
-    */
-    test: function(cat, name, args) {
-        args = args || [];
-        var result, ua, test,
-            cat_o = feature_tests[cat],
-            feature = cat_o && cat_o[name];
-
-        if (!feature) {
-        } else {
-
-            result = feature.result;
-
-            if (Y.Lang.isUndefined(result)) {
-
-                ua = feature.ua;
-                if (ua) {
-                    result = (Y.UA[ua]);
-                }
-
-                test = feature.test;
-                if (test && ((!ua) || result)) {
-                    result = test.apply(Y, args);
-                }
-
-                feature.result = result;
-            }
-        }
-
-        return result;
-    }
-});
-
-// Y.Features.add("load", "1", {});
-// Y.Features.test("load", "1");
-// caps=1:1;2:0;3:1;
-
-/* This file is auto-generated by (yogi.js loader --mix --yes) */
-/*jshint maxlen:900, eqeqeq: false */
-var add = Y.Features.add;
-// app-transitions-native
-add('load', '0', {
-    "name": "app-transitions-native",
-    "test": function (Y) {
-    var doc  = Y.config.doc,
-        node = doc ? doc.documentElement : null;
-
-    if (node && node.style) {
-        return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
-    }
-
-    return false;
-},
-    "trigger": "app-transitions"
-});
-// autocomplete-list-keys
-add('load', '1', {
-    "name": "autocomplete-list-keys",
-    "test": function (Y) {
-    // Only add keyboard support to autocomplete-list if this doesn't appear to
-    // be an iOS or Android-based mobile device.
-    //
-    // There's currently no feasible way to actually detect whether a device has
-    // a hardware keyboard, so this sniff will have to do. It can easily be
-    // overridden by manually loading the autocomplete-list-keys module.
-    //
-    // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
-    // doesn't fire the keyboard events used by AutoCompleteList, so there's
-    // no point loading the -keys module even when a bluetooth keyboard may be
-    // available.
-    return !(Y.UA.ios || Y.UA.android);
-},
-    "trigger": "autocomplete-list"
-});
-// dd-gestures
-add('load', '2', {
-    "name": "dd-gestures",
-    "trigger": "dd-drag",
-    "ua": "touchEnabled"
-});
-// dom-style-ie
-add('load', '3', {
-    "name": "dom-style-ie",
-    "test": function (Y) {
-
-    var testFeature = Y.Features.test,
-        addFeature = Y.Features.add,
-        WINDOW = Y.config.win,
-        DOCUMENT = Y.config.doc,
-        DOCUMENT_ELEMENT = 'documentElement',
-        ret = false;
-
-    addFeature('style', 'computedStyle', {
-        test: function() {
-            return WINDOW && 'getComputedStyle' in WINDOW;
-        }
-    });
-
-    addFeature('style', 'opacity', {
-        test: function() {
-            return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
-        }
-    });
-
-    ret =  (!testFeature('style', 'opacity') &&
-            !testFeature('style', 'computedStyle'));
-
-    return ret;
-},
-    "trigger": "dom-style"
-});
-// editor-para-ie
-add('load', '4', {
-    "name": "editor-para-ie",
-    "trigger": "editor-para",
-    "ua": "ie",
-    "when": "instead"
-});
-// event-base-ie
-add('load', '5', {
-    "name": "event-base-ie",
-    "test": function(Y) {
-    var imp = Y.config.doc && Y.config.doc.implementation;
-    return (imp && (!imp.hasFeature('Events', '2.0')));
-},
-    "trigger": "node-base"
-});
-// graphics-canvas
-add('load', '6', {
-    "name": "graphics-canvas",
-    "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-        useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
-        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
-    return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
-},
-    "trigger": "graphics"
-});
-// graphics-canvas-default
-add('load', '7', {
-    "name": "graphics-canvas-default",
-    "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-        useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
-        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
-    return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
-},
-    "trigger": "graphics"
-});
-// graphics-svg
-add('load', '8', {
-    "name": "graphics-svg",
-    "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-        useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
-        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
-    
-    return svg && (useSVG || !canvas);
-},
-    "trigger": "graphics"
-});
-// graphics-svg-default
-add('load', '9', {
-    "name": "graphics-svg-default",
-    "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-        useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
-        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
-    
-    return svg && (useSVG || !canvas);
-},
-    "trigger": "graphics"
-});
-// graphics-vml
-add('load', '10', {
-    "name": "graphics-vml",
-    "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
-    return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
-},
-    "trigger": "graphics"
-});
-// graphics-vml-default
-add('load', '11', {
-    "name": "graphics-vml-default",
-    "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
-    return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
-},
-    "trigger": "graphics"
-});
-// history-hash-ie
-add('load', '12', {
-    "name": "history-hash-ie",
-    "test": function (Y) {
-    var docMode = Y.config.doc && Y.config.doc.documentMode;
-
-    return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
-            !docMode || docMode < 8);
-},
-    "trigger": "history-hash"
-});
-// io-nodejs
-add('load', '13', {
-    "name": "io-nodejs",
-    "trigger": "io-base",
-    "ua": "nodejs"
-});
-// json-parse-shim
-add('load', '14', {
-    "name": "json-parse-shim",
-    "test": function (Y) {
-    var _JSON = Y.config.global.JSON,
-        Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
-        nativeSupport = Y.config.useNativeJSONParse !== false && !!Native;
-
-    function workingNative( k, v ) {
-        return k === "ok" ? true : v;
-    }
-    
-    // Double check basic functionality.  This is mainly to catch early broken
-    // implementations of the JSON API in Firefox 3.1 beta1 and beta2
-    if ( nativeSupport ) {
-        try {
-            nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
-        }
-        catch ( e ) {
-            nativeSupport = false;
-        }
-    }
-
-    return !nativeSupport;
-},
-    "trigger": "json-parse"
-});
-// json-stringify-shim
-add('load', '15', {
-    "name": "json-stringify-shim",
-    "test": function (Y) {
-    var _JSON = Y.config.global.JSON,
-        Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
-        nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native;
-
-    // Double check basic native functionality.  This is primarily to catch broken
-    // early JSON API implementations in Firefox 3.1 beta1 and beta2.
-    if ( nativeSupport ) {
-        try {
-            nativeSupport = ( '0' === Native.stringify(0) );
-        } catch ( e ) {
-            nativeSupport = false;
-        }
-    }
-
-
-    return !nativeSupport;
-},
-    "trigger": "json-stringify"
-});
-// scrollview-base-ie
-add('load', '16', {
-    "name": "scrollview-base-ie",
-    "trigger": "scrollview-base",
-    "ua": "ie"
-});
-// selector-css2
-add('load', '17', {
-    "name": "selector-css2",
-    "test": function (Y) {
-    var DOCUMENT = Y.config.doc,
-        ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
-
-    return ret;
-},
-    "trigger": "selector"
-});
-// transition-timer
-add('load', '18', {
-    "name": "transition-timer",
-    "test": function (Y) {
-    var DOCUMENT = Y.config.doc,
-        node = (DOCUMENT) ? DOCUMENT.documentElement: null,
-        ret = true;
-
-    if (node && node.style) {
-        ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
-    }
-
-    return ret;
-},
-    "trigger": "transition"
-});
-// widget-base-ie
-add('load', '19', {
-    "name": "widget-base-ie",
-    "trigger": "widget-base",
-    "ua": "ie"
-});
-// yql-jsonp
-add('load', '20', {
-    "name": "yql-jsonp",
-    "test": function (Y) {
-    /* Only load the JSONP module when not in nodejs or winjs
-    TODO Make the winjs module a CORS module
-    */
-    return (!Y.UA.nodejs && !Y.UA.winjs);
-},
-    "trigger": "yql",
-    "when": "after"
-});
-// yql-nodejs
-add('load', '21', {
-    "name": "yql-nodejs",
-    "trigger": "yql",
-    "ua": "nodejs",
-    "when": "after"
-});
-// yql-winjs
-add('load', '22', {
-    "name": "yql-winjs",
-    "trigger": "yql",
-    "ua": "winjs",
-    "when": "after"
-});
-
-}, '3.12.0', {"requires": ["yui-base"]});
-YUI.add('intl-base', function (Y, NAME) {
-
-/**
- * The Intl utility provides a central location for managing sets of
- * localized resources (strings and formatting patterns).
- *
- * @class Intl
- * @uses EventTarget
- * @static
- */
-
-var SPLIT_REGEX = /[, ]/;
-
-Y.mix(Y.namespace('Intl'), {
-
- /**
-    * Returns the language among those available that
-    * best matches the preferred language list, using the Lookup
-    * algorithm of BCP 47.
-    * If none of the available languages meets the user's preferences,
-    * then "" is returned.
-    * Extended language ranges are not supported.
-    *
-    * @method lookupBestLang
-    * @param {String[] | String} preferredLanguages The list of preferred
-    * languages in descending preference order, represented as BCP 47
-    * language tags. A string array or a comma-separated list.
-    * @param {String[]} availableLanguages The list of languages
-    * that the application supports, represented as BCP 47 language
-    * tags.
-    *
-    * @return {String} The available language that best matches the
-    * preferred language list, or "".
-    * @since 3.1.0
-    */
-    lookupBestLang: function(preferredLanguages, availableLanguages) {
-
-        var i, language, result, index;
-
-        // check whether the list of available languages contains language;
-        // if so return it
-        function scan(language) {
-            var i;
-            for (i = 0; i < availableLanguages.length; i += 1) {
-                if (language.toLowerCase() ===
-                            availableLanguages[i].toLowerCase()) {
-                    return availableLanguages[i];
-                }
-            }
-        }
-
-        if (Y.Lang.isString(preferredLanguages)) {
-            preferredLanguages = preferredLanguages.split(SPLIT_REGEX);
-        }
-
-        for (i = 0; i < preferredLanguages.length; i += 1) {
-            language = preferredLanguages[i];
-            if (!language || language === '*') {
-                continue;
-            }
-            // check the fallback sequence for one language
-            while (language.length > 0) {
-                result = scan(language);
-                if (result) {
-                    return result;
-                } else {
-                    index = language.lastIndexOf('-');
-                    if (index >= 0) {
-                        language = language.substring(0, index);
-                        // one-character subtags get cut along with the
-                        // following subtag
-                        if (index >= 2 && language.charAt(index - 2) === '-') {
-                            language = language.substring(0, index - 2);
-                        }
-                    } else {
-                        // nothing available for this language
-                        break;
-                    }
-                }
-            }
-        }
-
-        return '';
-    }
-});
-
-
-}, '3.12.0', {"requires": ["yui-base"]});
-YUI.add('yui-log', function (Y, NAME) {
-
-/**
- * Provides console log capability and exposes a custom event for
- * console implementations. This module is a `core` YUI module,
- * <a href="../classes/YUI.html#method_log">it's documentation is located under the YUI class</a>.
- *
- * @module yui
- * @submodule yui-log
- */
-
-var INSTANCE = Y,
-    LOGEVENT = 'yui:log',
-    UNDEFINED = 'undefined',
-    LEVELS = { debug: 1,
-               info: 2,
-               warn: 4,
-               error: 8 };
-
-/**
- * If the 'debug' config is true, a 'yui:log' event will be
- * dispatched, which the Console widget and anything else
- * can consume.  If the 'useBrowserConsole' config is true, it will
- * write to the browser console if available.  YUI-specific log
- * messages will only be present in the -debug versions of the
- * JS files.  The build system is supposed to remove log statements
- * from the raw and minified versions of the files.
- *
- * @method log
- * @for YUI
- * @param  {String}  msg  The message to log.
- * @param  {String}  cat  The log category for the message.  Default
- *                        categories are "info", "warn", "error", time".
- *                        Custom categories can be used as well. (opt).
- * @param  {String}  src  The source of the the message (opt).
- * @param  {boolean} silent If true, the log event won't fire.
- * @return {YUI}      YUI instance.
- */
-INSTANCE.log = function(msg, cat, src, silent) {
-    var bail, excl, incl, m, f, minlevel,
-        Y = INSTANCE,
-        c = Y.config,
-        publisher = (Y.fire) ? Y : YUI.Env.globalEvents;
-    // suppress log message if the config is off or the event stack
-    // or the event call stack contains a consumer of the yui:log event
-    if (c.debug) {
-        // apply source filters
-        src = src || "";
-        if (typeof src !== "undefined") {
-            excl = c.logExclude;
-            incl = c.logInclude;
-            if (incl && !(src in incl)) {
-                bail = 1;
-            } else if (incl && (src in incl)) {
-                bail = !incl[src];
-            } else if (excl && (src in excl)) {
-                bail = excl[src];
-            }
-
-            // Determine the current minlevel as defined in configuration
-            Y.config.logLevel = Y.config.logLevel || 'debug';
-            minlevel = LEVELS[Y.config.logLevel.toLowerCase()];
-
-            if (cat in LEVELS && LEVELS[cat] < minlevel) {
-                // Skip this message if the we don't meet the defined minlevel
-                bail = 1;
-            }
-        }
-        if (!bail) {
-            if (c.useBrowserConsole) {
-                m = (src) ? src + ': ' + msg : msg;
-                if (Y.Lang.isFunction(c.logFn)) {
-                    c.logFn.call(Y, msg, cat, src);
-                } else if (typeof console !== UNDEFINED && console.log) {
-                    f = (cat && console[cat] && (cat in LEVELS)) ? cat : 'log';
-                    console[f](m);
-                } else if (typeof opera !== UNDEFINED) {
-                    opera.postError(m);
-                }
-            }
-
-            if (publisher && !silent) {
-
-                if (publisher === Y && (!publisher.getEvent(LOGEVENT))) {
-                    publisher.publish(LOGEVENT, {
-                        broadcast: 2
-                    });
-                }
-
-                publisher.fire(LOGEVENT, {
-                    msg: msg,
-                    cat: cat,
-                    src: src
-                });
-            }
-        }
-    }
-
-    return Y;
-};
-
-/**
- * Write a system message.  This message will be preserved in the
- * minified and raw versions of the YUI files, unlike log statements.
- * @method message
- * @for YUI
- * @param  {String}  msg  The message to log.
- * @param  {String}  cat  The log category for the message.  Default
- *                        categories are "info", "warn", "error", time".
- *                        Custom categories can be used as well. (opt).
- * @param  {String}  src  The source of the the message (opt).
- * @param  {boolean} silent If true, the log event won't fire.
- * @return {YUI}      YUI instance.
- */
-INSTANCE.message = function() {
-    return INSTANCE.log.apply(INSTANCE, arguments);
-};
-
-
-}, '3.12.0', {"requires": ["yui-base"]});
-YUI.add('yui-later', function (Y, NAME) {
-
-/**
- * Provides a setTimeout/setInterval wrapper. This module is a `core` YUI module,
- * <a href="../classes/YUI.html#method_later">it's documentation is located under the YUI class</a>.
- *
- * @module yui
- * @submodule yui-later
- */
-
-var NO_ARGS = [];
-
-/**
- * Executes the supplied function in the context of the supplied
- * object 'when' milliseconds later.  Executes the function a
- * single time unless periodic is set to true.
- * @for YUI
- * @method later
- * @param when {int} the number of milliseconds to wait until the fn
- * is executed.
- * @param o the context object.
- * @param fn {Function|String} the function to execute or the name of
- * the method in the 'o' object to execute.
- * @param data [Array] data that is provided to the function.  This
- * accepts either a single item or an array.  If an array is provided,
- * the function is executed with one parameter for each array item.
- * If you need to pass a single array parameter, it needs to be wrapped
- * in an array [myarray].
- *
- * Note: native methods in IE may not have the call and apply methods.
- * In this case, it will work, but you are limited to four arguments.
- *
- * @param periodic {boolean} if true, executes continuously at supplied
- * interval until canceled.
- * @return {object} a timer object. Call the cancel() method on this
- * object to stop the timer.
- */
-Y.later = function(when, o, fn, data, periodic) {
-    when = when || 0;
-    data = (!Y.Lang.isUndefined(data)) ? Y.Array(data) : NO_ARGS;
-    o = o || Y.config.win || Y;
-
-    var cancelled = false,
-        method = (o && Y.Lang.isString(fn)) ? o[fn] : fn,
-        wrapper = function() {
-            // IE 8- may execute a setInterval callback one last time
-            // after clearInterval was called, so in order to preserve
-            // the cancel() === no more runny-run, we have to jump through
-            // an extra hoop.
-            if (!cancelled) {
-                if (!method.apply) {
-                    method(data[0], data[1], data[2], data[3]);
-                } else {
-                    method.apply(o, data || NO_ARGS);
-                }
-            }
-        },
-        id = (periodic) ? setInterval(wrapper, when) : setTimeout(wrapper, when);
-
-    return {
-        id: id,
-        interval: periodic,
-        cancel: function() {
-            cancelled = true;
-            if (this.interval) {
-                clearInterval(id);
-            } else {
-                clearTimeout(id);
-            }
-        }
-    };
-};
-
-Y.Lang.later = Y.later;
-
-
-
-}, '3.12.0', {"requires": ["yui-base"]});
-YUI.add('loader-base', function (Y, NAME) {
-
-/**
- * The YUI loader core
- * @module loader
- * @submodule loader-base
- */
-
-(function() {
-    var VERSION = Y.version,
-        BUILD = '/build/',
-        ROOT = VERSION + '/',
-        CDN_BASE = Y.Env.base,
-        GALLERY_VERSION = 'gallery-2013.08.22-21-03',
-        TNT = '2in3',
-        TNT_VERSION = '4',
-        YUI2_VERSION = '2.9.0',
-        COMBO_BASE = CDN_BASE + 'combo?',
-        META = {
-            version: VERSION,
-            root: ROOT,
-            base: Y.Env.base,
-            comboBase: COMBO_BASE,
-            skin: {
-                defaultSkin: 'sam',
-                base: 'assets/skins/',
-                path: 'skin.css',
-                after: [
-                    'cssreset',
-                    'cssfonts',
-                    'cssgrids',
-                    'cssbase',
-                    'cssreset-context',
-                    'cssfonts-context'
-                ]
-            },
-            groups: {},
-            patterns: {}
-        },
-        groups = META.groups,
-        yui2Update = function(tnt, yui2, config) {
-            var root = TNT + '.' +
-                    (tnt || TNT_VERSION) + '/' +
-                    (yui2 || YUI2_VERSION) + BUILD,
-                base = (config && config.base) ? config.base : CDN_BASE,
-                combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE;
-
-            groups.yui2.base = base + root;
-            groups.yui2.root = root;
-            groups.yui2.comboBase = combo;
-        },
-        galleryUpdate = function(tag, config) {
-            var root = (tag || GALLERY_VERSION) + BUILD,
-                base = (config && config.base) ? config.base : CDN_BASE,
-                combo = (config && config.comboBase) ? config.comboBase : COMBO_BASE;
-
-            groups.gallery.base = base + root;
-            groups.gallery.root = root;
-            groups.gallery.comboBase = combo;
-        };
-
-
-    groups[VERSION] = {};
-
-    groups.gallery = {
-        ext: false,
-        combine: true,
-        comboBase: COMBO_BASE,
-        update: galleryUpdate,
-        patterns: {
-            'gallery-': {},
-            'lang/gallery-': {},
-            'gallerycss-': {
-                type: 'css'
-            }
-        }
-    };
-
-    groups.yui2 = {
-        combine: true,
-        ext: false,
-        comboBase: COMBO_BASE,
-        update: yui2Update,
-        patterns: {
-            'yui2-': {
-                configFn: function(me) {
-                    if (/-skin|reset|fonts|grids|base/.test(me.name)) {
-                        me.type = 'css';
-                        me.path = me.path.replace(/\.js/, '.css');
-                        // this makes skins in builds earlier than
-                        // 2.6.0 work as long as combine is false
-                        me.path = me.path.replace(/\/yui2-skin/,
-                                            '/assets/skins/sam/yui2-skin');
-                    }
-                }
-            }
-        }
-    };
-
-    galleryUpdate();
-    yui2Update();
-
-    if (YUI.Env[VERSION]) {
-        Y.mix(META, YUI.Env[VERSION], false, [
-            'modules',
-            'groups',
-            'skin'
-        ], 0, true);
-    }
-
-    YUI.Env[VERSION] = META;
-}());
-/*jslint forin: true, maxlen: 350 */
-
-/**
- * Loader dynamically loads script and css files.  It includes the dependency
- * information for the version of the library in use, and will automatically pull in
- * dependencies for the modules requested. It can also load the
- * files from the Yahoo! CDN, and it can utilize the combo service provided on
- * this network to reduce the number of http connections required to download
- * YUI files.
- *
- * @module loader
- * @main loader
- * @submodule loader-base
- */
-
-var NOT_FOUND = {},
-    NO_REQUIREMENTS = [],
-    MAX_URL_LENGTH = 1024,
-    GLOBAL_ENV = YUI.Env,
-    GLOBAL_LOADED = GLOBAL_ENV._loaded,
-    CSS = 'css',
-    JS = 'js',
-    INTL = 'intl',
-    DEFAULT_SKIN = 'sam',
-    VERSION = Y.version,
-    ROOT_LANG = '',
-    YObject = Y.Object,
-    oeach = YObject.each,
-    yArray = Y.Array,
-    _queue = GLOBAL_ENV._loaderQueue,
-    META = GLOBAL_ENV[VERSION],
-    SKIN_PREFIX = 'skin-',
-    L = Y.Lang,
-    ON_PAGE = GLOBAL_ENV.mods,
-    modulekey,
-    _path = function(dir, file, type, nomin) {
-        var path = dir + '/' + file;
-        if (!nomin) {
-            path += '-min';
-        }
-        path += '.' + (type || CSS);
-
-        return path;
-    };
-
-
-    if (!YUI.Env._cssLoaded) {
-        YUI.Env._cssLoaded = {};
-    }
-
-
-/**
- * The component metadata is stored in Y.Env.meta.
- * Part of the loader module.
- * @property meta
- * @for YUI
- */
-Y.Env.meta = META;
-
-/**
- * Loader dynamically loads script and css files.  It includes the dependency
- * info for the version of the library in use, and will automatically pull in
- * dependencies for the modules requested. It can load the
- * files from the Yahoo! CDN, and it can utilize the combo service provided on
- * this network to reduce the number of http connections required to download
- * YUI files. You can also specify an external, custom combo service to host
- * your modules as well.
-
-        var Y = YUI();
-        var loader = new Y.Loader({
-            filter: 'debug',
-            base: '../../',
-            root: 'build/',
-            combine: true,
-            require: ['node', 'dd', 'console']
-        });
-        var out = loader.resolve(true);
-
- * @constructor
- * @class Loader
- * @param {Object} config an optional set of configuration options.
- * @param {String} config.base The base dir which to fetch this module from
- * @param {String} config.comboBase The Combo service base path. Ex: `http://yui.yahooapis.com/combo?`
- * @param {String} config.root The root path to prepend to module names for the combo service. Ex: `2.5.2/build/`
- * @param {String|Object} config.filter A filter to apply to result urls. <a href="#property_filter">See filter property</a>
- * @param {Object} config.filters Per-component filter specification.  If specified for a given component, this overrides the filter config.
- * @param {Boolean} config.combine Use a combo service to reduce the number of http connections required to load your dependencies
- * @param {Boolean} [config.async=true] Fetch files in async
- * @param {Array} config.ignore: A list of modules that should never be dynamically loaded
- * @param {Array} config.force A list of modules that should always be loaded when required, even if already present on the page
- * @param {HTMLElement|String} config.insertBefore Node or id for a node that should be used as the insertion point for new nodes
- * @param {Object} config.jsAttributes Object literal containing attributes to add to script nodes
- * @param {Object} config.cssAttributes Object literal containing attributes to add to link nodes
- * @param {Number} config.timeout The number of milliseconds before a timeout occurs when dynamically loading nodes.  If not set, there is no timeout
- * @param {Object} config.context Execution context for all callbacks
- * @param {Function} config.onSuccess Callback for the 'success' event
- * @param {Function} config.onFailure Callback for the 'failure' event
- * @param {Function} config.onCSS Callback for the 'CSSComplete' event.  When loading YUI components with CSS the CSS is loaded first, then the script.  This provides a moment you can tie into to improve the presentation of the page while the script is loading.
- * @param {Function} config.onTimeout Callback for the 'timeout' event
- * @param {Function} config.onProgress Callback executed each time a script or css file is loaded
- * @param {Object} config.modules A list of module definitions.  See <a href="#method_addModule">Loader.addModule</a> for the supported module metadata
- * @param {Object} config.groups A list of group definitions.  Each group can contain specific definitions for `base`, `comboBase`, `combine`, and accepts a list of `modules`.
- * @param {String} config.2in3 The version of the YUI 2 in 3 wrapper to use.  The intrinsic support for YUI 2 modules in YUI 3 relies on versions of the YUI 2 components inside YUI 3 module wrappers.  These wrappers change over time to accomodate the issues that arise from running YUI 2 in a YUI 3 sandbox.
- * @param {String} config.yui2 When using the 2in3 project, you can select the version of YUI 2 to use.  Valid values are `2.2.2`, `2.3.1`, `2.4.1`, `2.5.2`, `2.6.0`, `2.7.0`, `2.8.0`, `2.8.1` and `2.9.0` [default] -- plus all versions of YUI 2 going forward.
- */
-Y.Loader = function(o) {
-
-    var self = this;
-
-    //Catch no config passed.
-    o = o || {};
-
-    modulekey = META.md5;
-
-    /**
-     * Internal callback to handle multiple internal insert() calls
-     * so that css is inserted prior to js
-     * @property _internalCallback
-     * @private
-     */
-    // self._internalCallback = null;
-
-    /**
-     * Callback that will be executed when the loader is finished
-     * with an insert
-     * @method onSuccess
-     * @type function
-     */
-    // self.onSuccess = null;
-
-    /**
-     * Callback that will be executed if there is a failure
-     * @method onFailure
-     * @type function
-     */
-    // self.onFailure = null;
-
-    /**
-     * Callback for the 'CSSComplete' event.  When loading YUI components
-     * with CSS the CSS is loaded first, then the script.  This provides
-     * a moment you can tie into to improve the presentation of the page
-     * while the script is loading.
-     * @method onCSS
-     * @type function
-     */
-    // self.onCSS = null;
-
-    /**
-     * Callback executed each time a script or css file is loaded
-     * @method onProgress
-     * @type function
-     */
-    // self.onProgress = null;
-
-    /**
-     * Callback that will be executed if a timeout occurs
-     * @method onTimeout
-     * @type function
-     */
-    // self.onTimeout = null;
-
-    /**
-     * The execution context for all callbacks
-     * @property context
-     * @default {YUI} the YUI instance
-     */
-    self.context = Y;
-
-    /**
-     * Data that is passed to all callbacks
-     * @property data
-     */
-    // self.data = null;
-
-    /**
-     * Node reference or id where new nodes should be inserted before
-     * @property insertBefore
-     * @type string|HTMLElement
-     */
-    // self.insertBefore = null;
-
-    /**
-     * The charset attribute for inserted nodes
-     * @property charset
-     * @type string
-     * @deprecated , use cssAttributes or jsAttributes.
-     */
-    // self.charset = null;
-
-    /**
-     * An object literal containing attributes to add to link nodes
-     * @property cssAttributes
-     * @type object
-     */
-    // self.cssAttributes = null;
-
-    /**
-     * An object literal containing attributes to add to script nodes
-     * @property jsAttributes
-     * @type object
-     */
-    // self.jsAttributes = null;
-
-    /**
-     * The base directory.
-     * @property base
-     * @type string
-     * @default http://yui.yahooapis.com/[YUI VERSION]/build/
-     */
-    self.base = Y.Env.meta.base + Y.Env.meta.root;
-
-    /**
-     * Base path for the combo service
-     * @property comboBase
-     * @type string
-     * @default http://yui.yahooapis.com/combo?
-     */
-    self.comboBase = Y.Env.meta.comboBase;
-
-    /*
-     * Base path for language packs.
-     */
-    // self.langBase = Y.Env.meta.langBase;
-    // self.lang = "";
-
-    /**
-     * If configured, the loader will attempt to use the combo
-     * service for YUI resources and configured external resources.
-     * @property combine
-     * @type boolean
-     * @default true if a base dir isn't in the config
-     */
-    self.combine = o.base &&
-        (o.base.indexOf(self.comboBase.substr(0, 20)) > -1);
-
-    /**
-    * The default seperator to use between files in a combo URL
-    * @property comboSep
-    * @type {String}
-    * @default Ampersand
-    */
-    self.comboSep = '&';
-    /**
-     * Max url length for combo urls.  The default is 1024. This is the URL
-     * limit for the Yahoo! hosted combo servers.  If consuming
-     * a different combo service that has a different URL limit
-     * it is possible to override this default by supplying
-     * the maxURLLength config option.  The config option will
-     * only take effect if lower than the default.
-     *
-     * @property maxURLLength
-     * @type int
-     */
-    self.maxURLLength = MAX_URL_LENGTH;
-
-    /**
-     * Ignore modules registered on the YUI global
-     * @property ignoreRegistered
-     * @default false
-     */
-    self.ignoreRegistered = o.ignoreRegistered;
-
-    /**
-     * Root path to prepend to module path for the combo
-     * service
-     * @property root
-     * @type string
-     * @default [YUI VERSION]/build/
-     */
-    self.root = Y.Env.meta.root;
-
-    /**
-     * Timeout value in milliseconds.  If set, self value will be used by
-     * the get utility.  the timeout event will fire if
-     * a timeout occurs.
-     * @property timeout
-     * @type int
-     */
-    self.timeout = 0;
-
-    /**
-     * A list of modules that should not be loaded, even if
-     * they turn up in the dependency tree
-     * @property ignore
-     * @type string[]
-     */
-    // self.ignore = null;
-
-    /**
-     * A list of modules that should always be loaded, even
-     * if they have already been inserted into the page.
-     * @property force
-     * @type string[]
-     */
-    // self.force = null;
-
-    self.forceMap = {};
-
-    /**
-     * Should we allow rollups
-     * @property allowRollup
-     * @type boolean
-     * @default false
-     */
-    self.allowRollup = false;
-
-    /**
-     * A filter to apply to result urls.  This filter will modify the default
-     * path for all modules.  The default path for the YUI library is the
-     * minified version of the files (e.g., event-min.js).  The filter property
-     * can be a predefined filter or a custom filter.  The valid predefined
-     * filters are:
-     * <dl>
-     *  <dt>DEBUG</dt>
-     *  <dd>Selects the debug versions of the library (e.g., event-debug.js).
-     *      This option will automatically include the Logger widget</dd>
-     *  <dt>RAW</dt>
-     *  <dd>Selects the non-minified version of the library (e.g., event.js).
-     *  </dd>
-     * </dl>
-     * You can also define a custom filter, which must be an object literal
-     * containing a search expression and a replace string:
-     *
-     *      myFilter: {
-     *          'searchExp': "-min\\.js",
-     *          'replaceStr': "-debug.js"
-     *      }
-     *
-     * @property filter
-     * @type string| {searchExp: string, replaceStr: string}
-     */
-    // self.filter = null;
-
-    /**
-     * per-component filter specification.  If specified for a given
-     * component, this overrides the filter config.
-     * @property filters
-     * @type object
-     */
-    self.filters = {};
-
-    /**
-     * The list of requested modules
-     * @property required
-     * @type {string: boolean}
-     */
-    self.required = {};
-
-    /**
-     * If a module name is predefined when requested, it is checked againsts
-     * the patterns provided in this property.  If there is a match, the
-     * module is added with the default configuration.
-     *
-     * At the moment only supporting module prefixes, but anticipate
-     * supporting at least regular expressions.
-     * @property patterns
-     * @type Object
-     */
-    // self.patterns = Y.merge(Y.Env.meta.patterns);
-    self.patterns = {};
-
-    /**
-     * The library metadata
-     * @property moduleInfo
-     */
-    // self.moduleInfo = Y.merge(Y.Env.meta.moduleInfo);
-    self.moduleInfo = {};
-
-    self.groups = Y.merge(Y.Env.meta.groups);
-
-    /**
-     * Provides the information used to skin the skinnable components.
-     * The following skin definition would result in 'skin1' and 'skin2'
-     * being loaded for calendar (if calendar was requested), and
-     * 'sam' for all other skinnable components:
-     *
-     *      skin: {
-     *          // The default skin, which is automatically applied if not
-     *          // overriden by a component-specific skin definition.
-     *          // Change this in to apply a different skin globally
-     *          defaultSkin: 'sam',
-     *
-     *          // This is combined with the loader base property to get
-     *          // the default root directory for a skin. ex:
-     *          // http://yui.yahooapis.com/2.3.0/build/assets/skins/sam/
-     *          base: 'assets/skins/',
-     *
-     *          // Any component-specific overrides can be specified here,
-     *          // making it possible to load different skins for different
-     *          // components.  It is possible to load more than one skin
-     *          // for a given component as well.
-     *          overrides: {
-     *              calendar: ['skin1', 'skin2']
-     *          }
-     *      }
-     * @property skin
-     * @type {Object}
-     */
-    self.skin = Y.merge(Y.Env.meta.skin);
-
-    /*
-     * Map of conditional modules
-     * @since 3.2.0
-     */
-    self.conditions = {};
-
-    // map of modules with a hash of modules that meet the requirement
-    // self.provides = {};
-
-    self.config = o;
-    self._internal = true;
-
-    self._populateCache();
-
-    /**
-     * Set when beginning to compute the dependency tree.
-     * Composed of what YUI reports to be loaded combined
-     * with what has been loaded by any instance on the page
-     * with the version number specified in the metadata.
-     * @property loaded
-     * @type {string: boolean}
-     */
-    self.loaded = GLOBAL_LOADED[VERSION];
-
-
-    /**
-    * Should Loader fetch scripts in `async`, defaults to `true`
-    * @property async
-    */
-
-    self.async = true;
-
-    self._inspectPage();
-
-    self._internal = false;
-
-    self._config(o);
-
-    self.forceMap = (self.force) ? Y.Array.hash(self.force) : {};
-
-    self.testresults = null;
-
-    if (Y.config.tests) {
-        self.testresults = Y.config.tests;
-    }
-
-    /**
-     * List of rollup files found in the library metadata
-     * @property rollups
-     */
-    // self.rollups = null;
-
-    /**
-     * Whether or not to load optional dependencies for
-     * the requested modules
-     * @property loadOptional
-     * @type boolean
-     * @default false
-     */
-    // self.loadOptional = false;
-
-    /**
-     * All of the derived dependencies in sorted order, which
-     * will be populated when either calculate() or insert()
-     * is called
-     * @property sorted
-     * @type string[]
-     */
-    self.sorted = [];
-
-    /*
-     * A list of modules to attach to the YUI instance when complete.
-     * If not supplied, the sorted list of dependencies are applied.
-     * @property attaching
-     */
-    // self.attaching = null;
-
-    /**
-     * Flag to indicate the dependency tree needs to be recomputed
-     * if insert is called again.
-     * @property dirty
-     * @type boolean
-     * @default true
-     */
-    self.dirty = true;
-
-    /**
-     * List of modules inserted by the utility
-     * @property inserted
-     * @type {string: boolean}
-     */
-    self.inserted = {};
-
-    /**
-     * List of skipped modules during insert() because the module
-     * was not defined
-     * @property skipped
-     */
-    self.skipped = {};
-
-    // Y.on('yui:load', self.loadNext, self);
-
-    self.tested = {};
-
-    /*
-     * Cached sorted calculate results
-     * @property results
-     * @since 3.2.0
-     */
-    //self.results = {};
-
-    if (self.ignoreRegistered) {
-        //Clear inpage already processed modules.
-        self._resetModules();
-    }
-
-};
-
-Y.Loader.prototype = {
-    /**
-    * Checks the cache for modules and conditions, if they do not exist
-    * process the default metadata and populate the local moduleInfo hash.
-    * @method _populateCache
-    * @private
-    */
-    _populateCache: function() {
-        var self = this,
-            defaults = META.modules,
-            cache = GLOBAL_ENV._renderedMods,
-            i;
-
-        if (cache && !self.ignoreRegistered) {
-            for (i in cache) {
-                if (cache.hasOwnProperty(i)) {
-                    self.moduleInfo[i] = Y.merge(cache[i]);
-                }
-            }
-
-            cache = GLOBAL_ENV._conditions;
-            for (i in cache) {
-                if (cache.hasOwnProperty(i)) {
-                    self.conditions[i] = Y.merge(cache[i]);
-                }
-            }
-
-        } else {
-            for (i in defaults) {
-                if (defaults.hasOwnProperty(i)) {
-                    self.addModule(defaults[i], i);
-                }
-            }
-        }
-
-    },
-    /**
-    * Reset modules in the module cache to a pre-processed state so additional
-    * computations with a different skin or language will work as expected.
-    * @method _resetModules
-    * @private
-    */
-    _resetModules: function() {
-        var self = this, i, o,
-            mod, name, details;
-        for (i in self.moduleInfo) {
-            if (self.moduleInfo.hasOwnProperty(i)) {
-                mod = self.moduleInfo[i];
-                name = mod.name;
-                details  = (YUI.Env.mods[name] ? YUI.Env.mods[name].details : null);
-
-                if (details) {
-                    self.moduleInfo[name]._reset = true;
-                    self.moduleInfo[name].requires = details.requires || [];
-                    self.moduleInfo[name].optional = details.optional || [];
-                    self.moduleInfo[name].supersedes = details.supercedes || [];
-                }
-
-                if (mod.defaults) {
-                    for (o in mod.defaults) {
-                        if (mod.defaults.hasOwnProperty(o)) {
-                            if (mod[o]) {
-                                mod[o] = mod.defaults[o];
-                            }
-                        }
-                    }
-                }
-                delete mod.langCache;
-                delete mod.skinCache;
-                if (mod.skinnable) {
-                    self._addSkin(self.skin.defaultSkin, mod.name);
-                }
-            }
-        }
-    },
-    /**
-    Regex that matches a CSS URL. Used to guess the file type when it's not
-    specified.
-
-    @property REGEX_CSS
-    @type RegExp
-    @final
-    @protected
-    @since 3.5.0
-    **/
-    REGEX_CSS: /\.css(?:[?;].*)?$/i,
-
-    /**
-    * Default filters for raw and debug
-    * @property FILTER_DEFS
-    * @type Object
-    * @final
-    * @protected
-    */
-    FILTER_DEFS: {
-        RAW: {
-            'searchExp': '-min\\.js',
-            'replaceStr': '.js'
-        },
-        DEBUG: {
-            'searchExp': '-min\\.js',
-            'replaceStr': '-debug.js'
-        },
-        COVERAGE: {
-            'searchExp': '-min\\.js',
-            'replaceStr': '-coverage.js'
-        }
-    },
-    /*
-    * Check the pages meta-data and cache the result.
-    * @method _inspectPage
-    * @private
-    */
-    _inspectPage: function() {
-        var self = this, v, m, req, mr, i;
-
-        //Inspect the page for CSS only modules and mark them as loaded.
-        for (i in self.moduleInfo) {
-            if (self.moduleInfo.hasOwnProperty(i)) {
-                v = self.moduleInfo[i];
-                if (v.type && v.type === CSS) {
-                    if (self.isCSSLoaded(v.name)) {
-                        self.loaded[i] = true;
-                    }
-                }
-            }
-        }
-        for (i in ON_PAGE) {
-            if (ON_PAGE.hasOwnProperty(i)) {
-                v = ON_PAGE[i];
-                if (v.details) {
-                    m = self.moduleInfo[v.name];
-                    req = v.details.requires;
-                    mr = m && m.requires;
-
-                   if (m) {
-                       if (!m._inspected && req && mr.length !== req.length) {
-                           // console.log('deleting ' + m.name);
-                           delete m.expanded;
-                       }
-                   } else {
-                       m = self.addModule(v.details, i);
-                   }
-                   m._inspected = true;
-               }
-            }
-        }
-    },
-    /*
-    * returns true if b is not loaded, and is required directly or by means of modules it supersedes.
-    * @private
-    * @method _requires
-    * @param {String} mod1 The first module to compare
-    * @param {String} mod2 The second module to compare
-    */
-   _requires: function(mod1, mod2) {
-
-        var i, rm, after_map, s,
-            info = this.moduleInfo,
-            m = info[mod1],
-            other = info[mod2];
-
-        if (!m || !other) {
-            return false;
-        }
-
-        rm = m.expanded_map;
-        after_map = m.after_map;
-
-        // check if this module should be sorted after the other
-        // do this first to short circut circular deps
-        if (after_map && (mod2 in after_map)) {
-            return true;
-        }
-
-        after_map = other.after_map;
-
-        // and vis-versa
-        if (after_map && (mod1 in after_map)) {
-            return false;
-        }
-
-        // check if this module requires one the other supersedes
-        s = info[mod2] && info[mod2].supersedes;
-        if (s) {
-            for (i = 0; i < s.length; i++) {
-                if (this._requires(mod1, s[i])) {
-                    return true;
-                }
-            }
-        }
-
-        s = info[mod1] && info[mod1].supersedes;
-        if (s) {
-            for (i = 0; i < s.length; i++) {
-                if (this._requires(mod2, s[i])) {
-                    return false;
-                }
-            }
-        }
-
-        // check if this module requires the other directly
-        // if (r && yArray.indexOf(r, mod2) > -1) {
-        if (rm && (mod2 in rm)) {
-            return true;
-        }
-
-        // external css files should be sorted below yui css
-        if (m.ext && m.type === CSS && !other.ext && other.type === CSS) {
-            return true;
-        }
-
-        return false;
-    },
-    /**
-    * Apply a new config to the Loader instance
-    * @method _config
-    * @private
-    * @param {Object} o The new configuration
-    */
-    _config: function(o) {
-        var i, j, val, a, f, group, groupName, self = this,
-            mods = [], mod;
-        // apply config values
-        if (o) {
-            for (i in o) {
-                if (o.hasOwnProperty(i)) {
-                    val = o[i];
-                    //TODO This should be a case
-                    if (i === 'require') {
-                        self.require(val);
-                    } else if (i === 'skin') {
-                        //If the config.skin is a string, format to the expected object
-                        if (typeof val === 'string') {
-                            self.skin.defaultSkin = o.skin;
-                            val = {
-                                defaultSkin: val
-                            };
-                        }
-
-                        Y.mix(self.skin, val, true);
-                    } else if (i === 'groups') {
-                        for (j in val) {
-                            if (val.hasOwnProperty(j)) {
-                                groupName = j;
-                                group = val[j];
-                                self.addGroup(group, groupName);
-                                if (group.aliases) {
-                                    for (a in group.aliases) {
-                                        if (group.aliases.hasOwnProperty(a)) {
-                                            self.addAlias(group.aliases[a], a);
-                                        }
-                                    }
-                                }
-                            }
-                        }
-
-                    } else if (i === 'modules') {
-                        // add a hash of module definitions
-                        for (j in val) {
-                            if (val.hasOwnProperty(j)) {
-                                self.addModule(val[j], j);
-                            }
-                        }
-                    } else if (i === 'aliases') {
-                        for (j in val) {
-                            if (val.hasOwnProperty(j)) {
-                                self.addAlias(val[j], j);
-                            }
-                        }
-                    } else if (i === 'gallery') {
-                        if (this.groups.gallery.update) {
-                            this.groups.gallery.update(val, o);
-                        }
-                    } else if (i === 'yui2' || i === '2in3') {
-                        if (this.groups.yui2.update) {
-                            this.groups.yui2.update(o['2in3'], o.yui2, o);
-                        }
-                    } else {
-                        self[i] = val;
-                    }
-                }
-            }
-        }
-
-        // fix filter
-        f = self.filter;
-
-        if (L.isString(f)) {
-            f = f.toUpperCase();
-            self.filterName = f;
-            self.filter = self.FILTER_DEFS[f];
-            if (f === 'DEBUG') {
-                self.require('yui-log', 'dump');
-            }
-        }
-
-        if (self.filterName && self.coverage) {
-            if (self.filterName === 'COVERAGE' && L.isArray(self.coverage) && self.coverage.length) {
-                for (i = 0; i < self.coverage.length; i++) {
-                    mod = self.coverage[i];
-                    if (self.moduleInfo[mod] && self.moduleInfo[mod].use) {
-                        mods = [].concat(mods, self.moduleInfo[mod].use);
-                    } else {
-                        mods.push(mod);
-                    }
-                }
-                self.filters = self.filters || {};
-                Y.Array.each(mods, function(mod) {
-                    self.filters[mod] = self.FILTER_DEFS.COVERAGE;
-                });
-                self.filterName = 'RAW';
-                self.filter = self.FILTER_DEFS[self.filterName];
-            }
-        }
-
-    },
-
-    /**
-     * Returns the skin module name for the specified skin name.  If a
-     * module name is supplied, the returned skin module name is
-     * specific to the module passed in.
-     * @method formatSkin
-     * @param {string} skin the name of the skin.
-     * @param {string} mod optional: the name of a module to skin.
-     * @return {string} the full skin module name.
-     */
-    formatSkin: function(skin, mod) {
-        var s = SKIN_PREFIX + skin;
-        if (mod) {
-            s = s + '-' + mod;
-        }
-
-        return s;
-    },
-
-    /**
-     * Adds the skin def to the module info
-     * @method _addSkin
-     * @param {string} skin the name of the skin.
-     * @param {string} mod the name of the module.
-     * @param {string} parent parent module if this is a skin of a
-     * submodule or plugin.
-     * @return {string} the module name for the skin.
-     * @private
-     */
-    _addSkin: function(skin, mod, parent) {
-        var mdef, pkg, name, nmod,
-            info = this.moduleInfo,
-            sinf = this.skin,
-            ext = info[mod] && info[mod].ext;
-
-        // Add a module definition for the module-specific skin css
-        if (mod) {
-            name = this.formatSkin(skin, mod);
-            if (!info[name]) {
-                mdef = info[mod];
-                pkg = mdef.pkg || mod;
-                nmod = {
-                    skin: true,
-                    name: name,
-                    group: mdef.group,
-                    type: 'css',
-                    after: sinf.after,
-                    path: (parent || pkg) + '/' + sinf.base + skin +
-                          '/' + mod + '.css',
-                    ext: ext
-                };
-                if (mdef.base) {
-                    nmod.base = mdef.base;
-                }
-                if (mdef.configFn) {
-                    nmod.configFn = mdef.configFn;
-                }
-                this.addModule(nmod, name);
-
-            }
-        }
-
-        return name;
-    },
-    /**
-    * Adds an alias module to the system
-    * @method addAlias
-    * @param {Array} use An array of modules that makes up this alias
-    * @param {String} name The name of the alias
-    * @example
-    *       var loader = new Y.Loader({});
-    *       loader.addAlias([ 'node', 'yql' ], 'davglass');
-    *       loader.require(['davglass']);
-    *       var out = loader.resolve(true);
-    *
-    *       //out.js will contain Node and YQL modules
-    */
-    addAlias: function(use, name) {
-        YUI.Env.aliases[name] = use;
-        this.addModule({
-            name: name,
-            use: use
-        });
-    },
-    /**
-     * Add a new module group
-     * @method addGroup
-     * @param {Object} config An object containing the group configuration data
-     * @param {String} config.name required, the group name
-     * @param {String} config.base The base directory for this module group
-     * @param {String} config.root The root path to add to each combo resource path
-     * @param {Boolean} config.combine Should the request be combined
-     * @param {String} config.comboBase Combo service base path
-     * @param {Object} config.modules The group of modules
-     * @param {String} name the group name.
-     * @example
-     *      var loader = new Y.Loader({});
-     *      loader.addGroup({
-     *          name: 'davglass',
-     *          combine: true,
-     *          comboBase: '/combo?',
-     *          root: '',
-     *          modules: {
-     *              //Module List here
-     *          }
-     *      }, 'davglass');
-     */
-    addGroup: function(o, name) {
-        var mods = o.modules,
-            self = this, i, v;
-
-        name = name || o.name;
-        o.name = name;
-        self.groups[name] = o;
-
-        if (o.patterns) {
-            for (i in o.patterns) {
-                if (o.patterns.hasOwnProperty(i)) {
-                    o.patterns[i].group = name;
-                    self.patterns[i] = o.patterns[i];
-                }
-            }
-        }
-
-        if (mods) {
-            for (i in mods) {
-                if (mods.hasOwnProperty(i)) {
-                    v = mods[i];
-                    if (typeof v === 'string') {
-                        v = { name: i, fullpath: v };
-                    }
-                    v.group = name;
-                    self.addModule(v, i);
-                }
-            }
-        }
-    },
-
-    /**
-     * Add a new module to the component metadata.
-     * @method addModule
-     * @param {Object} config An object containing the module data.
-     * @param {String} config.name Required, the component name
-     * @param {String} config.type Required, the component type (js or css)
-     * @param {String} config.path Required, the path to the script from `base`
-     * @param {Array} config.requires Array of modules required by this component
-     * @param {Array} [config.optional] Array of optional modules for this component
-     * @param {Array} [config.supersedes] Array of the modules this component replaces
-     * @param {Array} [config.after] Array of modules the components which, if present, should be sorted above this one
-     * @param {Object} [config.after_map] Faster alternative to 'after' -- supply a hash instead of an array
-     * @param {Number} [config.rollup] The number of superseded modules required for automatic rollup
-     * @param {String} [config.fullpath] If `fullpath` is specified, this is used instead of the configured `base + path`
-     * @param {Boolean} [config.skinnable] Flag to determine if skin assets should automatically be pulled in
-     * @param {Object} [config.submodules] Hash of submodules
-     * @param {String} [config.group] The group the module belongs to -- this is set automatically when it is added as part of a group configuration.
-     * @param {Array} [config.lang] Array of BCP 47 language tags of languages for which this module has localized resource bundles, e.g., `["en-GB", "zh-Hans-CN"]`
-     * @param {Object} [config.condition] Specifies that the module should be loaded automatically if a condition is met. This is an object with up to four fields:
-     * @param {String} [config.condition.trigger] The name of a module that can trigger the auto-load
-     * @param {Function} [config.condition.test] A function that returns true when the module is to be loaded.
-     * @param {String} [config.condition.ua] The UA name of <a href="UA.html">Y.UA</a> object that returns true when the module is to be loaded. e.g., `"ie"`, `"nodejs"`.
-     * @param {String} [config.condition.when] Specifies the load order of the conditional module
-     *  with regard to the position of the trigger module.
-     *  This should be one of three values: `before`, `after`, or `instead`.  The default is `after`.
-     * @param {Object} [config.testresults] A hash of test results from `Y.Features.all()`
-     * @param {Function} [config.configFn] A function to exectute when configuring this module
-     * @param {Object} config.configFn.mod The module config, modifying this object will modify it's config. Returning false will delete the module's config.
-     * @param {String} [name] The module name, required if not in the module data.
-     * @return {Object} the module definition or null if the object passed in did not provide all required attributes.
-     */
-    addModule: function(o, name) {
-        name = name || o.name;
-
-        if (typeof o === 'string') {
-            o = { name: name, fullpath: o };
-        }
-
-
-        var subs, i, l, t, sup, s, smod, plugins, plug,
-            j, langs, packName, supName, flatSup, flatLang, lang, ret,
-            overrides, skinname, when, g, p,
-            conditions = this.conditions, trigger;
-
-        //Only merge this data if the temp flag is set
-        //from an earlier pass from a pattern or else
-        //an override module (YUI_config) can not be used to
-        //replace a default module.
-        if (this.moduleInfo[name] && this.moduleInfo[name].temp) {
-            //This catches temp modules loaded via a pattern
-            // The module will be added twice, once from the pattern and
-            // Once from the actual add call, this ensures that properties
-            // that were added to the module the first time around (group: gallery)
-            // are also added the second time around too.
-            o = Y.merge(this.moduleInfo[name], o);
-        }
-
-        o.name = name;
-
-        if (!o || !o.name) {
-            return null;
-        }
-
-        if (!o.type) {
-            //Always assume it's javascript unless the CSS pattern is matched.
-            o.type = JS;
-            p = o.path || o.fullpath;
-            if (p && this.REGEX_CSS.test(p)) {
-                o.type = CSS;
-            }
-        }
-
-        if (!o.path && !o.fullpath) {
-            o.path = _path(name, name, o.type);
-        }
-        o.supersedes = o.supersedes || o.use;
-
-        o.ext = ('ext' in o) ? o.ext : (this._internal) ? false : true;
-
-        // Handle submodule logic
-        subs = o.submodules;
-
-        this.moduleInfo[name] = o;
-
-        o.requires = o.requires || [];
-
-        /*
-        Only allowing the cascade of requires information, since
-        optional and supersedes are far more fine grained than
-        a blanket requires is.
-        */
-        if (this.requires) {
-            for (i = 0; i < this.requires.length; i++) {
-                o.requires.push(this.requires[i]);
-            }
-        }
-        if (o.group && this.groups && this.groups[o.group]) {
-            g = this.groups[o.group];
-            if (g.requires) {
-                for (i = 0; i < g.requires.length; i++) {
-                    o.requires.push(g.requires[i]);
-                }
-            }
-        }
-
-
-        if (!o.defaults) {
-            o.defaults = {
-                requires: o.requires ? [].concat(o.requires) : null,
-                supersedes: o.supersedes ? [].concat(o.supersedes) : null,
-                optional: o.optional ? [].concat(o.optional) : null
-            };
-        }
-
-        if (o.skinnable && o.ext && o.temp) {
-            skinname = this._addSkin(this.skin.defaultSkin, name);
-            o.requires.unshift(skinname);
-        }
-
-        if (o.requires.length) {
-            o.requires = this.filterRequires(o.requires) || [];
-        }
-
-        if (!o.langPack && o.lang) {
-            langs = yArray(o.lang);
-            for (j = 0; j < langs.length; j++) {
-                lang = langs[j];
-                packName = this.getLangPackName(lang, name);
-                smod = this.moduleInfo[packName];
-                if (!smod) {
-                    smod = this._addLangPack(lang, o, packName);
-                }
-            }
-        }
-
-
-        if (subs) {
-            sup = o.supersedes || [];
-            l = 0;
-
-            for (i in subs) {
-                if (subs.hasOwnProperty(i)) {
-                    s = subs[i];
-
-                    s.path = s.path || _path(name, i, o.type);
-                    s.pkg = name;
-                    s.group = o.group;
-
-                    if (s.supersedes) {
-                        sup = sup.concat(s.supersedes);
-                    }
-
-                    smod = this.addModule(s, i);
-                    sup.push(i);
-
-                    if (smod.skinnable) {
-                        o.skinnable = true;
-                        overrides = this.skin.overrides;
-                        if (overrides && overrides[i]) {
-                            for (j = 0; j < overrides[i].length; j++) {
-                                skinname = this._addSkin(overrides[i][j],
-                                         i, name);
-                                sup.push(skinname);
-                            }
-                        }
-                        skinname = this._addSkin(this.skin.defaultSkin,
-                                        i, name);
-                        sup.push(skinname);
-                    }
-
-                    // looks like we are expected to work out the metadata
-                    // for the parent module language packs from what is
-                    // specified in the child modules.
-                    if (s.lang && s.lang.length) {
-
-                        langs = yArray(s.lang);
-                        for (j = 0; j < langs.length; j++) {
-                            lang = langs[j];
-                            packName = this.getLangPackName(lang, name);
-                            supName = this.getLangPackName(lang, i);
-                            smod = this.moduleInfo[packName];
-
-                            if (!smod) {
-                                smod = this._addLangPack(lang, o, packName);
-                            }
-
-                            flatSup = flatSup || yArray.hash(smod.supersedes);
-
-                            if (!(supName in flatSup)) {
-                                smod.supersedes.push(supName);
-                            }
-
-                            o.lang = o.lang || [];
-
-                            flatLang = flatLang || yArray.hash(o.lang);
-
-                            if (!(lang in flatLang)) {
-                                o.lang.push(lang);
-                            }
-
-// Add rollup file, need to add to supersedes list too
-
-                            // default packages
-                            packName = this.getLangPackName(ROOT_LANG, name);
-                            supName = this.getLangPackName(ROOT_LANG, i);
-
-                            smod = this.moduleInfo[packName];
-
-                            if (!smod) {
-                                smod = this._addLangPack(lang, o, packName);
-                            }
-
-                            if (!(supName in flatSup)) {
-                                smod.supersedes.push(supName);
-                            }
-
-// Add rollup file, need to add to supersedes list too
-
-                        }
-                    }
-
-                    l++;
-                }
-            }
-            //o.supersedes = YObject.keys(yArray.hash(sup));
-            o.supersedes = yArray.dedupe(sup);
-            if (this.allowRollup) {
-                o.rollup = (l < 4) ? l : Math.min(l - 1, 4);
-            }
-        }
-
-        plugins = o.plugins;
-        if (plugins) {
-            for (i in plugins) {
-                if (plugins.hasOwnProperty(i)) {
-                    plug = plugins[i];
-                    plug.pkg = name;
-                    plug.path = plug.path || _path(name, i, o.type);
-                    plug.requires = plug.requires || [];
-                    plug.group = o.group;
-                    this.addModule(plug, i);
-                    if (o.skinnable) {
-                        this._addSkin(this.skin.defaultSkin, i, name);
-                    }
-
-                }
-            }
-        }
-
-        if (o.condition) {
-            t = o.condition.trigger;
-            if (YUI.Env.aliases[t]) {
-                t = YUI.Env.aliases[t];
-            }
-            if (!Y.Lang.isArray(t)) {
-                t = [t];
-            }
-
-            for (i = 0; i < t.length; i++) {
-                trigger = t[i];
-                when = o.condition.when;
-                conditions[trigger] = conditions[trigger] || {};
-                conditions[trigger][name] = o.condition;
-                // the 'when' attribute can be 'before', 'after', or 'instead'
-                // the default is after.
-                if (when && when !== 'after') {
-                    if (when === 'instead') { // replace the trigger
-                        o.supersedes = o.supersedes || [];
-                        o.supersedes.push(trigger);
-                    }
-                    // before the trigger
-                        // the trigger requires the conditional mod,
-                        // so it should appear before the conditional
-                        // mod if we do not intersede.
-                } else { // after the trigger
-                    o.after = o.after || [];
-                    o.after.push(trigger);
-                }
-            }
-        }
-
-        if (o.supersedes) {
-            o.supersedes = this.filterRequires(o.supersedes);
-        }
-
-        if (o.after) {
-            o.after = this.filterRequires(o.after);
-            o.after_map = yArray.hash(o.after);
-        }
-
-        // this.dirty = true;
-
-        if (o.configFn) {
-            ret = o.configFn(o);
-            if (ret === false) {
-                delete this.moduleInfo[name];
-                delete GLOBAL_ENV._renderedMods[name];
-                o = null;
-            }
-        }
-        //Add to global cache
-        if (o) {
-            if (!GLOBAL_ENV._renderedMods) {
-                GLOBAL_ENV._renderedMods = {};
-            }
-            GLOBAL_ENV._renderedMods[name] = Y.mix(GLOBAL_ENV._renderedMods[name] || {}, o);
-            GLOBAL_ENV._conditions = conditions;
-        }
-
-        return o;
-    },
-
-    /**
-     * Add a requirement for one or more module
-     * @method require
-     * @param {string[] | string*} what the modules to load.
-     */
-    require: function(what) {
-        var a = (typeof what === 'string') ? yArray(arguments) : what;
-        this.dirty = true;
-        this.required = Y.merge(this.required, yArray.hash(this.filterRequires(a)));
-
-        this._explodeRollups();
-    },
-    /**
-    * Grab all the items that were asked for, check to see if the Loader
-    * meta-data contains a "use" array. If it doesm remove the asked item and replace it with
-    * the content of the "use".
-    * This will make asking for: "dd"
-    * Actually ask for: "dd-ddm-base,dd-ddm,dd-ddm-drop,dd-drag,dd-proxy,dd-constrain,dd-drop,dd-scroll,dd-drop-plugin"
-    * @private
-    * @method _explodeRollups
-    */
-    _explodeRollups: function() {
-        var self = this, m, m2, i, a, v, len, len2,
-        r = self.required;
-
-        if (!self.allowRollup) {
-            for (i in r) {
-                if (r.hasOwnProperty(i)) {
-                    m = self.getModule(i);
-                    if (m && m.use) {
-                        len = m.use.length;
-                        for (a = 0; a < len; a++) {
-                            m2 = self.getModule(m.use[a]);
-                            if (m2 && m2.use) {
-                                len2 = m2.use.length;
-                                for (v = 0; v < len2; v++) {
-                                    r[m2.use[v]] = true;
-                                }
-                            } else {
-                                r[m.use[a]] = true;
-                            }
-                        }
-                    }
-                }
-            }
-            self.required = r;
-        }
-
-    },
-    /**
-    * Explodes the required array to remove aliases and replace them with real modules
-    * @method filterRequires
-    * @param {Array} r The original requires array
-    * @return {Array} The new array of exploded requirements
-    */
-    filterRequires: function(r) {
-        if (r) {
-            if (!Y.Lang.isArray(r)) {
-                r = [r];
-            }
-            r = Y.Array(r);
-            var c = [], i, mod, o, m;
-
-            for (i = 0; i < r.length; i++) {
-                mod = this.getModule(r[i]);
-                if (mod && mod.use) {
-                    for (o = 0; o < mod.use.length; o++) {
-                        //Must walk the other modules in case a module is a rollup of rollups (datatype)
-                        m = this.getModule(mod.use[o]);
-                        if (m && m.use && (m.name !== mod.name)) {
-                            c = Y.Array.dedupe([].concat(c, this.filterRequires(m.use)));
-                        } else {
-                            c.push(mod.use[o]);
-                        }
-                    }
-                } else {
-                    c.push(r[i]);
-                }
-            }
-            r = c;
-        }
-        return r;
-    },
-    /**
-     * Returns an object containing properties for all modules required
-     * in order to load the requested module
-     * @method getRequires
-     * @param {object}  mod The module definition from moduleInfo.
-     * @return {array} the expanded requirement list.
-     */
-    getRequires: function(mod) {
-
-        if (!mod) {
-            //console.log('returning no reqs for ' + mod.name);
-            return NO_REQUIREMENTS;
-        }
-
-        if (mod._parsed) {
-            //console.log('returning requires for ' + mod.name, mod.requires);
-            return mod.expanded || NO_REQUIREMENTS;
-        }
-
-        //TODO add modue cache here out of scope..
-
-        var i, m, j, add, packName, lang, testresults = this.testresults,
-            name = mod.name, cond,
-            adddef = ON_PAGE[name] && ON_PAGE[name].details,
-            d, go, def,
-            r, old_mod,
-            o, skinmod, skindef, skinpar, skinname,
-            intl = mod.lang || mod.intl,
-            info = this.moduleInfo,
-            ftests = Y.Features && Y.Features.tests.load,
-            hash, reparse;
-
-        // console.log(name);
-
-        // pattern match leaves module stub that needs to be filled out
-        if (mod.temp && adddef) {
-            old_mod = mod;
-            mod = this.addModule(adddef, name);
-            mod.group = old_mod.group;
-            mod.pkg = old_mod.pkg;
-            delete mod.expanded;
-        }
-
-        // console.log('cache: ' + mod.langCache + ' == ' + this.lang);
-
-        //If a skin or a lang is different, reparse..
-        reparse = !((!this.lang || mod.langCache === this.lang) && (mod.skinCache === this.skin.defaultSkin));
-
-        if (mod.expanded && !reparse) {
-            return mod.expanded;
-        }
-
-
-        d = [];
-        hash = {};
-        r = this.filterRequires(mod.requires);
-        if (mod.lang) {
-            //If a module has a lang attribute, auto add the intl requirement.
-            d.unshift('intl');
-            r.unshift('intl');
-            intl = true;
-        }
-        o = this.filterRequires(mod.optional);
-
-
-        mod._parsed = true;
-        mod.langCache = this.lang;
-        mod.skinCache = this.skin.defaultSkin;
-
-        for (i = 0; i < r.length; i++) {
-            if (!hash[r[i]]) {
-                d.push(r[i]);
-                hash[r[i]] = true;
-                m = this.getModule(r[i]);
-                if (m) {
-                    add = this.getRequires(m);
-                    intl = intl || (m.expanded_map &&
-                        (INTL in m.expanded_map));
-                    for (j = 0; j < add.length; j++) {
-                        d.push(add[j]);
-                    }
-                }
-            }
-        }
-
-        // get the requirements from superseded modules, if any
-        r = this.filterRequires(mod.supersedes);
-        if (r) {
-            for (i = 0; i < r.length; i++) {
-                if (!hash[r[i]]) {
-                    // if this module has submodules, the requirements list is
-                    // expanded to include the submodules.  This is so we can
-                    // prevent dups when a submodule is already loaded and the
-                    // parent is requested.
-                    if (mod.submodules) {
-                        d.push(r[i]);
-                    }
-
-                    hash[r[i]] = true;
-                    m = this.getModule(r[i]);
-
-                    if (m) {
-                        add = this.getRequires(m);
-                        intl = intl || (m.expanded_map &&
-                            (INTL in m.expanded_map));
-                        for (j = 0; j < add.length; j++) {
-                            d.push(add[j]);
-                        }
-                    }
-                }
-            }
-        }
-
-        if (o && this.loadOptional) {
-            for (i = 0; i < o.length; i++) {
-                if (!hash[o[i]]) {
-                    d.push(o[i]);
-                    hash[o[i]] = true;
-                    m = info[o[i]];
-                    if (m) {
-                        add = this.getRequires(m);
-                        intl = intl || (m.expanded_map &&
-                            (INTL in m.expanded_map));
-                        for (j = 0; j < add.length; j++) {
-                            d.push(add[j]);
-                        }
-                    }
-                }
-            }
-        }
-
-        cond = this.conditions[name];
-
-        if (cond) {
-            //Set the module to not parsed since we have conditionals and this could change the dependency tree.
-            mod._parsed = false;
-            if (testresults && ftests) {
-                oeach(testresults, function(result, id) {
-                    var condmod = ftests[id].name;
-                    if (!hash[condmod] && ftests[id].trigger === name) {
-                        if (result && ftests[id]) {
-                            hash[condmod] = true;
-                            d.push(condmod);
-                        }
-                    }
-                });
-            } else {
-                for (i in cond) {
-                    if (cond.hasOwnProperty(i)) {
-                        if (!hash[i]) {
-                            def = cond[i];
-                            //first see if they've specfied a ua check
-                            //then see if they've got a test fn & if it returns true
-                            //otherwise just having a condition block is enough
-                            go = def && ((!def.ua && !def.test) || (def.ua && Y.UA[def.ua]) ||
-                                        (def.test && def.test(Y, r)));
-
-                            if (go) {
-                                hash[i] = true;
-                                d.push(i);
-                                m = this.getModule(i);
-                                if (m) {
-                                    add = this.getRequires(m);
-                                    for (j = 0; j < add.length; j++) {
-                                        d.push(add[j]);
-                                    }
-
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        // Create skin modules
-        if (mod.skinnable) {
-            skindef = this.skin.overrides;
-            for (i in YUI.Env.aliases) {
-                if (YUI.Env.aliases.hasOwnProperty(i)) {
-                    if (Y.Array.indexOf(YUI.Env.aliases[i], name) > -1) {
-                        skinpar = i;
-                    }
-                }
-            }
-            if (skindef && (skindef[name] || (skinpar && skindef[skinpar]))) {
-                skinname = name;
-                if (skindef[skinpar]) {
-                    skinname = skinpar;
-                }
-                for (i = 0; i < skindef[skinname].length; i++) {
-                    skinmod = this._addSkin(skindef[skinname][i], name);
-                    if (!this.isCSSLoaded(skinmod, this._boot)) {
-                        d.push(skinmod);
-                    }
-                }
-            } else {
-                skinmod = this._addSkin(this.skin.defaultSkin, name);
-                if (!this.isCSSLoaded(skinmod, this._boot)) {
-                    d.push(skinmod);
-                }
-            }
-        }
-
-        mod._parsed = false;
-
-        if (intl) {
-
-            if (mod.lang && !mod.langPack && Y.Intl) {
-                lang = Y.Intl.lookupBestLang(this.lang || ROOT_LANG, mod.lang);
-                packName = this.getLangPackName(lang, name);
-                if (packName) {
-                    d.unshift(packName);
-                }
-            }
-            d.unshift(INTL);
-        }
-
-        mod.expanded_map = yArray.hash(d);
-
-        mod.expanded = YObject.keys(mod.expanded_map);
-
-        return mod.expanded;
-    },
-    /**
-    * Check to see if named css module is already loaded on the page
-    * @method isCSSLoaded
-    * @param {String} name The name of the css file
-    * @return Boolean
-    */
-    isCSSLoaded: function(name, skip) {
-        //TODO - Make this call a batching call with name being an array
-        if (!name || !YUI.Env.cssStampEl || (!skip && this.ignoreRegistered)) {
-            return false;
-        }
-        var el = YUI.Env.cssStampEl,
-            ret = false,
-            mod = YUI.Env._cssLoaded[name],
-            style = el.currentStyle; //IE
-
-
-        if (mod !== undefined) {
-            return mod;
-        }
-
-        //Add the classname to the element
-        el.className = name;
-
-        if (!style) {
-            style = Y.config.doc.defaultView.getComputedStyle(el, null);
-        }
-
-        if (style && style.display === 'none') {
-            ret = true;
-        }
-
-
-        el.className = ''; //Reset the classname to ''
-
-        YUI.Env._cssLoaded[name] = ret;
-
-        return ret;
-    },
-
-    /**
-     * Returns a hash of module names the supplied module satisfies.
-     * @method getProvides
-     * @param {string} name The name of the module.
-     * @return {object} what this module provides.
-     */
-    getProvides: function(name) {
-        var m = this.getModule(name), o, s;
-            // supmap = this.provides;
-
-        if (!m) {
-            return NOT_FOUND;
-        }
-
-        if (m && !m.provides) {
-            o = {};
-            s = m.supersedes;
-
-            if (s) {
-                yArray.each(s, function(v) {
-                    Y.mix(o, this.getProvides(v));
-                }, this);
-            }
-
-            o[name] = true;
-            m.provides = o;
-
-        }
-
-        return m.provides;
-    },
-
-    /**
-     * Calculates the dependency tree, the result is stored in the sorted
-     * property.
-     * @method calculate
-     * @param {object} o optional options object.
-     * @param {string} type optional argument to prune modules.
-     */
-    calculate: function(o, type) {
-        if (o || type || this.dirty) {
-
-            if (o) {
-                this._config(o);
-            }
-
-            if (!this._init) {
-                this._setup();
-            }
-
-            this._explode();
-
-            if (this.allowRollup) {
-                this._rollup();
-            } else {
-                this._explodeRollups();
-            }
-            this._reduce();
-            this._sort();
-        }
-    },
-    /**
-    * Creates a "psuedo" package for languages provided in the lang array
-    * @method _addLangPack
-    * @private
-    * @param {String} lang The language to create
-    * @param {Object} m The module definition to create the language pack around
-    * @param {String} packName The name of the package (e.g: lang/datatype-date-en-US)
-    * @return {Object} The module definition
-    */
-    _addLangPack: function(lang, m, packName) {
-        var name = m.name,
-            packPath, conf,
-            existing = this.moduleInfo[packName];
-
-        if (!existing) {
-
-            packPath = _path((m.pkg || name), packName, JS, true);
-
-            conf = {
-                path: packPath,
-                intl: true,
-                langPack: true,
-                ext: m.ext,
-                group: m.group,
-                supersedes: []
-            };
-            if (m.root) {
-                conf.root = m.root;
-            }
-            if (m.base) {
-                conf.base = m.base;
-            }
-
-            if (m.configFn) {
-                conf.configFn = m.configFn;
-            }
-
-            this.addModule(conf, packName);
-
-            if (lang) {
-                Y.Env.lang = Y.Env.lang || {};
-                Y.Env.lang[lang] = Y.Env.lang[lang] || {};
-                Y.Env.lang[lang][name] = true;
-            }
-        }
-
-        return this.moduleInfo[packName];
-    },
-
-    /**
-     * Investigates the current YUI configuration on the page.  By default,
-     * modules already detected will not be loaded again unless a force
-     * option is encountered.  Called by calculate()
-     * @method _setup
-     * @private
-     */
-    _setup: function() {
-        var info = this.moduleInfo, name, i, j, m, l,
-            packName;
-
-        for (name in info) {
-            if (info.hasOwnProperty(name)) {
-                m = info[name];
-                if (m) {
-
-                    // remove dups
-                    //m.requires = YObject.keys(yArray.hash(m.requires));
-                    m.requires = yArray.dedupe(m.requires);
-
-                    // Create lang pack modules
-                    //if (m.lang && m.lang.length) {
-                    if (m.lang) {
-                        // Setup root package if the module has lang defined,
-                        // it needs to provide a root language pack
-                        packName = this.getLangPackName(ROOT_LANG, name);
-                        this._addLangPack(null, m, packName);
-                    }
-
-                }
-            }
-        }
-
-
-        //l = Y.merge(this.inserted);
-        l = {};
-
-        // available modules
-        if (!this.ignoreRegistered) {
-            Y.mix(l, GLOBAL_ENV.mods);
-        }
-
-        // add the ignore list to the list of loaded packages
-        if (this.ignore) {
-            Y.mix(l, yArray.hash(this.ignore));
-        }
-
-        // expand the list to include superseded modules
-        for (j in l) {
-            if (l.hasOwnProperty(j)) {
-                Y.mix(l, this.getProvides(j));
-            }
-        }
-
-        // remove modules on the force list from the loaded list
-        if (this.force) {
-            for (i = 0; i < this.force.length; i++) {
-                if (this.force[i] in l) {
-                    delete l[this.force[i]];
-                }
-            }
-        }
-
-        Y.mix(this.loaded, l);
-
-        this._init = true;
-    },
-
-    /**
-     * Builds a module name for a language pack
-     * @method getLangPackName
-     * @param {string} lang the language code.
-     * @param {string} mname the module to build it for.
-     * @return {string} the language pack module name.
-     */
-    getLangPackName: function(lang, mname) {
-        return ('lang/' + mname + ((lang) ? '_' + lang : ''));
-    },
-    /**
-     * Inspects the required modules list looking for additional
-     * dependencies.  Expands the required list to include all
-     * required modules.  Called by calculate()
-     * @method _explode
-     * @private
-     */
-    _explode: function() {
-        //TODO Move done out of scope
-        var r = this.required, m, reqs, done = {},
-            self = this, name, expound;
-
-        // the setup phase is over, all modules have been created
-        self.dirty = false;
-
-        self._explodeRollups();
-        r = self.required;
-
-        for (name in r) {
-            if (r.hasOwnProperty(name)) {
-                if (!done[name]) {
-                    done[name] = true;
-                    m = self.getModule(name);
-                    if (m) {
-                        expound = m.expound;
-
-                        if (expound) {
-                            r[expound] = self.getModule(expound);
-                            reqs = self.getRequires(r[expound]);
-                            Y.mix(r, yArray.hash(reqs));
-                        }
-
-                        reqs = self.getRequires(m);
-                        Y.mix(r, yArray.hash(reqs));
-                    }
-                }
-            }
-        }
-
-    },
-    /**
-    * The default method used to test a module against a pattern
-    * @method _patternTest
-    * @private
-    * @param {String} mname The module being tested
-    * @param {String} pname The pattern to match
-    */
-    _patternTest: function(mname, pname) {
-        return (mname.indexOf(pname) > -1);
-    },
-    /**
-    * Get's the loader meta data for the requested module
-    * @method getModule
-    * @param {String} mname The module name to get
-    * @return {Object} The module metadata
-    */
-    getModule: function(mname) {
-        //TODO: Remove name check - it's a quick hack to fix pattern WIP
-        if (!mname) {
-            return null;
-        }
-
-        var p, found, pname,
-            m = this.moduleInfo[mname],
-            patterns = this.patterns;
-
-        // check the patterns library to see if we should automatically add
-        // the module with defaults
-        if (!m || (m && m.ext)) {
-            for (pname in patterns) {
-                if (patterns.hasOwnProperty(pname)) {
-                    p = patterns[pname];
-
-                    //There is no test method, create a default one that tests
-                    // the pattern against the mod name
-                    if (!p.test) {
-                        p.test = this._patternTest;
-                    }
-
-                    if (p.test(mname, pname)) {
-                        // use the metadata supplied for the pattern
-                        // as the module definition.
-                        found = p;
-                        break;
-                    }
-                }
-            }
-        }
-
-        if (!m) {
-            if (found) {
-                if (p.action) {
-                    p.action.call(this, mname, pname);
-                } else {
-                    // ext true or false?
-                    m = this.addModule(Y.merge(found), mname);
-                    if (found.configFn) {
-                        m.configFn = found.configFn;
-                    }
-                    m.temp = true;
-                }
-            }
-        } else {
-            if (found && m && found.configFn && !m.configFn) {
-                m.configFn = found.configFn;
-                m.configFn(m);
-            }
-        }
-
-        return m;
-    },
-
-    // impl in rollup submodule
-    _rollup: function() { },
-
-    /**
-     * Remove superceded modules and loaded modules.  Called by
-     * calculate() after we have the mega list of all dependencies
-     * @method _reduce
-     * @return {object} the reduced dependency hash.
-     * @private
-     */
-    _reduce: function(r) {
-
-        r = r || this.required;
-
-        var i, j, s, m, type = this.loadType,
-        ignore = this.ignore ? yArray.hash(this.ignore) : false;
-
-        for (i in r) {
-            if (r.hasOwnProperty(i)) {
-                m = this.getModule(i);
-                // remove if already loaded
-                if (((this.loaded[i] || ON_PAGE[i]) &&
-                        !this.forceMap[i] && !this.ignoreRegistered) ||
-                        (type && m && m.type !== type)) {
-                    delete r[i];
-                }
-                if (ignore && ignore[i]) {
-                    delete r[i];
-                }
-                // remove anything this module supersedes
-                s = m && m.supersedes;
-                if (s) {
-                    for (j = 0; j < s.length; j++) {
-                        if (s[j] in r) {
-                            delete r[s[j]];
-                        }
-                    }
-                }
-            }
-        }
-
-        return r;
-    },
-    /**
-    * Handles the queue when a module has been loaded for all cases
-    * @method _finish
-    * @private
-    * @param {String} msg The message from Loader
-    * @param {Boolean} success A boolean denoting success or failure
-    */
-    _finish: function(msg, success) {
-
-        _queue.running = false;
-
-        var onEnd = this.onEnd;
-        if (onEnd) {
-            onEnd.call(this.context, {
-                msg: msg,
-                data: this.data,
-                success: success
-            });
-        }
-        this._continue();
-    },
-    /**
-    * The default Loader onSuccess handler, calls this.onSuccess with a payload
-    * @method _onSuccess
-    * @private
-    */
-    _onSuccess: function() {
-        var self = this, skipped = Y.merge(self.skipped), fn,
-            failed = [], rreg = self.requireRegistration,
-            success, msg, i, mod;
-
-        for (i in skipped) {
-            if (skipped.hasOwnProperty(i)) {
-                delete self.inserted[i];
-            }
-        }
-
-        self.skipped = {};
-
-        for (i in self.inserted) {
-            if (self.inserted.hasOwnProperty(i)) {
-                mod = self.getModule(i);
-                if (mod && rreg && mod.type === JS && !(i in YUI.Env.mods)) {
-                    failed.push(i);
-                } else {
-                    Y.mix(self.loaded, self.getProvides(i));
-                }
-            }
-        }
-
-        fn = self.onSuccess;
-        msg = (failed.length) ? 'notregistered' : 'success';
-        success = !(failed.length);
-        if (fn) {
-            fn.call(self.context, {
-                msg: msg,
-                data: self.data,
-                success: success,
-                failed: failed,
-                skipped: skipped
-            });
-        }
-        self._finish(msg, success);
-    },
-    /**
-    * The default Loader onProgress handler, calls this.onProgress with a payload
-    * @method _onProgress
-    * @private
-    */
-    _onProgress: function(e) {
-        var self = this, i;
-        //set the internal cache to what just came in.
-        if (e.data && e.data.length) {
-            for (i = 0; i < e.data.length; i++) {
-                e.data[i] = self.getModule(e.data[i].name);
-            }
-        }
-        if (self.onProgress) {
-            self.onProgress.call(self.context, {
-                name: e.url,
-                data: e.data
-            });
-        }
-    },
-    /**
-    * The default Loader onFailure handler, calls this.onFailure with a payload
-    * @method _onFailure
-    * @private
-    */
-    _onFailure: function(o) {
-        var f = this.onFailure, msg = [], i = 0, len = o.errors.length;
-
-        for (i; i < len; i++) {
-            msg.push(o.errors[i].error);
-        }
-
-        msg = msg.join(',');
-
-
-        if (f) {
-            f.call(this.context, {
-                msg: msg,
-                data: this.data,
-                success: false
-            });
-        }
-
-        this._finish(msg, false);
-
-    },
-
-    /**
-    * The default Loader onTimeout handler, calls this.onTimeout with a payload
-    * @method _onTimeout
-    * @param {Get.Transaction} transaction The Transaction object from `Y.Get`
-    * @private
-    */
-    _onTimeout: function(transaction) {
-        var f = this.onTimeout;
-        if (f) {
-            f.call(this.context, {
-                msg: 'timeout',
-                data: this.data,
-                success: false,
-                transaction: transaction
-            });
-        }
-    },
-
-    /**
-     * Sorts the dependency tree.  The last step of calculate()
-     * @method _sort
-     * @private
-     */
-    _sort: function() {
-
-        // create an indexed list
-        var s = YObject.keys(this.required),
-            // loaded = this.loaded,
-            //TODO Move this out of scope
-            done = {},
-            p = 0, l, a, b, j, k, moved, doneKey;
-
-        // keep going until we make a pass without moving anything
-        for (;;) {
-
-            l = s.length;
-            moved = false;
-
-            // start the loop after items that are already sorted
-            for (j = p; j < l; j++) {
-
-                // check the next module on the list to see if its
-                // dependencies have been met
-                a = s[j];
-
-                // check everything below current item and move if we
-                // find a requirement for the current item
-                for (k = j + 1; k < l; k++) {
-                    doneKey = a + s[k];
-
-                    if (!done[doneKey] && this._requires(a, s[k])) {
-
-                        // extract the dependency so we can move it up
-                        b = s.splice(k, 1);
-
-                        // insert the dependency above the item that
-                        // requires it
-                        s.splice(j, 0, b[0]);
-
-                        // only swap two dependencies once to short circut
-                        // circular dependencies
-                        done[doneKey] = true;
-
-                        // keep working
-                        moved = true;
-
-                        break;
-                    }
-                }
-
-                // jump out of loop if we moved something
-                if (moved) {
-                    break;
-                // this item is sorted, move our pointer and keep going
-                } else {
-                    p++;
-                }
-            }
-
-            // when we make it here and moved is false, we are
-            // finished sorting
-            if (!moved) {
-                break;
-            }
-
-        }
-
-        this.sorted = s;
-    },
-
-    /**
-    * Handles the actual insertion of script/link tags
-    * @method _insert
-    * @private
-    * @param {Object} source The YUI instance the request came from
-    * @param {Object} o The metadata to include
-    * @param {String} type JS or CSS
-    * @param {Boolean} [skipcalc=false] Do a Loader.calculate on the meta
-    */
-    _insert: function(source, o, type, skipcalc) {
-
-
-        // restore the state at the time of the request
-        if (source) {
-            this._config(source);
-        }
-
-        // build the dependency list
-        // don't include type so we can process CSS and script in
-        // one pass when the type is not specified.
-
-        var modules = this.resolve(!skipcalc),
-            self = this, comp = 0, actions = 0,
-            mods = {}, deps, complete;
-
-        self._refetch = [];
-
-        if (type) {
-            //Filter out the opposite type and reset the array so the checks later work
-            modules[((type === JS) ? CSS : JS)] = [];
-        }
-        if (!self.fetchCSS) {
-            modules.css = [];
-        }
-        if (modules.js.length) {
-            comp++;
-        }
-        if (modules.css.length) {
-            comp++;
-        }
-
-        //console.log('Resolved Modules: ', modules);
-
-        complete = function(d) {
-            actions++;
-            var errs = {}, i = 0, o = 0, u = '', fn,
-                modName, resMods;
-
-            if (d && d.errors) {
-                for (i = 0; i < d.errors.length; i++) {
-                    if (d.errors[i].request) {
-                        u = d.errors[i].request.url;
-                    } else {
-                        u = d.errors[i];
-                    }
-                    errs[u] = u;
-                }
-            }
-
-            if (d && d.data && d.data.length && (d.type === 'success')) {
-                for (i = 0; i < d.data.length; i++) {
-                    self.inserted[d.data[i].name] = true;
-                    //If the external module has a skin or a lang, reprocess it
-                    if (d.data[i].lang || d.data[i].skinnable) {
-                        delete self.inserted[d.data[i].name];
-                        self._refetch.push(d.data[i].name);
-                    }
-                }
-            }
-
-            if (actions === comp) {
-                self._loading = null;
-                if (self._refetch.length) {
-                    //Get the deps for the new meta-data and reprocess
-                    for (i = 0; i < self._refetch.length; i++) {
-                        deps = self.getRequires(self.getModule(self._refetch[i]));
-                        for (o = 0; o < deps.length; o++) {
-                            if (!self.inserted[deps[o]]) {
-                                //We wouldn't be to this point without the module being here
-                                mods[deps[o]] = deps[o];
-                            }
-                        }
-                    }
-                    mods = Y.Object.keys(mods);
-                    if (mods.length) {
-                        self.require(mods);
-                        resMods = self.resolve(true);
-                        if (resMods.cssMods.length) {
-                            for (i=0; i <  resMods.cssMods.length; i++) {
-                                modName = resMods.cssMods[i].name;
-                                delete YUI.Env._cssLoaded[modName];
-                                if (self.isCSSLoaded(modName)) {
-                                    self.inserted[modName] = true;
-                                    delete self.required[modName];
-                                }
-                            }
-                            self.sorted = [];
-                            self._sort();
-                        }
-                        d = null; //bail
-                        self._insert(); //insert the new deps
-                    }
-                }
-                if (d && d.fn) {
-                    fn = d.fn;
-                    delete d.fn;
-                    fn.call(self, d);
-                }
-            }
-        };
-
-        this._loading = true;
-
-        if (!modules.js.length && !modules.css.length) {
-            actions = -1;
-            complete({
-                fn: self._onSuccess
-            });
-            return;
-        }
-
-
-        if (modules.css.length) { //Load CSS first
-            Y.Get.css(modules.css, {
-                data: modules.cssMods,
-                attributes: self.cssAttributes,
-                insertBefore: self.insertBefore,
-                charset: self.charset,
-                timeout: self.timeout,
-                context: self,
-                onProgress: function(e) {
-                    self._onProgress.call(self, e);
-                },
-                onTimeout: function(d) {
-                    self._onTimeout.call(self, d);
-                },
-                onSuccess: function(d) {
-                    d.type = 'success';
-                    d.fn = self._onSuccess;
-                    complete.call(self, d);
-                },
-                onFailure: function(d) {
-                    d.type = 'failure';
-                    d.fn = self._onFailure;
-                    complete.call(self, d);
-                }
-            });
-        }
-
-        if (modules.js.length) {
-            Y.Get.js(modules.js, {
-                data: modules.jsMods,
-                insertBefore: self.insertBefore,
-                attributes: self.jsAttributes,
-                charset: self.charset,
-                timeout: self.timeout,
-                autopurge: false,
-                context: self,
-                async: self.async,
-                onProgress: function(e) {
-                    self._onProgress.call(self, e);
-                },
-                onTimeout: function(d) {
-                    self._onTimeout.call(self, d);
-                },
-                onSuccess: function(d) {
-                    d.type = 'success';
-                    d.fn = self._onSuccess;
-                    complete.call(self, d);
-                },
-                onFailure: function(d) {
-                    d.type = 'failure';
-                    d.fn = self._onFailure;
-                    complete.call(self, d);
-                }
-            });
-        }
-    },
-    /**
-    * Once a loader operation is completely finished, process any additional queued items.
-    * @method _continue
-    * @private
-    */
-    _continue: function() {
-        if (!(_queue.running) && _queue.size() > 0) {
-            _queue.running = true;
-            _queue.next()();
-        }
-    },
-
-    /**
-     * inserts the requested modules and their dependencies.
-     * <code>type</code> can be "js" or "css".  Both script and
-     * css are inserted if type is not provided.
-     * @method insert
-     * @param {object} o optional options object.
-     * @param {string} type the type of dependency to insert.
-     */
-    insert: function(o, type, skipsort) {
-        var self = this, copy = Y.merge(this);
-        delete copy.require;
-        delete copy.dirty;
-        _queue.add(function() {
-            self._insert(copy, o, type, skipsort);
-        });
-        this._continue();
-    },
-
-    /**
-     * Executed every time a module is loaded, and if we are in a load
-     * cycle, we attempt to load the next script.  Public so that it
-     * is possible to call this if using a method other than
-     * Y.register to determine when scripts are fully loaded
-     * @method loadNext
-     * @deprecated
-     * @param {string} mname optional the name of the module that has
-     * been loaded (which is usually why it is time to load the next
-     * one).
-     */
-    loadNext: function() {
-        return;
-    },
-
-    /**
-     * Apply filter defined for this instance to a url/path
-     * @method _filter
-     * @param {string} u the string to filter.
-     * @param {string} name the name of the module, if we are processing
-     * a single module as opposed to a combined url.
-     * @return {string} the filtered string.
-     * @private
-     */
-    _filter: function(u, name, group) {
-        var f = this.filter,
-            hasFilter = name && (name in this.filters),
-            modFilter = hasFilter && this.filters[name],
-            groupName = group || (this.moduleInfo[name] ? this.moduleInfo[name].group : null);
-
-        if (groupName && this.groups[groupName] && this.groups[groupName].filter) {
-            modFilter = this.groups[groupName].filter;
-            hasFilter = true;
-        }
-
-        if (u) {
-            if (hasFilter) {
-                f = (L.isString(modFilter)) ? this.FILTER_DEFS[modFilter.toUpperCase()] || null : modFilter;
-            }
-            if (f) {
-                u = u.replace(new RegExp(f.searchExp, 'g'), f.replaceStr);
-            }
-        }
-        return u;
-    },
-
-    /**
-     * Generates the full url for a module
-     * @method _url
-     * @param {string} path the path fragment.
-     * @param {String} name The name of the module
-     * @param {String} [base=self.base] The base url to use
-     * @return {string} the full url.
-     * @private
-     */
-    _url: function(path, name, base) {
-        return this._filter((base || this.base || '') + path, name);
-    },
-    /**
-    * Returns an Object hash of file arrays built from `loader.sorted` or from an arbitrary list of sorted modules.
-    * @method resolve
-    * @param {Boolean} [calc=false] Perform a loader.calculate() before anything else
-    * @param {Array} [s=loader.sorted] An override for the loader.sorted array
-    * @return {Object} Object hash (js and css) of two arrays of file lists
-    * @example This method can be used as an off-line dep calculator
-    *
-    *        var Y = YUI();
-    *        var loader = new Y.Loader({
-    *            filter: 'debug',
-    *            base: '../../',
-    *            root: 'build/',
-    *            combine: true,
-    *            require: ['node', 'dd', 'console']
-    *        });
-    *        var out = loader.resolve(true);
-    *
-    */
-    resolve: function(calc, s) {
-
-        var len, i, m, url, group, groupName, j, frag,
-            comboSource, comboSources, mods, comboBase,
-            base, urls, u = [], tmpBase, baseLen, resCombos = {},
-            self = this, comboSep, maxURLLength,
-            inserted = (self.ignoreRegistered) ? {} : self.inserted,
-            resolved = { js: [], jsMods: [], css: [], cssMods: [] },
-            type = self.loadType || 'js', addSingle;
-
-        if (self.skin.overrides || self.skin.defaultSkin !== DEFAULT_SKIN || self.ignoreRegistered) {
-            self._resetModules();
-        }
-
-        if (calc) {
-            self.calculate();
-        }
-        s = s || self.sorted;
-
-        addSingle = function(m) {
-
-            if (m) {
-                group = (m.group && self.groups[m.group]) || NOT_FOUND;
-
-                //Always assume it's async
-                if (group.async === false) {
-                    m.async = group.async;
-                }
-
-                url = (m.fullpath) ? self._filter(m.fullpath, s[i]) :
-                      self._url(m.path, s[i], group.base || m.base);
-
-                if (m.attributes || m.async === false) {
-                    url = {
-                        url: url,
-                        async: m.async
-                    };
-                    if (m.attributes) {
-                        url.attributes = m.attributes;
-                    }
-                }
-                resolved[m.type].push(url);
-                resolved[m.type + 'Mods'].push(m);
-            } else {
-            }
-
-        };
-
-        len = s.length;
-
-        // the default combo base
-        comboBase = self.comboBase;
-
-        url = comboBase;
-
-        comboSources = {};
-
-        for (i = 0; i < len; i++) {
-            comboSource = comboBase;
-            m = self.getModule(s[i]);
-            groupName = m && m.group;
-            group = self.groups[groupName];
-            if (groupName && group) {
-
-                if (!group.combine || m.fullpath) {
-                    //This is not a combo module, skip it and load it singly later.
-                    addSingle(m);
-                    continue;
-                }
-                m.combine = true;
-                if (group.comboBase) {
-                    comboSource = group.comboBase;
-                }
-
-                if ("root" in group && L.isValue(group.root)) {
-                    m.root = group.root;
-                }
-                m.comboSep = group.comboSep || self.comboSep;
-                m.maxURLLength = group.maxURLLength || self.maxURLLength;
-            } else {
-                if (!self.combine) {
-                    //This is not a combo module, skip it and load it singly later.
-                    addSingle(m);
-                    continue;
-                }
-            }
-
-            comboSources[comboSource] = comboSources[comboSource] || [];
-            comboSources[comboSource].push(m);
-        }
-
-        for (j in comboSources) {
-            if (comboSources.hasOwnProperty(j)) {
-                resCombos[j] = resCombos[j] || { js: [], jsMods: [], css: [], cssMods: [] };
-                url = j;
-                mods = comboSources[j];
-                len = mods.length;
-
-                if (len) {
-                    for (i = 0; i < len; i++) {
-                        if (inserted[mods[i]]) {
-                            continue;
-                        }
-                        m = mods[i];
-                        // Do not try to combine non-yui JS unless combo def
-                        // is found
-                        if (m && (m.combine || !m.ext)) {
-                            resCombos[j].comboSep = m.comboSep;
-                            resCombos[j].group = m.group;
-                            resCombos[j].maxURLLength = m.maxURLLength;
-                            frag = ((L.isValue(m.root)) ? m.root : self.root) + (m.path || m.fullpath);
-                            frag = self._filter(frag, m.name);
-                            resCombos[j][m.type].push(frag);
-                            resCombos[j][m.type + 'Mods'].push(m);
-                        } else {
-                            //Add them to the next process..
-                            if (mods[i]) {
-                                addSingle(mods[i]);
-                            }
-                        }
-
-                    }
-                }
-            }
-        }
-
-
-        for (j in resCombos) {
-            if (resCombos.hasOwnProperty(j)) {
-                base = j;
-                comboSep = resCombos[base].comboSep || self.comboSep;
-                maxURLLength = resCombos[base].maxURLLength || self.maxURLLength;
-                for (type in resCombos[base]) {
-                    if (type === JS || type === CSS) {
-                        urls = resCombos[base][type];
-                        mods = resCombos[base][type + 'Mods'];
-                        len = urls.length;
-                        tmpBase = base + urls.join(comboSep);
-                        baseLen = tmpBase.length;
-                        if (maxURLLength <= base.length) {
-                            maxURLLength = MAX_URL_LENGTH;
-                        }
-
-                        if (len) {
-                            if (baseLen > maxURLLength) {
-                                u = [];
-                                for (s = 0; s < len; s++) {
-                                    u.push(urls[s]);
-                                    tmpBase = base + u.join(comboSep);
-
-                                    if (tmpBase.length > maxURLLength) {
-                                        m = u.pop();
-                                        tmpBase = base + u.join(comboSep);
-                                        resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
-                                        u = [];
-                                        if (m) {
-                                            u.push(m);
-                                        }
-                                    }
-                                }
-                                if (u.length) {
-                                    tmpBase = base + u.join(comboSep);
-                                    resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
-                                }
-                            } else {
-                                resolved[type].push(self._filter(tmpBase, null, resCombos[base].group));
-                            }
-                        }
-                        resolved[type + 'Mods'] = resolved[type + 'Mods'].concat(mods);
-                    }
-                }
-            }
-        }
-
-        resCombos = null;
-
-        return resolved;
-    },
-    /**
-    Shortcut to calculate, resolve and load all modules.
-
-        var loader = new Y.Loader({
-            ignoreRegistered: true,
-            modules: {
-                mod: {
-                    path: 'mod.js'
-                }
-            },
-            requires: [ 'mod' ]
-        });
-        loader.load(function() {
-            console.log('All modules have loaded..');
-        });
-
-
-    @method load
-    @param {Callback} cb Executed after all load operations are complete
-    */
-    load: function(cb) {
-        if (!cb) {
-            return;
-        }
-        var self = this,
-            out = self.resolve(true);
-
-        self.data = out;
-
-        self.onEnd = function() {
-            cb.apply(self.context || self, arguments);
-        };
-
-        self.insert();
-    }
-};
-
-
-
-}, '3.12.0', {"requires": ["get", "features"]});
-YUI.add('loader-rollup', function (Y, NAME) {
-
-/**
- * Optional automatic rollup logic for reducing http connections
- * when not using a combo service.
- * @module loader
- * @submodule rollup
- */
-
-/**
- * Look for rollup packages to determine if all of the modules a
- * rollup supersedes are required.  If so, include the rollup to
- * help reduce the total number of connections required.  Called
- * by calculate().  This is an optional feature, and requires the
- * appropriate submodule to function.
- * @method _rollup
- * @for Loader
- * @private
- */
-Y.Loader.prototype._rollup = function() {
-    var i, j, m, s, r = this.required, roll,
-        info = this.moduleInfo, rolled, c, smod;
-
-    // find and cache rollup modules
-    if (this.dirty || !this.rollups) {
-        this.rollups = {};
-        for (i in info) {
-            if (info.hasOwnProperty(i)) {
-                m = this.getModule(i);
-                // if (m && m.rollup && m.supersedes) {
-                if (m && m.rollup) {
-                    this.rollups[i] = m;
-                }
-            }
-        }
-    }
-
-    // make as many passes as needed to pick up rollup rollups
-    for (;;) {
-        rolled = false;
-
-        // go through the rollup candidates
-        for (i in this.rollups) {
-            if (this.rollups.hasOwnProperty(i)) {
-                // there can be only one, unless forced
-                if (!r[i] && ((!this.loaded[i]) || this.forceMap[i])) {
-                    m = this.getModule(i);
-                    s = m.supersedes || [];
-                    roll = false;
-
-                    // @TODO remove continue
-                    if (!m.rollup) {
-                        continue;
-                    }
-
-                    c = 0;
-
-                    // check the threshold
-                    for (j = 0; j < s.length; j++) {
-                        smod = info[s[j]];
-
-                        // if the superseded module is loaded, we can't
-                        // load the rollup unless it has been forced.
-                        if (this.loaded[s[j]] && !this.forceMap[s[j]]) {
-                            roll = false;
-                            break;
-                        // increment the counter if this module is required.
-                        // if we are beyond the rollup threshold, we will
-                        // use the rollup module
-                        } else if (r[s[j]] && m.type === smod.type) {
-                            c++;
-                            roll = (c >= m.rollup);
-                            if (roll) {
-                                break;
-                            }
-                        }
-                    }
-
-                    if (roll) {
-                        // add the rollup
-                        r[i] = true;
-                        rolled = true;
-
-                        // expand the rollup's dependencies
-                        this.getRequires(m);
-                    }
-                }
-            }
-        }
-
-        // if we made it here w/o rolling up something, we are done
-        if (!rolled) {
-            break;
-        }
-    }
-};
-
-
-}, '3.12.0', {"requires": ["loader-base"]});
-YUI.add('loader-yui3', function (Y, NAME) {
-
-/* This file is auto-generated by (yogi.js loader --mix --yes) */
-
-/*jshint maxlen:900, eqeqeq: false */
-
-/**
- * YUI 3 module metadata
- * @module loader
- * @submodule loader-yui3
- */
-YUI.Env[Y.version].modules = YUI.Env[Y.version].modules || {};
-Y.mix(YUI.Env[Y.version].modules, {
-    "align-plugin": {
-        "requires": [
-            "node-screen",
-            "node-pluginhost"
-        ]
-    },
-    "anim": {
-        "use": [
-            "anim-base",
-            "anim-color",
-            "anim-curve",
-            "anim-easing",
-            "anim-node-plugin",
-            "anim-scroll",
-            "anim-xy"
-        ]
-    },
-    "anim-base": {
-        "requires": [
-            "base-base",
-            "node-style"
-        ]
-    },
-    "anim-color": {
-        "requires": [
-            "anim-base"
-        ]
-    },
-    "anim-curve": {
-        "requires": [
-            "anim-xy"
-        ]
-    },
-    "anim-easing": {
-        "requires": [
-            "anim-base"
-        ]
-    },
-    "anim-node-plugin": {
-        "requires": [
-            "node-pluginhost",
-            "anim-base"
-        ]
-    },
-    "anim-scroll": {
-        "requires": [
-            "anim-base"
-        ]
-    },
-    "anim-shape": {
-        "requires": [
-            "anim-base",
-            "anim-easing",
-            "anim-color",
-            "matrix"
-        ]
-    },
-    "anim-shape-transform": {
-        "use": [
-            "anim-shape"
-        ]
-    },
-    "anim-xy": {
-        "requires": [
-            "anim-base",
-            "node-screen"
-        ]
-    },
-    "app": {
-        "use": [
-            "app-base",
-            "app-content",
-            "app-transitions",
-            "lazy-model-list",
-            "model",
-            "model-list",
-            "model-sync-rest",
-            "router",
-            "view",
-            "view-node-map"
-        ]
-    },
-    "app-base": {
-        "requires": [
-            "classnamemanager",
-            "pjax-base",
-            "router",
-            "view"
-        ]
-    },
-    "app-content": {
-        "requires": [
-            "app-base",
-            "pjax-content"
-        ]
-    },
-    "app-transitions": {
-        "requires": [
-            "app-base"
-        ]
-    },
-    "app-transitions-css": {
-        "type": "css"
-    },
-    "app-transitions-native": {
-        "condition": {
-            "name": "app-transitions-native",
-            "test": function (Y) {
-    var doc  = Y.config.doc,
-        node = doc ? doc.documentElement : null;
-
-    if (node && node.style) {
-        return ('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
-    }
-
-    return false;
-},
-            "trigger": "app-transitions"
-        },
-        "requires": [
-            "app-transitions",
-            "app-transitions-css",
-            "parallel",
-            "transition"
-        ]
-    },
-    "array-extras": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "array-invoke": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "arraylist": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "arraylist-add": {
-        "requires": [
-            "arraylist"
-        ]
-    },
-    "arraylist-filter": {
-        "requires": [
-            "arraylist"
-        ]
-    },
-    "arraysort": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "async-queue": {
-        "requires": [
-            "event-custom"
-        ]
-    },
-    "attribute": {
-        "use": [
-            "attribute-base",
-            "attribute-complex"
-        ]
-    },
-    "attribute-base": {
-        "requires": [
-            "attribute-core",
-            "attribute-observable",
-            "attribute-extras"
-        ]
-    },
-    "attribute-complex": {
-        "requires": [
-            "attribute-base"
-        ]
-    },
-    "attribute-core": {
-        "requires": [
-            "oop"
-        ]
-    },
-    "attribute-events": {
-        "use": [
-            "attribute-observable"
-        ]
-    },
-    "attribute-extras": {
-        "requires": [
-            "oop"
-        ]
-    },
-    "attribute-observable": {
-        "requires": [
-            "event-custom"
-        ]
-    },
-    "autocomplete": {
-        "use": [
-            "autocomplete-base",
-            "autocomplete-sources",
-            "autocomplete-list",
-            "autocomplete-plugin"
-        ]
-    },
-    "autocomplete-base": {
-        "optional": [
-            "autocomplete-sources"
-        ],
-        "requires": [
-            "array-extras",
-            "base-build",
-            "escape",
-            "event-valuechange",
-            "node-base"
-        ]
-    },
-    "autocomplete-filters": {
-        "requires": [
-            "array-extras",
-            "text-wordbreak"
-        ]
-    },
-    "autocomplete-filters-accentfold": {
-        "requires": [
-            "array-extras",
-            "text-accentfold",
-            "text-wordbreak"
-        ]
-    },
-    "autocomplete-highlighters": {
-        "requires": [
-            "array-extras",
-            "highlight-base"
-        ]
-    },
-    "autocomplete-highlighters-accentfold": {
-        "requires": [
-            "array-extras",
-            "highlight-accentfold"
-        ]
-    },
-    "autocomplete-list": {
-        "after": [
-            "autocomplete-sources"
-        ],
-        "lang": [
-            "en",
-            "es",
-            "hu",
-            "it"
-        ],
-        "requires": [
-            "autocomplete-base",
-            "event-resize",
-            "node-screen",
-            "selector-css3",
-            "shim-plugin",
-            "widget",
-            "widget-position",
-            "widget-position-align"
-        ],
-        "skinnable": true
-    },
-    "autocomplete-list-keys": {
-        "condition": {
-            "name": "autocomplete-list-keys",
-            "test": function (Y) {
-    // Only add keyboard support to autocomplete-list if this doesn't appear to
-    // be an iOS or Android-based mobile device.
-    //
-    // There's currently no feasible way to actually detect whether a device has
-    // a hardware keyboard, so this sniff will have to do. It can easily be
-    // overridden by manually loading the autocomplete-list-keys module.
-    //
-    // Worth noting: even though iOS supports bluetooth keyboards, Mobile Safari
-    // doesn't fire the keyboard events used by AutoCompleteList, so there's
-    // no point loading the -keys module even when a bluetooth keyboard may be
-    // available.
-    return !(Y.UA.ios || Y.UA.android);
-},
-            "trigger": "autocomplete-list"
-        },
-        "requires": [
-            "autocomplete-list",
-            "base-build"
-        ]
-    },
-    "autocomplete-plugin": {
-        "requires": [
-            "autocomplete-list",
-            "node-pluginhost"
-        ]
-    },
-    "autocomplete-sources": {
-        "optional": [
-            "io-base",
-            "json-parse",
-            "jsonp",
-            "yql"
-        ],
-        "requires": [
-            "autocomplete-base"
-        ]
-    },
-    "axes": {
-        "use": [
-            "axis-numeric",
-            "axis-category",
-            "axis-time",
-            "axis-stacked"
-        ]
-    },
-    "axes-base": {
-        "use": [
-            "axis-numeric-base",
-            "axis-category-base",
-            "axis-time-base",
-            "axis-stacked-base"
-        ]
-    },
-    "axis": {
-        "requires": [
-            "dom",
-            "widget",
-            "widget-position",
-            "widget-stack",
-            "graphics",
-            "axis-base"
-        ]
-    },
-    "axis-base": {
-        "requires": [
-            "classnamemanager",
-            "datatype-number",
-            "datatype-date",
-            "base",
-            "event-custom"
-        ]
-    },
-    "axis-category": {
-        "requires": [
-            "axis",
-            "axis-category-base"
-        ]
-    },
-    "axis-category-base": {
-        "requires": [
-            "axis-base"
-        ]
-    },
-    "axis-numeric": {
-        "requires": [
-            "axis",
-            "axis-numeric-base"
-        ]
-    },
-    "axis-numeric-base": {
-        "requires": [
-            "axis-base"
-        ]
-    },
-    "axis-stacked": {
-        "requires": [
-            "axis-numeric",
-            "axis-stacked-base"
-        ]
-    },
-    "axis-stacked-base": {
-        "requires": [
-            "axis-numeric-base"
-        ]
-    },
-    "axis-time": {
-        "requires": [
-            "axis",
-            "axis-time-base"
-        ]
-    },
-    "axis-time-base": {
-        "requires": [
-            "axis-base"
-        ]
-    },
-    "base": {
-        "use": [
-            "base-base",
-            "base-pluginhost",
-            "base-build"
-        ]
-    },
-    "base-base": {
-        "requires": [
-            "attribute-base",
-            "base-core",
-            "base-observable"
-        ]
-    },
-    "base-build": {
-        "requires": [
-            "base-base"
-        ]
-    },
-    "base-core": {
-        "requires": [
-            "attribute-core"
-        ]
-    },
-    "base-observable": {
-        "requires": [
-            "attribute-observable"
-        ]
-    },
-    "base-pluginhost": {
-        "requires": [
-            "base-base",
-            "pluginhost"
-        ]
-    },
-    "button": {
-        "requires": [
-            "button-core",
-            "cssbutton",
-            "widget"
-        ]
-    },
-    "button-core": {
-        "requires": [
-            "attribute-core",
-            "classnamemanager",
-            "node-base"
-        ]
-    },
-    "button-group": {
-        "requires": [
-            "button-plugin",
-            "cssbutton",
-            "widget"
-        ]
-    },
-    "button-plugin": {
-        "requires": [
-            "button-core",
-            "cssbutton",
-            "node-pluginhost"
-        ]
-    },
-    "cache": {
-        "use": [
-            "cache-base",
-            "cache-offline",
-            "cache-plugin"
-        ]
-    },
-    "cache-base": {
-        "requires": [
-            "base"
-        ]
-    },
-    "cache-offline": {
-        "requires": [
-            "cache-base",
-            "json"
-        ]
-    },
-    "cache-plugin": {
-        "requires": [
-            "plugin",
-            "cache-base"
-        ]
-    },
-    "calendar": {
-        "requires": [
-            "calendar-base",
-            "calendarnavigator"
-        ],
-        "skinnable": true
-    },
-    "calendar-base": {
-        "lang": [
-            "de",
-            "en",
-            "es",
-            "es-AR",
-            "fr",
-            "hu",
-            "it",
-            "ja",
-            "nb-NO",
-            "nl",
-            "pt-BR",
-            "ru",
-            "zh-Hans",
-            "zh-Hans-CN",
-            "zh-Hant",
-            "zh-Hant-HK",
-            "zh-HANT-TW"
-        ],
-        "requires": [
-            "widget",
-            "datatype-date",
-            "datatype-date-math",
-            "cssgrids"
-        ],
-        "skinnable": true
-    },
-    "calendarnavigator": {
-        "requires": [
-            "plugin",
-            "classnamemanager",
-            "datatype-date",
-            "node"
-        ],
-        "skinnable": true
-    },
-    "charts": {
-        "use": [
-            "charts-base"
-        ]
-    },
-    "charts-base": {
-        "requires": [
-            "dom",
-            "event-mouseenter",
-            "event-touch",
-            "graphics-group",
-            "axes",
-            "series-pie",
-            "series-line",
-            "series-marker",
-            "series-area",
-            "series-spline",
-            "series-column",
-            "series-bar",
-            "series-areaspline",
-            "series-combo",
-            "series-combospline",
-            "series-line-stacked",
-            "series-marker-stacked",
-            "series-area-stacked",
-            "series-spline-stacked",
-            "series-column-stacked",
-            "series-bar-stacked",
-            "series-areaspline-stacked",
-            "series-combo-stacked",
-            "series-combospline-stacked"
-        ]
-    },
-    "charts-legend": {
-        "requires": [
-            "charts-base"
-        ]
-    },
-    "classnamemanager": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "clickable-rail": {
-        "requires": [
-            "slider-base"
-        ]
-    },
-    "collection": {
-        "use": [
-            "array-extras",
-            "arraylist",
-            "arraylist-add",
-            "arraylist-filter",
-            "array-invoke"
-        ]
-    },
-    "color": {
-        "use": [
-            "color-base",
-            "color-hsl",
-            "color-harmony"
-        ]
-    },
-    "color-base": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "color-harmony": {
-        "requires": [
-            "color-hsl"
-        ]
-    },
-    "color-hsl": {
-        "requires": [
-            "color-base"
-        ]
-    },
-    "color-hsv": {
-        "requires": [
-            "color-base"
-        ]
-    },
-    "console": {
-        "lang": [
-            "en",
-            "es",
-            "hu",
-            "it",
-            "ja"
-        ],
-        "requires": [
-            "yui-log",
-            "widget"
-        ],
-        "skinnable": true
-    },
-    "console-filters": {
-        "requires": [
-            "plugin",
-            "console"
-        ],
-        "skinnable": true
-    },
-    "controller": {
-        "use": [
-            "router"
-        ]
-    },
-    "cookie": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "createlink-base": {
-        "requires": [
-            "editor-base"
-        ]
-    },
-    "cssbase": {
-        "after": [
-            "cssreset",
-            "cssfonts",
-            "cssgrids",
-            "cssreset-context",
-            "cssfonts-context",
-            "cssgrids-context"
-        ],
-        "type": "css"
-    },
-    "cssbase-context": {
-        "after": [
-            "cssreset",
-            "cssfonts",
-            "cssgrids",
-            "cssreset-context",
-            "cssfonts-context",
-            "cssgrids-context"
-        ],
-        "type": "css"
-    },
-    "cssbutton": {
-        "type": "css"
-    },
-    "cssfonts": {
-        "type": "css"
-    },
-    "cssfonts-context": {
-        "type": "css"
-    },
-    "cssgrids": {
-        "optional": [
-            "cssnormalize"
-        ],
-        "type": "css"
-    },
-    "cssgrids-base": {
-        "optional": [
-            "cssnormalize"
-        ],
-        "type": "css"
-    },
-    "cssgrids-responsive": {
-        "optional": [
-            "cssnormalize"
-        ],
-        "requires": [
-            "cssgrids",
-            "cssgrids-responsive-base"
-        ],
-        "type": "css"
-    },
-    "cssgrids-units": {
-        "optional": [
-            "cssnormalize"
-        ],
-        "requires": [
-            "cssgrids-base"
-        ],
-        "type": "css"
-    },
-    "cssnormalize": {
-        "type": "css"
-    },
-    "cssnormalize-context": {
-        "type": "css"
-    },
-    "cssreset": {
-        "type": "css"
-    },
-    "cssreset-context": {
-        "type": "css"
-    },
-    "dataschema": {
-        "use": [
-            "dataschema-base",
-            "dataschema-json",
-            "dataschema-xml",
-            "dataschema-array",
-            "dataschema-text"
-        ]
-    },
-    "dataschema-array": {
-        "requires": [
-            "dataschema-base"
-        ]
-    },
-    "dataschema-base": {
-        "requires": [
-            "base"
-        ]
-    },
-    "dataschema-json": {
-        "requires": [
-            "dataschema-base",
-            "json"
-        ]
-    },
-    "dataschema-text": {
-        "requires": [
-            "dataschema-base"
-        ]
-    },
-    "dataschema-xml": {
-        "requires": [
-            "dataschema-base"
-        ]
-    },
-    "datasource": {
-        "use": [
-            "datasource-local",
-            "datasource-io",
-            "datasource-get",
-            "datasource-function",
-            "datasource-cache",
-            "datasource-jsonschema",
-            "datasource-xmlschema",
-            "datasource-arrayschema",
-            "datasource-textschema",
-            "datasource-polling"
-        ]
-    },
-    "datasource-arrayschema": {
-        "requires": [
-            "datasource-local",
-            "plugin",
-            "dataschema-array"
-        ]
-    },
-    "datasource-cache": {
-        "requires": [
-            "datasource-local",
-            "plugin",
-            "cache-base"
-        ]
-    },
-    "datasource-function": {
-        "requires": [
-            "datasource-local"
-        ]
-    },
-    "datasource-get": {
-        "requires": [
-            "datasource-local",
-            "get"
-        ]
-    },
-    "datasource-io": {
-        "requires": [
-            "datasource-local",
-            "io-base"
-        ]
-    },
-    "datasource-jsonschema": {
-        "requires": [
-            "datasource-local",
-            "plugin",
-            "dataschema-json"
-        ]
-    },
-    "datasource-local": {
-        "requires": [
-            "base"
-        ]
-    },
-    "datasource-polling": {
-        "requires": [
-            "datasource-local"
-        ]
-    },
-    "datasource-textschema": {
-        "requires": [
-            "datasource-local",
-            "plugin",
-            "dataschema-text"
-        ]
-    },
-    "datasource-xmlschema": {
-        "requires": [
-            "datasource-local",
-            "plugin",
-            "datatype-xml",
-            "dataschema-xml"
-        ]
-    },
-    "datatable": {
-        "use": [
-            "datatable-core",
-            "datatable-table",
-            "datatable-head",
-            "datatable-body",
-            "datatable-base",
-            "datatable-column-widths",
-            "datatable-message",
-            "datatable-mutable",
-            "datatable-sort",
-            "datatable-datasource"
-        ]
-    },
-    "datatable-base": {
-        "requires": [
-            "datatable-core",
-            "datatable-table",
-            "datatable-head",
-            "datatable-body",
-            "base-build",
-            "widget"
-        ],
-        "skinnable": true
-    },
-    "datatable-body": {
-        "requires": [
-            "datatable-core",
-            "view",
-            "classnamemanager"
-        ]
-    },
-    "datatable-column-widths": {
-        "requires": [
-            "datatable-base"
-        ]
-    },
-    "datatable-core": {
-        "requires": [
-            "escape",
-            "model-list",
-            "node-event-delegate"
-        ]
-    },
-    "datatable-datasource": {
-        "requires": [
-            "datatable-base",
-            "plugin",
-            "datasource-local"
-        ]
-    },
-    "datatable-foot": {
-        "requires": [
-            "datatable-core",
-            "view"
-        ]
-    },
-    "datatable-formatters": {
-        "requires": [
-            "datatable-body",
-            "datatype-number-format",
-            "datatype-date-format",
-            "escape"
-        ]
-    },
-    "datatable-head": {
-        "requires": [
-            "datatable-core",
-            "view",
-            "classnamemanager"
-        ]
-    },
-    "datatable-message": {
-        "lang": [
-            "en",
-            "fr",
-            "es",
-            "hu",
-            "it"
-        ],
-        "requires": [
-            "datatable-base"
-        ],
-        "skinnable": true
-    },
-    "datatable-mutable": {
-        "requires": [
-            "datatable-base"
-        ]
-    },
-    "datatable-paginator": {
-        "lang": [
-            "en"
-        ],
-        "requires": [
-            "model",
-            "view",
-            "paginator-core",
-            "datatable-foot",
-            "datatable-paginator-templates"
-        ],
-        "skinnable": true
-    },
-    "datatable-paginator-templates": {
-        "requires": [
-            "template"
-        ]
-    },
-    "datatable-scroll": {
-        "requires": [
-            "datatable-base",
-            "datatable-column-widths",
-            "dom-screen"
-        ],
-        "skinnable": true
-    },
-    "datatable-sort": {
-        "lang": [
-            "en",
-            "fr",
-            "es",
-            "hu"
-        ],
-        "requires": [
-            "datatable-base"
-        ],
-        "skinnable": true
-    },
-    "datatable-table": {
-        "requires": [
-            "datatable-core",
-            "datatable-head",
-            "datatable-body",
-            "view",
-            "classnamemanager"
-        ]
-    },
-    "datatype": {
-        "use": [
-            "datatype-date",
-            "datatype-number",
-            "datatype-xml"
-        ]
-    },
-    "datatype-date": {
-        "use": [
-            "datatype-date-parse",
-            "datatype-date-format",
-            "datatype-date-math"
-        ]
-    },
-    "datatype-date-format": {
-        "lang": [
-            "ar",
-            "ar-JO",
-            "ca",
-            "ca-ES",
-            "da",
-            "da-DK",
-            "de",
-            "de-AT",
-            "de-DE",
-            "el",
-            "el-GR",
-            "en",
-            "en-AU",
-            "en-CA",
-            "en-GB",
-            "en-IE",
-            "en-IN",
-            "en-JO",
-            "en-MY",
-            "en-NZ",
-            "en-PH",
-            "en-SG",
-            "en-US",
-            "es",
-            "es-AR",
-            "es-BO",
-            "es-CL",
-            "es-CO",
-            "es-EC",
-            "es-ES",
-            "es-MX",
-            "es-PE",
-            "es-PY",
-            "es-US",
-            "es-UY",
-            "es-VE",
-            "fi",
-            "fi-FI",
-            "fr",
-            "fr-BE",
-            "fr-CA",
-            "fr-FR",
-            "hi",
-            "hi-IN",
-            "hu",
-            "id",
-            "id-ID",
-            "it",
-            "it-IT",
-            "ja",
-            "ja-JP",
-            "ko",
-            "ko-KR",
-            "ms",
-            "ms-MY",
-            "nb",
-            "nb-NO",
-            "nl",
-            "nl-BE",
-            "nl-NL",
-            "pl",
-            "pl-PL",
-            "pt",
-            "pt-BR",
-            "ro",
-            "ro-RO",
-            "ru",
-            "ru-RU",
-            "sv",
-            "sv-SE",
-            "th",
-            "th-TH",
-            "tr",
-            "tr-TR",
-            "vi",
-            "vi-VN",
-            "zh-Hans",
-            "zh-Hans-CN",
-            "zh-Hant",
-            "zh-Hant-HK",
-            "zh-Hant-TW"
-        ]
-    },
-    "datatype-date-math": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "datatype-date-parse": {},
-    "datatype-number": {
-        "use": [
-            "datatype-number-parse",
-            "datatype-number-format"
-        ]
-    },
-    "datatype-number-format": {},
-    "datatype-number-parse": {},
-    "datatype-xml": {
-        "use": [
-            "datatype-xml-parse",
-            "datatype-xml-format"
-        ]
-    },
-    "datatype-xml-format": {},
-    "datatype-xml-parse": {},
-    "dd": {
-        "use": [
-            "dd-ddm-base",
-            "dd-ddm",
-            "dd-ddm-drop",
-            "dd-drag",
-            "dd-proxy",
-            "dd-constrain",
-            "dd-drop",
-            "dd-scroll",
-            "dd-delegate"
-        ]
-    },
-    "dd-constrain": {
-        "requires": [
-            "dd-drag"
-        ]
-    },
-    "dd-ddm": {
-        "requires": [
-            "dd-ddm-base",
-            "event-resize"
-        ]
-    },
-    "dd-ddm-base": {
-        "requires": [
-            "node",
-            "base",
-            "yui-throttle",
-            "classnamemanager"
-        ]
-    },
-    "dd-ddm-drop": {
-        "requires": [
-            "dd-ddm"
-        ]
-    },
-    "dd-delegate": {
-        "requires": [
-            "dd-drag",
-            "dd-drop-plugin",
-            "event-mouseenter"
-        ]
-    },
-    "dd-drag": {
-        "requires": [
-            "dd-ddm-base"
-        ]
-    },
-    "dd-drop": {
-        "requires": [
-            "dd-drag",
-            "dd-ddm-drop"
-        ]
-    },
-    "dd-drop-plugin": {
-        "requires": [
-            "dd-drop"
-        ]
-    },
-    "dd-gestures": {
-        "condition": {
-            "name": "dd-gestures",
-            "trigger": "dd-drag",
-            "ua": "touchEnabled"
-        },
-        "requires": [
-            "dd-drag",
-            "event-synthetic",
-            "event-gestures"
-        ]
-    },
-    "dd-plugin": {
-        "optional": [
-            "dd-constrain",
-            "dd-proxy"
-        ],
-        "requires": [
-            "dd-drag"
-        ]
-    },
-    "dd-proxy": {
-        "requires": [
-            "dd-drag"
-        ]
-    },
-    "dd-scroll": {
-        "requires": [
-            "dd-drag"
-        ]
-    },
-    "dial": {
-        "lang": [
-            "en",
-            "es",
-            "hu"
-        ],
-        "requires": [
-            "widget",
-            "dd-drag",
-            "event-mouseenter",
-            "event-move",
-            "event-key",
-            "transition",
-            "intl"
-        ],
-        "skinnable": true
-    },
-    "dom": {
-        "use": [
-            "dom-base",
-            "dom-screen",
-            "dom-style",
-            "selector-native",
-            "selector"
-        ]
-    },
-    "dom-base": {
-        "requires": [
-            "dom-core"
-        ]
-    },
-    "dom-core": {
-        "requires": [
-            "oop",
-            "features"
-        ]
-    },
-    "dom-deprecated": {
-        "requires": [
-            "dom-base"
-        ]
-    },
-    "dom-screen": {
-        "requires": [
-            "dom-base",
-            "dom-style"
-        ]
-    },
-    "dom-style": {
-        "requires": [
-            "dom-base",
-            "color-base"
-        ]
-    },
-    "dom-style-ie": {
-        "condition": {
-            "name": "dom-style-ie",
-            "test": function (Y) {
-
-    var testFeature = Y.Features.test,
-        addFeature = Y.Features.add,
-        WINDOW = Y.config.win,
-        DOCUMENT = Y.config.doc,
-        DOCUMENT_ELEMENT = 'documentElement',
-        ret = false;
-
-    addFeature('style', 'computedStyle', {
-        test: function() {
-            return WINDOW && 'getComputedStyle' in WINDOW;
-        }
-    });
-
-    addFeature('style', 'opacity', {
-        test: function() {
-            return DOCUMENT && 'opacity' in DOCUMENT[DOCUMENT_ELEMENT].style;
-        }
-    });
-
-    ret =  (!testFeature('style', 'opacity') &&
-            !testFeature('style', 'computedStyle'));
-
-    return ret;
-},
-            "trigger": "dom-style"
-        },
-        "requires": [
-            "dom-style"
-        ]
-    },
-    "dump": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "editor": {
-        "use": [
-            "frame",
-            "editor-selection",
-            "exec-command",
-            "editor-base",
-            "editor-para",
-            "editor-br",
-            "editor-bidi",
-            "editor-tab",
-            "createlink-base"
-        ]
-    },
-    "editor-base": {
-        "requires": [
-            "base",
-            "frame",
-            "node",
-            "exec-command",
-            "editor-selection"
-        ]
-    },
-    "editor-bidi": {
-        "requires": [
-            "editor-base"
-        ]
-    },
-    "editor-br": {
-        "requires": [
-            "editor-base"
-        ]
-    },
-    "editor-lists": {
-        "requires": [
-            "editor-base"
-        ]
-    },
-    "editor-para": {
-        "requires": [
-            "editor-para-base"
-        ]
-    },
-    "editor-para-base": {
-        "requires": [
-            "editor-base"
-        ]
-    },
-    "editor-para-ie": {
-        "condition": {
-            "name": "editor-para-ie",
-            "trigger": "editor-para",
-            "ua": "ie",
-            "when": "instead"
-        },
-        "requires": [
-            "editor-para-base"
-        ]
-    },
-    "editor-selection": {
-        "requires": [
-            "node"
-        ]
-    },
-    "editor-tab": {
-        "requires": [
-            "editor-base"
-        ]
-    },
-    "escape": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "event": {
-        "after": [
-            "node-base"
-        ],
-        "use": [
-            "event-base",
-            "event-delegate",
-            "event-synthetic",
-            "event-mousewheel",
-            "event-mouseenter",
-            "event-key",
-            "event-focus",
-            "event-resize",
-            "event-hover",
-            "event-outside",
-            "event-touch",
-            "event-move",
-            "event-flick",
-            "event-valuechange",
-            "event-tap"
-        ]
-    },
-    "event-base": {
-        "after": [
-            "node-base"
-        ],
-        "requires": [
-            "event-custom-base"
-        ]
-    },
-    "event-base-ie": {
-        "after": [
-            "event-base"
-        ],
-        "condition": {
-            "name": "event-base-ie",
-            "test": function(Y) {
-    var imp = Y.config.doc && Y.config.doc.implementation;
-    return (imp && (!imp.hasFeature('Events', '2.0')));
-},
-            "trigger": "node-base"
-        },
-        "requires": [
-            "node-base"
-        ]
-    },
-    "event-contextmenu": {
-        "requires": [
-            "event-synthetic",
-            "dom-screen"
-        ]
-    },
-    "event-custom": {
-        "use": [
-            "event-custom-base",
-            "event-custom-complex"
-        ]
-    },
-    "event-custom-base": {
-        "requires": [
-            "oop"
-        ]
-    },
-    "event-custom-complex": {
-        "requires": [
-            "event-custom-base"
-        ]
-    },
-    "event-delegate": {
-        "requires": [
-            "node-base"
-        ]
-    },
-    "event-flick": {
-        "requires": [
-            "node-base",
-            "event-touch",
-            "event-synthetic"
-        ]
-    },
-    "event-focus": {
-        "requires": [
-            "event-synthetic"
-        ]
-    },
-    "event-gestures": {
-        "use": [
-            "event-flick",
-            "event-move"
-        ]
-    },
-    "event-hover": {
-        "requires": [
-            "event-mouseenter"
-        ]
-    },
-    "event-key": {
-        "requires": [
-            "event-synthetic"
-        ]
-    },
-    "event-mouseenter": {
-        "requires": [
-            "event-synthetic"
-        ]
-    },
-    "event-mousewheel": {
-        "requires": [
-            "node-base"
-        ]
-    },
-    "event-move": {
-        "requires": [
-            "node-base",
-            "event-touch",
-            "event-synthetic"
-        ]
-    },
-    "event-outside": {
-        "requires": [
-            "event-synthetic"
-        ]
-    },
-    "event-resize": {
-        "requires": [
-            "node-base",
-            "event-synthetic"
-        ]
-    },
-    "event-simulate": {
-        "requires": [
-            "event-base"
-        ]
-    },
-    "event-synthetic": {
-        "requires": [
-            "node-base",
-            "event-custom-complex"
-        ]
-    },
-    "event-tap": {
-        "requires": [
-            "node-base",
-            "event-base",
-            "event-touch",
-            "event-synthetic"
-        ]
-    },
-    "event-touch": {
-        "requires": [
-            "node-base"
-        ]
-    },
-    "event-valuechange": {
-        "requires": [
-            "event-focus",
-            "event-synthetic"
-        ]
-    },
-    "exec-command": {
-        "requires": [
-            "frame"
-        ]
-    },
-    "features": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "file": {
-        "requires": [
-            "file-flash",
-            "file-html5"
-        ]
-    },
-    "file-flash": {
-        "requires": [
-            "base"
-        ]
-    },
-    "file-html5": {
-        "requires": [
-            "base"
-        ]
-    },
-    "frame": {
-        "requires": [
-            "base",
-            "node",
-            "selector-css3",
-            "yui-throttle"
-        ]
-    },
-    "gesture-simulate": {
-        "requires": [
-            "async-queue",
-            "event-simulate",
-            "node-screen"
-        ]
-    },
-    "get": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "graphics": {
-        "requires": [
-            "node",
-            "event-custom",
-            "pluginhost",
-            "matrix",
-            "classnamemanager"
-        ]
-    },
-    "graphics-canvas": {
-        "condition": {
-            "name": "graphics-canvas",
-            "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-        useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
-        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
-    return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
-},
-            "trigger": "graphics"
-        },
-        "requires": [
-            "graphics"
-        ]
-    },
-    "graphics-canvas-default": {
-        "condition": {
-            "name": "graphics-canvas-default",
-            "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-        useCanvas = Y.config.defaultGraphicEngine && Y.config.defaultGraphicEngine == "canvas",
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
-        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
-    return (!svg || useCanvas) && (canvas && canvas.getContext && canvas.getContext("2d"));
-},
-            "trigger": "graphics"
-        }
-    },
-    "graphics-group": {
-        "requires": [
-            "graphics"
-        ]
-    },
-    "graphics-svg": {
-        "condition": {
-            "name": "graphics-svg",
-            "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-        useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
-        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
-    
-    return svg && (useSVG || !canvas);
-},
-            "trigger": "graphics"
-        },
-        "requires": [
-            "graphics"
-        ]
-    },
-    "graphics-svg-default": {
-        "condition": {
-            "name": "graphics-svg-default",
-            "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-        useSVG = !Y.config.defaultGraphicEngine || Y.config.defaultGraphicEngine != "canvas",
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas"),
-        svg = (DOCUMENT && DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"));
-    
-    return svg && (useSVG || !canvas);
-},
-            "trigger": "graphics"
-        }
-    },
-    "graphics-vml": {
-        "condition": {
-            "name": "graphics-vml",
-            "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
-    return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
-},
-            "trigger": "graphics"
-        },
-        "requires": [
-            "graphics"
-        ]
-    },
-    "graphics-vml-default": {
-        "condition": {
-            "name": "graphics-vml-default",
-            "test": function(Y) {
-    var DOCUMENT = Y.config.doc,
-		canvas = DOCUMENT && DOCUMENT.createElement("canvas");
-    return (DOCUMENT && !DOCUMENT.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") && (!canvas || !canvas.getContext || !canvas.getContext("2d")));
-},
-            "trigger": "graphics"
-        }
-    },
-    "handlebars": {
-        "use": [
-            "handlebars-compiler"
-        ]
-    },
-    "handlebars-base": {
-        "requires": []
-    },
-    "handlebars-compiler": {
-        "requires": [
-            "handlebars-base"
-        ]
-    },
-    "highlight": {
-        "use": [
-            "highlight-base",
-            "highlight-accentfold"
-        ]
-    },
-    "highlight-accentfold": {
-        "requires": [
-            "highlight-base",
-            "text-accentfold"
-        ]
-    },
-    "highlight-base": {
-        "requires": [
-            "array-extras",
-            "classnamemanager",
-            "escape",
-            "text-wordbreak"
-        ]
-    },
-    "history": {
-        "use": [
-            "history-base",
-            "history-hash",
-            "history-hash-ie",
-            "history-html5"
-        ]
-    },
-    "history-base": {
-        "requires": [
-            "event-custom-complex"
-        ]
-    },
-    "history-hash": {
-        "after": [
-            "history-html5"
-        ],
-        "requires": [
-            "event-synthetic",
-            "history-base",
-            "yui-later"
-        ]
-    },
-    "history-hash-ie": {
-        "condition": {
-            "name": "history-hash-ie",
-            "test": function (Y) {
-    var docMode = Y.config.doc && Y.config.doc.documentMode;
-
-    return Y.UA.ie && (!('onhashchange' in Y.config.win) ||
-            !docMode || docMode < 8);
-},
-            "trigger": "history-hash"
-        },
-        "requires": [
-            "history-hash",
-            "node-base"
-        ]
-    },
-    "history-html5": {
-        "optional": [
-            "json"
-        ],
-        "requires": [
-            "event-base",
-            "history-base",
-            "node-base"
-        ]
-    },
-    "imageloader": {
-        "requires": [
-            "base-base",
-            "node-style",
-            "node-screen"
-        ]
-    },
-    "intl": {
-        "requires": [
-            "intl-base",
-            "event-custom"
-        ]
-    },
-    "intl-base": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "io": {
-        "use": [
-            "io-base",
-            "io-xdr",
-            "io-form",
-            "io-upload-iframe",
-            "io-queue"
-        ]
-    },
-    "io-base": {
-        "requires": [
-            "event-custom-base",
-            "querystring-stringify-simple"
-        ]
-    },
-    "io-form": {
-        "requires": [
-            "io-base",
-            "node-base"
-        ]
-    },
-    "io-nodejs": {
-        "condition": {
-            "name": "io-nodejs",
-            "trigger": "io-base",
-            "ua": "nodejs"
-        },
-        "requires": [
-            "io-base"
-        ]
-    },
-    "io-queue": {
-        "requires": [
-            "io-base",
-            "queue-promote"
-        ]
-    },
-    "io-upload-iframe": {
-        "requires": [
-            "io-base",
-            "node-base"
-        ]
-    },
-    "io-xdr": {
-        "requires": [
-            "io-base",
-            "datatype-xml-parse"
-        ]
-    },
-    "json": {
-        "use": [
-            "json-parse",
-            "json-stringify"
-        ]
-    },
-    "json-parse": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "json-parse-shim": {
-        "condition": {
-            "name": "json-parse-shim",
-            "test": function (Y) {
-    var _JSON = Y.config.global.JSON,
-        Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
-        nativeSupport = Y.config.useNativeJSONParse !== false && !!Native;
-
-    function workingNative( k, v ) {
-        return k === "ok" ? true : v;
-    }
-    
-    // Double check basic functionality.  This is mainly to catch early broken
-    // implementations of the JSON API in Firefox 3.1 beta1 and beta2
-    if ( nativeSupport ) {
-        try {
-            nativeSupport = ( Native.parse( '{"ok":false}', workingNative ) ).ok;
-        }
-        catch ( e ) {
-            nativeSupport = false;
-        }
-    }
-
-    return !nativeSupport;
-},
-            "trigger": "json-parse"
-        },
-        "requires": [
-            "json-parse"
-        ]
-    },
-    "json-stringify": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "json-stringify-shim": {
-        "condition": {
-            "name": "json-stringify-shim",
-            "test": function (Y) {
-    var _JSON = Y.config.global.JSON,
-        Native = Object.prototype.toString.call(_JSON) === '[object JSON]' && _JSON,
-        nativeSupport = Y.config.useNativeJSONStringify !== false && !!Native;
-
-    // Double check basic native functionality.  This is primarily to catch broken
-    // early JSON API implementations in Firefox 3.1 beta1 and beta2.
-    if ( nativeSupport ) {
-        try {
-            nativeSupport = ( '0' === Native.stringify(0) );
-        } catch ( e ) {
-            nativeSupport = false;
-        }
-    }
-
-
-    return !nativeSupport;
-},
-            "trigger": "json-stringify"
-        },
-        "requires": [
-            "json-stringify"
-        ]
-    },
-    "jsonp": {
-        "requires": [
-            "get",
-            "oop"
-        ]
-    },
-    "jsonp-url": {
-        "requires": [
-            "jsonp"
-        ]
-    },
-    "lazy-model-list": {
-        "requires": [
-            "model-list"
-        ]
-    },
-    "loader": {
-        "use": [
-            "loader-base",
-            "loader-rollup",
-            "loader-yui3"
-        ]
-    },
-    "loader-base": {
-        "requires": [
-            "get",
-            "features"
-        ]
-    },
-    "loader-rollup": {
-        "requires": [
-            "loader-base"
-        ]
-    },
-    "loader-yui3": {
-        "requires": [
-            "loader-base"
-        ]
-    },
-    "matrix": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "model": {
-        "requires": [
-            "base-build",
-            "escape",
-            "json-parse"
-        ]
-    },
-    "model-list": {
-        "requires": [
-            "array-extras",
-            "array-invoke",
-            "arraylist",
-            "base-build",
-            "escape",
-            "json-parse",
-            "model"
-        ]
-    },
-    "model-sync-rest": {
-        "requires": [
-            "model",
-            "io-base",
-            "json-stringify"
-        ]
-    },
-    "node": {
-        "use": [
-            "node-base",
-            "node-event-delegate",
-            "node-pluginhost",
-            "node-screen",
-            "node-style"
-        ]
-    },
-    "node-base": {
-        "requires": [
-            "event-base",
-            "node-core",
-            "dom-base",
-            "dom-style"
-        ]
-    },
-    "node-core": {
-        "requires": [
-            "dom-core",
-            "selector"
-        ]
-    },
-    "node-deprecated": {
-        "requires": [
-            "node-base"
-        ]
-    },
-    "node-event-delegate": {
-        "requires": [
-            "node-base",
-            "event-delegate"
-        ]
-    },
-    "node-event-html5": {
-        "requires": [
-            "node-base"
-        ]
-    },
-    "node-event-simulate": {
-        "requires": [
-            "node-base",
-            "event-simulate",
-            "gesture-simulate"
-        ]
-    },
-    "node-flick": {
-        "requires": [
-            "classnamemanager",
-            "transition",
-            "event-flick",
-            "plugin"
-        ],
-        "skinnable": true
-    },
-    "node-focusmanager": {
-        "requires": [
-            "attribute",
-            "node",
-            "plugin",
-            "node-event-simulate",
-            "event-key",
-            "event-focus"
-        ]
-    },
-    "node-load": {
-        "requires": [
-            "node-base",
-            "io-base"
-        ]
-    },
-    "node-menunav": {
-        "requires": [
-            "node",
-            "classnamemanager",
-            "plugin",
-            "node-focusmanager"
-        ],
-        "skinnable": true
-    },
-    "node-pluginhost": {
-        "requires": [
-            "node-base",
-            "pluginhost"
-        ]
-    },
-    "node-screen": {
-        "requires": [
-            "dom-screen",
-            "node-base"
-        ]
-    },
-    "node-scroll-info": {
-        "requires": [
-            "array-extras",
-            "base-build",
-            "event-resize",
-            "node-pluginhost",
-            "plugin",
-            "selector"
-        ]
-    },
-    "node-style": {
-        "requires": [
-            "dom-style",
-            "node-base"
-        ]
-    },
-    "oop": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "overlay": {
-        "requires": [
-            "widget",
-            "widget-stdmod",
-            "widget-position",
-            "widget-position-align",
-            "widget-stack",
-            "widget-position-constrain"
-        ],
-        "skinnable": true
-    },
-    "paginator": {
-        "requires": [
-            "paginator-core"
-        ]
-    },
-    "paginator-core": {
-        "requires": [
-            "base"
-        ]
-    },
-    "paginator-url": {
-        "requires": [
-            "paginator"
-        ]
-    },
-    "panel": {
-        "requires": [
-            "widget",
-            "widget-autohide",
-            "widget-buttons",
-            "widget-modality",
-            "widget-position",
-            "widget-position-align",
-            "widget-position-constrain",
-            "widget-stack",
-            "widget-stdmod"
-        ],
-        "skinnable": true
-    },
-    "parallel": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "pjax": {
-        "requires": [
-            "pjax-base",
-            "pjax-content"
-        ]
-    },
-    "pjax-base": {
-        "requires": [
-            "classnamemanager",
-            "node-event-delegate",
-            "router"
-        ]
-    },
-    "pjax-content": {
-        "requires": [
-            "io-base",
-            "node-base",
-            "router"
-        ]
-    },
-    "pjax-plugin": {
-        "requires": [
-            "node-pluginhost",
-            "pjax",
-            "plugin"
-        ]
-    },
-    "plugin": {
-        "requires": [
-            "base-base"
-        ]
-    },
-    "pluginhost": {
-        "use": [
-            "pluginhost-base",
-            "pluginhost-config"
-        ]
-    },
-    "pluginhost-base": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "pluginhost-config": {
-        "requires": [
-            "pluginhost-base"
-        ]
-    },
-    "promise": {
-        "requires": [
-            "timers"
-        ]
-    },
-    "querystring": {
-        "use": [
-            "querystring-parse",
-            "querystring-stringify"
-        ]
-    },
-    "querystring-parse": {
-        "requires": [
-            "yui-base",
-            "array-extras"
-        ]
-    },
-    "querystring-parse-simple": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "querystring-stringify": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "querystring-stringify-simple": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "queue-promote": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "range-slider": {
-        "requires": [
-            "slider-base",
-            "slider-value-range",
-            "clickable-rail"
-        ]
-    },
-    "recordset": {
-        "use": [
-            "recordset-base",
-            "recordset-sort",
-            "recordset-filter",
-            "recordset-indexer"
-        ]
-    },
-    "recordset-base": {
-        "requires": [
-            "base",
-            "arraylist"
-        ]
-    },
-    "recordset-filter": {
-        "requires": [
-            "recordset-base",
-            "array-extras",
-            "plugin"
-        ]
-    },
-    "recordset-indexer": {
-        "requires": [
-            "recordset-base",
-            "plugin"
-        ]
-    },
-    "recordset-sort": {
-        "requires": [
-            "arraysort",
-            "recordset-base",
-            "plugin"
-        ]
-    },
-    "resize": {
-        "use": [
-            "resize-base",
-            "resize-proxy",
-            "resize-constrain"
-        ]
-    },
-    "resize-base": {
-        "requires": [
-            "base",
-            "widget",
-            "event",
-            "oop",
-            "dd-drag",
-            "dd-delegate",
-            "dd-drop"
-        ],
-        "skinnable": true
-    },
-    "resize-constrain": {
-        "requires": [
-            "plugin",
-            "resize-base"
-        ]
-    },
-    "resize-plugin": {
-        "optional": [
-            "resize-constrain"
-        ],
-        "requires": [
-            "resize-base",
-            "plugin"
-        ]
-    },
-    "resize-proxy": {
-        "requires": [
-            "plugin",
-            "resize-base"
-        ]
-    },
-    "router": {
-        "optional": [
-            "querystring-parse"
-        ],
-        "requires": [
-            "array-extras",
-            "base-build",
-            "history"
-        ]
-    },
-    "scrollview": {
-        "requires": [
-            "scrollview-base",
-            "scrollview-scrollbars"
-        ]
-    },
-    "scrollview-base": {
-        "requires": [
-            "widget",
-            "event-gestures",
-            "event-mousewheel",
-            "transition"
-        ],
-        "skinnable": true
-    },
-    "scrollview-base-ie": {
-        "condition": {
-            "name": "scrollview-base-ie",
-            "trigger": "scrollview-base",
-            "ua": "ie"
-        },
-        "requires": [
-            "scrollview-base"
-        ]
-    },
-    "scrollview-list": {
-        "requires": [
-            "plugin",
-            "classnamemanager"
-        ],
-        "skinnable": true
-    },
-    "scrollview-paginator": {
-        "requires": [
-            "plugin",
-            "classnamemanager"
-        ]
-    },
-    "scrollview-scrollbars": {
-        "requires": [
-            "classnamemanager",
-            "transition",
-            "plugin"
-        ],
-        "skinnable": true
-    },
-    "selector": {
-        "requires": [
-            "selector-native"
-        ]
-    },
-    "selector-css2": {
-        "condition": {
-            "name": "selector-css2",
-            "test": function (Y) {
-    var DOCUMENT = Y.config.doc,
-        ret = DOCUMENT && !('querySelectorAll' in DOCUMENT);
-
-    return ret;
-},
-            "trigger": "selector"
-        },
-        "requires": [
-            "selector-native"
-        ]
-    },
-    "selector-css3": {
-        "requires": [
-            "selector-native",
-            "selector-css2"
-        ]
-    },
-    "selector-native": {
-        "requires": [
-            "dom-base"
-        ]
-    },
-    "series-area": {
-        "requires": [
-            "series-cartesian",
-            "series-fill-util"
-        ]
-    },
-    "series-area-stacked": {
-        "requires": [
-            "series-stacked",
-            "series-area"
-        ]
-    },
-    "series-areaspline": {
-        "requires": [
-            "series-area",
-            "series-curve-util"
-        ]
-    },
-    "series-areaspline-stacked": {
-        "requires": [
-            "series-stacked",
-            "series-areaspline"
-        ]
-    },
-    "series-bar": {
-        "requires": [
-            "series-marker",
-            "series-histogram-base"
-        ]
-    },
-    "series-bar-stacked": {
-        "requires": [
-            "series-stacked",
-            "series-bar"
-        ]
-    },
-    "series-base": {
-        "requires": [
-            "graphics",
-            "axis-base"
-        ]
-    },
-    "series-candlestick": {
-        "requires": [
-            "series-range"
-        ]
-    },
-    "series-cartesian": {
-        "requires": [
-            "series-base"
-        ]
-    },
-    "series-column": {
-        "requires": [
-            "series-marker",
-            "series-histogram-base"
-        ]
-    },
-    "series-column-stacked": {
-        "requires": [
-            "series-stacked",
-            "series-column"
-        ]
-    },
-    "series-combo": {
-        "requires": [
-            "series-cartesian",
-            "series-line-util",
-            "series-plot-util",
-            "series-fill-util"
-        ]
-    },
-    "series-combo-stacked": {
-        "requires": [
-            "series-stacked",
-            "series-combo"
-        ]
-    },
-    "series-combospline": {
-        "requires": [
-            "series-combo",
-            "series-curve-util"
-        ]
-    },
-    "series-combospline-stacked": {
-        "requires": [
-            "series-combo-stacked",
-            "series-curve-util"
-        ]
-    },
-    "series-curve-util": {},
-    "series-fill-util": {},
-    "series-histogram-base": {
-        "requires": [
-            "series-cartesian",
-            "series-plot-util"
-        ]
-    },
-    "series-line": {
-        "requires": [
-            "series-cartesian",
-            "series-line-util"
-        ]
-    },
-    "series-line-stacked": {
-        "requires": [
-            "series-stacked",
-            "series-line"
-        ]
-    },
-    "series-line-util": {},
-    "series-marker": {
-        "requires": [
-            "series-cartesian",
-            "series-plot-util"
-        ]
-    },
-    "series-marker-stacked": {
-        "requires": [
-            "series-stacked",
-            "series-marker"
-        ]
-    },
-    "series-ohlc": {
-        "requires": [
-            "series-range"
-        ]
-    },
-    "series-pie": {
-        "requires": [
-            "series-base",
-            "series-plot-util"
-        ]
-    },
-    "series-plot-util": {},
-    "series-range": {
-        "requires": [
-            "series-cartesian"
-        ]
-    },
-    "series-spline": {
-        "requires": [
-            "series-line",
-            "series-curve-util"
-        ]
-    },
-    "series-spline-stacked": {
-        "requires": [
-            "series-stacked",
-            "series-spline"
-        ]
-    },
-    "series-stacked": {
-        "requires": [
-            "axis-stacked"
-        ]
-    },
-    "shim-plugin": {
-        "requires": [
-            "node-style",
-            "node-pluginhost"
-        ]
-    },
-    "slider": {
-        "use": [
-            "slider-base",
-            "slider-value-range",
-            "clickable-rail",
-            "range-slider"
-        ]
-    },
-    "slider-base": {
-        "requires": [
-            "widget",
-            "dd-constrain",
-            "event-key"
-        ],
-        "skinnable": true
-    },
-    "slider-value-range": {
-        "requires": [
-            "slider-base"
-        ]
-    },
-    "sortable": {
-        "requires": [
-            "dd-delegate",
-            "dd-drop-plugin",
-            "dd-proxy"
-        ]
-    },
-    "sortable-scroll": {
-        "requires": [
-            "dd-scroll",
-            "sortable"
-        ]
-    },
-    "stylesheet": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "substitute": {
-        "optional": [
-            "dump"
-        ],
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "swf": {
-        "requires": [
-            "event-custom",
-            "node",
-            "swfdetect",
-            "escape"
-        ]
-    },
-    "swfdetect": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "tabview": {
-        "requires": [
-            "widget",
-            "widget-parent",
-            "widget-child",
-            "tabview-base",
-            "node-pluginhost",
-            "node-focusmanager"
-        ],
-        "skinnable": true
-    },
-    "tabview-base": {
-        "requires": [
-            "node-event-delegate",
-            "classnamemanager"
-        ]
-    },
-    "tabview-plugin": {
-        "requires": [
-            "tabview-base"
-        ]
-    },
-    "template": {
-        "use": [
-            "template-base",
-            "template-micro"
-        ]
-    },
-    "template-base": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "template-micro": {
-        "requires": [
-            "escape"
-        ]
-    },
-    "test": {
-        "requires": [
-            "event-simulate",
-            "event-custom",
-            "json-stringify"
-        ]
-    },
-    "test-console": {
-        "requires": [
-            "console-filters",
-            "test",
-            "array-extras"
-        ],
-        "skinnable": true
-    },
-    "text": {
-        "use": [
-            "text-accentfold",
-            "text-wordbreak"
-        ]
-    },
-    "text-accentfold": {
-        "requires": [
-            "array-extras",
-            "text-data-accentfold"
-        ]
-    },
-    "text-data-accentfold": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "text-data-wordbreak": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "text-wordbreak": {
-        "requires": [
-            "array-extras",
-            "text-data-wordbreak"
-        ]
-    },
-    "timers": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "transition": {
-        "requires": [
-            "node-style"
-        ]
-    },
-    "transition-timer": {
-        "condition": {
-            "name": "transition-timer",
-            "test": function (Y) {
-    var DOCUMENT = Y.config.doc,
-        node = (DOCUMENT) ? DOCUMENT.documentElement: null,
-        ret = true;
-
-    if (node && node.style) {
-        ret = !('MozTransition' in node.style || 'WebkitTransition' in node.style || 'transition' in node.style);
-    }
-
-    return ret;
-},
-            "trigger": "transition"
-        },
-        "requires": [
-            "transition"
-        ]
-    },
-    "tree": {
-        "requires": [
-            "base-build",
-            "tree-node"
-        ]
-    },
-    "tree-labelable": {
-        "requires": [
-            "tree"
-        ]
-    },
-    "tree-lazy": {
-        "requires": [
-            "base-pluginhost",
-            "plugin",
-            "tree"
-        ]
-    },
-    "tree-node": {},
-    "tree-openable": {
-        "requires": [
-            "tree"
-        ]
-    },
-    "tree-selectable": {
-        "requires": [
-            "tree"
-        ]
-    },
-    "tree-sortable": {
-        "requires": [
-            "tree"
-        ]
-    },
-    "uploader": {
-        "requires": [
-            "uploader-html5",
-            "uploader-flash"
-        ]
-    },
-    "uploader-flash": {
-        "requires": [
-            "swf",
-            "widget",
-            "base",
-            "cssbutton",
-            "node",
-            "event-custom",
-            "file-flash",
-            "uploader-queue"
-        ]
-    },
-    "uploader-html5": {
-        "requires": [
-            "widget",
-            "node-event-simulate",
-            "file-html5",
-            "uploader-queue"
-        ]
-    },
-    "uploader-queue": {
-        "requires": [
-            "base"
-        ]
-    },
-    "view": {
-        "requires": [
-            "base-build",
-            "node-event-delegate"
-        ]
-    },
-    "view-node-map": {
-        "requires": [
-            "view"
-        ]
-    },
-    "widget": {
-        "use": [
-            "widget-base",
-            "widget-htmlparser",
-            "widget-skin",
-            "widget-uievents"
-        ]
-    },
-    "widget-anim": {
-        "requires": [
-            "anim-base",
-            "plugin",
-            "widget"
-        ]
-    },
-    "widget-autohide": {
-        "requires": [
-            "base-build",
-            "event-key",
-            "event-outside",
-            "widget"
-        ]
-    },
-    "widget-base": {
-        "requires": [
-            "attribute",
-            "base-base",
-            "base-pluginhost",
-            "classnamemanager",
-            "event-focus",
-            "node-base",
-            "node-style"
-        ],
-        "skinnable": true
-    },
-    "widget-base-ie": {
-        "condition": {
-            "name": "widget-base-ie",
-            "trigger": "widget-base",
-            "ua": "ie"
-        },
-        "requires": [
-            "widget-base"
-        ]
-    },
-    "widget-buttons": {
-        "requires": [
-            "button-plugin",
-            "cssbutton",
-            "widget-stdmod"
-        ]
-    },
-    "widget-child": {
-        "requires": [
-            "base-build",
-            "widget"
-        ]
-    },
-    "widget-htmlparser": {
-        "requires": [
-            "widget-base"
-        ]
-    },
-    "widget-locale": {
-        "requires": [
-            "widget-base"
-        ]
-    },
-    "widget-modality": {
-        "requires": [
-            "base-build",
-            "event-outside",
-            "widget"
-        ],
-        "skinnable": true
-    },
-    "widget-parent": {
-        "requires": [
-            "arraylist",
-            "base-build",
-            "widget"
-        ]
-    },
-    "widget-position": {
-        "requires": [
-            "base-build",
-            "node-screen",
-            "widget"
-        ]
-    },
-    "widget-position-align": {
-        "requires": [
-            "widget-position"
-        ]
-    },
-    "widget-position-constrain": {
-        "requires": [
-            "widget-position"
-        ]
-    },
-    "widget-skin": {
-        "requires": [
-            "widget-base"
-        ]
-    },
-    "widget-stack": {
-        "requires": [
-            "base-build",
-            "widget"
-        ],
-        "skinnable": true
-    },
-    "widget-stdmod": {
-        "requires": [
-            "base-build",
-            "widget"
-        ]
-    },
-    "widget-uievents": {
-        "requires": [
-            "node-event-delegate",
-            "widget-base"
-        ]
-    },
-    "yql": {
-        "requires": [
-            "oop"
-        ]
-    },
-    "yql-jsonp": {
-        "condition": {
-            "name": "yql-jsonp",
-            "test": function (Y) {
-    /* Only load the JSONP module when not in nodejs or winjs
-    TODO Make the winjs module a CORS module
-    */
-    return (!Y.UA.nodejs && !Y.UA.winjs);
-},
-            "trigger": "yql",
-            "when": "after"
-        },
-        "requires": [
-            "jsonp",
-            "jsonp-url"
-        ]
-    },
-    "yql-nodejs": {
-        "condition": {
-            "name": "yql-nodejs",
-            "trigger": "yql",
-            "ua": "nodejs",
-            "when": "after"
-        }
-    },
-    "yql-winjs": {
-        "condition": {
-            "name": "yql-winjs",
-            "trigger": "yql",
-            "ua": "winjs",
-            "when": "after"
-        }
-    },
-    "yui": {},
-    "yui-base": {},
-    "yui-later": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "yui-log": {
-        "requires": [
-            "yui-base"
-        ]
-    },
-    "yui-throttle": {
-        "requires": [
-            "yui-base"
-        ]
-    }
-});
-YUI.Env[Y.version].md5 = 'fd7c67956df50e445f40d1668dd1dc80';
-
-
-}, '3.12.0', {"requires": ["loader-base"]});
-YUI.add('yui', function (Y, NAME) {}, '3.12.0', {
-    "use": [
-        "yui-base",
-        "get",
-        "features",
-        "intl-base",
-        "yui-log",
-        "yui-later",
-        "loader-base",
-        "loader-rollup",
-        "loader-yui3"
-    ]
-});
--- a/js/src/jsapi-tests/testBinASTReader.cpp
+++ b/js/src/jsapi-tests/testBinASTReader.cpp
@@ -49,17 +49,17 @@ readFull(JSContext* cx, const char* path
     js::Vector<uint8_t> intermediate(cx);
     readFull(path, intermediate);
 
     if (!buf.appendAll(intermediate))
         MOZ_CRASH("Couldn't read data");
 }
 
 // Invariant: `path` must end with directory separator.
-void
+template<typename Tok> void
 runTestFromPath(JSContext* cx, const char* path)
 {
     const char BIN_SUFFIX[] = ".binjs";
     const char TXT_SUFFIX[] = ".js";
     fprintf(stderr, "runTestFromPath: entering directory '%s'\n", path);
     const size_t pathlen = strlen(path);
 
 #if defined(XP_UNIX)
@@ -117,17 +117,17 @@ runTestFromPath(JSContext* cx, const cha
                 MOZ_CRASH();
             if (!subPath.append(d_name, namlen))
                 MOZ_CRASH();
             // Append same directory separator.
             if (!subPath.append(path[pathlen - 1]))
                 MOZ_CRASH();
             if (!subPath.append(0))
                 MOZ_CRASH();
-            runTestFromPath(cx, subPath.begin());
+            runTestFromPath<Tok>(cx, subPath.begin());
             continue;
         }
 
         {
             // Make sure that we run GC between two tests. Otherwise, since we're running
             // everything from the same cx and without returning to JS, there is nothing
             // to deallocate the ASTs.
             JS::PrepareForFullGC(cx);
@@ -197,17 +197,17 @@ runTestFromPath(JSContext* cx, const cha
         // Parse binary file.
         CompileOptions binOptions(cx);
         binOptions.setFileAndLine(binPath.begin(), 0);
 
         js::frontend::UsedNameTracker binUsedNames(cx);
         if (!binUsedNames.init())
             MOZ_CRASH("Couldn't initialized binUsedNames");
 
-        js::frontend::BinASTParser binParser(cx, allocScope.alloc(), binUsedNames, binOptions);
+        js::frontend::BinASTParser<Tok> binParser(cx, allocScope.alloc(), binUsedNames, binOptions);
 
         auto binParsed = binParser.parse(binSource); // Will be deallocated once `reader` goes out of scope.
         RootedValue binExn(cx);
         if (binParsed.isErr()) {
             // Save exception for more detailed error message, if necessary.
             if (!js::GetAndClearException(cx, &binExn))
                 MOZ_CRASH("Couldn't clear binExn");
         }
@@ -294,16 +294,18 @@ runTestFromPath(JSContext* cx, const cha
     if (closedir(dir) != 0)
         MOZ_CRASH("Could not close dir");
 #endif // defined(XP_WIN)
 }
 
 BEGIN_TEST(testBinASTReaderECMAScript2)
 {
 #if defined(XP_WIN)
-    runTestFromPath(cx, "jsapi-tests\\binast\\parser\\tester\\");
+    runTestFromPath<js::frontend::BinTokenReaderTester>(cx, "jsapi-tests\\binast\\parser\\tester\\");
+    runTestFromPath<js::frontend::BinTokenReaderMultipart(cx, "jsapi-tests\\binast\\parser\\multipart\\");
 #else
-    runTestFromPath(cx, "jsapi-tests/binast/parser/tester/");
+    runTestFromPath<js::frontend::BinTokenReaderTester>(cx, "jsapi-tests/binast/parser/tester/");
+    runTestFromPath<js::frontend::BinTokenReaderMultipart>(cx, "jsapi-tests/binast/parser/multipart/");
 #endif // defined(XP_XIN)
     return true;
 }
 END_TEST(testBinASTReaderECMAScript2)
 
--- a/js/src/jsapi-tests/testBinTokenReaderTester.cpp
+++ b/js/src/jsapi-tests/testBinTokenReaderTester.cpp
@@ -125,78 +125,78 @@ void readFull(const char* path, js::Vect
 
 // Reading a simple string.
 BEGIN_TEST(testBinTokenReaderTesterSimpleString)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-simple-string.binjs", contents);
     Tokenizer tokenizer(cx, contents);
 
-    Maybe<Chars> found;
-    CHECK(tokenizer.readMaybeChars(found));
+    Chars found(cx);
+    CHECK(tokenizer.readChars(found).isOk());
 
-    CHECK(Tokenizer::equals(*found, "simple string")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
+    CHECK(Tokenizer::equals(found, "simple string")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterSimpleString)
 
 // Reading a string with embedded 0.
 BEGIN_TEST(testBinTokenReaderTesterStringWithEscapes)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-string-with-escapes.binjs", contents);
     Tokenizer tokenizer(cx, contents);
 
-    Maybe<Chars> found;
-    CHECK(tokenizer.readMaybeChars(found));
+    Chars found(cx);
+    CHECK(tokenizer.readChars(found).isOk());
 
-    CHECK(Tokenizer::equals(*found, "string with escapes \0\1\0")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
+    CHECK(Tokenizer::equals(found, "string with escapes \0\1\0")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterStringWithEscapes)
 
 // Reading an empty untagged tuple
 BEGIN_TEST(testBinTokenReaderTesterEmptyUntaggedTuple)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-empty-untagged-tuple.binjs", contents);
     Tokenizer tokenizer(cx, contents);
 
     {
         Tokenizer::AutoTuple guard(tokenizer);
-        CHECK(tokenizer.enterUntaggedTuple(guard));
-        CHECK(guard.done());
+        CHECK(tokenizer.enterUntaggedTuple(guard).isOk());
+        CHECK(guard.done().isOk());
     }
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterEmptyUntaggedTuple)
 
 // Reading a untagged tuple with two strings
 BEGIN_TEST(testBinTokenReaderTesterTwoStringsInTuple)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-trivial-untagged-tuple.binjs", contents);
     Tokenizer tokenizer(cx, contents);
 
     {
         Tokenizer::AutoTuple guard(tokenizer);
-        CHECK(tokenizer.enterUntaggedTuple(guard));
+        CHECK(tokenizer.enterUntaggedTuple(guard).isOk());
 
-        Maybe<Chars> found_0;
-        CHECK(tokenizer.readMaybeChars(found_0));
-        CHECK(Tokenizer::equals(*found_0, "foo")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
+        Chars found_0(cx);
+        CHECK(tokenizer.readChars(found_0).isOk());
+        CHECK(Tokenizer::equals(found_0, "foo")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
 
-        Maybe<Chars> found_1;
-        CHECK(tokenizer.readMaybeChars(found_1));
-        CHECK(Tokenizer::equals(*found_1, "bar")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
+        Chars found_1(cx);
+        CHECK(tokenizer.readChars(found_1).isOk());
+        CHECK(Tokenizer::equals(found_1, "bar")); // FIXME: Find a way to make CHECK_EQUAL use `Tokenizer::equals`.
 
-        CHECK(guard.done());
+        CHECK(guard.done().isOk());
     }
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterTwoStringsInTuple)
 
 // Reading a tagged tuple `Pattern { id: "foo", value: 3.1415}`
 BEGIN_TEST(testBinTokenReaderTesterSimpleTaggedTuple)
@@ -204,33 +204,33 @@ BEGIN_TEST(testBinTokenReaderTesterSimpl
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-simple-tagged-tuple.binjs", contents);
     Tokenizer tokenizer(cx, contents);
 
     {
         js::frontend::BinKind tag;
         Tokenizer::BinFields fields(cx);
         Tokenizer::AutoTaggedTuple guard(tokenizer);
-        CHECK(tokenizer.enterTaggedTuple(tag, fields, guard));
+        CHECK(tokenizer.enterTaggedTuple(tag, fields, guard).isOk());
 
         CHECK(tag == js::frontend::BinKind::BindingIdentifier);
 
-        Maybe<Chars> found_id;
+        Chars found_id(cx);
         const double EXPECTED_value = 3.1415;
-        Maybe<double> found_value;
 
         // Order of fields is deterministic.
         CHECK(fields[0] == js::frontend::BinField::Label);
         CHECK(fields[1] == js::frontend::BinField::Value);
-        CHECK(tokenizer.readMaybeChars(found_id));
-        CHECK(tokenizer.readMaybeDouble(found_value));
+        CHECK(tokenizer.readChars(found_id).isOk());
+        Maybe<double> found_value = tokenizer.readMaybeDouble().unwrap();
+        CHECK(found_value.isSome());
 
         CHECK(EXPECTED_value == *found_value); // Apparently, CHECK_EQUAL doesn't work on `double`.
-        CHECK(Tokenizer::equals(*found_id, "foo"));
-        CHECK(guard.done());
+        CHECK(Tokenizer::equals(found_id, "foo"));
+        CHECK(guard.done().isOk());
     }
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterSimpleTaggedTuple)
 
 
 // Reading an empty list
@@ -238,49 +238,49 @@ BEGIN_TEST(testBinTokenReaderTesterEmpty
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-empty-list.binjs", contents);
     Tokenizer tokenizer(cx, contents);
 
     {
         uint32_t length;
         Tokenizer::AutoList guard(tokenizer);
-        CHECK(tokenizer.enterList(length, guard));
+        CHECK(tokenizer.enterList(length, guard).isOk());
 
         CHECK(length == 0);
-        CHECK(guard.done());
+        CHECK(guard.done().isOk());
     }
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterEmptyList)
 
 // Reading `["foo", "bar"]`
 BEGIN_TEST(testBinTokenReaderTesterSimpleList)
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-trivial-list.binjs", contents);
     Tokenizer tokenizer(cx, contents);
 
     {
         uint32_t length;
         Tokenizer::AutoList guard(tokenizer);
-        CHECK(tokenizer.enterList(length, guard));
+        CHECK(tokenizer.enterList(length, guard).isOk());
 
         CHECK(length == 2);
 
-        Maybe<Chars> found_0;
-        CHECK(tokenizer.readMaybeChars(found_0));
-        CHECK(Tokenizer::equals(*found_0, "foo"));
+        Chars found_0(cx);
+        CHECK(tokenizer.readChars(found_0).isOk());
+        CHECK(Tokenizer::equals(found_0, "foo"));
 
-        Maybe<Chars> found_1;
-        CHECK(tokenizer.readMaybeChars(found_1));
-        CHECK(Tokenizer::equals(*found_1, "bar"));
+        Chars found_1(cx);
+        CHECK(tokenizer.readChars(found_1).isOk());
+        CHECK(Tokenizer::equals(found_1, "bar"));
 
-        CHECK(guard.done());
+        CHECK(guard.done().isOk());
     }
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterSimpleList)
 
 
 // Reading `[["foo", "bar"]]`
@@ -288,34 +288,34 @@ BEGIN_TEST(testBinTokenReaderTesterNeste
 {
     js::Vector<uint8_t> contents(cx);
     readFull("jsapi-tests/binast/tokenizer/tester/test-nested-lists.binjs", contents);
     Tokenizer tokenizer(cx, contents);
 
     {
         uint32_t outerLength;
         Tokenizer::AutoList outerGuard(tokenizer);
-        CHECK(tokenizer.enterList(outerLength, outerGuard));
+        CHECK(tokenizer.enterList(outerLength, outerGuard).isOk());
         CHECK(outerLength == 1);
 
         {
             uint32_t innerLength;
             Tokenizer::AutoList innerGuard(tokenizer);
-            CHECK(tokenizer.enterList(innerLength, innerGuard));
+            CHECK(tokenizer.enterList(innerLength, innerGuard).isOk());
             CHECK(innerLength == 2);
 
-            Maybe<Chars> found_0;
-            CHECK(tokenizer.readMaybeChars(found_0));
-            CHECK(Tokenizer::equals(*found_0, "foo"));
+            Chars found_0(cx);
+            CHECK(tokenizer.readChars(found_0).isOk());
+            CHECK(Tokenizer::equals(found_0, "foo"));
 
-            Maybe<Chars> found_1;
-            CHECK(tokenizer.readMaybeChars(found_1));
-            CHECK(Tokenizer::equals(*found_1, "bar"));
+            Chars found_1(cx);
+            CHECK(tokenizer.readChars(found_1).isOk());
+            CHECK(Tokenizer::equals(found_1, "bar"));
 
-            CHECK(innerGuard.done());
+            CHECK(innerGuard.done().isOk());
         }
 
-        CHECK(outerGuard.done());
+        CHECK(outerGuard.done().isOk());
     }
 
     return true;
 }
 END_TEST(testBinTokenReaderTesterNestedList)