how to reject the selected date in onSelect in jquery ui DatePicker - jquery-ui

I have a web-form where I'm asking the user for several dates. Usually, but not always, a repeated date will be a human error. So in the onSelect function I'm checking to see if the date has already been entered, and asking the user to confirm whether a duplicated date was intentional. If the user says No, how to clear the date value from the picker?
// datesList initialized in outer scope
onSelect: function (thedate, picker) {
if ($.inArray(new Date(thedate).valueOf(), datesList) == -1) {
//store chosen dates in datesList if we haven't seen it before
datesList.push(new Date(thedate).valueOf())
} else {
// ask the user if it was intentional
//if unintentional, reject the choice and clear the picker
}
}

Not sure you can do it with given options, but you could override _selectDate and add a condition. Something like this:
$.datepicker._selectDate = function(id, dateStr) {
var target = $(id);
var inst = this._getInst(target[0]);
dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
if (inst.input)
inst.input.val(dateStr);
this._updateAlternate(inst);
var onSelect = this._get(inst, 'onSelect');
if (onSelect){
// you get the value of onSelect
var shouldHide = onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
} else if (inst.input && shouldHide){
inst.input.trigger('change'); // fire the change event
}
if (inst.inline)
this._updateDatepicker(inst);
// If onSelect return false, you don't hide the datepicker
else if (shouldHide) {
this._hideDatepicker();
this._lastInput = inst.input[0];
if (typeof(inst.input[0]) != 'object')
inst.input.focus(); // restore focus
this._lastInput = null;
}
}
$('input').datepicker({
onSelect: function(e, ui) {
if (confirm('OK?')) {
return true;
} else {
this.value = "";
return false;
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js" integrity="sha256-T0Vest3yCU7pafRw9r+settMBX6JkKN06dqBnpQ8d30=" crossorigin="anonymous"></script>
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"></link>
<input type=text></input>

Related

Select2 - Show/Hide div based on selection

I am trying to have a div show if an option is selected using the Select2 plug in.
I tried using the following code but it does not work:
$(document).ready(function() {
var h = $(".shipment-details--other-description");
$("#shipment-details-select-pacakage-types").change(function() {
if (this.checked && this.value == "Other") {
h.show();
} else {
h.hide();
}
}).change()
});
The div is being hid but not being shown if the Other option is selected.
Is there a different way to do this with Select2?
Edit: Forgot to mention that this a multiple select field. Also, adjusted the code and took out the this.checked as that was for a check field.
try to create a new css class, is-hidden{ display:none;}
$(document).ready(function() {
var h = $(".shipment-details--other-description");
$("#shipment-details-select-pacakage-types").change(function() {
if (this.checked && this.value == "Other") {
h.addClass('is-hidden');
} else {
h.removeClass('is-hidden');
}
}).change()
});

Set Umbraco Property Editor Input to jQueryUI Datepicker

I'm close but still can't quite get this to work.
I have a new custom property editor that is loading correctly and is doing almost everything expected until I try to set the text field to be a jQuery UI element.
As soon as I add a directive in Angular for setting it to call the jQuery UI datepicker function, I get the following error suggesting it hasn't loaded the jQueryUI script library correctly:
TypeError: Object [object Object] has no method 'datepicker'
Trouble is, I can't see where I should be adding it as the logical places (to my mind, at least) seem to make no difference. Here is the code in full:
function MultipleDatePickerController($scope, assetsService) {
//tell the assetsService to load the markdown.editor libs from the markdown editors
//plugin folder
//assetsService
// .load([
// "http://code.jquery.com/ui/1.10.4/jquery-ui.min.js"
// ])
// .then(function () {
// //this function will execute when all dependencies have loaded
// });
//load the seperat css for the editor to avoid it blocking our js loading
assetsService.loadCss("/css/jquery-ui.custom.min.css");
if (!$scope.model.value) {
$scope.model.value = [];
}
//add any fields that there isn't values for
//if ($scope.model.config.min > 0) {
if ($scope.model.value.length > 0) {
for (var i = 0; i < $scope.model.value.length; i++) {
if ((i + 1) > $scope.model.value.length) {
$scope.model.value.push({ value: "" });
}
}
}
$scope.add = function () {
//if ($scope.model.config.max <= 0 || $scope.model.value.length < $scope.model.config.max) {
if ($scope.model.value.length <= 52) {
$scope.model.value.push({ value: "" });
}
};
$scope.remove = function (index) {
var remainder = [];
for (var x = 0; x < $scope.model.value.length; x++) {
if (x !== index) {
remainder.push($scope.model.value[x]);
}
}
$scope.model.value = remainder;
};
}
var datePicker = angular.module("umbraco").controller("AcuIT.MultidateController", MultipleDatePickerController);
datePicker.directive('jqdatepicker', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
$(function () {
element.datepicker({
dateFormat: 'dd/mm/yy',
onSelect: function (date) {
scope.$apply(function () {
ngModelCtrl.$setViewValue(date);
});
}
});
});
}
}
});
I faced the same problem when adapting a jQuery Date Range Picker for my Date Range Picker package for Umbraco 7. It's frustrating! The problem (I think) is that Angular's ng-model listens for "input" changes to trigger events and so doesn't pick up on a jQuery triggered event.
The way around it I found was to force the input event of the element you wish to update to fire manually, using jQuery's .trigger() event.
For example, the date picker I was using had this code for when a date was changed:
updateInputText: function () {
if (this.element.is('input')) {
this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));
}
},
I just adapted it to force an input trigger by adding this.element.trigger('input') to the code block, so it now reads:
updateInputText: function () {
if (this.element.is('input')) {
this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format));
this.element.trigger('input');
}
},
This forces Angular to "see" the change and then ng-model is updated. There may well be a more elegant way (as I'm an Angular newbie), but I know this worked for me.
Got it. This is probably a bit of a hack, but it's simple and effective so it's a win nonetheless.
The assetsService call is the key, where I've put code into the deferred .then statement to call jQueryUI's datepicker on any item that has the "jqdp" CSS class:
//tell the assetsService to load the markdown.editor libs from the markdown editors
//plugin folder
assetsService
.load([
"/App_Plugins/Multidate/jquery-ui.min.js"
])
.then(function () {
//this function will execute when all dependencies have loaded
$('.jqdp').datepicker({ dateFormat: 'dd/mm/yy' });
});
I've then gone and added that class to my view:
<input type="text" jqdatepicker name="item_{{$index}}" ng-model="item.value" class="jqdp" id="dp-{{model.alias}}-{{$index}}" />
Finally, I've added a directive to ensure that dynamically-added items also display a datepicker:
datePicker.directive('jqdatepicker', function () {
return function (scope, element, attrs) {
scope.$watch("jqdatepicker", function () {
try{
$(element).datepicker({ dateFormat: 'dd/mm/yy' });
}
catch(e)
{}
});
};
});
As I said, this is possibly a bit hacky but it achieves the right result and seems like a simple solution.

Datepicker using Jquery loses focus to the textbox after date selected.

Datepicker using Jquery loses focus to the textbox after date selected. I am using jquery-ui-1.9.2.When a date is selected the focus not coming to the textbox.Any solution?
Try using the below code.
HTML code:
<input type="text" id="date"/>
JQuery:
$("#date").datepicker({
onClose: function () {
$(this).focus();
}
});
JSFiddle1
EDIT: The above code has a problem in IE, the datepicker is not getting closed. Here in this blog you can find the more information.
<script language='javascript' src="jquery-migrate-1.2.1.js"></script> // download and add this
$("#date").datepicker({
/* fix buggy IE focus functionality */
fixFocusIE: false,
onClose: function(dateText, inst) {
this.fixFocusIE = true;
this.focus();
},
beforeShow: function(input, inst) {
var result = $.browser.msie ? !this.fixFocusIE : true;
this.fixFocusIE = false;
return result;
}
});
JSFiddle2
$(".datepicker").datepicker({
onClose: function () {
$(this).parents().nextAll().find($(":input[type !='hidden']")).first().focus();
}
});
});
I have found an easier way that will put the focus on the next input, no matter how nested it is. You can always swap out the condition after the .find to whatever you like and it will bring the focus to that.
Initialise all the datepcikers on Doc Ready
$('.datepicker').datepicker(
{
onClose: function () {
this.focus();
}
});
Exapnding Praveen's answer.
I had one problem with it. On IE datepicker refused to show up each odd time I focused a field.
Also, there was a slight logical issue with that solution (which did not affect anything, but still not correct to my eye): fixFocusIE field is being set on options, but then later it is being called on "this", when "this" refers to DOM element and not options object. So essentially there are two fixFocusIE - one in options (unused) and the second one on DOM element itself.
And also $.browser.msie did not work anymore, I had to invent my own IE detector.
My working code looks like that:
var el = $("selector of element I need to assign to datepicker");
var options = {}; // actually I fill options from defaults and do some other manipulations, but I left it as empty object here for brevity
options.fixFocusIE = false;
function detectIE() {
var ua = window.navigator.userAgent;
if(ua.indexOf('MSIE ') > 0 ||
ua.indexOf('Trident/') > 0 ||
ua.indexOf('Edge/') > 0) {
return true;
}
// other browser
return false;
}
/* blur() and change() are needed to update Angular bindings, if any */
options.onSelect = function(dateText, inst) {
options.fixFocusIE = true;
$(this).blur().change().focus();
};
options.onClose = function(dateText, inst) {
options.fixFocusIE = true;
this.focus();
};
options.beforeShow = function(input, inst) {
var result = detectIE() ? !options.fixFocusIE : true;
options.fixFocusIE = false;
return result;
};
/* and this one will reset fixFocusIE to prevent datepicker from refusing to show when focusing the field for second time in IE */
el.blur(function(){
options.fixFocusIE = false;
});
el.datepicker(options);

