Scrollable Calendar Widget

Scrolling Calendar

See the Demo.

Update: I built and tested this on Chrome using my macbook’s trackpad. It scrolls very smoothly, however I’ve heard reports that a scroll wheel jumps from month to month, but can cut off dates half-way. Needs to be updated for scroll wheels. Also touch events for mobile.

I haven’t been on Dribbble in awhile, but last night I was poking around and found a bit of inspiration. A little calendar widget design by Dribbble user Cat Noone caught my eye, but what really sparked my interest was the fisrt comment below it:

Really love this widget! Quick question how do you change the month? Or is the intention that you can only pick a day during a specific month?

I started thinking how the calendar might work if you used scrolling to change the month. From Cat’s design it seems there is a window of delivery, so she may not need to change months. But most apps I’ve used do.

Several hours later I ended up with my own Scrolling Calendar widget. It is just a prototype and could use work to make it more robust, but it will give you a feel for the scrolling interaction.

Building the Scrolling Calendar

I started building the calendar by setting up the HTML I thought I would use and styling it (borrowing from Cat’s color scheme). The initial HTML looked something like:

<div class="date-picker">
  <header>December 2014</header>
  <table class="calendar">
    <thead>
      <tr>
        <th>Su</th>
        <th>Mo</th>
        <th>Tu</th>
        <th>We</th>
        <th>Th</th>
        <th>Fr</th>
        <th>Sa</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="disabled">30</td>
        <td>1</td>
        <td>2</td>
        <td>3</td>
        <td>4</td>
        <td>5</td>
        <td>6</td>
      </tr>
      <!-- etc. -->
    </tbody>
  </table>
  <section class="controls">
    <button>Select Date</button>
  </section>
</div>

Many calendar components use tables to display, with each week being a row in the table. The dates which are not part of the current month but show because they are on the current week, they get a “disabled” look.

I wanted my scrolling calendar to show the current month’s dates in the highlighted blue color, and the other dates with the disabled look, but I didn’t feel like iterating over each date cell to add and remove classes was my favorite method. Couldn’t I use CSS to toggle whole months at a time instead? (It seems like Cat’s company, Liberio, actually has specific date ranges, in which case doing it by day makes the most sense.)

So I threw out the table. That always gives me a good feeling when I get rid of a table—I don’t know why. And instead of using spans and divs, I thought I’d get all HTML5ey and use custom elements. So <week>, <day>, <month>, and <date> were created.

Custom elements

This screenshot didn’t include it, but inside <week> would be <day>Su</day><day>Mo</day>, etc. The day and date elements became inline-blocks with a set width and height, and their containers got a set width so they would automatically wrap every 7th item.

Once I had the HTML and styles I wanted, I started to code it. I pulled in the trusted moment.js library to populate the dates, and since I was using a date library I auto-generated the weekdays with Moment as well (that’s why the screenshot above is missing the weekdays). The calendar will support multiple locales now!

When I was using the table-based HTML my thought was as the user scrolled up or down, rows would be added at the top or bottom of the table as needed. Now I would be creating months at a time. So the initial population of the calendar contains 3+ months. The current month, the previous month, and the next month. The “+” comes in because I need the “filler” dates from the month before the previous (e.g. January 2015 would show 28, 29, 30, and 31 from December). I can’t just leave these out because I am no longer using a row-based layout, so they are needed to make sure the dates are in the correct place.

At first I tried the “scroll” event, but it was the “wheel” event that I needed. You can’t get the wheel event’s delta change, and you can prevent it’s default action. When the user scrolls over the calendar, I use the delta to know where the screen should be, add a month to the front or back of the calendar if needed, and set the current month if needed. Scrolling up and down will change months very quickly. Try it out.

I played around with the “break point” in the middle of the calendar to determine when to switch the active month. It turned out that directly in the middle wasn’t quite right. It always looked like the break point was too low, because of the amount of visible text above and below. Also, the breakpoint couldn’t be a line, but a margin, otherwise you could get jitter when scrolling slowly between two months.

