The recent update (V 20.x) of Chrome has broken one of my forms with the new built-in date and time input type. I'm calling jQuery UI datepicker on a date field and it used to work perfectly prior to the update. After the update, Chrome overrides my placeholder and renders the jQuery UI widget unusable.
Any ideas of how I can prevent Chrome from messing up with my input fields without changing their type?
You have a couple of different options.
You could detect that the user is using Chrome by sniffing the user agent string and preventing click events.
if (navigator.userAgent.indexOf('Chrome') != -1) {
$('input[type=date]').on('click', function(event) {
event.preventDefault();
});
}
User agent sniffing is a bad idea, but this will work.
The ideal approach in my mind is to detect whether the browser supports a native datepicker, if it does use it, if not use jQuery UI's.
if (!Modernizr.inputtypes['date']) {
$('input[type=date]').datepicker({
// Consistent format with the HTML5 picker
dateFormat: 'yy-mm-dd'
});
}
Example - http://jsfiddle.net/tj_vantoll/8Wn34/
Of course since Chrome supports a native date picker the user would see that instead of jQuery UI's. But at least you wouldn't have a clash of functionality and the UI would be usable for the end user.
This intrigued me so I wrote up something about using jQuery UI's datepicker alongside the native control - http://tjvantoll.com/2012/06/30/creating-a-native-html5-datepicker-with-a-fallback-to-jquery-ui/.
Edit
If you're interested, I recently gave a talk on using jQuery UI's widgets alongside HTML5 form controls.
Slides
Video
To remove the arrow and spin buttons:
.unstyled::-webkit-inner-spin-button,
.unstyled::-webkit-calendar-picker-indicator {
display: none;
-webkit-appearance: none;
}
You can still active the calendar by pressing Alt+Down Arrow(checked on windows 10).
To disable, you need to add a little JavaScript:
dateInput.addEventListener('keydown', function(event) {
if (event.keyIdentifier == "Down") {
event.preventDefault()
}
}, false);
This works for me:
;
(function ($) {
$(document).ready(function (event) {
$(document).on('click input', 'input[type="date"], input[type="text"].date-picker', function (e) {
var $this = $(this);
$this.prop('type', 'text').datepicker({
showOtherMonths: true,
selectOtherMonths: true,
showButtonPanel: true,
changeMonth: true,
changeYear: true,
dateFormat: 'yy-mm-dd',
showWeek: true,
firstDay: 1
});
setTimeout(function() {
$this.datepicker('show');
}, 1);
});
});
})(jQuery, jQuery.ui);
I completely agree with TJ.
If you're doing any sort of editing, pre-filling, or dynamic setting of date values, you'll also need to know that as of 7/3/13 Chrome only honors the ISO standard date format (yyyy-mm-dd). It will display dates to the user in local format ('mm/dd/yy' for the US) but will ignore any values set in the HTML that are not ISO standard format.
To convert on page load, you can use TJ's user agent sniffer and do this:
if (navigator.userAgent.indexOf('Chrome/2') != -1) {
$('input[type=date]').each(function(){
var d = trim(this.getAttribute('value'));
if (d){
d = new Date(d);
var dStr = d.toISOString().split('T')[0];
this.value = dStr;
}
});
}
If, for example, you opt to disable the native datepicker and use jQuery's, you'll also need to set the date format to match Chrome's date field, or it won't display the input that the jQuery datepicker is sending it:
$('#myDate').datepicker({dateFormat: 'yy-mm-dd'});
Add those two things to the first option in TJ's answer and you have jQuery's datepicker working in Chrome without errors!
Relying on native datepickers is ideally the best solution. But when you need something that supports black-out dates, date ranges, or you just plain want it to look prettier, this will work.
Related
I want to take two date string with textbox or editor in mvc.
The format should be
"MM/yyyy-MM/yyyy".
I need to force the user for entering the input like above format without posting model.
#Html.TextBox("tbxDateRange", "", "{0:dd/MM/yyyy}", new { #class = "form-control dropdown", placeholder = "MM/yyyy - MM/yyyy" })
Above code not working event get just a formatted date string.
The format is working as expected. You are telling tbxDateRange's value (the zero in the third parameter ("{0:dd/MM/yyyy}") to format as day/month/year. It will therefore take the input in the text box and display it in that format.
It is only a display format. It will not enforce this format. For that you will need to do your own client side javascript (since you mentioned without posting the model). You could look at using a masked input element. ASP.NET MVC does not have a masked input out of the box.
You could use a masked input control like maskedinput which is a plugin for jQuery.
Additionally, you might want to look at breaking this up into two controls. One for the start and one for the end. You could consider using the html5 input type of date and you will automatically get a calendar. Although, if the day of the month will be too confusing for your users/UI then you could look at using jquery UI's datepicker and you can configure it to show only month and year.
Once you include jQuery UI in your app you would do something like jQuery UI DatePicker to show month year only.
In that example the winning answer formats the control in such a way to only show the month and year items of the control.
<script type="text/javascript">
$(function() {
$('.date-picker').datepicker( {
changeMonth: true,
changeYear: true,
showButtonPanel: true,
dateFormat: 'MM yy',
onClose: function(dateText, inst) {
$(this).datepicker('setDate', new Date(inst.selectedYear, inst.selectedMonth, 1));
}
});
});
</script>
<style>
.ui-datepicker-calendar {
display: none;
}
</style>
When I load my page the datepicker on my div always show in english, I have to click it to show in other language, as you can see in this fiddle: http://jsfiddle.net/bFHxf/
If you change from div to input there is no problem with it since you have to click it to show... is this some kind of feature or bug?
Any workaround?
I wrapped your code in the $(document).ready() function and that seems to take care of the problem.
http://jsfiddle.net/qtNyr/
Hope that helps!
I think that you are initializing the datepicker too early.
If you wait until the document is loaded, it should work. You can do this by surrounding the existing JavaScript code with
$(function() { existing code goes here });
So the result might look like:
$(function(){
$.datepicker.setDefaults( $.datepicker.regional[ "nl" ] );
$('#date').datepicker({
numberOfMonths: 2,
showButtonPanel: true,
dateFormat : 'dd/mm/yy'
});
})
Link to jsFiddle
I want to programmatically set date for the input with datebox control, For this i know i can use something like this
$(element).trigger('datebox', {'method':'set', 'value':'dateString'});
but this doesn't seem to update the control(i.e when i open the calendar, it is set to current date and not equal to the value in the input field)
EDIT:
based on JTsage's pointers i overwrote the default dateformat to mm/dd/yyyy, using sth like this.
jQuery.extend(jQuery.mobile.datebox.prototype.options.lang, {
'en': {
dateFormat: '%m/%d/%Y'
}
});
jQuery.extend(jQuery.mobile.datebox.prototype.options, {
useLang: 'en'
});
Then i tried setting the date using sth like this
$(element).trigger('datebox', {'method':'set', value:'07/02/2012'});
but this date is not appearing when i navigate to the page..Interestingly when i tried updating the date from firebug console(being on that page) it updated the field as well as datebox control.
I have no idea why this is happening..Need help, please respond JT
So finally i fixed the issue, by doing this
jQuery.extend(jQuery.mobile.datebox.prototype.options, {
'overrideDateFormat': '%m-%d-%Y',
'overrideHeaderFormat': '%m-%d-%Y'
});
setting the value of the input field explicitly
$(element).val('06-21-2012');
and then refreshing the datebox
$(element).trigger('datebox', {'method':'set', 'value':'06-21-2012'});
I found th solution, try this
$(element).trigger('datebox', { 'method': 'doset' });
I have a very simple html page with the following javascript in it
$(function() {
$( "#datepicker" ).datepicker({
changeMonth: true,
changeYear: true
});
$( "#datepicker" ).datepicker( "option", "dateFormat", "yy-mm-dd" );
});
Then I have the input target element
<input id="datepicker" type="text" class="boxtpl" name="${field.name}" value="${release?.startDate}">
and I see the html of the input from viewing source is valid...
<input id="datepicker" type="text" class="boxtpl" name="release.startDate" value="2012-02-07">
so when I do the GET request to get this page, my date ONLY renders if I delete that last line in the javascript that sets the format WHICH is very important as that is the format I have playframework configured for!!!!! If I don't set the format, the POST then breaks because formats don't match :(
Why is setting the format of datepicker clearing out my date????
I can try scripting more to set it manually though I tried calling the api to set it and that DID NOT work so it might not work doing raw javascript set either...not sure yet. anyone know why this occurs or better yet how to fix it???
thanks,
Dean
Not sure if it's a bug in jquery ui, but it seems that setting the format effectively deletes the default value. You can fix this with a chained
.datepicker("setDate", datepicker_default_val );
However, what I did in my web app was define a CSS class ".datepicker" then writing this code snippet provide date pickers to any with that class.
$( ".datepicker" ).each( function(index){
var datepicker_default_val = $(this).val();
$( this ).datepicker({numberOfMonths: 3, showButtonPanel: true});
$( this ).datepicker( "option", "dateFormat", 'yy-mm-dd' );
$( this ).datepicker("setDate", datepicker_default_val );
});
What this does is grabs every element with the tagged class, saves the default value to local var datepicker_default_val, sets the formatting, and then restores the value.
Little bit of a hack but put that in a $(document).ready(function(){ }); block and you should be good.
If the input field does not match the default dateFormat, it will simply delete it.
The option setting in the second line is too late then, after the first line it is already deleted.
Solution: Set the dateFormat in the first call:
$( "#datepicker" ).datepicker({
changeMonth: true,
changeYear: true,
dateFormat: "yy-mm-dd"
});
What do you mean by:
the POST then breaks because formats don't match
Also, I don't quite understand what you mean by your GET and POST requests? Do you mean the form methods? In such case you should amend your HTML code with the surrounding form tags and add a submit button so we can understand exactly what you want and try to reproduce the problem.
Anyway, see if this is what you want : http://jsfiddle.net/DAMEj/
Actually I just included the Jquery UI library in addition to their CSS for a full test of your code.
Besides, I don't get the purpose of these attributes name="${field.name}" value="${release?.startDate}", could you clarify?
And finally, what is it exactly that doesn't work for you?
EDIT:
So according to my last comment about the default date display, please check this out http://jsfiddle.net/sidou/ZUrPj/ and see if it fits your needs.
Happy JS fiddling ;)
If the input value is not parseable by jQuery, it will indeed delete the value from the input field (and even from the altField, if you set one).
For example, this might happen when using different locales. If you set the datepicker dateFormat to 'dd MM yy' and use French localisation, it will parse "10 Mars 2012", however a value of "10 March 2012" will get deleted.
In my case, i found than the JQuery was inyected by a "formoid" solution, soo, i just replace the function where the data was reinjected, adding the line
"value": date.attr("value")
I mixed with the Shaun answer too:
jQuery(".formoid-flat-blue").find('input[type=date]').each(function(){
var date = $(this);
var datepicker_default_val = $(this).val();
var text = $('<input type="text">');
text.get(0).className = date.get(0).className;
text.attr({
"name": date.attr("name"),
"placeholder": date.attr("placeholder"),
"required": date.attr("required"),
"value": date.attr("value")
});
date.replaceWith(text);
text.datepicker({
format: _dateFormat || date.attr("data-format") || 'yyyy-mm-dd'
});
if (datepicker_default_val) {
text.datepicker({
setDate: datepicker_default_val
});
}
});
I need to add custom validation(I think) for validating input from an user. Here's my use case:
I'm using the jquery ui datepicker for selecting dates, with localization like this:
$.datepicker.setDefaults( $.datepicker.regional[ currentLocale ] );
I use the bassistance validation plugin, and using rules for date:true and such does not work with different formats(or if they do please tell me how!). So I've made my own date validation methods like this
$.validator.addMethod("validDate", function(value) {
return parseDateString(value) != null;
}, jQuery.validator.messages.date);
This all works very well except for the fact when selecting a date in the datepicker the validation is fired before the value of the componet is changed! So I actually validate the previous value....
Does anyone have a solution for me?
Thanks in advance:)
You could trigger validation upon the user closing the datepicker popup:
$("#birthdate").datepicker({
onClose: function() {
/* Validate a specific element: */
$("form").validate().element("#birthdate");
}
});
Using validate's element() function will enable you to validate a particular field immediately.
I've created an example here in which any date who's year != 2011 will trigger failed validation.