diff options
Diffstat (limited to 'src/Angular.js')
| -rw-r--r-- | src/Angular.js | 588 |
1 files changed, 7 insertions, 581 deletions
diff --git a/src/Angular.js b/src/Angular.js index 97792868..d5b5144d 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -87,599 +87,25 @@ var _undefined = undefined, _ = window['_'], /** holds major version number for IE or NaN for real browsers */ msie = parseInt((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1], 10), - - /** - * @workInProgress - * @ngdoc function - * @name angular.element - * @function - * - * @description - * Wraps a raw DOM element or HTML string as [jQuery](http://jquery.com) element. - * `angular.element` is either an alias for [jQuery](http://api.jquery.com/jQuery/) function if - * jQuery is loaded or a function that wraps the element or string in angular's jQuery lite - * implementation. - * - * Real jQuery always takes precedence if it was loaded before angular. - * - * Angular's jQuery lite implementation is a tiny API-compatible subset of jQuery which allows - * angular to manipulate DOM. The functions implemented are usually just the basic versions of - * them and might not support arguments and invocation styles. - * - * NOTE: All element references in angular are always wrapped with jQuery (lite) and are never - * raw DOM references. - * - * Angular's jQuery lite implements these functions: - * - * - [addClass()](http://api.jquery.com/addClass/) - * - [after()](http://api.jquery.com/after/) - * - [append()](http://api.jquery.com/append/) - * - [attr()](http://api.jquery.com/attr/) - * - [bind()](http://api.jquery.com/bind/) - * - [children()](http://api.jquery.com/children/) - * - [clone()](http://api.jquery.com/clone/) - * - [css()](http://api.jquery.com/css/) - * - [data()](http://api.jquery.com/data/) - * - [hasClass()](http://api.jquery.com/hasClass/) - * - [parent()](http://api.jquery.com/parent/) - * - [remove()](http://api.jquery.com/remove/) - * - [removeAttr()](http://api.jquery.com/removeAttr/) - * - [removeClass()](http://api.jquery.com/removeClass/) - * - [removeData()](http://api.jquery.com/removeData/) - * - [replaceWith()](http://api.jquery.com/replaceWith/) - * - [text()](http://api.jquery.com/text/) - * - [trigger()](http://api.jquery.com/trigger/) - * - * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. - * @returns {Object} jQuery object. - */ jqLite = jQuery || jqLiteWrap, slice = Array.prototype.slice, push = Array.prototype.push, error = window[$console] ? bind(window[$console], window[$console]['error'] || noop) : noop, - /** - * @workInProgress - * @ngdoc overview - * @name angular - * @namespace The exported angular namespace. - */ angular = window[$angular] || (window[$angular] = {}), angularTextMarkup = extensionMap(angular, 'markup'), angularAttrMarkup = extensionMap(angular, 'attrMarkup'), - /** - * @workInProgress - * @ngdoc overview - * @name angular.directive - * @namespace Namespace for all directives. - * - * @description - * A directive is an HTML attribute that you can use in an existing HTML element type or in a - * DOM element type that you create as {@link angular.widget}, to modify that element's - * properties. You can use any number of directives per element. - * - * For example, you can add the ng:bind directive as an attribute of an HTML span element, as in - * `<span ng:bind="1+2"></span>`. How does this work? The compiler passes the attribute value - * `1+2` to the ng:bind extension, which in turn tells the {@link angular.scope} to watch that - * expression and report changes. On any change it sets the span text to the expression value. - * - * Here's how to define {@link angular.directive.ng:bind ng:bind}: - * <pre> - angular.directive('ng:bind', function(expression, compiledElement) { - var compiler = this; - return function(linkElement) { - var currentScope = this; - currentScope.$watch(expression, function(value) { - linkElement.text(value); - }); - }; - }); - * </pre> - * - * # Directive vs. Attribute Widget - * Both [attribute widgets](#!angular.widget) and directives can compile a DOM element - * attribute. So why have two different ways to do the same thing? The answer is that order - * matters, but we have no control over the order in which attributes are read. To solve this - * we apply attribute widget before the directive. - * - * For example, consider this piece of HTML, which uses the directives `ng:repeat`, `ng:init`, - * and `ng:bind`: - * <pre> - <ul ng:init="people=['mike', 'mary']"> - <li ng:repeat="person in people" ng:init="a=a+1" ng:bind="person"></li> - </ul> - * </pre> - * - * Notice that the order of execution matters here. We need to execute - * {@link angular.directive.ng:repeat ng:repeat} before we run the - * {@link angular.directive.ng:init ng:init} and `ng:bind` on the `<li/>;`. This is because we - * want to run the `ng:init="a=a+1` and `ng:bind="person"` once for each person in people. We - * could not have used directive to create this template because attributes are read in an - * unspecified order and there is no way of guaranteeing that the repeater attribute would - * execute first. Using the `ng:repeat` attribute directive ensures that we can transform the - * DOM element into a template. - * - * Widgets run before directives. Widgets may manipulate the DOM whereas directives are not - * expected to do so, and so they run last. - */ + /** @name angular.directive */ angularDirective = extensionMap(angular, 'directive'), - - /** - * @workInProgress - * @ngdoc overview - * @name angular.widget - * @namespace Namespace for all widgets. - * @description - * # Overview - * Widgets allow you to create DOM elements that the browser doesn't - * already understand. You create the widget in your namespace and - * assign it behavior. You can only bind one widget per DOM element - * (unlike directives, in which you can use any number per DOM - * element). Widgets are expected to manipulate the DOM tree by - * adding new elements whereas directives are expected to only modify - * element properties. - * - * Widgets come in two flavors: element and attribute. - * - * # Element Widget - * Let's say we would like to create a new element type in the - * namespace `my` that can watch an expression and alert() the user - * with each new value. - * - * <pre> - * <my:watch exp="name"/> - * </pre> - * - * You can implement `my:watch` like this: - * <pre> - * angular.widget('my:watch', function(compileElement) { - * var compiler = this; - * var exp = compileElement.attr('exp'); - * return function(linkElement) { - * var currentScope = this; - * currentScope.$watch(exp, function(value){ - * alert(value); - * }}; - * }; - * }); - * </pre> - * - * # Attribute Widget - * Let's implement the same widget, but this time as an attribute - * that can be added to any existing DOM element. - * <pre> - * <div my-watch="name">text</div> - * </pre> - * You can implement `my:watch` attribute like this: - * <pre> - * angular.widget('@my:watch', function(expression, compileElement) { - * var compiler = this; - * return function(linkElement) { - * var currentScope = this; - * currentScope.$watch(expression, function(value){ - * alert(value); - * }); - * }; - * }); - * </pre> - * - * @example - * <script> - * angular.widget('my:time', function(compileElement){ - * compileElement.css('display', 'block'); - * return function(linkElement){ - * function update(){ - * linkElement.text('Current time is: ' + new Date()); - * setTimeout(update, 1000); - * } - * update(); - * }; - * }); - * </script> - * <my:time></my:time> - */ + /** @name angular.widget */ angularWidget = extensionMap(angular, 'widget', lowercase), - - /** - * @workInProgress - * @ngdoc overview - * @name angular.validator - * @namespace Namespace for all filters. - * @description - * # Overview - * Validators are a standard way to check the user input against a specific criteria. For - * example, you might need to check that an input field contains a well-formed phone number. - * - * # Syntax - * Attach a validator on user input widgets using the `ng:validate` attribute. - * - * <doc:example> - * <doc:source> - * Change me: <input type="text" name="number" ng:validate="integer" value="123"> - * </doc:source> - * <doc:scenario> - * it('should validate the default number string', function() { - * expect(element('input[name=number]').attr('class')). - * not().toMatch(/ng-validation-error/); - * }); - * it('should not validate "foo"', function() { - * input('number').enter('foo'); - * expect(element('input[name=number]').attr('class')). - * toMatch(/ng-validation-error/); - * }); - * </doc:scenario> - * </doc:example> - * - * - * # Writing your own Validators - * Writing your own validator is easy. To make a function available as a - * validator, just define the JavaScript function on the `angular.validator` - * object. <angular/> passes in the input to validate as the first argument - * to your function. Any additional validator arguments are passed in as - * additional arguments to your function. - * - * You can use these variables in the function: - * - * * `this` — The current scope. - * * `this.$element` — The DOM element containing the binding. This allows the filter to manipulate - * the DOM in addition to transforming the input. - * - * In this example we have written a upsTrackingNo validator. - * It marks the input text "valid" only when the user enters a well-formed - * UPS tracking number. - * - * @css ng-validation-error - * When validation fails, this css class is applied to the binding, making its borders red by - * default. - * - * @example - * <script> - * angular.validator('upsTrackingNo', function(input, format) { - * var regexp = new RegExp("^" + format.replace(/9/g, '\\d') + "$"); - * return input.match(regexp)?"":"The format must match " + format; - * }); - * </script> - * <input type="text" name="trackNo" size="40" - * ng:validate="upsTrackingNo:'1Z 999 999 99 9999 999 9'" - * value="1Z 123 456 78 9012 345 6"/> - * - * @scenario - * it('should validate correct UPS tracking number', function() { - * expect(element('input[name=trackNo]').attr('class')). - * not().toMatch(/ng-validation-error/); - * }); - * - * it('should not validate in correct UPS tracking number', function() { - * input('trackNo').enter('foo'); - * expect(element('input[name=trackNo]').attr('class')). - * toMatch(/ng-validation-error/); - * }); - * - */ + /** @name angular.validator */ angularValidator = extensionMap(angular, 'validator'), - - /** - * @workInProgress - * @ngdoc overview - * @name angular.filter - * @namespace Namespace for all filters. - * @description - * # Overview - * Filters are a standard way to format your data for display to the user. For example, you - * might have the number 1234.5678 and would like to display it as US currency: $1,234.57. - * Filters allow you to do just that. In addition to transforming the data, filters also modify - * the DOM. This allows the filters to for example apply css styles to the filtered output if - * certain conditions were met. - * - * - * # Standard Filters - * - * The Angular framework provides a standard set of filters for common operations, including: - * {@link angular.filter.currency currency}, {@link angular.filter.json json}, - * {@link angular.filter.number number}, and {@link angular.filter.html html}. You can also add - * your own filters. - * - * - * # Syntax - * - * Filters can be part of any {@link angular.scope} evaluation but are typically used with - * {{bindings}}. Filters typically transform the data to a new data type, formating the data in - * the process. Filters can be chained and take optional arguments. Here are few examples: - * - * * No filter: {{1234.5678}} => 1234.5678 - * * Number filter: {{1234.5678|number}} => 1,234.57. Notice the “,” and rounding to two - * significant digits. - * * Filter with arguments: {{1234.5678|number:5}} => 1,234.56780. Filters can take optional - * arguments, separated by colons in a binding. To number, the argument “5” requests 5 digits - * to the right of the decimal point. - * - * - * # Writing your own Filters - * - * Writing your own filter is very easy: just define a JavaScript function on `angular.filter`. - * The framework passes in the input value as the first argument to your function. Any filter - * arguments are passed in as additional function arguments. - * - * You can use these variables in the function: - * - * * `this` — The current scope. - * * `this.$element` — The DOM element containing the binding. This allows the filter to manipulate - * the DOM in addition to transforming the input. - * - * - * @exampleDescription - * The following example filter reverses a text string. In addition, it conditionally makes the - * text upper-case (to demonstrate optional arguments) and assigns color (to demonstrate DOM - * modification). - * - * @example - <script type="text/javascript"> - angular.filter('reverse', function(input, uppercase, color) { - var out = ""; - for (var i = 0; i < input.length; i++) { - out = input.charAt(i) + out; - } - if (uppercase) { - out = out.toUpperCase(); - } - if (color) { - this.$element.css('color', color); - } - return out; - }); - </script> - - <input name="text" type="text" value="hello" /><br> - No filter: {{text}}<br> - Reverse: {{text|reverse}}<br> - Reverse + uppercase: {{text|reverse:true}}<br> - Reverse + uppercase + blue: {{text|reverse:true:"blue"}} - - */ + /** @name angular.fileter */ angularFilter = extensionMap(angular, 'filter'), - /** - * @workInProgress - * @ngdoc overview - * @name angular.formatter - * @namespace Namespace for all formats. - * @description - * # Overview - * The formatters are responsible for translating user readable text in an input widget to a - * data model stored in an application. - * - * # Writting your own Formatter - * Writing your own formatter is easy. Just register a pair of JavaScript functions with - * `angular.formatter`. One function for parsing user input text to the stored form, - * and one for formatting the stored data to user-visible text. - * - * Here is an example of a "reverse" formatter: The data is stored in uppercase and in - * reverse, while it is displayed in lower case and non-reversed. User edits are - * automatically parsed into the internal form and data changes are automatically - * formatted to the viewed form. - * - * <pre> - * function reverse(text) { - * var reversed = []; - * for (var i = 0; i < text.length; i++) { - * reversed.unshift(text.charAt(i)); - * } - * return reversed.join(''); - * } - * - * angular.formatter('reverse', { - * parse: function(value){ - * return reverse(value||'').toUpperCase(); - * }, - * format: function(value){ - * return reverse(value||'').toLowerCase(); - * } - * }); - * </pre> - * - * @example - * <script type="text/javascript"> - * function reverse(text) { - * var reversed = []; - * for (var i = 0; i < text.length; i++) { - * reversed.unshift(text.charAt(i)); - * } - * return reversed.join(''); - * } - * - * angular.formatter('reverse', { - * parse: function(value){ - * return reverse(value||'').toUpperCase(); - * }, - * format: function(value){ - * return reverse(value||'').toLowerCase(); - * } - * }); - * </script> - * - * Formatted: - * <input type="text" name="data" value="angular" ng:format="reverse"/> - * <br/> - * - * Stored: - * <input type="text" name="data"/><br/> - * <pre>{{data}}</pre> - * - * - * @scenario - * it('should store reverse', function(){ - * expect(element('.doc-example input:first').val()).toEqual('angular'); - * expect(element('.doc-example input:last').val()).toEqual('RALUGNA'); - * - * this.addFutureAction('change to XYZ', function($window, $document, done){ - * $document.elements('.doc-example input:last').val('XYZ').trigger('change'); - * done(); - * }); - * expect(element('.doc-example input:first').val()).toEqual('zyx'); - * }); - */ + /** @name angular.formatter */ angularFormatter = extensionMap(angular, 'formatter'), - - /** - * @workInProgress - * @ngdoc overview - * @name angular.service - * - * @description - * # Overview - * Services are substituable objects, which are wired together using dependency injection. - * Each service could have dependencies (other services), which are passed in constructor. - * Because JS is dynamicaly typed language, dependency injection can not use static types - * to satisfy these dependencies, so each service must explicitely define its dependencies. - * This is done by `$inject` property. - * - * For now, life time of all services is the same as the life time of page. - * - * - * # Built-in services - * The Angular framework provides a standard set of services for common operations. - * You can write your own services and rewrite these standard services as well. - * Like other core angular variables, the built-in services always start with $. - * - * * `angular.service.$browser` - * * `angular.service.$window` - * * `angular.service.$document` - * * `angular.service.$location` - * * `angular.service.$log` - * * `angular.service.$exceptionHandler` - * * `angular.service.$hover` - * * `angular.service.$invalidWidgets` - * * `angular.service.$route` - * * `angular.service.$xhr` - * * `angular.service.$xhr.error` - * * `angular.service.$xhr.bulk` - * * `angular.service.$xhr.cache` - * * `angular.service.$resource` - * * `angular.service.$cookies` - * * `angular.service.$cookieStore` - * - * # Writing your own custom services - * Angular provides only set of basic services, so you will probably need to write your custom - * service very soon. To do so, you need to write a factory function and register this function - * to angular's dependency injector. This factory function must return an object - your service - * (it is not called with new operator). - * - * **angular.service** has three parameters: - * - * - `{string} name` - Name of the service - * - `{function()} factory` - Factory function (called just once by DI) - * - `{Object} config` - Hash of configuration (`$inject`, `$creation`) - * - * If your service requires - depends on other services, you need to specify them - * in config hash - property $inject. This property is an array of strings (service names). - * These dependencies will be passed as parameters to the factory function by DI. - * This approach is very useful when testing, as you can inject mocks/stubs/dummies. - * - * Here is an example of very simple service. This service requires $window service (it's - * passed as a parameter to factory function) and it's just a function. - * - * This service simple stores all notifications and after third one, it displays all of them by - * window alert. - * <pre> - angular.service('notify', function(win) { - var msgs = []; - return function(msg) { - msgs.push(msg); - if (msgs.length == 3) { - win.alert(msgs.join("\n")); - msgs = []; - } - }; - }, {$inject: ['$window']}); - * </pre> - * - * And here is a unit test for this service. We use Jasmine spy (mock) instead of real browser's alert. - * <pre> - * var mock, notify; - * - * beforeEach(function() { - * mock = {alert: jasmine.createSpy()}; - * notify = angular.service('notify')(mock); - * }); - * - * it('should not alert first two notifications', function() { - * notify('one'); - * notify('two'); - * expect(mock.alert).not.toHaveBeenCalled(); - * }); - * - * it('should alert all after third notification', function() { - * notify('one'); - * notify('two'); - * notify('three'); - * expect(mock.alert).toHaveBeenCalledWith("one\ntwo\nthree"); - * }); - * - * it('should clear messages after alert', function() { - * notify('one'); - * notify('two'); - * notify('third'); - * notify('more'); - * notify('two'); - * notify('third'); - * expect(mock.alert.callCount).toEqual(2); - * expect(mock.alert.mostRecentCall.args).toEqual(["more\ntwo\nthird"]); - * }); - * </pre> - * - * # Injecting services into controllers - * Using services in a controllers is very similar to using service in other service. - * Again, we will use dependency injection. - * - * JavaScript is dynamic language, so DI is not able to figure out which services to inject by - * static types (like in static typed languages). Therefore you must specify the service name - * by the `$inject` property - it's an array that contains strings with names of services to be - * injected. The name must match the id that service has been registered as with angular. - * The order of the services in the array matters, because this order will be used when calling - * the factory function with injected parameters. The names of parameters in factory function - * don't matter, but by convention they match the service ids. - * <pre> - * function myController($loc, $log) { - * this.firstMethod = function() { - * // use $location service - * $loc.setHash(); - * }; - * this.secondMethod = function() { - * // use $log service - * $log.info('...'); - * }; - * } - * // which services to inject ? - * myController.$inject = ['$location', '$log']; - * </pre> - * - * @example - * <script type="text/javascript"> - * angular.service('notify', function(win) { - * var msgs = []; - * return function(msg) { - * msgs.push(msg); - * if (msgs.length == 3) { - * win.alert(msgs.join("\n")); - * msgs = []; - * } - * }; - * }, {$inject: ['$window']}); - * - * function myController(notifyService) { - * this.callNotify = function(msg) { - * notifyService(msg); - * }; - * } - * - * myController.$inject = ['notify']; - * </script> - * - * <div ng:controller="myController"> - * <p>Let's try this simple notify service, injected into the controller...</p> - * <input ng:init="message='test'" type="text" name="message" /> - * <button ng:click="callNotify(message);">NOTIFY</button> - * </div> - */ + /** @name angular.service */ angularService = extensionMap(angular, 'service'), angularCallbacks = extensionMap(angular, 'callbacks'), nodeName, @@ -942,7 +368,7 @@ function isNumber(value){ return typeof value == $number;} * @function * * @description - * Checks if a reference is defined. + * Checks if value is a date. * * @param {*} value Reference to check. * @returns {boolean} True if `value` is a `Date`. |
