liberty-prettydiff
Version:
Language aware code comparison tool for several web based languages. It also beautifies, minifies, and a few other things.
1,643 lines (1,482 loc) • 861 kB
Plain Text
/**
* @license AngularJS v1.2.10
* (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.10/" + (module
? module + "/"
: "") + code;
for (i = 2; i < arguments.length; i += 1) {
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;
}
/** holds major version number for IE or NaN for real browsers */
var 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.
*
* It is worth nothing that `.forEach` does not iterate over inherited properties because it filters
* using the `hasOwnProperty` method.
*
<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) {
// Need to check if hasOwnProperty exists, as on IE8 the result of
// querySelectorAll is an object without a hasOwnProperty function
if (key != "prototype" && key != "length" && key != "name" && (!obj.hasOwnProperty || 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 += 1) {
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 in obj) {
if (obj.hasOwnProperty(key)) {
keys.push(key);
}
}
return keys.sort();
}
function forEachSorted(obj, iterator, context) {
var keys = sortedKeys(obj);
for (var i = 0; i < keys.length; i += 1) {
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 -= 1;
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 += 1) {
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 += 1;
}
}
}
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 += 1) {
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 += 1) {
destination.push(copy(source[i]));
}
} else {
var h = destination.$$hashKey;
forEach(destination, function (value, key) {
delete destination[key];
});
for (var key in source) {
destination[key] = copy(source[key]);
}
setHashKey(destination, h);
}
}
return destination;
}
/**
* Create a shallow copy of an object
*/
function shallowCopy(src, dst) {
dst = dst || {};
for (var key 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) && key.charAt(0) !== "$" && key.charAt(1) !== "$") {
dst[key] = src[key];
}
}
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 += 1) {
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 (typeof value === "function") {
value = true;
} else 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, {
controller : JQLitePrototype.controller,
inheritedData: JQLitePrototype.inheritedData,
injector : JQLitePrototype.injector,
isolateScope : JQLitePrototype.isolateScope,
scope : JQLitePrototype.scope
});
// 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 += 1) {
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 (