From 58d0e8945d772eddbfecbe6a645b2f1c4dd38bf2 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Mon, 22 Nov 2010 12:05:01 -0800 Subject: allow documentation to be in external file * Load templates once instead of per request * show timing information * load files ending in .ngdoc and process them --- docs/angular.directive.ngdoc | 53 ++++ docs/angular.element.ngdoc | 43 ++++ docs/angular.filter.ngdoc | 76 ++++++ docs/angular.formatter.ngdoc | 78 ++++++ docs/angular.ngdoc | 4 + docs/angular.service.ngdoc | 159 ++++++++++++ docs/angular.validator.ngdoc | 73 ++++++ docs/angular.widget.ngdoc | 73 ++++++ docs/collect.js | 112 ++++++--- docs/index.html | 2 +- src/Angular.js | 588 +------------------------------------------ 11 files changed, 646 insertions(+), 615 deletions(-) create mode 100644 docs/angular.directive.ngdoc create mode 100644 docs/angular.element.ngdoc create mode 100644 docs/angular.filter.ngdoc create mode 100644 docs/angular.formatter.ngdoc create mode 100644 docs/angular.ngdoc create mode 100644 docs/angular.service.ngdoc create mode 100644 docs/angular.validator.ngdoc create mode 100644 docs/angular.widget.ngdoc diff --git a/docs/angular.directive.ngdoc b/docs/angular.directive.ngdoc new file mode 100644 index 00000000..9a08e4c7 --- /dev/null +++ b/docs/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 +``. 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}: +
+ angular.directive('ng:bind', function(expression, compiledElement) {
+ var compiler = this;
+ return function(linkElement) {
+ var currentScope = this;
+ currentScope.$watch(expression, function(value) {
+ linkElement.text(value);
+ });
+ };
+ });
+
+
+# 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`:
++
+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();
+ }
+});
+
+
+@example
+
+
+Formatted:
+
+{{data}}
+
+
+@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');
+});
diff --git a/docs/angular.ngdoc b/docs/angular.ngdoc
new file mode 100644
index 00000000..3f342d1b
--- /dev/null
+++ b/docs/angular.ngdoc
@@ -0,0 +1,4 @@
+@workInProgress
+@ngdoc overview
+@name angular
+@namespace The exported angular namespace.
diff --git a/docs/angular.service.ngdoc b/docs/angular.service.ngdoc
new file mode 100644
index 00000000..30fb8512
--- /dev/null
+++ b/docs/angular.service.ngdoc
@@ -0,0 +1,159 @@
+@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.
+
+ 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']});
+
+
+And here is a unit test for this service. We use Jasmine spy (mock) instead of real browser's alert.
+
+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"]);
+});
+
+
+# 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.
+
+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'];
+
+
+@example
+
+
+Let's try this simple notify service, injected into the controller...
+ + ++<my:watch exp="name"/> ++ +You can implement `my:watch` like this: +
+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);
+ }};
+ };
+});
+
+
+# Attribute Widget
+Let's implement the same widget, but this time as an attribute
+that can be added to any existing DOM element.
++<div my-watch="name">text</div> ++You can implement `my:watch` attribute like this: +
+angular.widget('@my:watch', function(expression, compileElement) {
+ var compiler = this;
+ return function(linkElement) {
+ var currentScope = this;
+ currentScope.$watch(expression, function(value){
+ alert(value);
+ });
+ };
+});
+
+
+@example
+
+
- angular.directive('ng:bind', function(expression, compiledElement) {
- var compiler = this;
- return function(linkElement) {
- var currentScope = this;
- currentScope.$watch(expression, function(value) {
- linkElement.text(value);
- });
- };
- });
- *
- *
- * # 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`:
- * -
- * <my:watch exp="name"/> - *- * - * You can implement `my:watch` like this: - *
- * 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);
- * }};
- * };
- * });
- *
- *
- * # Attribute Widget
- * Let's implement the same widget, but this time as an attribute
- * that can be added to any existing DOM element.
- * - * <div my-watch="name">text</div> - *- * You can implement `my:watch` attribute like this: - *
- * angular.widget('@my:watch', function(expression, compileElement) {
- * var compiler = this;
- * return function(linkElement) {
- * var currentScope = this;
- * currentScope.$watch(expression, function(value){
- * alert(value);
- * });
- * };
- * });
- *
- *
- * @example
- *
- *
- * 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();
- * }
- * });
- *
- *
- * @example
- *
- *
- * Formatted:
- *
- * {{data}}
- *
- *
- * @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.
- *
- 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']});
- *
- *
- * And here is a unit test for this service. We use Jasmine spy (mock) instead of real browser's alert.
- *
- * 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"]);
- * });
- *
- *
- * # 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.
- *
- * 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'];
- *
- *
- * @example
- *
- *
- * Let's try this simple notify service, injected into the controller...
- * - * - *