The final touch was the date selection. Handling the click on a date wasn’t difficult, but I ran into a usability issue when clicking on one of those “disabled” dates. I wanted to allow it so you didn’t have to scroll all the way when you saw the date you needed, but I also didn’t want the top of the calendar showing “January 2015″ when you just clicked on the December 28, 2014 date.

To fix this, I selected the month for the date when you click on it. This highlights those dates in blue and shows the correct month in the title bar. You can still scroll after that, but when you click you get confirmation of the date you selected.

Because I’m using moment.js with locales the calendar should work correctly for you, with Sunday being the first day of the week in the US and Monday in many other countries.

Things to Improve

This isn’t ready for prime time as it is just a proof of concept. If you wanted to go the distance you would want to add < and > buttons on the month line. Just because a user can scroll through the months, doesn’t mean that they will know they can. You’ll have to give them the training wheels and let them discover the scroll feature for themselves.

Currently I only create one month in front or back when scrolling past the break point. Using my track pad it is pretty smooth until I try to flick it very fast. It halts the flow. In my prototype you can still get years down the road very quickly, so I didn’t fix this, but to make it a smooth experience you would want to use the delta to add/remove several months when needed instead of just the one at a time.

You could add other features, such as selecting a range of dates, adding time selectors like Cat’s original design, providing maximum and minimum dates available, giving some sort of visual indication that scrolling is possible (without an ugly scrollbar hopefully), and packing it up for reuse of course.

What do you think, would this be useful and intuitive?

A Better jQuery by Extending the DOM

Not very long ago creating your own custom HTML was considered A Bad Thing™. If you deviate from standards you’re just as bad as table-based layouts and the <blink> tag. Now we have Custom Elements, Angular.js and Ember.js and Polymer. It’s alright now because it’s a standard. But before it was a standard I was trying to hack support for custom elements in Simpli5 with the __proto__ element. IE didn’t support __proto__ so it came to a halt. Note: Polymer’s Custom Element polyfill relies on the __proto__ property, and IE11 supports it now, even though it is non-standard. Oh, and we can look forward to using Object.setPrototypeOf.

What about extending the DOM? jQuery makes things really nice, but it must wrap everything to accomplish this, adding memory and slowing down (not significantly, so this may be a lame argument) access. Why can’t we just extend the DOM to add all the useful functionality we need? Prototype.js does it. Here are a bunch of easy wins, along with suggestions for some of the more in-depth ones. This won’t work with really old browsers such as IE8.

How to Extend

Before we get started, here’s a quick note on how you ought to extend the DOM. Make sure you use Object.defineProperty or Object.defineProperties on the prototypes of the DOM elements. This allows you to define getters and setters if needed, but it you can also leave the enumerable setting at its default of false so that for-i-in loops don’t see your methods. Otherwise you can mess up other libraries. To match the other methods, set configurable and writable to true. I’ll be using Element.prototype.method = xxx in my examples for brevity, but know that it really means

Object.defineProperty(Element.prototype, 'method', {
  configurable: true,
  writable: true,
  value: xxx
})

Also, remember to always return this from your methods if you’re not returning a value. That way they can be chainable like jQuery.

Finding Elements

document.querySelector(selector) and document.querySelectorAll(selector) return an element or all elements respectively, using the CSS selector provided. You don’t need jQuery to do this anymore, and you don’t even need to extend anything to have this. These same methods exist on every element, searching their children for the selector provided. And if you want to shorten the call, set Document.prototype.find = Document.prototype.querySelectorAll and Element.prototype.find = Element.prototype.querySelectorAll.

You’ve already got the built-in element.nextElementSibling, but if you really want it to be shorter, you can make a getter on Element.prototype.next to return this.nextElementSibling.

