'use strict'; //////////////////////////////////// if (typeof document.getAttribute == $undefined) document.getAttribute = function() {}; /** * @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) { return isString(s) ? s.replace(/[A-Z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) | 32);}) : s; }; var manualUppercase = function(s) { return isString(s) ? s.replace(/[a-z]/g, function(ch) {return fromCharCode(ch.charCodeAt(0) & ~32);}) : s; }; // 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; } function fromCharCode(code) {return String.fromCharCode(code);} /** * Creates the element for IE8 and below to allow styling of widgets * (http://ejohn.org/blog/html5-shiv/). This hack works only if angular is * included synchronously at the top of the document before IE sees any * unknown elements. See regression/issue-584.html. * * @param {string} elementName Name of the widget. * @returns {string} Lowercased string. */ function shivForIE(elementName) { elementName = lowercase(elementName); if (msie < 9 && elementName.charAt(0) != '@') { // ignore attr-widgets document.createElement(elementName); } return elementName; } var _undefined = undefined, _null = null, $$scope = '$scope', $angular = 'angular', $array = 'array', $boolean = 'boolean', $console = 'console', $date = 'date', $length = 'length', $name = 'name', $noop = 'noop', $null = 'null', $number = 'number', $object = 'object', $string = 'string', $value = 'value', $selected = 'selected', $undefined = 'undefined', NOOP = 'noop', Error = window.Error, /** holds major version number for IE or NaN for real browsers */ msie = parseInt((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1], 10), jqLite, // delay binding since jQuery could be loaded after us. jQuery, // delay binding slice = [].slice, push = [].push, error = window[$console] ? bind(window[$console], window[$console]['error'] || noop) : noop, /** @name angular */ angular = window.angular || (window.angular = {}), angularModule = angular.module || (angular.module = {}), /** @name angular.markup */ angularTextMarkup = extensionMap(angular, 'markup'), /** @name angular.attrMarkup */ angularAttrMarkup = extensionMap(angular, 'attrMarkup'), /** @name angular.directive */ angularDirective = extensionMap(angular, 'directive', lowercase), /** @name angular.widget */ angularWidget = extensionMap(angular, 'widget', shivForIE), /** @name angular.filter */ angularFilter = extensionMap(angular, 'filter'), /** @name angular.service */ angularInputType = extensionMap(angular, 'inputType', lowercase), /** @name angular.service */ angularCallbacks = extensionMap(angular, 'callbacks'), nodeName_, uid = ['0', '0', '0'], DATE_ISOSTRING_LN = 24; /** * @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`. *
     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']);
   
* * @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 (isObject(obj) && isNumber(obj.length)) { for (key = 0; key < obj.length; key++) iterator.call(context, obj[key], key); } else { for (key in obj) 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++) { iterator.call(context, obj[keys[i]], keys[i]); } return keys; } /** * 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 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(''); } /** * @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). */ function extend(dst) { forEach(arguments, function(obj){ if (obj !== dst) { forEach(obj, function(value, key){ dst[key] = value; }); } }); return dst; } 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.
     function foo(callback) {
       var result = calculateResult();
       (callback || angular.noop)(result);
     }
   
*/ 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. *
     function transformer(transformationFn, value) {
       return (transformationFn || identity)(value);
     };
   
