UNPKG

whitesource

Version:
580 lines (514 loc) 17.6 kB
'use strict'; (function(angular){ 'use strict'; var Module = angular.module('datePicker', []); Module.constant('datePickerConfig', { template: 'templates/datepicker.html', view: 'month', views: ['year', 'month', 'date', 'hours', 'minutes'], step: 5 }); function getVisibleMinutes(date, step) { date = new Date(date || new Date()); date = new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours()); var minutes = []; var stop = date.getTime() + 60 * 60 * 1000; while (date.getTime() < stop) { minutes.push(date); date = new Date(date.getTime() + step * 60 * 1000); } return minutes; } function getVisibleWeeks(date) { date = new Date(date || new Date()); date.setDate(1); date.setHours(0); date.setMinutes(0); date.setSeconds(0); date.setMilliseconds(0); if (date.getDay() === 0) { date.setDate(-5); } else { date.setDate(date.getDate() - (date.getDay() - 1)); } if (date.getDate() === 1) { date.setDate(-6); } var weeks = []; while (weeks.length < 6) { var week = []; for (var i = 0; i < 7; i++) { week.push(new Date(date)); date.setDate(date.getDate() + 1); } weeks.push(week); } return weeks; } function getVisibleYears(date) { var years = []; date = new Date(date || new Date()); date.setFullYear(date.getFullYear() - (date.getFullYear() % 10)); for (var i = 0; i < 12; i++) { years.push(new Date(date.getFullYear() + (i - 1), 0, 1)); } return years; } function getDaysOfWeek(date) { date = new Date(date || new Date()); date = new Date(date.getFullYear(), date.getMonth(), date.getDate()); date.setDate(date.getDate() - (date.getDay() - 1)); var days = []; for (var i = 0; i < 7; i++) { days.push(new Date(date)); date.setDate(date.getDate() + 1); } return days; } function getVisibleMonths(date) { date = new Date(date || new Date()); var year = date.getFullYear(); var months = []; for (var month = 0; month < 12; month++) { months.push(new Date(year, month, 1)); } return months; } function getVisibleHours(date) { date = new Date(date || new Date()); date.setHours(0); date.setMinutes(0); date.setSeconds(0); date.setMilliseconds(0); var hours = []; for (var i = 0; i < 24; i++) { hours.push(date); date = new Date(date.getTime() + 60 * 60 * 1000); } return hours; } Module.directive('datePicker', function datePickerDirective(datePickerConfig) { //noinspection JSUnusedLocalSymbols return { // this is a bug ? template: '<div ng-include="template"></div>', scope: { model: '=datePicker', after: '=?', before: '=?' }, link: function (scope, element, attrs) { scope.date = new Date(scope.model || new Date()); scope.views = datePickerConfig.views.concat(); scope.view = attrs.view || datePickerConfig.view; scope.now = new Date(); scope.template = attrs.template || datePickerConfig.template; var step = parseInt(attrs.step || datePickerConfig.step, 10); /** @namespace attrs.minView, attrs.maxView */ scope.views =scope.views.slice( scope.views.indexOf(attrs.maxView || 'year'), scope.views.indexOf(attrs.minView || 'minutes')+1 ); if (scope.views.length === 1 || scope.views.indexOf(scope.view)===-1) { scope.view = scope.views[0]; } scope.setView = function (nextView) { if (scope.views.indexOf(nextView) !== -1) { scope.view = nextView; } }; scope.setDate = function (date) { scope.date = date; // change next view var nextView = scope.views[scope.views.indexOf(scope.view) + 1]; if (!nextView || scope.model) { scope.model = new Date(scope.model || date); //noinspection FallThroughInSwitchStatementJS switch (scope.view) { case 'minutes': scope.model.setMinutes(date.getMinutes()); /*falls through*/ case 'hours': scope.model.setHours(date.getHours()); /*falls through*/ case 'date': scope.model.setDate(date.getDate()); /*falls through*/ case 'month': scope.model.setMonth(date.getMonth()); /*falls through*/ case 'year': scope.model.setFullYear(date.getFullYear()); } scope.$emit('setDate', scope.model, scope.view); } if (nextView) { scope.setView(nextView); } }; function update() { var view = scope.view; var date = scope.date; switch (view) { case 'year': scope.years = getVisibleYears(date); break; case 'month': scope.months = getVisibleMonths(date); break; case 'date': scope.weekdays = scope.weekdays || getDaysOfWeek(); scope.weeks = getVisibleWeeks(date); break; case 'hours': scope.hours = getVisibleHours(date); break; case 'minutes': scope.minutes = getVisibleMinutes(date, step); break; } } function watch() { if (scope.view !== 'date') { return scope.view; } return scope.model ? scope.model.getMonth() : null; } scope.$watch(watch, update); scope.next = function (delta) { var date = scope.date; delta = delta || 1; switch (scope.view) { case 'year': /*falls through*/ case 'month': date.setFullYear(date.getFullYear() + delta); break; case 'date': date.setMonth(date.getMonth() + delta); break; case 'hours': /*falls through*/ case 'minutes': date.setHours(date.getHours() + delta); break; } update(); }; scope.prev = function (delta) { return scope.next(-delta || -1); }; scope.isAfter = function (date) { return scope.after ? scope.after.getTime() <= date.getTime() : false; }; scope.isBefore = function (date) { return scope.before ? scope.before.getTime() >= date.getTime() : false; }; scope.isSameMonth = function (date) { return scope.isSameYear(date) && scope.model.getMonth() === date.getMonth(); }; scope.isSameYear = function (date) { return (scope.model ? scope.model.getFullYear() === date.getFullYear() : false); }; scope.isSameDay = function (date) { return scope.isSameMonth(date) && scope.model.getDate() === date.getDate(); }; scope.isSameHour = function (date) { return scope.isSameDay(date) && scope.model.getHours() === date.getHours(); }; scope.isSameMinutes = function (date) { return scope.isSameHour(date) && scope.model.getMinutes() === date.getMinutes(); }; scope.isNow = function (date) { var is = true; var now = scope.now; //noinspection FallThroughInSwitchStatementJS switch (scope.view) { case 'minutes': is &= ~~(date.getMinutes()/step) === ~~(now.getMinutes()/step); /*falls through*/ case 'hours': is &= date.getHours() === now.getHours(); /*falls through*/ case 'date': is &= date.getDate() === now.getDate(); /*falls through*/ case 'month': is &= date.getMonth() === now.getMonth(); /*falls through*/ case 'year': is &= date.getFullYear() === now.getFullYear(); } return is; }; } }; }); 'use strict'; var Module = angular.module('datePicker'); Module.directive('dateRange', function () { return { templateUrl: 'templates/daterange.html', scope: { start: '=', end: '=' }, link: function (scope) { scope.$watch('start.getTime()', function (value) { if (value && scope.end && value > scope.end.getTime()) { scope.end = new Date(value); } }); scope.$watch('end.getTime()', function (value) { if (value && scope.start && value < scope.start.getTime()) { scope.start = new Date(value); } }); } }; }); 'use strict'; var PRISTINE_CLASS = 'ng-pristine', DIRTY_CLASS = 'ng-dirty'; var Module = angular.module('datePicker'); Module.constant('dateTimeConfig', { template: function (attrs) { return '' + '<div ' + 'date-picker="' + attrs.ngModel + '" ' + (attrs.view ? 'view="' + attrs.view + '" ' : '') + (attrs.maxView ? 'max-view="' + attrs.maxView + '" ' : '') + (attrs.template ? 'template="' + attrs.template + '" ' : '') + (attrs.minView ? 'min-view="' + attrs.minView + '" ' : '') + 'class="dropdown-menu"></div>'; }, format: 'yyyy-MM-dd HH:mm', views: ['date', 'year', 'month', 'hours', 'minutes'], dismiss: false, position: 'relative' }); Module.directive('dateTimeAppend', function () { return { link: function (scope, element) { element.bind('click', function () { element.find('input')[0].focus(); }); } }; }); Module.directive('dateTime', function ($compile, $document, $filter, dateTimeConfig, $parse) { var body = $document.find('body'); var dateFilter = $filter('date'); return { require: 'ngModel', scope:true, link: function (scope, element, attrs, ngModel) { var format = attrs.format || dateTimeConfig.format; var parentForm = element.inheritedData('$formController'); var views = $parse(attrs.views)(scope) || dateTimeConfig.views.concat(); var view = attrs.view || views[0]; var index = views.indexOf(view); var dismiss = attrs.dismiss ? $parse(attrs.dismiss)(scope) : dateTimeConfig.dismiss; var picker = null; var position = attrs.position || dateTimeConfig.position; var container = null; if (index === -1) { views.splice(index, 1); } views.unshift(view); function formatter(value) { return dateFilter(value, format); } function parser() { return ngModel.$modelValue; } ngModel.$formatters.push(formatter); ngModel.$parsers.unshift(parser); var template = dateTimeConfig.template(attrs); function updateInput(event) { event.stopPropagation(); if (ngModel.$pristine) { ngModel.$dirty = true; ngModel.$pristine = false; element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS); if (parentForm) { parentForm.$setDirty(); } ngModel.$render(); } } function clear() { if (picker) { picker.remove(); picker = null; } if (container) { container.remove(); container = null; } } function showPicker() { if (picker) { return; } // create picker element picker = $compile(template)(scope); scope.$digest(); scope.$on('setDate', function (event, date, view) { updateInput(event); if (dismiss && views[views.length - 1] === view) { clear(); } }); scope.$on('$destroy', clear); // move picker below input element if (position === 'absolute') { var pos = angular.extend(element.offset(), { height: element[0].offsetHeight }); picker.css({ top: pos.top + pos.height, left: pos.left, display: 'block', position: position}); body.append(picker); } else { // relative container = angular.element('<div date-picker-wrapper></div>'); element[0].parentElement.insertBefore(container[0], element[0]); container.append(picker); // this approach doesn't work // element.before(picker); picker.css({top: element[0].offsetHeight + 'px', display: 'block'}); } picker.bind('mousedown', function (evt) { evt.preventDefault(); }); } element.bind('focus', showPicker); element.bind('blur', clear); } }; }); angular.module("datePicker").run(["$templateCache", function($templateCache) { $templateCache.put("templates/datepicker.html", "<div ng-switch=\"view\">\n" + " <div ng-switch-when=\"date\">\n" + " <table>\n" + " <thead>\n" + " <tr>\n" + " <th ng-click=\"prev()\">‹</th>\n" + " <th colspan=\"5\" class=\"switch\" ng-click=\"setView('month')\">{{date|date:\"yyyy MMMM\"}}</th>\n" + " <th ng-click=\"next()\">›</i></th>\n" + " </tr>\n" + " <tr>\n" + " <th ng-repeat=\"day in weekdays\" style=\"overflow: hidden\">{{ day|date:\"EEE\" }}</th>\n" + " </tr>\n" + " </thead>\n" + " <tbody>\n" + " <tr ng-repeat=\"week in weeks\">\n" + " <td ng-repeat=\"day in week\">\n" + " <span\n" + " ng-class=\"{'now':isNow(day),'active':isSameDay(day),'disabled':(day.getMonth()!=date.getMonth()),'after':isAfter(day),'before':isBefore(day)}\"\n" + " ng-click=\"setDate(day)\" ng-bind=\"day.getDate()\"></span>\n" + " </td>\n" + " </tr>\n" + " </tbody>\n" + " </table>\n" + " </div>\n" + " <div ng-switch-when=\"year\">\n" + " <table>\n" + " <thead>\n" + " <tr>\n" + " <th ng-click=\"prev(10)\">‹</th>\n" + " <th colspan=\"5\" class=\"switch\">{{years[0].getFullYear()}}-{{years[years.length-1].getFullYear()}}</th>\n" + " <th ng-click=\"next(10)\">›</i></th>\n" + " </tr>\n" + " </thead>\n" + " <tbody>\n" + " <tr>\n" + " <td colspan=\"7\">\n" + " <span ng-class=\"{'active':isSameYear(year),'now':isNow(year)}\"\n" + " ng-repeat=\"year in years\"\n" + " ng-click=\"setDate(year)\" ng-bind=\"year.getFullYear()\"></span>\n" + "\n" + "\n" + " </td>\n" + " </tr>\n" + " </tbody>\n" + " </table>\n" + " </div>\n" + " <div ng-switch-when=\"month\">\n" + " <table>\n" + " <thead>\n" + " <tr>\n" + " <th ng-click=\"prev()\">‹</th>\n" + " <th colspan=\"5\" class=\"switch\" ng-click=\"setView('year')\">{{ date|date:\"yyyy\" }}</th>\n" + " <th ng-click=\"next()\">›</i></th>\n" + " </tr>\n" + " </thead>\n" + " <tbody>\n" + " <tr>\n" + " <td colspan=\"7\">\n" + " <span ng-repeat=\"month in months\"\n" + " ng-class=\"{'active':isSameMonth(month),'after':isAfter(month),'before':isBefore(month),'now':isNow(month)}\"\n" + " ng-click=\"setDate(month)\">{{month|date:'MMM'}}</span>\n" + "\n" + " </td>\n" + " </tr>\n" + " </tbody>\n" + " </table>\n" + " </div>\n" + " <div ng-switch-when=\"hours\">\n" + " <table>\n" + " <thead>\n" + " <tr>\n" + " <th ng-click=\"prev(24)\">‹</th>\n" + " <th colspan=\"5\" class=\"switch\" ng-click=\"setView('date')\">{{ date|date:\"dd MMMM yyyy\" }}</th>\n" + " <th ng-click=\"next(24)\">›</i></th>\n" + " </tr>\n" + " </thead>\n" + " <tbody>\n" + " <tr>\n" + " <td colspan=\"7\">\n" + " <span ng-repeat=\"hour in hours\"\n" + " ng-class=\"{'now':isNow(hour),'active':isSameHour(hour)}\"\n" + " ng-click=\"setDate(hour)\" ng-bind=\"hour.getHours()+':00'\"></span>\n" + " </td>\n" + " </tr>\n" + " </tbody>\n" + " </table>\n" + " </div>\n" + " <div ng-switch-when=\"minutes\">\n" + " <table>\n" + " <thead>\n" + " <tr>\n" + " <th ng-click=\"prev()\">‹</th>\n" + " <th colspan=\"5\" class=\"switch\" ng-click=\"setView('hours')\">{{ date|date:\"dd MMMM yyyy\" }}\n" + " </th>\n" + " <th ng-click=\"next()\">›</i></th>\n" + " </tr>\n" + " </thead>\n" + " <tbody>\n" + " <tr>\n" + " <td colspan=\"7\">\n" + " <span ng-repeat=\"minute in minutes\"\n" + " ng-class=\"{active:isSameMinutes(minute),'now':isNow(minute)}\"\n" + " ng-click=\"setDate(minute)\">{{minute|date:\"HH:mm\"}}</span>\n" + " </td>\n" + " </tr>\n" + " </tbody>\n" + " </table>\n" + " </div>\n" + "</div>\n" ); $templateCache.put("templates/daterange.html", "<div>\n" + " <table>\n" + " <tr>\n" + " <td valign=\"top\">\n" + " <div date-picker=\"start\" class=\"date-picker\" date after=\"start\" before=\"end\" min-view=\"date\" max-view=\"date\"></div>\n" + " </td>\n" + " <td valign=\"top\">\n" + " <div date-picker=\"end\" class=\"date-picker\" date after=\"start\" before=\"end\" min-view=\"date\" max-view=\"date\"></div>\n" + " </td>\n" + " </tr>\n" + " </table>\n" + "</div>\n" ); }]); })(angular);