Enable first sunday in Jquery UI datapicker - jquery-ui

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...

Related

Custom "compare" and axis range in Highcharts

I added a custom "compare" routine in order to compute the difference of some point value relative to the previous point (instead of relative to the first point in the series as implemented in compare: 'value'):
Highcharts.wrap(Highcharts.Series.prototype, "setCompare", function(proceed, compare) {
// Set or unset the modifyValue method
this.modifyValue = (compare === 'value' || compare === 'percent' || compare === 'value_previous' || compare === 'percent_previous') ?
function(value, point) {
// MODIFIED ---------------------
var compareValue;
if (point && compare.includes("_previous")) {
compareValue = point.series.processedYData[point.index - 1];
} else {
compareValue = this.compareValue;
}
// -------------------------------
if (typeof value !== 'undefined' && typeof compareValue !== 'undefined') { // #2601, #5814
// Get the modified value
if (compare.includes('value')) { // MODIFIED!!!!!!!
value -= compareValue;
// Compare percent
} else {
value = 100 * (value / compareValue) - (this.options.compareBase === 100 ? 0 : 100);
}
// record for tooltip etc.
if (point) {
point.change = value;
}
return value;
}
return 0;
} :
null;
// Survive to export, #5485
this.userOptions.compare = compare; // ---WHAT TO DO???---
// Mark dirty
if (this.chart.hasRendered) {
this.isDirty = true;
}
});
The chart is drawn as expected (see fiddle), but the yaxis' range does not cover the new computed values. Any idea how to solve the problem?
Fiddle
You need also include this part of the code which will trigger and get the this.modifyValue from your custom wrap.
///
/// MISSED FUNCTIONS
///
var arrayMin = Highcharts.arrayMin = function arrayMin(data) {
var i = data.length, min = data[0];
while (i--) {
if (data[i] < min) {
min = data[i];
}
}
return min;
};
var arrayMax = Highcharts.arrayMax = function arrayMax(data) {
var i = data.length, max = data[0];
while (i--) {
if (data[i] > max) {
max = data[i];
}
}
return max;
};
// Modify series extremes
Highcharts.addEvent(Highcharts.Series.prototype, 'afterGetExtremes', function (e) {
var dataExtremes = e.dataExtremes;
if (this.modifyValue && dataExtremes) {
var extremes = [
this.modifyValue(dataExtremes.dataMin),
this.modifyValue(dataExtremes.dataMax)
];
dataExtremes.dataMin = arrayMin(extremes);
dataExtremes.dataMax = arrayMax(extremes);
}
});
///
///
///
Demo: https://jsfiddle.net/BlackLabel/ucvae7xy/

jQuery datetimepicker: disable time

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>

Sencha Touch 2.3.1 list scroll freezing

I'm using Sencha Touch 2.3.1 and using a list defined like this :
{
xtype: 'list',
id: 'index_list',
infinite: true,
flex: 1,
scrollToTopOnRefresh: false,
disableSelection: true,
store: 'store_index'
}
List's store has got more than 300 records, that's why I put the flag "infinite" to true.
Problem is when I scroll very fastly up and down through the list, app freezes and I can't do anything else with UI.
Also tested, put infinite flag to false doesn't fix it.
Cannot reproduce if data are less than ~300 records.
Platforms : iOS 6, 7 (iPhone), not iPad.
Have you got any idea ?
Use this override works for me
Ext.define('InfiniteListScroll.override.TouchGesture', {
override: 'Ext.event.publisher.TouchGesture',
lastEventType: null,
changedTouchesId: null,
lastEventObject: null,
onEvent: function(e) {
console.log('InfiniteListScroll.override.TouchGesture - onEvent');
var type = e.type,
lastEventType = this.lastEventType,
touchList = [e];
if ( type == 'touchstart' ) {
if( this.changedTouchesId == null ) {
this.changedTouchesId = e.changedTouches[0].identifier;
this.lastEventObject = e;
}
else {
console.log('changedTouchesId NOT null, touchEnd event wasnt fired for corresponding touchStart event.');
this.onTouchEnd( this.lastEventObject );
}
}
if (this.eventProcessors[type]) {
this.eventProcessors[type].call(this, e);
return;
}
if ('button' in e && e.button > 0) {
return;
}
else {
// Temporary fix for a recent Chrome bugs where events don't seem to bubble up to document
// when the element is being animated with webkit-transition (2 mousedowns without any mouseup)
if (type === 'mousedown' && lastEventType && lastEventType !== 'mouseup') {
var fixedEvent = document.createEvent("MouseEvent");
fixedEvent.initMouseEvent('mouseup', e.bubbles, e.cancelable,
document.defaultView, e.detail, e.screenX, e.screenY, e.clientX,
e.clientY, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.metaKey,
e.button, e.relatedTarget);
this.onEvent(fixedEvent);
}
if (type !== 'mousemove') {
this.lastEventType = type;
}
e.identifier = 1;
e.touches = (type !== 'mouseup') ? touchList : [];
e.targetTouches = (type !== 'mouseup') ? touchList : [];
e.changedTouches = touchList;
this.eventProcessors[this.mouseToTouchMap[type]].call(this, e);
}
},
onTouchEnd: function(e) {
console.log('InfiniteListScroll.override.TouchGesture - onTouchEnd');
if (!this.isStarted) {
return;
}
if (this.lastMoveEvent) {
this.onAnimationFrame();
}
var touchesMap = this.touchesMap,
currentIdentifiers = this.currentIdentifiers,
changedTouches = e.changedTouches,
ln = changedTouches.length,
identifier, i, touch;
this.changedTouchesId = null;
this.updateTouches(changedTouches);
changedTouches = e.changedTouches;
for (i = 0; i < ln; i++) {
Ext.Array.remove(currentIdentifiers, changedTouches[i].identifier);
}
e = this.factoryEvent(e);
for (i = 0; i < ln; i++) {
identifier = changedTouches[i].identifier;
touch = touchesMap[identifier];
delete touchesMap[identifier];
this.publish('touchend', touch.targets, e, {touch: touch});
}
this.invokeRecognizers('onTouchEnd', e);
// Only one touch currently active, and we're ending that one. So currentTouches should be 0 and clear the touchMap.
// This resolves an issue in iOS where it can sometimes not report a touchend/touchcancel
if (e.touches.length === 1 && currentIdentifiers.length) {
currentIdentifiers.length = 0;
this.touchesMap = {};
}
if (currentIdentifiers.length === 0) {
this.isStarted = false;
this.invokeRecognizers('onEnd', e);
if (this.animationQueued) {
this.animationQueued = false;
Ext.AnimationQueue.stop('onAnimationFrame', this);
}
}
}
});

