From e8233463732edeafa9e93d0ed399ba190c669bf9 Mon Sep 17 00:00:00 2001 From: spaceribs Date: Wed, 17 Feb 2016 14:28:59 -0500 Subject: [PATCH 1/4] updates for date range selection within a single calendar --- .gitignore | 1 + build/angular-mighty-datepicker.css | 4 ++ build/angular-mighty-datepicker.js | 76 ++++++++++++++++++++++++---- demo/index.html | 7 +++ gulpfile.js | 6 +-- src/angular-mighty-datepicker.coffee | 67 +++++++++++++++++++++--- src/angular-mighty-datepicker.less | 4 ++ 7 files changed, 144 insertions(+), 21 deletions(-) diff --git a/.gitignore b/.gitignore index 986ea28..0e62170 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ /bower_components .sass-cache *.map +.idea diff --git a/build/angular-mighty-datepicker.css b/build/angular-mighty-datepicker.css index a2d856b..24bcce0 100644 --- a/build/angular-mighty-datepicker.css +++ b/build/angular-mighty-datepicker.css @@ -33,6 +33,10 @@ color: #3b5; font-weight: bold; } +.mighty-picker-calendar__day--selected-to { + color: orange; + font-weight: bold; +} .mighty-picker__month { display: inline-block; margin: 0 6px; diff --git a/build/angular-mighty-datepicker.js b/build/angular-mighty-datepicker.js index 47616d0..1013045 100644 --- a/build/angular-mighty-datepicker.js +++ b/build/angular-mighty-datepicker.js @@ -4,7 +4,7 @@ angular.module("mightyDatepicker").directive("mightyDatepicker", [ "$compile", function($compile) { var options, pickerTemplate; - pickerTemplate = "
\n \n
\n
\n \n \n \n \n \n \n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
"; + pickerTemplate = "
\n \n
\n
\n \n \n \n \n \n \n
\n
\n
\n
\n
\n \n
\n
\n
\n
\n \n
"; options = { mode: "simple", months: 1, @@ -28,7 +28,7 @@ rangeTo: '=' }, link: function($scope, $element, $attrs) { - var _bake, _build, _buildMonth, _buildWeek, _getMarker, _indexMarkers, _indexOfMoment, _isInRange, _isSelected, _prepare, _setup, _withinLimits; + var _bake, _build, _buildMonth, _buildWeek, _getMarker, _indexMarkers, _indexOfMoment, _isInRange, _isSelected, _isSelectedTo, _prepare, _setup, _withinLimits; _bake = function() { var domEl; domEl = $compile(angular.element($scope.options.template))($scope); @@ -83,19 +83,45 @@ switch ($scope.options.mode) { case "multiple": return _indexOfMoment($scope.model, day, 'day') > -1; + case "range": + if ($scope.model) { + return day.isSame($scope.model.start, 'day'); + } + break; default: return $scope.model && day.isSame($scope.model, 'day'); } }; + _isSelectedTo = function(day) { + switch ($scope.options.mode) { + case "range": + if ($scope.model) { + return day.isSame($scope.model.end, 'day'); + } + break; + default: + return false; + } + }; _isInRange = function(day) { - if ($scope.options.rangeMode) { - if ($scope.options.rangeMode === "from") { - return moment.range($scope.model, $scope.before).contains(day) || day.isSame($scope.before, 'day'); - } else { - return moment.range($scope.after, $scope.model).contains(day) || day.isSame($scope.after, 'day'); - } - } else { - return false; + switch ($scope.options.mode) { + case "multiple": + if ($scope.options.rangeMode) { + if ($scope.options.rangeMode === "from") { + return moment.range($scope.model, $scope.before).contains(day) || day.isSame($scope.before, 'day'); + } else { + return moment.range($scope.after, $scope.model).contains(day) || day.isSame($scope.after, 'day'); + } + } else { + return false; + } + break; + case "range": + if ($scope.model.start) { + return $scope.model.contains(day); + } else { + return false; + } } }; _buildWeek = function(time, month) { @@ -114,6 +140,7 @@ return { date: day, selected: _isSelected(day) && withinMonth, + selectedTo: _isSelectedTo(day) && withinMonth, inRange: _isInRange(day), disabled: !(withinLimits && withinMonth && filter), marker: withinMonth ? _getMarker(day) : void 0 @@ -169,6 +196,15 @@ $scope.model = []; } break; + case "range": + if ($scope.model && $scope.model.start) { + if ($scope.model.start.isValid()) { + start = $scope.model.start; + } + } else { + $scope.model = moment.range(); + } + break; default: if ($scope.model) { start = moment($scope.model); @@ -204,7 +240,7 @@ _prepare(); }; $scope.select = function(day) { - var ix; + var endValid, ix, startValid; if (!day.disabled) { switch ($scope.options.mode) { case "multiple": @@ -215,6 +251,19 @@ $scope.model.push(moment(day.date)); } break; + case "range": + startValid = $scope.model.start.isValid(); + endValid = $scope.model.end.isValid(); + if ((startValid && endValid) || (!startValid && !endValid)) { + $scope.model = moment.range(moment(day.date), moment(null)); + } else if (startValid && !endValid) { + if (moment(day.date).isSameOrBefore($scope.model.end, 'day')) { + $scope.model.start = moment(day.date); + } else { + $scope.model.end = moment(day.date); + } + } + break; default: $scope.model = day.date; } @@ -236,6 +285,11 @@ return _prepare(); }); break; + case "range": + $scope.$watch('model', function(newVal, oldVal) { + return _prepare(); + }); + break; case "simple": $scope.$watch('model', function(newVal, oldVal) { if (!moment.isMoment(newVal)) { diff --git a/demo/index.html b/demo/index.html index 950aac6..396bb7f 100644 --- a/demo/index.html +++ b/demo/index.html @@ -55,6 +55,9 @@ $scope.dateDbB = moment().add('day', 2); $scope.optionsDbB = {}; + $scope.optionsR = {mode: "range"}; + $scope.range = moment.range(moment().subtract('day', 8), moment().subtract('day', 2)); + $scope.addMarker = function() { $scope.markers.push({day: $scope.mark, marker: 'new marker'}); } @@ -101,6 +104,10 @@

