mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-20 16:30:26 +00:00
add jsdocs for angular and filter namespaces + all filters
This commit is contained in:
parent
aec3c8478c
commit
1fe7e3a130
2 changed files with 277 additions and 10 deletions
111
src/Angular.js
111
src/Angular.js
|
|
@ -3,9 +3,30 @@
|
||||||
if (typeof document.getAttribute == $undefined)
|
if (typeof document.getAttribute == $undefined)
|
||||||
document.getAttribute = function() {};
|
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; };
|
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 uppercase = function (value){ return isString(value) ? value.toUpperCase() : value; };
|
||||||
|
|
||||||
|
|
||||||
var manualLowercase = function (s) {
|
var manualLowercase = function (s) {
|
||||||
return isString(s) ? s.replace(/[A-Z]/g,
|
return isString(s) ? s.replace(/[A-Z]/g,
|
||||||
function (ch) {return fromCharCode(ch.charCodeAt(0) | 32); }) : s;
|
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,
|
return isString(s) ? s.replace(/[a-z]/g,
|
||||||
function (ch) {return fromCharCode(ch.charCodeAt(0) & ~32); }) : s;
|
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()) {
|
if ('i' !== 'I'.toLowerCase()) {
|
||||||
lowercase = manualLowercase;
|
lowercase = manualLowercase;
|
||||||
uppercase = manualUppercase;
|
uppercase = manualUppercase;
|
||||||
|
|
@ -57,12 +83,95 @@ var _undefined = undefined,
|
||||||
slice = Array.prototype.slice,
|
slice = Array.prototype.slice,
|
||||||
push = Array.prototype.push,
|
push = Array.prototype.push,
|
||||||
error = window[$console] ? bind(window[$console], window[$console]['error'] || noop) : noop,
|
error = window[$console] ? bind(window[$console], window[$console]['error'] || noop) : noop,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name angular
|
||||||
|
* @namespace The exported angular namespace.
|
||||||
|
*/
|
||||||
angular = window[$angular] || (window[$angular] = {}),
|
angular = window[$angular] || (window[$angular] = {}),
|
||||||
angularTextMarkup = extensionMap(angular, 'markup'),
|
angularTextMarkup = extensionMap(angular, 'markup'),
|
||||||
angularAttrMarkup = extensionMap(angular, 'attrMarkup'),
|
angularAttrMarkup = extensionMap(angular, 'attrMarkup'),
|
||||||
angularDirective = extensionMap(angular, 'directive'),
|
angularDirective = extensionMap(angular, 'directive'),
|
||||||
angularWidget = extensionMap(angular, 'widget', lowercase),
|
angularWidget = extensionMap(angular, 'widget', lowercase),
|
||||||
angularValidator = extensionMap(angular, 'validator'),
|
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'),
|
angularFilter = extensionMap(angular, 'filter'),
|
||||||
angularFormatter = extensionMap(angular, 'formatter'),
|
angularFormatter = extensionMap(angular, 'formatter'),
|
||||||
angularService = extensionMap(angular, 'service'),
|
angularService = extensionMap(angular, 'service'),
|
||||||
|
|
|
||||||
176
src/filters.js
176
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){
|
angularFilter.currency = function(amount){
|
||||||
this.$element.toggleClass('ng-format-negative', amount < 0);
|
this.$element.toggleClass('ng-format-negative', amount < 0);
|
||||||
return '$' + angularFilter['number'].apply(this, [amount, 2]);
|
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 '';
|
return '';
|
||||||
}
|
}
|
||||||
fractionSize = typeof fractionSize == $undefined ? 2 : fractionSize;
|
fractionSize = typeof fractionSize == $undefined ? 2 : fractionSize;
|
||||||
var isNegative = amount < 0;
|
var isNegative = number < 0;
|
||||||
amount = Math.abs(amount);
|
number = Math.abs(number);
|
||||||
var pow = Math.pow(10, fractionSize);
|
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);
|
var whole = text.substring(0, text.length - fractionSize);
|
||||||
whole = whole || '0';
|
whole = whole || '0';
|
||||||
var frc = text.substring(text.length - fractionSize);
|
var frc = text.substring(text.length - fractionSize);
|
||||||
|
|
@ -30,6 +87,8 @@ angularFilter.number = function(amount, fractionSize){
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
function padNumber(num, digits, trim) {
|
function padNumber(num, digits, trim) {
|
||||||
var neg = '';
|
var neg = '';
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
|
|
@ -42,6 +101,8 @@ function padNumber(num, digits, trim) {
|
||||||
num = num.substr(num.length - digits);
|
num = num.substr(num.length - digits);
|
||||||
return neg + num;
|
return neg + num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function dateGetter(name, size, offset, trim) {
|
function dateGetter(name, size, offset, trim) {
|
||||||
return function(date) {
|
return function(date) {
|
||||||
var value = date['get' + name]();
|
var value = date['get' + name]();
|
||||||
|
|
@ -51,6 +112,8 @@ function dateGetter(name, size, offset, trim) {
|
||||||
return padNumber(value, size, trim);
|
return padNumber(value, size, trim);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var DATE_FORMATS = {
|
var DATE_FORMATS = {
|
||||||
yyyy: dateGetter('FullYear', 4),
|
yyyy: dateGetter('FullYear', 4),
|
||||||
yy: dateGetter('FullYear', 2, 0, true),
|
yy: dateGetter('FullYear', 2, 0, true),
|
||||||
|
|
@ -66,15 +129,32 @@ var DATE_FORMATS = {
|
||||||
m: dateGetter('Minutes', 1),
|
m: dateGetter('Minutes', 1),
|
||||||
ss: dateGetter('Seconds', 2),
|
ss: dateGetter('Seconds', 2),
|
||||||
s: dateGetter('Seconds', 1),
|
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){
|
Z: function(date){
|
||||||
var offset = date.getTimezoneOffset();
|
var offset = date.getTimezoneOffset();
|
||||||
return padNumber(offset / 60, 2) + padNumber(Math.abs(offset % 60), 2);
|
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 DATE_FORMATS_SPLIT = /([^yMdHhmsaZ]*)(y+|M+|d+|H+|h+|m+|s+|a|Z)(.*)/;
|
||||||
var NUMBER_STRING = /^\d+$/;
|
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) {
|
angularFilter.date = function(date, format) {
|
||||||
if (isString(date) && NUMBER_STRING.test(date)) {
|
if (isString(date) && NUMBER_STRING.test(date)) {
|
||||||
date = parseInt(date, 10);
|
date = parseInt(date, 10);
|
||||||
|
|
@ -102,23 +182,101 @@ angularFilter.date = function(date, format) {
|
||||||
return text;
|
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) {
|
angularFilter.json = function(object) {
|
||||||
this.$element.addClass("ng-monospace");
|
this.$element.addClass("ng-monospace");
|
||||||
return toJson(object, true);
|
return toJson(object, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc filter
|
||||||
|
* @name angular.filter.lowercase
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @see angular.lowercase
|
||||||
|
*/
|
||||||
angularFilter.lowercase = lowercase;
|
angularFilter.lowercase = lowercase;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ngdoc filter
|
||||||
|
* @name angular.filter.uppercase
|
||||||
|
* @function
|
||||||
|
*
|
||||||
|
* @see angular.uppercase
|
||||||
|
*/
|
||||||
angularFilter.uppercase = 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){
|
angularFilter.html = function(html, option){
|
||||||
return new HTML(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){
|
angularFilter.linky = function(text){
|
||||||
if (!text) return text;
|
if (!text) return text;
|
||||||
function regExpEscape(text) {
|
function regExpEscape(text) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue