Enable Datepicker only when first field has a value - javascript

Right now, the End Date selection is disabled. I want to only enable this when a Start Date is selected.
if( $('#datepicker1').val().length === 0) {
$('#datepicker2').datepicker("disable");
} else {
$('#datepicker2').datepicker("enable");
}
This clearly does not work. If I insert value = 'random date' into my first input field, it works fine. I'm not too sure on how do this. Clearly not as easy as I had hoped.
My other problem, or hope, is to disable the dates including and before the first selection.
You know, pick Start Date, and every date before and said date for the next picker would be disabled. But that is a whole other problem.

You can use something like this:
var end = $('#end').datepicker();
// Defining a function, because we're binding this to two different events
function enableEnd() {
end.attr('disabled', !this.value.length) // Enable the end input element if the first one has anything in it
.datepicker('option', 'minDate', this.value); // Set the minimum date to the date in the first input
}
$('#start').datepicker({
onSelect: enableEnd // Call enableEnd when a date is selected in the first datepicker
}).bind('input', enableEnd); // Do the same when something is inputted by the user
It's not really a good idea to enable the datepicker in the second field only after the first has been filled in, because the user can still add things into the second field manually, and you lose the format validation usually offered by jQuery UI datepicker. Instead, we disable the second input element directly.
See it working here: http://www.jsfiddle.net/yijiang/KwhLw/
Also note that we're using the input event here, because although it has less broad compatibility, is better than the usual methods used for keyboard event capturing. See a full discussion on this here: http://whattheheadsaid.com/tag/oninput

Just try this approach -
$('#datepicker1').datepicker({
//your other configurations.
onSelect: function(){
//enable datepicker 2 over here.
}
});

I would use the getDate method and see if it's null (nothing selected/entered), like this:
if($('#datepicker1').datepicker("getDate") === null)
For the other issue, check out the date range demo for the datepicker, it has a start/end date like you're aiming for.

Well, question is answered. For those who want to know what I have, here it is.
To change a Start Date and an End Date (A date range if you will) into an array of individual dates, I used this:
function createDateRangeArray($strDateFrom,$strDateTo) //Changes a Range of Dates to Specific Dates
{
static $aryRange = array(); //Creates an Array
$iDateFrom = mktime(1,0,0,substr($strDateFrom,5,2), substr($strDateFrom,8,2),substr($strDateFrom,0,4));
$iDateTo = mktime(1,0,0,substr($strDateTo,5,2), substr($strDateTo,8,2),substr($strDateTo,0,4));
if ($iDateTo >= $iDateFrom)
{
array_push($aryRange,date('Y-m-d',$iDateFrom)); // first entry
while ($iDateFrom<$iDateTo)
{
$iDateFrom += 86400; // add 24 hours
array_push($aryRange,date('Y-m-d',$iDateFrom));
}
}
return $aryRange; //Returns to step 1 and adds another value into the array
}
To get every date from my SQL Database and push them into a single array, this was used:
$query = "SELECT startdate, enddate FROM classdetails";
$results = mysql_query($query);
while ($arrays = mysql_fetch_array($results))
{
$aryDates = createDateRangeArray($arrays['startdate'],$arrays['enddate']);
echo "<br />";
}
So now I have managed to get every date range from an entire list of classes and made one huge array.
Now I had to use this array to actually disable the dates. Using the functions of which Yi Jiang has no generously wrote (thank you to everyone who helped me), the next step is:
$(function()
{
//To enable End Date picker only when Start Date has been chosen (And to disable all dates prior of said date)
var end = $('#enddate').datepicker( {numberOfMonths: 3, beforeShowDay: checkAvailability,});
// Defining a function, because we're binding this to two different events
function enableEnd() {
end.attr('disabled', !this.value.length) // Enable the end input element if the first one has anything in it
.datepicker('option', 'minDate', this.value); // Set the minimum date to the date in the first input
}
//End of function
// Datepicker
$('#startdate').datepicker({
numberOfMonths: 3,
beforeShowDay: checkAvailability,
onSelect: enableEnd // Call enableEnd when a date is selected in the first datepicker
}).bind('input', enableEnd); // Do the same when something is inputted by the user
//hover states on the static widgets
$('#dialog_link, ul#icons li').hover(
function() {$(this).toggleClass('ui-state-hover');}
);
});
//End of Function
//Disabling all dates where selected room and speaker is unavailable
var $myBadDates = new Array (<?php foreach($aryDates as $disabledate) { echo " \"$disabledate\","; } echo " 1"; ?>); //Creates the array (The echo " 1"; is merely to close the array and will not affect the outcome
function checkAvailability(mydate){
var $return=true;
var $returnclass ="available";
$checkdate = $.datepicker.formatDate('yy-mm-dd', mydate);
for(var i = 0; i < $myBadDates.length; i++)
{
if($myBadDates[i] == $checkdate)
{
$return = false;
$returnclass= "unavailable";
}
}
return [$return,$returnclass];
}
//End of function
The only thing in my body right now, for testing purposes, are:
<!-- Datepicker -->
<h2 class="header">Datepicker</h2>
<span>
Start Date: <input type="text" id="startdate" />
</span>
<span>
End Date: <input type="text" id="enddate" disabled="disabled" />
</span>
It's long, yes, but it works. Thank you to everyone who helped me get this working.
The edit was me changing a function to a JQuery function that exists (of which for some reason I did not use in the first place); toggleClass. Thanks for picking that out.

