diff options
Diffstat (limited to 'docs/content/api')
| -rw-r--r-- | docs/content/api/angular.attrMarkup.ngdoc | 15 | ||||
| -rw-r--r-- | docs/content/api/angular.directive.ngdoc | 53 | ||||
| -rw-r--r-- | docs/content/api/angular.element.ngdoc | 49 | ||||
| -rw-r--r-- | docs/content/api/angular.filter.ngdoc | 87 | ||||
| -rw-r--r-- | docs/content/api/angular.formatter.ngdoc | 82 | ||||
| -rw-r--r-- | docs/content/api/angular.markup.ngdoc | 66 | ||||
| -rw-r--r-- | docs/content/api/angular.ngdoc | 4 | ||||
| -rw-r--r-- | docs/content/api/angular.service.ngdoc | 175 | ||||
| -rw-r--r-- | docs/content/api/angular.validator.ngdoc | 77 | ||||
| -rw-r--r-- | docs/content/api/angular.widget.ngdoc | 78 |
10 files changed, 686 insertions, 0 deletions
diff --git a/docs/content/api/angular.attrMarkup.ngdoc b/docs/content/api/angular.attrMarkup.ngdoc new file mode 100644 index 00000000..aad20866 --- /dev/null +++ b/docs/content/api/angular.attrMarkup.ngdoc @@ -0,0 +1,15 @@ +@workInProgress +@ngdoc overview +@name angular.attrMarkup + +@description +Attribute markup extends the angular compiler in a very similar way as {@link angular.markup} except +that it allows you to modify the state of the attribute text rather then the content of a node. + +<pre> +angular.attrMarkup('extraClass', function(attrValue, attrName, element){ + if (attrName == 'additional-class') { + element.addClass(attrValue); + } +}); +</pre> diff --git a/docs/content/api/angular.directive.ngdoc b/docs/content/api/angular.directive.ngdoc new file mode 100644 index 00000000..9a08e4c7 --- /dev/null +++ b/docs/content/api/angular.directive.ngdoc @@ -0,0 +1,53 @@ +@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. diff --git a/docs/content/api/angular.element.ngdoc b/docs/content/api/angular.element.ngdoc new file mode 100644 index 00000000..2ce007fd --- /dev/null +++ b/docs/content/api/angular.element.ngdoc @@ -0,0 +1,49 @@ +@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 (as long as it was loaded before `DOMContentEvent`) + +Angular's jQuery lite implementation is a tiny API-compatible subset of jQuery which allows +angular to manipulate DOM. The jQuery lite implements only a subset of jQuery api, with the +focus on the most commonly needed functionality and minimal footprint. For this reason only a +limited number of jQuery methods, arguments and invocation styles are supported. + +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/) + +## Additionally these methods extend the jQuery and are available in both jQuery and jQuery lite +version: + +- `scope()` - retrieves the current angular scope of the element. + +@param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. +@returns {Object} jQuery object. diff --git a/docs/content/api/angular.filter.ngdoc b/docs/content/api/angular.filter.ngdoc new file mode 100644 index 00000000..5d4f5940 --- /dev/null +++ b/docs/content/api/angular.filter.ngdoc @@ -0,0 +1,87 @@ +@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. + + +@example + 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). + +<doc:example> + <doc:source> + <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"}} + </doc:source> + <doc:scenario> + it('should reverse text', function(){ + expect(binding('text|reverse')).toEqual('olleh'); + input('text').enter('ABC'); + expect(binding('text|reverse')).toEqual('CBA'); + }); + </doc:scenario> +</doc:example> + + diff --git a/docs/content/api/angular.formatter.ngdoc b/docs/content/api/angular.formatter.ngdoc new file mode 100644 index 00000000..4eef190e --- /dev/null +++ b/docs/content/api/angular.formatter.ngdoc @@ -0,0 +1,82 @@ +@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 +<doc:example> + <doc:source> + <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> + </doc:source> + <doc:scenario> + it('should store reverse', function(){ + expect(element('.doc-example-live input:first').val()).toEqual('angular'); + expect(element('.doc-example-live input:last').val()).toEqual('RALUGNA'); + + this.addFutureAction('change to XYZ', function($window, $document, done){ + $document.elements('.doc-example-live input:last').val('XYZ').trigger('change'); + done(); + }); + expect(element('.doc-example-live input:first').val()).toEqual('zyx'); + }); + </doc:scenario> +</doc:example> + diff --git a/docs/content/api/angular.markup.ngdoc b/docs/content/api/angular.markup.ngdoc new file mode 100644 index 00000000..a40385c8 --- /dev/null +++ b/docs/content/api/angular.markup.ngdoc @@ -0,0 +1,66 @@ +@workInProgress +@ngdoc overview +@name angular.markup + +@description +#Overview +Markups allow the angular compiler to transform content of DOM elements or portions of this content +into other text or DOM elements for further compilation. Markup extensions do not themselves produce +linking functions. Think of markup as a way to produce shorthand for a {@link angular.widget widget} + or a {@link angular.directive directive}. + +#`{{}}` (double curly) built-in markup +`{{}}` markup is a built-in markup, which translates the enclosed expression into an +{@link angular.directive.ng:bind ng:bind} directive. It simply transforms + +<pre> +{{expression}} +</pre> + +to: + +<pre> +<span ng:bind="expression"></span> +</pre> + +For example `{{1+2}}` is easier to write and understand than `<span ng:bind="1+2"></span>`. The +expanded elements are then {@link guide.compiler compiled} normally. + +# Custom markup +Let's say you want to define this shorthand for a horizontal rule: `---` for `<hr/>`. + +In other words, this HTML: +<pre> +header +--- +footer +</pre> + +should translate to: +<pre> +header +<hr/> +footer +</pre> + +Here's how the angular compiler could be extended to achieve this: +<pre> +angular.markup('---', function(text, textNode, parentElement) { + var compiler = this; + var index = text.indexOf('---'); + if (index > -1) { + var before = compiler.text(text.substring(0, index)); + var hr = compiler.element('hr'); + var after = compiler.text(text.substring(index + 3)); + textNode.after(after); + textNode.after(hr); + textNode.after(before); + textNode.remove(); + } +}); +</pre> + +Unlike {@link angular.widget widgets} and {@link angular.directive directives}, in which the +compiler matches the name of handler function to a DOM element or attribute name, for markup the +compiler calls every markup handler for every text node, giving the handler a chance to transform +the text. The markup handler needs to find all the matches in the text. diff --git a/docs/content/api/angular.ngdoc b/docs/content/api/angular.ngdoc new file mode 100644 index 00000000..3f342d1b --- /dev/null +++ b/docs/content/api/angular.ngdoc @@ -0,0 +1,4 @@ +@workInProgress +@ngdoc overview +@name angular +@namespace The exported angular namespace. diff --git a/docs/content/api/angular.service.ngdoc b/docs/content/api/angular.service.ngdoc new file mode 100644 index 00000000..0d3406e5 --- /dev/null +++ b/docs/content/api/angular.service.ngdoc @@ -0,0 +1,175 @@ +@workInProgress +@ngdoc overview +@name angular.service + +@description +# Overview +Services are substituable objects, which are wired together using dependency injection (DI). +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 identify these dependencies, so each service must explicitely define its dependencies. +This is done by `$inject` property. + + +# Built-in services +angular provides a set of services for common operations. These services can be overriden by custom +services if needed. + +Like other core angular variables and identifiers, the built-in services always start with `$`. + + * {@link angular.service.$browser $browser} + * {@link angular.service.$window $window} + * {@link angular.service.$document $document} + * {@link angular.service.$location $location} + * {@link angular.service.$log $log} + * {@link angular.service.$exceptionHandler $exceptionHandler} + * {@link angular.service.$hover $hover} + * {@link angular.service.$invalidWidgets $invalidWidgets} + * {@link angular.service.$route $route} + * {@link angular.service.$xhr $xhr} + * {@link angular.service.$xhr.error $xhr.error} + * {@link angular.service.$xhr.bulk $xhr.bulk} + * {@link angular.service.$xhr.cache $xhr.cache} + * {@link angular.service.$resource $resource} + * {@link angular.service.$cookies $cookies} + * {@link angular.service.$cookieStore $cookieStore} + +# Writing your own custom services +angular provides only set of basic services, so for any nontrivial application it will be necessary +to write one or more custom services. To do so, a factory function that creates a services needs to +be registered with angular's dependency injector. This factory function must return an object - the +service (it is not called with the `new` operator). + +**angular.service** accepts three parameters: + + - `{string} name` - Name of the service. + - `{function()} factory` - Factory function (called just once by DI). + - `{Object} config` - Configuration object with following properties: + - `$inject` - {Array.<string>} - Array of service ids that this service depends on. These + services will be passed as arguments into the factory function in the same order as specified + in the `$inject` array. Defaults to `[]`. + - `$eager` - {boolean} - If true, the service factory will be called and thus, the service will + be instantiated when angular boots. If false, service will be lazily instantiated when it is + first requested during instantiation of a dependant. Defaults to `false`. + +The `this` of the factory function is bound to the root scope of the angular application. + +angular enables services to participate in dependency injection (DI) by registering themselves with +angular's DI system (injector) under a `name` (id) as well as by declaring dependencies which need +to be provided for the factory function of the registered service. The ability to swap dependencies +for mocks/stubs/dummies in tests allows for services to be highly testable. + +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 as dependencies for controllers is very similar to using them as dependencies for +another service. + +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 +<doc:example> + <doc:source> + <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> + </doc:source> + <doc:scenario> + it('should test service', function(){ + expect(element(':input[name=message]').val()).toEqual('test'); + }); + </doc:scenario> +</doc:example> diff --git a/docs/content/api/angular.validator.ngdoc b/docs/content/api/angular.validator.ngdoc new file mode 100644 index 00000000..96b1e76a --- /dev/null +++ b/docs/content/api/angular.validator.ngdoc @@ -0,0 +1,77 @@ +@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 +<doc:example> + <doc:source> + <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"/> + </doc:source> + <doc: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/); + }); + </doc:scenario> +</doc:example> diff --git a/docs/content/api/angular.widget.ngdoc b/docs/content/api/angular.widget.ngdoc new file mode 100644 index 00000000..5fd7b259 --- /dev/null +++ b/docs/content/api/angular.widget.ngdoc @@ -0,0 +1,78 @@ +@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 +<doc:example> + <doc:source> + <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> + </doc:source> + <doc:scenario> + </doc:scenario> +</doc:example> |
