From ba6b68b6ae2bb2400a75ca2834fee47bfd60f1c6 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Mon, 31 Jan 2011 16:21:29 -0800 Subject: changed the documentation @example to use --- src/Angular.js | 92 ++++--- src/Compiler.js | 68 +++--- src/Scope.js | 46 ++-- src/angular-mocks.js | 26 +- src/apis.js | 530 +++++++++++++++++++++------------------- src/directives.js | 676 +++++++++++++++++++++++++++------------------------ src/filters.js | 351 +++++++++++++------------- src/formatters.js | 197 ++++++++------- src/services.js | 233 +++++++++++------- src/validators.js | 309 ++++++++++++----------- src/widgets.js | 554 +++++++++++++++++++++-------------------- 11 files changed, 1666 insertions(+), 1416 deletions(-) (limited to 'src') diff --git a/src/Angular.js b/src/Angular.js index 2812c926..de2de30d 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -484,14 +484,18 @@ function map(obj, iterator, context) { * @returns {number} The size of `obj` or `0` if `obj` is neither an object or an array. * * @example - * Number of items in array: {{ [1,2].$size() }}
- * Number of items in object: {{ {a:1, b:2, c:3}.$size() }}
- * - * @scenario - it('should print correct sizes for an array and an object', function() { - expect(binding('[1,2].$size()')).toBe('2'); - expect(binding('{a:1, b:2, c:3}.$size()')).toBe('3'); - }); + * + * + * Number of items in array: {{ [1,2].$size() }}
+ * Number of items in object: {{ {a:1, b:2, c:3}.$size() }}
+ *
+ * + * it('should print correct sizes for an array and an object', function() { + * expect(binding('[1,2].$size()')).toBe('2'); + * expect(binding('{a:1, b:2, c:3}.$size()')).toBe('3'); + * }); + * + *
*/ function size(obj) { var size = 0, key; @@ -556,17 +560,19 @@ function isLeafNode (node) { * @returns {*} The copy or updated `destination` if `destination` was specified. * * @example - Salutation:
- Name:
- -
- - The master object is NOT equal to the form object. - -
master={{master}}
-
form={{form}}
- - * @scenario + * + * + Salutation:
+ Name:
+ +
+ + The master object is NOT equal to the form object. + +
master={{master}}
+
form={{form}}
+ *
+ * it('should print that initialy the form object is NOT equal to master', function() { expect(element('.doc-example input[name=master.salutation]').val()).toBe('Hello'); expect(element('.doc-example input[name=master.name]').val()).toBe('world'); @@ -577,6 +583,8 @@ function isLeafNode (node) { element('.doc-example button').click(); expect(element('.doc-example span').css('display')).toBe('none'); }); + * + *
*/ function copy(source, destination){ if (!destination) { @@ -633,27 +641,31 @@ function copy(source, destination){ * @returns {boolean} True if arguments are equal. * * @example - Salutation:
- Name:
-
- - The greeting object is - NOT equal to - {salutation:'Hello', name:'world'}. - -
greeting={{greeting}}
- - @scenario - it('should print that initialy greeting is equal to the hardcoded value object', function() { - expect(element('.doc-example input[name=greeting.salutation]').val()).toBe('Hello'); - expect(element('.doc-example input[name=greeting.name]').val()).toBe('world'); - expect(element('.doc-example span').css('display')).toBe('none'); - }); - - it('should say that the objects are not equal when the form is modified', function() { - input('greeting.name').enter('kitty'); - expect(element('.doc-example span').css('display')).toBe('inline'); - }); + * + * + Salutation:
+ Name:
+
+ + The greeting object is + NOT equal to + {salutation:'Hello', name:'world'}. + +
greeting={{greeting}}
+ *
+ * + it('should print that initialy greeting is equal to the hardcoded value object', function() { + expect(element('.doc-example input[name=greeting.salutation]').val()).toBe('Hello'); + expect(element('.doc-example input[name=greeting.name]').val()).toBe('world'); + expect(element('.doc-example span').css('display')).toBe('none'); + }); + + it('should say that the objects are not equal when the form is modified', function() { + input('greeting.name').enter('kitty'); + expect(element('.doc-example span').css('display')).toBe('inline'); + }); + * + *
*/ function equals(o1, o2) { if (o1 == o2) return true; diff --git a/src/Compiler.js b/src/Compiler.js index c2c56650..472ec625 100644 --- a/src/Compiler.js +++ b/src/Compiler.js @@ -139,40 +139,44 @@ Compiler.prototype = { * @element ANY * @param {integer|string=} [priority=0] priority integer, or FIRST, LAST constant * - * @exampleDescription + * @example * try changing the invoice and see that the Total will lag in evaluation * @example -
TOTAL: without ng:eval-order {{ items.$sum('total') | currency }}
-
TOTAL: with ng:eval-order {{ items.$sum('total') | currency }}
- - - - - - - - - - - - - - - - - - - -
QTYDescriptionCostTotal
{{item.total = item.qty * item.cost | currency}}X
add{{ items.$sum('total') | currency }}
- * - * @scenario - it('should check ng:format', function(){ - expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99'); - expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$9.99'); - input('item.qty').enter('2'); - expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99'); - expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$19.98'); - }); + + +
TOTAL: without ng:eval-order {{ items.$sum('total') | currency }}
+
TOTAL: with ng:eval-order {{ items.$sum('total') | currency }}
+ + + + + + + + + + + + + + + + + + + +
QTYDescriptionCostTotal
{{item.total = item.qty * item.cost | currency}}X
add{{ items.$sum('total') | currency }}
+
+ + it('should check ng:format', function(){ + expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99'); + expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$9.99'); + input('item.qty').enter('2'); + expect(using('.doc-example-live div:first').binding("items.$sum('total')")).toBe('$9.99'); + expect(using('.doc-example-live div:last').binding("items.$sum('total')")).toBe('$19.98'); + }); + +
*/ templatize: function(element, elementIndex, priority){ diff --git a/src/Scope.js b/src/Scope.js index aef2706e..a73375ab 100644 --- a/src/Scope.js +++ b/src/Scope.js @@ -202,7 +202,7 @@ function errorHandlerFor(element, error) { * @returns {Object} Newly created scope. * * - * @exampleDescription + * @example * This example demonstrates scope inheritance and property overriding. * * In this example, the root scope encompasses the whole HTML DOM tree. This scope has `salutation`, @@ -216,27 +216,29 @@ function errorHandlerFor(element, error) { * - The child scope inherits the salutation property from the root scope. * - The $index property does not leak from the child scope to the root scope. * - * @example - -
-   $index={{$index}}
-   salutation={{salutation}}
-   name={{name}}
- - @scenario - it('should inherit the salutation property and override the name property', function() { - expect(using('.doc-example-live').repeater('li').row(0)). - toEqual(['0', 'Hello', 'World']); - expect(using('.doc-example-live').repeater('li').row(1)). - toEqual(['1', 'Hello', 'Earth']); - expect(using('.doc-example-live').element('pre').text()). - toBe('$index=\nsalutation=Hello\nname=Misko'); - }); - + + +
    +
  • + {{$index}}: {{salutation}} {{name}}! +
  • +
+
+       $index={{$index}}
+       salutation={{salutation}}
+       name={{name}}
+
+ + it('should inherit the salutation property and override the name property', function() { + expect(using('.doc-example-live').repeater('li').row(0)). + toEqual(['0', 'Hello', 'World']); + expect(using('.doc-example-live').repeater('li').row(1)). + toEqual(['1', 'Hello', 'Earth']); + expect(using('.doc-example-live').element('pre').text()). + toBe('$index=\nsalutation=Hello\nname=Misko'); + }); + +
*/ function createScope(parent, providers, instanceCache) { function Parent(){} diff --git a/src/angular-mocks.js b/src/angular-mocks.js index fe0fb011..71a18d06 100644 --- a/src/angular-mocks.js +++ b/src/angular-mocks.js @@ -239,10 +239,10 @@ angular.service('$exceptionHandler', function(e) { */ angular.service('$log', function() { var $log = { - log: function(){ $log.logs.push(arguments) }, - warn: function(){ $log.logs.push(arguments) }, - info: function(){ $log.logs.push(arguments) }, - error: function(){ $log.logs.push(arguments) } + log: function(){ $log.logs.push(arguments); }, + warn: function(){ $log.logs.push(arguments); }, + info: function(){ $log.logs.push(arguments); }, + error: function(){ $log.logs.push(arguments); } }; $log.log.logs = []; @@ -265,6 +265,15 @@ angular.service('$log', function() { * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC* * * @example + * !!!! WARNING !!!!! + * This is not a complete Date object so only methods that were implemented can be called safely. + * To make matters worse, TzDate instances inherit stuff from Date via a prototype. + * + * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is + * incomplete we might be missing some non-standard methods. This can result in errors like: + * "Date.prototype.foo called on incompatible Object". + * + *
  * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
  * newYearInBratislava.getTimezoneOffset() => -60;
  * newYearInBratislava.getFullYear() => 2010;
@@ -272,15 +281,8 @@ angular.service('$log', function() {
  * newYearInBratislava.getDate() => 1;
  * newYearInBratislava.getHours() => 0;
  * newYearInBratislava.getMinutes() => 0;
+ * 
* - * - * !!!! WARNING !!!!! - * This is not a complete Date object so only methods that were implemented can be called safely. - * To make matters worse, TzDate instances inherit stuff from Date via a prototype. - * - * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is - * incomplete we might be missing some non-standard methods. This can result in errors like: - * "Date.prototype.foo called on incompatible Object". */ function TzDate(offset, timestamp) { if (angular.isString(timestamp)) { diff --git a/src/apis.js b/src/apis.js index 35e3a92f..437cd6e0 100644 --- a/src/apis.js +++ b/src/apis.js @@ -79,22 +79,26 @@ var angularArray = { * @returns {number} The position of the element in `array`. The position is 0-based. `-1` is returned if the value can't be found. * * @example -
-
- Index of '{{bookName}}' in the list {{books}} is {{books.$indexOf(bookName)}}. - - @scenario - it('should correctly calculate the initial index', function() { - expect(binding('books.$indexOf(bookName)')).toBe('2'); - }); - - it('should recalculate', function() { - input('bookName').enter('foo'); - expect(binding('books.$indexOf(bookName)')).toBe('-1'); - - input('bookName').enter('Moby Dick'); - expect(binding('books.$indexOf(bookName)')).toBe('0'); - }); + + +
+
+ Index of '{{bookName}}' in the list {{books}} is {{books.$indexOf(bookName)}}. +
+ + it('should correctly calculate the initial index', function() { + expect(binding('books.$indexOf(bookName)')).toBe('2'); + }); + + it('should recalculate', function() { + input('bookName').enter('foo'); + expect(binding('books.$indexOf(bookName)')).toBe('-1'); + + input('bookName').enter('Moby Dick'); + expect(binding('books.$indexOf(bookName)')).toBe('0'); + }); + +
*/ 'indexOf': indexOf, @@ -117,42 +121,46 @@ var angularArray = { * @returns {number} Sum of items in the array. * * @example - - - - - - - - - - - - - - - -
QtyDescriptionCostTotal
{{item.qty * item.cost | currency}}[X]
add itemTotal:{{invoice.items.$sum('qty*cost') | currency}}
- - @scenario - //TODO: these specs are lame because I had to work around issues #164 and #167 - it('should initialize and calculate the totals', function() { - expect(repeater('.doc-example-live table tr', 'item in invoice.items').count()).toBe(3); - expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(1)). - toEqual(['$99.50']); - expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); - expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); - }); - - it('should add an entry and recalculate', function() { - element('.doc-example a:contains("add item")').click(); - using('.doc-example-live tr:nth-child(3)').input('item.qty').enter('20'); - using('.doc-example-live tr:nth-child(3)').input('item.cost').enter('100'); - - expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(2)). - toEqual(['$2,000.00']); - expect(binding("invoice.items.$sum('qty*cost')")).toBe('$2,099.50'); - }); + + + + + + + + + + + + + + + + + +
QtyDescriptionCostTotal
{{item.qty * item.cost | currency}}[X]
add itemTotal:{{invoice.items.$sum('qty*cost') | currency}}
+
+ + //TODO: these specs are lame because I had to work around issues #164 and #167 + it('should initialize and calculate the totals', function() { + expect(repeater('.doc-example-live table tr', 'item in invoice.items').count()).toBe(3); + expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(1)). + toEqual(['$99.50']); + expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); + expect(binding("invoice.items.$sum('qty*cost')")).toBe('$99.50'); + }); + + it('should add an entry and recalculate', function() { + element('.doc-example a:contains("add item")').click(); + using('.doc-example-live tr:nth-child(3)').input('item.qty').enter('20'); + using('.doc-example-live tr:nth-child(3)').input('item.cost').enter('100'); + + expect(repeater('.doc-example-live table tr', 'item in invoice.items').row(2)). + toEqual(['$2,000.00']); + expect(binding("invoice.items.$sum('qty*cost')")).toBe('$2,099.50'); + }); + +
*/ 'sum':function(array, expression) { var fn = angular['Function']['compile'](expression); @@ -185,33 +193,37 @@ var angularArray = { * @returns {*} The removed element. * * @example - -
- tasks = {{tasks}} - - @scenario - it('should initialize the task list with for tasks', function() { - expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(4); - expect(repeater('.doc-example ul li', 'task in tasks').column('task')). - toEqual(['Learn Angular', 'Read Documentation', 'Check out demos', - 'Build cool applications']); - }); - - it('should initialize the task list with for tasks', function() { - element('.doc-example ul li a:contains("X"):first').click(); - expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(3); - - element('.doc-example ul li a:contains("X"):last').click(); - expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(2); - - expect(repeater('.doc-example ul li', 'task in tasks').column('task')). - toEqual(['Read Documentation', 'Check out demos']); - }); + + +
    +
  • + {{task}} [X] +
  • +
+
+ tasks = {{tasks}} +
+ + it('should initialize the task list with for tasks', function() { + expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(4); + expect(repeater('.doc-example ul li', 'task in tasks').column('task')). + toEqual(['Learn Angular', 'Read Documentation', 'Check out demos', + 'Build cool applications']); + }); + + it('should initialize the task list with for tasks', function() { + element('.doc-example ul li a:contains("X"):first').click(); + expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(3); + + element('.doc-example ul li a:contains("X"):last').click(); + expect(repeater('.doc-example ul li', 'task in tasks').count()).toBe(2); + + expect(repeater('.doc-example ul li', 'task in tasks').column('task')). + toEqual(['Read Documentation', 'Check out demos']); + }); + +
*/ 'remove':function(array, value) { var index = indexOf(array, value); @@ -254,48 +266,52 @@ var angularArray = { * the predicate returned true for. * * @example -
- - Search: - - - - - - -
NamePhone
{{friend.name}}{{friend.phone}}
-
- Any:
- Name only
- Phone only
- - - - - - -
NamePhone
{{friend.name}}{{friend.phone}}
- - @scenario - it('should search across all fields when filtering with a string', function() { - input('searchText').enter('m'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). - toEqual(['Mary', 'Mike', 'Adam']); - - input('searchText').enter('76'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). - toEqual(['John', 'Julie']); - }); - - it('should search in specific fields when filtering with a predicate object', function() { - input('search.$').enter('i'); - expect(repeater('#searchObjResults tr', 'friend in friends').column('name')). - toEqual(['Mary', 'Mike', 'Julie']); - }); + + +
+ + Search: + + + + + + +
NamePhone
{{friend.name}}{{friend.phone}}
+
+ Any:
+ Name only
+ Phone only
+ + + + + + +
NamePhone
{{friend.name}}{{friend.phone}}
+
+ + it('should search across all fields when filtering with a string', function() { + input('searchText').enter('m'); + expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). + toEqual(['Mary', 'Mike', 'Adam']); + + input('searchText').enter('76'); + expect(repeater('#searchTextResults tr', 'friend in friends').column('name')). + toEqual(['John', 'Julie']); + }); + + it('should search in specific fields when filtering with a predicate object', function() { + input('search.$').enter('i'); + expect(repeater('#searchObjResults tr', 'friend in friends').column('name')). + toEqual(['Mary', 'Mike', 'Julie']); + }); + +
*/ 'filter':function(array, expression) { var predicates = []; @@ -398,53 +414,55 @@ var angularArray = { * * @TODO simplify the example. * - * @exampleDescription + * @example * This example shows how an initially empty array can be filled with objects created from user * input via the `$add` method. - * - * @example - [add empty] - [add 'John'] - [add 'Mary'] - - -
people = {{people}}
- - @scenario - beforeEach(function() { - expect(binding('people')).toBe('people = []'); - }); - - it('should create an empty record when "add empty" is clicked', function() { - element('.doc-example a:contains("add empty")').click(); - expect(binding('people')).toBe('people = [{\n "name":"",\n "sex":null}]'); - }); - - it('should create a "John" record when "add \'John\'" is clicked', function() { - element('.doc-example a:contains("add \'John\'")').click(); - expect(binding('people')).toBe('people = [{\n "name":"John",\n "sex":"male"}]'); - }); - - it('should create a "Mary" record when "add \'Mary\'" is clicked', function() { - element('.doc-example a:contains("add \'Mary\'")').click(); - expect(binding('people')).toBe('people = [{\n "name":"Mary",\n "sex":"female"}]'); - }); - - it('should delete a record when "X" is clicked', function() { - element('.doc-example a:contains("add empty")').click(); - element('.doc-example li a:contains("X"):first').click(); - expect(binding('people')).toBe('people = []'); - }); + + + [add empty] + [add 'John'] + [add 'Mary'] + +
    +
  • + + + [X] +
  • +
+
people = {{people}}
+
+ + beforeEach(function() { + expect(binding('people')).toBe('people = []'); + }); + + it('should create an empty record when "add empty" is clicked', function() { + element('.doc-example a:contains("add empty")').click(); + expect(binding('people')).toBe('people = [{\n "name":"",\n "sex":null}]'); + }); + + it('should create a "John" record when "add \'John\'" is clicked', function() { + element('.doc-example a:contains("add \'John\'")').click(); + expect(binding('people')).toBe('people = [{\n "name":"John",\n "sex":"male"}]'); + }); + + it('should create a "Mary" record when "add \'Mary\'" is clicked', function() { + element('.doc-example a:contains("add \'Mary\'")').click(); + expect(binding('people')).toBe('people = [{\n "name":"Mary",\n "sex":"female"}]'); + }); + + it('should delete a record when "X" is clicked', function() { + element('.doc-example a:contains("add empty")').click(); + element('.doc-example li a:contains("X"):first').click(); + expect(binding('people')).toBe('people = []'); + }); + +
*/ 'add':function(array, value) { array.push(isUndefined(value)? {} : value); @@ -471,29 +489,33 @@ var angularArray = { * @returns {number} Number of elements in the array (for which the condition evaluates to true). * * @example -

-     
-     

Number of items which have one point: {{ items.$count('points==1') }}

-

Number of items which have more than one point: {{items.$count('points>1')}}

- - @scenario - it('should calculate counts', function() { - expect(binding('items.$count(\'points==1\')')).toEqual(2); - expect(binding('items.$count(\'points>1\')')).toEqual(1); - }); - - it('should recalculate when updated', function() { - using('.doc-example li:first-child').input('item.points').enter('23'); - expect(binding('items.$count(\'points==1\')')).toEqual(1); - expect(binding('items.$count(\'points>1\')')).toEqual(2); - }); + + +

+         
    +
  • + {{item.name}}: points= + +
  • +
+

Number of items which have one point: {{ items.$count('points==1') }}

+

Number of items which have more than one point: {{items.$count('points>1')}}

+
+ + it('should calculate counts', function() { + expect(binding('items.$count(\'points==1\')')).toEqual(2); + expect(binding('items.$count(\'points>1\')')).toEqual(1); + }); + + it('should recalculate when updated', function() { + using('.doc-example li:first-child').input('item.points').enter('23'); + expect(binding('items.$count(\'points==1\')')).toEqual(1); + expect(binding('items.$count(\'points>1\')')).toEqual(2); + }); + +
*/ 'count':function(array, condition) { if (!condition) return array.length; @@ -535,52 +557,56 @@ var angularArray = { * @returns {Array} Sorted copy of the source array. * * @example -
- -
Sorting predicate = {{predicate}}
-
- - - - - - - - - - - -
Name - (^)Phone - (^)Age - (^)
{{friend.name}}{{friend.phone}}{{friend.age}}
- - @scenario - it('should be reverse ordered by aged', function() { - expect(binding('predicate')).toBe('Sorting predicate = -age'); - expect(repeater('.doc-example table', 'friend in friends').column('friend.age')). - toEqual(['35', '29', '21', '19', '10']); - expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); - }); - - it('should reorder the table when user selects different predicate', function() { - element('.doc-example a:contains("Name")').click(); - expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); - expect(repeater('.doc-example table', 'friend in friends').column('friend.age')). - toEqual(['35', '10', '29', '19', '21']); - - element('.doc-example a:contains("Phone")+a:contains("^")').click(); - expect(repeater('.doc-example table', 'friend in friends').column('friend.phone')). - toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); - expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); - }); + + +
+ +
Sorting predicate = {{predicate}}
+
+ + + + + + + + + + + +
Name + (^)Phone + (^)Age + (^)
{{friend.name}}{{friend.phone}}{{friend.age}}
+
+ + it('should be reverse ordered by aged', function() { + expect(binding('predicate')).toBe('Sorting predicate = -age'); + expect(repeater('.doc-example table', 'friend in friends').column('friend.age')). + toEqual(['35', '29', '21', '19', '10']); + expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). + toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); + }); + + it('should reorder the table when user selects different predicate', function() { + element('.doc-example a:contains("Name")').click(); + expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). + toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); + expect(repeater('.doc-example table', 'friend in friends').column('friend.age')). + toEqual(['35', '10', '29', '19', '21']); + + element('.doc-example a:contains("Phone")+a:contains("^")').click(); + expect(repeater('.doc-example table', 'friend in friends').column('friend.phone')). + toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); + expect(repeater('.doc-example table', 'friend in friends').column('friend.name')). + toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); + }); + +
*/ //TODO: WTH is descend param for and how/when it should be used, how is it affected by +/- in // predicate? the code below is impossible to read and specs are not very good. @@ -648,21 +674,25 @@ var angularArray = { * @returns {Array} A new sub-array of length `limit`. * * @example -
- Limit [1,2,3,4,5,6,7,8,9] to: -

Output: {{ numbers.$limitTo(limit) | json }}

-
- - * @scenario - it('should limit the numer array to first three items', function() { - expect(element('.doc-example input[name=limit]').val()).toBe('3'); - expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]'); - }); - - it('should update the output when -3 is entered', function() { - input('limit').enter(-3); - expect(binding('numbers.$limitTo(limit) | json')).toEqual('[7,8,9]'); - }); + + +
+ Limit [1,2,3,4,5,6,7,8,9] to: +

Output: {{ numbers.$limitTo(limit) | json }}

+
+
+ + it('should limit the numer array to first three items', function() { + expect(element('.doc-example input[name=limit]').val()).toBe('3'); + expect(binding('numbers.$limitTo(limit) | json')).toEqual('[1,2,3]'); + }); + + it('should update the output when -3 is entered', function() { + input('limit').enter(-3); + expect(binding('numbers.$limitTo(limit) | json')).toEqual('[7,8,9]'); + }); + +
*/ limitTo: function(array, limit) { limit = parseInt(limit, 10); diff --git a/src/directives.js b/src/directives.js index 104ff9c8..5ca7c2ec 100644 --- a/src/directives.js +++ b/src/directives.js @@ -4,22 +4,26 @@ * @name angular.directive.ng:init * * @description - * `ng:init` attribute allows the for initialization tasks to be executed + * `ng:init` attribute allows the for initialization tasks to be executed * before the template enters execution mode during bootstrap. * * @element ANY * @param {expression} expression to eval. * * @example + +
{{greeting}} {{person}}!
- * - * @scenario - it('should check greeting', function(){ - expect(binding('greeting')).toBe('Hello'); - expect(binding('person')).toBe('World'); - }); +
+ + it('should check greeting', function(){ + expect(binding('greeting')).toBe('Hello'); + expect(binding('person')).toBe('World'); + }); + +
*/ angularDirective("ng:init", function(expression){ return function(element){ @@ -33,66 +37,70 @@ angularDirective("ng:init", function(expression){ * @name angular.directive.ng:controller * * @description - * To support the Model-View-Controller design pattern, it is possible - * to assign behavior to a scope through `ng:controller`. The scope is - * the MVC model. The HTML (with data bindings) is the MVC view. + * To support the Model-View-Controller design pattern, it is possible + * to assign behavior to a scope through `ng:controller`. The scope is + * the MVC model. The HTML (with data bindings) is the MVC view. * The `ng:controller` directive specifies the MVC controller class * * @element ANY * @param {expression} expression to eval. * * @example - -
- Name: - [ greet ]
- Contact: - -
- * - * @scenario - it('should check controller', function(){ - expect(element('.doc-example-live div>:input').val()).toBe('John Smith'); - expect(element('.doc-example-live li[ng\\:repeat-index="0"] input').val()).toBe('408 555 1212'); - expect(element('.doc-example-live li[ng\\:repeat-index="1"] input').val()).toBe('john.smith@example.org'); - element('.doc-example-live li:first a:contains("clear")').click(); - expect(element('.doc-example-live li:first input').val()).toBe(''); - element('.doc-example-live li:last a:contains("add")').click(); - expect(element('.doc-example-live li[ng\\:repeat-index="2"] input').val()).toBe('yourname@example.org'); - }); + + + +
+ Name: + [ greet ]
+ Contact: +
    +
  • + + + [ clear + | X ] +
  • +
  • [ add ]
  • +
+
+
+ + it('should check controller', function(){ + expect(element('.doc-example-live div>:input').val()).toBe('John Smith'); + expect(element('.doc-example-live li[ng\\:repeat-index="0"] input').val()).toBe('408 555 1212'); + expect(element('.doc-example-live li[ng\\:repeat-index="1"] input').val()).toBe('john.smith@example.org'); + element('.doc-example-live li:first a:contains("clear")').click(); + expect(element('.doc-example-live li:first input').val()).toBe(''); + element('.doc-example-live li:last a:contains("add")').click(); + expect(element('.doc-example-live li[ng\\:repeat-index="2"] input').val()).toBe('yourname@example.org'); + }); + +
*/ angularDirective("ng:controller", function(expression){ this.scope(true); @@ -112,36 +120,38 @@ angularDirective("ng:controller", function(expression){ * @name angular.directive.ng:eval * * @description - * The `ng:eval` allows you to execute a binding which has side effects + * The `ng:eval` allows you to execute a binding which has side effects * without displaying the result to the user. * * @element ANY * @param {expression} expression to eval. * - * @exampleDescription - * Notice that `{{` `obj.multiplied = obj.a * obj.b` `}}` has a side effect of assigning - * a value to `obj.multiplied` and displaying the result to the user. Sometimes, - * however, it is desirable to execute a side effect without showing the value to - * the user. In such a case `ng:eval` allows you to execute code without updating - * the display. - * * @example - * - * * - * = {{obj.multiplied = obj.a * obj.b}}
- * - * - * obj.divide = {{obj.divide}}
- * obj.updateCount = {{obj.updateCount}} - * - * @scenario - it('should check eval', function(){ - expect(binding('obj.divide')).toBe('3'); - expect(binding('obj.updateCount')).toBe('2'); - input('obj.a').enter('12'); - expect(binding('obj.divide')).toBe('6'); - expect(binding('obj.updateCount')).toBe('3'); - }); + * Notice that `{{` `obj.multiplied = obj.a * obj.b` `}}` has a side effect of assigning + * a value to `obj.multiplied` and displaying the result to the user. Sometimes, + * however, it is desirable to execute a side effect without showing the value to + * the user. In such a case `ng:eval` allows you to execute code without updating + * the display. + + + + * + = {{obj.multiplied = obj.a * obj.b}}
+ + + obj.divide = {{obj.divide}}
+ obj.updateCount = {{obj.updateCount}} +
+ + it('should check eval', function(){ + expect(binding('obj.divide')).toBe('3'); + expect(binding('obj.updateCount')).toBe('2'); + input('obj.a').enter('12'); + expect(binding('obj.divide')).toBe('6'); + expect(binding('obj.updateCount')).toBe('3'); + }); + +
*/ angularDirective("ng:eval", function(expression){ return function(element){ @@ -155,27 +165,30 @@ angularDirective("ng:eval", function(expression){ * @name angular.directive.ng:bind * * @description - * The `ng:bind` attribute asks to replace the text content of this - * HTML element with the value of the given expression and kept it up to - * date when the expression's value changes. Usually you just write - * {{expression}} and let compile it into + * The `ng:bind` attribute asks to replace the text content of this + * HTML element with the value of the given expression and kept it up to + * date when the expression's value changes. Usually you just write + * {{expression}} and let compile it into * `` at bootstrap time. - * + * * @element ANY * @param {expression} expression to eval. * - * @exampleDescription - * Try it here: enter text in text box and watch the greeting change. * @example - * Enter name: .
- * Hello ! - * - * @scenario - it('should check ng:bind', function(){ - expect(using('.doc-example-live').binding('name')).toBe('Whirled'); - using('.doc-example-live').input('name').enter('world'); - expect(using('.doc-example-live').binding('name')).toBe('world'); - }); + * Try it here: enter text in text box and watch the greeting change. + + + Enter name: .
+ Hello ! +
+ + it('should check ng:bind', function(){ + expect(using('.doc-example-live').binding('name')).toBe('Whirled'); + using('.doc-example-live').input('name').enter('world'); + expect(using('.doc-example-live').binding('name')).toBe('world'); + }); + +
*/ angularDirective("ng:bind", function(expression, element){ element.addClass('ng-binding'); @@ -259,32 +272,35 @@ function compileBindTemplate(template){ * @name angular.directive.ng:bind-template * * @description - * The `ng:bind-template` attribute specifies that the element - * text should be replaced with the template in ng:bind-template. - * Unlike ng:bind the ng:bind-template can contain multiple `{{` `}}` - * expressions. (This is required since some HTML elements + * The `ng:bind-template` attribute specifies that the element + * text should be replaced with the template in ng:bind-template. + * Unlike ng:bind the ng:bind-template can contain multiple `{{` `}}` + * expressions. (This is required since some HTML elements * can not have SPAN elements such as TITLE, or OPTION to name a few. - * + * * @element ANY * @param {string} template of form * {{ expression }} to eval. * - * @exampleDescription - * Try it here: enter text in text box and watch the greeting change. * @example - Salutation:
- Name:
-

- * 
- * @scenario
-   it('should check ng:bind', function(){
-     expect(using('.doc-example-live').binding('{{salutation}} {{name}}')).
-       toBe('Hello World!');
-     using('.doc-example-live').input('salutation').enter('Greetings');
-     using('.doc-example-live').input('name').enter('user');
-     expect(using('.doc-example-live').binding('{{salutation}} {{name}}')).
-       toBe('Greetings user!');
-   });
+ * Try it here: enter text in text box and watch the greeting change.
+   
+     
+      Salutation: 
+ Name:
+

+     
+ + it('should check ng:bind', function(){ + expect(using('.doc-example-live').binding('{{salutation}} {{name}}')). + toBe('Hello World!'); + using('.doc-example-live').input('salutation').enter('Greetings'); + using('.doc-example-live').input('name').enter('user'); + expect(using('.doc-example-live').binding('{{salutation}} {{name}}')). + toBe('Greetings user!'); + }); + +
*/ angularDirective("ng:bind-template", function(expression, element){ element.addClass('ng-binding'); @@ -313,49 +329,52 @@ var REMOVE_ATTRIBUTES = { * @name angular.directive.ng:bind-attr * * @description - * The `ng:bind-attr` attribute specifies that the element attributes - * which should be replaced by the expression in it. Unlike `ng:bind` - * the `ng:bind-attr` contains a JSON key value pairs representing - * which attributes need to be changed. You don’t usually write the - * `ng:bind-attr` in the HTML since embedding - * {{expression}} into the + * The `ng:bind-attr` attribute specifies that the element attributes + * which should be replaced by the expression in it. Unlike `ng:bind` + * the `ng:bind-attr` contains a JSON key value pairs representing + * which attributes need to be changed. You don’t usually write the + * `ng:bind-attr` in the HTML since embedding + * {{expression}} into the * attribute directly is the preferred way. The attributes get * translated into `` at * bootstrap time. - * + * * This HTML snippet is preferred way of working with `ng:bind-attr` *
  *   Google
  * 
- * + * * The above gets translated to bellow during bootstrap time. *
  *   Google
  * 
- * + * * @element ANY - * @param {string} attribute_json a JSON key-value pairs representing - * the attributes to replace. Each key matches the attribute - * which needs to be replaced. Each value is a text template of - * the attribute with embedded - * {{expression}}s. Any number of + * @param {string} attribute_json a JSON key-value pairs representing + * the attributes to replace. Each key matches the attribute + * which needs to be replaced. Each value is a text template of + * the attribute with embedded + * {{expression}}s. Any number of * key-value pairs can be specified. * - * @exampleDescription - * Try it here: enter text in text box and click Google. * @example - Google for: - - Google - * - * @scenario - it('should check ng:bind-attr', function(){ - expect(using('.doc-example-live').element('a').attr('href')). - toBe('http://www.google.com/search?q=AngularJS'); - using('.doc-example-live').input('query').enter('google'); - expect(using('.doc-example-live').element('a').attr('href')). - toBe('http://www.google.com/search?q=google'); - }); + * Try it here: enter text in text box and click Google. + + + Google for: + + Google + + + it('should check ng:bind-attr', function(){ + expect(using('.doc-example-live').element('a').attr('href')). + toBe('http://www.google.com/search?q=AngularJS'); + using('.doc-example-live').input('query').enter('google'); + expect(using('.doc-example-live').element('a').attr('href')). + toBe('http://www.google.com/search?q=google'); + }); + + */ angularDirective("ng:bind-attr", function(expression){ return function(element){ @@ -396,23 +415,28 @@ angularDirective("ng:bind-attr", function(expression){ * @name angular.directive.ng:click * * @description - * The ng:click allows you to specify custom behavior when + * The ng:click allows you to specify custom behavior when * element is clicked. - * + * * @element ANY * @param {expression} expression to eval upon click. * * @example - - count: {{count}} - * @scenario - it('should check ng:click', function(){ - expect(binding('count')).toBe('0'); - element('.doc-example-live :button').click(); - expect(binding('count')).toBe('1'); - }); + + + + count: {{count}} + + + it('should check ng:click', function(){ + expect(binding('count')).toBe('0'); + element('.doc-example-live :button').click(); + expect(binding('count')).toBe('1'); + }); + + */ /* * A directive that allows creation of custom onclick handlers that are defined as angular @@ -440,35 +464,37 @@ angularDirective("ng:click", function(expression, element){ * @name angular.directive.ng:submit * * @description - * - * @element form - * @param {expression} expression to eval. - * - * @exampleDescription - * @example - *
- * Enter text and hit enter: - * - *
- *
list={{list}}
- * @scenario - it('should check ng:submit', function(){ - expect(binding('list')).toBe('list=[]'); - element('.doc-example-live form input').click(); - this.addFutureAction('submit from', function($window, $document, done) { - $window.angular.element( - $document.elements('.doc-example-live form')). - trigger('submit'); - done(); - }); - expect(binding('list')).toBe('list=["hello"]'); - }); - */ -/** * Enables binding angular expressions to onsubmit events. * * Additionally it prevents the default action (which for form means sending the request to the * server and reloading the current page). + * + * @element form + * @param {expression} expression to eval. + * + * @example + + +
+ Enter text and hit enter: + +
+
list={{list}}
+
+ + it('should check ng:submit', function(){ + expect(binding('list')).toBe('list=[]'); + element('.doc-example-live form input').click(); + this.addFutureAction('submit from', function($window, $document, done) { + $window.angular.element( + $document.elements('.doc-example-live form')). + trigger('submit'); + done(); + }); + expect(binding('list')).toBe('list=["hello"]'); + }); + +
*/ angularDirective("ng:submit", function(expression, element) { return injectUpdateView(function($updateView, element) { @@ -488,26 +514,30 @@ angularDirective("ng:submit", function(expression, element) { * @name angular.directive.ng:watch * * @description - * The `ng:watch` allows you watch a variable and then execute + * The `ng:watch` allows you watch a variable and then execute * an evaluation on variable change. - * + * * @element ANY * @param {expression} expression to eval. * - * @exampleDescription - * Notice that the counter is incremented - * every time you change the text. * @example -
-
- Change counter: {{counter}} Name: {{name}} -
- * @scenario - it('should check ng:watch', function(){ - expect(using('.doc-example-live').binding('counter')).toBe('2'); - using('.doc-example-live').input('name').enter('abc'); - expect(using('.doc-example-live').binding('counter')).toBe('3'); - }); + * Notice that the counter is incremented + * every time you change the text. + + +
+
+ Change counter: {{counter}} Name: {{name}} +
+
+ + it('should check ng:watch', function(){ + expect(using('.doc-example-live').binding('counter')).toBe('2'); + using('.doc-example-live').input('name').enter('abc'); + expect(using('.doc-example-live').binding('counter')).toBe('3'); + }); + +
*/ //TODO: delete me, since having watch in UI is logic in UI. (leftover form getangular) angularDirective("ng:watch", function(expression, element){ @@ -544,34 +574,37 @@ function ngClass(selector) { * @name angular.directive.ng:class * * @description - * The `ng:class` allows you to set CSS class on HTML element + * The `ng:class` allows you to set CSS class on HTML element * conditionally. - * + * * @element ANY * @param {expression} expression to eval. * - * @exampleDescription * @example - - -
- Sample Text      - * - * @scenario - it('should check ng:class', function(){ - expect(element('.doc-example-live span').attr('className')).not(). - toMatch(/ng-input-indicator-wait/); + + + + +
+ Sample Text      +
+ + it('should check ng:class', function(){ + expect(element('.doc-example-live span').attr('className')).not(). + toMatch(/ng-input-indicator-wait/); + + using('.doc-example-live').element(':button:first').click(); - using('.doc-example-live').element(':button:first').click(); + expect(element('.doc-example-live span').attr('className')). + toMatch(/ng-input-indicator-wait/); - expect(element('.doc-example-live span').attr('className')). - toMatch(/ng-input-indicator-wait/); + using('.doc-example-live').element(':button:last').click(); - using('.doc-example-live').element(':button:last').click(); - - expect(element('.doc-example-live span').attr('className')).not(). - toMatch(/ng-input-indicator-wait/); - }); + expect(element('.doc-example-live span').attr('className')).not(). + toMatch(/ng-input-indicator-wait/); + }); + +
*/ angularDirective("ng:class", ngClass(function(){return true;})); @@ -581,33 +614,35 @@ angularDirective("ng:class", ngClass(function(){return true;})); * @name angular.directive.ng:class-odd * * @description - * The `ng:class-odd` and `ng:class-even` works exactly as - * `ng:class`, except it works in conjunction with `ng:repeat` + * The `ng:class-odd` and `ng:class-even` works exactly as + * `ng:class`, except it works in conjunction with `ng:repeat` * and takes affect only on odd (even) rows. * * @element ANY - * @param {expression} expression to eval. Must be inside + * @param {expression} expression to eval. Must be inside * `ng:repeat`. - * - * @exampleDescription * @example -
    -
  1. - - {{name}}       - -
  2. -
- * - * @scenario - it('should check ng:class-odd and ng:class-even', function(){ - expect(element('.doc-example-live li:first span').attr('className')). - toMatch(/ng-format-negative/); - expect(element('.doc-example-live li:last span').attr('className')). - toMatch(/ng-input-indicator-wait/); - }); + + +
    +
  1. + + {{name}}       + +
  2. +
+
+ + it('should check ng:class-odd and ng:class-even', function(){ + expect(element('.doc-example-live li:first span').attr('className')). + toMatch(/ng-format-negative/); + expect(element('.doc-example-live li:last span').attr('className')). + toMatch(/ng-input-indicator-wait/); + }); + +
*/ angularDirective("ng:class-odd", ngClass(function(i){return i % 2 === 0;})); @@ -617,33 +652,35 @@ angularDirective("ng:class-odd", ngClass(function(i){return i % 2 === 0;})); * @name angular.directive.ng:class-even * * @description - * The `ng:class-odd` and `ng:class-even` works exactly as - * `ng:class`, except it works in conjunction with `ng:repeat` + * The `ng:class-odd` and `ng:class-even` works exactly as + * `ng:class`, except it works in conjunction with `ng:repeat` * and takes affect only on odd (even) rows. * * @element ANY - * @param {expression} expression to eval. Must be inside + * @param {expression} expression to eval. Must be inside * `ng:repeat`. - * - * @exampleDescription * @example -
    -
  1. - - {{name}}       - -
  2. -
- * - * @scenario - it('should check ng:class-odd and ng:class-even', function(){ - expect(element('.doc-example-live li:first span').attr('className')). - toMatch(/ng-format-negative/); - expect(element('.doc-example-live li:last span').attr('className')). - toMatch(/ng-input-indicator-wait/); - }); + + +
    +
  1. + + {{name}}       + +
  2. +
+
+ + it('should check ng:class-odd and ng:class-even', function(){ + expect(element('.doc-example-live li:first span').attr('className')). + toMatch(/ng-format-negative/); + expect(element('.doc-example-live li:last span').attr('className')). + toMatch(/ng-input-indicator-wait/); + }); + +
*/ angularDirective("ng:class-even", ngClass(function(i){return i % 2 === 1;})); @@ -655,27 +692,30 @@ angularDirective("ng:class-even", ngClass(function(i){return i % 2 === 1;})); * @description * The `ng:show` and `ng:hide` allows you to show or hide a portion * of the HTML conditionally. - * + * * @element ANY - * @param {expression} expression if truthy then the element is + * @param {expression} expression if truthy then the element is * shown or hidden respectively. * - * @exampleDescription * @example - Click me:
- Show: I show up when you checkbox is checked?
- Hide: I hide when you checkbox is checked? - * - * @scenario - it('should check ng:show / ng:hide', function(){ - expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live span:last:visible').count()).toEqual(1); - - input('checked').check(); - - expect(element('.doc-example-live span:first:visible').count()).toEqual(1); - expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); - }); + + + Click me:
+ Show: I show up when you checkbox is checked?
+ Hide: I hide when you checkbox is checked? +
+ + it('should check ng:show / ng:hide', function(){ + expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); + expect(element('.doc-example-live span:last:visible').count()).toEqual(1); + + input('checked').check(); + + expect(element('.doc-example-live span:first:visible').count()).toEqual(1); + expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); + }); + +
*/ angularDirective("ng:show", function(expression, element){ return function(element){ @@ -693,27 +733,30 @@ angularDirective("ng:show", function(expression, element){ * @description * The `ng:show` and `ng:hide` allows you to show or hide a portion * of the HTML conditionally. - * + * * @element ANY - * @param {expression} expression if truthy then the element is + * @param {expression} expression if truthy then the element is * shown or hidden respectively. * - * @exampleDescription * @example - Click me:
- Show: I show up when you checkbox is checked?
- Hide: I hide when you checkbox is checked? - * - * @scenario - it('should check ng:show / ng:hide', function(){ - expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live span:last:visible').count()).toEqual(1); - - input('checked').check(); - - expect(element('.doc-example-live span:first:visible').count()).toEqual(1); - expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); - }); + + + Click me:
+ Show: I show up when you checkbox is checked?
+ Hide: I hide when you checkbox is checked? +
+ + it('should check ng:show / ng:hide', function(){ + expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); + expect(element('.doc-example-live span:last:visible').count()).toEqual(1); + + input('checked').check(); + + expect(element('.doc-example-live span:first:visible').count()).toEqual(1); + expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); + }); + +
*/ angularDirective("ng:hide", function(expression, element){ return function(element){ @@ -730,28 +773,31 @@ angularDirective("ng:hide", function(expression, element){ * * @description * The ng:style allows you to set CSS style on an HTML element conditionally. - * + * * @element ANY - * @param {expression} expression which evals to an object whes key's are - * CSS style names and values are coresponding values for those + * @param {expression} expression which evals to an object whes key's are + * CSS style names and values are coresponding values for those * CSS keys. * - * @exampleDescription * @example - - -
- Sample Text -
myStyle={{myStyle}}
- * - * @scenario - it('should check ng:style', function(){ - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); - element('.doc-example-live :button[value=set]').click(); - expect(element('.doc-example-live span').css('color')).toBe('red'); - element('.doc-example-live :button[value=clear]').click(); - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); - }); + + + + +
+ Sample Text +
myStyle={{myStyle}}
+
+ + it('should check ng:style', function(){ + expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); + element('.doc-example-live :button[value=set]').click(); + expect(element('.doc-example-live span').css('color')).toBe('red'); + element('.doc-example-live :button[value=clear]').click(); + expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); + }); + +
*/ angularDirective("ng:style", function(expression, element){ return function(element){ diff --git a/src/filters.js b/src/filters.js index 7fa7926d..0f6121ec 100644 --- a/src/filters.js +++ b/src/filters.js @@ -14,19 +14,23 @@ * When the value is negative, this css class is applied to the binding making it by default red. * * @example -
- {{amount | currency}} - * - * @scenario - it('should init with 1234.56', function(){ - expect(binding('amount | currency')).toBe('$1,234.56'); - }); - it('should update', function(){ - input('amount').enter('-1234'); - expect(binding('amount | currency')).toBe('$-1,234.00'); - expect(element('.doc-example-live .ng-binding').attr('className')). - toMatch(/ng-format-negative/); - }); + + +
+ {{amount | currency}} +
+ + it('should init with 1234.56', function(){ + expect(binding('amount | currency')).toBe('$1,234.56'); + }); + it('should update', function(){ + input('amount').enter('-1234'); + expect(binding('amount | currency')).toBe('$-1,234.00'); + expect(element('.doc-example-live .ng-binding').attr('className')). + toMatch(/ng-format-negative/); + }); + +
*/ angularFilter.currency = function(amount){ this.$element.toggleClass('ng-format-negative', amount < 0); @@ -49,24 +53,28 @@ angularFilter.currency = function(amount){ * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit. * * @example - Enter number:
- Default formatting: {{val | number}}
- No fractions: {{val | number:0}}
- Negative number: {{-val | number:4}} - - * @scenario - it('should format numbers', function(){ - expect(binding('val | number')).toBe('1,234.57'); - expect(binding('val | number:0')).toBe('1,235'); - expect(binding('-val | number:4')).toBe('-1,234.5679'); - }); - - it('should update', function(){ - input('val').enter('3374.333'); - expect(binding('val | number')).toBe('3,374.33'); - expect(binding('val | number:0')).toBe('3,374'); - expect(binding('-val | number:4')).toBe('-3,374.3330'); - }); + + + Enter number:
+ Default formatting: {{val | number}}
+ No fractions: {{val | number:0}}
+ Negative number: {{-val | number:4}} +
+ + it('should format numbers', function(){ + expect(binding('val | number')).toBe('1,234.57'); + expect(binding('val | number:0')).toBe('1,235'); + expect(binding('-val | number:4')).toBe('-1,234.5679'); + }); + + it('should update', function(){ + input('val').enter('3374.333'); + expect(binding('val | number')).toBe('3,374.33'); + expect(binding('val | number:0')).toBe('3,374'); + expect(binding('-val | number:4')).toBe('-3,374.3330'); + }); + +
*/ angularFilter.number = function(number, fractionSize){ if (isNaN(number) || !isFinite(number)) { @@ -183,19 +191,22 @@ var NUMBER_STRING = /^\d+$/; * @returns {string} Formatted string or the input if input is not recognized as date/millis. * * @example - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
- {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: - {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
- * - * @scenario - it('should format date', function(){ - expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")). - toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} \-?\d{4}/); - expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")). - toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(am|pm)/); - }); - * + + + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: + {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
+ {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: + {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
+
+ + it('should format date', function(){ + expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")). + toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} \-?\d{4}/); + expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")). + toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(am|pm)/); + }); + +
*/ angularFilter.date = function(date, format) { if (isString(date)) { @@ -255,19 +266,23 @@ angularFilter.date = function(date, format) { * @css ng-monospace Always applied to the encapsulating element. * * @example: - -
{{ obj | json }}
- * - * @scenario - it('should jsonify filtered objects', function() { - expect(binding('obj | json')).toBe('{\n "a":1,\n "b":[]}'); - }); - - it('should update', function() { - input('objTxt').enter('[1, 2, 3]'); - expect(binding('obj | json')).toBe('[1,2,3]'); - }); + + + +
{{ obj | json }}
+
+ + it('should jsonify filtered objects', function() { + expect(binding('obj | json')).toBe('{\n "a":1,\n "b":[]}'); + }); + + it('should update', function() { + input('objTxt').enter('[1, 2, 3]'); + expect(binding('obj | json')).toBe('[1,2,3]'); + }); + +
* */ angularFilter.json = function(object) { @@ -324,63 +339,67 @@ angularFilter.uppercase = uppercase; * @returns {string} Sanitized or raw html. * * @example - Snippet: - - - - - - - - - - - - - - - - - - - - - -
FilterSourceRendered
html filter -
<div ng:bind="snippet | html">
</div>
-
-
-
no filter
<div ng:bind="snippet">
</div>
unsafe html filter
<div ng:bind="snippet | html:'unsafe'">
</div>
- * - * @scenario - it('should sanitize the html snippet ', function(){ - expect(using('#html-filter').binding('snippet | html')). - toBe('

an html\nclick here\nsnippet

'); - }); - - it ('should escape snippet without any filter', function() { - expect(using('#escaped-html').binding('snippet')). - toBe("<p style=\"color:blue\">an html\n" + - "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + - "snippet</p>"); - }); - - it ('should inline raw snippet if filtered as unsafe', function() { - expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")). - toBe("

an html\n" + - "click here\n" + - "snippet

"); - }); - - it('should update', function(){ - input('snippet').enter('new text'); - expect(using('#html-filter').binding('snippet | html')).toBe('new text'); - expect(using('#escaped-html').binding('snippet')).toBe("new <b>text</b>"); - expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")).toBe('new text'); - }); + + + + + + + + + + + + + + + + + + + + + +
FilterSourceRendered
html filter +
<div ng:bind="snippet | html">
</div>
+
+
+
no filter
<div ng:bind="snippet">
</div>
unsafe html filter
<div ng:bind="snippet | html:'unsafe'">
</div>
+ + + it('should sanitize the html snippet ', function(){ + expect(using('#html-filter').binding('snippet | html')). + toBe('

an html\nclick here\nsnippet

'); + }); + + it('should escape snippet without any filter', function() { + expect(using('#escaped-html').binding('snippet')). + toBe("<p style=\"color:blue\">an html\n" + + "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + + "snippet</p>"); + }); + + it('should inline raw snippet if filtered as unsafe', function() { + expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")). + toBe("

an html\n" + + "click here\n" + + "snippet

"); + }); + + it('should update', function(){ + input('snippet').enter('new text'); + expect(using('#html-filter').binding('snippet | html')).toBe('new text'); + expect(using('#escaped-html').binding('snippet')).toBe("new <b>text</b>"); + expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")).toBe('new text'); + }); +
+
*/ angularFilter.html = function(html, option){ return new HTML(html, option); @@ -401,59 +420,63 @@ angularFilter.html = function(html, option){ * @returns {string} Html-linkified text. * * @example - Snippet: - - - - - - - - - - - - - - - - -
FilterSourceRendered
linky filter -
<div ng:bind="snippet | linky">
</div>
-
-
-
no filter
<div ng:bind="snippet">
</div>
- - @scenario - it('should linkify the snippet with urls', function(){ - expect(using('#linky-filter').binding('snippet | linky')). - toBe('Pretty text with some links:\n' + - 'http://angularjs.org/,\n' + - 'us@somewhere.org,\n' + - 'another@somewhere.org,\n' + - 'and one more: ftp://127.0.0.1/.'); - }); - - it ('should not linkify snippet without the linky filter', function() { - expect(using('#escaped-html').binding('snippet')). - toBe("Pretty text with some links:\n" + - "http://angularjs.org/,\n" + - "mailto:us@somewhere.org,\n" + - "another@somewhere.org,\n" + - "and one more: ftp://127.0.0.1/."); - }); - - it('should update', function(){ - input('snippet').enter('new http://link.'); - expect(using('#linky-filter').binding('snippet | linky')). - toBe('new http://link.'); - expect(using('#escaped-html').binding('snippet')).toBe('new http://link.'); - }); + + + Snippet: + + + + + + + + + + + + + + + + +
FilterSourceRendered
linky filter +
<div ng:bind="snippet | linky">
</div>
+
+
+
no filter
<div ng:bind="snippet">
</div>
+
+ + it('should linkify the snippet with urls', function(){ + expect(using('#linky-filter').binding('snippet | linky')). + toBe('Pretty text with some links:\n' + + 'http://angularjs.org/,\n' + + 'us@somewhere.org,\n' + + 'another@somewhere.org,\n' + + 'and one more: ftp://127.0.0.1/.'); + }); + + it ('should not linkify snippet without the linky filter', function() { + expect(using('#escaped-html').binding('snippet')). + toBe("Pretty text with some links:\n" + + "http://angularjs.org/,\n" + + "mailto:us@somewhere.org,\n" + + "another@somewhere.org,\n" + + "and one more: ftp://127.0.0.1/."); + }); + + it('should update', function(){ + input('snippet').enter('new http://link.'); + expect(using('#linky-filter').binding('snippet | linky')). + toBe('new http://link.'); + expect(using('#escaped-html').binding('snippet')).toBe('new http://link.'); + }); + +
*/ //TODO: externalize all regexps angularFilter.linky = function(text){ diff --git a/src/formatters.js b/src/formatters.js index e96e3634..d0fea46e 100644 --- a/src/formatters.js +++ b/src/formatters.js @@ -18,17 +18,21 @@ angularFormatter.noop = formatter(identity, identity); * @returns {?string} A JSON string representation of the model. * * @example - *
- * - *
data={{data}}
- *
- * - * @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 }'); - * }); + + +
+ +
data={{data}}
+
+
+ + 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, function(value){ return fromJson(value || 'null'); @@ -45,17 +49,21 @@ angularFormatter.json = formatter(toJson, function(value){ * @returns {boolean} Converts to `true` unless user enters (blank), `f`, `false`, `0`, `no`, `[]`. * * @example - * Enter truthy text: - * - * - *
value={{value}}
- * - * @scenario - * it('should format boolean', function(){ - * expect(binding('value')).toEqual('value=false'); - * input('value').enter('truthy'); - * expect(binding('value')).toEqual('value=true'); - * }); + + + Enter truthy text: + + +
value={{value}}
+
+ + 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); @@ -70,16 +78,20 @@ angularFormatter['boolean'] = formatter(toString, toBoolean); * @returns {number} Number from the parsed string. * * @example - * Enter valid number: - * - *
value={{value}}
- * - * @scenario - * it('should format numbers', function(){ - * expect(binding('value')).toEqual('value=1234'); - * input('value').enter('5678'); - * expect(binding('value')).toEqual('value=5678'); - * }); + + + Enter valid number: + +
value={{value}}
+
+ + 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)) { @@ -100,20 +112,24 @@ angularFormatter.number = formatter(toString, function(obj){ * @returns {Array} Array parsed from the entered string. * * @example - * Enter a list of items: - * - * - *
value={{value}}
- * - * @scenario - * it('should format lists', function(){ - * expect(binding('value')).toEqual('value=["chair","table"]'); - * this.addFutureAction('change to XYZ', function($window, $document, done){ - * $document.elements('.doc-example :input:last').val(',,a,b,').trigger('change'); - * done(); - * }); - * expect(binding('value')).toEqual('value=["a","b"]'); - * }); + + + Enter a list of items: + + +
value={{value}}
+
+ + it('should format lists', function(){ + expect(binding('value')).toEqual('value=["chair","table"]'); + this.addFutureAction('change to XYZ', function($window, $document, done){ + $document.elements('.doc-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; }, @@ -138,20 +154,24 @@ angularFormatter.list = formatter( * @returns {String} Trim excess leading and trailing space. * * @example - * Enter text with leading/trailing spaces: - * - * - *
value={{value|json}}
- * - * @scenario - * it('should format trim', function(){ - * expect(binding('value')).toEqual('value="book"'); - * this.addFutureAction('change to XYZ', function($window, $document, done){ - * $document.elements('.doc-example :input:last').val(' text ').trigger('change'); - * done(); - * }); - * expect(binding('value')).toEqual('value="text"'); - * }); + + + Enter text with leading/trailing spaces: + + +
value={{value|json}}
+
+ + it('should format trim', function(){ + expect(binding('value')).toEqual('value="book"'); + this.addFutureAction('change to XYZ', function($window, $document, done){ + $document.elements('.doc-example :input:last').val(' text ').trigger('change'); + done(); + }); + expect(binding('value')).toEqual('value="text"'); + }); + +
*/ angularFormatter.trim = formatter( function(obj) { return obj ? trim("" + obj) : ""; } @@ -176,33 +196,36 @@ angularFormatter.trim = formatter( * @returns {object} object which is located at the selected position. * * @example - * - *
- * User: - * - * - * user={{currentUser.name}}
- * password={{currentUser.password}}
- *
- * - * @scenario - * it('should retrieve object by index', function(){ - * expect(binding('currentUser.password')).toEqual('guest'); - * select('currentUser').option('2'); - * expect(binding('currentUser.password')).toEqual('abc'); - * }); + + + +
+ User: + + + user={{currentUser.name}}
+ password={{currentUser.password}}
+ + + it('should retrieve object by index', function(){ + expect(binding('currentUser.password')).toEqual('guest'); + select('currentUser').option('2'); + expect(binding('currentUser.password')).toEqual('abc'); + }); + + */ angularFormatter.index = formatter( function(object, array){ diff --git a/src/services.js b/src/services.js index 68860e22..f54234a6 100644 --- a/src/services.js +++ b/src/services.js @@ -22,8 +22,19 @@ function angularServiceInject(name, fn, inject, eager) { * suffer from window globality. * * @example +<<<<<<< HEAD +======= + + + + + + + + +>>>>>>> changed the documentation @example to use */ angularServiceInject("$window", bind(window, identity, window), [], EAGER); @@ -63,10 +74,16 @@ angularServiceInject("$document", function(window){ * Notice that using browser's forward/back buttons changes the $location. * * @example - clear hash | - test hash
- -
$location = {{$location}}
+ + + clear hash | + test hash
+ +
$location = {{$location}}
+
+ + +
*/ angularServiceInject("$location", function($browser) { var scope = this, @@ -98,9 +115,15 @@ angularServiceInject("$location", function($browser) { * Browser is updated at the end of $eval() * * @example - * scope.$location.update('http://www.angularjs.org/path#hash?search=x'); - * scope.$location.update({host: 'www.google.com', protocol: 'https'}); - * scope.$location.update({hashPath: '/path', hashSearch: {a: 'b', x: true}}); + + + scope.$location.update('http://www.angularjs.org/path#hash?search=x'); + scope.$location.update({host: 'www.google.com', protocol: 'https'}); + scope.$location.update({hashPath: '/path', hashSearch: {a: 'b', x: true}}); + + + + * * @param {(string|Object)} href Full href as a string or object with properties */ @@ -133,14 +156,18 @@ angularServiceInject("$location", function($browser) { * @see update() * * @example - * scope.$location.updateHash('/hp') - * ==> update({hashPath: '/hp'}) - * - * scope.$location.updateHash({a: true, b: 'val'}) - * ==> update({hashSearch: {a: true, b: 'val'}}) - * - * scope.$location.updateHash('/hp', {a: true}) - * ==> update({hashPath: '/hp', hashSearch: {a: true}}) + + + scope.$location.updateHash('/hp') + ==> update({hashPath: '/hp'}) + scope.$location.updateHash({a: true, b: 'val'}) + ==> update({hashSearch: {a: true, b: 'val'}}) + scope.$location.updateHash('/hp', {a: true}) + ==> update({hashPath: '/hp', hashSearch: {a: true}}) + + + + * * @param {(string|Object)} path A hashPath or hashSearch object * @param {Object=} search A hashSearch object @@ -176,7 +203,9 @@ angularServiceInject("$location", function($browser) { * - everything else * * @example - * scope.$location.href = 'http://www.angularjs.org/path#a/b' + *
+   *   scope.$location.href = 'http://www.angularjs.org/path#a/b'
+   * 
* immediately after this call, other properties are still the old ones... * * This method checks the changes and update location to the consistent state @@ -298,13 +327,19 @@ angularServiceInject("$location", function($browser) { * The main purpose of this service is to simplify debugging and troubleshooting. * * @example -

Reload this page with open console, enter text and hit the log button...

- Message: - - - - - + + +

Reload this page with open console, enter text and hit the log button...

+ Message: + + + + + +
+ + +
*/ var $logFactory; //reference to be used only in tests angularServiceInject("$log", $logFactory = function($window){ @@ -622,42 +657,46 @@ function switchRouteMatcher(on, when, dstName) { * widget. * * @example -

- This example shows how changing the URL hash causes the $route - to match a route against the URL, and the [[ng:include]] pulls in the partial. - Try changing the URL in the input box to see changes. -

- - - -Chose: -Moby | -Moby: Ch1 | -Gatsby | -Gatsby: Ch4
- -
$location={{$location}}
-
$route.current.template={{$route.current.template}}
-
$route.current.params={{$route.current.params}}
-
$route.current.scope.name={{$route.current.scope.name}}
-
- + function ChapterCntl() { + this.name = "ChapterCntl"; + } + + + Chose: + Moby | + Moby: Ch1 | + Gatsby | + Gatsby: Ch4
+ +
$location={{$location}}
+
$route.current.template={{$route.current.template}}
+
$route.current.params={{$route.current.params}}
+
$route.current.scope.name={{$route.current.scope.name}}
+
+ + + + +
*/ angularServiceInject('$route', function(location) { var routes = {}, @@ -1122,43 +1161,49 @@ angularServiceInject('$xhr.cache', function($xhr, $defer, $log){ * @returns {Object} A resource "class". * * @example - - -
- - -
-
-

- - {{item.actor.name}} - Expand replies: {{item.links.replies[0].count}} -

- {{item.object.content | html}} -
- - {{reply.actor.name}}: {{reply.content | html}} + + + + +
+ + +
+
+

+ + {{item.actor.name}} + Expand replies: {{item.links.replies[0].count}} +

+ {{item.object.content | html}} +
+ + {{reply.actor.name}}: {{reply.content | html}} +
+
-
-
+ + + + */ angularServiceInject('$resource', function($xhr){ var resource = new ResourceFactory($xhr); diff --git a/src/validators.js b/src/validators.js index 30936574..e2a9d7f6 100644 --- a/src/validators.js +++ b/src/validators.js @@ -14,24 +14,27 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * - * Enter valid SSN: - *
- * - *
- * - * @scenario - * it('should invalidate non ssn', function(){ - * var textBox = element('.doc-example :input'); - * expect(textBox.attr('className')).not().toMatch(/ng-validation-error/); - * expect(textBox.val()).toEqual('123-45-6789'); - * - * input('ssn').enter('123-45-67890'); - * expect(textBox.attr('className')).toMatch(/ng-validation-error/); - * }); + + + + Enter valid SSN: +
+ +
+
+ + it('should invalidate non ssn', function(){ + var textBox = element('.doc-example :input'); + expect(textBox.attr('className')).not().toMatch(/ng-validation-error/); + expect(textBox.val()).toEqual('123-45-6789'); + input('ssn').enter('123-45-67890'); + expect(textBox.attr('className')).toMatch(/ng-validation-error/); + }); + +
* */ 'regexp': function(value, regexp, msg) { @@ -57,28 +60,29 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter number:
- * Enter number greater than 10:
- * Enter number between 100 and 200:
- * - * @scenario - * it('should invalidate number', function(){ - * var n1 = element('.doc-example :input[name=n1]'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('n1').enter('1.x'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * - * var n2 = element('.doc-example :input[name=n2]'); - * expect(n2.attr('className')).not().toMatch(/ng-validation-error/); - * input('n2').enter('9'); - * expect(n2.attr('className')).toMatch(/ng-validation-error/); - * - * var n3 = element('.doc-example :input[name=n3]'); - * expect(n3.attr('className')).not().toMatch(/ng-validation-error/); - * input('n3').enter('201'); - * expect(n3.attr('className')).toMatch(/ng-validation-error/); - * - * }); + + + Enter number:
+ Enter number greater than 10:
+ Enter number between 100 and 200:
+
+ + it('should invalidate number', function(){ + var n1 = element('.doc-example :input[name=n1]'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('n1').enter('1.x'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + var n2 = element('.doc-example :input[name=n2]'); + expect(n2.attr('className')).not().toMatch(/ng-validation-error/); + input('n2').enter('9'); + expect(n2.attr('className')).toMatch(/ng-validation-error/); + var n3 = element('.doc-example :input[name=n3]'); + expect(n3.attr('className')).not().toMatch(/ng-validation-error/); + input('n3').enter('201'); + expect(n3.attr('className')).toMatch(/ng-validation-error/); + }); + +
* */ 'number': function(value, min, max) { @@ -110,28 +114,29 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter integer:
- * Enter integer equal or greater than 10:
- * Enter integer between 100 and 200 (inclusive):
- * - * @scenario - * it('should invalidate integer', function(){ - * var n1 = element('.doc-example :input[name=n1]'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('n1').enter('1.1'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * - * var n2 = element('.doc-example :input[name=n2]'); - * expect(n2.attr('className')).not().toMatch(/ng-validation-error/); - * input('n2').enter('10.1'); - * expect(n2.attr('className')).toMatch(/ng-validation-error/); - * - * var n3 = element('.doc-example :input[name=n3]'); - * expect(n3.attr('className')).not().toMatch(/ng-validation-error/); - * input('n3').enter('100.1'); - * expect(n3.attr('className')).toMatch(/ng-validation-error/); - * - * }); + + + Enter integer:
+ Enter integer equal or greater than 10:
+ Enter integer between 100 and 200 (inclusive):
+
+ + it('should invalidate integer', function(){ + var n1 = element('.doc-example :input[name=n1]'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('n1').enter('1.1'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + var n2 = element('.doc-example :input[name=n2]'); + expect(n2.attr('className')).not().toMatch(/ng-validation-error/); + input('n2').enter('10.1'); + expect(n2.attr('className')).toMatch(/ng-validation-error/); + var n3 = element('.doc-example :input[name=n3]'); + expect(n3.attr('className')).not().toMatch(/ng-validation-error/); + input('n3').enter('100.1'); + expect(n3.attr('className')).toMatch(/ng-validation-error/); + }); + +
*/ 'integer': function(value, min, max) { var numberError = angularValidator['number'](value, min, max); @@ -154,16 +159,20 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter valid date: - * - * - * @scenario - * it('should invalidate date', function(){ - * var n1 = element('.doc-example :input'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('text').enter('123/123/123'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * }); + + + Enter valid date: + + + + it('should invalidate date', function(){ + var n1 = element('.doc-example :input'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('text').enter('123/123/123'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + }); + + * */ 'date': function(value) { @@ -187,16 +196,20 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter valid email: - * - * - * @scenario - * it('should invalidate email', function(){ - * var n1 = element('.doc-example :input'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('text').enter('a@b.c'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * }); + + + Enter valid email: + + + + it('should invalidate email', function(){ + var n1 = element('.doc-example :input'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('text').enter('a@b.c'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + }); + + * */ 'email': function(value) { @@ -217,16 +230,20 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter valid phone number: - * - * - * @scenario - * it('should invalidate phone', function(){ - * var n1 = element('.doc-example :input'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('text').enter('+12345678'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * }); + + + Enter valid phone number: + + + + it('should invalidate phone', function(){ + var n1 = element('.doc-example :input'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('text').enter('+12345678'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + }); + + * */ 'phone': function(value) { @@ -250,16 +267,20 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * Enter valid phone number: - * - * - * @scenario - * it('should invalidate url', function(){ - * var n1 = element('.doc-example :input'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('text').enter('abc://server/path'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * }); + + + Enter valid phone number: + + + + it('should invalidate url', function(){ + var n1 = element('.doc-example :input'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('text').enter('abc://server/path'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + }); + + * */ 'url': function(value) { @@ -280,17 +301,21 @@ extend(angularValidator, { * @css ng-validation-error * * @example - * - * - * @scenario - * it('should invalidate json', function(){ - * var n1 = element('.doc-example :input'); - * expect(n1.attr('className')).not().toMatch(/ng-validation-error/); - * input('json').enter('{name}'); - * expect(n1.attr('className')).toMatch(/ng-validation-error/); - * }); + + + + + + it('should invalidate json', function(){ + var n1 = element('.doc-example :input'); + expect(n1.attr('className')).not().toMatch(/ng-validation-error/); + input('json').enter('{name}'); + expect(n1.attr('className')).toMatch(/ng-validation-error/); + }); + + * */ 'json': function(value) { @@ -338,35 +363,35 @@ extend(angularValidator, { * @css ng-input-indicator-wait, ng-validation-error * * @example - * - * This input is validated asynchronously: - *
- * - *
- * - * @scenario - * it('should change color in delayed way', function(){ - * var textBox = element('.doc-example :input'); - * expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/); - * expect(textBox.attr('className')).not().toMatch(/ng-validation-error/); - * - * input('text').enter('X'); - * expect(textBox.attr('className')).toMatch(/ng-input-indicator-wait/); - * - * pause(.6); - * - * expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/); - * expect(textBox.attr('className')).toMatch(/ng-validation-error/); - * - * }); + + + + This input is validated asynchronously: +
+ +
+
+ + it('should change color in delayed way', function(){ + var textBox = element('.doc-example :input'); + expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/); + expect(textBox.attr('className')).not().toMatch(/ng-validation-error/); + input('text').enter('X'); + expect(textBox.attr('className')).toMatch(/ng-input-indicator-wait/); + pause(.6); + expect(textBox.attr('className')).not().toMatch(/ng-input-indicator-wait/); + expect(textBox.attr('className')).toMatch(/ng-validation-error/); + }); + +
* */ /* diff --git a/src/widgets.js b/src/widgets.js index cf65cd40..ea76cfc2 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -19,117 +19,122 @@ * * * @example - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameFormatHTMLUI{{input#}}
textString<input type="text" name="input1">{{input1|json}}
textareaString<textarea name="input2"></textarea>{{input2|json}}
radioString - <input type="radio" name="input3" value="A">
- <input type="radio" name="input3" value="B"> -
- - - {{input3|json}}
checkboxBoolean<input type="checkbox" name="input4" value="checked">{{input4|json}}
pulldownString - <select name="input5">
-   <option value="c">C</option>
-   <option value="d">D</option>
- </select>
-
- - {{input5|json}}
multiselectArray - <select name="input6" multiple size="4">
-   <option value="e">E</option>
-   <option value="f">F</option>
- </select>
-
- - {{input6|json}}
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameFormatHTMLUI{{input#}}
textString<input type="text" name="input1">{{input1|json}}
textareaString<textarea name="input2"></textarea>{{input2|json}}
radioString + <input type="radio" name="input3" value="A">
+ <input type="radio" name="input3" value="B"> +
+ + + {{input3|json}}
checkboxBoolean<input type="checkbox" name="input4" value="checked">{{input4|json}}
pulldownString + <select name="input5">
+   <option value="c">C</option>
+   <option value="d">D</option>
+ </select>
+
+ + {{input5|json}}
multiselectArray + <select name="input6" multiple size="4">
+   <option value="e">E</option>
+   <option value="f">F</option>
+ </select>
+
+ + {{input6|json}}
+
+ - * @scenario - * it('should exercise text', function(){ - * input('input1').enter('Carlos'); - * expect(binding('input1')).toEqual('"Carlos"'); - * }); - * it('should exercise textarea', function(){ - * input('input2').enter('Carlos'); - * expect(binding('input2')).toEqual('"Carlos"'); - * }); - * it('should exercise radio', function(){ - * expect(binding('input3')).toEqual('null'); - * input('input3').select('A'); - * expect(binding('input3')).toEqual('"A"'); - * input('input3').select('B'); - * expect(binding('input3')).toEqual('"B"'); - * }); - * it('should exercise checkbox', function(){ - * expect(binding('input4')).toEqual('false'); - * input('input4').check(); - * expect(binding('input4')).toEqual('true'); - * }); - * it('should exercise pulldown', function(){ - * expect(binding('input5')).toEqual('"c"'); - * select('input5').option('d'); - * expect(binding('input5')).toEqual('"d"'); - * }); - * it('should exercise multiselect', function(){ - * expect(binding('input6')).toEqual('[]'); - * select('input6').options('e'); - * expect(binding('input6')).toEqual('["e"]'); - * select('input6').options('e', 'f'); - * expect(binding('input6')).toEqual('["e","f"]'); - * }); + it('should exercise text', function(){ + input('input1').enter('Carlos'); + expect(binding('input1')).toEqual('"Carlos"'); + }); + it('should exercise textarea', function(){ + input('input2').enter('Carlos'); + expect(binding('input2')).toEqual('"Carlos"'); + }); + it('should exercise radio', function(){ + expect(binding('input3')).toEqual('null'); + input('input3').select('A'); + expect(binding('input3')).toEqual('"A"'); + input('input3').select('B'); + expect(binding('input3')).toEqual('"B"'); + }); + it('should exercise checkbox', function(){ + expect(binding('input4')).toEqual('false'); + input('input4').check(); + expect(binding('input4')).toEqual('true'); + }); + it('should exercise pulldown', function(){ + expect(binding('input5')).toEqual('"c"'); + select('input5').option('d'); + expect(binding('input5')).toEqual('"d"'); + }); + it('should exercise multiselect', function(){ + expect(binding('input6')).toEqual('[]'); + select('input6').options('e'); + expect(binding('input6')).toEqual('["e"]'); + select('input6').options('e', 'f'); + expect(binding('input6')).toEqual('["e","f"]'); + }); + +
*/ function modelAccessor(scope, element) { @@ -193,26 +198,29 @@ function compileFormatter(expr) { * @element INPUT * @css ng-validation-error * - * @exampleDescription + * @example * This example shows how the input element becomes red when it contains invalid input. Correct * the input to make the error disappear. * - * @example - I don't validate: -
+ + + I don't validate: +
- I need an integer or nothing: -
- * - * @scenario - it('should check ng:validate', function(){ - expect(element('.doc-example-live :input:last').attr('className')). - toMatch(/ng-validation-error/); + I need an integer or nothing: +
+
+ + it('should check ng:validate', function(){ + expect(element('.doc-example-live :input:last').attr('className')). + toMatch(/ng-validation-error/); - input('value').enter('123'); - expect(element('.doc-example-live :input:last').attr('className')). - not().toMatch(/ng-validation-error/); - }); + input('value').enter('123'); + expect(element('.doc-example-live :input:last').attr('className')). + not().toMatch(/ng-validation-error/); + }); + +
*/ /** * @workInProgress @@ -226,19 +234,22 @@ function compileFormatter(expr) { * @element INPUT * @css ng-validation-error * - * @exampleDescription + * @example * This example shows how the input element becomes red when it contains invalid input. Correct * the input to make the error disappear. * - * @example - I cannot be blank:
- * - * @scenario - it('should check ng:required', function(){ - expect(element('.doc-example-live :input').attr('className')).toMatch(/ng-validation-error/); - input('value').enter('123'); - expect(element('.doc-example-live :input').attr('className')).not().toMatch(/ng-validation-error/); - }); + + + I cannot be blank:
+
+ + it('should check ng:required', function(){ + expect(element('.doc-example-live :input').attr('className')).toMatch(/ng-validation-error/); + input('value').enter('123'); + expect(element('.doc-example-live :input').attr('className')).not().toMatch(/ng-validation-error/); + }); + +
*/ /** * @workInProgress @@ -256,21 +267,24 @@ function compileFormatter(expr) { * * @element INPUT * - * @exampleDescription + * @example * This example shows how the user input is converted from a string and internally represented as an * array. * - * @example - Enter a comma separated list of items: - -
list={{list}}
- * - * @scenario - it('should check ng:format', function(){ - expect(binding('list')).toBe('list=["table","chairs","plate"]'); - input('list').enter(',,, a ,,,'); - expect(binding('list')).toBe('list=["a"]'); - }); + + + Enter a comma separated list of items: + +
list={{list}}
+
+ + it('should check ng:format', function(){ + expect(binding('list')).toBe('list=["table","chairs","plate"]'); + input('list').enter(',,, a ,,,'); + expect(binding('list')).toBe('list=["a"]'); + }); + +
*/ function valueAccessor(scope, element) { var validatorName = element.attr('ng:validate') || NOOP, @@ -453,28 +467,32 @@ function radioInit(model, view, element) { * @element INPUT * @param {expression} expression to execute. * - * @exampleDescription * @example -
- - changeCount {{textCount}}
- - changeCount {{checkboxCount}}
- * - * @scenario - it('should check ng:change', function(){ - expect(binding('textCount')).toBe('0'); - expect(binding('checkboxCount')).toBe('0'); + * @example + + +
+ + changeCount {{textCount}}
+ + changeCount {{checkboxCount}}
+
+ + it('should check ng:change', function(){ + expect(binding('textCount')).toBe('0'); + expect(binding('checkboxCount')).toBe('0'); - using('.doc-example-live').input('text').enter('abc'); - expect(binding('textCount')).toBe('1'); - expect(binding('checkboxCount')).toBe('0'); + using('.doc-example-live').input('text').enter('abc'); + expect(binding('textCount')).toBe('1'); + expect(binding('checkboxCount')).toBe('0'); - using('.doc-example-live').input('checkbox').check(); - expect(binding('textCount')).toBe('1'); - expect(binding('checkboxCount')).toBe('1'); - }); + using('.doc-example-live').input('checkbox').check(); + expect(binding('textCount')).toBe('1'); + expect(binding('checkboxCount')).toBe('1'); + }); + +
*/ function inputWidget(events, modelAccessor, viewAccessor, initFn, textBox) { return injectService(['$updateView', '$defer'], function($updateView, $defer, element) { @@ -594,27 +612,31 @@ angularWidget('option', function(){ * @param {string=} onload Expression to evaluate when a new partial is loaded. * * @example - * - * url = {{url}} - *
- * - * - * @scenario - * it('should load date filter', function(){ - * expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.date/); - * }); - * it('should change to hmtl filter', function(){ - * select('url').option('angular.filter.html.html'); - * expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.html/); - * }); - * it('should change to blank', function(){ - * select('url').option('(blank)'); - * expect(element('.doc-example ng\\:include').text()).toEqual(''); - * }); + + + + url = {{url}} +
+ +
+ + it('should load date filter', function(){ + expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.date/); + }); + it('should change to hmtl filter', function(){ + select('url').option('angular.filter.html.html'); + expect(element('.doc-example ng\\:include').text()).toMatch(/angular\.filter\.html/); + }); + it('should change to blank', function(){ + select('url').option('(blank)'); + expect(element('.doc-example ng\\:include').text()).toEqual(''); + }); + +
*/ angularWidget('ng:include', function(element){ var compiler = this, @@ -690,32 +712,36 @@ angularWidget('ng:include', function(element){ * * `ng:switch-default`: the default case when no other casses match. * * @example - - switch={{switch}} - - -
Settings Div
- Home Span - default -
- - * - * @scenario - * it('should start in settings', function(){ - * expect(element('.doc-example ng\\:switch').text()).toEqual('Settings Div'); - * }); - * it('should change to home', function(){ - * select('switch').option('home'); - * expect(element('.doc-example ng\\:switch').text()).toEqual('Home Span'); - * }); - * it('should select deafault', function(){ - * select('switch').option('other'); - * expect(element('.doc-example ng\\:switch').text()).toEqual('default'); - * }); + + + + switch={{switch}} + + +
Settings Div
+ Home Span + default +
+ +
+ + it('should start in settings', function(){ + expect(element('.doc-example ng\\:switch').text()).toEqual('Settings Div'); + }); + it('should change to home', function(){ + select('switch').option('home'); + expect(element('.doc-example ng\\:switch').text()).toEqual('Home Span'); + }); + it('should select deafault', function(){ + select('switch').option('other'); + expect(element('.doc-example ng\\:switch').text()).toEqual('default'); + }); + +
*/ var ngSwitch = angularWidget('ng:switch', function (element){ var compiler = this, @@ -838,25 +864,29 @@ angularWidget('a', function() { * * For example: `(name, age) in {'adam':10, 'amalie':12}`. * - * @exampleDescription + * @example * This example initializes the scope to a list of names and * than uses `ng:repeat` to display every person. - * @example -
- I have {{friends.length}} friends. They are: -
    -
  • - [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. -
  • -
-
- * @scenario - it('should check ng:repeat', function(){ - var r = using('.doc-example-live').repeater('ul li'); - expect(r.count()).toBe(2); - expect(r.row(0)).toEqual(["1","John","25"]); - expect(r.row(1)).toEqual(["2","Mary","28"]); - }); + + +
+ I have {{friends.length}} friends. They are: +
    +
  • + [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. +
  • +
+
+
+ + it('should check ng:repeat', function(){ + var r = using('.doc-example-live').repeater('ul li'); + expect(r.count()).toBe(2); + expect(r.row(0)).toEqual(["1","John","25"]); + expect(r.row(1)).toEqual(["2","Mary","28"]); + }); + +
*/ angularWidget("@ng:repeat", function(expression, element){ element.removeAttr('ng:repeat'); @@ -946,20 +976,24 @@ angularWidget("@ng:repeat", function(expression, element){ * * @element ANY * - * @exampleDescription + * @example * In this example there are two location where a siple binding (`{{}}`) is present, but the one * wrapped in `ng:non-bindable` is left alone. * * @example -
Normal: {{1 + 2}}
-
Ignored: {{1 + 2}}
- * - * @scenario - it('should check ng:non-bindable', function(){ - expect(using('.doc-example-live').binding('1 + 2')).toBe('3'); - expect(using('.doc-example-live').element('div:last').text()). - toMatch(/1 \+ 2/); - }); + + +
Normal: {{1 + 2}}
+
Ignored: {{1 + 2}}
+
+ + it('should check ng:non-bindable', function(){ + expect(using('.doc-example-live').binding('1 + 2')).toBe('3'); + expect(using('.doc-example-live').element('div:last').text()). + toMatch(/1 \+ 2/); + }); + +
*/ angularWidget("@ng:non-bindable", noop); @@ -989,26 +1023,30 @@ angularWidget("@ng:non-bindable", noop); * - doesn't require `$route` service to be available on the root scope * * - * # Example - * Because of the nature of this widget, we can't include the usual live example for it. Instead - * following is a code snippet showing the typical usage: - * -
-     
-     
- foo | bar | undefined
- The view is included below: -
- -
-
+ function BootstrapCtrl(){} + function OverviewCtrl(){} + +
+ overview | bootstrap | undefined
+ The view is included below: +
+ +
+ + + + */ angularWidget('ng:view', function(element) { var compiler = this; -- cgit v1.2.3