We can make sure the built-in element.matches exists without prefix by using a pollyfill:

if (!Element.prototype.matches) {
  Element.prototype.matches = Element.prototype.webkitMatchesSelector ||
  Element.prototype.mozMatchesSelector ||
  Element.prototype.msMatchesSelector ||
  Element.prototype.oMatchesSelector
}

which allows an element.closest method to match jQuery’s method of the same name.

Events

Why not add Element.prototype.on = Element.prototype.addEventListener and Element.prototype.off = Element.prototype.removeEventListener (and the same to Document and Window) to shorten our event listening? Or to really shine we make the on method accept a selector and use event.target.matches to optionally call the listener, like jQuery, but built in.

You can add a trigger method if you don’t like dispatchEvent. It can take a string and make a MouseEvent, KeyboardEvent, CustomEvent, etc. for you.

Lists of Things

jQuery is nice because you can do one action to a whole list of elements at a time. What about extending NodeList? You know, that non-array you get back from calls like element.children, and document.querySelectorAll. We could add a bunch of methods to NodeList.prototype that have the same name as methods we add to Element.prototype except that the NodeList versions iterate over their elements and call the element method of the same name. This would allow element.children.on('click', onClick) or document.find('.tag').removeClass('tag').

Dealing with Nulls

One things jQuery does nicely is it handles nicely when the thing you’re looking for doesn’t exist. $(‘dummy-element’).on(‘event’, function(){}) won’t break, even though there is no dummy-element. When we’re getting back NodeLists it’s not a big deal because iterating over 0 elements won’t cause any errors. But you may want to create a dummy element class to return from calls to next() or prev() which only return one element, so that you can continue to chain without breaking. I’ll let you figure out how this could best be done, but one idea is you might think of returning an empty NodeList from document.createElement('div').children or something.

More Complex Settings

Creating elements from strings of HTML is one thing that takes a little more doing. Fortunately, jQuery has already done the work for us and we can just add the method to Document.prototype.create or something. If you don’t want to go looking through the jQuery source, Krasimir has already done the work for you.

Another heavier item is setting a bunch of CSS properties at once, taking into account browser prefixes. Here is one solution that I’ve come up with which extends the style property of your elements.

// Allows setting a lot of CSS styles at once, doing translations for vendor-
// prefixed styles.
// E.g. element.style.set({ color: red, transform: 'rotate(7deg)' })
var prefixes = ['webkit', 'moz', 'ms', 'o']
Object.defineProperty(CSSStyleDeclaration.prototype, 'set', {
  configurable: true,
  value: function(properties) {
    var style = this
    Object.keys(properties).forEach(function(property) {
      var value = properties[property]
      if (typeof style[property] == 'string') {
        style[property] = value
      } else {
        var capitalized = property.charAt(0).toUpperCase() + property.slice(1)
        for (var i = 0; i < prefixes.length; i++) {
          property = prefixes[i] + capitalized
          if (typeof style[property] == 'string') {
            style[property] = value
            break
          }
        }
      }
    })
  }
})

The Rest

Now that you’ve got the hang of it, you can see how you might easily add append(), prepend(), addClass(), and any number of things that you need from jQuery. Even if you only use the library for pet projects, it will be a good exercise in learning the DOM methods and build your understanding of how jQuery works internally as well.

Extending the DOM is a lot of fun and it can be quite enjoyable to work with native objects everywhere, sprinkled with your own helper methods. I don’t know if something like this will ever become mainstream, but you shouldn’t have any issues doing it with your own applications.

Because of potential conflicts (the main reason for not going this route), it is best to avoid extending the DOM in libraries that you want to load on other websites. Imagine if Facebook used a library like this in their Facebook Like button, and Google did the same in their Google Plus button. One of them would likely break the other, and they are so often on the same page that it would always be broken.

MyStickies Uses it Minimally

