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>
Related
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>
I am using the XDSoft jQuery datetimepicker in my app (Ruby on Rails 4 (just for information, not using bootstrap datetimepicker)).
I was wondering if there is a way to disable/deactivate a specific time at a specific date, for example disable only 17:00 on 12/17/2014?
disabledDates: ['...'] disables a specific date.
I tried disabledDateTimes and disabledTimes but they don't work.
Thanks.
Here is one example of how this can be done using the XDSoft DateTimePicker you are asking about.
I have a specificDates array which you can use to add dates you want to target.
I also have an hoursToTakeAway multi dimensional array which corresponds with the specificDates array where you can specify the hours to take away.
HTML
<input class="eventStartDate newEventStart eventEditDate startTime eventEditMetaEntry" id="from_date" name="from_date" placeholder="Start date and time" readonly="readonly" type="text" />
Javascript
var specificDates = ['24/12/2014','17/12/2014'];
var hoursToTakeAway = [[14,15],[17]];
$('#from_date').datetimepicker({
format:'d.m.Y H:i',
timepicker: true,
lang: 'en',
onGenerate:function(ct,$i){
var ind = specificDates.indexOf(ct.dateFormat('d/m/Y'));
$('.xdsoft_time_variant .xdsoft_time').show();
if(ind !== -1) {
$('.xdsoft_time_variant .xdsoft_time').each(function(index){
if(hoursToTakeAway[ind].indexOf(parseInt($(this).text())) !== -1) {
$(this).hide();
}
});
}
}
});
Example
Fiddle
Basically I am taking advantage of the onGenerate event which happens after each calendar has been rendered. Then I am checking to see if the date matches the specified day and if it does, we iterate through all the time elements and hide the ones specified for the specific date.
Updated Fiddle implementing disable.
Fiddle 2
This code is working for me:
var specificDates = ['24/12/2014','17/12/2014'];
var hoursToTakeAway = [[14,15],[17]];
$('#from_date').datetimepicker({
format:'d.m.Y H:i',
timepicker: true,
lang: 'en',
onGenerate:function(ct,$i){
var ind = specificDates.indexOf(ct.dateFormat('d/m/Y'));
$('.xdsoft_time_variant .xdsoft_time').show();
if(ind !== -1) {
$('.xdsoft_time_variant .xdsoft_time').each(function(index){
if(hoursToTakeAway[ind].indexOf(parseInt($(this).text())) !== -1) {
$(this).hide();
}
});
}
}
});
If someone still need solution, i write code to disable ranges of time in jquery-ui-datepicker.
First I need to init ranges, that will be disabled at current date:
dateObj1 = new Date(2016,6,22,0);
dateObj2 = new Date(2016,6,27,10);
diap1 = [dateObj1, dateObj2];
dateObj1 = new Date(2016,6,27,13);
dateObj2 = new Date(2016,6,27,14);
diap2 = [dateObj1, dateObj2];
dateObj1 = new Date(2016,6,27,20);
dateObj2 = new Date(2016,6,29,10);
diap3 = [dateObj1, dateObj2];
dateObj1 = new Date(2016,6,27,0);
dateObj2 = new Date(2016,6,27,13);
diap4 = [dateObj1, dateObj2];
dateObj1 = new Date(2016,7,02,4);
dateObj2 = new Date(2016,7,02,4,59);
diap5 = [dateObj1, dateObj2];
diapazons = [diap1,diap2,diap3,diap4,diap5];
Then I need function, to proceed this ranges, detect intersections and create ranges, that will be displayed:
function getAvailableTimes(restricts, curr_year, curr_month, cur_day)
{
day_diaps = [[new Date(curr_year,curr_month,cur_day,0), new Date(curr_year,curr_month,cur_day,23,59,59)]];
restricts.forEach(function(item, i, arr) {
day_diaps.forEach(function(day_diap, i_d, arr_d) {
//console.log('day = '+day_diap.toString());
if (day_diap[0] >= item[1])
{
//console.log(i+' раньше');
}
else if (day_diap[1] <= item[0])
{
//console.log(i+' позже');
}
else if (day_diap[0] >= item[0] && day_diap[1] <= item[1])
{
//console.log(i+' закрыт полностью');
arr_d.splice(i_d,1);
}
else if (day_diap[0] >= item[0] && day_diap[1] >= item[1])
{
day_diap[0] = item[1];
//console.log(i+' ранее перекрытие, начало смещено на '+ day_diap.toString());
}
else if (day_diap[0] <= item[0] && day_diap[1] <= item[1])
{
day_diap[1] = item[0];
//console.log(i+' позднее перекрытие, конец смещен на '+ day_diap.toString());
}
else if (day_diap[0] <= item[0] && day_diap[1] >= item[1])
{
new_diap = [item[1],day_diap[1]];
arr_d.push(new_diap);
day_diap[1] = item[0];
//console.log(i+' restrict полностью умещается в диапазон '+ day_diap.toString());
//console.log(i+' добавлен диапазон '+ new_diap.toString());
}
});
});
return day_diaps;
}
And code in of datetimepicker:
<input type="text" id="default_datetimepicker"/>
<script>
$.datetimepicker.setLocale('ru');
var dates_to_disable = ['30-07-2016','31-07-2016','04-08-2016'];
$('#default_datetimepicker').datetimepicker({
formatTime:'H:i',
lang: "ru",
defaultTime:"10:00",
formatDate:'d-m-Y',
todayButton: "true",
minDate:'01-01--1970', // yesterday is minimum date
disabledDates:dates_to_disable,
onGenerate:function(ct,i){
var dates = jQuery(this).find('.xdsoft_date ');
$.each(dates, function(index, value){
year = jQuery(value).attr('data-year');
month = jQuery(value).attr('data-month');
date = jQuery(value).attr('data-date');
diaps = getAvailableTimes(diapazons,year,month,date);
net_nihrena = true;
diaps.forEach(function(day_diap, i_d, arr_d) {
net_nihrena = false;
});
if (net_nihrena)
{
jQuery(value).addClass('xdsoft_disabled');
//jQuery(value).addClass('xdsoft_restricted');
}
});
cur_date = ct;
diaps = getAvailableTimes(diapazons,ct.getFullYear(),ct.getMonth(),ct.getDate());
var times = jQuery(this).find('.xdsoft_time ');
$.each(times, function(index){
var hour = $(this).attr('data-hour');
var minute = $(this).attr('data-minute');
cur_date.setHours(hour,minute,0);
net_takogo_vremeni = true;
diaps.forEach(function(day_diap, i_d, arr_d) {
if ((day_diap[0] < cur_date && day_diap[1] > cur_date) || hour==0)
{
net_takogo_vremeni = false;
}
});
if (net_takogo_vremeni)
{
$(this).addClass('xdsoft_disabled');
//$(this).addClass('xdsoft_restricted');
}
});
},
onSelectDate : function(ct) {
}
});
</script>
I have been busy creating a solution to a client that has proven to be a bit more difficult than I thought it would be. I am using the jQuery Datepicker widget to display calendar events (monthly view) from server-side code. Every thing in the following code works EXCEPT the CSS. It is not changing anything and it seems I've tried everything in the world.
A Calendar is shown in month-view on page-load (MVC) and if a user has events the day should have a different background-color. Also, when the user changes month-to-month, the same logic happens (ajax call to server). Again, this all is working well. My directive to change the background color will not.
<script type="text/javascript">
$(document).ready(function () {
$.expr[":"].exactly = function (el, i, m) {
var s = m[3];
if (!s) return false;
return eval("/^" + s + "$/i").test($(el).text());
};
var currentYear = (new Date).getFullYear();
var currentMonth = (new Date).getMonth();
function getTheData(year, month) {
var theYear = year;
var theMonth = month;
//alert(theYear + ", " + theMonth);
$.post("GetMeSomeData", { year: theYear, month: theMonth }, function(data) {
//cycle through the dates and address the CSS appropriately
var i = 0;
for (i = 0; i < data.length; i++) {
$('.ui-datepicker-calendar td a:exactly(' + data[i]['d'] + ')')
.css({ backgroundColor: 'blue' });
}
});
}
$('#date').datepicker({
inline: true,
beforeShowDay: getTheData(currentYear, currentMonth),
onSelect: function (dateText, inst) {
Date.prototype.toString = function () { return isNaN(this) ? 'NaN' : [this.getDate(), this.getMonth(), this.getFullYear()].join('/'); };
d = new Date(dateText);
//alert(d.getDate() + ", " + d.getFullYear());
getTheData(d.getFullYear(), d.getDate());
},
onChangeMonthYear: function (year, month, inst) {
//alert(year + ", " + month);
getTheData(year, month);
}
});
});
</script>
I'm using the datepicker form jQuery-ui-1.8.16.
I have the following code:
Site.Calendar = function() {
// Set default setting for all calendars
jQuery.datepicker.setDefaults({
showOn : 'both',
buttonImageOnly : true,
buttonText: '',
changeMonth : true,
changeYear : true,
showOtherMonths : true,
selectOtherMonths : true,
showButtonPanel : true,
dateFormat : "D, d M, yy",
showAnim : "slideDown",
onSelect: Site.Calendar.customiseTodayButton
});
};
Site.Calendar.customiseTodayButton = function(dateText, inst) {
console.log("hello");
};
My customiseTodayButton function is only getting triggered when I select an actual date and NOT on the Today button.
Is there any way to override how the today button work's in the jQuery datepicker?
Thanks
I found the following posted here:
Today button in jQuery Datepicker doesn't work
jQuery.datepicker._gotoToday = function(id) {
var target = jQuery(id);
var inst = this._getInst(target[0]);
if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
inst.selectedDay = inst.currentDay;
inst.drawMonth = inst.selectedMonth = inst.currentMonth;
inst.drawYear = inst.selectedYear = inst.currentYear;
}
else {
var date = new Date();
inst.selectedDay = date.getDate();
inst.drawMonth = inst.selectedMonth = date.getMonth();
inst.drawYear = inst.selectedYear = date.getFullYear();
this._setDateDatepicker(target, date);
this._selectDate(id, this._getDateDatepicker(target));
}
this._notifyChange(inst);
this._adjustDate(target);
}
It simply rewrites the goToToday method and adds two new lines:
this._setDateDatepicker(target, date);
this._selectDate(id, this._getDateDatepicker(target));
Maybe there is a cleaner way to fix this with your original answer Mark?
There isn't a standard event for when the today button is clicked. However, taking a look at the jquery.ui.datepicker.js code, it appears that it calls $.datepicker._gotoToday. I'll assume by customizeTodayButton you're attempting to change the behavior of what it does currently (not the looks, the looks would be done with styling). To change the existing behavior, it's good to know what it does now. So, that in mind, this is the current code of the function used:
/* Action for current link. */
_gotoToday: function(id) {
var target = $(id);
var inst = this._getInst(target[0]);
if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
inst.selectedDay = inst.currentDay;
inst.drawMonth = inst.selectedMonth = inst.currentMonth;
inst.drawYear = inst.selectedYear = inst.currentYear;
}
else {
var date = new Date();
inst.selectedDay = date.getDate();
inst.drawMonth = inst.selectedMonth = date.getMonth();
inst.drawYear = inst.selectedYear = date.getFullYear();
}
this._notifyChange(inst);
this._adjustDate(target);
},
To override this function with your own functionality, you'll want to do update your code to something like this:
Site.Calendar = function() {
//override the existing _goToToday functionality
$.datepicker._gotoTodayOriginal = $.datepicker._gotoToday;
$.datepicker._gotoToday = function(id) {
// now, call the original handler
$.datepicker._gotoTodayOriginal.apply(this, [id]);
// invoke selectDate to select the current date and close datepicker.
$.datepicker._selectDate.apply(this, [id]);
};
// Set default setting for all calendars
jQuery.datepicker.setDefaults({
showOn: 'both',
buttonImageOnly: true,
buttonText: '',
changeMonth: true,
changeYear: true,
showOtherMonths: true,
selectOtherMonths: true,
showButtonPanel: true,
dateFormat: "D, d M, yy",
showAnim: "slideDown"
});
};
Also, here's a working jsFiddle of what you're looking for.
I realized the overriding of the today button in this way:
jQuery.datepicker._gotoToday = function(id) {
var today = new Date();
var dateRef = jQuery("<td><a>" + today.getDate() + "</a></td>");
this._selectDay(id, today.getMonth(), today.getFullYear(), dateRef);
};
This is quite simple and does the "select date and close datepicker" functionality that I would.
I'm currently working on a Jquery datepicker where holidays are disabled and all sundays, except for the first one in each month. I have been trying to play around a little with the code, and found out how to disable all sundays and holidays, but i cant figure out how to enable the first sunday of evey month.
Currently my code looks like this:
<script type="text/javascript">
(function(){
var natDays = [[12, 24],[12, 25], [1,1], [12, 31]];
var daysToDisable = [0];
function nationalDays(date) {
for (i = 0; i < natDays.length; i++) {
if (date.getMonth() == natDays[i][0] - 1
&& date.getDate() == natDays[i][1]) {
return [false, natDays[i][2] + '_day'];
}
}
for (i = 0; i < daysToDisable.length; i++) {
if ($.inArray(day, daysToDisable) != -1) {
return [false];
}
}
return [true];
}
// Datepicker
$('#datepicker').datepicker({
inline: true,
firstDay: 1,
changeYear: true,
changeMonth: true,
beforeShowDay: nationalDays,
});
});
</script>
Logically, the first Sunday of the month is always on or before the 7th and the second (and subsequent) Sundays are after the 7th.
function nationalDays(date) {
for (i = 0; i < natDays.length; i++) {
if (date.getMonth() == natDays[i][0] - 1 && date.getDate() == natDays[i][1]) {
return [false, natDays[i][2] + '_day'];
}
}
if (date.getDate() > 7 && $.inArray(date.getDay(), daysToDisable) != -1)
return [false];
}
return [true];
}
I would also suggest to change the structure of your natDays array to a flat array in order to speed up lookups. For your class prefixes (which are not set in your example), you can use an extra array with matching indices. Your final function would look like this:
var natDays = ["12-24", "12-25", "1-1", "12-31"];
var classPrefixes = ["", "", "", ""];
var daysToDisable = [0];
function nationalDays(date) {
var index = $.inArray((date.getMonth() + 1) + "-" + date.getDate(), natDays);
if (index != -1) {
return [false, classPrefixes[index] + '_day'];
}
if (date.getDate() > 7 && $.inArray(date.getDay(), daysToDisable) != -1)
return [false];
}
return [true];
}
The method you're looking for is date.getDay(), which will return a number from 0 to 6, with 0 being Sunday.
function nationalDays(date) {
if(date.getDay() == 0) {
// do stuff...