aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/.jshintrc3
-rw-r--r--src/ng/directive/input.js535
-rw-r--r--src/ng/filter/filters.js34
3 files changed, 568 insertions, 4 deletions
diff --git a/src/.jshintrc b/src/.jshintrc
index f32caa45..4e19601d 100644
--- a/src/.jshintrc
+++ b/src/.jshintrc
@@ -101,6 +101,9 @@
"getter": false,
"getBlockElements": false,
+ /* filters.js */
+ "getFirstThursdayOfYear": false,
+
/* AngularPublic.js */
"version": false,
"publishExternalAPI": false,
diff --git a/src/ng/directive/input.js b/src/ng/directive/input.js
index c31bb400..cb432c52 100644
--- a/src/ng/directive/input.js
+++ b/src/ng/directive/input.js
@@ -11,6 +11,11 @@
var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/;
var EMAIL_REGEXP = /^[a-z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-z0-9-]+(\.[a-z0-9-]+)*$/i;
var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/;
+var DATE_REGEXP = /^(\d{4})-(\d{2})-(\d{2})$/;
+var DATETIMELOCAL_REGEXP = /^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)$/;
+var WEEK_REGEXP = /^(\d{4})-W(\d\d)$/;
+var MONTH_REGEXP = /^(\d{4})-(\d\d)$/;
+var TIME_REGEXP = /^(\d\d):(\d\d)$/;
var inputType = {
@@ -91,6 +96,425 @@ var inputType = {
*/
'text': textInputType,
+ /**
+ * @ngdoc input
+ * @name input[date]
+ *
+ * @description
+ * Input with date validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, text must be entered in a valid ISO-8601
+ * date format (yyyy-MM-dd), for example: `2009-01-06`. The model must always be a Date object.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO date string (yyyy-MM-dd).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
+ * a valid ISO date string (yyyy-MM-dd).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="date-input-directive">
+ <file name="index.html">
+ <script>
+ function Ctrl($scope) {
+ $scope.value = new Date(2013, 9, 22);
+ }
+ </script>
+ <form name="myForm" ng-controller="Ctrl as dateCtrl">
+ Pick a date between in 2013:
+ <input type="date" id="exampleInput" name="input" ng-model="value"
+ placeholder="yyyy-MM-dd" min="2013-01-01" max="2013-12-31" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.date">
+ Not a valid date!</span>
+ <tt>value = {{value | date: "yyyy-MM-dd"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('value | date: "yyyy-MM-dd"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (see https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-10-22');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01-01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>f
+ */
+ 'date': createDateInputType('date', DATE_REGEXP,
+ createDateParser(DATE_REGEXP, ['yyyy', 'MM', 'dd']),
+ 'yyyy-MM-dd'),
+
+ /**
+ * @ngdoc input
+ * @name input[dateTimeLocal]
+ *
+ * @description
+ * Input with datetime validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * local datetime format (yyyy-MM-ddTHH:mm), for example: `2010-12-28T14:57`. The model must be a Date object.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO datetime format (yyyy-MM-ddTHH:mm).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
+ * a valid ISO datetime format (yyyy-MM-ddTHH:mm).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="datetimelocal-input-directive">
+ <file name="index.html">
+ <script>
+ function Ctrl($scope) {
+ $scope.value = new Date(2010, 11, 28, 14, 57);
+ }
+ </script>
+ <form name="myForm" ng-controller="Ctrl as dateCtrl">
+ Pick a date between in 2013:
+ <input type="datetime-local" id="exampleInput" name="input" ng-model="value"
+ placeholder="yyyy-MM-ddTHH:mm" min="2001-01-01T00:00" max="2013-12-31T00:00" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.datetimelocal">
+ Not a valid date!</span>
+ <tt>value = {{value | date: "yyyy-MM-ddTHH:mm"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('value | date: "yyyy-MM-ddTHH:mm"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2010-12-28T14:57');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01-01T23:59');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'datetime-local': createDateInputType('datetimelocal', DATETIMELOCAL_REGEXP,
+ createDateParser(DATETIMELOCAL_REGEXP, ['yyyy', 'MM', 'dd', 'HH', 'mm']),
+ 'yyyy-MM-ddTHH:mm'),
+
+ /**
+ * @ngdoc input
+ * @name input[time]
+ *
+ * @description
+ * Input with time validation and transformation. In browsers that do not yet support
+ * the HTML5 date input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * local time format (HH:mm), for example: `14:57`. Model must be a Date object. This binding will always output a
+ * Date object to the model of January 1, 1900, or local date `new Date(0, 0, 1, HH, mm)`.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO time format (HH:mm).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be a
+ * valid ISO time format (HH:mm).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="time-input-directive">
+ <file name="index.html">
+ <script>
+ function Ctrl($scope) {
+ $scope.value = new Date(0, 0, 1, 14, 57);
+ }
+ </script>
+ <form name="myForm" ng-controller="Ctrl as dateCtrl">
+ Pick a between 8am and 5pm:
+ <input type="time" id="exampleInput" name="input" ng-model="value"
+ placeholder="HH:mm" min="08:00" max="17:00" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.time">
+ Not a valid date!</span>
+ <tt>value = {{value | date: "HH:mm"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('value | date: "HH:mm"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('14:57');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('23:59');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'time': createDateInputType('time', TIME_REGEXP,
+ createDateParser(TIME_REGEXP, ['HH', 'mm']),
+ 'HH:mm'),
+
+ /**
+ * @ngdoc input
+ * @name input[week]
+ *
+ * @description
+ * Input with week-of-the-year validation and transformation to Date. In browsers that do not yet support
+ * the HTML5 week input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * week format (yyyy-W##), for example: `2013-W02`. The model must always be a Date object.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be a
+ * valid ISO week format (yyyy-W##).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must be
+ * a valid ISO week format (yyyy-W##).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="week-input-directive">
+ <file name="index.html">
+ <script>
+ function Ctrl($scope) {
+ $scope.value = new Date(2013, 0, 3);
+ }
+ </script>
+ <form name="myForm" ng-controller="Ctrl as dateCtrl">
+ Pick a date between in 2013:
+ <input id="exampleInput" type="week" name="input" ng-model="value"
+ placeholder="YYYY-W##" min="2012-W32" max="2013-W52" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.week">
+ Not a valid date!</span>
+ <tt>value = {{value | date: "yyyy-Www"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('value | date: "yyyy-Www"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-W01');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-W01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'week': createDateInputType('week', WEEK_REGEXP, weekParser, 'yyyy-Www'),
+
+ /**
+ * @ngdoc input
+ * @name input[month]
+ *
+ * @description
+ * Input with month validation and transformation. In browsers that do not yet support
+ * the HTML5 month input, a text element will be used. In that case, the text must be entered in a valid ISO-8601
+ * month format (yyyy-MM), for example: `2009-01`. The model must always be a Date object. In the event the model is
+ * not set to the first of the month, the first of that model's month is assumed.
+ *
+ * @param {string} ngModel Assignable angular expression to data-bind to.
+ * @param {string=} name Property name of the form under which the control is published.
+ * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. This must be
+ * a valid ISO month format (yyyy-MM).
+ * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. This must
+ * be a valid ISO month format (yyyy-MM).
+ * @param {string=} required Sets `required` validation error key if the value is not entered.
+ * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to
+ * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of
+ * `required` when you want to data-bind to the `required` attribute.
+ * @param {string=} ngChange Angular expression to be executed when input changes due to user
+ * interaction with the input element.
+ *
+ * @example
+ <example name="month-input-directive">
+ <file name="index.html">
+ <script>
+ function Ctrl($scope) {
+ $scope.value = new Date(2013, 9, 1);
+ }
+ </script>
+ <form name="myForm" ng-controller="Ctrl as dateCtrl">
+ Pick a month int 2013:
+ <input id="exampleInput" type="month" name="input" ng-model="value"
+ placeholder="yyyy-MM" min="2013-01" max="2013-12" required />
+ <span class="error" ng-show="myForm.input.$error.required">
+ Required!</span>
+ <span class="error" ng-show="myForm.input.$error.month">
+ Not a valid month!</span>
+ <tt>value = {{value | date: "yyyy-MM"}}</tt><br/>
+ <tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br/>
+ <tt>myForm.input.$error = {{myForm.input.$error}}</tt><br/>
+ <tt>myForm.$valid = {{myForm.$valid}}</tt><br/>
+ <tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br/>
+ </form>
+ </file>
+ <file name="protractor.js" type="protractor">
+ var value = element(by.binding('value | date: "yyyy-MM"'));
+ var valid = element(by.binding('myForm.input.$valid'));
+ var input = element(by.model('value'));
+
+ // currently protractor/webdriver does not support
+ // sending keys to all known HTML5 input controls
+ // for various browsers (https://github.com/angular/protractor/issues/562).
+ function setInput(val) {
+ // set the value of the element and force validation.
+ var scr = "var ipt = document.getElementById('exampleInput'); " +
+ "ipt.value = '" + val + "';" +
+ "angular.element(ipt).scope().$apply(function(s) { s.myForm[ipt.name].$setViewValue('" + val + "'); });";
+ browser.executeScript(scr);
+ }
+
+ it('should initialize to model', function() {
+ expect(value.getText()).toContain('2013-10');
+ expect(valid.getText()).toContain('myForm.input.$valid = true');
+ });
+
+ it('should be invalid if empty', function() {
+ setInput('');
+ expect(value.getText()).toEqual('value =');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+
+ it('should be invalid if over max', function() {
+ setInput('2015-01');
+ expect(value.getText()).toContain('');
+ expect(valid.getText()).toContain('myForm.input.$valid = false');
+ });
+ </file>
+ </example>
+ */
+ 'month': createDateInputType('month', MONTH_REGEXP,
+ createDateParser(MONTH_REGEXP, ['yyyy', 'MM']),
+ 'yyyy-MM'),
/**
* @ngdoc input
@@ -593,6 +1017,108 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
}
}
+function weekParser(isoWeek) {
+ if(isDate(isoWeek)) {
+ return isoWeek;
+ }
+
+ if(isString(isoWeek)) {
+ WEEK_REGEXP.lastIndex = 0;
+ var parts = WEEK_REGEXP.exec(isoWeek);
+ if(parts) {
+ var year = +parts[1],
+ week = +parts[2],
+ firstThurs = getFirstThursdayOfYear(year),
+ addDays = (week - 1) * 7;
+ return new Date(year, 0, firstThurs.getDate() + addDays);
+ }
+ }
+
+ return NaN;
+}
+
+function createDateParser(regexp, mapping) {
+ return function(iso) {
+ var parts, map;
+
+ if(isDate(iso)) {
+ return iso;
+ }
+
+ if(isString(iso)) {
+ regexp.lastIndex = 0;
+ parts = regexp.exec(iso);
+
+ if(parts) {
+ parts.shift();
+ map = { yyyy: 0, MM: 1, dd: 1, HH: 0, mm: 0 };
+
+ forEach(parts, function(part, index) {
+ if(index < mapping.length) {
+ map[mapping[index]] = +part;
+ }
+ });
+
+ return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm);
+ }
+ }
+
+ return NaN;
+ };
+}
+
+function createDateInputType(type, regexp, parseDate, format) {
+ return function dynamicDateInputType(scope, element, attr, ctrl, $sniffer, $browser, $filter) {
+ textInputType(scope, element, attr, ctrl, $sniffer, $browser);
+
+ ctrl.$parsers.push(function(value) {
+ if(ctrl.$isEmpty(value)) {
+ ctrl.$setValidity(type, true);
+ return null;
+ }
+
+ if(regexp.test(value)) {
+ ctrl.$setValidity(type, true);
+ return parseDate(value);
+ }
+
+ ctrl.$setValidity(type, false);
+ return undefined;
+ });
+
+ ctrl.$formatters.push(function(value) {
+ if(isDate(value)) {
+ return $filter('date')(value, format);
+ }
+ return '';
+ });
+
+ if(attr.min) {
+ var minValidator = function(value) {
+ var valid = ctrl.$isEmpty(value) ||
+ (parseDate(value) >= parseDate(attr.min));
+ ctrl.$setValidity('min', valid);
+ return valid ? value : undefined;
+ };
+
+ ctrl.$parsers.push(minValidator);
+ ctrl.$formatters.push(minValidator);
+ }
+
+ if(attr.max) {
+ var maxValidator = function(value) {
+ var valid = ctrl.$isEmpty(value) ||
+ (parseDate(value) <= parseDate(attr.max));
+ ctrl.$setValidity('max', valid);
+ return valid ? value : undefined;
+ };
+
+ ctrl.$parsers.push(maxValidator);
+ ctrl.$formatters.push(maxValidator);
+ }
+ };
+}
+
function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
textInputType(scope, element, attr, ctrl, $sniffer, $browser);
@@ -852,14 +1378,14 @@ function checkboxInputType(scope, element, attr, ctrl) {
</file>
</example>
*/
-var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) {
+var inputDirective = ['$browser', '$sniffer', '$filter', function($browser, $sniffer, $filter) {
return {
restrict: 'E',
require: '?ngModel',
link: function(scope, element, attr, ctrl) {
if (ctrl) {
(inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer,
- $browser);
+ $browser, $filter);
}
}
};
@@ -1247,6 +1773,11 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* - {@link input[number] number}
* - {@link input[email] email}
* - {@link input[url] url}
+ * - {@link input[date] date}
+ * - {@link input[dateTimeLocal] dateTimeLocal}
+ * - {@link input[time] time}
+ * - {@link input[month] month}
+ * - {@link input[week] week}
* - {@link ng.directive:select select}
* - {@link ng.directive:textarea textarea}
*
diff --git a/src/ng/filter/filters.js b/src/ng/filter/filters.js
index b81838c6..7c805660 100644
--- a/src/ng/filter/filters.js
+++ b/src/ng/filter/filters.js
@@ -235,6 +235,32 @@ function timeZoneGetter(date) {
return paddedZone;
}
+function getFirstThursdayOfYear(year) {
+ // 0 = index of January
+ var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();
+ // 4 = index of Thursday (+1 to account for 1st = 5)
+ // 11 = index of *next* Thursday (+1 account for 1st = 12)
+ return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);
+}
+
+function getThursdayThisWeek(datetime) {
+ return new Date(datetime.getFullYear(), datetime.getMonth(),
+ // 4 = index of Thursday
+ datetime.getDate() + (4 - datetime.getDay()));
+}
+
+function weekGetter(size) {
+ return function(date) {
+ var firstThurs = getFirstThursdayOfYear(date.getFullYear()),
+ thisThurs = getThursdayThisWeek(date);
+
+ var diff = +thisThurs - +firstThurs,
+ result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
+
+ return padNumber(result, size);
+ };
+}
+
function ampmGetter(date, formats) {
return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
}
@@ -263,10 +289,12 @@ var DATE_FORMATS = {
EEEE: dateStrGetter('Day'),
EEE: dateStrGetter('Day', true),
a: ampmGetter,
- Z: timeZoneGetter
+ Z: timeZoneGetter,
+ ww: weekGetter(2),
+ w: weekGetter(1)
};
-var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,
+var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,
NUMBER_STRING = /^\-?\d+$/;
/**
@@ -301,6 +329,8 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+
* * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)
* * `'a'`: am/pm marker
* * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
+ * * `'ww'`: ISO-8601 week of year (00-53)
+ * * `'w'`: ISO-8601 week of year (0-53)
*
* `format` string can also be one of the following predefined
* {@link guide/i18n localizable formats}: