diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/guide.contribute.ngdoc | 27 | ||||
| -rw-r--r-- | docs/guide.css.ngdoc | 46 | ||||
| -rw-r--r-- | docs/guide.downloading.ngdoc | 35 | ||||
| -rw-r--r-- | docs/guide.expression.ngdoc | 207 | ||||
| -rw-r--r-- | docs/guide.ngdoc | 1 | ||||
| -rw-r--r-- | docs/guide.testing.ngdoc | 8 | ||||
| -rw-r--r-- | docs/spec/ngdocSpec.js | 17 | ||||
| -rw-r--r-- | docs/src/ngdoc.js | 12 | ||||
| -rw-r--r-- | docs/src/templates/doc_widgets.js | 1 | ||||
| -rw-r--r-- | docs/src/templates/docs.js | 5 |
10 files changed, 349 insertions, 10 deletions
diff --git a/docs/guide.contribute.ngdoc b/docs/guide.contribute.ngdoc new file mode 100644 index 00000000..9e50e661 --- /dev/null +++ b/docs/guide.contribute.ngdoc @@ -0,0 +1,27 @@ +@workInProgress +@ngdoc overview +@name Developer Guide: Contributing +@description + +# Open Source +Angular is an open source project licensed under the +{@link http://github.com/angular/angular.js/blob/master/LICENSE MIT license}. We welcome any +contributions from the community, but in order to make the contribution process manageable, we ask +you to follow the following guidelines: + +# Source Code +* Discuss any major changes on our {@link http://groups.google.com/group/angular mailing list}. + For small changes and bugfixes, just go ahead and craft your patch and submit it. +* Use coding style described + {@link http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml here}. +* To submit any changes, we ask you to use {@link http://github.com} + * Create a github {@link https://github.com/signup/free account} + * Clone the {@link http://github.com/angular/angular.js main angular repository} + * Create a new branch off of the master (`git branch my-fix-branch`) + * Switch to the branch (`git checkout my-fix-branch`), make your changes and commit (`git commit -a`) + * For any new features or regressions we require a test(s) to be submitted with the change + * Run js lint (`rake lint`) and fix any warnings or errors + * Push your branch to github (`git push origin my-fix-branch`) + * Send a pull request via github into `angular:master` + * Once the patch is reviewed and merged, you can delete your branch (`git push origin :my-fix-branch; git checkout master; git branch -D my-fix-branch`) + * TADA! diff --git a/docs/guide.css.ngdoc b/docs/guide.css.ngdoc new file mode 100644 index 00000000..6e028f30 --- /dev/null +++ b/docs/guide.css.ngdoc @@ -0,0 +1,46 @@ +@workInProgress +@ngdoc overview +@name Developer Guide: CSS +@description + +# CSS +angular includes built-in CSS classes, which in turn have predefined CSS styles. + +# Built-in CSS classes + +## `ng-exception` + +**Usage:** angular applies this class to a DOM element if that element contains an Expression that +threw an exception when evaluated. + +**Styling:** The built-in styling of the ng-exception class displays an error message surrounded +by a solid red border, for example: + + > <div class="ng-exception">Error message</div> + + + +You can try to evaluate malformed expressions in {@link angualr.expression expression} to see the +`ng-exception` class' styling. + +## `ng-validation-error` + +**Usage:** angular applies this class to an input widget element if that element's input does not +pass validation. Note that you set the validation criteria on the input widget element using the +Ng:validate or Ng:required directives. + +**Styling:** The built-in styling of the ng-validation-error class turns the border of the input +box red and includes a hovering UI element that includes more details of the validation error. You +can see an example in {@link angular.widget.@ng:validate ng:validate example}. + +## How to override the styles for built-in classes + +To override the styles for these built-in classes, you can do any of the following: + +Download the source code, edit angular.css, and host the source on your own server. +Create a local css file, overriding any styles that you'd like, and link to it from your HTML file +as you normally would: + +<pre> +<link href="yourfile.css" rel="stylesheet" type="text/css"> +</pre> diff --git a/docs/guide.downloading.ngdoc b/docs/guide.downloading.ngdoc new file mode 100644 index 00000000..9f0f2194 --- /dev/null +++ b/docs/guide.downloading.ngdoc @@ -0,0 +1,35 @@ +@workInProgress +@ngdoc overview +@name Developer Guide: Downloading +@description + +# Downloading +Follow these steps to download, compile, and host angular.js on your own server: + +## Step 0 + +If you don't already have Rake (Ruby Make) installed, download and install it from +http://rake.rubyforge.org/. + +## Step 1 + +Download the angular source code from GitHub: http://github.com/angular/angular.js. + +## Step 2 + +The source code should include a Rakefile. Compile the source by typing rake compile. + +## Step 3 + +Host the files on your server. Look through your source tree and make sure that the css and js +directories are parallel (i.e. share a common root node). + +In the js directory you should see these different versions of the angular bootstrap code: + +* **angular-?.?.?.js** - this file is unobfuscated, uncompressed, and human-readable. Note that + despite the name of the file, there is no additional functionality built in to help you debug + your application; it has the prefix debug because you can read the source code. +* **angular-?.?.?.min.js** - this is a compressed and obfuscated version of `angular-?.?.?.js`. + You might want to use this version if you want to load a smaller but functionally equivalent + version of the code in your application. Note: this minified version was created using the + Closure Compiler. diff --git a/docs/guide.expression.ngdoc b/docs/guide.expression.ngdoc new file mode 100644 index 00000000..421dd9c7 --- /dev/null +++ b/docs/guide.expression.ngdoc @@ -0,0 +1,207 @@ +@workInProgress +@ngdoc overview +@name Developer Guide: Expression +@description + +# Expressions +Expressions are the bindings that you write in HTML and embed in templates in order to create +views in angular. They are not equivalent to JavaScript expressions. + +For example, these are all valid expressions in angular: + +* `1+2={{1+2}}` +* `3*10|currency` +* `Hello {{name}}!` +* `Hello {{'World'}}!` + + +# angular expressions vs. JS expressions +It might be tempting to think of angular view expressions as JavaScript expressions, but that is +not entirely correct. angular does not use a simple JavaScript eval of the expression text. You +can think of angular expressions as JavaScript expressions with these differences: + + * **Attribute Evaluation:** evaluation of all attributes are against the current scope, not to + the global window as in JavaScript. + * **Forgiving:** expression evaluation is forgiving to undefined and null, unlike in JavaScript. + * **No Control Flow Statements:** you cannot do the following from an angular expression: + conditionals, loops, or throw. + * **Type Augmentation:** the scope expression evaluator augments built-in types. + * **Filters:** you can add filters to an expression, for example to convert raw data into a + human-readable format. + * **The $:** angular reserves this prefix to differentiate its API names from others. + +If you want to run arbitrary JavaScript code, make it a controller method and call that. If you +want to eval an angular expression from JavaScript, use the Scope:$eval() method. + +## Example +<doc:example> + <doc:source> + 1+2={{1+2}} + </doc:source> + <doc:scenario> + it('should calculate expression in binding', function(){ + expect(binding('1+2')).toEqual('3'); + }); + </doc:scenario> +</doc:example> + +You can try evaluating different expressions here: + +<doc:example> + <doc:source> + <div ng:init="exprs=[]" class="expressions"> + Expression: + <input type='text' name="expr" value="3*10|currency" size="80"/> + <button ng:click="exprs.$add(expr)">Evaluate</button> + <ul> + <li ng:repeat="expr in exprs"> + [ <a href="" ng:click="exprs.$remove(expr)">X</a> ] + <tt>{{expr}}</tt> => <span ng:bind="$parent.$eval(expr)"></span> + </li> + </ul> + </div> + </doc:source> + <doc:scenario> + it('should allow user expression testing', function(){ + element('.expressions :button').click(); + var li = using('.expressions ul').repeater('li'); + expect(li.count()).toBe(1); + expect(li.row(0)).toEqual(["3*10|currency", "$30.00"]); + }); + </doc:scenario> +</doc:example> + +# Attribute Evaluation + +Evaluation of all attributes are against the current scope. Unlike JavaScript, where names +default to global window properties, angular expressions have to use $window to refer to the +global object. E.g. if you want to call alert(), which is defined on window, an expression must +use $window.alert(). This is done intentionally to prevent accidental access to the global state +(a common source of subtle bugs). + +<doc:example> + <doc:source> + <div class="example2" ng:init="$window = $service('$window')"> + Name: <input name="name" type="text" value="World"/> + <button ng:click="($window.mockWindow || $window).alert('Hello ' + name)">Greet</button> + </div> + </doc:source> + <doc:scenario> + it('should calculate expression in binding', function(){ + var alertText; + this.addFutureAction('set mock', function($window, $document, done) { + $window.mockWindow = { + alert: function(text){ alertText = text; } + }; + done(); + }); + element(':button:contains(Greet)').click(); + expect(this.addFuture('alert text', function(done) { + done(null, alertText); + })).toBe('Hello World'); + }); + </doc:scenario> +</doc:example> + +## Forgiving + +Expression evaluation is forgiving to undefined and null. In JavaScript, evaluating a.b.c throws +an exception if a is not an object. While this makes sense for a general purpose language, the +expression evaluations are primarily used for data binding, which often look like this: `{{a.b.c}}`. +It makes more sense to show nothing than to throw an exception if a is undefined (e.g. perhaps +we are waiting for the server response, and it will become defined soon). If expression +evaluation wasn't forgiving we'd have to write bindings that clutter the code, for example: +`{{((a||{}).b||{}).c}}` + +Similarly, invoking a function a.b.c() on undefined or null simply returns undefined. + +Assignments work the same way in reverse. a.b.c = 10 creates the intermediary objects even if a +is undefined. + + +## No Control Flow Statements + +You cannot write a control flow statement in an expression. The reason behind this is core to +the angular philosophy that application logic should be in controllers, not in the view. If you +need a conditional (including ternary operators), loop, or to throw from a view expression, +delegate to a JavaScript method instead. + + +## Type Augmentation + +Built-in types have methods like [].push(), but the richness of these methods is limited. Consider +the example below, which allows you to do a simple search over a canned set of contacts. The +example would be much more complicated if we did not have the Array:$filter(). There is no +built-in method on Array called $filter and angular doesn't add it to Array.prototype because that +could collide with other JavaScript frameworks. + +For this reason the scope expression evaluator augments the built-in types to make them act like +they have extra methods. The actual method for $filter() is angular.Array.filter(). You can call +it from JavaScript. + +Extensions: You can further extend the expression vocabulary by adding new methods to +`angular.Array` or `angular.String`, etc. + +<doc:example> + <doc:source> + <div ng:init="friends = [ + {name:'John', phone:'555-1212'}, + {name:'Mary', phone:'555-9876'}, + {name:'Mike', phone:'555-4321'}, + {name:'Adam', phone:'555-5678'}, + {name:'Julie', phone:'555-8765'}]"></div> + Search: <input name="searchText"/> + <table class="example3"> + <tr><th>Name</th><th>Phone</th><tr> + <tr ng:repeat="friend in friends.$filter(searchText)"> + <td>{{friend.name}}</td> + <td>{{friend.phone}}</td> + </tr> + </table> + </doc:source> + <doc:scenario> + it('should filter the list', function(){ + var tr = using('table.example3').repeater('tr.ng-attr-widget'); + expect(tr.count()).toBe(5); + input('searchText').enter('a'); + expect(tr.count()).toBe(2); + + }); + </doc:scenario> +</doc:example> + +## Filters + +When presenting data to the user, you might need to convert the data from its raw format to a +user-friendly format. For example, you might have a data object that needs to be formatted +according to the locale before displaying it to the user. You can pass expressions through a +chain of filters like this: + +<pre> +name | uppercase +</pre> + +The expression evaluator simply passes the value of name to angular.filter.uppercase. + +Chain filters using this syntax: + +<pre> +value | filter1 | filter2 +</pre> + +You can also pass colon-delimited arguments to filters, for example, to display the number 123 +with 2 decimal points: 123 | number:2 + +# The $ + +You might be wondering, what is the significance of the $ prefix? It is simply a prefix that +angular chooses to differentiate its API names from others. If angular didn't use $, then +evaluating a.length() would return undefined because neither a nor angular define such a property. +Consider that in a future version of angular we might choose to add a length method, in which case +the behavior of the expression would change. Worse yet, you the developer could create a length +property and then we would have collision. This problem exists because angular augments existing +objects with additional behavior. By prefixing its additions with $ we are reserving our namespace +so that angular developers and developers who use angular can develop in harmony without +collisions. + + diff --git a/docs/guide.ngdoc b/docs/guide.ngdoc index b1ac143e..fd5d05df 100644 --- a/docs/guide.ngdoc +++ b/docs/guide.ngdoc @@ -34,3 +34,4 @@ * service:$browser(mock) * {@link guide.downloading Downloading} - How to download, compile, and host the angular environment on your own server. +* {@link guide.contribute Contributing} - How to contribute to angular project. diff --git a/docs/guide.testing.ngdoc b/docs/guide.testing.ngdoc new file mode 100644 index 00000000..bb3a1441 --- /dev/null +++ b/docs/guide.testing.ngdoc @@ -0,0 +1,8 @@ +@workInProgress +@ngdoc overview +@name Developer Guide: Testing +@description + +# Testing Angular Applications + +to be written... diff --git a/docs/spec/ngdocSpec.js b/docs/spec/ngdocSpec.js index 9d84ee7e..d912bf3a 100644 --- a/docs/spec/ngdocSpec.js +++ b/docs/spec/ngdocSpec.js @@ -319,6 +319,7 @@ describe('ngdoc', function(){ var doc = new Doc("@description " + 'foo {@link angular.foo}\n\n da {@link angular.foo bar foo bar } \n\n' + 'dad{@link angular.foo}\n\n' + + 'external{@link http://angularjs.org}\n\n' + '{@link angular.directive.ng:foo ng:foo}'); doc.parse(); expect(doc.description). @@ -329,6 +330,8 @@ describe('ngdoc', function(){ toContain('dad<a href="#!angular.foo"><code>angular.foo</code></a>'); expect(doc.description). toContain('<a href="#!angular.directive.ng:foo"><code>ng:foo</code></a>'); + expect(doc.description). + toContain('<a href="http://angularjs.org">http://angularjs.org</a>'); }); }); @@ -357,12 +360,16 @@ describe('ngdoc', function(){ }); it('should render description in related method', function(){ - var doc = new Doc(); + var doc = new Doc('').parse(); doc.ngdoc = 'service'; - doc.methods = [new Doc('@ngdoc method\n@exampleDescription MDesc\n@example MExmp').parse()]; - doc.properties = [new Doc('@ngdoc property\n@exampleDescription PDesc\n@example PExmp').parse()]; - expect(doc.html()).toContain('<p>MDesc</p><div ng:non-bindable=""><pre class="brush: js; html-script: true;">MExmp</pre>'); - expect(doc.html()).toContain('<p>PDesc</p><div ng:non-bindable=""><pre class="brush: js; html-script: true;">PExmp</pre>'); + doc.methods = [ + new Doc('@ngdoc method\n@exampleDescription MDesc\n@example MExmp').parse()]; + doc.properties = [ + new Doc('@ngdoc property\n@exampleDescription PDesc\n@example PExmp').parse()]; + expect(doc.html()).toContain('<p>MDesc</p><div ng:non-bindable="">' + + '<pre class="brush: js; html-script: true;">MExmp</pre>'); + expect(doc.html()).toContain('<p>PDesc</p><div ng:non-bindable="">' + + '<pre class="brush: js; html-script: true;">PExmp</pre>'); }); }); diff --git a/docs/src/ngdoc.js b/docs/src/ngdoc.js index e01d9ccf..a3a037cd 100644 --- a/docs/src/ngdoc.js +++ b/docs/src/ngdoc.js @@ -114,7 +114,7 @@ Doc.prototype = { description: markdown(text.replace(match[0], match[2])) }; } else if(atName == 'description') { - text.replace(/<doc:scenario>([\s\S]*)<\/doc:scenario>/mi, + text.replace(/<doc:scenario>([\s\S]*?)<\/doc:scenario>/gmi, function(_, scenario){ self.scenarios.push(scenario); }); @@ -154,7 +154,7 @@ Doc.prototype = { throw new Error("Don't know how to format @ngdoc: " + self.ngdoc); }).call(self, dom); - dom.example(self.exampleDescription, self.example, self.scenario); + dom.example(self.exampleDescription, self.example, self.scenarios[0]); }); return dom.toString(); @@ -438,6 +438,8 @@ Doc.prototype = { ////////////////////////////////////////////////////////// function markdown (text) { + var IS_URL = /^(https?:\/\/|ftps?:\/\/|mailto:)/; + var IS_ANGULAR = /^angular\./; if (!text) return text; var parts = text.split(/(<pre>[\s\S]*?<\/pre>|<doc:example>[\s\S]*?<\/doc:example>)/), match; @@ -462,10 +464,10 @@ function markdown (text) { text = text.replace(/<angular\/>/gm, '<tt><angular/></tt>'); text = text.replace(/{@link ([^\s}]+)((\s|\n)+(.+?))?\s*}/gm, function(_all, url, _2, _3, title){ - return '<a href="#!' + url + '">' - + (url.match(/^angular\./) ? '<code>' : '') + return '<a href="' + (url.match(IS_URL) ? '' : '#!') + url + '">' + + (url.match(IS_ANGULAR) ? '<code>' : '') + (title || url) - + (url.match(/^angular\./) ? '</code>' : '') + + (url.match(IS_ANGULAR) ? '</code>' : '') + '</a>'; }); text = new Showdown.converter().makeHtml(text); diff --git a/docs/src/templates/doc_widgets.js b/docs/src/templates/doc_widgets.js index 39b9ff48..bfa8e5d0 100644 --- a/docs/src/templates/doc_widgets.js +++ b/docs/src/templates/doc_widgets.js @@ -56,6 +56,7 @@ }); function indent(text) { + if (!text) return text; var lines = text.split(/\n/); var lineNo = []; // remove any leading blank lines diff --git a/docs/src/templates/docs.js b/docs/src/templates/docs.js index aaea8c9d..ab96a699 100644 --- a/docs/src/templates/docs.js +++ b/docs/src/templates/docs.js @@ -40,4 +40,9 @@ function DocsController($location, $browser, $window) { } +// prevent compilation of code +angular.widget('code', function(element){ + element.attr('ng:non-bindable', 'true'); +}); + SyntaxHighlighter['defaults'].toolbar = false; |
