Created
November 9, 2015 21:50
-
-
Save csaftoiu/0c930dd0edb11a71d7fc to your computer and use it in GitHub Desktop.
Angular binding for Foundation Datepicker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
/** | |
* @ngdoc overview | |
* @name foundation.datepicker.angular | |
* @description | |
* # foundation.datepicker.angular | |
* | |
* Add angular support for {@link http://foundation-datepicker.peterbeno.com/example.html foundation-datepicker}. | |
*/ | |
angular | |
.module('foundation.datepicker.angular', []) | |
/** | |
* @ngdoc directive | |
* @name foundation.datepicker.angular.directive:datePicker | |
* | |
* @restrict E | |
* | |
* @description Element directive for | |
* {@link http://foundation-datepicker.peterbeno.com/example.html foundation-datepicker}. | |
* Adds a text input field which, when clicked, pops up the datepicker. | |
* | |
* @param {string} ngModel Assignable angular expression to data-bind the date to. | |
* This should be a JavaScript Date object. | |
* @param {string=} format The date format, combination of d, dd, m, mm, yy, yyyy, hh, ii. Default `"yyyy-mm-dd"`. | |
* @param {string=} language Two-char iso shortcut of language you want to use, default `"en"`. Must include the | |
* proper locale `.js` file, via a `<script>` tag. | |
* @param {string=} pickTime Provide this param to enable picking the time after picking the date. | |
* @param {expression=} ngMindate Specify a minimum allowable date. | |
* @param {expression=} ngMaxdate Specify a maximum allowable date. | |
* | |
* @example | |
* Generate an input element which picks a date and time, bound to `$scope.travelTime`, that must be >= today's date. | |
* | |
* HTML: | |
* <pre> | |
* <date-picker ng-model="travelTime" pick-time | |
* format="yyyy-mm-dd hh:ii" | |
* ng-mindate="today"></date-picker> | |
* </pre> | |
* Controller: | |
* <pre> | |
* $scope.travelTime = new Date(); | |
* var now = new Date(); | |
* $scope.today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); | |
* </pre> | |
* Output may be something like: <br> | |
* <img src="http://i.imgur.com/5KWGtqu.png"> | |
*/ | |
.directive('datePicker', function () { | |
var toFakeUTC = function (realLocal) { | |
return new Date(Date.UTC( | |
realLocal.getFullYear(), realLocal.getMonth(), realLocal.getDate(), | |
realLocal.getHours(), realLocal.getMinutes(), realLocal.getSeconds())); | |
}; | |
var fromFakeUTC = function (fakeUTC) { | |
return new Date(fakeUTC.getTime() + (fakeUTC.getTimezoneOffset() * 60000)); | |
}; | |
return { | |
require: 'ngModel', | |
restrict: 'E', | |
scope: { format: "@", language: "@", pickTime: "@", | |
mindate: '=ngMindate', maxdate: '=ngMaxdate'}, | |
template: '<input type="text" ng-model="formattedDate">', | |
link: function (scope, element, attrs, ngModelCtrl) { | |
if (scope.format === undefined) { | |
scope.format = "yyyy-mm-dd"; | |
} | |
if (scope.language === undefined) { | |
scope.language = "en"; | |
} | |
var $input = $(element.children("input")[0]); | |
var datepicker = $input.fdatepicker({ | |
format: scope.format, | |
language: scope.language, | |
pickTime: attrs.pickTime !== undefined && scope.pickTime !== "0", | |
onRender: function (date) { | |
// scope.mindate/scope.maxdate are in real local time, convert to | |
// fake utc to compare equally with the date picker | |
if (scope.mindate !== undefined) { | |
if (date.valueOf() < toFakeUTC(scope.mindate).valueOf()) { | |
return 'disabled'; | |
} | |
} | |
if (scope.maxdate !== undefined) { | |
if (date.valueOf() > toFakeUTC(scope.maxdate).valueOf()) { | |
return 'disabled'; | |
} | |
} | |
return ''; | |
} | |
}).data('datepicker'); | |
// modelValue is a Date object, in whatever local time zone | |
// viewValue is the formatted date according to foundation-datepicker | |
ngModelCtrl.$formatters.push(function (modelValue) { | |
// formatDate formats the date in UTC time, so we need to get a date which, when formatted in UTC, would | |
// look like this local timezone | |
return $.fn.fdatepicker.DPGlobal.formatDate( | |
toFakeUTC(modelValue), $.fn.fdatepicker.DPGlobal.parseFormat(scope.format), scope.language); | |
}); | |
ngModelCtrl.$render = function () { | |
// set view value | |
scope.formattedDate = ngModelCtrl.$viewValue; | |
// lock to model value. not sure why this is needed but without it the values | |
// sometimes get out of sync | |
if (datepicker.getDate() !== ngModelCtrl.$modelValue) { | |
datepicker.update(ngModelCtrl.$modelValue); | |
} | |
}; | |
// updated by the datepicker acting on the <input> field | |
scope.$watch('formattedDate', function (newValue, oldValue) { | |
ngModelCtrl.$setViewValue(newValue); | |
}); | |
ngModelCtrl.$parsers.push(function (viewValue) { | |
var fakeUTC = $.fn.fdatepicker.DPGlobal.parseDate( | |
viewValue, $.fn.fdatepicker.DPGlobal.parseFormat(scope.format), scope.language); | |
// asUTC is 'fake' UTC (as a UTC date, but in the local timezone) | |
// convert it to real UTC | |
return fromFakeUTC(fakeUTC); | |
}); | |
// watch mindate/maxdate changes, set value if it's over/under | |
scope.$watch('mindate', function (newMin) { | |
if (newMin === undefined) { | |
return; | |
} | |
if (datepicker.getDate() < newMin) { // handles UTC conversions | |
datepicker.update(newMin); | |
} | |
}); | |
scope.$watch('maxdate', function (newMax) { | |
if (newMax === undefined) { | |
return; | |
} | |
if (datepicker.getDate() > newMax) { | |
datepicker.update(newMax); | |
} | |
}); | |
} | |
}; | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment