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.
Related
I have a datepicker which the user can select a date from. When a date is selected, the input field is being filled with the right value, and it is displayed.
However, then submitting the form, the field posts empty data for that field, like it is only being displayed in the input field but it has no value.
I know it's really hard to describe this issue, so I'm attaching some images.
Here is the js code behind the datepicker itself:
<script>
$(document).ready(function () {
$('[data-toggle="datepickerFrom"]').datepicker({
format: 'dd-mm-yyyy'
});
// Available date placeholders:
// Year: yyyy
// Month: mm
// Day: dd
if (window.innerWidth < 768) {
$('[data-toggle="datepicker"]').attr('readonly', 'readonly')
}
});
</script>
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
I have a small javascript program that looks at the value in one select box (id_Decade for the decade) and adjusts the range of values in two other select (range of years for that decade). The html for the page is created by a Django 2.0 application. I am running jQuery as well.
One of the range of years select boxes (id_Date_year) works correctly - the decade is read from id_Decade, the range of years is created, the id_Date_year select boxes are populated correctly, and if there is a pre-selected year in id_date_year, that is preserved.
The problem the other select box, id_Approximate Date_year, does not preserve the pre-selected year value. The years for the decade are loaded correctly, but the pre-selected year is not selected again.
In this picture, it shows the page after loading. The initial decade is 1890, and the pre-selected year is 1894. Note how the Date select boxes have the year 1984 selected, but the Approximate Date boxes have Choose a year selected. Both select boxes have the correct range of years - 1890-1899.
If I change the decade to 1950, then the Date and Approximate Date selects are correct, since the selected year is 1894, and that is not in the decade of the 1950s. Both select boxes have the same range of years - 1950 to 1959.
Both select boxes use the same code. I know that a space is verboten in the id name of an element, but Django is creating that id value, and I have not found a way to change it.
Here is the code:
(function($) {
$(document).ready(function(){
console.log("Made it into update years from decade");
// Get the selected year if there is a Date field
var Date_years = $('#id_Date_year');
var selectedDateYear = Date_years.find(':selected').val();
console.log("selectedDateYear="+selectedDateYear);
// Get the decade selected
var decade1 = $('#id_Decade option:selected').text();
console.log("decade1="+decade1);
// get the years for that decade
newOptions = years_from_decade(decade1);
// update the date select box
update_options(newOptions, Date_years, selectedDateYear);
// Get the selected year if there is an Approximate Date field
var Approximate_years = $("[id='id_Approximate Date_year']");
var selectedApproximateYear = Approximate_years.find(':selected').val();
console.log("selectedApproximateYear="+selectedApproximateYear);
// update the date select box
update_options(newOptions, Approximate_years, selectedApproximateYear);
$('#id_Decade').change(function(){
// chang the years if the decade changes
var decade2 = $('#id_Decade option:selected').text();
console.log("decade2="+decade2);
newOptions = years_from_decade(decade2);
console.log("we have newOptions=");
console.log(newOptions);
update_options(newOptions, Date_years, selectedDateYear);
update_options(newOptions, Approximate_years, selectedApproximateYear);
})
// calculate the years for the decade
function years_from_decade(decade) {
console.log("we have a decade="+decade);
var newOptions = {};
base_year = parseInt(decade, 10);
for (i = 0; i < 10; i++) {
year = base_year + i;
key = year.toString();
newOptions[key] = key;
}
return newOptions;
}
// replace the options with new ones
function update_options(newOptions, target, selectedYear) {
console.log("update_options selectedYear="+selectedYear);
target.find('option:gt(0)').remove(); // remove all options, but not the first
$.each(newOptions, function(key, value) {
target.append($("<option></option>").attr("value", value).text(key));
console.log("value="+value+" selectedYear="+selectedYear);
if (value == selectedYear) {
console.log("got a match! value="+value);
target.val(value).change();
}
})
}
});
})(jQuery);
The console messages for both select boxes are the same. The matching of the pre-selected year works in both cases, but the id_Approximate Date_year select box does not get the pre-selected year selected, whereas the id_Date_year does.
Is this behavior related to the space in the id value? As you can see from my code, I am not an experienced js coder. I am sure there are much better ways to do what I want to do!
Thanks!
Mark
You are correct that you can not use a space in a jQuery selector. If this is what's causing your problem, you can get around it multiple ways:
Using plain JS and wrapping it with $() to convert it to jQuery object
$(document.getElementById('id_Approximate Date_year'))
Using attribute selector $("[id='content Module']")
Escaping the space $('id_Approximate\\ Date_year')
Demo examples:
$('#div one') .html('$(\'#div one\') Successful')
$(document.getElementById('div two')) .html('$(document.getElementById(\'div two\')) Successful')
$("[id='div three']") .html('$("[id=\'div three\']") Successful')
$('#div\\ four') .html('$(\'#div\\\\ four\') Successful')
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="div one">Unchanged</div>
<div id="div two">Unchanged</div>
<div id="div three">Unchanged</div>
<div id="div four">Unchanged</div>
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 :)
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.