The angular datepicker totally mis-behavior as expectation - javascript

I ran into a deadly chaos on datepicker issues.
Who can solve my problem I can give 100 point as a return.
When I click the calendar on 2016-08-23 it will show me the 2016-08-22 as the date value.
Furthermore, the date value in angular model is also not correct.
I want to make the output can be consistent.
To reproduce the buggy issue, change your timezone between LA and TOKYO
DEMO site: https://test.jiyubi.com/tour_package/home
controller js
app.controller('tourPackageStartDatePickerCtrl',
function ($scope) {
$scope.initStartDate = function () {
$scope.startDate = $scope.startDate || null;
};
$scope.initStartDate();
$scope.dateOptions = {
baseDate: $scope.startDate,
minDate: $scope.startDate || moment.utc().toDate(),
};
$scope.openStartDateClick = function () {
$scope.startDatePopup.opened = true;
};
});
app.controller('tourPackageEndDatePickerCtrl',
function ($scope, $rootScope) {
$scope.clear = function () {
$scope.endDate = null;
};
$scope.endDateOptions = {
dateDisabled: disabledDays,
baseDate: new Date(),
};
$scope.openEndDateClick = function () {
$scope.endDatePopup.opened = true;
};
$scope.$watch("endDate", function (new_val, old_val) {
if (new_val && moment(new_val).isValid()) {
setTravelDateRange($scope.startDate, $scope.endDate);
}
}, true)
function setTravelDateRange(startDate, endDate) {
var start_date = moment_with_TAIPEI_TZ(startDate).format("YYYY/MM/DD");
var end_date = moment_with_TAIPEI_TZ(endDate).format("YYYY/MM/DD");
moment(startDate.toDateString()).tz("Asia/Taipei").format("YYYY/MM/DD");
$scope.q_param.startDate = start_date;
$scope.q_param.date_range = start_date + "-" + end_date;
}
});
helper.js
function moment_with_TAIPEI_TZ(time){
return moment(time).tz("Asia/Taipei");
}
function MOMENT_WITH_LOCAL(time){
return moment(time).local();
}
function discard_timezone(value) {
return moment.utc(value).format(DEFAULT_MOMENT_TIME_FORMAT);
}
function getYYYYMMDD(value) {
return moment.utc(value).format("YYYY/MM/DD");
}
function date_without_timezone(value) {
return moment.utc(value).toDate();
}

It's may be because of a timezone issue.
Could you please try to convert to date without considering the timezone?
this.convertToDateWithoutTimezone = function(date) {
if (date.toString().match(/(\d\d\d\d)-(\d\d)-(\d\d)/)) {
var year = $filter('date')(date.slice(0, 10), 'yyyy'),
month = $filter('date')(date.slice(0, 10), 'MM'),
day = $filter('date')(date.slice(0, 10), 'dd');
return new Date(year, month - 1, day);
} else {
return new Date(date);
}
};

Related

JavaScript - prototype not returning functions - this.registerSelectors() is not a function - no Constructor