Jquery UI datepicker. Disable array of Dates

I have been trying to search for a solution to my Jquery ui datepicker problem and I'm having no luck. Here's what I'm trying to do...
I have an application where i'm doing some complex PHP to return a JSON array of dates that I want BLOCKED out of the Jquery UI Datepicker. I am returning this array:
["2013-03-14","2013-03-15","2013-03-16"]
Is there not a simple way to simply say: block these dates from the datepicker?
I've read the UI documentation and I see nothing that helps me. Anyone have any ideas?
You can use beforeShowDay to do this
The following example disables dates 14 March 2013 thru 16 March 2013
var array = ["2013-03-14","2013-03-15","2013-03-16"]
$('input').datepicker({
beforeShowDay: function(date){
var string = jQuery.datepicker.formatDate('yy-mm-dd', date);
return [ array.indexOf(string) == -1 ]
}
});
Demo: Fiddle
IE 8 doesn't have indexOf function, so I used jQuery inArray instead.
$('input').datepicker({
beforeShowDay: function(date){
var string = jQuery.datepicker.formatDate('yy-mm-dd', date);
return [$.inArray(string, array) == -1];
}
});
If you also want to block Sundays (or other days) as well as the array of dates, I use this code:
jQuery(function($){
var disabledDays = [
"27-4-2016", "25-12-2016", "26-12-2016",
"4-4-2017", "5-4-2017", "6-4-2017", "6-4-2016", "7-4-2017", "8-4-2017", "9-4-2017"
];
//replace these with the id's of your datepickers
$("#id-of-first-datepicker,#id-of-second-datepicker").datepicker({
beforeShowDay: function(date){
var day = date.getDay();
var string = jQuery.datepicker.formatDate('d-m-yy', date);
var isDisabled = ($.inArray(string, disabledDays) != -1);
//day != 0 disables all Sundays
return [day != 0 && !isDisabled];
}
});
});
$('input').datepicker({
beforeShowDay: function(date){
var string = jQuery.datepicker.formatDate('yy-mm-dd', date);
return [ array.indexOf(string) == -1 ]
}
});
beforeShowDate didn't work for me, so I went ahead and developed my own solution:
$('#embeded_calendar').datepicker({
minDate: date,
localToday:datePlusOne,
changeDate: true,
changeMonth: true,
changeYear: true,
yearRange: "-120:+1",
onSelect: function(selectedDateFormatted){
var selectedDate = $("#embeded_calendar").datepicker('getDate');
deactivateDates(selectedDate);
}
});
var excludedDates = [ "10-20-2017","10-21-2016", "11-21-2016"];
deactivateDates(new Date());
function deactivateDates(selectedDate){
setTimeout(function(){
var thisMonthExcludedDates = thisMonthDates(selectedDate);
thisMonthExcludedDates = getDaysfromDate(thisMonthExcludedDates);
var excludedTDs = page.find('td[data-handler="selectDay"]').filter(function(){
return $.inArray( $(this).text(), thisMonthExcludedDates) >= 0
});
excludedTDs.unbind('click').addClass('ui-datepicker-unselectable');
}, 10);
}
function thisMonthDates(date){
return $.grep( excludedDates, function( n){
var dateParts = n.split("-");
return dateParts[0] == date.getMonth() + 1 && dateParts[2] == date.getYear() + 1900;
});
}
function getDaysfromDate(datesArray){
return $.map( datesArray, function( n){
return n.split("-")[1];
});
}
For DD-MM-YY use this code:
var array = ["03-03-2017', '03-10-2017', '03-25-2017"]
$('#datepicker').datepicker({
beforeShowDay: function(date){
var string = jQuery.datepicker.formatDate('dd-mm-yy', date);
return [ array.indexOf(string) == -1 ]
}
});
function highlightDays(date) {
for (var i = 0; i < dates.length; i++) {
if (new Date(dates[i]).toString() == date.toString()) {
return [true, 'highlight'];
}
}
return [true, ''];
}
If you want to disable particular date(s) in jquery datepicker then here is the simple demo for you.
<script type="text/javascript">
var arrDisabledDates = {};
arrDisabledDates[new Date("08/28/2017")] = new Date("08/28/2017");
arrDisabledDates[new Date("12/23/2017")] = new Date("12/23/2017");
$(".datepicker").datepicker({
dateFormat: "dd/mm/yy",
beforeShowDay: function (date) {
var day = date.getDay(),
bDisable = arrDisabledDates[date];
if (bDisable)
return [false, "", ""]
}
});
</script>

