diff options
| author | Di Peng | 2011-08-16 16:00:16 -0700 |
|---|---|---|
| committer | Igor Minar | 2011-08-30 02:11:09 -0700 |
| commit | e068addadb14b44374ebb5353b860700731c866f (patch) | |
| tree | 73d43d7df45af3ba46ac89bbcb515ad0452d6488 /src/widgets.js | |
| parent | 0da4902e9db4f6f494b8be74c41f21d5e5520b79 (diff) | |
| download | angular.js-e068addadb14b44374ebb5353b860700731c866f.tar.bz2 | |
feat(widget): add ng:pluralize as an Angular widget
Diffstat (limited to 'src/widgets.js')
| -rw-r--r-- | src/widgets.js | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/src/widgets.js b/src/widgets.js index 16053b08..a1c4c5d6 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -1445,3 +1445,195 @@ angularWidget('ng:view', function(element) { compiler.directives(true); } }); + + +/** + * @ngdoc widget + * @name angular.widget.ng:pluralize + * + * @description + * # Overview + * ng:pluralize is a widget that displays messages according to en-US localization rules. + * These rules are bundled with angular.js and the rules can be overridden + * (see {@link guide/dev_guide.i18n Angular i18n} dev guide). You configure ng:pluralize by + * specifying the mappings between + * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html + * plural categories} and the strings to be displayed. + * + * # Plural categories and explicit number rules + * There are two + * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html + * plural categories} in Angular's default en-US locale: "one" and "other". + * + * While a pural category may match many numbers (for example, in en-US locale, "other" can match + * any number that is not 1), an explicit number rule can only match one number. For example, the + * explicit number rule for "3" matches the number 3. You will see the use of plural categories + * and explicit number rules throughout later parts of this documentation. + * + * # Configuring ng:pluralize + * You configure ng:pluralize by providing 2 attributes: `count` and `when`. + * You can also provide an optional attribute, `offset`. + * + * The value of the `count` attribute can be either a string or an {@link guide/dev_guide.expressions + * Angular expression}; these are evaluated on the current scope for its binded value. + * + * The `when` attribute specifies the mappings between plural categories and the actual + * string to be displayed. The value of the attribute should be a JSON object so that Angular + * can interpret it correctly. + * + * The following example shows how to configure ng:pluralize: + * + * <pre> + * <ng:pluralize count="personCount" + when="{'0': 'Nobody is viewing.', + * 'one': '1 person is viewing.', + * 'other': '{} people are viewing.'}"> + * </ng:pluralize> + *</pre> + * + * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not + * specify this rule, 0 would be matched to the "other" category and "0 people are viewing" + * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for + * other numbers, for example 12, so that instead of showing "12 people are viewing", you can + * show "a dozen people are viewing". + * + * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted + * into pluralized strings. In the previous example, Angular will replace `{}` with + * <span ng:non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder + * for <span ng:non-bindable>{{numberExpression}}</span>. + * + * # Configuring ng:pluralize with offset + * The `offset` attribute allows further customization of pluralized text, which can result in + * a better user experience. For example, instead of the message "4 people are viewing this document", + * you might display "John, Kate and 2 others are viewing this document". + * The offset attribute allows you to offset a number by any desired value. + * Let's take a look at an example: + * + * <pre> + * <ng:pluralize count="personCount" offset=2 + * when="{'0': 'Nobody is viewing.', + * '1': '{{person1}} is viewing.', + * '2': '{{person1}} and {{person2}} are viewing.', + * 'one': '{{person1}}, {{person2}} and one other person are viewing.', + * 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}"> + * </ng:pluralize> + * </pre> + * + * Notice that we are still using two plural categories(one, other), but we added + * three explicit number rules 0, 1 and 2. + * When one person, perhaps John, views the document, "John is viewing" will be shown. + * When three people view the document, no explicit number rule is found, so + * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category. + * In this case, plural category 'one' is matched and "John, Marry and one other person are viewing" + * is shown. + * + * Note that when you specify offsets, you must provide explicit number rules for + * numbers from 0 up to and including the offset. If you use an offset of 3, for example, + * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for + * plural categories "one" and "other". + * + * @param {string|expression} count The variable to be bounded to. + * @param {string} when The mapping between plural category to its correspoding strings. + * @param {number=} offset Offset to deduct from the total number. + * + * @example + <doc:example> + <doc:source> + Person 1:<input type="text" name="person1" value="Igor" /><br/> + Person 2:<input type="text" name="person2" value="Misko" /><br/> + Number of People:<input type="text" name="personCount" value="1" /><br/> + + <!--- Example with simple pluralization rules for en locale ---> + Without Offset: + <ng:pluralize count="personCount" + when="{'0': 'Nobody is viewing.', + 'one': '1 person is viewing.', + 'other': '{} people are viewing.'}"> + </ng:pluralize><br> + + <!--- Example with offset ---> + With Offset(2): + <ng:pluralize count="personCount" offset=2 + when="{'0': 'Nobody is viewing.', + '1': '{{person1}} is viewing.', + '2': '{{person1}} and {{person2}} are viewing.', + 'one': '{{person1}}, {{person2}} and one other person are viewing.', + 'other': '{{person1}}, {{person2}} and {} other people are viewing.'}"> + </ng:pluralize> + </doc:source> + <doc:scenario> + it('should show correct pluralized string', function(){ + expect(element('.doc-example-live .ng-pluralize:first').text()). + toBe('1 person is viewing.'); + expect(element('.doc-example-live .ng-pluralize:last').text()). + toBe('Igor is viewing.'); + + using('.doc-example-live').input('personCount').enter('0'); + expect(element('.doc-example-live .ng-pluralize:first').text()). + toBe('Nobody is viewing.'); + expect(element('.doc-example-live .ng-pluralize:last').text()). + toBe('Nobody is viewing.'); + + using('.doc-example-live').input('personCount').enter('2'); + expect(element('.doc-example-live .ng-pluralize:first').text()). + toBe('2 people are viewing.'); + expect(element('.doc-example-live .ng-pluralize:last').text()). + toBe('Igor and Misko are viewing.'); + + using('.doc-example-live').input('personCount').enter('3'); + expect(element('.doc-example-live .ng-pluralize:first').text()). + toBe('3 people are viewing.'); + expect(element('.doc-example-live .ng-pluralize:last').text()). + toBe('Igor, Misko and one other person are viewing.'); + + using('.doc-example-live').input('personCount').enter('4'); + expect(element('.doc-example-live .ng-pluralize:first').text()). + toBe('4 people are viewing.'); + expect(element('.doc-example-live .ng-pluralize:last').text()). + toBe('Igor, Misko and 2 other people are viewing.'); + }); + + it('should show data-binded names', function(){ + using('.doc-example-live').input('personCount').enter('4'); + expect(element('.doc-example-live .ng-pluralize:last').text()). + toBe('Igor, Misko and 2 other people are viewing.'); + + using('.doc-example-live').input('person1').enter('Di'); + using('.doc-example-live').input('person2').enter('Vojta'); + expect(element('.doc-example-live .ng-pluralize:last').text()). + toBe('Di, Vojta and 2 other people are viewing.'); + }); + </doc:scenario> + </doc:example> + */ +angularWidget('ng:pluralize', function(element) { + var numberExp = element.attr('count'), + whenExp = element.attr('when'), + offset = element.attr('offset') || 0; + + return annotate('$locale', function($locale, element) { + var scope = this, + whens = scope.$eval(whenExp), + whensExpFns = {}; + + forEach(whens, function(expression, key) { + whensExpFns[key] = compileBindTemplate(expression.replace(/{}/g, + '{{' + numberExp + '-' + offset + '}}')); + }); + + scope.$watch(function() { + var value = parseFloat(scope.$eval(numberExp)); + + if (!isNaN(value)) { + //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise, + //check it against pluralization rules in $locale service + if (!whens[value]) value = $locale.pluralCat(value - offset); + return whensExpFns[value](scope, element, true); + } else { + return ''; + } + }, function(scope, newVal) { + element.text(newVal); + }); + }); +}); |
