Building a date and time picker that doesn’t suck

| 9 min. (1769 words)

A few weeks ago I was on a hunt for a date picker to use in a new feature for Raygun. My overall feeling about date and time pickers is not the greatest. They often do the basic job, but they also come with some down sides. I needed a user friendly date picker that could handle time as well as the dates – unfortunately, with most of the date and time pickers I found they were…

  • Ugly, flat and boring
  • Too small
  • No support for time. Only date
  • Tricky to change the style. Requiring a lot of overrides in the CSS
  • Sketchy animations
  • No support for 12h and 24h time format
  • Oh, I think I could make this list pretty long…well, you get the idea

To find the right date and time picker in the big deep ocean of the web is time consuming. After some researching and experimenting I came across one picker I liked. The date-time-picker that is made by Eonasdan (Github name) and 68 other contributors.

I found this date and time picker sticking out of the dark ocean like glistening jewellery in a shipwreck. It completely shined and had more glamour than I expected. In this article I will cover the good and bad parts, and also a solution for the bad ones.

The good parts

I really like this tool for its elegance. Now I’ve been playing around with it, it feels like a solid date-time-picker and I love it for following reasons…

  • Default style is clean
  • It has plenty of options, but I’m not gonna cover them all here
  • Easy to implement
  • Easy to link two pickers. A to and from time. The UI prevents the user from picking invalid dates
  • It handles the time and date switch with smooth animations. Or side by side if preferred
  • Support for 80 preset local time formats and languages
  • Easy implementation of local time. E.g. local(“sv”) will give a Swedish time format dd/mm/yyyy. “de” – German, “en-au” – Australian and so on…
  • Many other options for placement/disable/enable of buttons and icons
  • The popup is moving relative to the viewport. If too close to any side of the screen, it will move to a better position
  • It’s still improving. First release was Sept 2013 and new releases are constantly launched since
  • Good documentation

Now you might be wondering how it works, what’s the name, where do I find it etc, but patience… one thing at the time. Let’s look at the UI first.

The UI

Date picker view

It works pretty much as we are used to. But it has some cool features I’d like to highlight. The first view is the regular date picker view. Apart from the regular things we would expect, we have a button with a time icon at the bottom. This will lead the user to the time picker view. Also, the actual date at the top is clickable. That will lead the user to a more generic date picker view such as year and month view. Alternative you can have a side by side layout.

Time picker view

The user can easily click up and down to select a time but again, the actual time is clickable. This will take the user to the quick time picker view.

Quick time picker view

Instead of tiring out the users finger by clicking up and down on the arrow on the previous view he/she can now pick the time in one click.

Quick month picker view

Same as above, a quicker way to select the month.

Quick year picker view

OMG! The user can also quick pick their desired year as well.

Is everything really that good?

Well, would you be surprised if I say yes…. but. The ‘but’ to this tool is something you can find in the name – it’s called bootstrap-date-time-picker. As you might guess, you need Bootstrap. And that’s not too bad… if you have Bootstrap. Here at Raygun we are not using Bootstrap, and this is the same for many developers. Therefore I will give you a with-bootstrap to no-bootstrap solution. What is bootstrap dependent in the date picker is the CSS and two javascript functions… which are jQuery plugins anyway. I’ve been cleaning up all the CSS I found unused, I’ve been stripping, brushing and tiding up the css to shrink the file size and broaden the market for this date-time-picker. The CSS went from 6600 lines to 100, and that felt like a good shower after a long hike.

What do you need?

  • jQuery.js
  • moment+local.js
  • bootstrap-datepicker.css
  • bootstrap-datepicker.js
  • bootstrap.js (It’s only two jQuery plugins you need. Transition and collapse are required if you’re not using the full Bootstrap javascript)
  • bootstrap.css
  • [optional] replace the bootstrap.css with the bootstrap-stripped.css you’ll find below. This is the option I’ve given you if you don’t want to use Bootstrap.

It might look like there is a lot of bootstrap dependencies, but some of them is just file names.

How do I get it?

As mentioned before, the date-time-picker is well documented and easy to implement. Have a look at the documentation, and why not check it out on GitHub as well. Maybe even do a contribution?

Settings

This is one of the beautiful things with the picker – all the settings. Change the time format and language to Japanese, apply your own icons by changing the icon-class-name-setting, disable the date view and only present the time picker view, or why not the side by side view. Well, the options are all listed below and you can find them all explained  here.

$.fn.datetimepicker.defaults = {
    format: false,
    dayViewHeaderFormat: 'MMMM YYYY',
    extraFormats: false,
    stepping: 1,
    minDate: false,
    maxDate: false,
    useCurrent: true,
    collapse: true,
    locale: moment.locale(),
    defaultDate: false,
    disabledDates: false,
    enabledDates: false,
    icons: {
        time: 'glyphicon glyphicon-time',
        date: 'glyphicon glyphicon-calendar',
        up: 'glyphicon glyphicon-chevron-up',
        down: 'glyphicon glyphicon-chevron-down',
        previous: 'glyphicon glyphicon-chevron-left',
        next: 'glyphicon glyphicon-chevron-right',
        today: 'glyphicon glyphicon-screenshot',
        clear: 'glyphicon glyphicon-trash'
    },
    useStrict: false,
    sideBySide: false,
    daysOfWeekDisabled: [],
    calendarWeeks: false,
    viewMode: 'days',
    toolbarPlacement: 'default',
    showTodayButton: false,
    showClear: false,
    widgetPositioning: {
        horizontal: 'auto',
        vertical: 'auto'
    },
    widgetParent: null,
    keepOpen: false
};

