Pickadate.js
github.com
github.com
This value is not what it says:
SECONDS_IN_DAY = 86400000,
That's the number of milliseconds in a day. Instead of a magic precalculated number, why not create all the relevant constants so the values become perfectly clear: HOURS_IN_DAY = 24,
MINUTES_IN_DAY = HOURS_IN_DAY * 60,
SECONDS_IN_DAY = MINUTES_IN_DAY * 60,
MILLISECONDS_IN_DAY = SECONDS_IN_DAY * 1000,
Personally, I find these kinds of string constants get in the way: STRING_DIV = 'div',
STRING_TR = 'tr',
The string 'div' is never going to change to something else, is it? It would be better to just use the string directly where you need it.This is an amazing and scary piece of code:
/**
* Get the count of the number of
* days in a month, given the
* month and year
*/
getCountDays = function( year, month ) {
var
// Set flip based on if month is
// before or after July
flip = ( month > 6 ) ? true : false
// If it's February
if ( month === 1 ) {
// If it's not a leap year
// then 28 otherwise 29
return ( year % 4 ) ? 28 : 29
}
// If it's an odd month ID
if ( month % 2 ) {
// If it's after July then 31
// otherwise 30
return ( flip ) ? 31 : 30
}
// If it's an even month ID
// and it's after July then 30
// otherwise 31
return ( flip ) ? 30 : 31
}, //getCountDays
It also calculates leap years incorrectly - try getCountDays(1900,1). February 1900 had 28 days, not 29.Why not let JavaScript do the work for you?
getCountDays = function( year, month ) {
var msInMonth = new Date(year,month+1) - new Date(year,month);
return Math.floor( msInMonth / MILLISECONDS_IN_DAY );
},
This will handle all leap years correctly.You can probably do something similar in your createDate function to avoid the manual tests.
Also the name getCountDays is not very informative. Maybe getDaysInMonth?
The settings options use names_with_underscores, but that's not very idiomatic in JavaScript (except for capitalized constants). camelCaseNames would be more comfortable.
The problem here, of course, is that it makes the code a lot harder to understand. To understand and verify the function, I'd start by writing out a table of the days in each month while reciting the "30 days hath September" rhyme. :-) Then I'd have to go through all the the flip and non-flip cases in the code and compare against my table.
Let's imagine that JavaScript didn't have convenient date calculations so we couldn't use the updated function I posted above. If that were the case, what would be a simpler way to code the function? Just use the table of months directly. After all, there are only 12 months to deal with, so it's very simple:
getCountDays: function( year, month ) {
var monthDays = [
31, 0, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
];
return monthDays[month] || getFebDays( year );
},
where getFebDays() handles all the special cases for leap years ( /4, /100, /400, etc.)Now, with the exception of February, it's trivial to see at a glance if the function is correct.
getCountDays( 2012, 2 ) // Daylight time began March 11
30 // oops
new Date(year,month,...) uses local time, so the day will be an hour longer or shorter when the time changes.A quick and dirty fix would be to use Math.round instead of Math.floor:
getCountDays = function( year, month ) {
var msInMonth = new Date(year,month+1) - new Date(year,month);
return Math.round( msInMonth / MILLISECONDS_IN_DAY );
},
And maybe better to use UTC? (I'd stick with Math.round at the same time.) getCountDays = function( year, month ) {
var msInMonth = Date.UTC(year,month+1) - Date.UTC(year,month);
return Math.round( msInMonth / MILLISECONDS_IN_DAY );
},It does look nice and easy otherwise, though.
Also I haven't looked at the API that hard, but from the examples it looks like it only supports american way of setting the date i.e. DD/Month/YYYY
Update: another big omission, I can select year only by scrolling through it month by month. i.e. try selecting February 12, 2016
http://news.ycombinator.com/item?id=4812223
It is even done without html5 input/type=date so probably is compatible with IE4
http://dojotoolkit.org/reference-guide/1.8/dijit/form.html#d...
Now with Dojo AMD (1.7+) it's even better and cleaner. You only require what you need and then build.
Here's an article describing the behavior in Chrome: http://updates.html5rocks.com/2012/08/Quick-FAQs-on-input-ty.... That behavior's in line with the current spec: http://dev.w3.org/html5/spec/forms.html#input-author-notes.
EDIT: I just realized that the OP might not be the author, so I'll just add an issue on GitHub.
Also the fact that javascript is a lot more readable when you put a blank line between every two lines bothers me (a lot!).
And that it works perfectly and looks great, man that bothers me.
// If datePassed is true
else if ( datePassed === true ) {
Yes, very well documented. >.> // Set the element as readonly
element.readOnly = true
// Get the date today
DATE_TODAY = P.getDateToday()
// Get the date to select
DATE_SELECTED = P.getDateSelected()
// Get the month to focus
MONTH_FOCUSED = P.getMonthFocused()
// Get the date ranges
DATE_MIN = P.getDateRange( SETTINGS.date_min )
DATE_MAX = P.getDateRange( SETTINGS.date_max, 1 ) // Return the calendarObject
return calendarObject
It's like this all the way through the code!(Edited to correct that the likely final minified size will be closer to 5k. Hoping to add accessibility features and localizability.)
d = new Date(base);
d.setDate(d.getDate() + 1);
Changing rel() to do this fixes the loop problem, but something else is surely wrong, because the result page now looks like this: http://i.imgur.com/ZUAJg.pngIt's not just loops that can trigger this stuff. It's also callbacks that trigger the same callbacks.
https://github.com/listenrightmeow/daterange
Under 5k/100 lines uncompressed. You can easily modify above to work in a prototype fashion without a library. Unfortunately I was lazy when I wrote it and used ender/jquery for selector support.
* The example looks unappealing. Not styled, not bound to a text field.
* It's not clear to my why clicking twice in a row produces a range — should this not be accomplished through mouse dragging or similar?
* If I select an end date that precedes the start date, it shows an alert box, which apparently is hardwired into the library. Not only does this make it impossible to translate the widget into multiple languages, but it's really not the task of the library to handle the error like this (an "onInvalidRange" or similar should be provided for the app to plug in).
* Month name is hardwired, no translation possible.
* No week numbers.
* No highlighting of today, holidays, or indeed of the selected range.
* No way to plug in custom dates that should be highlighted (for example, "booked" dates).
In other words, this is incomplete. I can't speak for most people, but it's useless to me. Sure, I could take your code and extend it to fit my app, but I could just as easily write it from scratch -- which defeats the point of reusability.
Sorry if this comes across a bit harsh, but you did open yourself to criticism:
> I have always wondered why javascript date pickers were always over complicated for the job.
Frankly, I suspect you have underestimated the job. :-)
1) I think you should put a little tiny triangle / down arrow on the right side of the text-box to give it the official "selection" ui signal.
2) I think you should NOT grey out dates that have already passed and are not selectable but instead keep them the same black color as the others, just <strikethrough> them. They're really hard to see when grayed out that much and it confused me a little bit when I first saw the month.
(tested on iPhone iOS 5.1)
Demo: http://labs.perifer.se/timedatepicker/
(I'm not the author.)
Edit: Added link to demo since that's the first thing I usually look for.
While we're on the subject of date pickers, is there a favorite among HN users? What have you all used for your web apps?
http://dojotoolkit.org/reference-guide/1.8/dijit/form/DateTe...
If it supported keyboard input, that problem would be solved.
https://github.com/amsul/pickadate.js/blob/gh-pages/index.ht...
That's what I was wondering. If there were a way, it'd be pretty awesome to use a library like this as a polyfill rather than as a separate thing you attach to text inputs.
[0]: https://github.com/Modernizr/Modernizr/wiki/Undetectables
It'd be so helpful if makers of these js elements put screenshots of what the element looks like on top 3 mobile devices. Of course, this raises the question that they would need access to these devices. Which raises the question, for people who do mobile-heavy web dev, how do you test things rapidly beside having an iPhone next to you to constantly hit refresh?
For anyone who cares, the Closure Compiler gets jQuery UI Datepicker down to 30kb (11kb gzipped).
Not quite as drastic as he claims but still significantly larger compared to his 6.7kb (2.8kb gzipped).