How to use HTML to validate a date range? - javascript

Alternatively, is it possible to validate against another field's value with HTML?
A common example would be selecting a date range where "from" date should be less than or equal to "to" date. The following would described the desired relationship between the values, if only you could use element references in syntax:
<input type="date" name="from" max="to"> //todo: populate with ~to.value
<input type="date" name="to" min="from"> //todo: populate with ~from.value

It's possible to utilize html5 validation mechanism with some javascript to dynamically update min/max attributes:
//in this case a single input restriction is sufficient to validate the form:
$('#from, #to').on('change', function(){
$('#to').attr('min', $('#from').val());
});
Fiddled. Both min and max could be applied to the respective fields for enhanced UX if browser implementation of a datepicker respects range limitations (by disabling dates outside of the desired range)

Here, Web Components are very useful, however they are not full supported in all browsers yet .
The idea is to create a simple html Element, with two children (from and to) as the following:
<div id="fromToDate">
<div></div>
<div></div>
</div>
then create a template, which defines how the date picker should look:
<template id="fromToDateTemplate">
<label for="fromDate">from</label>
<input type="date" class="fromDate" select=":first" required="" />
<label for="toDate">to</label>
<input type="date" class="toDate" select=":last" required="" />
</template>
the select parameter defines, where the value is taken from so the first input field takes the first div from the "#fromToDate".
Last we have to populate the "shadow root" and define the logic:
var shadow = document.querySelector('#fromToDate').webkitCreateShadowRoot(),
template = document.querySelector('#fromToDateTemplate');
shadow.appendChild(template.content);
shadow.querySelector(".fromDate").addEventListener("change", function (e) {
var to = this.value;
shadow.querySelector(".toDate").setAttribute("min", this.value);
});
template.remove();
In the end two input fields are renderd and when selecting a date in the first datepicker, the second datepicker can't pick any lower data.
Fiddler example: http://jsfiddle.net/cMS9A/
Advantages:
Build as widget
Easy to reause
won't break pages
can be styled independently
Disadvantages:
Not supported in all browsers yet
Future reading:
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/
https://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html

If you want to avoid issues with someone hacking / crashing yor site - validate input data with:
(optional) javascript before sending a form (protects against malforming data using javascript, inputting incorrect one, reduces traffic)
(mandatory) on server side (protects against more clever guys that might malform input data using fiddler for example)
This is the only (at least second point) approach that protects you and your site.

It's great to see things moving towards a pure HTML solution ... but why not take a look at using moment.js to fill in the gaps for the time being?
http://momentjs.com/
There are plenty of good examples there and a lot of useful utility methods.

I'm worry, that there's no chance how to validate a input value based on other input value. Only good old javascript.
But maybe you can use <input type="range" …> and set some minimal step (1 day / 1 hour / …). Then you can use min and max value by same-named attributes.

Related

Is it possible to limit max-date on keyup?

