diff options
| author | pliablepixels <pliablepixels@gmail.com> | 2016-01-26 17:29:16 -0500 |
|---|---|---|
| committer | pliablepixels <pliablepixels@gmail.com> | 2016-01-26 17:29:16 -0500 |
| commit | ac521c0b5cd3420a0c45f3e0946b00565992a98b (patch) | |
| tree | b13a84baa6550b60d323e803fff075987c42fa73 /www/lib/ion-datetime-picker/src | |
| parent | 9bc9950984b940449c16b557b41672e65e17b4d1 (diff) | |
#154 - closed data leak holes, added date-time picker for a neater interface
Former-commit-id: 401a743f555a5dd8021e6b8af790cd38808fd1ac
Diffstat (limited to 'www/lib/ion-datetime-picker/src')
| -rw-r--r-- | www/lib/ion-datetime-picker/src/picker-i18n.js | 9 | ||||
| -rw-r--r-- | www/lib/ion-datetime-picker/src/picker-popup.html | 81 | ||||
| -rw-r--r-- | www/lib/ion-datetime-picker/src/picker.js | 184 | ||||
| -rw-r--r-- | www/lib/ion-datetime-picker/src/picker.scss | 133 |
4 files changed, 407 insertions, 0 deletions
diff --git a/www/lib/ion-datetime-picker/src/picker-i18n.js b/www/lib/ion-datetime-picker/src/picker-i18n.js new file mode 100644 index 00000000..e3de39e3 --- /dev/null +++ b/www/lib/ion-datetime-picker/src/picker-i18n.js @@ -0,0 +1,9 @@ +angular.module("ion-datetime-picker") + .factory("$ionicPickerI18n", function($window) { + return { + ok: "OK", + cancel: "Cancel", + weekdays: $window.moment ? $window.moment.weekdaysMin() : ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"], + months: $window.moment ? $window.moment.months() : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] + }; + });
\ No newline at end of file diff --git a/www/lib/ion-datetime-picker/src/picker-popup.html b/www/lib/ion-datetime-picker/src/picker-popup.html new file mode 100644 index 00000000..df1e3646 --- /dev/null +++ b/www/lib/ion-datetime-picker/src/picker-popup.html @@ -0,0 +1,81 @@ +<div class="ion-datetime-picker"> + <div ng-if-start="dateEnabled" class="row month-year"> + <div class="col col-10 left-arrow"> + <button class="button button-small button-positive button-clear icon ion-chevron-left" ng-click="changeBy(-1, 'month')"></button> + </div> + <label class="col col-50 month-input"> + <div class="item item-input item-select"> + <select ng-model="bind.month" ng-options="index as month for (index, month) in i18n.months" ng-change="change('month')"></select> + </div> + </label> + <label class="col year-input"> + <div class="item item-input"> + <input type="number" ng-model="bind.year" min="1900" max="2999" ng-change="change('year')" ng-blur="changed()" required> + </div> + </label> + <div class="col col-10 right-arrow"> + <button class="button button-small button-positive button-clear icon ion-chevron-right" ng-click="changeBy(+1, 'month')"></button> + </div> + </div> + + <div class="row calendar weekdays"> + <div class="col" ng-repeat="weekday in weekdays"> + <div class="weekday">{{i18n.weekdays[weekday]}}</div> + </div> + </div> + <div ng-if-end class="row calendar days" ng-repeat="y in rows"> + <div class="col" ng-repeat="x in cols"> + <div ng-show="(cellDay = y * 7 + x - firstDay) > 0 && cellDay <= daysInMonth" ng-click="changeDay(cellDay)" class="day" ng-class="{'selected': cellDay === day, 'today': cellDay === today.day && month === today.month && year === today.year}">{{cellDay}}</div> + </div> + </div> + + <div ng-if-start="timeEnabled" class="row time-buttons"> + <div class="col"></div> + <div class="col-20"><button class="button button-positive button-clear icon ion-chevron-up" ng-click="changeBy(+1, 'hour')"></button></div> + <div class="col"></div> + <div class="col-20"><button class="button button-positive button-clear icon ion-chevron-up" ng-click="changeBy(+1, 'minute')"></button></div> + <div ng-if-start="secondsEnabled" class="col"></div> + <div ng-if-end class="col-20"><button class="button button-positive button-clear icon ion-chevron-up" ng-click="changeBy(+1, 'second')"></button></div> + <div ng-if-start="meridiemEnabled" class="col"></div> + <div ng-if-end class="col-20"><button class="button button-positive button-clear icon ion-chevron-up" ng-click="changeBy(+12, 'hour')"></button></div> + <div class="col"></div> + </div> + <div class="row time"> + <div class="col"></div> + <label class="col col-20"> + <div class="item item-input"> + <input type="text" ng-model="bind.hour" pattern="0?([01]?[0-9]|2[0-3])" ng-change="change('hour')" ng-blur="changed()" required> + </div> + </label> + <div class="col colon">:</div> + <label class="col col-20"> + <div class="item item-input"> + <input type="text" ng-model="bind.minute" pattern="0?[0-5]?[0-9]" ng-change="change('minute')" ng-blur="changed()" required> + </div> + </label> + <div ng-if-start="secondsEnabled" class="col colon">:</div> + <label ng-if-end class="col col-20"> + <div class="item item-input"> + <input type="text" ng-model="bind.second" pattern="0?[0-5]?[0-9]" ng-change="change('second')" ng-blur="changed()" required> + </div> + </label> + <div ng-if-start="meridiemEnabled" class="col"></div> + <label ng-if-end class="col col-20"> + <div class="item item-input"> + <input type="text" ng-model="bind.meridiem" pattern="[aApP][mM]" ng-change="change('meridiem')" ng-blur="changed()" required> + </div> + </label> + <div class="col"></div> + </div> + <div ng-if-end class="row time-buttons"> + <div class="col"></div> + <div class="col-20"><button class="button button-positive button-clear icon ion-chevron-down" ng-click="changeBy(-1, 'hour')"></button></div> + <div class="col"></div> + <div class="col-20"><button class="button button-positive button-clear icon ion-chevron-down" ng-click="changeBy(-1, 'minute')"></button></div> + <div ng-if-start="secondsEnabled" class="col"></div> + <div ng-if-end class="col-20"><button class="button button-positive button-clear icon ion-chevron-down" ng-click="changeBy(-1, 'second')"></button></div> + <div ng-if-start="meridiemEnabled" class="col"></div> + <div ng-if-end class="col-20"><button class="button button-positive button-clear icon ion-chevron-down" ng-click="changeBy(-12, 'hour')"></button></div> + <div class="col"></div> + </div> +</div>
\ No newline at end of file diff --git a/www/lib/ion-datetime-picker/src/picker.js b/www/lib/ion-datetime-picker/src/picker.js new file mode 100644 index 00000000..62c941ce --- /dev/null +++ b/www/lib/ion-datetime-picker/src/picker.js @@ -0,0 +1,184 @@ +angular.module("ion-datetime-picker", ["ionic"]) + .directive("ionDatetimePicker", function() { + return { + restrict: "AE", + require: "ngModel", + scope: { + modelDate: "=ngModel", + title: "=", + subTitle: "=", + buttonOk: "=", + buttonCancel: "=" + }, + controller: function($scope, $ionicPopup, $ionicPickerI18n, $timeout) { + $scope.i18n = $ionicPickerI18n; + $scope.bind = {}; + + $scope.rows = [0, 1, 2, 3, 4, 5]; + $scope.cols = [1, 2, 3, 4, 5, 6, 7]; + $scope.weekdays = [0, 1, 2, 3, 4, 5, 6]; + + $scope.showPopup = function() { + $ionicPopup.show({ + templateUrl: "picker-popup.html", + title: $scope.title || ("Pick " + ($scope.dateEnabled ? "a date" : "") + ($scope.dateEnabled && $scope.timeEnabled ? " and " : "") + ($scope.timeEnabled ? "a time" : "")), + subTitle: $scope.subTitle || "", + scope: $scope, + buttons: [ + { + text: $scope.buttonOk || $scope.i18n.ok, + type: "button-positive", + onTap: function() { + $scope.commit(); + } + }, { + text: $scope.buttonCancel || $scope.i18n.cancel, + type: "button-stable", + onTap: function() { + $timeout(function() { + $scope.processModel(); + }, 200); + } + } + ] + }); + }; + + $scope.prepare = function() { + if ($scope.mondayFirst) { + $scope.weekdays.push($scope.weekdays.shift()); + } + }; + + $scope.processModel = function() { + var date = $scope.modelDate instanceof Date ? $scope.modelDate : new Date(); + $scope.year = $scope.dateEnabled ? date.getFullYear() : 0; + $scope.month = $scope.dateEnabled ? date.getMonth() : 0; + $scope.day = $scope.dateEnabled ? date.getDate() : 0; + $scope.hour = $scope.timeEnabled ? date.getHours() : 0; + $scope.minute = $scope.timeEnabled ? date.getMinutes() : 0; + $scope.second = $scope.secondsEnabled ? date.getSeconds() : 0; + + changeViewData(); + }; + + var changeViewData = function() { + var date = new Date($scope.year, $scope.month, $scope.day, $scope.hour, $scope.minute, $scope.second); + + if ($scope.dateEnabled) { + $scope.year = date.getFullYear(); + $scope.month = date.getMonth(); + $scope.day = date.getDate(); + + $scope.bind.year = $scope.year; + $scope.bind.month = $scope.month.toString(); + + $scope.firstDay = new Date($scope.year, $scope.month, 1).getDay(); + if ($scope.mondayFirst) { + $scope.firstDay = ($scope.firstDay || 7) - 1; + } + $scope.daysInMonth = new Date($scope.year, $scope.month + 1, 0).getDate(); + if ($scope.day > $scope.daysInMonth) { + $scope.day = $scope.daysInMonth; + } + } + + if ($scope.timeEnabled) { + $scope.hour = date.getHours(); + $scope.minute = date.getMinutes(); + $scope.second = date.getSeconds(); + $scope.meridiem = $scope.hour < 12 ? "AM" : "PM"; + + $scope.bind.hour = $scope.meridiemEnabled ? ($scope.hour % 12 || 12).toString() : $scope.hour.toString(); + $scope.bind.minute = ($scope.minute < 10 ? "0" : "") + $scope.minute.toString(); + $scope.bind.second = ($scope.second < 10 ? "0" : "") + $scope.second.toString(); + $scope.bind.meridiem = $scope.meridiem; + } + }; + + $scope.changeBy = function(value, unit) { + if (+value) { + // DST workaround + if ((unit === "hour" || unit === "minute") && value === -1) { + var date = new Date($scope.year, $scope.month, $scope.day, $scope.hour - 1, $scope.minute); + if (($scope.minute === 0 || unit === "hour") && $scope.hour === date.getHours()) { + $scope.hour--; + } + } + $scope[unit] += +value; + changeViewData(); + } + }; + $scope.change = function(unit) { + var value = $scope.bind[unit]; + if (value && unit === "meridiem") { + value = value.toUpperCase(); + if (value === "AM" && $scope.meridiem === "PM") { + $scope.hour -= 12; + } else if (value === "PM" && $scope.meridiem === "AM") { + $scope.hour += 12; + } + changeViewData(); + } else if (+value || value === "0") { + $scope[unit] = +value; + changeViewData(); + } + }; + $scope.changeDay = function(day) { + $scope.day = day; + changeViewData(); + }; + $scope.changed = function() { + changeViewData(); + }; + + if ($scope.dateEnabled) { + $scope.$watch(function() { + return new Date().getDate(); + }, function() { + var today = new Date(); + $scope.today = { + day: today.getDate(), + month: today.getMonth(), + year: today.getFullYear() + }; + }); +// $scope.goToToday = function() { +// $scope.year = $scope.today.year; +// $scope.month = $scope.today.month; +// $scope.day = $scope.today.day; +// +// changeViewData(); +// }; + } + }, + link: function($scope, $element, $attrs, ngModelCtrl) { + $scope.dateEnabled = "date" in $attrs && $attrs.date !== "false"; + $scope.timeEnabled = "time" in $attrs && $attrs.time !== "false"; + if ($scope.dateEnabled === false && $scope.timeEnabled === false) { + $scope.dateEnabled = $scope.timeEnabled = true; + } + + $scope.mondayFirst = "mondayFirst" in $attrs && $attrs.mondayFirst !== "false"; + $scope.secondsEnabled = $scope.timeEnabled && "seconds" in $attrs && $attrs.seconds !== "false"; + $scope.meridiemEnabled = $scope.timeEnabled && "amPm" in $attrs && $attrs.amPm !== "false"; + + + + + $scope.prepare(); + + ngModelCtrl.$render = function() { + $scope.modelDate = ngModelCtrl.$viewValue; + $scope.processModel(); + }; + + $scope.commit = function() { + $scope.modelDate = new Date($scope.year, $scope.month, $scope.day, $scope.hour, $scope.minute, $scope.second); + ngModelCtrl.$setViewValue($scope.modelDate); + }; + + $element.on("click", $scope.showPopup); + } + }; + });
\ No newline at end of file diff --git a/www/lib/ion-datetime-picker/src/picker.scss b/www/lib/ion-datetime-picker/src/picker.scss new file mode 100644 index 00000000..da060e66 --- /dev/null +++ b/www/lib/ion-datetime-picker/src/picker.scss @@ -0,0 +1,133 @@ +.ion-datetime-picker { + .calendar { + text-align: center; + font-size: 12px; + + .col { + padding: 0; + } + .day, .weekday { + padding: 5px; + } + .day { + &:hover, &.activated, &.today:hover, &.today.activated { + background-color: #bdf; + color: black; + cursor: pointer; + } + &.today { + background-color: #e4e4e4; + } + &.selected, &.selected:hover, &.selected.activated { + background-color: #387ef5; + color: white; + } + } + .weekday { + font-weight: bold; + } + } + .month-year { + padding: 0; + text-align: center; + + select { + width: 100%; + } + .button { + padding: 0; + width: 100%; + height: 25px; + min-width: 0; + min-height: 0; + } + .item-input { + height: 25px; + padding: 0; + margin: 0; + + &.item-select:after { + right: 5px; + } + input, select { + font-size: 12px; + width: 100%; + height: 100%; + max-width: none; + line-height: 20px; + } + select { + left: 0; + padding: 0 15px 0 1px; + direction: ltr; + } + input { + text-align: center; + padding: 0 5px; + + &.ng-invalid { + background-color: #ffe4ea; + } + &::-webkit-outer-spin-button, &::-webkit-inner-spin-button { + display: none; + } + } + } + } + + .time-buttons { + .col { + padding: 0; + } + .button { + padding: 0; + width: 100%; + height: 36px; + min-width: 0; + min-height: 0; + } + .button:before { + line-height: 35px; + } + &:first-child { + padding-top: 0; + } + &:last-child { + padding-bottom: 0; + } + } + + .time { + .col { + padding: 0; + } + .colon { + color: #999; + font-size: 16px; + padding: 0; + text-align: center; + line-height: 32px; + } + .item-input { + height: 35px; + padding: 0; + margin: 0; + + input { + font-size: 16px; + width: 100%; + height: 100%; + max-width: none; + text-align: center; + padding: 0 5px; + + &.ng-invalid { + background-color: #ffe4ea; + } + &::-webkit-outer-spin-button, &::-webkit-inner-spin-button { + display: none; + } + } + } + } +}
\ No newline at end of file |
