diff options
| author | Igor Minar | 2010-11-01 13:44:39 -0700 | 
|---|---|---|
| committer | Igor Minar | 2010-11-03 09:47:21 -0700 | 
| commit | 1fe7e3a1302e948a31ab80d02ede6975c3bddd58 (patch) | |
| tree | 27e9606e9dfa603db6b20e062b61f9b4423a48a9 /src | |
| parent | aec3c8478c2eb937e24306087c5bc1ef49722036 (diff) | |
| download | angular.js-1fe7e3a1302e948a31ab80d02ede6975c3bddd58.tar.bz2 | |
add jsdocs for angular and filter namespaces + all filters
Diffstat (limited to 'src')
| -rw-r--r-- | src/Angular.js | 111 | ||||
| -rw-r--r-- | src/filters.js | 176 | 
2 files changed, 277 insertions, 10 deletions
diff --git a/src/Angular.js b/src/Angular.js index 62ab163a..62cfdef6 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -3,9 +3,30 @@  if (typeof document.getAttribute == $undefined)    document.getAttribute = function() {}; -//The below may not be true on browsers in the Turkish locale. +/** + * @ngdoc + * @name angular.lowercase + * @function + * + * @description Converts string to lowercase + * @param {string} value + * @return {string} Lowercased string. + */  var lowercase = function (value){ return isString(value) ? value.toLowerCase() : value; }; + + +/** + * @ngdoc + * @name angular#uppercase + * @function + * + * @description Converts string to uppercase. + * @param {string} value + * @return {string} Uppercased string. + */  var uppercase = function (value){ return isString(value) ? value.toUpperCase() : value; }; + +  var manualLowercase = function (s) {    return isString(s) ? s.replace(/[A-Z]/g,        function (ch) {return fromCharCode(ch.charCodeAt(0) | 32); }) : s; @@ -14,6 +35,11 @@ var manualUppercase = function (s) {    return isString(s) ? s.replace(/[a-z]/g,        function (ch) {return fromCharCode(ch.charCodeAt(0) & ~32); }) : s;  }; + + +// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish +// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods with +// correct but slower alternatives.  if ('i' !== 'I'.toLowerCase()) {    lowercase = manualLowercase;    uppercase = manualUppercase; @@ -57,12 +83,95 @@ var _undefined        = undefined,      slice             = Array.prototype.slice,      push              = Array.prototype.push,      error             = window[$console] ? bind(window[$console], window[$console]['error'] || noop) : noop, + +    /** +     * @name angular +     * @namespace The exported angular namespace. +     */      angular           = window[$angular]    || (window[$angular] = {}),      angularTextMarkup = extensionMap(angular, 'markup'),      angularAttrMarkup = extensionMap(angular, 'attrMarkup'),      angularDirective  = extensionMap(angular, 'directive'),      angularWidget     = extensionMap(angular, 'widget', lowercase),      angularValidator  = extensionMap(angular, 'validator'), + + +    /** +     * @ngdoc overview +     * @name angular.filter +     * @namespace Namespace for all filters. +     * +     * # 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}, {@link angular.filter.json}, {@link angular.filter.number}, +     * and {@link angular.filter.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. +     * * `$element` — The DOM element containing the binding. This allows the filter to manipulate +     *   the DOM in addition to transforming the input. +     * +     * 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> +         <span ng:non-bindable="true">{{"hello"|reverse}}</span>: {{"hello"|reverse}}<br> +         <span ng:non-bindable="true">{{"hello"|reverse:true}}</span>: {{"hello"|reverse:true}}<br> +         <span ng:non-bindable="true">{{"hello"|reverse:true:"blue"}}</span>: +           {{"hello"|reverse:true:"blue"}} + +     * //TODO: I completely dropped a mention of using the other option (setter method), it's +     * confusing to have two ways to do the same thing. I just wonder if we should prefer using the +     * setter way over direct assignment because in the future we might want to be able to intercept +     * filter registrations for some reason. +     */      angularFilter     = extensionMap(angular, 'filter'),      angularFormatter  = extensionMap(angular, 'formatter'),      angularService    = extensionMap(angular, 'service'), diff --git a/src/filters.js b/src/filters.js index 4ab2b32c..ed824f93 100644 --- a/src/filters.js +++ b/src/filters.js @@ -1,17 +1,74 @@ +/** + * @ngdoc filter + * @name angular.filter.currency + * @function + * + * @description + *   Formats a number as a currency (ie $1,234.56). + * + * @param {number} amout Input to filter. + * @returns {string} Formated number. + * + * @css ng-format-negative + *   When the value is negative, this css class is applied to the binding making it by default red. + *    + * @example + *   <input type="text" name="amount" value="1234.56"/> <br/> + *   {{amount | currency}} + * + * @scenario + *   it('should init with 1234.56', function(){ + *     expect(bind('amount')).toEqual('$1,234.56'); + *   }); + *   it('should update', function(){ + *     element(':input[name=amount]').value('-1234'); + *     expect(bind('amount')).toEqual('-$1,234.00'); + *     expect(bind('amount')).toHaveColor('red'); + *   }); + */  angularFilter.currency = function(amount){    this.$element.toggleClass('ng-format-negative', amount < 0);    return '$' + angularFilter['number'].apply(this, [amount, 2]);  }; -angularFilter.number = function(amount, fractionSize){ -  if (isNaN(amount) || !isFinite(amount)) { + +/** + * @ngdoc filter + * @name angular.filter.number + * @function + * + * @description + *   Formats a number as text. + * + *   If the input is not a number empty string is returned. + * + * @param {(number|string)} number Number to format. + * @param {(number|string)=} fractionSize Number of decimal places to round the number to. Default 2. + * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit. + * + * @example + *   <span ng:non-bindable="true">{{1234.56789|number}}</span>: {{1234.56789|number}}<br/> + *   <span ng:non-bindable="true">{{1234.56789|number:0}}</span>: {{1234.56789|number:0}}<br/> + *   <span ng:non-bindable="true">{{1234.56789|number:2}}</span>: {{1234.56789|number:2}}<br/> + *   <span ng:non-bindable="true">{{-1234.56789|number:4}}</span>: {{-1234.56789|number:4}} + * + * @scenario + *   it('should format numbers', function(){ + *     expect(element('span[ng\\:bind="1234.56789|number"]').val()).toBe('1,234.57'); + *     expect(element('span[ng\\:bind="1234.56789|number:0"]').val()).toBe('1,234'); + *     expect(element('span[ng\\:bind="1234.56789|number:2"]').val()).toBe('1,234.56'); + *     expect(element('span[ng\\:bind="-1234.56789|number:4"]').val()).toBe('-1,234.56789'); + *   }); + */ +angularFilter.number = function(number, fractionSize){ +  if (isNaN(number) || !isFinite(number)) {      return '';    }    fractionSize = typeof fractionSize == $undefined ? 2 : fractionSize; -  var isNegative = amount < 0; -  amount = Math.abs(amount); +  var isNegative = number < 0; +  number = Math.abs(number);    var pow = Math.pow(10, fractionSize); -  var text = "" + Math.round(amount * pow); +  var text = "" + Math.round(number * pow);    var whole = text.substring(0, text.length - fractionSize);    whole = whole || '0';    var frc = text.substring(text.length - fractionSize); @@ -30,6 +87,8 @@ angularFilter.number = function(amount, fractionSize){    }    return text;  }; + +  function padNumber(num, digits, trim) {    var neg = '';    if (num < 0) { @@ -42,6 +101,8 @@ function padNumber(num, digits, trim) {      num = num.substr(num.length - digits);    return neg + num;  } + +  function dateGetter(name, size, offset, trim) {    return function(date) {      var value = date['get' + name](); @@ -51,6 +112,8 @@ function dateGetter(name, size, offset, trim) {      return padNumber(value, size, trim);    };  } + +  var DATE_FORMATS = {    yyyy: dateGetter('FullYear', 4),    yy:   dateGetter('FullYear', 2, 0, true), @@ -66,15 +129,32 @@ var DATE_FORMATS = {     m:   dateGetter('Minutes', 1),    ss:   dateGetter('Seconds', 2),     s:   dateGetter('Seconds', 1), -  a:    function(date){return date.getHours() < 12 ? 'am' : 'pm'; }, +  a:    function(date){return date.getHours() < 12 ? 'am' : 'pm';},    Z:    function(date){            var offset = date.getTimezoneOffset();            return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);          }  }; + +  var DATE_FORMATS_SPLIT = /([^yMdHhmsaZ]*)(y+|M+|d+|H+|h+|m+|s+|a|Z)(.*)/;  var NUMBER_STRING = /^\d+$/; + +/** + * @ngdoc filter + * @name angular.filter.date + * @function + * + * @description + *   Formats `date` to a string based on the requested `format`. + * + * @param {(Date|number|string)} date Date to format either as Date object or milliseconds. + * @param {string=} format Formatting rules. If not specified, Date#toLocaleDateString is used. + * @returns {string} Formatted string or the input if input is not recognized as date/millis. + * + * //TODO example + scenario + */  angularFilter.date = function(date, format) {    if (isString(date) && NUMBER_STRING.test(date)) {      date = parseInt(date, 10); @@ -102,23 +182,101 @@ angularFilter.date = function(date, format) {    return text;  }; + +/** + * @ngdoc filter + * @name angular.filter.json + * @function + * + * @description + *   Allows you to convert a JavaScript object into JSON string. + * + *   This filter is mostly useful for debugging. When using the double curly {{value}} notation + *   the binding is automatically converted to JSON. + * + * @param {*} object Any JavaScript object (including arrays and primitive types) to filter. + * @returns {string} JSON string. + * + * @css ng-monospace Always applied to the encapsulating element. + * + * @example + *   <span ng:non-bindable>{{   {a:1, b:[]} | json   }}</span>: <pre>{{ {a:1, b:[]} | json }}</pre> + * + * @scenario + *   it('should jsonify filtered objects', function() { + *     expect(element('pre[ng\\:bind-template="{{ {a:1, b:[]} | json }}"]').val()).toBe( + *      '{\n  "a":1,\n  "b":[]}' + *     ); + *   } + * + */  angularFilter.json = function(object) {    this.$element.addClass("ng-monospace");    return toJson(object, true);  }; + +/** + * @ngdoc filter + * @name angular.filter.lowercase + * @function + * + * @see angular.lowercase + */  angularFilter.lowercase = lowercase; + +/** + * @ngdoc filter + * @name angular.filter.uppercase + * @function + * + * @see angular.uppercase + */  angularFilter.uppercase = uppercase; -/**</> - * @exportedAs filter:html - * @param {string=} option if 'unsafe' then do not sanitize the HTML input + +/** + * @ngdoc filter + * @name angular.filter.html + * @function + * + * @description + *   Prevents the input from getting escaped by angular. By default the input is sanitized and + *   inserted into the DOM as is. + * + *   The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are + *   then serialized back to properly escaped html string. This means that no unsafe input can make + *   it into the returned string, however since our parser is more strict than a typical browser + *   parser, it's possible that some obscure input, which would be recognized as valid HTML by a + *   browser, won't make it through the sanitizer. + * + *   If you hate your users, you may call the filter with optional 'unsafe' argument, which bypasses + *   the html sanitizer, but makes your application vulnerable to XSS and other attacks. Using this + *   option is strongly discouraged and should be used only if you absolutely trust the input being + *   filtered and you can't get the content through the sanitizer. + * + * @param {string} html Html input. + * @param {string=} option If 'unsafe' then do not sanitize the HTML input. + * @returns {string} Sanitized or raw html.   */  angularFilter.html =  function(html, option){    return new HTML(html, option);  }; + +/** + * @ngdoc filter + * @name angular.filter.linky + * @function + * + * @description + *   Finds links in text input and turns them into html links. Supports http/https/ftp/mailto links. + * + * @param {string} text Input text. + * @returns {string} Html-linkified text. + */ +//TODO: externalize all regexps  angularFilter.linky = function(text){    if (!text) return text;    function regExpEscape(text) {  | 