Summary: I have 5 text inputs, one of which is using the Date attribute. I'm adding validation to the inputs, and one feature I would like to add is to limit the max date. I know I can do this in HTML, however it looks like that only works for the calendar functionality. My thoughts are using keyup, so the user is unable to exceed the year 2050 (for example) within the input in real time.
Effort: I looked into the Max attribute in HTML for a while, but it looks like I will have to do this manually in either Js or jQuery. My immediate thought is to pull the value from the input, slice the last 4 integers, and then create text validation from that.
I would rather use a text input and create the entire validation myself, but I would like to keep the calendar functionality without using any external resources. I'm curious if there is a simpler or more efficient way of doing this?
<input type="date" class="search__input" id="adv-input-2" placeholder="MM / DD / YY" max="2050-12-31"></span>
I've also noticed that using keyup is actually not firing when I use it on a date input, until the entire date is inputted:
// sets limits for date input
$('#adv-input-2').keyup(function(e) {
let input = $(this);
});
For example, 10/DD/YYYY will result in value: "" until the entire field is completed.
If you want to do this manually then you can use change event instead of keyup like this way.
// sets limits for date input
$('#adv-input-2').change(function(e) {
let input = $(this);
console.log(input.val());
if(input.prop('max') < input.val()) {
input.val('');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<input type="date" class="search__input" id="adv-input-2" placeholder="MM / DD / YY" max="2050-12-31"></span>

Is it possible to limit the number of autocomplete-box rows?

As you know, autocomplete attribute is used for <input>s by default. Something like this:
Ok, I can totally remove that attribute by setting it off:
<input type="email" name="email" autocomplete="off">
// ^^^^^^^^^^^^^^^^^^
But I don't want disable it completely. I just want to limit it to two rows. Currently it is six rows. Anyway, Is there any solution (even by JS) to limit the number of that box's rows?
You can specify array of autocomplete options using jQuery.
$("#email").autocomplete({
source: function(request, response){
var results = $.ui.autocomplete.filter(yourAutocompleteArray, request.term);
response(results.slice(0, NUMBER_OF_ROWS_YOU_WANT));
}
});
As #SoftwareEngineer171 mentioned, you could using jQuery UI as a solution if you need that kind of control which is not available in HTML5 input control.
Link for example

Multi Dates Picker Bug?

I've been trying to add a date picker to my site that allows users to pick multiple non-concurrent dates. Multidatespicker appears to do what I want but i've got to a point where I think I have discovered a bug, particularly with it's AltField, which is confirmed here. The bug seems to stop the altfield's values showing. If you visit the Multidatespicker demo and inspect the altfield you'll see that while it appears empty the values are showing in the code.
The issue this presents for me is that I can't edit previously selected dates when returning a record from my App/DB. When passing the value of altfield back to my Rails App for database storage I only receive the hidden values shown in the code.
If I can get the altfield to correctly show these values and allow me to edit them via the date selector, then I should be amend within my app's backend.
Note the suggested fix on the github link above does not solve this issue - it only enables rendering dates in 'dateVar' as being selected in the picker....it does nothing to show values in altField.
Has anyone used this and had the same problem and solved it?
Does anyone know how to fix it?
OR
Can anyone suggest a good alternative that will work nicely with a Rails 3 App using Twitter Bootstrap. It's very important that i'm able to select multiple non-concurrent dates. I've searched quite extensively but MultiDatesPicker seems to be one of the only options I can find.
The problem is that Multidatespicker is not listening #altField so we need to create our own listener to add/remove dates.
The idea is to add values to a hidden or readonly input and add/remove dates by an other. This prevent the customer to add dates in #altField and getting them overwritten by the plugin.
HTML
<input type="text" id="date">
<button type="button" id="addDate">Add dates</button>
<button type="button" id="removeDate">Remove dates</button>
<div class="ui-state-error" id="error"></div>
<br />
<input type="text" id="altField" readonly value="2013-08-30,2013-08-31">
JAVASCRIPT
And with javascript we simply add the date with a button (could be on keyup or anything your imagination can imagine :)
var dates = $('#altField').val().split(',');
$('#datepicker').multiDatesPicker({
dateFormat: "yy-mm-dd",
addDates: dates,
altField: '#altField'
});
$('#addDate, #removeDate').on('click', function() {
try {
var $date = $('#date');
var addOrRem = $(this).attr('id') === "addDate" ? 'addDates' : 'removeDates';
$('#datepicker').multiDatesPicker(addOrRem, $date.val());
$date.val('');
} catch (e) {
var $error = $('#error');
$error.html(e).slideDown();
setTimeout(function() {
$error.slideUp();
}, 2000);
}
});
jsFiddle
I have scanned the source of MultiDatesPicker. I don't find any method which set the date from the #altfield. So it is not a bug it is missing.
I also do not understand the difference between the preselected dates and the altfield.
I think you can do what you want with a combination of preselect and the altfield:
html
<div id="with-altField"></div>
<input type="text" id="altField" value="08/22/2013,08/21/2013">
</div>
javascript
//first read the values of the #altfield
var dates = $('#altField').val().split(',');
//second set your multiDatesPicker with the dates of step 1 and an altfield
$('#with-altField').multiDatesPicker({
dateFormat: "mm/dd/yy",
addDates: dates,
altField: '#altField'
});
nb load the javascript on document ready

HTML/JS Form with calculations then output result as PDF

I would like to make a form in HTML where a user enters some data, and via JS that data is used to calculate results that are output to result fields in real time. By that I mean that say I enter Age (24) and Height (1.82m), a field will automatically display the result of 24 * 1.82 after the 1.82 is typed.
Also I would like to know how to output a web page as PDF.
First question :
function calc() {
var a = parseFloat(document.getElementById('field1').value);
var b = parseFloat(document.getElementById('field2').value);
document.getElementById('total').value = a * b;
}
This gets the values from 2 fields (field1 and field2), multiplies them together and then updates the value of the total input. Example HTML used with the above would be :
<input id="field1" onblur="calc()" value="24" />
<input id="field2" onblur="calc()" value="1.82" />
<input id="total" value="" />
the onblur attribute calls the specified function (calc()) when the input looses focus. Note that this is a very simple example and contains no error checking (ie there is a number present etc)
Second question :
For creating PDFs from HTML wkhtmltopdf is the best I have used - its simple to use and has lots of wrappers for different languages (server side - not client side). It runs as a standalone application too (on a server). Oh and its free !
You will have to input fields, add an event listener that is being triggered when the content changes and then simply fill the "result" input with the result. With the use of jQuery this will be very simple.
For generating pdf's in Javascript take a look at this libary:
http://code.google.com/p/jspdf/

javascript cannot call an element in array

Ok, let me explain more... the goal is to make the checkbox checked if there's a change on select. The actual code was:
function checkit(date)
{
document.forms[0].date.checked = true;
}
<input type="checkbox" name="date[]" value="2008-08-14">Aug 14, 2008<br>
<select name="slot[]" size="1" onchange="checkit(date[]);"/>
<option value="2008-08-15;0900;1700">9am to 5pm</option>
<option value="2008-08-15;1330;1730">1:30pm to 5:30pm</option>
</select>
<input type="checkbox" name="date[]" value="2008-08-15">Aug 14, 2008<br>
<select name="slot[]" size="1" onchange="checkit(date[]);"/>
<option value="2008-08-15;0900;1700">9am to 5pm</option>
<option value="2008-08-15;1330;1730">1:30pm to 5:30pm</option>
</select>
<input type="checkbox" name="date[]" value="2008-08-16">Aug 14, 2008<br>
<select name="slot[]" size="1" onchange="checkit(date[]);"/>
<option value="2008-08-15;0900;1700">9am to 5pm</option>
<option value="2008-08-15;1330;1730">1:30pm to 5:30pm</option>
</select>
In PHP, if it sees a variable with [ ], it automatically creates an array. In Javascript, I expected that Javascript would recognize the [] and execute based on the current element. For example, if I select a value in the second checkbox, it should fire an event to check that element box. I don't want to name the variable like date1, date2, date3, date4... I hope this clarifies more. I know I am missing out something... I tried "this" keyword to make it "this current element" but it doesn't seem to work but it could be that I used the improper syntax.
What I expected was that onchange event, it should fire its argument which is "date[]" but I would assume that Javascript should know which element in date[] it will use instead of expliciting calling it date[1] and so on. The checkit function gets the "date[]" name and checks that date[] checkbox.
BTW, many thanks for the supplementary answers (I learned something new!)
It doesn't work because (as dreas said) your HTML-code has errors and you are naming your variables in a way that conflicts with javascript syntax.
The name of your input is date[1] and the [ and ] have special meaning in javascript code.
In this code:
document.forms[0].date.checked = true;
you are trying to access the documents first form (document.forms[0]) and then tries to access a field called date, but there aren't any. According to your HTML-markup you have fields called "date[1]", "date[2]" and "date[3]".
But you can't access them like this:
document.forms[0].date[1].checked = true;
Why? Because date[1] tries to index the date with 1, and in this case your date is not an array.
You can access it if you enclose it in quotes:
document.forms[0]["date[1]"].checked = true;
Note that now "date[1]" is used as a string.
What exactly are you trying to do with this code ?
According to your piece of code (which has some syntax errors), you are checking a checkbox, then calling a js function that will check the checkbox again...?
What exactly are you trying to achieve?
Try this code:
function checkit(date)
{
var date = document.getElementById(date);
date.checked = true;
}
<input type="checkbox" id="date[1]" value="2008-08-14" onchange="checkit('date[1]')");/>Aug 14, 2008<br />
<input type="checkbox" id="date[2]" value="2008-08-14" onchange="checkit('date[2]')");/>Aug 14, 2008<br />
<input type="checkbox" id="date[3]" value="2008-08-14" onchange="checkit('date[3]')");/>Aug 14, 2008<br />
PHP has the syntax arr[] = something to put something at the next available index in an array.
Javascript doesn't have that syntax; if you want to put something at the next available index in an array use arr.push(something) instead.
But the portion of your example you're referring to is in HTML, not Javascript. Javascript accesses it but the form fields themselves are created in HTML... so you have to give it your own name rather than an automatically-incremented name.
If you are creating the HTML dynamically through DOM calls (e.g. for each input element, document.createElement('input'), assign attributes and then appendChild() to the main form), then you could automatically name the form fields... but that's a whole other method of generating HTML & has a bunch of pitfalls to watch out for.
First, you're wanting to use a PHP-specific feature in Javascript. No, there is no such feature so far as I can tell.
Second, I'd strongly advise not using HTML input names like "date[1]" ... that might be legal HTML (I'd have to try it in a few browsers to be sure it was effectively allowed), but it is almost 100% a likely source of errors in the maintenance cycle.
I'm assuming this code is either auto-generated for you or you just want to take a blok and copy/paste in your editor. If it is the former, I'd name the elements "date_1" in the autogen code and be done with it. If the latter then you can either maintain the number in your code (ie, manually type in date_1 through date_257) or use a Javascript document.write call to generate the HTML with less effort. I'd ONLY do the latter (document.write out HTML) if there is really no other way. If you're talking about 10-25 copies, handling this manually by hand is less likely to have a problem than using document.write; if you have more than 25 such instances then maybe it makes sense to automate the element generation.

Categories