*/ function identity($) {return $;} identity.$inject = []; function valueFn(value) {return function() {return value;};} function extensionMap(angular, name, transform) { var extPoint; return angular[name] || (extPoint = angular[name] = function(name, fn, prop){ name = (transform || identity)(name); if (isDefined(fn)) { extPoint[name] = extend(fn, prop || {}); } return extPoint[name]; }); } /** * @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 value instanceof 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 value instanceof 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';} /** * 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 isBoolean(value) {return typeof value == $boolean;} function isTextNode(node) {return nodeName_(node) == '#text';} function trim(value) { return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; } function isElement(node) { return node && (node.nodeName // we are a direct element || (node.bind && node.find)); // we have a bind 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; } /** * HTML class which is the only class which can be used in ng:bind to inline HTML for security * reasons. * * @constructor * @param html raw (unsafe) html * @param {string=} option If set to 'usafe', get method will return raw (unsafe/unsanitized) html */ function HTML(html, option) { this.html = html; this.get = lowercase(option) == 'unsafe' ? valueFn(html) : function htmlSanitize() { var buf = []; htmlParser(html, htmlSanitizeWriter(buf)); return buf.join(''); }; } 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 isVisible(element) { var rect = element[0].getBoundingClientRect(), width = (rect.width || (rect.right||0 - rect.left||0)), height = (rect.height || (rect.bottom||0 - rect.top||0)); return width>0 && height>0; } function map(obj, iterator, context) { var results = []; forEach(obj, function(value, index, list) { results.push(iterator.call(context, value, index, list)); }); return results; } /** * @ngdoc function * @name angular.Object.size * @function * * @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. * * @example * * * *
* Number of items in array: {{ [1,2].$size() }}
* Number of items in object: {{ {a:1, b:2, c:3}.$size() }}
* String length: {{fooStringLength}} *
*
* * it('should print correct sizes for an array and an object', function() { * expect(binding('[1,2].$size()')).toBe('2'); * expect(binding('{a:1, b:2, c:3}.$size()')).toBe('3'); * expect(binding('fooStringLength')).toBe('3'); * }); * *
*/ function size(obj, ownPropsOnly) { var size = 0, key; if (isArray(obj) || isString(obj)) { return obj.length; } else if (isObject(obj)){ for (key in obj) if (!ownPropsOnly || obj.hasOwnProperty(key)) size++; } return size; } function includes(array, obj) { for ( var i = 0; i < array.length; i++) { if (obj === array[i]) return true; } return false; } function indexOf(array, obj) { for ( var i = 0; i < array.length; i++) { if (obj === array[i]) return i; } return -1; } 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 * Alias for {@link angular.Object.copy} */ /** * @ngdoc function * @name angular.Object.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, `source` is returned. * * Note: this function is used to augment the Object type in Angular expressions. See * {@link angular.Array} for more information about Angular arrays. * * @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 * *
Salutation:
Name:

The master object is NOT equal to the form object.
master={{master}}
form={{form}}
*
* it('should print that initialy the form object is NOT equal to master', function() { expect(element('.doc-example-live input[ng\\:model="master.salutation"]').val()).toBe('Hello'); expect(element('.doc-example-live input[ng\\:model="master.name"]').val()).toBe('world'); expect(element('.doc-example-live span').css('display')).toBe('inline'); }); it('should make form and master equal when the copy button is clicked', function() { element('.doc-example-live button').click(); expect(element('.doc-example-live span').css('display')).toBe('none'); }); * *
*/ function copy(source, destination){ if (!destination) { destination = source; if (source) { if (isArray(source)) { destination = copy(source, []); } else if (isDate(source)) { destination = new Date(source.getTime()); } else if (isObject(source)) { destination = copy(source, {}); } } } else { if (isArray(source)) { while(destination.length) { destination.pop(); } for ( var i = 0; i < source.length; i++) { destination.push(copy(source[i])); } } else { forEach(destination, function(value, key){ delete destination[key]; }); for ( var key in source) { destination[key] = copy(source[key]); } } } return destination; } /** * @ngdoc function * @name angular.equals * @function * * @description * Alias for {@link angular.Object.equals} */ /** * @ngdoc function * @name angular.Object.equals * @function * * @description * Determines if two objects or two values are equivalent. Supports value types, 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 pass `===` comparison. * * During a property comparision, properties of `function` type and properties with names * that begin with `$` are ignored. * * Note: This function is used to augment the Object type in Angular expressions. See * {@link angular.Array} for more information about Angular arrays. * * @param {*} o1 Object or value to compare. * @param {*} o2 Object or value to compare. * @returns {boolean} True if arguments are equal. * * @example * *
Salutation:
Name:

The greeting object is NOT equal to {salutation:'Hello', name:'world'}.
greeting={{greeting}}
*
* it('should print that initialy greeting is equal to the hardcoded value object', function() { expect(element('.doc-example-live input[ng\\:model="greeting.salutation"]').val()).toBe('Hello'); expect(element('.doc-example-live input[ng\\:model="greeting.name"]').val()).toBe('world'); expect(element('.doc-example-live span').css('display')).toBe('none'); }); it('should say that the objects are not equal when the form is modified', function() { input('greeting.name').enter('kitty'); expect(element('.doc-example-live span').css('display')).toBe('inline'); }); * *
*/ function equals(o1, o2) { if (o1 === o2) return true; if (o1 === null || o2 === null) return false; var t1 = typeof o1, t2 = typeof o2, length, key, keySet; if (t1 == t2 && t1 == 'object') { if (o1 instanceof Array) { if ((length = o1.length) == o2.length) { for(key=0; key 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 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; } ///////////////////////////////////////////////// /** * 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 = decodeURIComponent(key_value[0]); obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true; } }); return obj; } function toKeyValue(obj) { var parts = []; forEach(obj, function(value, key) { parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true))); }); return parts.length ? parts.join('&') : ''; } /** * We need our custom mehtod because encodeURIComponent is too agressive 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 becuase encodeURIComponent is too agressive 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((pctEncodeSpaces ? null : /%20/g), '+'); } /** * @ngdoc directive * @name angular.directive.ng:autobind * @element script * * @TODO ng:autobind is not a directive!! it should be documented as bootstrap parameter in a * separate bootstrap section. * @TODO rename to ng:autobind to ng:autoboot * * @description * Technically, ng:autobind is not a directive; it is an Angular bootstrap parameter that can act * as a directive. It must exist in the script used to boot Angular and can be used only one time. * For details on bootstrapping Angular, see {@link guide/dev_guide.bootstrap Initializing Angular} * in the Angular Developer Guide. * * `ng:autobind` with no parameters tells Angular to compile and manage the whole page. * * `ng:autobind="[root element ID]"` tells Angular to compile and manage part of the document, * starting at "root element ID". * */ function angularInit(config, document){ var autobind = config.autobind; if (autobind) { var modules = [ngModule]; forEach((config.modules || '').split(','), function(module){ module = trim(module); if (module) { modules.push(module); } }); createInjector(modules, angularModule)(['$rootScope', '$compile', '$injector', function(scope, compile, injector){ scope.$apply(function(){ compile(isString(autobind) ? document.getElementById(autobind) : document)(scope); }); }]); } } function angularJsConfig(document) { bindJQuery(); var scripts = document.getElementsByTagName('script'), script = scripts[scripts.length-1], scriptSrc = script.src, config = {}, hashPos; hashPos = scriptSrc.indexOf('#'); if (hashPos != -1) extend(config, parseKeyValue(scriptSrc.substr(hashPos+1))); eachAttribute(jqLite(script), function(value, name){ if (/^ng:/.exec(name)) { name = name.substring(3).replace(/-/g, '_'); value = value || true; config[name] = value; } }); return config; } function bindJQuery() { // bind to jQuery if present; jQuery = window.jQuery; // reset to jQuery or default to us. if (jQuery) { jqLite = jQuery; extend(jQuery.fn, { scope: JQLitePrototype.scope, inheritedData: JQLitePrototype.inheritedData }); JQLitePatchJQueryRemove('remove', true); JQLitePatchJQueryRemove('empty'); JQLitePatchJQueryRemove('html'); } else { jqLite = jqLiteWrap; } angular.element = jqLite; } /** * throw error of the argument is falsy. */ function assertArg(arg, name, reason) { if (!arg) { var error = new Error("Argument '" + (name||'?') + "' is " + (reason || "required")); throw error; } return arg; } function assertArgFn(arg, name) { assertArg(isFunction(arg), name, 'not a function, got ' + (typeof arg == 'object' ? arg.constructor.name : typeof arg)); return arg; } function publishExternalAPI(angular){ extend(angular, { 'copy': copy, 'extend': extend, 'equals': equals, 'forEach': forEach, 'injector': function(){ return createInjector(arguments, angularModule); }, 'noop':noop, 'bind':bind, 'toJson': toJson, 'fromJson': fromJson, 'identity':identity, 'isUndefined': isUndefined, 'isDefined': isDefined, 'isString': isString, 'isFunction': isFunction, 'isObject': isObject, 'isNumber': isNumber, 'isArray': isArray, 'version': version, 'isDate': isDate, 'lowercase': lowercase, 'uppercase': uppercase }); angularModule.NG = ngModule; } ngModule.$inject = ['$provide', '$injector']; function ngModule($provide, $injector) { // TODO(misko): temporary services to get the compiler working; $provide.value('$textMarkup', angularTextMarkup); $provide.value('$attrMarkup', angularAttrMarkup); $provide.value('$directive', angularDirective); $provide.value('$widget', angularWidget); $provide.service('$browser', $BrowserProvider); $provide.service('$compile', $CompileProvider); $provide.service('$cookies', $CookiesProvider); $provide.service('$cookieStore', $CookieStoreProvider); $provide.service('$defer', $DeferProvider); $provide.service('$document', $DocumentProvider); $provide.service('$exceptionHandler', $ExceptionHandlerProvider); $provide.service('$formFactory', $FormFactoryProvider); $provide.service('$locale', $LocaleProvider); $provide.service('$location', $LocationProvider); $provide.service('$locationConfig', $LocationConfigProvider); $provide.service('$log', $LogProvider); $provide.service('$parse', $ParseProvider); $provide.service('$resource', $ResourceProvider); $provide.service('$route', $RouteProvider); $provide.service('$routeParams', $RouteParamsProvider); $provide.service('$rootScope', $RootScopeProvider); $provide.service('$sniffer', $SnifferProvider); $provide.service('$window', $WindowProvider); $provide.service('$xhr.bulk', $XhrBulkProvider); $provide.service('$xhr.cache', $XhrCacheProvider); $provide.service('$xhr.error', $XhrErrorProvider); $provide.service('$xhr', $XhrProvider); } /** * @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: '"NG_VERSION_FULL"', // all of these placeholder strings will be replaced by rake's major: "NG_VERSION_MAJOR", // compile task minor: "NG_VERSION_MINOR", dot: "NG_VERSION_DOT", codeName: '"NG_VERSION_CODENAME"' };