jQuery Datepicker, select multiple dates and mark them via css at selection time, permanently

so I have spent a day developing and reading (teh other way around) to enable my jQuery datepicker to select and highlight mutliple dates.
For this I have managed to write the selected dates to an array which is visualized in a simple textfield.
What I could not manage is to permanently modify the look of the selected date in the datepicker.
I have implemented the "beforeShowDay:" option, which is working properly uppon loading the datepicker, but of course is not called directly on selecting a date.
For this I guessed, I would need to refresh the view "onSelect", but the refresh is not working properly.
Right now, I have some small methods for handling the datearray.
Uppon adding or removing a date, I am trying to refresh the datepicker.
Uppon selecting a date, I am either adding it to, or remove it from the dates-array.
Also, onSelect, I am matching the selected day and try to addClass().
But once again, I think I missed something all the way round, as it is not shown in my datepicker.
Here's my code for now:
var dates = new Array();
function addDate(date) {
if (jQuery.inArray(date, dates) < 0 && date) {
dates.push(date);
}
}
function removeDate(index) {
dates.splice(index, 1);
}
// Adds a date if we don't have it yet, else remove it and update the dates
// textfield
function addOrRemoveDate(date) {
var index = jQuery.inArray(date, dates);
if (index >= 0) {
removeDate(index);
updateDatesField(dates);
} else {
addDate(date);
updateDatesField(dates);
}
jQuery(calContainer).datepicker("refresh");
}
var calContainer = document.getElementById("calendar-container");
jQuery(calContainer).datepicker({
minDate : new Date(),
dateFormat : "#",
onSelect : function(dateText, inst) {
addOrRemoveDate(dateText);
jQuery(".ui-datepicker-calendar tbody tr td a").each(function() {
if (jQuery(this).text() == inst.selectedDay) {
jQuery(this).addClass("ui-state-highlight");
jQuery(this).parent().addClass("selected");
}
});
// addTimeSelectorColumns(dates);
},
beforeShowDay : function(_date) {
var gotDate = -1;
for ( var index = 0; index < dates.length; index++) {
if (_date.getTime() == dates[index]) {
gotDate = 1;
} else {
gotDate = -1;
}
}
if (gotDate >= 0) {
return [ true, "ui-datepicker-today", "Event Name" ];
}
return [ true, "" ];
}
});
function updateDatesField(dates) {
if (dates.length > 0) {
var tmpDatesStrArr = new Array();
var dateString = "";
var datesField = document.getElementById("dates");
for ( var index = 0; index < dates.length; index++) {
var dateNum = dates[index];
var tmpDate = new Date();
tmpDate.setTime(dateNum);
dateString = tmpDate.getDate() + "." + tmpDate.getMonth() + "."
+ tmpDate.getFullYear();
tmpDatesStrArr.push(dateString);
}
jQuery(datesField).val(tmpDatesStrArr);
}
}
(I am still a beginner in Javascript/jQuery, so any help or hints towards my coding are welcome, btw...)
It depends whether you want to stick with jQuery UI or not. If you are open to other library, there is a jQuery Datepicker that supports multiple selection: jquery.datePicker with multiple select enabled. It may save you sometmie fiddling with jQuery UI's one, as it does not natively support multiple selection.
EDIT:
If your main library is not jQuery, I think you should look for a standalone or Prototype-dependent library instead. The JS Calendar looks promising. It natively supports multiple selection by detecting the Ctrl key.

Resources