diff --git a/LICENSE b/LICENSE
index 5a4053a..c277087 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,7 @@
MIT License
Copyright (c) 2017 Mark Chapman
+Copyright (c) 2012-2013 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +19,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
\ No newline at end of file
+THE SOFTWARE.
diff --git a/README.md b/README.md
index 2faf658..1ec537a 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# fng-bootstrap-datetime
-Plugin for forms-angular that adds datetime picker (github.com/zhaber/angular-js-bootstrap-datetimepicker) support.
+Plugin for forms-angular that adds datetime picker support.
## Usage
@@ -27,10 +27,10 @@ In your Mongoose schemas you can set up fields like this:
},
Options can be added to a fngUiBootstrapDatetimePicker object within the form object as illustrated by the examples above.
-A complete list of setting options can be found in the Settings section of [this page](https://github.com/zhaber/angular-js-bootstrap-datetimepicker). Any setting
+A complete list of setting options can be found in the Settings section below. Any setting
Date options (see [uib-datepicker](https://angular-ui.github.io/bootstrap/#!#datepicker) settings can be added as a JSON string as shown above.
-For (my) convenience, the following defaults have been changed from https://github.com/zhaber/angular-js-bootstrap-datetimepicker:
+For (my) convenience, the following defaults have been changed from the defaults shown below:
show-button-bar: false,
show-meridian: false,
@@ -40,4 +40,188 @@ For (my) convenience, the following defaults have been changed from https://gith
###Known Limitations:
Styling in (unsupported) Bootstrap 2 applications (such as the forms-angular.org website at the time of writing) has a few issues,
-including inline help placing and the width of the first columnof the dropdown when weeks are not shown.
\ No newline at end of file
+including inline help placing and the width of the first columnof the dropdown when weeks are not shown.
+
+##Readme from github.com/zhaber/angular-js-bootstrap-datetimepicker (now Angular 4+ only)
+
+The plugin is based on AngularUI [Datepicker](https://github.com/angular-ui/bootstrap/tree/master/src/datepicker) and [Timepicker](https://github.com/angular-ui/bootstrap/tree/master/src/timepicker).
+
+Demo: [Plunker](http://plnkr.co/edit/qRhNlfTWlt9wIexa3WbB?p=preview)
+
+Date is formatted using the [date filter](http://docs.angularjs.org/api/ng.filter:date) and is localized.
+
+## Install
+
+### NPM
+Run `npm install angular-ui-bootstrap-datetimepicker` to install. Use the `--save` option to add it to your package.json's dependencies.
+
+If you're using browserify, you can simply `require('angular-ui-bootstrap-datetimepicker')` to make it available in your angular project. Ensure that your angular module depends on `ui.bootstrap.datetimepicker`. You must be using the `ui.bootstrap` module as well - also availbe via npm.
+
+Also include the stylesheet `datetimepicker.css` in your html. Note that this is the same stylesheet that the package.json's `style` declaration has.
+
+### Bower
+
+Run `bower install angular-ui-bootstrap-datetimepicker --save` to persist it to `bower.json`
+
+Include the `ui.bootstrap.datetimepicker` module in your `app.js` file. You must be using the `ui.bootstrap` module as well.
+
+### NuGet
+
+See https://www.nuget.org/packages/Angular-js-bootstrap-datetimepicker/
+
+## Usage Sample
+~~~javascript
+// Disable weekend selection
+$scope.isDisabledDate = function(currentDate, mode) {
+ return mode === 'day' && (currentDate.getDay() === 0 || currentDate.getDay() === 6);
+};
+~~~
+~~~html
+
+
+~~~
+
+## Datetimepicker Settings
+
+ * `clear-text`
+ _(Default: 'Clear')_ :
+ The text to display for the clear button.
+
+ * `close-text`
+ _(Default: 'Done')_ :
+ The text to display for the close popup button.
+
+ * `current-text`
+ _(Default: 'Today')_ :
+ The text to display for the current day button.
+
+ * `datepicker-append-to-body`
+ _(Default: false)_ :
+ Append the datepicker popup element to body, rather than inserting after datepicker-popup.
+
+ * `datepicker-popup-template-url`
+ _(Default: uib/template/datepickerPopup/popup.html)_ :
+ Add the ability to override the template used on the component.
+
+ * `datepicker-template-url`
+ _(Default: uib/template/datepicker/datepicker.html)_ :
+ Add the ability to override the template used on the component (inner uib-datepicker).
+
+ * `date-disabled (date, mode)`
+ _(Default: null)_ :
+ An optional expression to disable visible options based on passing date and current mode _(day|month|year)_.
+
+ * `date-format`
+ _(Default: 'yyyy-MM-dd')_ :
+ The format for displayed dates.
+
+ * `date-ng-click`
+ _(Default: null)_ :
+ A function called when a date input is clicked.
+
+ * `date-opened`
+ _(Default: false)_ :
+ Whether or not to show the datepicker.
+
+ * `date-options` attribute.
+ _(Default: {})_ :
+ Options for datepicker in JSON format. E.g. minDate and maxDate, which define the minimum and maximum available date and time.
+
+ * `day-format`
+ _(Default: 'dd')_ :
+ Format of day in month.
+
+ * `day-header-format`
+ _(Default: 'EEE')_ :
+ Format of day in week header.
+
+ * `day-title-format`
+ _(Default: 'MMMM yyyy')_ :
+ Format of title when selecting day.
+
+ * `disabled-date`
+ _(Defaults: false)_ :
+ Whether the date input is disabled.
+
+ * `hidden-date`
+ _(Defaults: false)_ :
+ Whether a user can see the date input.
+
+ * `hidden-time`
+ _(Defaults: false)_ :
+ Whether a user can see the hours & minutes input.
+
+ * `hour-step`
+ _(Defaults: 1)_ :
+ Number of hours to increase or decrease when using a button.
+
+ * `max-time`
+ _(Defaults: ['12:59 PM'])_ :
+ Maximum time for time picker (Date).
+
+ * `meridians`
+ _(Defaults: ['AM', 'PM'])_ :
+ Meridian labels
+
+ * `min-time`
+ _(Defaults: ['0:00 AM'])_ :
+ Minumum time for time picker (Date).
+
+ * `minute-step`
+ _(Defaults: 1)_ :
+ Number of minutes to increase or decrease when using a button.
+
+ * `month-format`
+ _(Default: 'MMMM')_ :
+ Format of month in year.
+
+ * `month-title-format`
+ _(Default: 'yyyy')_ :
+ Format of title when selecting month.
+
+ * `mousewheel`
+ _(Defaults: true)_ :
+ Whether user can scroll inside the hours & minutes input to increase or decrease it's values.
+
+ * `ng-model`
+ :
+ The date and time object.
+
+ * `readonly-date`
+ _(Defaults: false)_ :
+ Whether a user can type inside the date input.
+
+ * `readonly-time`
+ _(Defaults: false)_ :
+ Whether a user can type inside the hours & minutes input.
+
+ * `required`
+ _(Defaults: false)_ :
+ Whether a non-empty value is required.
+
+ * `show-button-bar`
+ _(Defaults: true)_ :
+ Whether or not to display a button bar underneath the uib-datepicker..
+
+ * `show-meridian`
+ _(Defaults: true)_ :
+ Whether to display 12H or 24H mode.
+
+ * `show-spinners`
+ _(Defaults: true)_ :
+ Shows spinner arrows above and below the inputs.
+
+ * `timepicker-template-url`
+ _(Defaults: uib/template/timepicker/timepicker.html)_ :
+ Add the ability to override the template used on the component.
+
+ * `year-format`
+ _(Default: 'yyyy')_ :
+ Format of year in year range.
+
+ * `year-range`
+ _(Default: 20)_ :
+ Number of years displayed in year selection.
diff --git a/bower.json b/bower.json
index 35b9f95..4a1df5e 100644
--- a/bower.json
+++ b/bower.json
@@ -1,13 +1,14 @@
{
"name": "fng-bootstrap-datetime",
- "description": "datetime input plugin for forms-angular, using angular-ui-bootstrap-datetimepicker",
+ "description": "datetime input plugin for forms-angular",
"version":"0.11.0",
"main": [
"fng-bootstrap-datetime.js",
"fng-bootstrap-datetime.css"
],
"authors": [
- "Mark Chapman"
+ "Mark Chapman",
+ "Vitalii Fedorenko"
],
"license": "MIT",
"keywords": [
@@ -20,8 +21,5 @@
"bower_components",
"test",
"tests"
- ],
- "dependencies": {
- "angular-ui-bootstrap-datetimepicker":"latest"
- }
+ ]
}
diff --git a/fng-bootstrap-datetime.css b/fng-bootstrap-datetime.css
index e7b5b63..4a54b68 100644
--- a/fng-bootstrap-datetime.css
+++ b/fng-bootstrap-datetime.css
@@ -1,3 +1,18 @@
+.datetimepicker-wrapper {
+ vertical-align: middle;
+ display: inline-block;
+}
+
+.datetimepicker-wrapper > input {
+ margin-bottom: 0 !important;
+ width: 130px;
+}
+
+.datetimepicker-wrapper [ng-model=hours],
+.datetimepicker-wrapper [ng-model=minutes] {
+ width: 46px !important;
+}
+
.dtwrap {
min-width: 230px;
-}
\ No newline at end of file
+}
diff --git a/fng-bootstrap-datetime.js b/fng-bootstrap-datetime.js
index ca56fca..a1f3b5a 100644
--- a/fng-bootstrap-datetime.js
+++ b/fng-bootstrap-datetime.js
@@ -1,3 +1,348 @@
+angular.module('ui.bootstrap.datetimepicker', ["ui.bootstrap.dateparser", "ui.bootstrap.datepicker", "ui.bootstrap.timepicker"])
+ .directive('datepickerPopup', function () {
+ return {
+ restrict: 'EAC',
+ require: 'ngModel',
+ link: function (scope, element, attr, controller) {
+ //remove the default formatter from the input directive to prevent conflict
+ controller.$formatters.shift();
+ }
+ }
+ })
+ .directive('datetimepicker', [
+ function () {
+
+ function versionCheck(){
+ return (angular.version.major === 1 && (angular.version.minor > 4 || (angular.version.minor === 4 && angular.version.dot >= 4)));
+ }
+
+ if (!versionCheck()) {
+ return {
+ restrict: 'EA',
+ template: "
Angular 1.4.4 or above is required for datetimepicker to work correctly
";
+ // form is isolated so the directive is registered as one component in the parent form (not date and time)
+ var tmpl = "" + dateTmpl + timeTmpl + "";
+ return tmpl;
+ },
+ controller: ['$scope', '$attrs',
+ function ($scope, $attrs) {
+ $scope.date_change = function () {
+ // If we changed the date only, set the time (h,m) on it.
+ // This is important in case the previous date was null.
+ // This solves the issue when the user set a date and time, cleared the date, and chose another date,
+ // and then, the time was cleared too - which is unexpected
+ var time = $scope.time;
+ if ($scope.ngModel && $scope.time) { // if ngModel is null, that's because the user cleared the date field
+ $scope.ngModel.setHours(time.getHours(), time.getMinutes(), 0, 0);
+ $scope.ngModel = new Date($scope.ngModel); // By default, ngModel watches the model by reference, not value. This is important to know when binding inputs to models that are objects (e.g. Date) (from: https://docs.angularjs.org/api/ng/directive/ngModel)
+ }
+ };
+ $scope.time_change = function () {
+ if ($scope.ngModel && $scope.time) {
+ $scope.ngModel.setHours($scope.time.getHours(), $scope.time.getMinutes(), 0, 0);
+ $scope.ngModel = new Date($scope.ngModel); // By default, ngModel watches the model by reference, not value. This is important to know when binding inputs to models that are objects (e.g. Date) (from: https://docs.angularjs.org/api/ng/directive/ngModel)
+ } // else the time is invalid, keep the current Date value in datepicker
+ };
+ $scope.open = function ($event) {
+ $event.preventDefault();
+ $event.stopPropagation();
+ $scope.innerDateOpened = true;
+ };
+ $attrs.$observe('dateFormat', function(newDateFormat, oldValue) {
+ $scope.dateFormat = newDateFormat;
+ });
+ $scope.dateOptions = angular.isDefined($scope.dateOptions) ? $scope.dateOptions : {};
+ $scope.dateOptions.dateDisabled = $scope.dateDisabled;
+ }
+ ],
+ link: function (scope, element, attrs, ctrl) {
+ var updateMinTime = function() {
+ if (!scope.ngModel) {
+ return;
+ }
+ if (scope.minTime) {
+ scope.minDate = new Date(scope.ngModel.getFullYear(),
+ scope.ngModel.getMonth(),
+ scope.ngModel.getDate(),
+ scope.minTime.getHours(),
+ scope.minTime.getMinutes(),
+ 0);
+ if (scope.dateOptions.minDate && scope.dateOptions.minDate > scope.minDate) {
+ scope.minDate = scope.dateOptions.minDate;
+ }
+ } else {
+ scope.minDate = scope.dateOptions.minDate;
+ }
+ };
+ var updateMaxTime = function() {
+ if (!scope.ngModel) {
+ return;
+ }
+ if (scope.maxTime) {
+ scope.maxDate = new Date(scope.ngModel.getFullYear(),
+ scope.ngModel.getMonth(),
+ scope.ngModel.getDate(),
+ scope.maxTime.getHours(),
+ scope.maxTime.getMinutes(),
+ 0);
+ if (scope.dateOptions.maxDate && scope.dateOptions.maxDate < scope.maxDate) {
+ scope.maxDate = scope.dateOptions.maxDate;
+ }
+ } else {
+ scope.maxDate = scope.dateOptions.maxDate;
+ }
+ };
+
+ var firstTimeAssign = true;
+
+ scope.$watch(function () {
+ return scope.ngModel;
+ }, function (newTime) {
+ if (scope.ngModel && !(scope.ngModel instanceof Date)) {
+ // convert from ISO format to Date
+ scope.ngModel = new Date(scope.ngModel);
+ }
+
+ var timeElement = element[0].querySelector('[name=timepicker]');
+
+ // if a time element is focused, updating its model will cause hours/minutes to be formatted by padding with leading zeros
+ if (timeElement && !timeElement.contains(document.activeElement)) {
+
+ if (newTime === null || newTime === '') { // if the newTime is not defined
+ if (firstTimeAssign) { // if it's the first time we assign the time value
+ // create a new default time where the hours, minutes, seconds and milliseconds are set to 0.
+ newTime = new Date();
+ newTime.setHours(0, 0, 0, 0);
+ } else { // clear the time
+ scope.time = null;
+ if (scope.ngChange) scope.$eval(scope.ngChange);
+ return;
+ }
+ }
+ // Update timepicker (watch on ng-model in timepicker does not use object equality),
+ // also if the ngModel was not a Date, convert it to date
+ newTime = new Date(newTime);
+
+ if (isNaN(newTime.getTime()) === false) {
+ scope.time = newTime; // change the time in timepicker
+ if (firstTimeAssign) {
+ firstTimeAssign = false;
+ }
+ }
+ }
+ updateMinTime();
+ updateMaxTime();
+ if (scope.ngChange) {
+ scope.$eval(scope.ngChange);
+ }
+ }, true);
+
+ scope.$watch(function () {
+ return scope.datetimepickerForm && Object.keys(scope.datetimepickerForm.$error);
+ }, function (errors) {
+ if (angular.isUndefined(errors)) {
+ return;
+ }
+ Object.keys(ctrl.$error).forEach(function (error) {
+ ctrl.$setValidity(error, true);
+ });
+ errors.forEach(function (error) {
+ ctrl.$setValidity(error, false);
+ });
+ }, true);
+
+ scope.$watch(function () {
+ return scope.datetimepickerForm && (scope.datetimepickerForm.timepicker.$touched || scope.datetimepickerForm.datepicker.$touched);
+ }, function (touched) {
+ if (touched) {
+ ctrl.$setTouched();
+ }
+ });
+
+ scope.$watch(function () {
+ return scope.datetimepickerForm && scope.datetimepickerForm.$dirty;
+ }, function (dirty) {
+ if (dirty) {
+ ctrl.$setDirty();
+ }
+ });
+
+ scope.$watch('dateOpened', function (value) {
+ scope.innerDateOpened = value;
+ });
+ scope.$watch('innerDateOpened', function (value) {
+ if (angular.isDefined(scope.dateOpened)) {
+ scope.dateOpened = value;
+ }
+ });
+ scope.$watch('dateOptions.minDate', function (value) {
+ updateMinTime();
+ });
+ scope.$watch('timeMin', function (value) {
+ updateMinTime();
+ });
+ scope.$watch('dateOptions.maxDate', function (value) {
+ updateMaxTime();
+ });
+ scope.$watch('timeMax', function (value) {
+ updateMaxTime();
+ });
+ }
+ }
+ }
+ ]).directive('isolateForm', [function () {
+ return {
+ restrict: 'A',
+ require: '?form',
+ link: function (scope, element, attrs, formController) {
+ if (!formController) {
+ return;
+ }
+
+ // Remove this form from parent controller
+ formController.$$parentForm.$removeControl(formController)
+ if (!formController.$$parentForm) {
+ return;
+ }
+ var _handler = formController.$setValidity;
+ formController.$setValidity = function (validationErrorKey, isValid, cntrl) {
+ _handler.call(formController, validationErrorKey, isValid, cntrl);
+ formController.$$parentForm.$setValidity(validationErrorKey, true, this);
+ }
+ }
+ };
+}]);
+
(function () {
'use strict';
var uiBootstrapDateModule = angular.module('fng.uiBootstrapDateTime', ['ui.bootstrap']);
@@ -20,7 +365,7 @@
'date-format': 'dd/MM/yyyy'
};
- // // Set form to dirty when required. Works OK with existing records - hopefully new records will have other field types
+ // Set form to dirty when required. Works OK with existing records - hopefully new records will have other field types
var watchField = attrs.model + '.' + attrs.fngFldName;
var formName = attrs.fngOptName;
scope.$watch(watchField, function (newVal, oldVal) {
@@ -57,4 +402,4 @@
};
}]
)
-})();
\ No newline at end of file
+})();
diff --git a/package.json b/package.json
index f76d7df..e3b5ae1 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "fng-bootstrap-datetime",
"version": "0.11.0",
- "description": "datetime input plugin for forms-angular, using angular-ui-bootstrap-datetimepicker",
+ "description": "datetime input plugin for forms-angular",
"main": "fng-bootstrap-datetime.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
@@ -9,6 +9,9 @@
"keywords": [
"forms-angular"
],
- "author": "Mark Chapman",
+ "authors": [
+ "Mark Chapman",
+ "Vitalii Fedorenko"
+ ],
"license": "MIT"
}