In our VS solution project, there are about 50 different JS files. What I am doing is moving the code out of these files (Require.js was used in these separated files) and combining all the code into one larger single JS file. Reason for this is to reduce the requests from the website.
Nonetheless, I am receiving 1 of 2 errors, depending on if I wrap the JS functions/prototypes w/ a self-containing function.
The code uses jQuery and jQuery.UI
First error (if wrapped) is FormBuilderDatePicker is not a constructor
Second error (if not wrapped) is this.registerSelectors is not a function
Calling JS code:
var quoteModuleObjArr = [
{ formId: "quote-module-form-moving", className: '.zipcode-moving', moveType: 'moving' },
{ formId: "quote-module-form-storage", className: '.zipcode-storage', moveType: 'storage' },
{ formId: "quote-module-form-moving-storage", className: '.zipcode-moving-storage', moveType: 'moving-storage' }
];
for (var i = 0; i < quoteModuleObjArr.length; i++) {
var formBuilder = null;
formBuilder = new FormBuilderDatePicker({
datepicker: '#' + quoteModuleObjArr[i].formId + ' input.isDatePicker',
formId: '#' + quoteModuleObjArr[i].formId
});
}
FormBuilderDatePicker function/prototype (wrapped):
var FormBuilderDatePicker = (function () { // remove for the 2nd error (unwrapped)
function FormBuilderDatePicker(options) {
this.options = options;
this.options = $.extend(true, {}, this.defaults, this.options);
this.registerSelectors();
this.delegateEvents()
};
FormBuilderDatePicker.prototype.defaults = {
datepicker: ".hasDatePicker",
disabledDays: [],
datepickerOptions: {
minDate: 0,
maxDate: "+12M"
},
formId: ''
};
FormBuilderDatePicker.prototype.registerSelectors = function () {
this.options.$datepicker = $(this.options.datepicker);
};
FormBuilderDatePicker.prototype.delegateEvents = function () {
var _self = this;
this.options.$datepicker.on("error", function () {
var selectedDate = _self.options.$datepicker.val();
_self.options.disabledDays.push(selectedDate)
});
this.options.$datepicker.on("change", function () {
$(this).valid()
});
this.options.datepickerOptions.beforeShowDay = function (date) {
var today = new Date;
var todayDate = $.datepicker.formatDate("mm/dd/yy", today);
var selectedDate = $.datepicker.formatDate("mm/dd/yy", date);
var notToday = todayDate != selectedDate;
var isDisabledDay = $.inArray($.datepicker.formatDate("m/d/yy", date), _self.options.disabledDays) == -1;
var result = notToday && isDisabledDay;
if (notToday == false) {
setTimeout(function () {
$(".ui-datepicker-today").removeClass("ui-state-disabled");
}, 0);
return [result, "ui-datepicker-current-day"];
}
return [result];
};
this.options.datepickerOptions.onChangeMonthYear = function (year, month, datepicker) {
}
this.options.$datepicker.datepicker(this.options.datepickerOptions);
};
return FormBuilderDatePicker; // remove for the 2nd error (unwrapped)
})(); // remove for the 2nd error (unwrapped)
I have also tried creating an init function, that calls FormBuilderDatePicker.registerSelectors() and FormBuilderDatePicker.delegateEvents(), and removed the last (2) lines within the constructor, but I get the same error, that registerSelectors() is not a function (same w/ delagateEvents().
I've also read that for prototypes to have the ability to be called, they need a return within the function. Hence, during testing, I added a return true; to the delegateEvents and registerSelectors functions, but this did not work either.
All code above is inside a $(function() {});
Updated Code/Solution:
setupFormBuilderDatePicker();
setupQuoteModuleDatePicker();
// ***********************************************
// Quote Module Date Picker
// ***********************************************
var FormBuilderDatePicker;
function setupFormBuilderDatePicker() {
FormBuilderDatePicker = (function () {
function FormBuilderDatePicker(options) {
this.options = options;
this.options = $.extend(true, {}, this.defaults, this.options);
this.registerSelectors();
this.delegateEvents()
};
FormBuilderDatePicker.prototype.defaults = {
datepicker: ".hasDatePicker",
disabledDays: [],
datepickerOptions: {
minDate: 0,
maxDate: "+12M"
},
formId: ''
};
FormBuilderDatePicker.prototype.registerSelectors = function () {
this.options.$datepicker = $(this.options.datepicker);
};
FormBuilderDatePicker.prototype.delegateEvents = function () {
var _self = this;
this.options.$datepicker.on("error", function () {
var selectedDate = _self.options.$datepicker.val();
_self.options.disabledDays.push(selectedDate)
});
this.options.$datepicker.on("change", function () {
$(this).valid()
});
this.options.datepickerOptions.beforeShowDay = function (date) {
var today = new Date;
var todayDate = $.datepicker.formatDate("mm/dd/yy", today);
var selectedDate = $.datepicker.formatDate("mm/dd/yy", date);
var notToday = todayDate != selectedDate;
var isDisabledDay = $.inArray($.datepicker.formatDate("m/d/yy", date), _self.options.disabledDays) == -1;
var result = notToday && isDisabledDay;
if (notToday == false) {
setTimeout(function () {
$(".ui-datepicker-today").removeClass("ui-state-disabled");
}, 0);
return [result, "ui-datepicker-current-day"];
}
return [result];
};
this.options.datepickerOptions.onChangeMonthYear = function (year, month, datepicker) {
}
this.options.$datepicker.datepicker(this.options.datepickerOptions);
};
return FormBuilderDatePicker;
})();
}
function setupQuoteModuleDatePicker() {
var quoteModuleObjArr = [
{ formId: "quote-module-form-moving", className: '.zipcode-moving', moveType: 'moving' },
{ formId: "quote-module-form-storage", className: '.zipcode-storage', moveType: 'storage' },
{ formId: "quote-module-form-moving-storage", className: '.zipcode-moving-storage', moveType: 'moving-storage' }
];
for (var i = 0; i < quoteModuleObjArr.length; i++) {
var formBuilder = null;
formBuilder = new FormBuilderDatePicker({
datepicker: '#' + quoteModuleObjArr[i].formId + ' input.isDatePicker',
formId: '#' + quoteModuleObjArr[i].formId
});
greyOutFacilityClosedDates(quoteModuleObjArr[i].formId, quoteModuleObjArr[i].className, formBuilder, quoteModuleObjArr[i].moveType);
//return formBuilder;
}
}
Just for testing purposes the OP's above posted code was taken as is ... results/conclusion ...
FormBuilderDatePicker exists as constructor function.
registerSelectors exists as prototypal method.
There was another error within the code of the prototypal delegateEvents methods though ... this.options.$datepicker.datepicker ... of cause is not provided with the current environment (settings).
The OP's script got sanitized and (re)formatted into the next provided example code in order to provide proof that the OP's code actually does work. Thus there must be some other reasons for the OP's script failures.
const dp = new FormBuilderDatePicker;
console.log({ registerSelectors: dp.registerSelectors });
console.log({ dp });
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var FormBuilderDatePicker = (function () {
function FormBuilderDatePicker(options) {
this.options = options;
this.options = $.extend(true, {}, this.defaults, this.options);
this.registerSelectors();
this.delegateEvents();
};
FormBuilderDatePicker.prototype.defaults = {
datepicker: ".hasDatePicker",
disabledDays: [],
datepickerOptions: {
minDate: 0,
maxDate: "+12M",
},
formId: '',
};
FormBuilderDatePicker.prototype.registerSelectors = function () {
this.options.$datepicker = $(this.options.datepicker);
};
FormBuilderDatePicker.prototype.delegateEvents = function () {
var _self = this;
this.options.$datepicker.on("error", function () {
var selectedDate = _self.options.$datepicker.val();
_self.options.disabledDays.push(selectedDate);
});
this.options.$datepicker.on("change", function () {
$(this).valid();
});
this.options.datepickerOptions.beforeShowDay = function (date) {
var today = new Date;
var todayDate = $.datepicker.formatDate("mm/dd/yy", today);
var selectedDate = $.datepicker.formatDate("mm/dd/yy", date);
var notToday = todayDate != selectedDate;
var isDisabledDay = $.inArray($.datepicker.formatDate("m/d/yy", date), _self.options.disabledDays) == -1;
var result = notToday && isDisabledDay;
if (notToday == false) {
setTimeout(function () {
$(".ui-datepicker-today").removeClass("ui-state-disabled");
}, 0);
return [result, "ui-datepicker-current-day"];
}
return [result];
};
this.options.datepickerOptions.onChangeMonthYear = function (year, month, datepicker) {
};
// this.options.$datepicker.datepicker(this.options.datepickerOptions);
};
return FormBuilderDatePicker;
}());
</script>

Custom datepicker on cell edit with ag-grid

I am trying to implement a date picker on cell edit. i have tried the below example
https://www.ag-grid.com/javascript-grid-cell-editing/#example-datepicker-cell-editing
This example used jquery-ui datepicker
function getDatePicker() {
function Datepicker() {}
Datepicker.prototype.init = function(params) {
this.eInput = document.createElement("input");
this.eInput.value = params.value;
$(this.eInput).datepicker({ dateFormat: "dd/mm/yy" });
};
Datepicker.prototype.getGui = function() {
return this.eInput;
};
Datepicker.prototype.afterGuiAttached = function() {
this.eInput.focus();
this.eInput.select();
};
Datepicker.prototype.getValue = function() {
return this.eInput.value;
};
Datepicker.prototype.destroy = function() {};
Datepicker.prototype.isPopup = function() {
return false;
};
return Datepicker;
}
This line
$(this.eInput).datepicker({ dateFormat: "dd/mm/yy" });
is used to add jquery-ui datepicker
How can i have a custom DatePicker react component that i want to include instead of jquery-ui datepicker ?
You need to implement interface ICellEditorComp {...} a Doc about custom editors is here https://www.ag-grid.com/javascript-grid-cell-editor/
Sample code from https://www.ag-grid.com/javascript-grid-cell-editing/#example-datepicker-cell-editing is written in a way it supports Jquery UI Datepicker in react project.
I have a suggested solution that i have tried with TextField Material UI and Material UI Native DatePicker.
Kindly check below code it worked well for me.
const getDatePicker = () => {
function Datepicker() {}
Datepicker.prototype.init = function(params) {
const fillZeros = (a) => {
return (Number(a) < 10) ? '0' + a : a;
}
const getFormatedDate = (dateString ) => {
const dateParse = new Date(dateString.split('/')[1]+'-' + dateString.split('/')[0]+'-'+dateString.split('/')[2]);
const dd = dateParse.getDate();
const mm = dateParse.getMonth() + 1; //January is 0!
const yyyy = dateParse.getFullYear();
console.log(dateString, yyyy + '-' + fillZeros(mm) + '-' + fillZeros(dd));
return yyyy + '-' + fillZeros(mm) + '-' + fillZeros(dd);
}
this.textInput = React.createRef();
const eInput = React.createElement(TextField, {
type: "date",
defaultValue: getFormatedDate(params.value),
ref: this.textInput
});
this.div = document.createElement('div');
this.div.className = "ag-cell-parent-append";
ReactDOM.render(eInput, this.div);
};
Datepicker.prototype.getGui = function() {
return this.div;
};
Datepicker.prototype.afterGuiAttached = function() {
this.textInput.current.focus();
};
Datepicker.prototype.getValue = function() {
return this.textInput.current.querySelector('input').value;
};
Datepicker.prototype.destroy = function() {};
Datepicker.prototype.isPopup = function() {
return false;
};
return Datepicker;
}
Full working example is in stackblitz

Angularjs input string to time format

I am new to angular. I am working in uib time picker, it doesn't accept the string time.
For example, I have time from json like "06:00". I need 24hrs and 12hrs format also. The problem is I am creating the directive for display time in ng-model, and I have a text input also. Suppose if I enter the value in input text, example 1111, it is needed to be formatted to 11:11
Some other examples: 183 - 18:03 , 18349 - 18:34:09 like this.
Please some one help me to solve this problem.
dateTimeMask.directive('timeMask', function($filter) {
return {
restrict: 'A',
priority: 1,
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
var timeFormat;
function formatter(value) {
var formattedValueLength = timeFormat.length;
var unformattedValueLength = timeFormat.replace(':', '').length;
var timeMask = new String(timeFormat);
if (ngModel.$isEmpty(value)) {
return value;
}
if (!value) {
ngModel.$setValidity('time', true);
return null;
} else if (angular.isDate(value) && !isNaN(value)) {
ngModel.$setValidity('time', true);
return value;
}
else if (angular.isString(value)) {
var timeRegex = /^(0?[0-9]|1[0-2]):[0-5][0-9] ?[a|p]m$/i;
if (!scope.showMeridian) {
timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/;
}
if (!timeRegex.test(value)) {
ngModel.$setValidity('time', false);
return undefined;
}
else {
ngModel.$setValidity('time', true);
var date = new Date();
var sp = value.split(":");
var apm = sp[1].match(/[a|p]m/i);
if (apm) {
sp[1] = sp[1].replace(/[a|p]m/i, '');
if (apm[0].toLowerCase() == 'pm') {
sp[0] = sp[0] + 12;
}
}
date.setHours(sp[0], sp[1]);
return date;
}
}
else {
ngModel.$setValidity('time', false);
return undefined;
}
}
var showTime = function(data) {
timeFormat = (!scope.showMeridian) ? "HH:mm" : "hh:mm a";
return $filter('date')(formatter(data), timeFormat);
};
scope.$watch('showMeridian', function(value) {
var myTime = ngModel.$modelValue;
if (myTime) {
element.val(showTime(myTime));
}
});
ngModel.$formatters.push(function (value) {
timeFormat = (!scope.showMeridian) ? "HH:mm" : "hh:mm a";
var date = formatter(value);
return date;
});
ngModel.$parsers.push(function (value) {
var date = showTime(value);
return date;
});
} //link function
};
});
Here is my html code which will display the time in pop up i need to update both text and popup values please some one to help me to solve this problem.