I use element prototype extension for MyStickies, but only to pollyfill missing functionality such as element.remove, element.matches, and element.classList. This way I won’t conflict with any other libraries (the MyStickies script is loaded on every page you browse when you install the extension), but I can still rely on the useful functionality that is standardized, but not implemented yet in every browser I support.

What say you? Is extending the DOM the epitome of all evil? Or would you do it for your own applications?

Use array-view Instead of Angular’s Filters

AngularJS uses dirty checking to discover when changes have occurred to the data it is displaying on-screen. This simplifies your code. It speeds up development. And it allows you to use whatever-the-heck you want for your data and models, instead of forcing you to use their model classes (as Ember and Backbone require).

Dirty checking also re-runs filters. A lot.

Checking whether 32 has changed to 33 isn’t a big deal. Checking whether an array that, using Angular’s filters, is sorted and filtered by re-sorting and re-filtering the original is slightly more expensive. Doing that on every $digest (e.g. every key-stroke in an input field), especially on large arrays, could kill performance on slower machines and mobile.

array-view

Introducing array-view. array-view is a library that provides a sorted, filtered, even paginated view onto your original array. The view is an actual array that stays in sync with your original, so any push/pop/shift/etc will affect both arrays. And the best part, the view syncs only when required, not whenever $digest is run.

You can even use array-view to simply keep an array sorted automatically whenever you add new objects to it. It’s simple and easy to use.

And the best part: it’s still an array. Any library expecting arrays can use it. You can use it in your JavaScript SDK you provide for customers.

Inline HTML Editing Sneak Peek

You are building a website, CMS, blog platform, ecommerce site, or web app. You need the user to edit their webpages, product info, or posts. You have an idea for how it will work, how your product will make this easier than any other. But after hours of searching for something you can use you are emotionally exhausted. The only things out there that aren’t ugly hobby projects are over-engineered replace-your-textarea solutions. You can’t have your vision. You can only have someone else’s complete package. Or you can start your own hobby project and stop because of time, releasing it among the crowds of other partially started WYSIWYGs.

I have felt keenly the pain of existing WYSIWYG solutions through the years. I’ve been meaning to take the time to build one from scratch that kept the core separate from the toolbar/interface. One that other’s could build custom solutions with. I finally made some time. It’s still not finished, but it’s in a usable state. I wanted to provide a sneak peak.

Inline WYSIWYG Sneak Peak

To make portions of an HTML page editable you can add a data-editable="simple" attribute to the element or call editable.enable(element, 'simple'). The following screenshot is the HTML for the page being edited in the video. We’ll be open sourcing it soon.

Screen Shot 2013-03-26 at 2.46

I am an Original

I’ve been quietly working for Original the last month. I’ve worked with startups before, but this is my first real startup experience. We have a remote team of six really great people.

The hiring process was amazing. There was no resume submitted, just my Github profile and a few Skype interviews. We are using hall.com to keep in sync, Pivotal Tracker to organize the work, and Github branches and pull-requests for features and issue tracking for bugs.

We are using Node.js and Angular and MongoDB for our product. We’ve been able to build quickly and are excited to start getting feedback from an early alpha.

We really are remote, the six of us being scattered from the West coast to the East, all working from home, coffee shops, colocation, or wherever we feel like. No skimping on benefits either in the name of cash flow. I feel well taken care of.

Basically, this is my dream job. Minus an office AR Drone.

I’ll keep you posted.

restdb: A NoSQL JavaScript Database

I’ve thought for awhile how much fun it would be to make and/or hack on a JavaScript database. After seeing the implementation of an append-only B+ tree in JavaScript for a CouchDB clone I thought, what the heck, why not? So for my company’s hackday I thought it would be a great way for me to expand my knowledge and grow in new ways.

The Why and What

The real bottlenecks in distributed databases are network and storage, not the speed of the language. As long as the database is architected well, handles concurrency well, and is able to scale, then it should be perfectly fine to write it in any language. JavaScript and Node.js seem suited particularly well because of its ability to deal well with concurrency, IO, and many connections.

