diff options
| author | Misko Hevery | 2010-11-08 20:34:18 -0800 |
|---|---|---|
| committer | Misko Hevery | 2010-11-09 09:15:29 -0800 |
| commit | c048f0d8e8385e96e9fff0b4ff733cecfa726d93 (patch) | |
| tree | afb32329985985e2c0beec3fd5f9ad38389a80c5 | |
| parent | 96e37a08666f4000cbba6f77a4b362a3480c934b (diff) | |
| download | angular.js-c048f0d8e8385e96e9fff0b4ff733cecfa726d93.tar.bz2 | |
Added formatter documentation.
| -rw-r--r-- | docs/formatter.template | 24 | ||||
| -rw-r--r-- | docs/overview.template | 4 | ||||
| -rw-r--r-- | src/Angular.js | 132 | ||||
| -rw-r--r-- | src/formatters.js | 118 |
4 files changed, 276 insertions, 2 deletions
diff --git a/docs/formatter.template b/docs/formatter.template new file mode 100644 index 00000000..19611ca1 --- /dev/null +++ b/docs/formatter.template @@ -0,0 +1,24 @@ +<h1><tt>{{name}}</tt></h1> +<h2>Description</h2> +{{{description}}} + +<h2>Usage</h2> +<h3>In HTML Template Binding</h3> +<tt> + <input type="text" ng:format="{{shortName}}"> +</tt> +<h3>In JavaScript</h3> +<tt ng:non-bindable> +var userInputString = angular.formatter.{{shortName}}.format(modelValue);<br/> +var modelValue = angular.formatter.{{shortName}}.parse(userInputString); +</tt> + +<h3>Returns</h3> +{{{returns}}} + +<h3>CSS</h3> +{{{css}}} + +<WIKI:SOURCE style="display:block;"> +{{{example}}} +</WIKI:SOURCE>
\ No newline at end of file diff --git a/docs/overview.template b/docs/overview.template index 61fd426f..f7540999 100644 --- a/docs/overview.template +++ b/docs/overview.template @@ -1,6 +1,6 @@ <h1><tt>{{name}}</tt></h1> {{{description}}} -<WIKI:SOURCE style="display:block;"> +{{#example}}<WIKI:SOURCE style="display:block;">{{/example}} {{{example}}} -</WIKI:SOURCE> +{{#example}}</WIKI:SOURCE>{{/example}} diff --git a/src/Angular.js b/src/Angular.js index 73f2841a..9934b401 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -92,6 +92,65 @@ var _undefined = undefined, angularTextMarkup = extensionMap(angular, 'markup'), angularAttrMarkup = extensionMap(angular, 'attrMarkup'), angularDirective = extensionMap(angular, 'directive'), + + /** + * @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> + */ angularWidget = extensionMap(angular, 'widget', lowercase), /** @@ -224,6 +283,79 @@ var _undefined = undefined, */ angularFilter = extensionMap(angular, 'filter'), + /** + * @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 Fromatter + * 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> + * 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('.example :input:first').val()).toEqual('<angular/>'); + * expect(element('.example :input:last').val()).toEqual('>/RALUGNA<'); + * + * this.addFutureAction('change to XYZ', function($window, $document, done){ + * $document.elements('.example :input:last').val('XYZ').trigger('change'); + * done(); + * }); + * expect(element('.example :input:first').val()).toEqual('zyx'); + * }); + */ angularFormatter = extensionMap(angular, 'formatter'), angularService = extensionMap(angular, 'service'), angularCallbacks = extensionMap(angular, 'callbacks'), diff --git a/src/formatters.js b/src/formatters.js index ba57a3ed..5c602cc8 100644 --- a/src/formatters.js +++ b/src/formatters.js @@ -6,8 +6,76 @@ function toString(obj) { var NUMBER = /^\s*[-+]?\d*(\.\d*)?\s*$/; angularFormatter.noop = formatter(identity, identity); + +/** + * @ngdoc formatter + * @name angular.formatter.json + * + * @description + * Formats the user input as JSON text. + * + * @returns {string} A JSON string representation of the model. + * + * @example + * <div ng:init="data={name:'misko', project:'angular'}"> + * <input type="text" size='50' name="data" ng:format="json"/> + * <pre>data={{data}}</pre> + * </div> + * + * @scenario + * it('should format json', function(){ + * expect(binding('data')).toEqual('data={\n \"name\":\"misko\",\n \"project\":\"angular\"}'); + * input('data').enter('{}'); + * expect(binding('data')).toEqual('data={\n }'); + * }); + */ angularFormatter.json = formatter(toJson, fromJson); + +/** + * @ngdoc formatter + * @name angular.formatter.boolean + * + * @description + * Use boolean formatter if you wish to store the data as boolean. + * + * @returns Convert to `true` unless user enters (blank), `f`, `false`, `0`, `no`, `[]`. + * + * @example + * Enter truthy text: + * <input type="text" name="value" ng:format="boolean" value="no"/> + * <input type="checkbox" name="value"/> + * <pre>value={{value}}</pre> + * + * @scenario + * it('should format boolean', function(){ + * expect(binding('value')).toEqual('value=false'); + * input('value').enter('truthy'); + * expect(binding('value')).toEqual('value=true'); + * }); + */ angularFormatter['boolean'] = formatter(toString, toBoolean); + +/** + * @ngdoc formatter + * @name angular.formatter.number + * + * @description + * Use number formatter if you wish to convert the user entered string to a number. + * + * @returns parse string to number. + * + * @example + * Enter valid number: + * <input type="text" name="value" ng:format="number" value="1234"/> + * <pre>value={{value}}</pre> + * + * @scenario + * it('should format numbers', function(){ + * expect(binding('value')).toEqual('value=1234'); + * input('value').enter('5678'); + * expect(binding('value')).toEqual('value=5678'); + * }); + */ angularFormatter.number = formatter(toString, function(obj){ if (obj == _null || NUMBER.exec(obj)) { return obj===_null || obj === '' ? _null : 1*obj; @@ -16,6 +84,31 @@ angularFormatter.number = formatter(toString, function(obj){ } }); +/** + * @ngdoc formatter + * @name angular.formatter.list + * + * @description + * Use number formatter if you wish to convert the user entered string to a number. + * + * @returns parse string to number. + * + * @example + * Enter a list of items: + * <input type="text" name="value" ng:format="list" value=" chair ,, table"/> + * <input type="text" name="value" ng:format="list"/> + * <pre>value={{value}}</pre> + * + * @scenario + * it('should format lists', function(){ + * expect(binding('value')).toEqual('value=["chair","table"]'); + * this.addFutureAction('change to XYZ', function($window, $document, done){ + * $document.elements('.example :input:last').val(',,a,b,').trigger('change'); + * done(); + * }); + * expect(binding('value')).toEqual('value=["a","b"]'); + * }); + */ angularFormatter.list = formatter( function(obj) { return obj ? obj.join(", ") : obj; }, function(value) { @@ -28,6 +121,31 @@ angularFormatter.list = formatter( } ); +/** + * @ngdoc formatter + * @name angular.formatter.trim + * + * @description + * Use trim formatter if you wish to trim extra spaces in user text. + * + * @returns {String} Trim excess leading and trailing space. + * + * @example + * Enter text with leading/trailing spaces: + * <input type="text" name="value" ng:format="trim" value=" book "/> + * <input type="text" name="value" ng:format="trim"/> + * <pre>value={{value|json}}</pre> + * + * @scenario + * it('should format trim', function(){ + * expect(binding('value')).toEqual('value="book"'); + * this.addFutureAction('change to XYZ', function($window, $document, done){ + * $document.elements('.example :input:last').val(' text ').trigger('change'); + * done(); + * }); + * expect(binding('value')).toEqual('value="text"'); + * }); + */ angularFormatter.trim = formatter( function(obj) { return obj ? trim("" + obj) : ""; } ); |