angular bootstrap datepicker get visible dates (day mode)

I need to get visible dates from the Datepicker if mode is day.
Example:
In this case I need to get these 42 days. Also if user change month, I should refresh the Datepicker controller view and get new 42 days.
So i managed to fix this.
We need to extend uibDatepickerDirective
angular.module('ui.bootstrap.datepicker')
.config(function ($provide) {
$provide.decorator('uibDatepickerDirective', function ($delegate, $timeout) {
var directive = $delegate[0];
var link = directive.link;
angular.extend(directive.scope, {
visibleDates: '=?'
});
directive.compile = function () {
return function (scope, element, attrs, ctrls) {
link.apply(this, arguments);
var datepickerCtrl = ctrls[0];
datepickerCtrl.getVisibleDates = function () {
var year = this.activeDate.getFullYear(),
month = this.activeDate.getMonth(),
firstDayOfMonth = new Date(this.activeDate);
firstDayOfMonth.setFullYear(year, month, 1);
var difference = this.startingDay - firstDayOfMonth.getDay(),
numDisplayedFromPreviousMonth = difference > 0 ?
7 - difference : -difference,
firstDate = new Date(firstDayOfMonth);
if (numDisplayedFromPreviousMonth > 0) {
firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
}
return this.getDates(firstDate, 42);;
}
var firstTime = true;
$timeout(function () {
scope.$watch("activeDt", function () {
var newValues = datepickerCtrl.getVisibleDates();
if (firstTime) {
scope.visibleDates = newValues;
firstTime = false;
return;
}
if (newValues[0].getYear() !== scope.visibleDates[0].getYear() ||
newValues[0].getMonth() !== scope.visibleDates[0].getMonth() ||
newValues[0].getDate() !== scope.visibleDates[0].getDate()) {
scope.visibleDates = newValues;
}
});
});
}
};
return $delegate;
});
});
And in directive itself we need to pass atribute visible-dates and point to the variable where we want to save these 42 days.
<span uib-datepicker visible-dates="visibleDates" datepicker- ng-model="datePicked"></span>
This way we will update visibleDates (42 of them) if we change month in datepicker, but if we change activeDate (scope.activeDt) on the same month (same visible dates), it will stay unchanged.

