diff options
| author | Misko Hevery | 2010-11-07 13:04:48 -0800 | 
|---|---|---|
| committer | Misko Hevery | 2010-11-07 13:06:55 -0800 | 
| commit | 91b6c5f7ffaa19f967547ae3916641fed9e0f04c (patch) | |
| tree | 24be352f7e30519848e1364db5ea2dd6ff87e983 /src | |
| parent | 5be325a0c1a660268d29541bc668d9cb7d641fcb (diff) | |
| download | angular.js-91b6c5f7ffaa19f967547ae3916641fed9e0f04c.tar.bz2 | |
Added documentation for validators.
BACKWARD INCOMPATIBLE: removed ssn validators, since it is unlikely that most people will need it and if they do, they can added it thorough RegExp
Diffstat (limited to 'src')
| -rw-r--r-- | src/filters.js | 4 | ||||
| -rw-r--r-- | src/scenario/dsl.js | 29 | ||||
| -rw-r--r-- | src/validators.js | 217 | ||||
| -rw-r--r-- | src/widgets.js | 129 | 
4 files changed, 344 insertions, 35 deletions
diff --git a/src/filters.js b/src/filters.js index 206da240..14d0dff8 100644 --- a/src/filters.js +++ b/src/filters.js @@ -343,7 +343,7 @@ snippet</p></textarea>       });       it('should update', function(){ -       textarea('snippet').enter('new <b>text</b>'); +       input('snippet').enter('new <b>text</b>');         expect(using('#html-filter').binding('snippet | html')).toBe('new <b>text</b>');         expect(using('#escaped-html').binding('snippet')).toBe("new <b>text</b>");         expect(using('#html-unsafe-filter').binding("snippet | html:'unsafe'")).toBe('new <b>text</b>'); @@ -415,7 +415,7 @@ and one more: ftp://127.0.0.1/.</textarea>       });       it('should update', function(){ -       textarea('snippet').enter('new http://link.'); +       input('snippet').enter('new http://link.');         expect(using('#linky-filter').binding('snippet | linky')).           toBe('new <a href="http://link">http://link</a>.');         expect(using('#escaped-html').binding('snippet')).toBe('new http://link.'); diff --git a/src/scenario/dsl.js b/src/scenario/dsl.js index f37ab71d..99bc63a9 100644 --- a/src/scenario/dsl.js +++ b/src/scenario/dsl.js @@ -191,7 +191,7 @@ angular.scenario.dsl('input', function() {    chain.enter = function(value) {      return this.addFutureAction("input '" + this.name + "' enter '" + value + "'", function($window, $document, done) { -      var input = $document.elements('input[name="$1"]', this.name); +      var input = $document.elements(':input[name="$1"]', this.name);        input.val(value);        input.trigger('change');        done(); @@ -200,7 +200,7 @@ angular.scenario.dsl('input', function() {    chain.check = function() {      return this.addFutureAction("checkbox '" + this.name + "' toggle", function($window, $document, done) { -      var input = $document.elements('input:checkbox[name="$1"]', this.name); +      var input = $document.elements(':checkbox[name="$1"]', this.name);        input.trigger('click');        done();      }); @@ -209,7 +209,7 @@ angular.scenario.dsl('input', function() {    chain.select = function(value) {      return this.addFutureAction("radio button '" + this.name + "' toggle '" + value + "'", function($window, $document, done) {        var input = $document. -        elements('input:radio[name$="@$1"][value="$2"]', this.name, value); +        elements(':radio[name$="@$1"][value="$2"]', this.name, value);        input.trigger('click');        done();      }); @@ -224,29 +224,6 @@ angular.scenario.dsl('input', function() {  /**   * Usage: - *    textarea(name).enter(value) enters value in the text area with specified name - */ -angular.scenario.dsl('textarea', function() { -  var chain = {}; - -  chain.enter = function(value) { -    return this.addFutureAction("textarea '" + this.name + "' enter '" + value + "'", function($window, $document, done) { -      var textarea = $document.elements('textarea[name="$1"]', this.name); -      textarea.val(value); -      textarea.trigger('change'); -      done(); -    }); -  }; - -  return function(name) { -    this.name = name; -    return chain; -  }; -}); - - -/** - * Usage:   *    repeater('#products table', 'Product List').count() number of rows   *    repeater('#products table', 'Product List').row(1) all bindings in row as an array   *    repeater('#products table', 'Product List').column('product.name') all values across all rows in an array diff --git a/src/validators.js b/src/validators.js index 2d8b5354..9715be59 100644 --- a/src/validators.js +++ b/src/validators.js @@ -1,6 +1,31 @@  extend(angularValidator, {    'noop': function() { return _null; }, +  /** +   * @ngdoc validator +   * @name angular.validator.regexp +   * @description +   * Use regexp validator to restrict the input to any Regular Expression. +   *  +   * @param {string} value value to validate +   * @param {regexp} expression regular expression. +   * @css ng-validation-error +   *  +   * @example +   * Enter valid SSN: +   * <input name="ssn" value="123-45-6789" ng:validate="regexp:/^\d\d\d-\d\d-\d\d\d\d$/" > +   *  +   * @scenario +   * it('should invalidate non ssn', function(){ +   *   var textBox = element('.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) {      if (!value.match(regexp)) {        return msg || @@ -10,6 +35,43 @@ extend(angularValidator, {      }    }, +  /** +   * @ngdoc validator +   * @name angular.validator.number +   * @description +   * Use number validator to restrict the input to numbers with an  +   * optional range. (See integer for whole numbers validator). +   *  +   * @param {string} value value to validate +   * @param {int=} [min=MIN_INT] minimum value. +   * @param {int=} [max=MAX_INT] maximum value. +   * @css ng-validation-error +   *  +   * @example +   * Enter number: <input name="n1" ng:validate="number" > <br> +   * Enter number greater than 10: <input name="n2" ng:validate="number:10" > <br> +   * Enter number between 100 and 200: <input name="n3" ng:validate="number:100:200" > <br> +   *  +   * @scenario +   * it('should invalidate number', function(){ +   *   var n1 = element('.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('.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('.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) {      var num = 1 * value;      if (num == value) { @@ -25,6 +87,42 @@ extend(angularValidator, {      }    }, +  /** +   * @ngdoc validator +   * @name angular.validator.integer +   * @description +   * Use number validator to restrict the input to integers with an  +   * optional range. (See integer for whole numbers validator). +   *  +   * @param {string} value value to validate +   * @param {int=} [min=MIN_INT] minimum value. +   * @param {int=} [max=MAX_INT] maximum value. +   * @css ng-validation-error +   *  +   * @example +   * Enter integer: <input name="n1" ng:validate="integer" > <br> +   * Enter integer equal or greater than 10: <input name="n2" ng:validate="integer:10" > <br> +   * Enter integer between 100 and 200 (inclusive): <input name="n3" ng:validate="integer:100:200" > <br> +   *  +   * @scenario +   * it('should invalidate integer', function(){ +   *   var n1 = element('.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('.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('.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);      if (numberError) return numberError; @@ -34,6 +132,29 @@ extend(angularValidator, {      return _null;    }, +  /** +   * @ngdoc validator +   * @name angular.validator.date +   * @description +   * Use date validator to restrict the user input to a valid date +   * in format in format MM/DD/YYYY. +   *  +   * @param {string} value value to validate +   * @css ng-validation-error +   *  +   * @example +   * Enter valid date: +   * <input name="text" value="1/1/2009" ng:validate="date" > +   *  +   * @scenario +   * it('should invalidate date', function(){ +   *   var n1 = element('.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) {      var fields = /^(\d\d?)\/(\d\d?)\/(\d\d\d\d)$/.exec(value);      var date = fields ? new Date(fields[3], fields[1]-1, fields[2]) : 0; @@ -44,13 +165,28 @@ extend(angularValidator, {                _null : "Value is not a date. (Expecting format: 12/31/2009).";    }, -  'ssn': function(value) { -    if (value.match(/^\d\d\d-\d\d-\d\d\d\d$/)) { -      return _null; -    } -    return "SSN needs to be in 999-99-9999 format."; -  }, - +  /** +   * @ngdoc validator +   * @name angular.validator.email +   * @description +   * Use email validator if you wist to restrict the user input to a valid email. +   *  +   * @param {string} value value to validate +   * @css ng-validation-error +   *  +   * @example +   * Enter valid email: +   * <input name="text" ng:validate="email" value="me@example.com"> +   *  +   * @scenario +   * it('should invalidate email', function(){ +   *   var n1 = element('.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) {      if (value.match(/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/)) {        return _null; @@ -58,6 +194,28 @@ extend(angularValidator, {      return "Email needs to be in username@host.com format.";    }, +  /** +   * @ngdoc validator +   * @name angular.validator.phone +   * @description +   * Use phone validator to restrict the input phone numbers. +   *  +   * @param {string} value value to validate +   * @css ng-validation-error +   *  +   * @example +   * Enter valid phone number: +   * <input name="text" value="1(234)567-8901" ng:validate="phone" > +   *  +   * @scenario +   * it('should invalidate phone', function(){ +   *   var n1 = element('.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) {      if (value.match(/^1\(\d\d\d\)\d\d\d-\d\d\d\d$/)) {        return _null; @@ -68,6 +226,28 @@ extend(angularValidator, {      return "Phone number needs to be in 1(987)654-3210 format in North America or +999 (123) 45678 906 internationaly.";    }, +  /** +   * @ngdoc validator +   * @name angular.validator.url +   * @description +   * Use phone validator to restrict the input URLs. +   *  +   * @param {string} value value to validate +   * @css ng-validation-error +   *  +   * @example +   * Enter valid phone number: +   * <input name="text" value="http://example.com/abc.html" size="40" ng:validate="url" > +   *  +   * @scenario +   * it('should invalidate url', function(){ +   *   var n1 = element('.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) {      if (value.match(/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/)) {        return _null; @@ -75,6 +255,29 @@ extend(angularValidator, {      return "URL needs to be in http://server[:port]/path format.";    }, +  /** +   * @ngdoc validator +   * @name angular.validator.json +   * @description +   * Use json validator if you wish to restrict the user input to a valid JSON. +   *  +   * @param {string} value value to validate +   * @css ng-validation-error +   *  +   * @example +   * <textarea name="json" cols="60" rows="5" ng:validate="json"> +   * {name:'abc'} +   * </textarea> +   *  +   * @scenario +   * it('should invalidate json', function(){ +   *   var n1 = element('.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) {      try {        fromJson(value); diff --git a/src/widgets.js b/src/widgets.js index 4845e694..43a16c8c 100644 --- a/src/widgets.js +++ b/src/widgets.js @@ -1,5 +1,134 @@  /** + * @ngdoc widget + * @name angular.widget.HTML   * + * @description + * The most common widgets you will use will be in the from of the + * standard HTML set. These widgets are bound using the name attribute + * to an expression. In addition they can have `ng:validate`, `ng:required`, + * `ng:format`, `ng:change` attribute to further control their behavior. + *  + * @usageContent + *   see example below for usage + *  + *   <input type="text|checkbox|..." ... /> + *   <textarea ... /> + *   <select ...> + *     <option>...</option> + *   </select> + *  + * @example +<table style="font-size:.9em;"> +  <tr> +    <th>Name</th> +    <th>Format</th> +    <th>HTML</th> +    <th>UI</th> +    <th ng:non-bindable>{{input#}}</th> +  </tr> +  <tr> +    <th>text</th> +    <td>String</td> +    <td><tt><input type="text" name="input1"></tt></td> +    <td><input type="text" name="input1" size="4"></td> +    <td><tt>{{input1|json}}</tt></td> +  </tr> +  <tr> +    <th>textarea</th> +    <td>String</td> +    <td><tt><textarea name="input2"></textarea></tt></td> +    <td><textarea name="input2" cols='6'></textarea></td> +    <td><tt>{{input2|json}}</tt></td> +  </tr> +  <tr> +    <th>radio</th> +    <td>String</td> +    <td><tt> +      <input type="radio" name="input3" value="A"><br> +      <input type="radio" name="input3" value="B"> +    </tt></td> +    <td> +      <input type="radio" name="input3" value="A"> +      <input type="radio" name="input3" value="B"> +    </td> +    <td><tt>{{input3|json}}</tt></td> +  </tr> +  <tr> +    <th>checkbox</th> +    <td>Boolean</td> +    <td><tt><input type="checkbox" name="input4" value="checked"></tt></td> +    <td><input type="checkbox" name="input4" value="checked"></td> +    <td><tt>{{input4|json}}</tt></td> +  </tr> +  <tr> +    <th>pulldown</th> +    <td>String</td> +    <td><tt> +      <select name="input5"><br> +        <option value="c">C</option><br> +        <option value="d">D</option><br> +      </select><br> +    </tt></td> +    <td> +      <select name="input5"> +        <option value="c">C</option> +        <option value="d">D</option> +      </select> +    </td> +    <td><tt>{{input5|json}}</tt></td> +  </tr> +  <tr> +    <th>multiselect</th> +    <td>Array</td> +    <td><tt> +      <select name="input6" multiple size="4"><br> +        <option value="e">E</option><br> +        <option value="f">F</option><br> +      </select><br> +    </tt></td> +    <td> +      <select name="input6" multiple size="4"> +        <option value="e">E</option> +        <option value="f">F</option> +      </select> +    </td> +    <td><tt>{{input6|json}}</tt></td> +  </tr> +</table> +  + * @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"]'); + * });   */  function modelAccessor(scope, element) {  | 