Set up

The installation is pretty straight forward. Just follow this guide.

After installation you can ether use the full bootstrap.css or replace it with the stripped version you can find below.

Use it without the massive Bootstrap CSS

The following CSS is what was left after I removed the unused CSS. I even stripped out some used but less important CSS roles to make it as small as possible and to have less to overwrite.

Once you have replaced the Bootstrap css with the stripped CSS below, the picker will look slightly different. Some margins and fonts will be changed. So it needs a little bit of CSS love to make it shine as you want it to.

Custom CSS to replace with for something in your style

This CSS is a very basic way to set up your font, font-icon, icon classes and so on. This block is for you to get started but I think you might want to replace this entire block with your own code.

/*
*
* Temporary css.
* Set up the font, icons and clear css you prefer.
* This is just minimum customization for you to get started
*/


html {
  font-size: 10px;

  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}



@font-face {
  font-family: 'Glyphicons Halflings';

  src: url('./fonts/glyphicons-halflings-regular.eot');
  src: url('./fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('./fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('./fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('./fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
}
.glyphicon {
  position: relative;
  top: 1px;
  display: inline-block;
  font-family: 'Glyphicons Halflings';
  font-style: normal;
  font-weight: normal;
  line-height: 1;

  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.glyphicon-time:before {
  content: "\e023";
}
.glyphicon-chevron-left:before {
  content: "\e079";
}
.glyphicon-chevron-right:before {
  content: "\e080";
}
.glyphicon-calendar:before {
  content: "\e109";
}
.glyphicon-chevron-up:before {
  content: "\e113";
}
.glyphicon-chevron-down:before {
  content: "\e114";
}


/* -- END OF TEMPORARY CSS -- */

The minimum bootstrap CSS to use

So this is the absolutely minimum CSS I found I could use. Replace the bootstrap.css with this code.

.list-unstyled {
  padding-left: 0;
  list-style: none;
}

.btn {
  display: inline-block;
  padding: 6px 12px;
  margin-bottom: 0;
  font-size: 14px;
  font-weight: normal;
  line-height: 1.42857143;
  text-align: center;
  white-space: nowrap;
  vertical-align: middle;
  -ms-touch-action: manipulation;
      touch-action: manipulation;
  cursor: pointer;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  background-image: none;
  border: 1px solid transparent;
  border-radius: 4px;
}
.btn:focus,
.btn:active:focus
 {
  outline: thin dotted;
  outline: 5px auto -webkit-focus-ring-color;
  outline-offset: -2px;
}
.btn:hover,
.btn:focus,
 {
  color: #333;
  text-decoration: none;
}
.btn:active,
 {
  background-image: none;
  outline: 0;
  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
          box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
}
.btn-primary {
  color: #fff;
  background-color: #337ab7;
  border-color: #2e6da4;
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active,
,
 {
  color: #fff;
  background-color: #286090;
  border-color: #204d74;
}
.btn-primary:active,
,
 {
  background-image: none;
}
.collapse {
  display: none;
  visibility: hidden;
}
.collapse.in {
  display: block;
  visibility: visible;
}
.collapsing {
  position: relative;
  height: 0;
  overflow: hidden;
  -webkit-transition-timing-function: ease;
       -o-transition-timing-function: ease;
          transition-timing-function: ease;
  -webkit-transition-duration: .35s;
       -o-transition-duration: .35s;
          transition-duration: .35s;
  -webkit-transition-property: height, visibility;
       -o-transition-property: height, visibility;
          transition-property: height, visibility;
}
.dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1000;
  display: none;
  float: left;
  min-width: 160px;
  padding: 5px 0;
  margin: 2px 0 0;
  font-size: 14px;
  text-align: left;
  list-style: none;
  background-color: #fff;
  -webkit-background-clip: padding-box;
          background-clip: padding-box;
  border: 1px solid #ccc;
  border: 1px solid rgba(0, 0, 0, .15);
  border-radius: 4px;
  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
          box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
}

Summary

From my experience with this date and time picker I must say I’m very satisfied. It delivered more than I expected. When I first started to look for a date picker my mind was thinking “Oh, what a hassle. I need to start a CSS war and override all !important roles.” Instead I found this one and I was excited. I gave it a shot to un-bootstrapify the picker and it worked out well. But I stripped it for my own needs, so there’s a small chance it causes some problems with things like older browsers. So far I haven’t seen any problem with the stripped down CSS, but be aware and please let me know if you find any problems in the comments.

I must say that the picker is well built and has good built in support for different local times and such. Therefore it’s quite a bit of code to implement, but we do get a lot from this picker, so I still think the good parts are worth all that code.

I hope you found this article helpful and who knows, it might save you some time in the future when you need a nice looking date time picker.