diff options
Diffstat (limited to 'js/vendor/angular-ui/modules/directives/date')
4 files changed, 543 insertions, 0 deletions
diff --git a/js/vendor/angular-ui/modules/directives/date/README.md b/js/vendor/angular-ui/modules/directives/date/README.md new file mode 100644 index 000000000..71f15d933 --- /dev/null +++ b/js/vendor/angular-ui/modules/directives/date/README.md @@ -0,0 +1,73 @@ +# ui-date directive + +This directive allows you to add a date-picker to your form elements. + +# Requirements + +- JQuery +- JQueryUI +- [Date.toISOString()](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date/toISOString) (requires [polyfill](https://github.com/kriskowal/es5-shim/) for ≤IE8) + +# Usage + +Load the script file in your application: + + <script type="text/javascript" src="angular-ui.js"></script> + +Add the date module as a dependency to your application module: + + var myAppModule = angular.module('MyApp', ['ui.directives']) + +Apply the directive to your form elements: + + <input ui-date name="DateOfBirth"></input> + +## Options + +All the jQueryUI DatePicker options can be passed through the directive. + + myAppModule.controller('MyController', function($scope) { + $scope.dateOptions = { + changeYear: true, + changeMonth: true, + yearRange: '1900:-0' + }; + }); + + <input ui-date="dateOptions" name="DateOfBirth"></input> + +## Static Inline Picker + +If you want a static picker then simply apply the directive to a div rather than an input element. + + <div ui-date="dateOptions" name="DateOfBirth"></div> + +# Working with ng-model + +The ui-date directive plays nicely with ng-model and validation directives such as ng-required. + +If you add the ng-model directive to same the element as ui-date then the picked date is automatically synchronized with the model value. + +_The ui-date directive stores and expects the model value to be a standard javascript Date object._ + +## ui-date-format directive +The ui-date directive only works with Date objects. +If you want to pass date strings to and from the date directive via ng-model then you must use the ui-date-format directive. +This directive specifies the format of the date string that will be expected in the ng-model. +The format string syntax is that defined by the JQueryUI Date picker. For example + + <input ui-date ui-date-format="DD, d MM, yy" ng-model="myDate"></input> + +Now you can set myDate in the controller. + + $scope.myDate = "Thursday, 11 October, 2012"; + +## ng-required directive + +If you apply the required directive to element then the form element is invalid until a date is picked. + +Note: Remember that the ng-required directive must be explictly set, i.e. to "true". This is especially true on divs: + + <div ui-date="dateOptions" name="DateOfBirth" ng-required="true"></div> + + diff --git a/js/vendor/angular-ui/modules/directives/date/date.js b/js/vendor/angular-ui/modules/directives/date/date.js new file mode 100644 index 000000000..238ac7ff8 --- /dev/null +++ b/js/vendor/angular-ui/modules/directives/date/date.js @@ -0,0 +1,111 @@ +/*global angular */ +/* + jQuery UI Datepicker plugin wrapper + + @note If ≤ IE8 make sure you have a polyfill for Date.toISOString() + @param [ui-date] {object} Options to pass to $.fn.datepicker() merged onto ui.config + */ + +angular.module('ui.directives') + +.directive('uiDate', ['ui.config', function (uiConfig) { + 'use strict'; + var options; + options = {}; + if (angular.isObject(uiConfig.date)) { + angular.extend(options, uiConfig.date); + } + return { + require:'?ngModel', + link:function (scope, element, attrs, controller) { + var getOptions = function () { + return angular.extend({}, uiConfig.date, scope.$eval(attrs.uiDate)); + }; + var initDateWidget = function () { + var opts = getOptions(); + + // If we have a controller (i.e. ngModelController) then wire it up + if (controller) { + var updateModel = function () { + scope.$apply(function () { + var date = element.datepicker("getDate"); + element.datepicker("setDate", element.val()); + controller.$setViewValue(date); + element.blur(); + }); + }; + if (opts.onSelect) { + // Caller has specified onSelect, so call this as well as updating the model + var userHandler = opts.onSelect; + opts.onSelect = function (value, picker) { + updateModel(); + scope.$apply(function() { + userHandler(value, picker); + }); + }; + } else { + // No onSelect already specified so just update the model + opts.onSelect = updateModel; + } + // In case the user changes the text directly in the input box + element.bind('change', updateModel); + + // Update the date picker when the model changes + controller.$render = function () { + var date = controller.$viewValue; + if ( angular.isDefined(date) && date !== null && !angular.isDate(date) ) { + throw new Error('ng-Model value must be a Date object - currently it is a ' + typeof date + ' - use ui-date-format to convert it from a string'); + } + element.datepicker("setDate", date); + }; + } + // If we don't destroy the old one it doesn't update properly when the config changes + element.datepicker('destroy'); + // Create the new datepicker widget + element.datepicker(opts); + if ( controller ) { + // Force a render to override whatever is in the input text box + controller.$render(); + } + }; + // Watch for changes to the directives options + scope.$watch(getOptions, initDateWidget, true); + } + }; +} +]) + +.directive('uiDateFormat', ['ui.config', function(uiConfig) { + var directive = { + require:'ngModel', + link: function(scope, element, attrs, modelCtrl) { + var dateFormat = attrs.uiDateFormat || uiConfig.dateFormat; + if ( dateFormat ) { + // Use the datepicker with the attribute value as the dateFormat string to convert to and from a string + modelCtrl.$formatters.push(function(value) { + if (angular.isString(value) ) { + return $.datepicker.parseDate(dateFormat, value); + } + }); + modelCtrl.$parsers.push(function(value){ + if (value) { + return $.datepicker.formatDate(dateFormat, value); + } + }); + } else { + // Default to ISO formatting + modelCtrl.$formatters.push(function(value) { + if (angular.isString(value) ) { + return new Date(value); + } + }); + modelCtrl.$parsers.push(function(value){ + if (value) { + return value.toISOString(); + } + }); + } + } + }; + return directive; +}]); diff --git a/js/vendor/angular-ui/modules/directives/date/dependencies.json b/js/vendor/angular-ui/modules/directives/date/dependencies.json new file mode 100644 index 000000000..9b9d050fa --- /dev/null +++ b/js/vendor/angular-ui/modules/directives/date/dependencies.json @@ -0,0 +1,5 @@ +{ + "core": [ "jquery", "jquery-ui" ], + "internal": [], + "external": [] +}
\ No newline at end of file diff --git a/js/vendor/angular-ui/modules/directives/date/test/dateSpec.js b/js/vendor/angular-ui/modules/directives/date/test/dateSpec.js new file mode 100644 index 000000000..fc0c4db78 --- /dev/null +++ b/js/vendor/angular-ui/modules/directives/date/test/dateSpec.js @@ -0,0 +1,354 @@ +/*global describe, beforeEach, it, inject, expect, module, $*/ +describe('uiDate', function() { + 'use strict'; + var selectDate; + selectDate = function(element, date) { + element.datepicker('setDate', date); + $.datepicker._selectDate(element); + }; + beforeEach(module('ui.directives')); + describe('simple use on input element', function() { + it('should have a date picker attached', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile("<input ui-date/>")($rootScope); + expect(element.datepicker()).toBeDefined(); + }); + }); + it('should be able to get the date from the model', function() { + inject(function($compile, $rootScope) { + var aDate, element; + aDate = new Date(2010, 12, 1); + element = $compile("<input ui-date ng-model='x'/>")($rootScope); + $rootScope.$apply(function() { + $rootScope.x = aDate; + }); + expect(element.datepicker('getDate')).toEqual(aDate); + }); + }); + it('should put the date in the model', function() { + inject(function($compile, $rootScope) { + var aDate, element; + aDate = new Date(2010, 12, 1); + element = $compile("<input ui-date ng-model='x'/>")($rootScope); + $rootScope.$apply(); + selectDate(element, aDate); + expect($rootScope.x).toEqual(aDate); + }); + }); + it('should blur the input element after selecting a date', function() { + inject(function($compile, $rootScope) { + var aDate, element; + aDate = new Date(2010, 12, 1); + element = $compile("<input ui-date ng-model='x'/>")($rootScope); + $rootScope.$apply(); + $(document.body).append(element); // Need to add it to the document so that it can get focus + element.focus(); + expect(document.activeElement).toEqual(element[0]); + selectDate(element, aDate); + expect(document.activeElement).not.toEqual(element[0]); + element.remove(); // And then remove it again! + }); + }); + }); + describe('when model is not a Date', function() { + var element; + var scope; + beforeEach(inject(function($compile, $rootScope) { + element = $compile('<input ui-date="{dateFormat: \'yy-mm-dd\'}" ng-model="x"/>')($rootScope); + scope = $rootScope; + })); + it('should not freak out when the model is null', function() { + scope.$apply(function() { + scope.x = null; + }); + expect(element.datepicker('getDate')).toBe(null); + }); + it('should not freak out when the model is undefined', function() { + scope.$apply(function() { + scope.x = undefined; + }); + expect(element.datepicker('getDate')).toBe(null); + }); + it('should throw an error if you try to pass in a boolean when the model is false', function() { + expect(function() { + scope.$apply(function() { + scope.x = false; + }); + }).toThrow(); + }); + }); + + it('should update the input field correctly on a manual update', function() { + inject(function($compile, $rootScope) { + var dateString = '2012-08-17'; + var dateObj = $.datepicker.parseDate('yy-mm-dd', dateString); + var element = $compile('<input ui-date="{dateFormat: \'yy-mm-dd\'}" ng-model="x"/>')($rootScope); + $rootScope.$apply(function() { + $rootScope.x = dateObj; + }); + // Now change the data in the input box + dateString = '2012-8-01'; + dateObj = $.datepicker.parseDate('yy-mm-dd', dateString); + element.val(dateString); + element.trigger("change"); + expect(element.datepicker('getDate')).toEqual(dateObj); + expect(element.val()).toEqual('2012-08-01'); + $rootScope.$digest(); + expect($rootScope.x).toEqual(dateObj); + }); + }); + + describe("use with user events", function() { + it('should call the user onSelect event within a scope.$apply context', function() { + inject(function($compile, $rootScope) { + var watched = false; + $rootScope.myDateSelected = function() { + $rootScope.watchMe = true; + } + $rootScope.$watch("watchMe", function(watchMe) { + if (watchMe) { + watched = true; + } + }); + var aDate = new Date(2012,9,11); + var element = $compile('<input ui-date="{onSelect: myDateSelected}" ng-model="x"/>')($rootScope); + $rootScope.$apply(); + selectDate(element, aDate); + expect(watched).toBeTruthy(); + }); + }); + }); + + describe('use with ng-required directive', function() { + it('should be invalid initially', function() { + inject(function($compile, $rootScope) { + var aDate, element; + aDate = new Date(2010, 12, 1); + element = $compile("<input ui-date ng-model='x' ng-required='true' />")($rootScope); + $rootScope.$apply(); + expect(element.hasClass('ng-invalid')).toBeTruthy(); + }); + }); + it('should be valid if model has been specified', function() { + inject(function($compile, $rootScope) { + var aDate, element; + aDate = new Date(2010, 12, 1); + element = $compile("<input ui-date ng-model='x' ng-required='true' />")($rootScope); + $rootScope.$apply(function() { + $rootScope.x = aDate; + }); + expect(element.hasClass('ng-valid')).toBeTruthy(); + }); + }); + it('should be valid after the date has been picked', function() { + inject(function($compile, $rootScope) { + var aDate, element; + aDate = new Date(2010, 12, 1); + element = $compile("<input ui-date ng-model='x' ng-required='true' />")($rootScope); + $rootScope.$apply(); + selectDate(element, aDate); + expect(element.hasClass('ng-valid')).toBeTruthy(); + }); + }); + }); + describe('simple use on a div element', function() { + it('should have a date picker attached', function() { + inject(function($compile, $rootScope) { + var element; + element = $compile("<div ui-date></div>")($rootScope); + expect(element.datepicker()).toBeDefined(); + }); + }); + it('should be able to get the date from the model', function() { + inject(function($compile, $rootScope) { + var aDate, element; + aDate = new Date(2010, 12, 1); + element = $compile("<div ui-date ng-model='x'></div>")($rootScope); + $rootScope.$apply(function() { + $rootScope.x = aDate; + }); + expect(element.datepicker('getDate')).toEqual(aDate); + }); + }); + it('should put the date in the model', function() { + inject(function($compile, $rootScope) { + var aDate, element; + aDate = new Date(2010, 12, 1); + element = $compile("<div ui-date ng-model='x'></div>")($rootScope); + $rootScope.$apply(); + selectDate(element, aDate); + expect($rootScope.x).toEqual(aDate); + }); + }); + }); + describe('use with ng-required directive', function() { + it('should be invalid initially', function() { + inject(function($compile, $rootScope) { + var element = $compile("<div ui-date ng-model='x' ng-required='true' ></div>")($rootScope); + $rootScope.$apply(); + expect(element.hasClass('ng-invalid')).toBeTruthy(); + }); + }); + it('should be valid if model has been specified', function() { + inject(function($compile, $rootScope) { + var aDate, element; + aDate = new Date(2010, 12, 1); + element = $compile("<div ui-date ng-model='x' ng-required='true' ></div>")($rootScope); + $rootScope.$apply(function() { + $rootScope.x = aDate; + }); + expect(element.hasClass('ng-valid')).toBeTruthy(); + }); + }); + it('should be valid after the date has been picked', function() { + inject(function($compile, $rootScope) { + var aDate, element; + aDate = new Date(2010, 12, 1); + element = $compile("<div ui-date ng-model='x' ng-required='true' ></div>")($rootScope); + $rootScope.$apply(); + selectDate(element, aDate); + expect(element.hasClass('ng-valid')).toBeTruthy(); + }); + }); + }); + describe('when attribute options change', function() { + it('should watch attribute and update date widget accordingly', function() { + inject(function($compile, $rootScope) { + var element; + $rootScope.config = { + minDate: 5 + }; + element = $compile("<input ui-date='config' ng-model='x'/>")($rootScope); + $rootScope.$apply(); + expect(element.datepicker("option", "minDate")).toBe(5); + $rootScope.$apply(function() { + $rootScope.config.minDate = 10; + }); + expect(element.datepicker("option", "minDate")).toBe(10); + }); + }); + }); +}); + +describe('uiDateFormat', function() { + beforeEach(module('ui.directives')); + + describe('$formatting', function() { + it('should parse the date correctly from an ISO string', function() { + inject(function($compile, $rootScope) { + var aDate, aDateString, element; + aDate = new Date(2012,8,17); + aDateString = (aDate).toISOString(); + + element = $compile('<input ui-date-format ng-model="x"/>')($rootScope); + $rootScope.x = aDateString; + $rootScope.$digest(); + + // Check that the model has not been altered + expect($rootScope.x).toEqual(aDateString); + // Check that the viewValue has been parsed correctly + expect(element.controller('ngModel').$viewValue).toEqual(aDate); + }); + }); + it('should parse the date correctly from a custom string', function() { + inject(function($compile, $rootScope) { + var aDate = new Date(2012, 9, 11); + var aDateString = "Thursday, 11 October, 2012"; + + var element = $compile('<input ui-date-format="DD, d MM, yy" ng-model="x"/>')($rootScope); + $rootScope.x = aDateString; + $rootScope.$digest(); + + // Check that the model has not been altered + expect($rootScope.x).toEqual(aDateString); + // Check that the viewValue has been parsed correctly + expect(element.controller('ngModel').$viewValue).toEqual(aDate); + }); + }); + it('should handle unusual model values', function() { + inject(function($compile, $rootScope) { + var element = $compile('<input ui-date-format ng-model="x"/>')($rootScope); + + $rootScope.x = false; + $rootScope.$digest(); + // Check that the model has not been altered + expect($rootScope.x).toEqual(false); + // Check that the viewValue has been parsed correctly + expect(element.controller('ngModel').$viewValue).toEqual(null); + + $rootScope.x = undefined; + $rootScope.$digest(); + // Check that the model has not been altered + expect($rootScope.x).toBeUndefined(); + // Check that the viewValue has been parsed correctly + expect(element.controller('ngModel').$viewValue).toEqual(null); + + $rootScope.x = null; + $rootScope.$digest(); + // Check that the model has not been altered + expect($rootScope.x).toBeNull(); + // Check that the viewValue has been parsed correctly + expect(element.controller('ngModel').$viewValue).toEqual(null); + }); + }); + }); + + describe('$parsing', function() { + it('should format a selected date correctly to an ISO string', function() { + inject(function($compile, $rootScope) { + var aDate = new Date(2012,8,17); + var aDateString = (aDate).toISOString(); + var element = $compile('<input ui-date-format ng-model="x"/>')($rootScope); + $rootScope.$digest(); + + element.controller('ngModel').$setViewValue(aDate); + // Check that the model is updated correctly + expect($rootScope.x).toEqual(aDateString); + // Check that the $viewValue has not been altered + expect(element.controller('ngModel').$viewValue).toEqual(aDate); + }); + }); + + it('should format a selected date correctly to a custom string', function() { + inject(function($compile, $rootScope) { + var format = 'DD, d MM, yy'; + var aDate = new Date(2012,9,11); + var aDateString = "Thursday, 11 October, 2012"; + var element = $compile('<input ui-date-format="' + format + '" ng-model="x"/>')($rootScope); + $rootScope.$digest(); + + element.controller('ngModel').$setViewValue(aDate); + // Check that the model is updated correctly + expect($rootScope.x).toEqual(aDateString); + // Check that the $viewValue has not been altered + expect(element.controller('ngModel').$viewValue).toEqual(aDate); + }); + }); + }); + + describe('with uiConfig', function() { + var element, scope, config; + var format = 'DD, d MM, yy'; + var aDate = new Date(2012,9,11); + var aDateString = "Thursday, 11 October, 2012"; + var aISODateString = aDate.toISOString(); + beforeEach(inject(['$compile', '$rootScope', 'ui.config', function($compile, $rootScope, uiConfig) { + config = uiConfig; + element = $compile('<input ui-date-format ng-model="x"/>')($rootScope); + scope = $rootScope; + }])); + + it('use ISO if not config value', function() { + scope.x = aISODateString; + scope.$digest(); + expect(element.controller('ngModel').$viewValue).toEqual(aDate); + }); + it('use format value if config given', function() { + config.dateFormat = format; + scope.x = aDateString; + scope.$digest(); + expect(element.controller('ngModel').$viewValue).toEqual(aDate); + }); + }); +}); |