Related

How to compare two full year dates

The idea in my example is to allow user to select only the year in to input already selected in from input (have the same year in from and to date input).
The issue here is that it works fine when we use the date picker but, when we hit manually the date into 'to' input, it compare juste the first number of the year ***8/04/14, I want to wait until the user finish the full date example 2018/04/14 then I alert OK. I the actual code, if I take the example : from = 2018/04/14, to = 2018/05/29, So it compare 2018/04/14 with from = 8/05/29, it alert ok in the 8 of 2018 and not in the complete year.
$("#from").on("change", function() {
year();
var from = $("#from").val();
if (from) {
var maxYear = new Date(from).getFullYear();
$("#to").attr("max", maxYear+"-12-31");
$("#to").attr("min", maxYear+"-01-01");
}
});
$("#to").on("change", function(){
year();
});
function year() {
var from = $("#from").val();
var to = $("#to").val();
if(from && to && new Date(from).getFullYear() != new Date(to).getFullYear()) {
$("#to").val("");
alert("OK");
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="from">from</div>
<input id="from" type="date">
<div class="to">to</div>
<input id="to" type="date">
Try using
$("#to").on("blur", function(){
year();
});
That should active the check only after the input loses focus.
Change event is triggered when input change, if you want catch user event, or key event you should try to declare all "change code" as stand alone functions and add another eventListener.
Maybe with blur or key down will work as you want but lot of event exist : https://www.w3schools.com/jsref/dom_obj_event.asp

Gray out all but certain dates on Bootstrap datepicker

I'm setting up a datepicker, but I only want the user to be able to select dates from a pre-determined date array I have populated. These are dates where relevant events happened. Nothing happened on the other dates outside of the array.
Below is an example array that I would have.
dateArr = ["2015-10-27", "2015-10-29", "2015-11-10", "2016-11-30", "2016-12-07", "2017-06-29", "2017-06-30", "2017-10-23", "2017-12-13", "2018-03-27", "2018-03-29", "2018-03-30", "2018-03-31", "2018-04-02", "2018-04-07", "2018-04-08", "2018-04-09"]
I've looked at other examples, but none seem to do what I'm trying to do. The array dates would be selectable, and the rest would be grayed out.
Try with below Jquery code:
HTML Code:
<div id="datepicker"></div>
Jquery Code :
jQuery(function(){
var enableDays = ["7-8-2019", "13-8-2019"];
function enableAllTheseDays(date) {
var sdate = $.datepicker.formatDate( 'd-m-yy', date)
console.log(sdate)
if($.inArray(sdate, enableDays) != -1) {
return [true];
}
return [false];
}
$('#datepicker').datepicker({dateFormat: 'dd-mm-yy', beforeShowDay: enableAllTheseDays});
});
JFiddle Code Here:
http://jsfiddle.net/qampw1n5/

Execute function on second click in jquery

I have a calendar button that on click opens up a date picker and places the date into an input text box. What I want to happen, is have a second text box auto-fill with the date 30 days into the future. What I am having trouble with is getting this to work with jquery.
HTML:
<tr>
<td align = "center">Entry Date From: <input id="ENTRYDATEFROM" name="ENTRYDATEFROM" type="text" maxLength="10" size="12" value="">
<img height="20"src="calendarsrc" id="entrySrc"></td>
<td align = "center">Entry Date To: <input id="ENTRYDATETO" name="ENTRYDATETO" type="text" maxLength="10" size="12" value="">
<img height="20"src="calendarsrc" id="entrySrc2"></td>
</tr>
JQUERY:
$(document).ready(function() {
$("#entrySrc").click(function(){
gAnytime.fPopCalendar(document.myform.ENTRYDATEFROM);
});
$("#entrySrc2").click(function(){
gAnytime.fPopCalendar(document.myform.ENTRYDATETO);
});
//Tried this but had no success
//$(document).on("change", "#entrySrc", populate);
});
function populate(){
var q = $("#ENTRYDATEFROM");
var dateTo = new Date(q.val());
var newDate = new Date(dateTo.setDate(dateTo.getDate() + 30));
var formatted = padNumber(newDate.getUTCMonth() + 1) + '-' + padNumber(newDate.getUTCDate()) + '-' + newDate.getUTCFullYear();
$("#ENTRYDATETO").val(formatted);
}
function padNumber(number) {
var string = '' + number;
string = string.length < 2 ? '0' + string : string;
return string;
}
This is what my GUI looks like before anything is clicked:
This is what happens when I click the #entrySrc calendar button located to the right of the input text box
I can then click on any date that I wish within that calendar box. This will populate the input text box to the left of it.
How can I execute my populate function on/against that second click located within the calendar box?
There may be a very simple solution to this: simply fire the populate() method when #entrySrc changes.
$(document).on("change", "#entrySrc", populate);
or one of these alternatives:
$("#entrySrc").on("change", populate);
$("#entrySrc").change(populate);
note you're passing populate, not populate().
Based on the very poor documentation here: http://calendarxp.net/tutorials/flat/tutorials/PluginsSDK.htm I would guess you need to do the following:
Open your plugins.js file, which is apparently where to hook into a load of global functions (this control is sooooooo old).
Put your code into the fOnChange template (which I gather will be a nearly empty function):
///////////// Calendar Onchange Handler ////////////////////////////
// It's triggered whenever the calendar gets changed to y(ear),m(onth),d(ay)
// d = 0 means the calendar is about to switch to the month of (y,m);
// d > 0 means a specific date [y,m,d] is about to be selected.
// e is a reference to the triggering event object
// Return a true value will cancel the change action.
// NOTE: DO NOT define this handler unless you really need to use it.
////////////////////////////////////////////////////////////////////
function fOnChange(y,m,d,e) {
.... put your code here ....
return false; // return true to cancel the change.
}
What you put in there should be something of practical use. I would suggest generating a custom event like this:
function fOnChange(y,m,d,e) {
var $e = $(e.target); // (or e.originalTarget or whatever you can find with a debugger!)
$e.trigger("calchange");
return false; // return true to cancel the change.
}
This will require that jQuery is included before their js file.
In your code, listen for it like this for all calendars:
$(document).on('calchange', populate);

mootools datepicker set value from other datepicker

I have a mootools datepicker (Arian / monkeyphysics) with 2 date input fields.
I want to set the date of the 2nd field one day after the first one.
So far I have:
window.addEvent("domready", function(e){
new DatePicker('#arrival_date', { positionOffset: { x: -3, y: 5 }});
new DatePicker('#departure_date', { positionOffset: { x: -3, y: 5 },onShow: function(){test();}
});
function test(){
firstvalue = Date.parse($('arrival_date').value);
newvalue = firstvalue.increment(); //ad 1 day to first input date
console.log(newvalue); // Logs ok:Fri Jan 16 1970 22:24:11 ...
$('arrival_date').set('value', newvalue ); //doesn't work
$$('#departure_date').attach('#arrival_date'); //doesn't work
$$('#departure_date').select(newvalue ); //doesn't work
}
How to do? (set the date of the 2nd field one day after the first one.)
That version of DatePicker uses hided inputs. So what you see is not what your input has as value, it has a unix datestamp.
If you noticed the Date.parse($('arrival_date').value); was in the 70's, that's because javascript uses miliseconds and unix time is in seconds. To get the "real" day from the $('arrival_date').value you need to multiply by 1000. But you actually dont need that.
To make the second DatePicker get the day from the first you can use this:
onSelect: function (){
var depDate = $('departure_date');
if (depDate.value == ""){
depDate.value = $('arrival_date').value + 86400;
}
}
This will add one day to the first datepicker date if the second is empty. The thing is that you will not see the change until the you open the datepicker, so if you change the value programatically the user will not see. Which means that without the if, in case the user changes the first input again, you loose the second date and user doesn't notice, leading to frustration/bugs.

Changing the content of a <select option> in Javascript but previous selection stays, why?

I'm trying to do a simple script that checks a date and if "day chosen" == "tomorrow" then change a dropdown containing delivery options:
Drop down:
0-When?(selected)
1-AM
2-PM
If day = tomorrow then I remove in javascript the options:
Drop down:
0-When?
2-PM(selected)
The script:
// remove all options first
document.getElementById('inputheurelivraison').options.length = 0;
if (parseInt(datebits[2]) == parseInt(demain)){//remove am
document.getElementById('inputheurelivraison').options[0] = new Option("WHEN?", 0, false, false);
document.getElementById('inputheurelivraison').options[1] = new Option("PM", 2, true, true); // new Option(text, value, defaultSelected, selected)
alert ("<? echo t(73); ?>");
}
else {//put am
document.getElementById('inputheurelivraison').options[0] = new Option("WHEN?", 0, true, true);
document.getElementById('inputheurelivraison').options[1] = new Option("AM", 1, false, false);
document.getElementById('inputheurelivraison').options[2] = new Option("PM", 2, false, false);
}
The problem:
Let's say someone fill the form, then choose "AM" as the option and then change the date to "tomorrow", then my scripts run and remove the "AM" choice from the list and choose "PM" as "selected". When the user submit the form, the POST data is "AM" as selected...
Why? I chose "PM" and when I take a look at the HTML it says "PM" as "selected" so why does it not submit that value?
Thanks a bunch in advance
Joe
There is no need to remove all options first, you can remove only the ones you don't want. Something like the following should be suitable (note storage of reference to DOM element so only get once):
var doIt = (function() {
// Reference to removed option
var removedOption;
return function(s) {
// Get reference to select once
var select = document.getElementById('inputheurelivraison');
if (parseInt(datebits[2]) == parseInt(demain)) {
// Store reference to am option then remove it
removedOption = select.options[1];
select.removeChild(select.options[1]);
// Make pm selected (it's now index 1)
select.options[1].selected = true;
// Debug?
alert ("<? echo t(73); ?>");
} else {
// Replace removed option
select.insertBefore(removedOption, select.options[1]);
// Make first option selected
select.options[0].selected = true;
}
}
}());
Alternatively you can move the unneeded option to a hidden select element.
The above is just a proof of concept example, there are many ways to skin the cat, the bottom line is you don't have to delete all the options and recreate the ones you want every time.
Thanks for your answers. But I just found out what was the bug. I'll explain it in case it could help anybody else:
After checking if the "day" = "tomorrow" and changing the form, the script would then POST the data in AJAX to a PHP file. So here was the origin of the problem: I was asking my script to POST the selectedIndex of my dropdown instead of the option[selectedIndex].valueof it. For this reason, my script was returning "AM" as the choice even if "PM" was selected because selectedIndex always start at 0, 1, 2 etc. and my value were AM=1 and PM=2.
So I changed:
document.getElementById("inputheurelivraison").selectedIndex
for:
document.getElementById('inputheurelivraison').options[document.getElementById("inputheurelivraison").selectedIndex].value
when sending the POST value in AJAX and now it's fine.
Hope nobody else makes this error :)

Categories