From 29cafba56ee5ba376606e41f830571afb337dc8d Mon Sep 17 00:00:00 2001 From: g00fy Date: Mon, 7 Oct 2013 22:53:31 +0200 Subject: [PATCH] stage 2 --- app/index.html | 111 ++++---- app/scripts/module.js | 504 ++++++++++++---------------------- app/templates/datepicker.html | 241 ++++++++-------- 3 files changed, 355 insertions(+), 501 deletions(-) diff --git a/app/index.html b/app/index.html index 89ef06e..620eac4 100644 --- a/app/index.html +++ b/app/index.html @@ -12,7 +12,7 @@ - +

{{ start }}

Calendar

@@ -20,64 +20,67 @@

views

default
<div date-picker="start"></div> 
-
-
year
-
<div date-picker="start"  year></div> 
+ + {{ start }} +
+ + +
-
month
-
<div date-picker="start month></div> 
-
-
date
-
<div date-picker="start" date></div> 
-
-
hours
-
<div date-picker="start" hours></div> 
-
-
minutes
-
<div date-picker="start" minutes></div> 
-
+ + + + + + + + + + + +
-
-

Input

-
default
-
<input type="datetime" ng-model="model" date-time></div> 
- -
Input format
-
<input type="datetime" ng-model="model" date-time format="long"></div> 
- -
A button
-
<div class="dropdown">
-  <a class="dropdown-toggle btn btn-danger">
-    pick a date: {{(date|date)}}
-  </a>
-  <div class="dropdown-menu" ng-click="$event.preventDefault();$event.stopPropagation()">
-    <div date-picker="date" class="datetimepicker"></div>
-  </div>
-</div>
- -
Date range
-
<div date-range start="start" end="end" ></div> 
-
-
Date range button
+ + + + + + + + - -
+ + + + +
diff --git a/app/scripts/module.js b/app/scripts/module.js index 810199c..37bdb76 100644 --- a/app/scripts/module.js +++ b/app/scripts/module.js @@ -4,11 +4,8 @@ Module.directive('datePicker', function () { - var viewOptions = ['month', 'date', 'year', 'month', 'hours', 'minutes']; - - function isValidDate(date) { - return date instanceof Date && !isNaN(date.getTime()); - } + var views = ['year', 'month', 'date', 'hours', 'minutes']; + var noop = angular.noop; function getVisibleMinutes(date) { date = new Date(date || new Date()); @@ -100,349 +97,198 @@ } return { + templateUrl: 'templates/datepicker.html', + replace:true, scope : { - date : '=datePicker', + model: '=datePicker', + view : '=?', after : '=?', before: '=?' }, link : function (scope, element, attrs) { - scope.views = []; + // if model value was updated or already existing; + var updated = !!scope.model; - for (var attr in attrs) { //noinspection JSUnfilteredForInLoop - if (viewOptions.indexOf(attr) !== -1) { //noinspection JSUnfilteredForInLoop - scope.views.push(attr); + scope.date = new Date(); + + if(!scope.view){ + // set default view + scope.view = views[0]; + } + + scope.setView= function(nextView){ + scope.view = nextView; + }; + + + scope.setDate = function(date){ + scope.date = date; + // change next view + var nextView = views[views.indexOf(scope.view)+1]; + if(nextView){ + scope.view = nextView; + updated = true; } - } - - if (!scope.views.length) { - scope.views = ['date', 'month', 'year', 'hours', 'minutes']; - } - scope.view = scope.views[0]; - - function hasView(view) { - return scope.views.indexOf(view) !== -1; - } - - function ensureDate() { - // we need to return new instance as ngModel $watch watches only for identity - not for equality - if (!(isValidDate(scope.date))) { - scope.date = new Date(2000, 1, 1); + if(!nextView || updated){ + scope.model = date; } - scope.date = new Date(scope.date); - } - - function setYear(date) { - ensureDate(); - scope.date.setFullYear(date.getFullYear()); - } - - function setMonth(date) { - setYear(date); - scope.date.setMonth(date.getMonth()); - } - - function setDate(date) { - setMonth(date); - scope.date.setDate(date.getDate()); - } - - function setHours(date) { - setDate(date); - scope.date.setHours(date.getHours()); - } - - function setMinutes(date) { - setHours(date); - scope.date.setMinutes(date.getMinutes()); - } - - scope.setYear = function (date) { - setYear(date); - scope.$emit('setYear', date); }; - scope.setMonth = function (date) { - setMonth(date); - scope.$emit('setMonth', date); - }; - - scope.setDate = function (date) { - setDate(date); - scope.$emit('setDate', date); - }; - - scope.setHours = function (date) { - setHours(date); - scope.$emit('setHours', date); - }; - - scope.setMinutes = function (date) { - setMinutes(date); - scope.$emit('setMinutes', date); - }; - - scope.setView = function setView(view) { - if (hasView(view)) { - scope.view = view; - switch (view) { + 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(scope.visibleDate); + scope.minutes = getVisibleMinutes(date); break; - case 'hours' : - scope.hours = getVisibleHours(scope.visibleDate); - break; - case 'date' : - scope.weeks = getVisibleWeeks(scope.visibleDate); - break; - case 'month' : - scope.months = getVisibleMonths(scope.visibleDate); - break; - case 'year' : - scope.years = getVisibleYears(scope.visibleDate); - break; - } - } - }; - - scope.nextMonth = function (delta) { - scope.visibleDate.setMonth(scope.visibleDate.getMonth() + (delta || 1)); - }; - - scope.prevMonth = function (delta) { - scope.nextMonth(-delta || -1); - }; - - scope.nextDay = function (delta) { - scope.visibleDate.setDate(scope.visibleDate.getDate() + (delta || 1)); - }; - - scope.prevDay = function (delta) { - scope.nextDay(-delta || -1); - }; - - scope.nextHour = function (delta) { - scope.visibleDate.setHours(scope.visibleDate.getHours() + (delta || 1)); - }; - - scope.prevHour = function (delta) { - scope.nextHour(-delta || -1); - }; - - scope.nextYear = function (delta) { - scope.visibleDate.setFullYear(scope.visibleDate.getFullYear() + (delta || 1)); - }; - scope.prevYear = function (delta) { - scope.nextYear(-delta || -1); - }; - - scope.visibleDate = new Date(); - - scope.$watch('date', function (date) { - if (date) { - scope.visibleDate = new Date(date); - } - }); - - scope.isAfter = function (date) { - return date >= scope.after; - }; - - scope.isBefore = function (date) { - return date <= scope.before; - }; - - function validDate() { - return scope.date instanceof Date; - } - - scope.isSameMinutes = function (date) { - if (!validDate()){ - return false; - } - var b = scope.date; - return (date.getTime() - date.getSeconds() * 1000 - date.getMilliseconds()) === (b.getTime() - b.getSeconds() * 1000 - b.getMilliseconds()); - }; - - scope.isSameMonth = function (date) { - if (!validDate()){ - return false; - } - return date.getFullYear() === scope.date.getFullYear() && date.getMonth() === scope.date.getMonth(); - }; - - scope.isSameYear = function (date) { - if (!validDate()){ - return false; - } - return date.getFullYear() === scope.date.getFullYear(); - }; - - scope.isSameDate = function (date) { - if (!validDate()){ - return false; - } - return scope.date.getDate() === date.getDate() && scope.isSameMonth(date); - }; - - scope.isSameHour = function (date) { - if (!validDate()){ - return false; - } - return scope.date.getHours() === date.getHours() && scope.isSameDate(date); - }; - - scope.isOldMonth = function (date) { - return date - .getTime() < scope.visibleDate.getTime() && date.getMonth() !== scope.visibleDate.getMonth(); - }; - - scope.isNewHour = function (date) { - return date.getTime() > scope.visibleDate.getTime() && date.getHours() !== scope.visibleDate.getHours(); - }; - - scope.isOldHour = function (date) { - return date.getTime() < scope.visibleDate.getTime() && date.getHours() !== scope.visibleDate.getHours(); - }; - - scope.isNewMonth = function (date) { - return date.getTime() > scope.visibleDate.getTime() && date.getMonth() !== scope.visibleDate.getMonth(); - }; - - - scope.$on('setDate', scope.setView.bind(null, 'hours')); - scope.$on('setMonth', scope.setView.bind(null, 'date')); - scope.$on('setHours', scope.setView.bind(null, 'minutes')); - scope.$on('setYear', scope.setView.bind(null, 'month')); - - scope.$watch(function () { - return isValidDate(scope.visibleDate); - }, function (valid) { - if (!valid) { - scope.visibleDate = new Date(); - } - }); - - //hours - scope.$watch('[visibleDate.getDate(),visibleDate.getHours()].join()', function () { - if (scope.view === 'hours') { - scope.hours = getVisibleHours(scope.visibleDate); - } - }); - - //date - scope.$watch('[visibleDate.getFullYear(),visibleDate.getMonth(),visibleDate.getDate()].join()', function () { - if (scope.view === 'date') { - scope.weeks = getVisibleWeeks(scope.visibleDate); - scope.weekdays = getDaysOfWeek(scope.visibleDate); - } - }); - - scope.$watch('[visibleDate.getFullYear(),visibleDate.getMonth()].join()', function () { - if (scope.view === 'month') { - scope.months = getVisibleMonths(scope.visibleDate); - } - }); - - scope.$watch('visibleDate.getYear()', function () { - if (scope.view === 'year') { - scope.years = getVisibleYears(scope.visibleDate); - } - }); - - scope.$watch('visibleDate.getTime()', function () { - if (scope.view === 'minutes') { - scope.minutes = getVisibleMinutes(scope.visibleDate); - } - }); - - }, - replace:true, - templateUrl: 'templates/datepicker.html' - }; - }); - - Module.directive('dateTime', function ($compile, $document, $filter) { - var body = $document.find('body'); - var dateFilter = $filter('date'); - return { - require: 'ngModel', - link : function (scope, element, attrs, ngModel) { - var format = attrs.format || 'yyyy-MM-dd HH:mm'; - - var viewsOptions = ['date', 'year', 'month', 'hours', 'minutes', 'month']; - var views = []; - for (var attr in attrs) { - //noinspection JSUnfilteredForInLoop - if (viewsOptions.indexOf(attr) !== -1) { //noinspection JSUnfilteredForInLoop - views.push(attr); } } - function formatter(value) { - return dateFilter(value, format); - } - - ngModel.$formatters.push(formatter); - - var picker = null; - var clear = function(){ - if(picker){ - picker.remove(); - picker = null; - } - }; - var template = ''; - - function update(obj,date){ - ngModel.$setViewValue(date); - } - - element.bind('focus', function () { - if (!picker) { - // create picker element - picker = $compile(template)(scope); - body.append(picker); - scope.$digest(); - - - scope.$on('setDate', update); - scope.$on('setMonth',update); - scope.$on('setHours',update); - scope.$on('setYear', update); - - var pos = angular.extend(element.offset(), { height: element[0].offsetHeight }); - picker.css({ top: pos.top + pos.height, left: pos.left, display: 'block', position: 'absolute'}); - picker.bind('mousedown', function () { - return false; - }); - } - return false; + scope.$watch('view', function (view) { + update(); }); - element.bind('blur', clear); + + scope.next = function(delta){ + var date = scope.date; + delta = delta || 1; + switch(scope.view){ + case 'year': + case 'month': + date.setFullYear(date.getFullYear() + delta); + break; + case 'date': + date.setMonth(date.getMonth() + delta); + break; + case 'hours': + case 'minutes': + date.setHours(date.getHours() + delta); + break; + } + update(); + }; + + scope.prev = function(delta){ + return scope.next(delta || -1); + }; + + scope.isAfter = function(date){ + return updated && scope.model ? scope.model.getTime() >= date.getTime(): false; + }; + + scope.isBefore = function(date){ + return scope.model ? scope.model.getTime() <= date.getTime(): false; + }; + + scope.isSameMonth = function(date){ + return scope.isSameYear(date) && scope.model ? scope.model.getMonth() == date.getMonth() : false; + }; + + scope.isSameYear= function(date){ + return (scope.model ? scope.model.getFullYear() == date.getFullYear(): false); + }; + + scope.isSameDay = function(date){ + return scope.isSameMonth(date) && scope.model ? scope.model.getDate() == date.getDate() : false; + }; } }; }); - 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); - } - }); - } - }; - }); +// Module.directive('dateTime', function ($compile, $document, $filter) { +// var body = $document.find('body'); +// var dateFilter = $filter('date'); +// return { +// require: 'ngModel', +// link : function (scope, element, attrs, ngModel) { +// var format = attrs.format || 'yyyy-MM-dd HH:mm'; +// +// var viewsOptions = ['date', 'year', 'month', 'hours', 'minutes', 'month']; +// var views = []; +// for (var attr in attrs) { +// //noinspection JSUnfilteredForInLoop +// if (viewsOptions.indexOf(attr) !== -1) { //noinspection JSUnfilteredForInLoop +// views.push(attr); +// } +// } +// +// function formatter(value) { +// return dateFilter(value, format); +// } +// +// ngModel.$formatters.push(formatter); +// +// var picker = null; +// var clear = function(){ +// if(picker){ +// picker.remove(); +// picker = null; +// } +// }; +// var template = ''; +// +// function update(obj,date){ +// ngModel.$setViewValue(date); +// } +// +// element.bind('focus', function () { +// if (!picker) { +// // create picker element +// picker = $compile(template)(scope); +// body.append(picker); +// scope.$digest(); +// +// +// scope.$on('setDate', update); +// scope.$on('setMonth',update); +// scope.$on('setHours',update); +// scope.$on('setYear', update); +// +// var pos = angular.extend(element.offset(), { height: element[0].offsetHeight }); +// picker.css({ top: pos.top + pos.height, left: pos.left, display: 'block', position: 'absolute'}); +// picker.bind('mousedown', function () { +// return false; +// }); +// } +// return false; +// }); +// element.bind('blur', clear); +// } +// }; +// }); + +// 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); +// } +// }); +// } +// }; +// }); })(angular); diff --git a/app/templates/datepicker.html b/app/templates/datepicker.html index 2c4fe30..060c6dc 100644 --- a/app/templates/datepicker.html +++ b/app/templates/datepicker.html @@ -1,127 +1,132 @@
-
-
- - - - - - - - - - - - - - - - - - - - - -
{{visibleDate|date:"yyyy MMMM"}}
{{ day|date:"EEE"}}
{{ day.getDate() }} -
-
-
- - - - - - - - - - - - - -
{{years[0].getFullYear()}}-{{years[years.length-1].getFullYear()}}
- {{year.getFullYear()}} -
-
+
+
+ + + + + + + + + + + + + + + + + + + + + +
{{date|date:"yyyy MMMM"}}
{{ day|date:"EEE"}}
{{ day.getDate() }} + -
- - - - - - - - - - - + + + + + + + +
{{ visibleDate|date:"yyyy" }}
+
+
+
+ + + + + + + + + + + + + +
{{years[0].getFullYear()}}-{{years[years.length-1].getFullYear()}}
+ {{year.getFullYear()}} + + +
+
+ +
+ + + + + + + + + + + - - - - - - - -
{{ date|date:"yyyy" }}
{{month|date:'MMM'}} -
-
+ ng-click="setDate(month)">{{month|date:'MMM'}} -
- - - - - - - - - - - + + + + + + + +
{{ visibleDate|date:"dd MMMM yyyy" }}
+
+
+ +
+ + + + + + + + + + + - - - - - - - -
{{ date|date:"dd MMMM yyyy" }}
{{hour|date:"HH:mm"}} -
-
-
- - - - - - - - - - - - - - - - - - -
{{ visibleDate|date:"dd MMMM yyyy HH:mm" }} -
- {{minute|date:"HH:mm"}} -
-
+ ng-click="setDate(hour)">{{hour|date:"HH:mm"}} +
+
+
+ + + + + + + + + + + + + + + + + + +
{{ date|date:"dd MMMM yyyy HH:mm" }} +
+ + {{minute|date:"HH:mm"}} +
+