Using a dynamo-styled setup that can expand a ring of gossip-protocol-linked nodes should work well with node. Allowing socket-based connections as well as RESTful interfaces would work easily. Providing real-time websocket updates to web apps would allow for both a great web-interface into the health and load of the database as well as direct and instant updates to web apps relying on the data.

The format of this database is key-value. It stores JSON documents, but handles any other types of document too, from HTML to binary and images. They key for each document is a URI. This allows the organization of documents and related types (e.g. /tweets/1234 and /users/123/comments/1234). The database needs to be able to create custom indexes to sort documents in custom ways. And a mechanism needs to be in place to create and update those indexes and access them via a defined URI. Being inspired by CouchDB’s design documents, the indexes and other possible custom data handling (think document validation, triggers or callbacks, and refined ACLs/permissions) could be taken care of by creating special JSON documents called “apps”. These will be prefixed with an underscore to differentiate them from other documents.

The Parts

Rather than using a node B-tree I opted to use Google’s already stable leveldb. Node.js has a module with bindings for leveldb, so this provides a great start but it doesn’t support streams. This is a negative because the whole document is loaded into memory by the leveldb module. If it supported streams we could send the data along as we received it from the file system and keep memory low, especially relavent when storing large files such as pictures and video.

I’m using express for the REST server. This may be more than I need for this very specific use-case, but I know it well and can drop down to node’s HTTP stack sans-express if needed.

There is a gossip protocol module which is a start for our dynamo style ring, but there is a lot more work to be done on coordinating where on the ring documents are stored. I’m thinking it can work like Riak where you specify a number of vhosts for the ring and each vhost would be a separate database and separate node process. Leveldb only allows one process to be connected at a time, to prevent contention. Map-reduce queries would be spread around to each vhost. And the vhosts would be spread around the cluster/ring as it is grown. I’ve also included an mdns module, or more commonly known as zero-conf or bonjour, so that the nodes on a network can automatically detect each other and auto-join a ring possibly, depending on a configuration value.

I’ll use the msgpack module to serialize and store the JSON to leveldb. This will make it faster to pull the data off disk and into memory for indexing and map-reduce, and keeps the database smaller. The REST interface could support JSON and msgpack and then we could use the msgpack protocol in addition to the REST interface, allowing for connecting clients the choice to work in the smaller/faster binary format of msgpack.

The Result: restdb

I created and called this project restdb, since it is a database very much based on the REST protocol. I was only able to get the initial parts working today. This was mostly because I forgot to use –data-binary with curl for testing and spent a long time figuring out why my image wasn’t displaying in the browser. But you may install and run the database if you’ve got node.js installed by following the instructions in the readme.

You can do PUTs, GETs, and DELETEs. And it works well. The next steps would be to handle JSON correctly with msgpack. And to give support for the specialized app documents.

Each index created will be a separate database that stores the index field as the key and the document id as the value. This might cause problems as each vhost would need to have an additional database to its own for each index created. CouchDB deals with similar problems as it has a b-tree file for each database and for each index (view) in each database. It recommends increasing the ulimit on your machine. ElasticSearch has similar requirements. So I figure we’re not in too poor of company.

Future of restdb

It was a lot of fun to think about how I would build a database. It turned out to be able to be an application server as well as a database since using the app documents you could host complete web apps from the database. This is like the CouchApp, but I feel it supports it from the ground up rather than a bolt-on or pivot afterwards.

I don’t feel confident in my ability to write a production-ready, mature, or stable database. So I will continue to work on this whenever I get the itch to have some fun hacking, but it is not something I will commit any large amount of time to. However, if you are also interested in hacking JavaScript and want something meatier than a webapp to sink your teeth into, please fork and contribute to restdb. It has some great potential.

Next Page »