I have a custom appointment form with multiple locations. On Sundays all locations are closed. On Saturdays only a few locations are open. One location is so busy that all appointments need to be 1 week in advance at the very least.
I was finding answers saying, "You cannot update the current picker. You need to destroy it, set the reserved dates in an array, and rebuild the datepicker with those options.", which meant duplicating the datepicker that's on the custom form with all it's odd regional formats and options.
Then, after telling everyone it's going to be more work than it's worth I found out you can just out the next 7 days dynamically with:
$('input.datepicker').datepicker( 'option', 'minDate', '+7d');
That works! Then also found you could tell the current datepicker to switch to today's date with this:
$('input.datepicker').datepicker('setDate', 'today');
So can I get a live datepicker to hide weekends? I should be able to but the option I found fails:
$('input.datepicker').datepicker({ beforeShowDay: jQuery.datepicker.noWeekends });
I really want to be able to say, "no weekends" or "no sundays", without destroying and rebuilding, but it's not a popular topic since most forms don't need to update the datepicker dynamically.
Here's a simple fiddle of what I'd like to accomplish: https://jsfiddle.net/56qsau34/
EDIT: So I was really close but I had the wrong method(?) for applying an update to the live datepicker. If you take the last guess and write it properly it works!
$('input.datepicker').datepicker( 'option', 'beforeShowDay', jQuery.datepicker.noWeekends );
EDIT #2: Just for the poor soul that finds this without the final solution. When you realize that you need to 'toggle' the noWeekends feature this function that returns all the dates with 'true' will come in real handy:
$('input.datepicker').datepicker('option', 'beforeShowDay', function(d) {
var year = d.getFullYear(),
month = ("0" + (d.getMonth() + 1)).slice(-2),
day = ("0" + (d.getDate())).slice(-2);
var formatted = year + '-' + month + '-' + day;
//is it a sunday - this was the missing bit for all my specs
if (d.getUTCDay() != 0) {
return [true, "",""];
}else{
return [false, "",""];
}
}
Yes, you can change the options without destroying the widget.
$.datepicker.noSundays = function (date) {
return [ date.getDay() != 0, "" ];
}
$("#foo").click(function() {
$("input").datepicker();
});
$("#nowknd").click(function() {
$("#datepicker").datepicker('option', 'beforeShowDay', $.datepicker.noWeekends);
});
$("#okwknd").click(function() {
$("#datepicker").datepicker('option', 'beforeShowDay', '');
});
$("#nosuns").click(function() {
$("#datepicker").datepicker('option', 'beforeShowDay', $.datepicker.noSundays);
});
$("#weekblock").click(function() {
$("#datepicker").datepicker('option', 'minDate', '+7d');
});
<link href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" />
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<p>Date:<input type="text" id="datepicker"></p>
<p>
<button id="foo">Make it a datepicker</button>
<button id="nowknd">Block weekends</button>
<button id="okwknd">Allow weekends</button>
<button id="nosuns">Block Sundays</button>
<button id="weekblock">Block off a week</button>
</p>
Does this help?
Can the jQuery UI Datepicker be made to disable Saturdays and Sundays (and holidays)?
weekends visible but not selectable.
<!doctype html>
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!--
want to hide weekends from calendar
https://stackoverflow.com/questions/501943/can-the-jquery-ui-datepicker-be-made-to-disable-saturdays-and-sundays-and-holid
-->
<title>jQuery UI Datepicker - Disable the Selection of some days </title>
<link href="jquery-ui-1.10.3.css" rel="stylesheet">
<script
src="https://code.jquery.com/jquery-2.2.0.min.js"
integrity="sha256-ihAoc6M/JPfrIiIeayPE9xjin4UWjsx2mjW/rtmxLM4="
crossorigin="anonymous"></script>
<script
src="https://code.jquery.com/ui/1.10.3/jquery-ui.min.js"
integrity="sha256-lnH4vnCtlKU2LmD0ZW1dU7ohTTKrcKP50WA9fa350cE="
crossorigin="anonymous"></script>
<script type="text/javascript">
$(function () {
$(".datepicker1").datepicker({
beforeShowDay: $.datepicker.noWeekends
});
});
</script>
</head>
<body>
<h3>Click in the TextBox to select a date :</h3>
<p>weekends are not selectable</p>
<input type="text" class="datepicker1" />
</body>
</html>
Related
Please can someone please explain how this code works? It's a trivial piece of code but I don't understand/appreciate how the Option
beforeShowDay
, that calls a function works.
The DisableDates Option calls function DisableDates(date) (that seemingly) takes in a date parameter - and I can't understand how this date parameter is being passed?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link
rel="stylesheet"
href="http://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"
/>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<div id="date"></div>
<script>
$(function () {
var dates = ["08/11/2020", "09/11/2020", "10/11/2020", "12/11/2020"];
$("#date").datepicker({
changeYear: true,
changeMonth: true,
dateFormat: "yy/mm/dd",
minDate: new Date("2020/10/01"),
maxDate: "+3m",
beforeShowDay: DisableDates,
});
function DisableDates(date) {
var string = jQuery.datepicker.formatDate("dd/mm/yy", date);
return [dates.indexOf(string) == -1];
}
});
</script>
</body>
</html>
jQuery datepicker internally calling that function and passing parameter also.
Consider below small demo where you can assign your function to another variable and use that variable to call your function with parameter.
// plugin sample code with options
function demo(options) {
// assign option values to plugin variables.
this.date = options.date;
this.beforeShowDay = options.beforeShowDay;
// trigger function which invoke callback function with parameters
this.triggerBeforeShowDay = function() {
// as we have this.beforeShowDay = options.beforeShowDay;
// below code will be same as DisableDates(this.date)
this.beforeShowDay(this.date);
}
// return plugin object
return this;
}
// Your callback function with parameter
function DisableDates(date) {
console.log(date)
}
// pass options values in plugin
let d = new demo({
date: new Date("2020/10/01"),
beforeShowDay: DisableDates
});
// trigger function : Note - this part would be done internally on text change event from jquery datepicker.
// For demo only we are manually calling it.
d.triggerBeforeShowDay();
I'm making a site that, depending on the user's time of the day, will show a night, afternoon or morning image.
But as it seems, the JS isn't working due to a Syntax Error on calling the function with "onload=" in the tag <body>. My VS Code Javascript higlighter isn't working on the words window, document nor getElementById.
Which part of my JS could be wrong?
Here's the HTML
<!DOCTYPE html>
<html lang="pt-br">
<head>
<script type="javascript" src="/script.js"></script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie-edge">
<link rel="stylesheet" href="/style.css">
</head>
<body onload="load()">
<section>
<div id="msg">
Message here
</div>
<div id="foto">
<img id="image" src="img/afternoon.png">
</div>
</section>
<footer>
<p>© Koala</p>
</footer>
</body>
</html>
And here's the JS
function load(){
var msg = window.document.getElementById('msg');
var img = window.document.getElementById('image');
var dt = new.Date();
var hour = dt.getHours();
msg.innerHTML = 'Now it is ${hour} hours.';
if (hour>= 0 && hour < 12) {
img.src = 'img/morning.png';
} else if (hour => 12 && hour < 18) {
img.src = 'img/afternoon.png';
} else {
img.src = 'img/night.png';
}
}
PS: I've tried running it on Mozilla and Chrome. No success.
The error appears to be with this line:
var dt = new.Date();
To instantiate a new Date object, you need to use this syntax:
var dt = new Date();
Once this syntax error is fixed, then the JS file should be loaded properly and then the onload attribute will be able to fire the load function.
Here's a working demo: https://codesandbox.io/s/stack-overflow-onload-8opgp?file=/script.js
I am a fan of the timepicker from this SO answer but can't get it to work in a project where input elements are created dynamically. Problem seems that this timepicker needs to store the object returned by the constructor. Ideally, timepicker should work like the datepicker from jQuery-UI. So I tried to be clever and before creating a jQuery plugin I tried to make a javascript class like this:
function MyTimePicker(inputelement) {
// store the timepicker object
this.mytimepicker = new TimePicker(inputelement);
// show picked time in the element
this.mytimepicker.on('change', function (evt) {
var value = (evt.hour || '00') + ':' + (evt.minute || '00');
evt.element.value = value;
});
}
and use it like this on three input elements:
var dummy1;
var dummy2;
var dummy3;
window.onload = function () {
dummy1 = new MyTimePicker(jQuery('#time2').get(0));
dummy2 = new MyTimePicker(jQuery('#time3').get(0));
dummy3 = new MyTimePicker(jQuery('#time4').get(0));
};
It doesn't work. The timepicker popup appears when clicking in each of the input elements, but the on(change) event is never called so that the picked time does not show in the input element.
Either because of not having enough experience with Javascript objects, or with using this timepicker.
Update: I improved my code with a proper prototype, here is the complete code, completely standalone to play with:
<!DOCTYPE html>
<html>
<head>
<title>Timepicker class, standalone, by Jonatas Walker</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
<!-- source: https://github.com/jonataswalker/timepicker.js SO: https://stackoverflow.com/a/36758501/1845672 -->
<link href="//cdn.jsdelivr.net/timepicker.js/latest/timepicker.min.css" rel="stylesheet">
<script src="//cdn.jsdelivr.net/timepicker.js/latest/timepicker.min.js"></script>
</head>
<body>
<div id="arrayoftimes">
<input id="time2" type="time" placeholder="Time HH:MM"><br />
<input id="time3" type="time" placeholder="Time HH:MM"><br />
<input id="time4" type="time" placeholder="Time HH:MM"><br />
</div>
<script>
// Javascript Class. this disturbs the above reference application of TimePicker. It probably is not re-entrant.
//constructor
function MyTimePicker(selector) {
this.mytimepicker;
this.init(selector);
}
//prototype
MyTimePicker.prototype = {
init: function (selector) {
var inputelement = jQuery(selector).get(0);
this.mytimepicker = new TimePicker(inputelement);
// show picked time in the element
this.mytimepicker.on('change', function (evt) {
var value = (evt.hour || '00') + ':' + (evt.minute || '00');
evt.element.value = value;
});
}
};
</script>
<script>
var dummy1;
var dummy2;
var dummy3;
window.onload = function () {
dummy1 = new MyTimePicker('#time2');
dummy2 = new MyTimePicker('#time3');
dummy3 = new MyTimePicker('#time4');
};
</script>
</body>
</html>
Now the first input element works OK, but the picked time value goes into all three input elements. The other two inputs do show the timepicker dialog, but the picked value does not appear.
In the Firebug console, after picking the first time, I see two errors in the timepicker.js: TypeError: active is undefined.
Could that indicate that, somehow, the timepicker internal code is not re-entrant?
Or am I doing something wrong with object oriented javascript?
Update:
I am pretty sure that there is a bug in timepicker.js. I will report here as soon as I find it.
With gforce301 helping me to read the docs, I came to this solution to turn the timepicker into a jQuery plugin. This code has test code and is stand-alone, and contains checkboxes to select or deselect inputs for the timepicker.
The plugin is at the end of this code.
Working: you can add more inputs with the timepicker. Test this with selecting more checkboxes.
Not working: you cannot remove a timepicker from an input. If you deselect a checkbox, the related input will not be listed in the new target list passed to the setTarget() method, but the timepicker keeps working on the deselected input.
<!DOCTYPE html>
<html>
<head>
<title>Test of Timepicker class, standalone, by Jonatas Walker</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
<!-- source: https://github.com/jonataswalker/timepicker.js SO: https://stackoverflow.com/a/36758501/1845672 -->
<link href="http://cdn.jsdelivr.net/timepicker.js/latest/timepicker.min.css" rel="stylesheet">
<script src="http://cdn.jsdelivr.net/timepicker.js/latest/timepicker.min.js"></script>
<style>
.timepicker {background-color: yellow;}
</style>
</head>
<body>
<div id="arrayoftimes">
Time 1
<input type="checkbox" onclick="settimeclass(this, '#time1')" />
<input id="time1" type="text" placeholder="Time HH:MM"/>
<br />
Time 2
<input type="checkbox" onclick="settimeclass(this, '#time2')" />
<input id="time2" type="text" placeholder="Time HH:MM"/>
<br />
Time 3
<input type="checkbox" onclick="settimeclass(this, '#time3')" />
<input id="time3" type="text" placeholder="Time HH:MM"/>
<br />
<br />
ID's with timepicker: <span id='msg'></span>
</div>
<script> //this code is specific for this particular page
// at page load, uncheck all checkboxes
$('input:checkbox').prop('checked', false);
$('input:text').val('');
// when (un)checking a checkbox, adjust the timepicker class on each time input
function settimeclass(self, id){
if ($(self).prop('checked')){
$(id).addClass('timepicker');
}else{
$(id).removeClass('timepicker');
}
// apply the new jquery plugin for the timepicker
$('.timepicker').timepicker();
}
</script>
<script> // this code could be moved to a library
// jquery plugin for Jonatas's timepicker
(function ( $ ) {
// create time picker object
var _timepickerobj = new TimePicker([]);//([...], {lang:'en', theme:'dark'});
// attach event for formatting the time
_timepickerobj.on('change', function(evt) {
var value = (evt.hour || '00') + ':' + (evt.minute || '00');
evt.element.value = value;
});
// set timepicker target to jquery selector
$.fn.timepicker = function() {
var sel_array = this.toArray();
//_timepickerobj.target = [];// no effect
_timepickerobj.setTarget(sel_array);
// debugging: list time input id's with timepicker
var sel_ids = $.map(sel_array ,function(sel) {return sel.id;});
$('#msg').text(sel_ids);
return this;
}
}( jQuery ));
</script>
</body>
</html>
This plugin is good enough for my project, but it would be nice if someone could improve, e.g. on removing a timepicker from an input.
I'm trying to input a date selector tool so that a survey respondent can input a date by clicking on the field, a calendar will pop up, they can select the date, and the date will be inputted to the Qualtrics question text box.
Qualtrics has their own calendar tool available, but the issue is that the calendar is always visible. I only want the calendar to be visible when they either click the text box itself or a calendar icon (either would be fine). Here's the Qualtrics code:
Enter a date:
<link href="https://ajax.googleapis.com/ajax/libs/yui/2.9.0/build/calendar/assets/skins/sam/calendar.css" rel="stylesheet" type="text/css" /> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/yui/2.9.0/build/yahoo-dom-event/yahoo-dom-event.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/yui/2.9.0/build/calendar/calendar-min.js"></script> <script>
Qualtrics.SurveyEngine.addOnload(function ()
{
var qid = this.questionId;
var calid = qid + '_cal';
var y = QBuilder('div');
$(y).setStyle({clear:'both'});
var d = QBuilder('div',{className:'yui-skin-sam'},[
QBuilder('div', {id:calid}),
y
]);
var c = this.questionContainer;
c = $(c).down('.QuestionText');
c.appendChild(d);
var cal1 = new YAHOO.widget.Calendar(calid);
cal1.render();
var input = $('QR~' + qid);
$(input).setStyle({marginTop: '20px',width: '150px'});
var p =$(input).up();
var x = QBuilder('div');
$(x).setStyle({clear:'both'});
p.insert(x,{position:'before'});
cal1.selectEvent.subscribe(function(e,dates){
var date = dates[0][0];
if (date[1] < 10)
date[1] = '0' + date[1];
if (date[2] < 10)
date[2] = '0' + date[2];
input.value = date[1] +'-'+date[2]+'-'+date[0];
})
});
</script>
Here's the calendar tool that I'd like to use, but I can't figure out how to get the date to feed into the Qualtrics field text box.
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery UI Datepicker - Default functionality</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
$( function() {
$( "#datepicker" ).datepicker();
} );
</script>
</head>
<body>
<p>Date: <input type="text" id="datepicker"></p>
</body>
</html>
Your problem is that in Qualtrics $ refers to prototypejs, not jQuery. So, you need to do something like:
$j = jQuery.noconflict();
$j( function() {
$j( "#datepicker" ).datepicker();
} );
However, that may not work if the datepicker code is itself using $ to refer to jQuery.
I've used https://github.com/joshsalverda/datepickr successfully with Qualtrics.
EDIT:
To implement datepickr in Quatrics:
Add datepickr script to Qualtrics header (you can upload the file to Qualtrics then get the url of the file to add to the header in a script tag)
Add datepickr CSS to Qualtrics custom CSS
Add JavaScript to your question to add datepickr to an input element (e.g., datepickr($(this.questionId).down('.InputText')), {dateFormat: 'm/d/Y'});
Add this JavaScript to the field to use a plain HTML date input (no jQuery required).
Qualtrics.SurveyEngine.addOnload(function() {
var textInputs = this.questionContainer.querySelectorAll('input[type="text"]');
if (typeof textInputs[0] !== 'undefined') {
textInputs[0].type = 'date';
}
});
This is similar to the messages app on an iphone, where newer text messages you get will simply show you the time in a format like 9:55 PM, but once they are a day old it says Yesterday, and anything older than a day says the day of that week Monday, Tuesday, etc, anything older than that week just displays that date like 12/22/2014.
I've been able to successfully format my timestamps using the date filter:
{{message.timestamp | date:"h:mm a" }}
What would work best for something like this, a custom filter? Is it possible purely in angular?
You can use moment.js date library with angular filter to achieve that. moment has various standard formatting expressions available. Take a look at the documentation.
Include moment.js in your application, you can download it or refer to a cdn location. Example:
//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min.js
Create a filter:
.constant('moment', window.moment) //Save moment in constant for ease of dependency injection
.filter('dateMoment', ['moment', function(moment){
return function(input){
//Return formatted date
if(!input) return '_';
return moment(input).calendar();
}
}]);
Use the filter with the binding:
{{message.timestamp | dateMoment }}
Demo
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, moment) {
var currDt = new Date();
$scope.messages = [{
message: 'message1',
date: currDt
}, {
message: 'message11',
date: (new Date(currDt)).setDate(currDt.getDate()-1)
}, {
message: 'message3',
date: (new Date(currDt)).setDate(currDt.getDate()-3)
}, {
message: 'message4',
date: (new Date(currDt)).setDate(currDt.getDate()-4)
}, {
message: 'message5',
date: (new Date(currDt)).setDate(currDt.getDate()-5)
}, {
message: 'message2',
date: (new Date(currDt)).setDate(currDt.getDate()-30)
}]
}).constant('moment', moment).filter('dateMoment', ['moment',
function(moment) {
return function(input) {
return moment(input).calendar();
}
}
]);
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="moment.js#*" data-semver="2.8.3" src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min.js"></script>
<script data-require="angular.js#1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-repeat="msg in messages">{{msg.message}} ---- {{msg.date|dateMoment}}</div>
</body>
</html>