diff --git a/example/tweeter/tweeter_demo.html b/example/tweeter/tweeter_demo.html
index 6966192a5114..593831046708 100644
--- a/example/tweeter/tweeter_demo.html
+++ b/example/tweeter/tweeter_demo.html
@@ -5,7 +5,7 @@
-
+
diff --git a/lib/closure-compiler/README b/lib/closure-compiler/README
index ece717586fff..270cfc278ca5 100644
--- a/lib/closure-compiler/README
+++ b/lib/closure-compiler/README
@@ -146,13 +146,13 @@ the parse tree data structures were extracted and modified
significantly for use by Google's JavaScript compiler.
Local Modifications: The packages have been renamespaced. All code not
-relavant to parsing has been removed. A JSDoc parser and static typing
+relevant to parsing has been removed. A JsDoc parser and static typing
system have been added.
-----
Code in:
-lib/libtrunk_rhino_parser_jarjared.jar
+lib/rhino
Rhino
URL: http://www.mozilla.org/rhino
@@ -161,9 +161,8 @@ License: Netscape Public License and MPL / GPL dual license
Description: Mozilla Rhino is an implementation of JavaScript for the JVM.
-Local Modifications: None. We've used JarJar to renamespace the code
-post-compilation. See:
-http://code.google.com/p/jarjar/
+Local Modifications: Minor changes to parsing JSDoc that usually get pushed
+up-stream to Rhino trunk.
-----
@@ -172,7 +171,7 @@ lib/args4j.jar
Args4j
URL: https://args4j.dev.java.net/
-Version: 2.0.12
+Version: 2.0.16
License: MIT
Description:
@@ -188,7 +187,7 @@ lib/guava.jar
Guava Libraries
URL: http://code.google.com/p/guava-libraries/
-Version: r08
+Version: 13.0.1
License: Apache License 2.0
Description: Google's core Java libraries.
@@ -210,13 +209,28 @@ Description: Annotations for software defect detection.
Local Modifications: None.
+-----
+Code in:
+lib/jarjar.jar
+
+Jar Jar Links
+URL: http://jarjar.googlecode.com/
+Version: 1.1
+License: Apache License 2.0
+
+Description:
+A utility for repackaging Java libraries.
+
+Local Modifications: None.
+
+
----
Code in:
lib/junit.jar
JUnit
URL: http://sourceforge.net/projects/junit/
-Version: 4.8.2
+Version: 4.10
License: Common Public License 1.0
Description: A framework for writing and running automated tests in Java.
@@ -230,7 +244,7 @@ lib/protobuf-java.jar
Protocol Buffers
URL: http://code.google.com/p/protobuf/
-Version: 2.3.0
+Version: 2.4.1
License: New BSD License
Description: Supporting libraries for protocol buffers,
@@ -267,9 +281,9 @@ Local Modifications: None
---
Code in:
-tools/maven-ant-tasks-2.1.1.jar
+tools/maven-ant-tasks-2.1.3.jar
URL: http://maven.apache.org
-Version 2.1.1
+Version 2.1.3
License: Apache License 2.0
Description:
Maven Ant tasks are used to manage dependencies and to install/deploy to
diff --git a/lib/closure-compiler/compiler.jar b/lib/closure-compiler/compiler.jar
index 694808c0cac6..059db41d2c3b 100644
Binary files a/lib/closure-compiler/compiler.jar and b/lib/closure-compiler/compiler.jar differ
diff --git a/lib/closure-compiler/version.txt b/lib/closure-compiler/version.txt
index df60031294fa..dfd519f07eba 100644
--- a/lib/closure-compiler/version.txt
+++ b/lib/closure-compiler/version.txt
@@ -1 +1,2 @@
-20110615
+20130207
+r4796bc81
diff --git a/lib/externs/json.js b/lib/externs/json.js
new file mode 100644
index 000000000000..591d69bb133f
--- /dev/null
+++ b/lib/externs/json.js
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @fileoverview Definitions for the JSON specification.
+ * @see http://www.json.org/json2.js.
+ * @externs
+ */
+
+// This cannot go into the COMMON externs because it conflicts with the pure
+// JavaScript implementations of the API.
+
+var JSON = {};
+
+/**
+ * @param {string} jsonStr The string to parse.
+ * @param {(function(string, *) : *)=} opt_reviver
+ * @return {*} The JSON object.
+ * @throws {Error}
+ * @nosideeffects
+ */
+JSON.parse = function(jsonStr, opt_reviver) {};
+
+/**
+ * @param {*} jsonObj Input object.
+ * @param {(Array.|(function(string, *) : *)|null)=} opt_replacer
+ * @param {(number|string)=} opt_space
+ * @return {string} JSON string which represents jsonObj.
+ * @throws {Error}
+ * @nosideeffects
+ */
+JSON.stringify = function(jsonObj, opt_replacer, opt_space) {};
diff --git a/src/Angular.js b/src/Angular.js
index 27ef157d0091..44f19dfb97ca 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -59,38 +59,11 @@ var /** holds major version number for IE or NaN for real browsers */
/** @name angular */
angular = window.angular || (window.angular = {}),
+ ng = {}, //ng namespace for closure types
angularModule,
nodeName_,
uid = ['0', '0', '0'];
-/**
- * @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`.
- *
-
- *
- * @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`.
- */
-
/**
* @private
@@ -114,6 +87,34 @@ function isArrayLike(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`.
+ *
+
+ *
+ * @template T
+ * @param {Object.|Array.|undefined} obj Object to iterate over.
+ * @param {function(T, (string|number))} iterator Iterator function.
+ * @param {Object=} context Object to become context (`this`) for the iterator function.
+ * @returns {Object.|Array.|undefined} Returns the input `obj`.
+ */
function forEach(obj, iterator, context) {
var key;
if (obj) {
@@ -149,6 +150,14 @@ function sortedKeys(obj) {
return keys.sort();
}
+
+/**
+ * @template T
+ * @param {Object.} obj
+ * @param {function(T, string)} iterator
+ * @param {Object=} context
+ * @return {Array.} sorted array of keys
+ */
function forEachSorted(obj, iterator, context) {
var keys = sortedKeys(obj);
for ( var i = 0; i < keys.length; i++) {
@@ -160,8 +169,10 @@ function forEachSorted(obj, iterator, context) {
/**
* when using forEach the params are value, key, but it is often useful to have key, value.
- * @param {function(string, *)} iteratorFn
- * @returns {function(*, string)}
+ *
+ * @template T1, T2
+ * @param {function(T1, T2)} iteratorFn
+ * @returns {function(T2, T1)}
*/
function reverseParams(iteratorFn) {
return function(value, key) { iteratorFn(key, value) };
@@ -173,7 +184,7 @@ function reverseParams(iteratorFn) {
* 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
+ * @returns {string} A unique alpha-numeric string
*/
function nextUid() {
var index = uid.length;
@@ -206,10 +217,10 @@ function nextUid() {
* 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).
+ * @param {!Object} dst Destination object.
+ * @param {...Object} var_args Source object(s).
*/
-function extend(dst) {
+function extend(dst, var_args) {
forEach(arguments, function(obj){
if (obj !== dst) {
forEach(obj, function(value, key){
@@ -225,6 +236,11 @@ function int(str) {
}
+/**
+ * @param {Object} parent
+ * @param {Object=} extra
+ * @return {*}
+ */
function inherit(parent, extra) {
return extend(new (extend(function() {}, {prototype:parent}))(), extra);
}
@@ -390,12 +406,11 @@ 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;
+ return !!(obj && obj.document && obj.location && obj.alert && obj.setInterval);
}
@@ -426,18 +441,18 @@ function trim(value) {
* @description
* Determines if a reference is a DOM element (or wrapped jQuery element).
*
- * @param {*} value Reference to check.
+ * @param {*} node Reference to check.
* @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
*/
function isElement(node) {
- return 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
+ || (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, ...}
+ * @returns {Object} in the form of {key1:true, key2:true, ...}
*/
function makeMap(str){
var obj = {}, items = str.split(","), i;
@@ -460,10 +475,17 @@ if (msie < 9) {
}
+/**
+ * @template T
+ * @param {!(Array.|Object.)} obj
+ * @param {!function(T, (string|number))} iterator
+ * @param {Object=} context
+ * @return {!Array}
+ */
function map(obj, iterator, context) {
var results = [];
- forEach(obj, function(value, index, list) {
- results.push(iterator.call(context, value, index, list));
+ forEach(obj, function(value, index) {
+ results.push(iterator.call(context, value, index));
});
return results;
}
@@ -544,25 +566,26 @@ function isLeafNode (node) {
* Note: this function is used to augment the Object type in Angular expressions. See
* {@link ng.$filter} for more information about Angular arrays.
*
- * @param {*} source The source that will be used to make a copy.
+ * @template T
+ * @param {!T} 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.
+ * @returns {!T} The copy or updated `destination`, if `destination` was specified.
*/
function copy(source, destination){
if (isWindow(source) || isScope(source)) throw Error("Can't copy Window or Scope");
if (!destination) {
- destination = source;
if (source) {
if (isArray(source)) {
- destination = copy(source, []);
+ return copy(source, []);
} else if (isDate(source)) {
- destination = new Date(source.getTime());
+ return new Date(source.getTime());
} else if (isObject(source)) {
- destination = copy(source, {});
+ return copy(source, {});
}
}
+ return source;
} else {
if (source === destination) throw Error("Can't copy equivalent objects or arrays");
if (isArray(source)) {
@@ -676,15 +699,15 @@ function sliceArgs(args, startIndex) {
*
* @description
* Returns a function which calls function `fn` bound to `self` (`self` becomes the `this` for
- * `fn`). You can supply optional `args` that are are prebound to the function. This feature is also
+ * `fn`). You can supply optional `var_args` that are are prebound to the function. This feature is also
* known as [function currying](http://en.wikipedia.org/wiki/Currying).
*
* @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.
+ * @param {...*} var_args Optional arguments to be prebound to the `fn` function call.
* @returns {function()} Function that wraps the `fn` with all the specified bindings.
*/
-function bind(self, fn) {
+function bind(self, fn, var_args) {
var curryArgs = arguments.length > 2 ? sliceArgs(arguments, 2) : [];
if (isFunction(fn) && !(fn instanceof RegExp)) {
return curryArgs.length
@@ -730,12 +753,12 @@ function toJsonReplacer(key, value) {
* @description
* Serializes input into a JSON-formatted string.
*
- * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
+ * @param {*} obj Input to be serialized into JSON.
* @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace.
- * @returns {string} Jsonified string representing `obj`.
+ * @returns {string|undefined} Jsonified string representing `obj`.
*/
function toJson(obj, pretty) {
- return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : null);
+ return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : undefined);
}
@@ -748,11 +771,11 @@ function toJson(obj, pretty) {
* Deserializes a JSON string.
*
* @param {string} json JSON string to deserialize.
- * @returns {Object|Array|Date|string|number} Deserialized thingy.
+ * @returns {Object|Array|string|number} Deserialized thingy.
*/
function fromJson(json) {
return isString(json)
- ? JSON.parse(json)
+ ? /** @type {Object|Array|string|number}*/(JSON.parse(json))
: json;
}
@@ -787,15 +810,18 @@ function startingTag(element) {
/**
* Parses an escaped url query string into key-value pairs.
+ *
+ * @param {string} keyValueString
* @returns Object.<(string|boolean)>
*/
-function parseKeyValue(/**string*/keyValue) {
- var obj = {}, key_value, key;
- forEach((keyValue || "").split('&'), function(keyValue){
+function parseKeyValue(keyValueString) {
+ var obj = {};
+ var key_value, key;
+ forEach((keyValueString || "").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;
+ keyValue = keyValue.split('=');
+ key = decodeURIComponent(keyValue[0]);
+ obj[key] = isDefined(keyValue[1]) ? decodeURIComponent(keyValue[1]) : true;
}
});
return obj;
@@ -855,11 +881,9 @@ function encodeUriQuery(val, pctEncodeSpaces) {
* @name ng.directive:ngApp
*
* @element ANY
- * @param {angular.Module} ngApp an optional application
- * {@link angular.module module} name to load.
+ * @param {string} ngApp an optional application {@link angular.module module} name to load.
*
* @description
- *
* Use this directive to auto-bootstrap on application. Only
* one directive can be used per HTML document. The directive
* designates the root of the application and is typically placed
@@ -878,6 +902,11 @@ function encodeUriQuery(val, pctEncodeSpaces) {
*
*/
+
+/**
+ * @param {!(Element|Document)} element
+ * @param {!function(!Element, Array.)} bootstrap
+ */
function angularInit(element, bootstrap) {
var elements = [element],
appElement,
@@ -930,9 +959,9 @@ function angularInit(element, bootstrap) {
*
* See: {@link guide/bootstrap Bootstrap}
*
- * @param {Element} element DOM element which is the root of angular application.
- * @param {Array=} modules an array of module declarations. See: {@link angular.module modules}
- * @returns {AUTO.$injector} Returns the newly created injector for this app.
+ * @param {!Element} element DOM element which is the root of angular application.
+ * @param {Array.=} modules an array of module declarations. See: {@link angular.module modules}
+ * @returns {ng.Injector} Returns the newly created injector for this app.
*/
function bootstrap(element, modules) {
element = jqLite(element);
@@ -984,6 +1013,9 @@ function bindJQuery() {
/**
* throw error of the argument is falsy.
+ * @param {*} arg
+ * @param {string=} name
+ * @param {string=} reason
*/
function assertArg(arg, name, reason) {
if (!arg) {
@@ -992,7 +1024,12 @@ function assertArg(arg, name, reason) {
return arg;
}
-function assertArgFn(arg, name, acceptArrayAnnotation) {
+/**
+ * @param {*} arg
+ * @param {string} name
+ * @param {boolean=} acceptArrayAnnotation
+ */
+ function assertArgFn(arg, name, acceptArrayAnnotation) {
if (acceptArrayAnnotation && isArray(arg)) {
arg = arg[arg.length - 1];
}
diff --git a/src/angular-bootstrap.js b/src/angular-bootstrap.js
index 86b958148c40..03ba8d888d57 100644
--- a/src/angular-bootstrap.js
+++ b/src/angular-bootstrap.js
@@ -1,227 +1,11 @@
+'use strict';
-/*!
- * $script.js Async loader & dependency manager
- * https://github.com/ded/script.js
- * (c) Dustin Diaz, Jacob Thornton 2011
- * License: MIT
- */
-(function (name, definition, context) {
- if (typeof context['module'] != 'undefined' && context['module']['exports']) context['module']['exports'] = definition()
- else if (typeof context['define'] != 'undefined' && context['define'] == 'function' && context['define']['amd']) define(name, definition)
- else context[name] = definition()
-})('$script', function () {
- var doc = document
- , head = doc.getElementsByTagName('head')[0]
- , validBase = /^https?:\/\//
- , list = {}, ids = {}, delay = {}, scriptpath
- , scripts = {}, s = 'string', f = false
- , push = 'push', domContentLoaded = 'DOMContentLoaded', readyState = 'readyState'
- , addEventListener = 'addEventListener', onreadystatechange = 'onreadystatechange'
+//try to bind to jquery now so that one can write angular.element().read()
+//but we will rebind on bootstrap again.
+bindJQuery();
- function every(ar, fn) {
- for (var i = 0, j = ar.length; i < j; ++i) if (!fn(ar[i])) return f
- return 1
- }
- function each(ar, fn) {
- every(ar, function(el) {
- return !fn(el)
- })
- }
-
- if (!doc[readyState] && doc[addEventListener]) {
- doc[addEventListener](domContentLoaded, function fn() {
- doc.removeEventListener(domContentLoaded, fn, f)
- doc[readyState] = 'complete'
- }, f)
- doc[readyState] = 'loading'
- }
-
- function $script(paths, idOrDone, optDone) {
- paths = paths[push] ? paths : [paths]
- var idOrDoneIsDone = idOrDone && idOrDone.call
- , done = idOrDoneIsDone ? idOrDone : optDone
- , id = idOrDoneIsDone ? paths.join('') : idOrDone
- , queue = paths.length
- function loopFn(item) {
- return item.call ? item() : list[item]
- }
- function callback() {
- if (!--queue) {
- list[id] = 1
- done && done()
- for (var dset in delay) {
- every(dset.split('|'), loopFn) && !each(delay[dset], loopFn) && (delay[dset] = [])
- }
- }
- }
- setTimeout(function () {
- each(paths, function (path) {
- if (scripts[path]) {
- id && (ids[id] = 1)
- return scripts[path] == 2 && callback()
- }
- scripts[path] = 1
- id && (ids[id] = 1)
- create(!validBase.test(path) && scriptpath ? scriptpath + path + '.js' : path, callback)
- })
- }, 0)
- return $script
- }
-
- function create(path, fn) {
- var el = doc.createElement('script')
- , loaded = f
- el.onload = el.onerror = el[onreadystatechange] = function () {
- if ((el[readyState] && !(/^c|loade/.test(el[readyState]))) || loaded) return;
- el.onload = el[onreadystatechange] = null
- loaded = 1
- scripts[path] = 2
- fn()
- }
- el.async = 1
- el.src = path
- head.insertBefore(el, head.firstChild)
- }
-
- $script.get = create
-
- $script.order = function (scripts, id, done) {
- (function callback(s) {
- s = scripts.shift()
- if (!scripts.length) $script(s, id, done)
- else $script(s, callback)
- }())
- }
-
- $script.path = function (p) {
- scriptpath = p
- }
- $script.ready = function (deps, ready, req) {
- deps = deps[push] ? deps : [deps]
- var missing = [];
- !each(deps, function (dep) {
- list[dep] || missing[push](dep);
- }) && every(deps, function (dep) {return list[dep]}) ?
- ready() : !function (key) {
- delay[key] = delay[key] || []
- delay[key][push](ready)
- req && req(missing)
- }(deps.join('|'))
- return $script
- }
- return $script
-}, this);
-
-
-/**
- * @license AngularJS
- * (c) 2010-2012 Google, Inc. http://angularjs.org
- * License: MIT
- */
-(function(window, document) {
-
- var filename = /^(.*\/)angular-bootstrap.js(#.*)?$/,
- scripts = document.getElementsByTagName("SCRIPT"),
- serverPath,
- match,
- globalVars = {},
- IGNORE = {
- innerHeight: true, innerWidth: true,
- onkeyup: true, onkeydown: true, onresize: true,
- event: true, frames: true, external: true,
- sessionStorage: true, clipboardData: true, localStorage: true};
-
- for(var j = 0; j < scripts.length; j++) {
- match = (scripts[j].src || "").match(filename);
- if (match) {
- serverPath = match[1];
- }
- }
-
- document.write('');
-
- $script.path(serverPath+'../');
- $script('angularFiles', function() {
- var index = 0,
- scripts = angularFiles.angularSrc;
-
- try { delete window.angularFiles; } catch(e) { window.angularFiles = undefined; }
- // initialize the window property cache
- for (var prop in window) {
- if (IGNORE[prop] || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
- continue;
- }
- try {
- globalVars[key(prop)] = window[prop];
- } catch(e) {} //ignore properties that throw exception when accessed (common in FF)
- }
-
- (function next() {
- if (index < scripts.length) {
- var file = scripts[index++],
- last = index == scripts.length,
- name = last ? 'angular' : file;
-
- $script(file.replace(/\.js$/, ''), name, function() {
- angularClobberTest(file);
- next();
- });
- } else {
- // empty the cache to prevent mem leaks
- globalVars = {};
-
- bindJQuery();
- publishExternalAPI(window.angular);
-
- angularInit(document, angular.bootstrap);
- }
- })();
- });
-
- function key(prop) {
- return "ng-clobber_" + prop;
- }
-
- function angularClobberTest(file) {
- var varKey, prop,
- clobbered = {};
-
- for (prop in window) {
- varKey = key(prop);
-
- if (IGNORE[prop] || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
- continue;
- } else if (!globalVars.hasOwnProperty(varKey)) {
- //console.log('new global variable found: ', prop);
- try {
- globalVars[varKey] = window[prop];
- } catch(e) {} //ignore properties that throw exception when accessed (common in FF)
- } else if (globalVars[varKey] !== window[prop] && !isActuallyNaN(window[prop]) && prop != 'jqLite') {
- clobbered[prop] = true;
- console.error("Global variable clobbered by script " + file + "! Variable name: " + prop);
- globalVars[varKey] = window[prop];
- }
- }
- for (varKey in globalVars) {
- prop = varKey.substr(11);
- if (prop === 'event' || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
- continue;
- }
- if (!clobbered[prop] &&
- prop != 'event' &&
- prop != 'jqLite' &&
- !isActuallyNaN(globalVars[varKey]) &&
- globalVars[varKey] !== window[prop]) {
-
- delete globalVars[varKey];
- console.warn("Global variable unexpectedly deleted in script " + file + "! " +
- "Variable name: " + prop);
- }
- }
-
- function isActuallyNaN(val) {
- return (typeof val === 'number') && isNaN(val);
- }
- };
-})(window, document);
+publishExternalAPI(angular);
+jqLite(document).ready(function() {
+ angularInit(document, bootstrap);
+});
diff --git a/src/angular-dev.js b/src/angular-dev.js
new file mode 100644
index 000000000000..86b958148c40
--- /dev/null
+++ b/src/angular-dev.js
@@ -0,0 +1,227 @@
+
+/*!
+ * $script.js Async loader & dependency manager
+ * https://github.com/ded/script.js
+ * (c) Dustin Diaz, Jacob Thornton 2011
+ * License: MIT
+ */
+(function (name, definition, context) {
+ if (typeof context['module'] != 'undefined' && context['module']['exports']) context['module']['exports'] = definition()
+ else if (typeof context['define'] != 'undefined' && context['define'] == 'function' && context['define']['amd']) define(name, definition)
+ else context[name] = definition()
+})('$script', function () {
+ var doc = document
+ , head = doc.getElementsByTagName('head')[0]
+ , validBase = /^https?:\/\//
+ , list = {}, ids = {}, delay = {}, scriptpath
+ , scripts = {}, s = 'string', f = false
+ , push = 'push', domContentLoaded = 'DOMContentLoaded', readyState = 'readyState'
+ , addEventListener = 'addEventListener', onreadystatechange = 'onreadystatechange'
+
+ function every(ar, fn) {
+ for (var i = 0, j = ar.length; i < j; ++i) if (!fn(ar[i])) return f
+ return 1
+ }
+ function each(ar, fn) {
+ every(ar, function(el) {
+ return !fn(el)
+ })
+ }
+
+ if (!doc[readyState] && doc[addEventListener]) {
+ doc[addEventListener](domContentLoaded, function fn() {
+ doc.removeEventListener(domContentLoaded, fn, f)
+ doc[readyState] = 'complete'
+ }, f)
+ doc[readyState] = 'loading'
+ }
+
+ function $script(paths, idOrDone, optDone) {
+ paths = paths[push] ? paths : [paths]
+ var idOrDoneIsDone = idOrDone && idOrDone.call
+ , done = idOrDoneIsDone ? idOrDone : optDone
+ , id = idOrDoneIsDone ? paths.join('') : idOrDone
+ , queue = paths.length
+ function loopFn(item) {
+ return item.call ? item() : list[item]
+ }
+ function callback() {
+ if (!--queue) {
+ list[id] = 1
+ done && done()
+ for (var dset in delay) {
+ every(dset.split('|'), loopFn) && !each(delay[dset], loopFn) && (delay[dset] = [])
+ }
+ }
+ }
+ setTimeout(function () {
+ each(paths, function (path) {
+ if (scripts[path]) {
+ id && (ids[id] = 1)
+ return scripts[path] == 2 && callback()
+ }
+ scripts[path] = 1
+ id && (ids[id] = 1)
+ create(!validBase.test(path) && scriptpath ? scriptpath + path + '.js' : path, callback)
+ })
+ }, 0)
+ return $script
+ }
+
+ function create(path, fn) {
+ var el = doc.createElement('script')
+ , loaded = f
+ el.onload = el.onerror = el[onreadystatechange] = function () {
+ if ((el[readyState] && !(/^c|loade/.test(el[readyState]))) || loaded) return;
+ el.onload = el[onreadystatechange] = null
+ loaded = 1
+ scripts[path] = 2
+ fn()
+ }
+ el.async = 1
+ el.src = path
+ head.insertBefore(el, head.firstChild)
+ }
+
+ $script.get = create
+
+ $script.order = function (scripts, id, done) {
+ (function callback(s) {
+ s = scripts.shift()
+ if (!scripts.length) $script(s, id, done)
+ else $script(s, callback)
+ }())
+ }
+
+ $script.path = function (p) {
+ scriptpath = p
+ }
+ $script.ready = function (deps, ready, req) {
+ deps = deps[push] ? deps : [deps]
+ var missing = [];
+ !each(deps, function (dep) {
+ list[dep] || missing[push](dep);
+ }) && every(deps, function (dep) {return list[dep]}) ?
+ ready() : !function (key) {
+ delay[key] = delay[key] || []
+ delay[key][push](ready)
+ req && req(missing)
+ }(deps.join('|'))
+ return $script
+ }
+ return $script
+}, this);
+
+
+/**
+ * @license AngularJS
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * License: MIT
+ */
+(function(window, document) {
+
+ var filename = /^(.*\/)angular-bootstrap.js(#.*)?$/,
+ scripts = document.getElementsByTagName("SCRIPT"),
+ serverPath,
+ match,
+ globalVars = {},
+ IGNORE = {
+ innerHeight: true, innerWidth: true,
+ onkeyup: true, onkeydown: true, onresize: true,
+ event: true, frames: true, external: true,
+ sessionStorage: true, clipboardData: true, localStorage: true};
+
+ for(var j = 0; j < scripts.length; j++) {
+ match = (scripts[j].src || "").match(filename);
+ if (match) {
+ serverPath = match[1];
+ }
+ }
+
+ document.write('');
+
+ $script.path(serverPath+'../');
+ $script('angularFiles', function() {
+ var index = 0,
+ scripts = angularFiles.angularSrc;
+
+ try { delete window.angularFiles; } catch(e) { window.angularFiles = undefined; }
+ // initialize the window property cache
+ for (var prop in window) {
+ if (IGNORE[prop] || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
+ continue;
+ }
+ try {
+ globalVars[key(prop)] = window[prop];
+ } catch(e) {} //ignore properties that throw exception when accessed (common in FF)
+ }
+
+ (function next() {
+ if (index < scripts.length) {
+ var file = scripts[index++],
+ last = index == scripts.length,
+ name = last ? 'angular' : file;
+
+ $script(file.replace(/\.js$/, ''), name, function() {
+ angularClobberTest(file);
+ next();
+ });
+ } else {
+ // empty the cache to prevent mem leaks
+ globalVars = {};
+
+ bindJQuery();
+ publishExternalAPI(window.angular);
+
+ angularInit(document, angular.bootstrap);
+ }
+ })();
+ });
+
+ function key(prop) {
+ return "ng-clobber_" + prop;
+ }
+
+ function angularClobberTest(file) {
+ var varKey, prop,
+ clobbered = {};
+
+ for (prop in window) {
+ varKey = key(prop);
+
+ if (IGNORE[prop] || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
+ continue;
+ } else if (!globalVars.hasOwnProperty(varKey)) {
+ //console.log('new global variable found: ', prop);
+ try {
+ globalVars[varKey] = window[prop];
+ } catch(e) {} //ignore properties that throw exception when accessed (common in FF)
+ } else if (globalVars[varKey] !== window[prop] && !isActuallyNaN(window[prop]) && prop != 'jqLite') {
+ clobbered[prop] = true;
+ console.error("Global variable clobbered by script " + file + "! Variable name: " + prop);
+ globalVars[varKey] = window[prop];
+ }
+ }
+ for (varKey in globalVars) {
+ prop = varKey.substr(11);
+ if (prop === 'event' || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
+ continue;
+ }
+ if (!clobbered[prop] &&
+ prop != 'event' &&
+ prop != 'jqLite' &&
+ !isActuallyNaN(globalVars[varKey]) &&
+ globalVars[varKey] !== window[prop]) {
+
+ delete globalVars[varKey];
+ console.warn("Global variable unexpectedly deleted in script " + file + "! " +
+ "Variable name: " + prop);
+ }
+ }
+
+ function isActuallyNaN(val) {
+ return (typeof val === 'number') && isNaN(val);
+ }
+ };
+})(window, document);
+
diff --git a/src/angular.suffix b/src/angular.suffix
index c86200bb31f4..1292c703ec0e 100644
--- a/src/angular.suffix
+++ b/src/angular.suffix
@@ -1,11 +1 @@
- //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);
diff --git a/src/apis.js b/src/apis.js
index 0e94e2a55ce2..d041f0815c15 100644
--- a/src/apis.js
+++ b/src/apis.js
@@ -33,10 +33,14 @@ function hashKey(obj) {
/**
* HashMap which can use objects as keys
+ *
+ * @constructor
+ * @param {(Object|Array)=} initMap Map of key/value data for HashMap initialization.
*/
-function HashMap(array){
- forEach(array, this.put, this);
+function HashMap(initMap) {
+ forEach(initMap, this.put, this);
}
+
HashMap.prototype = {
/**
* Store key value pair
@@ -68,9 +72,10 @@ HashMap.prototype = {
/**
* A map where multiple values can be added to the same key such that they form a queue.
- * @returns {HashQueueMap}
+ * @constructor
*/
function HashQueueMap() {}
+
HashQueueMap.prototype = {
/**
* Same as array push, but using an array as the value for the hash
diff --git a/src/auto/injector.js b/src/auto/injector.js
index 70160fc566b4..9046f8e8a4ea 100644
--- a/src/auto/injector.js
+++ b/src/auto/injector.js
@@ -144,7 +144,7 @@ function annotate(fn) {
* @description
* Invoke the method and supply the method arguments from the `$injector`.
*
- * @param {!function} fn The function to invoke. The function arguments come form the function annotation.
+ * @param {!Function} fn The function to invoke. The function arguments come form the function annotation.
* @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.
@@ -159,7 +159,7 @@ function annotate(fn) {
* 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 {!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`.
@@ -238,7 +238,7 @@ function annotate(fn) {
* ).toEqual(['$compile', '$rootScope']);
*
*
- * @param {function|Array.} fn Function for which dependent service names need to be retrieved as described
+ * @param {Function|Array.} fn Function for which dependent service names need to be retrieved as described
* above.
*
* @returns {Array.} The names of the services which the function requires.
@@ -394,7 +394,10 @@ function annotate(fn) {
* decorated or delegated to.
*/
-
+/**
+ * @param {Array.} modulesToLoad
+ * @return {ng.Injector}
+ */
function createInjector(modulesToLoad) {
var INSTANTIATING = {},
providerSuffix = 'Provider',
@@ -417,7 +420,7 @@ function createInjector(modulesToLoad) {
instanceCache = {},
instanceInjector = (instanceCache.$injector =
createInternalInjector(instanceCache, function(servicename) {
- var provider = providerInjector.get(servicename + providerSuffix);
+ var provider = /** @type {!ng.Provider} */(providerInjector.get(servicename + providerSuffix));
return instanceInjector.invoke(provider.$get, provider);
}));
@@ -430,6 +433,11 @@ function createInjector(modulesToLoad) {
// $provider
////////////////////////////////////
+ /**
+ * @template T
+ * @param {function(...[?]):T} delegate
+ * @return {function((string|Object), *):(T|undefined)}
+ */
function supportObject(delegate) {
return function(key, value) {
if (isObject(key)) {
@@ -440,14 +448,21 @@ function createInjector(modulesToLoad) {
}
}
+ /**
+ * @param {!string} name
+ * @param {!(ng.Provider|Function|Array)} provider_
+ * @return {ng.Provider}}
+ */
function provider(name, provider_) {
if (isFunction(provider_) || isArray(provider_)) {
- provider_ = providerInjector.instantiate(provider_);
+ provider_ = /** @type {ng.Provider}*/(
+ providerInjector.instantiate(/** @type {ng.Injectable}*/(provider_))
+ );
}
if (!provider_.$get) {
throw Error('Provider ' + name + ' must define $get factory method.');
}
- return providerCache[name + providerSuffix] = provider_;
+ return providerCache[name + providerSuffix] = /** @type {ng.Provider}*/(provider_);
}
function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); }
@@ -466,12 +481,12 @@ function createInjector(modulesToLoad) {
}
function decorator(serviceName, decorFn) {
- var origProvider = providerInjector.get(serviceName + providerSuffix),
+ var origProvider = /** @type {ng.Provider}*/(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});
+ return instanceInjector.invoke(decorFn, undefined, {$delegate: origInstance});
};
}
@@ -523,6 +538,11 @@ function createInjector(modulesToLoad) {
// internal Injector
////////////////////////////////////
+ /**
+ * @param cache
+ * @param factory
+ * @return {ng.Injector}
+ */
function createInternalInjector(cache, factory) {
function getService(serviceName) {
@@ -583,12 +603,15 @@ function createInjector(modulesToLoad) {
}
function instantiate(Type, locals) {
- var Constructor = function() {},
- instance, returnedValue;
+ /**
+ * @constructor
+ */
+ var Constructor = function() {};
Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
- instance = new Constructor();
- returnedValue = invoke(Type, instance, locals);
+
+ var instance = new Constructor();
+ var returnedValue = invoke(Type, instance, locals);
return isObject(returnedValue) ? returnedValue : instance;
}
@@ -601,3 +624,44 @@ function createInjector(modulesToLoad) {
};
}
}
+
+
+/**
+ * @typedef {{
+ * invoke: function(ng.Injectable, !Object=, !Object=):*,
+ * instantiate: function(ng.Injectable, !Object=):*,
+ * get: function(!string):*,
+ * annotate: function(!Function):!Array.
+ * }}
+ */
+ng.Injector;
+
+/**
+ * @typedef {{
+ * $get: function():*
+ * }}
+ */
+ng.Provider;
+
+
+/**
+ * @typedef {!(Function|Array.)}
+ */
+ng.Injectable;
+
+
+/**
+ * @typedef {{
+ * requires: !Array.,
+ * invokeQueue: !Array.>,
+ *
+ * service: function(!string, ng.Injectable):ng.Module,
+ * factory: function(!string, ng.Injectable):ng.Module,
+ * value: function(!string, *):ng.Module,
+ *
+ * filter: function(!string, ng.Injectable):ng.Module,
+ *
+ * init: function(ng.Injectable):ng.Module
+ * }}
+ */
+ng.Module;
diff --git a/src/jqLite.js b/src/jqLite.js
index 1d92f2ab0d55..dc3dfb23c33b 100644
--- a/src/jqLite.js
+++ b/src/jqLite.js
@@ -59,7 +59,7 @@
* - [val()](http://api.jquery.com/val/)
* - [wrap()](http://api.jquery.com/wrap/)
*
- * ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:
+ * ## In addition to the above, Angular provides additional methods to both jQuery and jQuery lite:
*
* - `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
@@ -71,17 +71,49 @@
* - `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.
+ * @param {string|Element} element HTML string or Element 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
+
+/////////////////////////////////////////////
+
+/**
+ * @constructor
+ */
+function JQLite(element) {
+ if (element instanceof JQLite) {
+ return element;
+ }
+ if (!(this instanceof JQLite)) {
+ if (isString(element) && element.charAt(0) != '<') {
+ throw Error('selectors not implemented');
+ }
+ 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 = '
' + element; // IE insanity to make NoScope elements work!
+ div.removeChild(div.firstChild); // remove the superfluous div
+ JQLiteAddNodes(this, div.childNodes);
+ this.remove(); // detach the elements from the temporary DOM div.
+ } else {
+ JQLiteAddNodes(this, element);
+ }
+}
+
+/////////////////////////////////////////////
+
+var jqCache = JQLite.cache = {};
+var jqName = JQLite.expando = 'ng-' + new Date().getTime();
+var jqId = 1;
+var 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.attachEvent('on' + type, fn);});
+var removeEventListenerFn = (window.document.removeEventListener
? function(element, type, fn) {element.removeEventListener(type, fn, false); }
: function(element, type, fn) {element.detachEvent('on' + type, fn); });
@@ -112,7 +144,12 @@ function camelCase(name) {
//
/////////////////////////////////////////////
-function JQLitePatchJQueryRemove(name, dispatchThis) {
+/**
+ * @param {!string} name
+ * @param {!boolean=} fireEventOnMainElement if the $destroy event should be fired on the
+ * current element of the method call.
+ */
+function JQLitePatchJQueryRemove(name, fireEventOnMainElement) {
var originalJqFn = jQuery.fn[name];
originalJqFn = originalJqFn.$original || originalJqFn;
removePatch.$original = originalJqFn;
@@ -120,7 +157,7 @@ function JQLitePatchJQueryRemove(name, dispatchThis) {
function removePatch() {
var list = [this],
- fireEvent = dispatchThis,
+ fireEvent = fireEventOnMainElement,
set, setIndex, setLength,
element, childIndex, childLength, children,
fns, events;
@@ -132,7 +169,7 @@ function JQLitePatchJQueryRemove(name, dispatchThis) {
if (fireEvent) {
element.triggerHandler('$destroy');
} else {
- fireEvent = !fireEvent;
+ fireEvent = !fireEvent; // skip the main element and then fire on children
}
for(childIndex = 0, childLength = (children = element.children()).length;
childIndex < childLength;
@@ -145,56 +182,91 @@ function JQLitePatchJQueryRemove(name, dispatchThis) {
}
}
-/////////////////////////////////////////////
-function JQLite(element) {
- if (element instanceof JQLite) {
- return element;
- }
- if (!(this instanceof JQLite)) {
- if (isString(element) && element.charAt(0) != '<') {
- throw Error('selectors not implemented');
- }
- 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 = '
' + element; // IE insanity to make NoScope elements work!
- div.removeChild(div.firstChild); // remove the superfluous div
- JQLiteAddNodes(this, div.childNodes);
- this.remove(); // detach the elements from the temporary DOM div.
- } else {
- JQLiteAddNodes(this, element);
- }
+/**
+ * @param {!Node} node
+ * @return {!Node}
+ */
+function JQLiteClone(node) {
+ return /** @type {!Node} */(node.cloneNode(true));
}
-function JQLiteClone(element) {
- return element.cloneNode(true);
-}
-function JQLiteDealoc(element){
- JQLiteRemoveData(element);
- for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
+/**
+ * @param {!Node} node
+ */
+function JQLiteDealoc(node){
+ JQLiteRemoveData(node);
+ for ( var i = 0, children = node.childNodes || []; i < children.length; i++) {
JQLiteDealoc(children[i]);
}
}
-function JQLiteUnbind(element, type, fn) {
- var events = JQLiteExpandoStore(element, 'events'),
- handle = JQLiteExpandoStore(element, 'handle');
+
+/**
+ * @param {!Node} node
+ * @param {!string} type
+ * @param {!Function} fn
+ */
+function JQLiteBind(node, type, fn){
+ var events = JQLiteExpandoStore(node, 'events'),
+ handle = JQLiteExpandoStore(node, 'handle');
+
+ if (!events) JQLiteExpandoStore(node, 'events', events = {});
+ if (!handle) JQLiteExpandoStore(node, 'handle', handle = createEventHandler(node, events));
+
+ forEach(type.split(' '), function(type){
+ var eventFns = events[type];
+
+ if (!eventFns) {
+ if (type == 'mouseenter' || type == 'mouseleave') {
+ var counter = 0;
+
+ events.mouseenter = [];
+ events.mouseleave = [];
+
+ JQLiteBind(node, 'mouseover', function(event) {
+ counter++;
+ if (counter == 1) {
+ handle(event, 'mouseenter');
+ }
+ });
+ JQLiteBind(node, 'mouseout', function(event) {
+ counter --;
+ if (counter == 0) {
+ handle(event, 'mouseleave');
+ }
+ });
+ } else {
+ addEventListenerFn(node, type, handle);
+ events[type] = [];
+ }
+ eventFns = events[type]
+ }
+ eventFns.push(fn);
+ });
+}
+
+
+/**
+ * @param {!Node} node
+ * @param {!string=} type
+ * @param {!Function=} fn
+ */
+function JQLiteUnbind(node, type, fn) {
+ var events = JQLiteExpandoStore(node, 'events'),
+ handle = JQLiteExpandoStore(node, 'handle');
if (!handle) return; //no listeners registered
if (isUndefined(type)) {
forEach(events, function(eventHandler, type) {
- removeEventListenerFn(element, type, eventHandler);
+ removeEventListenerFn(node, type, eventHandler);
delete events[type];
});
} else {
if (isUndefined(fn)) {
- removeEventListenerFn(element, type, events[type]);
+ removeEventListenerFn(node, type, events[type]);
delete events[type];
} else {
arrayRemove(events[type], fn);
@@ -202,27 +274,160 @@ function JQLiteUnbind(element, type, fn) {
}
}
-function JQLiteRemoveData(element) {
- var expandoId = element[jqName],
+
+/**
+ * @param {!Element} element
+ * @param {!string} eventName
+ */
+function JQLiteTriggerHandler(element, eventName) {
+ var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];
+
+ forEach(eventFns, function(fn) {
+ fn.call(element, null);
+ });
+}
+
+
+/**
+ * @param {!Node} origNode
+ * @param {!Node} replaceNode
+ */
+function JQLiteReplaceWith(origNode, replaceNode) {
+ var index, parent = origNode.parentNode;
+ JQLiteDealoc(origNode);
+ forEach(new JQLite(replaceNode), function(node){
+ if (index) {
+ parent.insertBefore(node, index.nextSibling);
+ } else {
+ parent.replaceChild(node, origNode);
+ }
+ index = node;
+ });
+}
+
+
+/**
+ * @param {!Element} element
+ * @param {!Node} node
+ */
+function JQLiteAppend(element, node) {
+ forEach(new JQLite(node), function(child){
+ if (element.nodeType === 1 || element.nodeType === 11) {
+ element.appendChild(child);
+ }
+ });
+}
+
+
+/**
+ * @param {!Element} element
+ * @param {!Node} node
+ */
+function JQLitePrepend(element, node) {
+ if (element.nodeType === 1) {
+ var index = element.firstChild;
+ forEach(new JQLite(node), function(child){
+ if (index) {
+ element.insertBefore(child, index);
+ } else {
+ element.appendChild(child);
+ index = child;
+ }
+ });
+ }
+}
+
+
+/**
+ * @param {!Element} element
+ * @param {!Element} wrapElement
+ */
+function JQLiteWrap(element, wrapElement) {
+ wrapElement = jqLite(wrapElement)[0];
+ var parent = element.parentNode;
+ if (parent) {
+ parent.replaceChild(wrapElement, element);
+ }
+ wrapElement.appendChild(element);
+}
+
+
+/**
+ * @param {!Node} node
+ */
+function JQLiteRemove(node) {
+ JQLiteDealoc(node);
+ var parent = node.parentNode;
+ if (parent) parent.removeChild(node);
+}
+
+
+/**
+ * @param {!Node} origNode
+ * @param {!Node} newNode
+ */
+function JQLiteAfter(origNode, newNode) {
+ var index = origNode, parent = origNode.parentNode;
+ forEach(new JQLite(newNode), function(node){
+ parent.insertBefore(node, index.nextSibling);
+ index = node;
+ });
+}
+
+
+/**
+ * @param {!Element} element
+ * @return {!Array.}
+ */
+function JQLiteChildren(element) {
+ var children = [];
+ forEach(element.childNodes, function(element){
+ if (element.nodeType === 1)
+ children.push(element);
+ });
+ return children;
+}
+
+
+/**
+ * @param {!Element} element
+ * @return {!NodeList|!Array}
+ */
+function JQLiteContents(element) {
+ return element.childNodes || [];
+}
+
+
+/**
+ * @param {!Node} node
+ */
+function JQLiteRemoveData(node) {
+ var expandoId = node[jqName],
expandoStore = jqCache[expandoId];
if (expandoStore) {
if (expandoStore.handle) {
expandoStore.events.$destroy && expandoStore.handle({}, '$destroy');
- JQLiteUnbind(element);
+ JQLiteUnbind(node);
}
delete jqCache[expandoId];
- element[jqName] = undefined; // ie does not allow deletion of attributes on elements.
+ node[jqName] = undefined; // ie does not allow deletion of attributes on elements.
}
}
-function JQLiteExpandoStore(element, key, value) {
- var expandoId = element[jqName],
+
+/**
+ * @param {!Node} node
+ * @param {!string} key
+ * @param {*=} value
+ */
+function JQLiteExpandoStore(node, key, value) {
+ var expandoId = node[jqName],
expandoStore = jqCache[expandoId || -1];
if (isDefined(value)) {
if (!expandoStore) {
- element[jqName] = expandoId = jqNextId();
+ node[jqName] = expandoId = jqNextId();
expandoStore = jqCache[expandoId] = {};
}
expandoStore[key] = value;
@@ -231,14 +436,21 @@ function JQLiteExpandoStore(element, key, value) {
}
}
-function JQLiteData(element, key, value) {
- var data = JQLiteExpandoStore(element, 'data'),
+
+/**
+ * @param {!Node} node
+ * @param {!(string|Object)} key
+ * @param {*=} value
+ * @return {*}
+ */
+function JQLiteData(node, key, value) {
+ var data = JQLiteExpandoStore(node, 'data'),
isSetter = isDefined(value),
keyDefined = !isSetter && isDefined(key),
isSimpleGetter = keyDefined && !isObject(key);
if (!data && !isSimpleGetter) {
- JQLiteExpandoStore(element, 'data', data = {});
+ JQLiteExpandoStore(node, 'data', data = {});
}
if (isSetter) {
@@ -249,7 +461,7 @@ function JQLiteData(element, key, value) {
// don't create data in this case.
return data && data[key];
} else {
- extend(data, key);
+ extend(data, /** @type {Object} */(key));
}
} else {
return data;
@@ -257,11 +469,171 @@ function JQLiteData(element, key, value) {
}
}
-function JQLiteHasClass(element, selector) {
+
+/**
+ * @param {!Element} element
+ * @param {!string} name
+ */
+function JQLiteRemoveAttr(element,name) {
+ element.removeAttribute(name);
+}
+
+/**
+ * @param {!Element} element
+ * @param {!string} className
+ * @return {!boolean}
+ */
+function JQLiteHasClass(element, className) {
return ((" " + element.className + " ").replace(/[\n\t]/g, " ").
- indexOf( " " + selector + " " ) > -1);
+ indexOf( " " + className + " " ) > -1);
}
+
+/**
+ * @param {!Element} element
+ * @param {!string} name
+ * @param {!string=} value
+ * @return {string|undefined}
+ */
+function JQLiteCss(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;
+ }
+}
+
+
+/**
+ * @param {!Element} element
+ * @param {!string} name
+ * @param {!(string|boolean)} value
+ * @return {(string|undefined)}
+ */
+function JQLiteAttr(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;
+ }
+}
+
+
+/**
+ * @param {!Node} element
+ * @param {!string} name
+ * @param {*=} value
+ * @return {*}
+ */
+function JQLiteProp(element, name, value) {
+ if (isDefined(value)) {
+ element[name] = value;
+ } else {
+ return element[name];
+ }
+}
+
+
+/**
+ * @param {!Node} node
+ * @param {!string=} value
+ * @return {string|undefined}
+ */
+function JQLiteTextOldIE(node, value) {
+ if (node.nodeType == 1 /** Element */) {
+ if (isUndefined(value))
+ return node.innerText;
+ node.innerText = value;
+ } else {
+ if (isUndefined(value)) return node.nodeValue;
+ node.nodeValue = /** @type {string} */(value);
+ }
+}
+
+
+/**
+ * @param {!Element} element
+ * @param {!string=} value
+ * @return {string|undefined}
+ */
+function JQLiteText(element, value) {
+ if (isUndefined(value)) {
+ return element.textContent;
+ }
+ element.textContent = value;
+}
+
+
+/**
+ * @param {!Node} element
+ * @param {!string=} value
+ * @return {*}
+ */
+function JQLiteVal(element, value) {
+ if (isUndefined(value)) {
+ return element.value;
+ }
+ element.value = value;
+}
+
+
+/**
+ * @param {!Element} element
+ * @param {!string=} value
+ * @return {string|undefined}
+ */
+function JQLiteHtml(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;
+}
+
+
+/**
+ * @param {!Element} element
+ * @param {!string} cssClasses
+ */
function JQLiteRemoveClass(element, cssClasses) {
if (cssClasses) {
forEach(cssClasses.split(' '), function(cssClass) {
@@ -274,6 +646,11 @@ function JQLiteRemoveClass(element, cssClasses) {
}
}
+
+/**
+ * @param {!Element} element
+ * @param {!string} cssClasses
+ */
function JQLiteAddClass(element, cssClasses) {
if (cssClasses) {
forEach(cssClasses.split(' '), function(cssClass) {
@@ -284,6 +661,62 @@ function JQLiteAddClass(element, cssClasses) {
}
}
+
+/**
+ * @param {!Element} element
+ * @param {!string} className
+ * @param {!boolean=} condition
+ */
+function JQLiteToggleClass(element, className, condition) {
+ if (isUndefined(condition)) {
+ condition = !JQLiteHasClass(element, className);
+ }
+ (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, className);
+}
+
+
+/**
+ * @param {!Node} node
+ * @return {Element}
+ */
+function JQLiteParent(node) {
+ var parent = node.parentNode;
+ return /** @type {Element} */(parent && parent.nodeType !== 11 ? parent : null);
+}
+
+
+/**
+ * @param {!Element} element
+ * @return {Element}
+ */
+function JQLiteNext(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 /** @type {Element} */(elm);
+}
+
+
+/**
+ * @param {!Element} element
+ * @param {!string} selector
+ * @return {!NodeList}
+ */
+function JQLiteFind(element, selector) {
+ return element.getElementsByTagName(selector);
+}
+
+
+/**
+ * @param {!JQLite} root
+ * @param {!(Element|NodeList|JQLite|Array)} elements
+ */
function JQLiteAddNodes(root, elements) {
if (elements) {
elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
@@ -295,29 +728,59 @@ function JQLiteAddNodes(root, elements) {
}
}
+/**
+ * @param {!Element} element
+ * @param {!string} name
+ * @return {!Object|undefined}
+ */
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
+/**
+ * @param {!Element} element
+ * @return {!ng.Injector}
+ */
+function JQLiteInjector(element) {
+ return JQLiteInheritedData(element, '$injector');
+}
+
+
+/**
+ * @param {!Node} node
+ * @param {string} name
+ * @param {*=} value Bogus param to make this fn look like getter/setter (fn.length === 3)
+ */
+function JQLiteInheritedData(node, name, value) {
+ var $element = jqLite(node);
+
+ // if node is the document object work with the html node instead
// this makes $(document).scope() possible
- if(element[0].nodeType == 9) {
- element = element.find('html');
+ if(node.nodeType == 9) {
+ $element = $element.find('html');
}
- while (element.length) {
- if (value = element.data(name)) return value;
- element = element.parent();
+ while ($element.length) {
+ if (value = $element.data(name)) return value;
+ $element = $element.parent();
}
}
+
+/**
+ * @param {!Element} element
+ * @return {!ng.Scope}
+ */
+function JQLiteScope(element) {
+ return JQLiteInheritedData(element, '$scope');
+}
+
//////////////////////////////////////////
// Functions which are declared directly.
//////////////////////////////////////////
-var JQLitePrototype = JQLite.prototype = {
+var JQLitePrototype = extend(JQLite.prototype, /** @lends {JQLite.prototype} */{
+
ready: function(fn) {
var fired = false;
@@ -329,7 +792,7 @@ var JQLitePrototype = JQLite.prototype = {
this.bind('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.
- JQLite(window).bind('load', trigger); // fallback to window.onload for others
+ new JQLite(window).bind('load', trigger); // fallback to window.onload for others
},
toString: function() {
var value = [];
@@ -345,7 +808,7 @@ var JQLitePrototype = JQLite.prototype = {
push: push,
sort: [].sort,
splice: [].splice
-};
+});
//////////////////////////////////////////
// Functions iterating getter/setters.
@@ -369,122 +832,36 @@ function getBooleanAttrName(element, name) {
return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
}
-forEach({
- data: JQLiteData,
- inheritedData: JQLiteInheritedData,
- scope: function(element) {
- return JQLiteInheritedData(element, '$scope');
- },
+forEach(/** @lends {JQLite.prototype} */{
- controller: JQLiteController ,
- injector: function(element) {
- return JQLiteInheritedData(element, '$injector');
- },
+ data: /** @type function(!string, *=):* */(JQLiteData),
- removeAttr: function(element,name) {
- element.removeAttribute(name);
- },
+ inheritedData: /** @type function(!string):* */(JQLiteInheritedData),
- hasClass: JQLiteHasClass,
+ scope: /** @type function():!ng.Scope */(JQLiteScope),
- css: function(element, name, value) {
- name = camelCase(name);
+ controller: /** @type function():!Object */(JQLiteController),
- if (isDefined(value)) {
- element.style[name] = value;
- } else {
- var val;
+ injector: /** @type function():!ng.Injector */(JQLiteInjector),
- 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';
- }
+ removeAttr: /** @type function(!string):undefined */(JQLiteRemoveAttr),
- val = val || element.style[name];
+ hasClass: /** @type function(!string):!boolean */(JQLiteHasClass),
- if (msie <= 8) {
- // jquery weirdness :-/
- val = (val === '') ? undefined : val;
- }
+ css: /** @type function(!string, !string):(string|undefined) */(JQLiteCss),
- return val;
- }
- },
+ attr: /** @type function(!string, !(string|boolean)=):(string|undefined) */(JQLiteAttr),
- 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: /** @type function(!string, *=):* */(JQLiteProp),
- prop: function(element, name, value) {
- if (isDefined(value)) {
- element[name] = value;
- } else {
- return element[name];
- }
- },
+ text: /** @type function(!string=):!* */(extend((msie < 9) ? JQLiteTextOldIE : JQLiteText, {$dv:''})),
- text: extend((msie < 9)
- ? function(element, value) {
- if (element.nodeType == 1 /** Element */) {
- if (isUndefined(value))
- return element.innerText;
- element.innerText = value;
- } else {
- if (isUndefined(value))
- return element.nodeValue;
- element.nodeValue = value;
- }
- }
- : function(element, value) {
- if (isUndefined(value)) {
- return element.textContent;
- }
- element.textContent = value;
- }, {$dv:''}),
+ val: /** @type function(!string=):(string|undefined) */(JQLiteVal),
- val: function(element, value) {
- if (isUndefined(value)) {
- return element.value;
- }
- element.value = value;
- },
+ html: /** @type function(!string=):(string|undefined) */(JQLiteHtml)
- html: function(element, value) {
- if (isUndefined(value)) {
- return element.innerHTML;
- }
- for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
- JQLiteDealoc(childNodes[i]);
- }
- element.innerHTML = value;
- }
}, function(fn, name){
/**
* Properties: writes return selection, reads return first value
@@ -566,9 +943,13 @@ function createEventHandler(element, events) {
// as they would cause memory leaks in IE8.
if (msie <= 8) {
// IE7/8 does not allow to delete property on native object
+ /**
+ * @type {*}
+ */
+ var releaseMem = null;
event.preventDefault = null;
event.stopPropagation = null;
- event.isDefaultPrevented = null;
+ event.isDefaultPrevented = /** @type {function (): ?} */(releaseMem);
} else {
// It shouldn't affect normal browsers (native methods are defined on prototype).
delete event.preventDefault;
@@ -585,164 +966,48 @@ function createEventHandler(element, events) {
// These functions chain results into a single
// selector.
//////////////////////////////////////////
-forEach({
- removeData: JQLiteRemoveData,
+forEach(/** @lends {JQLite.prototype} */{
- dealoc: JQLiteDealoc,
+ removeData: /** @type {function():!JQLite} */(JQLiteRemoveData),
- bind: function bindFn(element, type, fn){
- var events = JQLiteExpandoStore(element, 'events'),
- handle = JQLiteExpandoStore(element, 'handle');
+ dealoc: /** @type {function():!JQLite}*/(JQLiteDealoc),
- if (!events) JQLiteExpandoStore(element, 'events', events = {});
- if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events));
+ bind: /** @type {function(!string, !Function):!JQLite} */(JQLiteBind),
- forEach(type.split(' '), function(type){
- var eventFns = events[type];
+ unbind: /** @type {function(string=, Function=):!JQLite}*/(JQLiteUnbind),
- if (!eventFns) {
- if (type == 'mouseenter' || type == 'mouseleave') {
- var counter = 0;
+ replaceWith: /** @type {function(!Node):!JQLite} */(JQLiteReplaceWith),
- events.mouseenter = [];
- events.mouseleave = [];
+ children: /** @type {function():!JQLite} */(JQLiteChildren),
- bindFn(element, 'mouseover', function(event) {
- counter++;
- if (counter == 1) {
- handle(event, 'mouseenter');
- }
- });
- bindFn(element, 'mouseout', function(event) {
- counter --;
- if (counter == 0) {
- handle(event, 'mouseleave');
- }
- });
- } else {
- addEventListenerFn(element, type, handle);
- events[type] = [];
- }
- eventFns = events[type]
- }
- eventFns.push(fn);
- });
- },
+ contents: /** @type {function():!JQLite} */(JQLiteContents),
- unbind: JQLiteUnbind,
+ append: /** @type {function(!Node):!JQLite} */(JQLiteAppend),
- 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;
- });
- },
+ prepend: /** @type {function(!Node):!JQLite} */(JQLitePrepend),
- children: function(element) {
- var children = [];
- forEach(element.childNodes, function(element){
- if (element.nodeType === 1)
- children.push(element);
- });
- return children;
- },
+ wrap: /** @type {function(!Element):!JQLite} */(JQLiteWrap),
- contents: function(element) {
- return element.childNodes || [];
- },
+ remove: /** @type {function():!JQLite} */(JQLiteRemove),
- append: function(element, node) {
- forEach(new JQLite(node), function(child){
- if (element.nodeType === 1 || element.nodeType === 11) {
- element.appendChild(child);
- }
- });
- },
+ after: /** @type {function(!Node):!JQLite} */(JQLiteAfter),
- prepend: function(element, node) {
- if (element.nodeType === 1) {
- var index = element.firstChild;
- forEach(new JQLite(node), function(child){
- if (index) {
- element.insertBefore(child, index);
- } else {
- element.appendChild(child);
- index = child;
- }
- });
- }
- },
-
- 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: /** @type {function(!string):!JQLite}*/(JQLiteAddClass),
- addClass: JQLiteAddClass,
- removeClass: JQLiteRemoveClass,
+ removeClass: /** @type {function(!string):!JQLite}*/(JQLiteRemoveClass),
- toggleClass: function(element, selector, condition) {
- if (isUndefined(condition)) {
- condition = !JQLiteHasClass(element, selector);
- }
- (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector);
- },
+ toggleClass: /** @type {function(!string, !boolean=):!JQLite} */(JQLiteToggleClass),
- parent: function(element) {
- var parent = element.parentNode;
- return parent && parent.nodeType !== 11 ? parent : null;
- },
-
- next: function(element) {
- if (element.nextElementSibling) {
- return element.nextElementSibling;
- }
+ parent: /** @type {function():!JQLite} */(JQLiteParent),
- // IE8 doesn't have nextElementSibling
- var elm = element.nextSibling;
- while (elm != null && elm.nodeType !== 1) {
- elm = elm.nextSibling;
- }
- return elm;
- },
+ next: /** @type {function():!JQLite} */(JQLiteNext),
- find: function(element, selector) {
- return element.getElementsByTagName(selector);
- },
+ find: /** @type {function(!string):!JQLite} */(JQLiteFind),
- clone: JQLiteClone,
+ clone: /** @type {function():!JQLite}*/(JQLiteClone),
- triggerHandler: function(element, eventName) {
- var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName];
+ triggerHandler: /** @type {function(!string):!JQLite} */(JQLiteTriggerHandler)
- forEach(eventFns, function(fn) {
- fn.call(element, null);
- });
- }
}, function(fn, name){
/**
* chaining functions
diff --git a/src/loader.js b/src/loader.js
index ecb166085460..b769d26d9034 100644
--- a/src/loader.js
+++ b/src/loader.js
@@ -15,7 +15,7 @@ function setupModuleLoader(window) {
}
return ensure(ensure(window, 'angular', Object), 'module', function() {
- /** @type {Object.} */
+ /** @type {Object.} */ // TODO(i): do we want to allow null?!?
var modules = {};
/**
@@ -60,9 +60,9 @@ function setupModuleLoader(window) {
* @param {!string} name The name of the module to create or retrieve.
* @param {Array.=} 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
+ * @param {Function=} configFn Optional configuration function for the module. Same as
* {@link angular.Module#config Module#config()}.
- * @returns {module} new module with the {@link angular.Module} api.
+ * @returns {ng.Module} new module with the {@link angular.Module} api.
*/
return function module(name, requires, configFn) {
if (requires && modules.hasOwnProperty(name)) {
@@ -81,8 +81,7 @@ function setupModuleLoader(window) {
var config = invokeLater('$injector', 'invoke');
- /** @type {angular.Module} */
- var moduleInstance = {
+ var moduleInstance = /** @lends {ng.Module}*/{
// Private state
_invokeQueue: invokeQueue,
_runBlocks: runBlocks,
@@ -91,9 +90,11 @@ function setupModuleLoader(window) {
* @ngdoc property
* @name angular.Module#requires
* @propertyOf angular.Module
- * @returns {Array.} 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.
+ *
+ * @type {Array.} List of module names which must be loaded before this module.
*/
requires: requires,
@@ -101,8 +102,7 @@ function setupModuleLoader(window) {
* @ngdoc property
* @name angular.Module#name
* @propertyOf angular.Module
- * @returns {string} Name of the module.
- * @description
+ * @type {string} Name of the module.
*/
name: name,
@@ -111,10 +111,12 @@ function setupModuleLoader(window) {
* @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()}.
+ *
+ * @param {string} name service name
+ * @param {Function} providerType Construction function for creating new instance of the service.
*/
provider: invokeLater('$provide', 'provider'),
@@ -122,10 +124,12 @@ function setupModuleLoader(window) {
* @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()}.
+ *
+ * @param {string} name service name
+ * @param {Function} providerFunction Function for creating new instance of the service.
*/
factory: invokeLater('$provide', 'factory'),
@@ -133,10 +137,12 @@ function setupModuleLoader(window) {
* @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()}.
+ *
+ * @param {string} name service name
+ * @param {Function} constructor A constructor function that will be instantiated.
*/
service: invokeLater('$provide', 'service'),
@@ -144,10 +150,12 @@ function setupModuleLoader(window) {
* @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()}.
+ *
+ * @param {string} name service name
+ * @param {*} object Service instance object.
*/
value: invokeLater('$provide', 'value'),
@@ -155,11 +163,13 @@ function setupModuleLoader(window) {
* @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()}.
+ *
+ * @param {string} name constant name
+ * @param {*} object Constant value.
*/
constant: invokeLater('$provide', 'constant', 'unshift'),
@@ -167,10 +177,12 @@ function setupModuleLoader(window) {
* @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()}.
+ *
+ * @param {string} name Filter name.
+ * @param {Function} filterFactory Factory function for creating new instance of filter.
*/
filter: invokeLater('$filterProvider', 'register'),
@@ -178,10 +190,12 @@ function setupModuleLoader(window) {
* @ngdoc method
* @name angular.Module#controller
* @methodOf angular.Module
- * @param {string} name Controller name.
- * @param {Function} constructor Controller constructor function.
+ *
* @description
* See {@link ng.$controllerProvider#register $controllerProvider.register()}.
+ *
+ * @param {string} name Controller name.
+ * @param {Function} constructor Controller constructor function.
*/
controller: invokeLater('$controllerProvider', 'register'),
@@ -189,11 +203,13 @@ function setupModuleLoader(window) {
* @ngdoc method
* @name angular.Module#directive
* @methodOf angular.Module
+ *
+ * @description
+ * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
+ *
* @param {string} name directive name
* @param {Function} directiveFactory Factory function for creating new instance of
* directives.
- * @description
- * See {@link ng.$compileProvider#directive $compileProvider.directive()}.
*/
directive: invokeLater('$compileProvider', 'directive'),
@@ -201,10 +217,12 @@ function setupModuleLoader(window) {
* @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.
+ *
+ * @param {Function} configFn Execute this function on module load. Useful for service
+ * configuration.
*/
config: config,
@@ -212,14 +230,16 @@ function setupModuleLoader(window) {
* @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.
+ *
+ * @param {Function} initializationFn Execute this function after injector creation.
+ * Useful for application initialization.
*/
- run: function(block) {
- runBlocks.push(block);
+ run: function(initializationFn) {
+ runBlocks.push(initializationFn);
return this;
}
};
@@ -233,17 +253,17 @@ function setupModuleLoader(window) {
/**
* @param {string} provider
* @param {string} method
- * @param {String=} insertMethod
- * @returns {angular.Module}
+ * @param {string=} insertMethod
+ * @returns {function(...[*]):ng.Module}
*/
function invokeLater(provider, method, insertMethod) {
return function() {
- invokeQueue[insertMethod || 'push']([provider, method, arguments]);
+ /** @type {Function} */(
+ /** @type {Object} */(invokeQueue)[insertMethod || 'push'])([provider, method, arguments]);
return moduleInstance;
}
}
});
};
});
-
}
diff --git a/src/ng/anchorScroll.js b/src/ng/anchorScroll.js
index 0ddc9c78af65..d19ddefd9ef9 100644
--- a/src/ng/anchorScroll.js
+++ b/src/ng/anchorScroll.js
@@ -12,6 +12,8 @@
*
* It also watches the `$location.hash()` and scroll whenever it changes to match any anchor.
* This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
+ *
+ * @constructor
*/
function $AnchorScrollProvider() {
diff --git a/src/ng/browser.js b/src/ng/browser.js
index fa050d54511f..4a6878ca4094 100644
--- a/src/ng/browser.js
+++ b/src/ng/browser.js
@@ -15,12 +15,13 @@
* 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
+ * @param {Object} window The global window object.
+ * @param {Object} document jQuery wrapped document.
+ * @param {Object} $log console.log or an object with the same interface.
+ * @param {Object} $sniffer $sniffer service
+ * @constructor
*/
function Browser(window, document, $log, $sniffer) {
var self = this,
@@ -105,12 +106,11 @@ function Browser(window, document, $log, $sniffer) {
};
/**
- * @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.
+ *
+ * @param {number} interval How often should browser call poll functions (ms)
+ * @param {function(function(), number=)} setTimeout Reference to a real or fake `setTimeout` fn.
*/
function startPoller(interval, setTimeout) {
(function check() {
@@ -143,7 +143,7 @@ function Browser(window, document, $log, $sniffer) {
* 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 {string=} url New url (when used as setter)
* @param {boolean=} replace Should new url replace current history record ?
*/
self.url = function(url, replace) {
@@ -205,7 +205,7 @@ function Browser(window, document, $log, $sniffer) {
* @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) {
+ self.onUrlChange = function(listener) {
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
@@ -221,8 +221,8 @@ function Browser(window, document, $log, $sniffer) {
urlChangeInit = true;
}
- urlChangeListeners.push(callback);
- return callback;
+ urlChangeListeners.push(listener);
+ return listener;
};
//////////////////////////////////////////////////////////////
@@ -230,10 +230,7 @@ function Browser(window, document, $log, $sniffer) {
//////////////////////////////////////////////////////////////
/**
- * Returns current
- * (always relative - without domain)
- *
- * @returns {string=}
+ * @returns {string|undefined} Returns current (always relative - without domain)
*/
self.baseHref = function() {
var href = baseElement.attr('href');
@@ -251,9 +248,6 @@ function Browser(window, document, $log, $sniffer) {
* @name ng.$browser#cookies
* @methodOf ng.$browser
*
- * @param {string=} name Cookie name
- * @param {string=} value Cokkie 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.
@@ -265,7 +259,9 @@ function Browser(window, document, $log, $sniffer) {
*
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)
+ * @param {string=} name Cookie name
+ * @param {(string|undefined)=} value Cookie value
+ * @returns {Object|undefined} Hash of all cookies (if called without any parameter)
*/
self.cookies = function(name, value) {
var cookieLength, cookieArray, cookie, i, index;
@@ -355,6 +351,10 @@ function Browser(window, document, $log, $sniffer) {
}
+
+/**
+ * @constructor
+ */
function $BrowserProvider(){
this.$get = ['$window', '$log', '$sniffer', '$document',
function( $window, $log, $sniffer, $document){
diff --git a/src/ng/cacheFactory.js b/src/ng/cacheFactory.js
index ce690ebfe2a4..08a54c50e2b9 100644
--- a/src/ng/cacheFactory.js
+++ b/src/ng/cacheFactory.js
@@ -5,15 +5,14 @@
* @description
* Factory that constructs cache objects.
*
- *
* @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:
+ * @returns {Object} Newly created cache object with the following set of methods:
*
- * - `{object}` `info()` — Returns id, size, and options of cache.
+ * - `{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.
@@ -21,6 +20,10 @@
* - `{void}` `destroy()` — Removes references to this cache from $cacheFactory.
*
*/
+
+/**
+ * @constructor
+ */
function $CacheFactoryProvider() {
this.$get = function() {
@@ -165,6 +168,10 @@ function $CacheFactoryProvider() {
* See {@link ng.$cacheFactory $cacheFactory}.
*
*/
+
+/**
+ * @constructor
+ */
function $TemplateCacheProvider() {
this.$get = ['$cacheFactory', function($cacheFactory) {
return $cacheFactory('templates');
diff --git a/src/ng/compile.js b/src/ng/compile.js
index 18adc2c9eff7..3c787b2b2d39 100644
--- a/src/ng/compile.js
+++ b/src/ng/compile.js
@@ -92,11 +92,11 @@ var NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';
*
*
- * @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 {string|Element} element Element or HTML string to compile into a template function.
+ * @param {function(ng.Scope, ng.$compile.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
+ * @returns {function(ng.Scope, ng.$compile.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.
@@ -145,11 +145,9 @@ var NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: ';
/**
* @ngdoc service
* @name ng.$compileProvider
- * @function
*
- * @description
+ * @constructor
*/
-$CompileProvider.$inject = ['$provide'];
function $CompileProvider($provide) {
var hasDirectives = {},
Suffix = 'Directive',
@@ -167,11 +165,11 @@ function $CompileProvider($provide) {
* @description
* Register a new directives with the compiler.
*
- * @param {string} name Name of the directive in camel-case. (ie ngBind which will match as
+ * @param {!(string|Object)} name Name of the directive in camel-case. (ie ngBind which will match as
* ng-bind).
- * @param {function} directiveFactory An injectable directive factroy function. See {@link guide/directive} for more
+ * @param {!Function} directiveFactory An injectable directive factory function. See {@link guide/directive} for more
* info.
- * @returns {ng.$compileProvider} Self for chaining.
+ * @returns {$CompileProvider} Returns self for method chaining.
*/
this.directive = function registerDirective(name, directiveFactory) {
if (isString(name)) {
@@ -203,7 +201,8 @@ function $CompileProvider($provide) {
}
hasDirectives[name].push(directiveFactory);
} else {
- forEach(name, reverseParams(registerDirective));
+ forEach(/** @type {Object.}*/(name),
+ reverseParams(/** @type {function(!(string|number), !Function):$CompileProvider} */(registerDirective)));
}
return this;
};
@@ -215,7 +214,13 @@ function $CompileProvider($provide) {
function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
$controller, $rootScope) {
- var Attributes = function(element, attr) {
+
+ /**
+ * @param {!JQLite=} element Element the attributes belong to.
+ * @param {Object=} attr Initial attribute values.
+ * @constructor
+ */
+ var Attributes = function Attributes(element, attr) {
this.$$element = element;
this.$attr = attr || {};
};
@@ -228,10 +233,11 @@ function $CompileProvider($provide) {
* 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 {string|boolean|undefined|null} value The value to set. If `null` or `undefined`
+ * 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.
+ * @param {string=} attrName Optional denormalized attribute name. Defaults to key.
*/
$set: function(key, value, writeAttr, attrName) {
var booleanKey = getBooleanAttrName(this.$$element[0], key),
@@ -258,7 +264,9 @@ function $CompileProvider($provide) {
if (value === null || value === undefined) {
this.$$element.removeAttr(attrName);
} else {
- this.$$element.attr(attrName, value);
+ /** @type {JQLite} */
+ var e = this.$$element;
+ e.attr(attrName, value);
}
}
@@ -310,6 +318,12 @@ function $CompileProvider($provide) {
//================================
+ /**
+ * @param {!JQLite} $compileNodes
+ * @param transcludeFn
+ * @param {!number=} maxPriority
+ * @return {Function}
+ */
function compile($compileNodes, transcludeFn, maxPriority) {
if (!($compileNodes instanceof jqLite)) {
// jquery always rewraps, where as we need to preserve the original selector so that we can modify it.
@@ -358,13 +372,14 @@ function $CompileProvider($provide) {
* function, which is the a linking function for the node.
*
* @param {NodeList} nodeList an array of nodes to compile
- * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the
+ * @param {function(ng.Scope, ng.$compile.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
+ * @param {!JQLite=} $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.
+ * @param {number=} maxPriority Up to what priority directives should be evaluated.
+ * @returns {?ng.$compile.compositeLinkFn} A composite linking function of all of the matched
+ * directives or null.
*/
function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {
var linkFns = [],
@@ -393,6 +408,9 @@ function $CompileProvider($provide) {
// return a linking function if we have found anything, null otherwise
return linkFnFound ? compositeLinkFn : null;
+ /**
+ * @type {ng.$compile.compositeLinkFn}
+ */
function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;
@@ -520,13 +538,13 @@ function $CompileProvider($provide) {
* 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.
+ * @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
+ * @param {!Node} compileNode The raw DOM node to apply the compile functions to
+ * @param {!Object} templateAttrs The shared attribute function
+ * @param {!function(ng.Scope, ng.$compile.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 we are working on the root of the compile tree then this
+ * @param {!JQLite=} $rootElement If we are working on the root of the compile tree then this
* argument has the root jqLite array so that we can replace widgets on it.
* @returns linkFn
*/
@@ -584,7 +602,7 @@ function $CompileProvider($provide) {
$compileNode = templateAttrs.$$element =
jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));
compileNode = $compileNode[0];
- replaceWith($rootElement, jqLite($template[0]), compileNode);
+ replaceWith(/** @type {!JQLite} */($rootElement), jqLite($template[0]), compileNode);
childTranscludeFn = compile($template, transcludeFn, terminalPriority);
} else {
$template = jqLite(JQLiteClone(compileNode)).contents();
@@ -608,7 +626,7 @@ function $CompileProvider($provide) {
throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);
}
- replaceWith($rootElement, $compileNode, compileNode);
+ replaceWith(/** @type {!JQLite} */($rootElement), $compileNode, compileNode);
var newTemplateAttrs = {$attr: {}};
@@ -833,6 +851,7 @@ function $CompileProvider($provide) {
* looks up the directive and decorates it with exception handling and proper parameters. We
* call this the boundDirective.
*
+ * @param {Array} tDirectives Array of directives found in the template.
* @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:
@@ -841,6 +860,7 @@ function $CompileProvider($provide) {
* * `A': attribute
* * `C`: class
* * `M`: comment
+ * @param {!number=} maxPriority Up to what priority the directives should be evaluated.
* @returns true if directive was added.
*/
function addDirective(tDirectives, name, location, maxPriority) {
@@ -867,8 +887,8 @@ function $CompileProvider($provide) {
* 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)
+ * @param {Object} dst destination attributes (original DOM)
+ * @param {Object} src source attributes (from the directive template)
*/
function mergeTemplateAttributes(dst, src) {
var srcAttr = src.$attr,
@@ -1048,11 +1068,11 @@ function $CompileProvider($provide) {
* 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} $element 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.
+ * @param {!JQLite} $rootElement The root of the compile tree. Used so that
+ * we can replace nodes in the root of the tree.
+ * @param {!JQLite} $element 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, $element, newNode) {
var oldNode = $element[0],
@@ -1078,6 +1098,12 @@ function $CompileProvider($provide) {
}];
}
+/**
+ * @type {Array.}
+ */
+$CompileProvider.$inject = ['$provide'];
+
+
var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i;
/**
* Converts all accepted directives format into proper directive name.
@@ -1110,7 +1136,7 @@ function directiveNormalize(name) {
* @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
+ * @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.
*/
@@ -1138,7 +1164,7 @@ function directiveNormalize(name) {
*/
function nodesetLinkingFn(
- /* angular.Scope */ scope,
+ /* ng.Scope */ scope,
/* NodeList */ nodeList,
/* Element */ rootElement,
/* function(Function) */ boundTranscludeFn
@@ -1146,8 +1172,23 @@ function nodesetLinkingFn(
function directiveLinkingFn(
/* nodesetLinkingFn */ nodesetLinkingFn,
- /* angular.Scope */ scope,
+ /* ng.Scope */ scope,
/* Node */ node,
/* Element */ rootElement,
/* function(Function) */ boundTranscludeFn
){}
+
+
+ng.$compile = {};
+
+/**
+ * @typedef {function(Element, ng.Scope):undefined}
+ */
+ng.$compile.cloneAttachFn;
+
+
+/**
+ * @typedef {function(!ng.Scope, !NodeList, !JQLite, !Function=)}
+ * scope, nodeList, $rootElement, boundTranscludeFn
+ */
+ng.$compile.compositeLinkFn;
diff --git a/src/ng/controller.js b/src/ng/controller.js
index e2f1b6ac7ce3..1fedffa8953e 100644
--- a/src/ng/controller.js
+++ b/src/ng/controller.js
@@ -9,6 +9,8 @@
*
* This provider allows controller registration via the
* {@link ng.$controllerProvider#register register} method.
+ *
+ * @constructor
*/
function $ControllerProvider() {
var controllers = {};
@@ -18,13 +20,13 @@ function $ControllerProvider() {
* @ngdoc function
* @name ng.$controllerProvider#register
* @methodOf ng.$controllerProvider
- * @param {string} name Controller name
+ * @param {string|Object.} name Controller name
* @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI
* annotations in the array notation).
*/
this.register = function(name, constructor) {
if (isObject(name)) {
- extend(controllers, name)
+ extend(controllers, /** @type Object */(name))
} else {
controllers[name] = constructor;
}
@@ -58,7 +60,7 @@ function $ControllerProvider() {
*/
return function(constructor, locals) {
if(isString(constructor)) {
- var name = constructor;
+ var name = /** @type {string} */(constructor);
constructor = controllers.hasOwnProperty(name)
? controllers[name]
: getter(locals.$scope, name, true) || getter($window, name, true);
diff --git a/src/ng/directive/booleanAttrs.js b/src/ng/directive/booleanAttrs.js
index 2d1278cddb1c..44b43c668e75 100644
--- a/src/ng/directive/booleanAttrs.js
+++ b/src/ng/directive/booleanAttrs.js
@@ -304,6 +304,9 @@
* @param {string} expression Angular expression that will be evaluated.
*/
+/**
+ * @type {Object}
+ */
var ngAttributeAliasDirectives = {};
diff --git a/src/ng/directive/form.js b/src/ng/directive/form.js
index 36b775cb3b40..b08fd2927f48 100644
--- a/src/ng/directive/form.js
+++ b/src/ng/directive/form.js
@@ -13,27 +13,25 @@ var nullFormCtrl = {
* @ngdoc object
* @name ng.directive:form.FormController
*
+ * @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`.
+ *
* @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) — such as `required`, `url` or `email`),
* - values are arrays of controls or forms that are invalid with given error.
*
- * @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`.
- *
+ * @constructor
*/
-//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,
@@ -54,7 +52,11 @@ function FormController(element, attrs) {
element.addClass(PRISTINE_CLASS);
toggleValidCss(true);
- // convenience method for easy toggling of classes
+ /**
+ * Convenience method for easy toggling of classes
+ * @param {boolean} isValid
+ * @param {string=} validationErrorKey
+ */
function toggleValidCss(isValid, validationErrorKey) {
validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
element.
@@ -151,6 +153,10 @@ function FormController(element, attrs) {
};
}
+//asks for $scope to fool the BC controller module
+FormController.$inject = ['$element', '$attrs', '$scope'];
+
+
/**
* @ngdoc directive
@@ -257,6 +263,11 @@ function FormController(element, attrs) {
*/
+
+/**
+ * @param {boolean=} isNgForm
+ * @return {Array}
+ */
var formDirectiveFactory = function(isNgForm) {
return ['$timeout', function($timeout) {
var formDirective = {
diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js
index aaabd1033398..61f407bc0b0b 100644
--- a/src/ng/directive/input.js
+++ b/src/ng/directive/input.js
@@ -5,374 +5,11 @@ var EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/;
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 trimming the
- * input.
- *
- * @example
-
-
-
-
-
-
- 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');
- });
-
-
- */
'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 then `min`.
- * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.
- * @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
-
-
-
-
-
-
- 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');
- });
-
-
- */
'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
-
-
-
-
-
-
- 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');
- });
-
-
- */
'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.
- *
- * @example
-
-
-
-
-
-
- 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');
- });
-
-
- */
'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
-
-
-
-
-
-
- it('should change state', function() {
- expect(binding('color')).toEqual('blue');
-
- input('color').select('red');
- expect(binding('color')).toEqual('red');
- });
-
-
- */
'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
-
-
-
-
-
-
- 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');
- });
-
-
- */
'checkbox': checkboxInputType,
'hidden': noop,
@@ -387,7 +24,81 @@ function isEmpty(value) {
}
-function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
+/**
+ * @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 trimming the
+ * input.
+ *
+ * @example
+
+
+
+
+
+
+ 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');
+ });
+
+
+ */
+ng.textInputType;
+
+function textInputType(scope, element, /** @type {ng.InputAttrs} */attr, ctrl, $sniffer, $browser) {
var listener = function() {
var value = element.val();
@@ -507,6 +218,77 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
}
}
+
+/**
+ * @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 then `min`.
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater then `min`.
+ * @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
+
+
+
+
+
+
+ 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');
+ });
+
+
+ */
+ng.numberInputType;
+
function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
textInputType(scope, element, attr, ctrl, $sniffer, $browser);
@@ -569,6 +351,74 @@ function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
});
}
+
+/**
+ * @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
+
+
+
+
+
+
+ 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');
+ });
+
+
+ */
+ng.urlInputType;
+
function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
textInputType(scope, element, attr, ctrl, $sniffer, $browser);
@@ -586,6 +436,72 @@ function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) {
ctrl.$parsers.push(urlValidator);
}
+
+/**
+ * @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.
+ *
+ * @example
+
+
+
+
+
+
+ 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');
+ });
+
+
+ */
+ng.emailInputType;
+
function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
textInputType(scope, element, attr, ctrl, $sniffer, $browser);
@@ -603,6 +519,47 @@ function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {
ctrl.$parsers.push(emailValidator);
}
+
+/**
+ * @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
+
+
+
+
+
+
+ it('should change state', function() {
+ expect(binding('color')).toEqual('blue');
+
+ input('color').select('red');
+ expect(binding('color')).toEqual('red');
+ });
+
+
+ */
+ng.radioInputType;
+
function radioInputType(scope, element, attr, ctrl) {
// make the name unique, if not defined
if (isUndefined(attr.name)) {
@@ -625,6 +582,53 @@ function radioInputType(scope, element, attr, ctrl) {
attr.$observe('value', ctrl.$render);
}
+
+/**
+ * @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
+
+
+
+
+
+
+ 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');
+ });
+
+
+ */
+ng.checkboxInputType;
+
function checkboxInputType(scope, element, attr, ctrl) {
var trueValue = attr.ngTrueValue,
falseValue = attr.ngFalseValue;
@@ -775,6 +779,8 @@ function checkboxInputType(scope, element, attr, ctrl) {
*/
+ng.inputDirective;
+
var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {
return {
restrict: 'E',
@@ -929,7 +935,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
$element.addClass(PRISTINE_CLASS);
toggleValidCss(true);
- // convenience method for easy toggling of classes
+ /**
+ * Convenience method for easy toggling of classes
+ * @param {boolean} isValid
+ * @param {string=} validationErrorKey
+ */
function toggleValidCss(isValid, validationErrorKey) {
validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : '';
$element.
@@ -1248,6 +1258,8 @@ var requiredDirective = function() {
*/
+ng.ngListDirective;
+
var ngListDirective = function() {
return {
require: 'ngModel',
@@ -1300,3 +1312,9 @@ var ngValueDirective = function() {
}
};
};
+
+
+/**
+ * @typedef {{ngFalseValue, ngTrueValue, ngPattern, ngTrim}}
+ */
+ng.InputAttrs;
diff --git a/src/ng/directive/ngBind.js b/src/ng/directive/ngBind.js
index 0c99f27ddaeb..d74e363d69ab 100644
--- a/src/ng/directive/ngBind.js
+++ b/src/ng/directive/ngBind.js
@@ -22,7 +22,7 @@
*
*
* @element ANY
- * @param {expression} ngBind {@link guide/expression Expression} to evaluate.
+ * @param {string} 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.
@@ -47,6 +47,8 @@
*/
+ng.ngBindDirective;
+
var ngBindDirective = ngDirective(function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBind);
scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
@@ -102,6 +104,8 @@ var ngBindDirective = ngDirective(function(scope, element, attr) {
*/
+ng.ngBindTemplateDirective;
+
var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
return function(scope, element, attr) {
// TODO: move this to scenario runner
@@ -127,13 +131,15 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
* See {@link ngSanitize.$sanitize $sanitize} docs for examples.
*
* @element ANY
- * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.
+ * @param {string} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate.
*/
-var ngBindHtmlUnsafeDirective = [function() {
+ng.ngBindHtmlUnsafeDirective;
+
+var ngBindHtmlUnsafeDirective = function() {
return function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);
scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) {
element.html(value || '');
});
};
-}];
+};
diff --git a/src/ng/directive/ngClass.js b/src/ng/directive/ngClass.js
index 79c55d7abdd6..f1139566c372 100644
--- a/src/ng/directive/ngClass.js
+++ b/src/ng/directive/ngClass.js
@@ -69,7 +69,7 @@ function classDirective(name, selector) {
* new classes are added.
*
* @element ANY
- * @param {expression} ngClass {@link guide/expression Expression} to eval. The result
+ * @param {string} 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.
*
@@ -119,7 +119,7 @@ var ngClassDirective = classDirective('', true);
* {@link ng.directive:ngRepeat ngRepeat}.
*
* @element ANY
- * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result
+ * @param {string} 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
@@ -166,7 +166,7 @@ var ngClassOddDirective = classDirective('Odd', 0);
* {@link ng.directive:ngRepeat ngRepeat}.
*
* @element ANY
- * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The
+ * @param {string} 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
diff --git a/src/ng/directive/ngCloak.js b/src/ng/directive/ngCloak.js
index baa7afa8b71f..02dc52f91573 100644
--- a/src/ng/directive/ngCloak.js
+++ b/src/ng/directive/ngCloak.js
@@ -10,7 +10,7 @@
* directive to avoid the undesirable flicker effect caused by the html template display.
*
* The directive can be applied to the `` element, but typically a fine-grained application is
- * prefered in order to benefit from progressive rendering of the browser view.
+ * preferred in order to benefit from progressive rendering of the browser view.
*
* `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and
* `angular.min.js` files. Following is the css rule:
diff --git a/src/ng/directive/ngController.js b/src/ng/directive/ngController.js
index b6619d319426..c38b59dcf408 100644
--- a/src/ng/directive/ngController.js
+++ b/src/ng/directive/ngController.js
@@ -20,7 +20,7 @@
*
* @element ANY
* @scope
- * @param {expression} ngController Name of a globally accessible constructor function or an
+ * @param {string} ngController Name of a globally accessible constructor function or an
* {@link guide/expression expression} that on the current scope evaluates to a
* constructor function.
*
@@ -95,9 +95,11 @@
*/
-var ngControllerDirective = [function() {
+ng.ngController;
+
+var ngControllerDirective = function() {
return {
scope: true,
controller: '@'
};
-}];
+};
diff --git a/src/ng/directive/ngEventDirs.js b/src/ng/directive/ngEventDirs.js
index e2aedd7ff509..9a9a17adf370 100644
--- a/src/ng/directive/ngEventDirs.js
+++ b/src/ng/directive/ngEventDirs.js
@@ -9,7 +9,7 @@
* element is clicked.
*
* @element ANY
- * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon
+ * @param {string} ngClick {@link guide/expression Expression} to evaluate upon
* click. (Event object is available as `$event`)
*
* @example
@@ -29,6 +29,8 @@
*/
+ng.ngClick;
+
/*
* A directive that allows creation of custom onclick handlers that are defined as angular
* expressions and are compiled and executed within the current scope.
@@ -93,7 +95,7 @@ forEach(
* Specify custom behavior on mouseup event.
*
* @element ANY
- * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon
+ * @param {string} ngMouseup {@link guide/expression Expression} to evaluate upon
* mouseup. (Event object is available as `$event`)
*
* @example
@@ -207,7 +209,7 @@ forEach(
* server and reloading the current page).
*
* @element form
- * @param {expression} ngSubmit {@link guide/expression Expression} to eval.
+ * @param {string} ngSubmit {@link guide/expression Expression} to eval.
*
* @example
diff --git a/src/ng/directive/ngInclude.js b/src/ng/directive/ngInclude.js
index d4eacbe3e0af..0954bef6f379 100644
--- a/src/ng/directive/ngInclude.js
+++ b/src/ng/directive/ngInclude.js
@@ -83,7 +83,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
return {
restrict: 'ECA',
terminal: true,
- compile: function(element, attr) {
+ compile: function(element, /** @type {ng.ngIncludeAttrs;}*/ attr) {
var srcExp = attr.ngInclude || attr.src,
onloadExp = attr.onload || '',
autoScrollExp = attr.autoscroll;
@@ -129,3 +129,9 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
}
};
}];
+
+
+/**
+ * @typedef {{autoscroll}}
+ */
+ng.ngIncludeAttrs;
diff --git a/src/ng/directive/ngInit.js b/src/ng/directive/ngInit.js
index d157f3967d51..a3ca84403cf0 100644
--- a/src/ng/directive/ngInit.js
+++ b/src/ng/directive/ngInit.js
@@ -9,7 +9,7 @@
* before the template enters execution mode during bootstrap.
*
* @element ANY
- * @param {expression} ngInit {@link guide/expression Expression} to eval.
+ * @param {string} ngInit {@link guide/expression Expression} to eval.
*
* @example
diff --git a/src/ng/directive/ngPluralize.js b/src/ng/directive/ngPluralize.js
index 3938d4e39378..d7135942266d 100644
--- a/src/ng/directive/ngPluralize.js
+++ b/src/ng/directive/ngPluralize.js
@@ -86,7 +86,7 @@
* 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} count The variable to be bounded to.
* @param {string} when The mapping between plural category to its correspoding strings.
* @param {number=} offset Offset to deduct from the total number.
*
@@ -169,6 +169,9 @@
*/
+ng.ngPluralize;
+
+
var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) {
var BRACE = /{}/g;
return {
diff --git a/src/ng/directive/ngRepeat.js b/src/ng/directive/ngRepeat.js
index c59fefacc956..851746294f97 100644
--- a/src/ng/directive/ngRepeat.js
+++ b/src/ng/directive/ngRepeat.js
@@ -20,7 +20,7 @@
* @element ANY
* @scope
* @priority 1000
- * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. Two
+ * @param {string} ngRepeat An expression indicating how to enumerate a collection. Two
* formats are currently supported:
*
* * `variable in expression` – where variable is the user defined loop variable and `expression`
diff --git a/src/ng/directive/ngShowHide.js b/src/ng/directive/ngShowHide.js
index 74195468915b..03b8e7b2582f 100644
--- a/src/ng/directive/ngShowHide.js
+++ b/src/ng/directive/ngShowHide.js
@@ -9,7 +9,7 @@
* conditionally.
*
* @element ANY
- * @param {expression} ngShow If the {@link guide/expression expression} is truthy
+ * @param {string} ngShow If the {@link guide/expression expression} is truthy
* then the element is shown or hidden respectively.
*
* @example
@@ -49,7 +49,7 @@ var ngShowDirective = ngDirective(function(scope, element, attr){
* conditionally.
*
* @element ANY
- * @param {expression} ngHide If the {@link guide/expression expression} is truthy then
+ * @param {string} ngHide If the {@link guide/expression expression} is truthy then
* the element is shown or hidden respectively.
*
* @example
diff --git a/src/ng/directive/ngStyle.js b/src/ng/directive/ngStyle.js
index a1c2b699ebb4..9eb77afe47cf 100644
--- a/src/ng/directive/ngStyle.js
+++ b/src/ng/directive/ngStyle.js
@@ -8,7 +8,7 @@
* 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
+ * @param {string} 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.
*
diff --git a/src/ng/directive/ngSwitch.js b/src/ng/directive/ngSwitch.js
index 24c6047ac809..e9bcdc1e81c2 100644
--- a/src/ng/directive/ngSwitch.js
+++ b/src/ng/directive/ngSwitch.js
@@ -1,5 +1,7 @@
'use strict';
+var NG_SWITCH = 'ng-switch';
+
/**
* @ngdoc directive
* @name ng.directive:ngSwitch
@@ -8,11 +10,22 @@
* @description
* Conditionally change the DOM structure.
*
- * @usageContent
- * ...
- * ...
- * ...
- * ...
+ * @usage
+ *
+ * ...
+ * ...
+ * ...
+ * ...
+ *
+ *
+ * or
+ *
+ *
+ * ...
+ * ...
+ * ...
+ * ...
+ *
*
* @scope
* @param {*} ngSwitch|on expression to match against ng-switch-when.
@@ -59,14 +72,13 @@
*/
-var NG_SWITCH = 'ng-switch';
var ngSwitchDirective = valueFn({
restrict: 'EA',
require: 'ngSwitch',
- controller: function ngSwitchController() {
+ controller: /** @constructor */function ngSwitchController() {
this.cases = {};
},
- link: function(scope, element, attr, ctrl) {
+ link: function(scope, element, /** @type {ng.ngSwitch} */attr, ctrl) {
var watchExpr = attr.ngSwitch || attr.on,
selectedTransclude,
selectedElement,
@@ -111,3 +123,8 @@ var ngSwitchDefaultDirective = ngDirective({
};
}
});
+
+/**
+ * @typedef {{on, change, ngSwitch}}
+ */
+ng.ngSwitchAttrs;
diff --git a/src/ng/directive/script.js b/src/ng/directive/script.js
index 16bd7d15b7d9..b75b92ae89ee 100644
--- a/src/ng/directive/script.js
+++ b/src/ng/directive/script.js
@@ -8,8 +8,8 @@
* 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.
*
- * @restrict E
- * @param {'text/ng-template'} type must be set to `'text/ng-template'`
+ * @restrict A
+ * @param {string} type must be set to `'text/ng-template'`
*
* @example
@@ -28,7 +28,15 @@
});
+ *
+ * @usage
+
*/
+ng.scriptDirective;
+
var scriptDirective = ['$templateCache', function($templateCache) {
return {
restrict: 'E',
diff --git a/src/ng/directive/select.js b/src/ng/directive/select.js
index d82bd139c3b2..934381c7094b 100644
--- a/src/ng/directive/select.js
+++ b/src/ng/directive/select.js
@@ -32,7 +32,7 @@
* @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:
+ * @param {string=} ngOptions collection comprehension expression in one of the following forms:
*
* * for array data sources:
* * `label` **`for`** `value` **`in`** `array`
diff --git a/src/ng/document.js b/src/ng/document.js
index f1f2d334ff7b..c454aa21414c 100644
--- a/src/ng/document.js
+++ b/src/ng/document.js
@@ -8,6 +8,8 @@
* @description
* A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document`
* element.
+ *
+ * @constructor
*/
function $DocumentProvider(){
this.$get = ['$window', function(window){
diff --git a/src/ng/exceptionHandler.js b/src/ng/exceptionHandler.js
index f74e09eead3a..84c35fa349ca 100644
--- a/src/ng/exceptionHandler.js
+++ b/src/ng/exceptionHandler.js
@@ -1,26 +1,30 @@
'use strict';
/**
- * @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.
- *
- * @param {Error} exception Exception associated with the error.
- * @param {string=} cause optional information about the context in which
- * the error was thrown.
- *
+ * @constructor
*/
function $ExceptionHandlerProvider() {
- this.$get = ['$log', function($log){
- return function(exception, cause) {
+ this.$get = ['$log', function($log) {
+
+ /**
+ * @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.
+ *
+ * @param {Error} exception Exception associated with the error.
+ * @param {string=} cause optional information about the context in which
+ * the error was thrown.
+ *
+ */
+ return function $exceptionHandler(exception, cause) {
$log.error.apply($log, arguments);
};
}];
diff --git a/src/ng/filter.js b/src/ng/filter.js
index e3ccb72ee2b6..89d23e2b3d0f 100644
--- a/src/ng/filter.js
+++ b/src/ng/filter.js
@@ -48,6 +48,7 @@
* {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer
* Guide.
*/
+
/**
* @ngdoc method
* @name ng.$filterProvider#register
@@ -55,8 +56,8 @@
* @description
* Register filter factory function.
*
- * @param {String} name Name of the filter.
- * @param {function} fn The filter factory function which is injectable.
+ * @param {string} name Name of the filter.
+ * @param {Function} fn The filter factory function which is injectable.
*/
@@ -71,11 +72,17 @@
*
* {{ expression | [ filter_name ] }}
*
- * @param {String} name Name of the filter function to retrieve
+ * @param {string} name Name of the filter function to retrieve
* @return {Function} the filter function
*/
-$FilterProvider.$inject = ['$provide'];
-function $FilterProvider($provide) {
+ng.$Filter;
+
+var $FilterProvider = ['$provide',
+ /**
+ * @constructor
+ * @param $provide
+ */
+ function $FilterProvider_($provide) {
var suffix = 'Filter';
function register(name, factory) {
@@ -91,13 +98,13 @@ function $FilterProvider($provide) {
////////////////////////////////////////
- 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);
-}
+ register('currency', currencyFilterFactory);
+ register('date', dateFilterFactory);
+ register('filter', filterFilterFactory);
+ register('json', jsonFilterFactory);
+ register('limitTo', limitToFilterFactory);
+ register('lowercase', lowercaseFilterFactory);
+ register('number', numberFilterFactory);
+ register('orderBy', orderByFilterFactory);
+ register('uppercase', uppercaseFilterFactory);
+}];
diff --git a/src/ng/filter/filter.js b/src/ng/filter/filter.js
index 467f6699f394..93a0d70287d8 100644
--- a/src/ng/filter/filter.js
+++ b/src/ng/filter/filter.js
@@ -1,86 +1,87 @@
'use strict';
-/**
- * @ngdoc filter
- * @name ng.filter:filter
- * @function
- *
- * @description
- * Selects a subset of items from `array` and returns it as a new array.
- *
- * Note: This function is used to augment the `Array` type in Angular expressions. See
- * {@link ng.$filter} for more information about Angular arrays.
- *
- * @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.
- *
- * @example
-
-
-
+function filterFilterFactory() {
- Search:
-
-
Name
Phone
-
-
{{friend.name}}
-
{{friend.phone}}
-
-
-
- Any:
- Name only
- Phone only
-
-
Name
Phone
-
-
{{friend.name}}
-
{{friend.phone}}
-
-
-
-
- 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']);
+ /**
+ * @ngdoc filter
+ * @name ng.filter:filter
+ * @function
+ *
+ * @description
+ * Selects a subset of items from `array` and returns it as a new array.
+ *
+ * Note: This function is used to augment the `Array` type in Angular expressions. See
+ * {@link ng.$filter} for more information about Angular arrays.
+ *
+ * @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.
+ *
+ * @example
+
+
+
- input('searchText').enter('76');
- expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')).
- toEqual(['John', 'Julie']);
- });
+ Search:
+
+
Name
Phone
+
+
{{friend.name}}
+
{{friend.phone}}
+
+
+
+ Any:
+ Name only
+ Phone only
+
+
Name
Phone
+
+
{{friend.name}}
+
{{friend.phone}}
+
+
+
+
+ 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']);
- 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']);
- });
-
-
- */
-function filterFilter() {
+ 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']);
+ });
+
+
+ */
return function(array, expression) {
if (!(array instanceof Array)) return array;
var predicates = [];
diff --git a/src/ng/filter/filters.js b/src/ng/filter/filters.js
index 4680a30681e4..b165b56fbf1b 100644
--- a/src/ng/filter/filters.js
+++ b/src/ng/filter/filters.js
@@ -1,71 +1,75 @@
'use strict';
-/**
- * @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
-
-
-
-
+
+
+ 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)');
+ });
+
+
+ */
+ return function currencyFilter(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=2] Number of decimal places to round the number to.
- * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
- *
- * @example
+
+var numberFilterFactory = ['$locale', function numberFilterFactory_($locale) {
+ var formats = $locale.NUMBER_FORMATS;
+
+ /**
+ * @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=2] Number of decimal places to round the number to.
+ * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit.
+ *
+ * @example
-
-
-
- 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');
- });
+function limitToFilterFactory() {
+ /**
+ * @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`.
+ *
+ * Note: This function is used to augment the `Array` type in Angular expressions. See
+ * {@link ng.$filter} for more information about Angular arrays.
+ *
+ * @template T
+ * @param {T} 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 {!T} A new sub-array or substring of length `limit` or less if input array
+ * had less than `limit` elements.
+ *
+ * @example
+
+
+
+
+
+
+ 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 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');
- });
-
-
- */
-function limitToFilter(){
- return function(input, limit) {
+ 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');
+ });
+
+
+ */
+ return function limitToFilter(input, limit) {
if (!isArray(input) && !isString(input)) return input;
-
+
limit = int(limit);
if (isString(input)) {
diff --git a/src/ng/filter/orderBy.js b/src/ng/filter/orderBy.js
index 93f3f5a6977d..d654f8216269 100644
--- a/src/ng/filter/orderBy.js
+++ b/src/ng/filter/orderBy.js
@@ -1,97 +1,98 @@
'use strict';
-/**
- * @ngdoc function
- * @name ng.filter:orderBy
- * @function
- *
- * @description
- * Orders a specified `array` by the `expression` predicate.
- *
- * Note: this function is used to augment the `Array` type in Angular expressions. See
- * {@link ng.$filter} for more informaton about Angular arrays.
- *
- * @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
-
-
-
-
-
-
- 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']);
- });
+var orderByFilterFactory = ['$parse', function orderByFilterFact($parse){
- 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']);
+ /**
+ * @ngdoc function
+ * @name ng.filter:orderBy
+ * @function
+ *
+ * @description
+ * Orders a specified `array` by the `expression` predicate.
+ *
+ * Note: this function is used to augment the `Array` type in Angular expressions. See
+ * {@link ng.$filter} for more informaton about Angular arrays.
+ *
+ * @template T
+ * @param {Array.} array The array to sort.
+ * @param {function(T):number|string|Array.<(function(T):number|string)>} sortPredicate 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=} reverseOrder Reverse the order the array.
+ * @returns {Array.} Sorted copy of the source array.
+ *
+ * @example
+
+
+
+
+
+
+ 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']);
+ });
- 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']);
- });
-
-
- */
-orderByFilter.$inject = ['$parse'];
-function orderByFilter($parse){
- return function(array, sortPredicate, reverseOrder) {
+ 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']);
+ });
+
+
+ */
+ return function orderByFilter(array, sortPredicate, reverseOrder) {
if (!(array instanceof Array)) return array;
if (!sortPredicate) return array;
- sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate];
+ sortPredicate = /** @type {!Array} */ (isArray(sortPredicate) ? sortPredicate: [sortPredicate]);
sortPredicate = map(sortPredicate, function(predicate){
var descending = false, get = predicate || identity;
if (isString(predicate)) {
@@ -134,4 +135,4 @@ function orderByFilter($parse){
}
}
}
-}
+}];
diff --git a/src/ng/http.js b/src/ng/http.js
index 65d2ee5debd2..c79b492bd29b 100644
--- a/src/ng/http.js
+++ b/src/ng/http.js
@@ -72,7 +72,7 @@ function isSameDomain(requestUrl, locationUrl) {
* Headers are lazy parsed when first requested.
* @see parseHeaders
*
- * @param {(string|Object)} headers Headers to provide access to.
+ * @param {string} 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
@@ -81,6 +81,9 @@ function isSameDomain(requestUrl, locationUrl) {
function headersGetter(headers) {
var headersObj = isObject(headers) ? headers : undefined;
+ /**
+ * @param {string=} name The header name.
+ */
return function(name) {
if (!headersObj) headersObj = parseHeaders(headers);
@@ -100,12 +103,12 @@ function headersGetter(headers) {
*
* @param {*} data Data to transform.
* @param {function(string=)} headers Http headers getter fn.
- * @param {(function|Array.)} fns Function or an array of functions.
+ * @param {(Function|Array.)} fns Function or an array of functions.
* @returns {*} Transformed data.
*/
function transformData(data, headers, fns) {
if (isFunction(fns))
- return fns(data, headers);
+ return /** @type {Function} */(fns)(data, headers);
forEach(fns, function(fn) {
data = fn(data, headers);
@@ -120,6 +123,9 @@ function isSuccess(status) {
}
+/**
+ * @constructor
+ */
function $HttpProvider() {
var JSON_START = /^\s*(\[|\{[^\{])/,
JSON_END = /[\}\]]\s*$/,
@@ -132,7 +138,7 @@ function $HttpProvider() {
// strip json vulnerability protection prefix
data = data.replace(PROTECTION_PREFIX, '');
if (JSON_START.test(data) && JSON_END.test(data))
- data = fromJson(data, true);
+ data = fromJson(data);
}
return data;
}],
@@ -403,7 +409,7 @@ function $HttpProvider() {
* 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
+ * @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)
@@ -431,7 +437,7 @@ function $HttpProvider() {
* - **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
+ * @returns {ng.$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
@@ -687,6 +693,9 @@ function $HttpProvider() {
return $http;
+ /**
+ * @param {...string} names
+ */
function createShortMethods(names) {
forEach(arguments, function(name) {
$http[name] = function(url, config) {
@@ -699,7 +708,10 @@ function $HttpProvider() {
}
- function createShortMethodsWithData(name) {
+ /**
+ * @param {...string} names
+ */
+ function createShortMethodsWithData(names) {
forEach(arguments, function(name) {
$http[name] = function(url, data, config) {
return $http(extend(config || {}, {
@@ -828,3 +840,13 @@ function $HttpProvider() {
}];
}
+
+
+/**
+ * @typedef {{
+ * then: Function,
+ * success: Function,
+ * error: Function
+ * }}
+ */
+ng.$HttpPromise;
diff --git a/src/ng/httpBackend.js b/src/ng/httpBackend.js
index bca46ee1a939..d344a1fd9ffc 100644
--- a/src/ng/httpBackend.js
+++ b/src/ng/httpBackend.js
@@ -22,6 +22,8 @@ var XHR = window.XMLHttpRequest || function() {
*
* During testing this implementation is swapped with {@link ngMock.$httpBackend mock
* $httpBackend} which can be trained with responses.
+ *
+ * @constructor
*/
function $HttpBackendProvider() {
this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) {
@@ -89,6 +91,12 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
}
+ /**
+ * @param {Function} callback
+ * @param {number} status
+ * @param {string=} response
+ * @param {string=} headersString
+ */
function completeRequest(callback, status, response, headersString) {
// URL_MATCH is defined in src/service/location.js
var protocol = (url.match(URL_MATCH) || ['', locationProtocol])[1];
diff --git a/src/ng/interpolate.js b/src/ng/interpolate.js
index dcf05d778f3e..bfe45f2bb09d 100644
--- a/src/ng/interpolate.js
+++ b/src/ng/interpolate.js
@@ -6,8 +6,9 @@
* @function
*
* @description
- *
* Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
+ *
+ * @constructor
*/
function $InterpolateProvider() {
var startSymbol = '{{';
@@ -21,7 +22,7 @@ function $InterpolateProvider() {
* 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.
+ * @returns {string|$InterpolateProvider} Returns the symbol when used as getter and self if used as setter.
*/
this.startSymbol = function(value){
if (value) {
@@ -40,7 +41,7 @@ function $InterpolateProvider() {
* 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.
+ * @returns {string|$InterpolateProvider} Returns the symbol when used as getter and self if used as setter.
*/
this.endSymbol = function(value){
if (value) {
@@ -81,8 +82,8 @@ function $InterpolateProvider() {
* @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.
- * @returns {function(context)} an interpolation function which is used to compute the interpolated
+ * embedded expression will return undefined instead of an interpolation function.
+ * @returns {function(ng.Scope)|undefined} 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
@@ -123,11 +124,11 @@ function $InterpolateProvider() {
if (!mustHaveExpression || hasInterpolation) {
concat.length = length;
- fn = function(context) {
+ fn = function(/** @type {ng.Scope} */scope) {
try {
for(var i = 0, ii = length, part; i=} search New search params - string or hash object
+ * @param {string|Object.=} search New search params - string or hash object
* @param {string=} paramValue If `search` is a string, then `paramValue` will override only a
* single search parameter. If the value is `null`, the parameter will be deleted.
*
- * @return {string} search
+ * @return {string|ng.core.Location} search
*/
search: function(search, paramValue) {
if (isUndefined(search))
@@ -358,7 +366,7 @@ LocationUrl.prototype = {
this.$$search[search] = paramValue;
}
} else {
- this.$$search = isString(search) ? parseKeyValue(search) : search;
+ this.$$search = isString(search) ? parseKeyValue(/** @type {string} */(search)) : search;
}
this.$$compose();
@@ -399,6 +407,11 @@ LocationUrl.prototype = {
LocationHashbangUrl.prototype = inherit(LocationUrl.prototype);
+/**
+ * @constructor
+ * @implements {ng.core.Location}
+ * @extends {LocationHashbangUrl}
+ */
function LocationHashbangInHtml5Url(url, hashPrefix, appBaseUrl, baseExtra) {
LocationHashbangUrl.apply(this, arguments);
@@ -466,6 +479,8 @@ function locationGetterSetter(property, preprocess) {
* @name ng.$locationProvider
* @description
* Use the `$locationProvider` to configure how the application deep linking paths are stored.
+ *
+ * @constructor
*/
function $LocationProvider(){
var hashPrefix = '',
@@ -480,7 +495,7 @@ function $LocationProvider(){
* @returns {*} current value if used as getter or itself (chaining) if used as setter
*/
this.hashPrefix = function(prefix) {
- if (isDefined(prefix)) {
+ if (prefix !== undefined) {
hashPrefix = prefix;
return this;
} else {
@@ -616,3 +631,89 @@ function $LocationProvider(){
}
}];
}
+
+
+ng.core = {};
+
+/**
+ * @interface
+ */
+ng.core.Location = function() {};
+
+
+/**
+ * @protected
+ * @param {!string} url
+ */
+ng.core.Location.$$parse = function(url) {};
+
+
+/**
+ * @protected
+ */
+ng.core.Location.$$compose = function() {};
+
+
+/**
+ * @protected
+ */
+ng.core.Location.$$replace;
+
+
+/**
+ * @return {!string} full url
+ */
+ng.core.Location.absUrl = function() {};
+
+
+/**
+ * @param {string=} url
+ * @return {ng.core.Location} url
+ */
+ng.core.Location.url = function(url) {};
+
+
+/**
+ * @return {!string} protocol of current url
+ */
+ng.core.Location.protocol = function() {};
+
+
+/**
+ * @return {!string}
+ */
+ng.core.Location.host = function() {};
+
+
+/**
+ * @return {!number}
+ */
+ng.core.Location.port = function() {};
+
+
+/**
+ * @param {string=} path
+ * @return {string}
+ */
+ng.core.Location.path = function(path) {};
+
+
+/**
+ * @param {!(string|Object.)=} search
+ * @param {!string=} paramValue
+ * @return {!(string|ng.core.Location)}
+ */
+ng.core.Location.search = function(search, paramValue) {};
+
+
+/**
+ * @param {!string=} hash New hash fragment
+ * @return {!string} hash
+ */
+ng.core.Location.hash = function(hash) {};
+
+
+/**
+ * @return {!ng.core.Location}
+ */
+ng.core.Location.replace = function() {};
diff --git a/src/ng/log.js b/src/ng/log.js
index 2a58d442399a..39f01fa4bcaa 100644
--- a/src/ng/log.js
+++ b/src/ng/log.js
@@ -38,11 +38,13 @@
* @name ng.$logProvider
* @description
* Use the `$logProvider` to configure how the application logs messages
+ *
+ * @constructor
*/
function $LogProvider(){
var debug = true,
self = this;
-
+
/**
* @ngdoc property
* @name ng.$logProvider#debugEnabled
@@ -59,7 +61,7 @@ function $LogProvider(){
return debug;
}
};
-
+
this.$get = ['$window', function($window){
return {
/**
@@ -101,18 +103,18 @@ function $LogProvider(){
* 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);
@@ -121,17 +123,17 @@ function $LogProvider(){
}())
};
- 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;
+ function formatError(error) {
+ if (error instanceof Error) {
+ if (error.stack) {
+ error = (error.message && error.stack.indexOf(error.message) === -1)
+ ? 'Error: ' + error.message + '\n' + error.stack
+ : error.stack;
+ } else if (error.sourceURL) {
+ error = error.message + '\n' + error.sourceURL + ':' + error['line'];
}
}
- return arg;
+ return error;
}
function consoleLog(type) {
diff --git a/src/ng/parse.js b/src/ng/parse.js
index 5a70979a7b8e..4e811e3d59ba 100644
--- a/src/ng/parse.js
+++ b/src/ng/parse.js
@@ -101,9 +101,13 @@ function lex(text, csp){
return chars.indexOf(lastCh) != -1;
}
+ /**
+ * @param {number=} [i=1]
+ * @return {?string}
+ */
function peek(i) {
var num = i || 1;
- return index + num < text.length ? text.charAt(index + num) : false;
+ return index + num < text.length ? text.charAt(index + num) : null;
}
function isNumber(ch) {
return '0' <= ch && ch <= '9';
@@ -121,6 +125,11 @@ function lex(text, csp){
return ch == '-' || ch == '+' || isNumber(ch);
}
+ /**
+ * @param {string} error
+ * @param {number=} start
+ * @param {number=} end
+ */
function throwError(error, start, end) {
end = end || index;
throw Error("Lexer Error: " + error + " at column" +
@@ -306,8 +315,12 @@ function parser(text, json, $filter, csp){
return value;
///////////////////////////////////
+ /**
+ * @param msg {string}
+ * @param token {{text: string, index: number}}
+ */
function throwError(msg, token) {
- throw Error("Syntax Error: Token '" + token.text +
+ throw new Error("Syntax Error: Token '" + token.text +
"' " + msg + " at column " +
(token.index + 1) + " of the expression [" +
text + "] starting at [" + text.substring(token.index) + "].");
@@ -319,6 +332,13 @@ function parser(text, json, $filter, csp){
return tokens[0];
}
+ /**
+ * @param {string=} e1
+ * @param {string=} e2
+ * @param {string=} e3
+ * @param {string=} e4
+ * @return {({text: string, index: number}|undefined)}
+ */
function peek(e1, e2, e3, e4) {
if (tokens.length > 0) {
var token = tokens[0];
@@ -328,9 +348,14 @@ function parser(text, json, $filter, csp){
return token;
}
}
- return false;
}
+ /**
+ * @param {string=} e1
+ * @param {string=} e2
+ * @param {string=} e3
+ * @param {string=} e4
+ */
function expect(e1, e2, e3, e4){
var token = peek(e1, e2, e3, e4);
if (token) {
@@ -540,7 +565,7 @@ function parser(text, json, $filter, csp){
context = primary;
primary = fieldAccess(primary);
} else {
- throwError("IMPOSSIBLE");
+ throwError("!!!", {}); // should never happen
}
}
return primary;
@@ -676,7 +701,7 @@ function setter(obj, path, setValue) {
* Return the value accesible 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
+ * @param {boolean=} [bindFnToScope=true]
* @returns value as accesbile by path
*/
//TODO(misko): this function needs to be removed
@@ -856,6 +881,10 @@ function getterFn(path, csp) {
* allows one to set values to expressions.
*
*/
+
+/**
+ * @constructor
+ */
function $ParseProvider() {
var cache = {};
this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
diff --git a/src/ng/q.js b/src/ng/q.js
index ef856dca6572..868c679e6439 100644
--- a/src/ng/q.js
+++ b/src/ng/q.js
@@ -123,31 +123,35 @@
* you can treat promises attached to a scope as if they were the resulting values.
* - Q has many more features that $q, but that comes at a cost of bytes. $q is tiny, but contains
* all the important functionality needed for common async tasks.
- *
+ *
* # Testing
- *
+ *
*
* 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);
* });
*
*/
+
+/**
+ * @constructor
+ */
function $QProvider() {
this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) {
@@ -161,10 +165,10 @@ function $QProvider() {
/**
* 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
+ * @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.
+ * @returns {Object} Promise manager.
*/
function qFactory(nextTick, exceptionHandler) {
@@ -175,7 +179,7 @@ function qFactory(nextTick, exceptionHandler) {
* @description
* Creates a `Deferred` object which represents a task which will finish in the future.
*
- * @returns {Deferred} Returns a new instance of deferred.
+ * @returns {ng.Deferred} Returns a new instance of deferred.
*/
var defer = function() {
var pending = [],
@@ -291,7 +295,7 @@ function qFactory(nextTick, exceptionHandler) {
*
*
* @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`.
+ * @returns {ng.Promise} Returns a promise that was already resolved as rejected with the `reason`.
*/
var reject = function(reason) {
return {
@@ -316,8 +320,8 @@ function qFactory(nextTick, exceptionHandler) {
* the promise comes from a source that can't be trusted.
*
* @param {*} value Value or a promise
- * @returns {Promise} Returns a single promise that will be resolved with an array of values,
- * each value corresponding to the promise at the same index in the `promises` array. If any of
+ * @returns {ng.Promise} Returns a single promise that will be resolved with an array of values,
+ * each value coresponding to the promise at the same index in the `promises` array. If any of
* the promises is resolved with a rejection, this resulting promise will be resolved with the
* same rejection.
*/
@@ -377,8 +381,8 @@ function qFactory(nextTick, exceptionHandler) {
* Combines multiple promises into a single promise that is resolved when all of the input
* promises are resolved.
*
- * @param {Array.} promises An array of promises.
- * @returns {Promise} Returns a single promise that will be resolved with an array of values,
+ * @param {Array.} promises An array of promises.
+ * @returns {ng.Promise} Returns a single promise that will be resolved with an array of values,
* each value corresponding to the promise at the same index in the `promises` array. If any of
* the promises is resolved with a rejection, this resulting promise will be resolved with the
* same rejection.
@@ -413,3 +417,19 @@ function qFactory(nextTick, exceptionHandler) {
all: all
};
}
+
+
+/**
+ * @typedef {{then: Function}}
+ */
+ng.Promise;
+
+
+/**
+ * @typedef {{
+ * promise: ng.Promise,
+ * resolve: function(*): undefined,
+ * reject: function(*): undefined
+ * }}
+ */
+ng.Deferred;
diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js
index 549517b66ad9..2c32ac8cc86e 100644
--- a/src/ng/rootScope.js
+++ b/src/ng/rootScope.js
@@ -58,6 +58,10 @@
* All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide
* event processing life-cycle. See {@link guide/scope developer guide on scopes}.
*/
+
+/**
+ * @constructor
+ */
function $RootScopeProvider(){
var TTL = 10;
@@ -119,14 +123,7 @@ function $RootScopeProvider(){
expect(parent.salutation).toEqual('Hello');
*
*
- *
- * @param {Object.=} providers Map of service factory which need to be provided
- * for the current scope. Defaults to {@link ng}.
- * @param {Object.=} 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.
- *
+ * @constructor
*/
function Scope() {
this.$id = nextUid();
@@ -167,12 +164,12 @@ function $RootScopeProvider(){
* 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
+ * @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.
+ * @returns {ng.Scope} The newly created child scope.
*
*/
$new: function(isolate) {
@@ -187,6 +184,10 @@ function $RootScopeProvider(){
child = new Scope();
child.$root = this.$root;
} else {
+ /**
+ * @constructor
+ * @extends {ng.Scope}
+ */
Child = function() {}; // should be anonymous; This is so that when the minifier munges
// the name it does not become random set of chars. These will then show up as class
// name in the debugger.
@@ -205,7 +206,7 @@ function $RootScopeProvider(){
} else {
this.$$childHead = this.$$childTail = child;
}
- return child;
+ return /** @type ng.Scope */ (child);
},
/**
@@ -267,14 +268,14 @@ function $RootScopeProvider(){
*
*
*
- * @param {(function()|string)} watchExpression Expression that is evaluated on each
+ * @param {(function()|string)} watchExp Expression that is evaluated on each
* {@link ng.$rootScope.Scope#$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.
+ * the `watchExp` changes.
*
* - `string`: Evaluated as {@link guide/expression expression}
* - `function(newValue, oldValue, scope)`: called with current and previous values as parameters.
@@ -507,11 +508,13 @@ function $RootScopeProvider(){
expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
*
*
- * @param {(string|function())=} expression An angular expression to be executed.
+ * @param {(string|function())} expr 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 Map of local variables to be used during expression evaluation
+ *
* @returns {*} The result of evaluating the expression.
*/
$eval: function(expr, locals) {
@@ -536,7 +539,7 @@ function $RootScopeProvider(){
* Any exceptions from the execution of the expression are forwarded to the
* {@link ng.$exceptionHandler $exceptionHandler} service.
*
- * @param {(string|function())=} expression An angular expression to be executed.
+ * @param {(string|function())} expr 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.
@@ -585,7 +588,7 @@ function $RootScopeProvider(){
* was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method.
*
*
- * @param {(string|function())=} exp An angular expression to be executed.
+ * @param {(string|function())=} expr 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.
@@ -620,7 +623,8 @@ function $RootScopeProvider(){
* event life cycle.
*
* @param {string} name Event name to listen on.
- * @param {function(event, args...)} listener Function to call when the event is emitted.
+ * @param {function((ng.ScopeBroadcastEvent|ng.ScopeEmitEvent), ...[*])} listener Function to
+ * call when the event is emitted.
* @returns {function()} Returns a deregistration function for this listener.
*
* The event listener function format is: `function(event, args...)`. The `event` object
@@ -662,21 +666,22 @@ function $RootScopeProvider(){
* 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 emmited from the {@link ng.$rootScope.Scope#$on listeners} will be passed
+ * Any exception emitted from the {@link ng.$rootScope.Scope#$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#$on}
+ * @return {ng.ScopeEmitEvent} Event object, see {@link ng.$rootScope.Scope#$on}
*/
$emit: function(name, args) {
var empty = [],
namedListeners,
scope = this,
stopPropagation = false,
+ /** @type {ng.ScopeEmitEvent} */
event = {
name: name,
- targetScope: scope,
+ targetScope: /** @type ng.Scope */(scope), // TODO(i): remove type cast
stopPropagation: function() {stopPropagation = true;},
preventDefault: function() {
event.defaultPrevented = true;
@@ -733,15 +738,16 @@ function $RootScopeProvider(){
*
* @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#$on}
+ * @return {ng.ScopeBroadcastEvent} Event object, see {@link ng.$rootScope.Scope#$on}
*/
$broadcast: function(name, args) {
var target = this,
current = target,
next = target,
+ /** @type ng.ScopeBroadcastEvent */
event = {
name: name,
- targetScope: target,
+ targetScope: /** @type ng.Scope */ (target), // TODO(i): remove type cast
preventDefault: function() {
event.defaultPrevented = true;
},
@@ -815,3 +821,43 @@ function $RootScopeProvider(){
function initWatchVal() {}
}];
}
+
+/**
+ * @typedef {{
+ * $id: string,
+ * $watch: function((function()|string), (function()|string)=, boolean=):(function():undefined),
+ * $digest: function():undefined,
+ * $apply: function((string|Function)=),
+ * $new: function(!boolean=):ng.Scope,
+ * $destroy: function():undefined,
+ * $eval: function((string|function())): *,
+ * $evalAsync: function((string|function())): undefined,
+ * $on: function(string, function((ng.ScopeBroadcastEvent|ng.ScopeEmitEvent), ...[*])):(function():undefined),
+ * $emit: function(string, ...[*]): ng.ScopeEmitEvent,
+ * $broadcast: function(string, ...[*]): ng.ScopeBroadcastEvent
+ * }}
+ */
+ng.Scope;
+
+
+/**
+ * @typedef {{
+ * name: string,
+ * targetScope: ng.Scope,
+ * preventDefault: function(): undefined,
+ * defaultPrevented: boolean
+ * }}
+ */
+ng.ScopeBroadcastEvent;
+
+
+/**
+ * @typedef {{
+ * name: string,
+ * targetScope: ng.Scope,
+ * stopPropagation: function(): undefined,
+ * preventDefault: function(): undefined,
+ * defaultPrevented: boolean
+ * }}
+ */
+ng.ScopeEmitEvent;
diff --git a/src/ng/route.js b/src/ng/route.js
index 971caa1ccbdb..f0079d8cba5e 100644
--- a/src/ng/route.js
+++ b/src/ng/route.js
@@ -7,10 +7,12 @@
* @function
*
* @description
- *
* Used for configuring routes. See {@link ng.$route $route} for an example.
+ *
+ * @constructor
*/
function $RouteProvider(){
+ /** @type Object.