Two linked jQuery Sliders adding up to 100%

I'm trying to link two jQuery UI sliders so they'll add up to 100%. I've found the perfect solution for three sliders here on SO, but for some reason I am unable to get the math to add up correctly when modifying this jsFiddle example to strip out the third slider: http://jsfiddle.net/gWbMp/3/
Can anyone help me out in forking this to simply include two sliders instead of three?
Here's the (close) javascript I've ended up with but it's not quite right:
var min = 0;
var max = 100;
$("input").change(function(){
console.log("a");
var index = $(this).attr('class').substring(0,1);
$("#slider_"+ index).slider('value', this.value);
refreshSliders( index - 0 );
});
$('.selector').slider({
animate : true
}, {
min : min
}, {
max : max
}, {
change : function(event, ui) {
totalvalue = $("#slider_1").slider("value") + $("#slider_2").slider("value");
$('.1percent').val($("#slider_1").slider("value"));
$('.2percent').val($("#slider_2").slider("value"));
}
}, {
slide : function(event, ui) {
$('.1percent').val($("#slider_1").slider("value"));
$('.2percent').val($("#slider_2").slider("value"));
}
});
$("#slider_1").slider('value', 10);
$("#slider_2").slider('value', 90);
$('.1percent').val($("#slider_1").slider("value"));
$('.2percent').val($("#slider_2").slider("value"));
function refreshSliders(slidermainin) {
var value1 = $("#slider_1").slider("option", "value");
var value2 = $("#slider_2").slider("option", "value");
var valuechange = (value1 + value2) - 100;
var valuemain = 0, valueother1 = 0;
switch(slidermainin) {
case 1:
slidermain = "#slider_1";
sliderother1 = "#slider_2";
valuemain = value1;
valueother1 = value2;
break;
case 2:
slidermain = "#slider_2";
sliderother1 = "#slider_1";
valuemain = value2;
valueother1 = value1;
break;
}
if (valueother1 === 0) {
if (valueother1 === 0) {
if (valuechange <= 0) {
$(sliderother1).slider('value', valueother1 - (valuechange / 2));
}
} else {
if (valuechange <= 0) {
$(sliderother1).slider('value', valueother1 - (valuechange / 2));
} else {
$(sliderother1).slider('value', valueother1 - valuechange);
}
}
} else {
$(sliderother1).slider('value', valueother1 - (valuechange / 2));
}
}
var bindSliders = function(selector, value) {
$(selector).bind("slidechange slide", function(event, ui) {
event.originalEvent && (event.originalEvent.type == 'mousemove' || event.originalEvent.type == 'mouseup' || event.originalEvent.type == 'keydown') && refreshSliders(value);
});
};
bindSliders("#slider_1", 1);
bindSliders("#slider_2", 2);
I think this can be done much shorter for two sliders
You can rewrite refreshSliders function to calculate second value on the basis of max value
And call it directly on slider "change" and "slide" (or even just second one)
function refreshSliders(thisSlider, ui){
var thisNum = $(thisSlider).attr("id").replace("slider_", "");
var otherNum = (thisNum==1)?2:1;
$('.'+thisNum+'percent').val(ui.value);
if ($("#slider_"+otherNum).slider("value")!=max-ui.value){
$("#slider_"+otherNum).slider("value", max-ui.value);
$('.'+otherNum+'percent').val(max-ui.value);
}
}
have a look at this jsfiddle, i forked it from original one and adjusted a bit: http://jsfiddle.net/paulitto/fBxCm/1/

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>

Resources