Input Calendar jumping to next input

I'm using this Calendar, and "i'm forced to use it" and i'm wondering if you could help me sorting out a small issue i'm having.
Calendar: http://www.bulgaria-web-developers.com/projects/javascript/calendar/
I have 2 input fields that this calendar is on,
<input type="text" id="cr_date_from" />
<input type="text" id="cr_date_to" />
And after selecting the date in "date_from" i need it to jump to "date_to" and have the same date as selected in the date_from field. As this will not cause confusion when people are selecting a date months ahead in time, and not to scroll all the way to that date in the date_to as well...
I've tried researching on this for a while now without luck, so i'm hoping you guys are able to help me out..
Appreciate all help on this!
Here is also the javascript for those interested...
bindSearch: function () {
var self = this,
dateFrom = new Calendar({
element: "cr_date_from",
//dateFormat: "Y-m-d",
dateFormat: self.opts.dateFormat,
monthNamesFull: self.opts.monthNamesFull,
dayNames: self.opts.dayNames,
disablePast: true,
months: 3,
onSelect: function () {
reCalc.call(self);
}
}),
dateTo = new Calendar({
element: "cr_date_to",
//dateFormat: "Y-m-d",
dateFormat: self.opts.dateFormat,
monthNamesFull: self.opts.monthNamesFull,
dayNames: self.opts.dayNames,
disablePast: true,
months: 3,
onSelect: function () {
reCalc.call(self);
}
}),
lnkFrom = document.getElementById("crDateFrom"),
lnkTo = document.getElementById("crDateTo"),
btnQuote = document.getElementById("crBtnQuote"),
btnMap = document.getElementById("crBtnMap"),
sameLoc = document.getElementById("cr_same_location"),
returnLoc = document.getElementById("crReturnBox");
self.elFrom = document.getElementById("cr_date_from");
self.elTo = document.getElementById("cr_date_to");
self.elHFrom = document.getElementById("cr_hour_from");
self.elMFrom = document.getElementById("cr_minutes_from");
self.elHTo = document.getElementById("cr_hour_to");
self.elMTo = document.getElementById("cr_minutes_to");
function reCalc() {
var from = Date.parseExact(this.elFrom.value, dateFormat(self.opts.dateFormat, 'datejs')).getTime() + (parseInt(this.elHFrom.value, 10) * 3600000) + (parseInt(this.elMFrom.value, 10) * 60000),
to = Date.parseExact(this.elTo.value, dateFormat(self.opts.dateFormat, 'datejs')).getTime() + (parseInt(this.elHTo.value, 10) * 3600000) + (parseInt(this.elMTo.value, 10) * 60000),
nd = document.getElementById("crNumDays"),
days;
if (from !== null && to !== null) {
days = Math.ceil((to - from) / 86400000);
if (days > 0) {
nd.lastChild.innerHTML = days;
nd.style.display = "";
} else {
nd.style.display = "none";
}
} else {
nd.style.display = "none";
}
}
if (lnkFrom) {
lnkFrom.onclick = function (e) {
if (e && e.preventDefault) {
e.preventDefault();
}
dateFrom.isOpen ? dateFrom.close() : dateFrom.open();
return false;
};
}
if (lnkTo) {
lnkTo.onclick = function (e) {
if (e && e.preventDefault) {
e.preventDefault();
}
dateTo.isOpen ? dateTo.close() : dateTo.open();
return false;
};
}
if (btnMap) {
btnMap.onclick = function (e) {
self.overlayMap.open();
if (e && e.preventDefault) {
e.preventDefault();
}
return false;
}
}
if (sameLoc && returnLoc) {
function bindLoc(el) {
if (this.checked) {
el.style.display = "none";
} else {
el.style.display = "";
}
}
sameLoc.onchange = function () {
bindLoc.call(this, returnLoc);
};
sameLoc.onclick = function () {
bindLoc.call(this, returnLoc);
};
}
if (btnQuote) {
btnQuote.onclick = function () {
this.disabled = true;
if (!self.validateSearch(this)) {
this.disabled = false;
return;
}
self.passed.first = true;
self.loadCars.apply(self, [JABB.Utils.serialize(document.getElementById("crFormSearch"))]);
};
}
},

Categories

Resources