Double datepicker for data range

+
+

Single datepicker for date range

+ +
diff --git a/gulpfile.js b/gulpfile.js index f3cfbd9..b8e1687 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -15,7 +15,7 @@ var warn = function(err) { console.warn(err); }; var paths = { src: "./src/", dst: "./build/" -} +}; var onError = function (err) { gutil.beep(); @@ -24,7 +24,7 @@ var onError = function (err) { gulp.task("default", ["bower", "build"]); -gulp.task("build", ["coffee", "less"]) +gulp.task("build", ["coffee", "less"]); gulp.task("server", ["build", "watch"], function() { connect.server({ @@ -36,7 +36,7 @@ gulp.task("server", ["build", "watch"], function() { gulp.task("clean", function(){ return gulp.src(paths.dst, {read: false}) .pipe(clean()); -}) +}); gulp.task("watch", function(){ return gulp.watch(paths.src + "**/*", ["build"]); diff --git a/src/angular-mighty-datepicker.coffee b/src/angular-mighty-datepicker.coffee index 384b65d..d88b0a1 100644 --- a/src/angular-mighty-datepicker.coffee +++ b/src/angular-mighty-datepicker.coffee @@ -22,6 +22,7 @@ angular.module("mightyDatepicker").directive "mightyDatepicker", ["$compile", ($ bo-class='{ "mighty-picker-calendar__day": day, "mighty-picker-calendar__day--selected": day.selected, + "mighty-picker-calendar__day--selected-to": day.selectedTo, "mighty-picker-calendar__day--disabled": day.disabled, "mighty-picker-calendar__day--in-range": day.inRange, "mighty-picker-calendar__day--marked": day.marker @@ -95,17 +96,37 @@ angular.module("mightyDatepicker").directive "mightyDatepicker", ["$compile", ($ switch $scope.options.mode when "multiple" return _indexOfMoment($scope.model, day, 'day') > -1 + when "range" + if $scope.model + return day.isSame($scope.model.start, 'day') else return $scope.model && day.isSame($scope.model, 'day') - _isInRange = (day) -> - if $scope.options.rangeMode - if $scope.options.rangeMode == "from" - return moment.range($scope.model, $scope.before).contains(day) || day.isSame($scope.before, 'day') + _isSelectedTo = (day) -> + switch $scope.options.mode + when "range" + if $scope.model + return day.isSame($scope.model.end, 'day') else - return moment.range($scope.after, $scope.model).contains(day) || day.isSame($scope.after, 'day') - else - return false + return false + + _isInRange = (day) -> + switch $scope.options.mode + when "multiple" + if $scope.options.rangeMode + if $scope.options.rangeMode == "from" + return moment.range($scope.model, $scope.before).contains(day) || + day.isSame($scope.before, 'day') + else + return moment.range($scope.after, $scope.model).contains(day) || + day.isSame($scope.after, 'day') + else + return false + when "range" + if $scope.model.start + return $scope.model.contains(day) + else + return false _buildWeek = (time, month) -> days = [] @@ -118,6 +139,7 @@ angular.module("mightyDatepicker").directive "mightyDatepicker", ["$compile", ($ filter = $scope.options.filter(day) if $scope.options.filter date: day selected: _isSelected(day) && withinMonth + selectedTo: _isSelectedTo(day) && withinMonth inRange: _isInRange(day) disabled: !(withinLimits && withinMonth && filter) marker: _getMarker(day) if withinMonth @@ -157,6 +179,14 @@ angular.module("mightyDatepicker").directive "mightyDatepicker", ["$compile", ($ start = moment(dates.sort().slice(-1)[0]) else $scope.model = [] + + when "range" + if $scope.model && $scope.model.start + if $scope.model.start.isValid() + start = $scope.model.start + else + $scope.model = moment.range() + else start = moment($scope.model) if $scope.model @@ -196,6 +226,25 @@ angular.module("mightyDatepicker").directive "mightyDatepicker", ["$compile", ($ $scope.model.splice(ix, 1) else $scope.model.push(moment(day.date)) + + when "range" + startValid = $scope.model.start.isValid() + endValid = $scope.model.end.isValid() + + # if the start date and end date are both valid or invalid + # reset the dates. + if (startValid && endValid) || (!startValid && !endValid) + $scope.model = moment.range(moment(day.date), moment(null)) + + # if the end date is invalid + # set the end date. + else if startValid && !endValid + # push back the start date if the selected day is before + if moment(day.date).isSameOrBefore($scope.model.end, 'day') + $scope.model.start = moment(day.date) + else + $scope.model.end = moment(day.date) + else $scope.model = day.date $scope.options.callback day.date if $scope.options.callback @@ -213,6 +262,10 @@ angular.module("mightyDatepicker").directive "mightyDatepicker", ["$compile", ($ $scope.$watchCollection 'model', (newVals, oldVals) -> _prepare() + when "range" + $scope.$watch 'model', (newVal, oldVal) -> + _prepare() + when "simple" $scope.$watch 'model', (newVal, oldVal) -> newVal = moment(newVal) unless moment.isMoment(newVal) diff --git a/src/angular-mighty-datepicker.less b/src/angular-mighty-datepicker.less index 6201268..4e44138 100644 --- a/src/angular-mighty-datepicker.less +++ b/src/angular-mighty-datepicker.less @@ -33,6 +33,10 @@ color: #3b5; font-weight: bold; } +.mighty-picker-calendar__day--selected-to { + color: orange; + font-weight: bold; +} .mighty-picker__month { display: inline-block; margin: 0 6px; From af328cc6c7ed7abf57cbd2f27417734cf3f71720 Mon Sep 17 00:00:00 2001 From: spaceribs Date: Wed, 17 Feb 2016 14:35:49 -0500 Subject: [PATCH 2/4] fixing a small bug --- build/angular-mighty-datepicker.js | 2 +- src/angular-mighty-datepicker.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/angular-mighty-datepicker.js b/build/angular-mighty-datepicker.js index 1013045..cf638f2 100644 --- a/build/angular-mighty-datepicker.js +++ b/build/angular-mighty-datepicker.js @@ -257,7 +257,7 @@ if ((startValid && endValid) || (!startValid && !endValid)) { $scope.model = moment.range(moment(day.date), moment(null)); } else if (startValid && !endValid) { - if (moment(day.date).isSameOrBefore($scope.model.end, 'day')) { + if (moment(day.date).isSameOrBefore($scope.model.start, 'day')) { $scope.model.start = moment(day.date); } else { $scope.model.end = moment(day.date); diff --git a/src/angular-mighty-datepicker.coffee b/src/angular-mighty-datepicker.coffee index d88b0a1..bb5ded2 100644 --- a/src/angular-mighty-datepicker.coffee +++ b/src/angular-mighty-datepicker.coffee @@ -240,7 +240,7 @@ angular.module("mightyDatepicker").directive "mightyDatepicker", ["$compile", ($ # set the end date. else if startValid && !endValid # push back the start date if the selected day is before - if moment(day.date).isSameOrBefore($scope.model.end, 'day') + if moment(day.date).isSameOrBefore($scope.model.start, 'day') $scope.model.start = moment(day.date) else $scope.model.end = moment(day.date) From 2ecf21cadda98060f4ba030f4f1aa148e5f493c0 Mon Sep 17 00:00:00 2001 From: spaceribs Date: Thu, 18 Feb 2016 09:51:18 -0500 Subject: [PATCH 3/4] moment update for better coverage --- src/angular-mighty-datepicker.coffee | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/angular-mighty-datepicker.coffee b/src/angular-mighty-datepicker.coffee index bb5ded2..dfa0d7b 100644 --- a/src/angular-mighty-datepicker.coffee +++ b/src/angular-mighty-datepicker.coffee @@ -240,7 +240,8 @@ angular.module("mightyDatepicker").directive "mightyDatepicker", ["$compile", ($ # set the end date. else if startValid && !endValid # push back the start date if the selected day is before - if moment(day.date).isSameOrBefore($scope.model.start, 'day') + if moment(day.date).isBefore($scope.model.start, 'day') || + moment(day.date).isSame($scope.model.start, 'day') $scope.model.start = moment(day.date) else $scope.model.end = moment(day.date) From 0e0a9c5311442e9bc272ec53facba3f0eeebf2be Mon Sep 17 00:00:00 2001 From: spaceribs Date: Thu, 18 Feb 2016 09:58:27 -0500 Subject: [PATCH 4/4] building and fixing a syntax error --- build/angular-mighty-datepicker.js | 2 +- src/angular-mighty-datepicker.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/angular-mighty-datepicker.js b/build/angular-mighty-datepicker.js index cf638f2..ba6a96e 100644 --- a/build/angular-mighty-datepicker.js +++ b/build/angular-mighty-datepicker.js @@ -257,7 +257,7 @@ if ((startValid && endValid) || (!startValid && !endValid)) { $scope.model = moment.range(moment(day.date), moment(null)); } else if (startValid && !endValid) { - if (moment(day.date).isSameOrBefore($scope.model.start, 'day')) { + if (moment(day.date).isBefore($scope.model.start, 'day') || moment(day.date).isSame($scope.model.start, 'day')) { $scope.model.start = moment(day.date); } else { $scope.model.end = moment(day.date); diff --git a/src/angular-mighty-datepicker.coffee b/src/angular-mighty-datepicker.coffee index dfa0d7b..2d44c7b 100644 --- a/src/angular-mighty-datepicker.coffee +++ b/src/angular-mighty-datepicker.coffee @@ -242,7 +242,7 @@ angular.module("mightyDatepicker").directive "mightyDatepicker", ["$compile", ($ # push back the start date if the selected day is before if moment(day.date).isBefore($scope.model.start, 'day') || moment(day.date).isSame($scope.model.start, 'day') - $scope.model.start = moment(day.date) + $scope.model.start = moment(day.date) else $scope.model.end = moment(day.date)