rjcc

rjcc is a web calendar control written in the spirit of the suckless tools. That is to say: it has no dependencies, is reltively small (lines-of-code-wise) doesn't assume that it knows your page better than you.

This is not for if you've gone all-in on React. There are good calendar controls for React. Go use one. This is for when you just need a plain old calendar for an "old school" page (think: minimal JS), and you don't feel like dragging in a couple dozen layers of complexity just to make that happen.

No hard dependencies.

Why: because while jQuery and friends do a great job of making things slightly easier to deal with the garbage that is your average browser's scripting environment, a project (i.e. your library's users) typically only uses one of those frameworks. In my case, I wasn't about to drag in another 100K or so of code just for a calendar, so I couldn't reasonably use anything that used a framework other than jQuery. There went half the contenders. I also didn't want to drag in the overengineered almost-round-wheel that is jQuery UI, so there went another half dozen. Finally, I wasn't about to fork a control just to get it working with a modern version of jQuery. Suddenly I was only left with a dozen or so options based on framework alone.

Reasonable code quality.

Why: JavaScript is a crippled, badly-designed language (albeit one that's slowly recovering), and a lot of the code written in it just plain sucks. This is mostly due to the fact that JS environments put up with way too much stupidity on the part of developers, but it's also due to the fact that the web's low barrier to entry means that it's the modern equivalent of BASIC: the thing that young developers get their start writing for. I dig that last part 'cause programming can be fun to learn, and I'm not gonna fault people for learning (we all gotta start somewhere!) But the large number of new developers does mean that a lot of the code out there is... uh... creative in ways that I'd rather it not be. So code quality took out a few more candidates.

No heavily-integrated styling.

Why: I'm not really a big fan of CSS (I think it's another comically-defective web technology, although it too is improving slowly), but it's the best tool I've got for web page look and feel, and this thing had to look presentable.

So calendar controls which had tons of hard-coded styling (or which made too many assumptions about how elements would be styled) were disqualified. It's painful enough to deal with CSS on its own without having to also fight a bunch of goofy inline styling from some control at the same time. I'm also not gonna drag in a 5KB stylesheet and 20KB of images just for a 5KB calendar control, so ones that came with a ton of other resources were also skipped. This brought me down to a half-dozen or so total.

Sane selection event model.

Why: Because UI interaction should be event-driven. This means that if you're building a date picker, the caller should be able to give you a callback to have invoked when the user picks a date. This callback should then receive the date that was selected. If I (the caller) have to do anything more than that just to figure out what the user picked, you're making me do too much and I'm going to skip your control and use something else. This took out a couple more candidates.

Partial date support.

Why: Because I want the user to be able to select just a month/year or just a year. This wasn't a hard requirement as I figured I'd have to add it to the control anyways -- but the control had to at least not prove downright hostile to this sort of addition. Sadly, most did.

"Partial" dates are relatively uncommon in many "general audience" sites, but painfully-common in certain problem domains. Clinical data acquisition, for example, is rife with partial dates. Patients can't remember dates, records get lost, etc. So a control that assumes that anything date-like consists of a year, a month, and a day is not suitable.

No assumption that I'm putting the date into an input.

Why: Because I'm not.

This is the one that took out all the rest of the candidates. Every single one of them assumed that I was going to be 1) displaying a calendar as a result of focusing/clicking on a text input and/or 2) taking the date that was selected and putting it into an input. Both assumptions were wrong.

I needed a control that could be used to populate an input, but a) could also be used independently b) rendered where I bloody well told it too, not just "near the input that I 'attached' it to" c) didn't mess with the input directly. I have my own event model that needs to be observed -- I don't want to fight with a third party UI component when it comes to manipulation of form controls. So yeah, from about fifty contenders to zero. (And that's leaving out things like documentation, licensing, etc.)

No options? Time to write one. This is my attempt at that.

Why use RJCC?

First, flexibility. The caller determines where (or even if) the control is rendered. You can position it anywhere you'd like, use whatever mechanism you want to show/hide it, etc. You create the element that it renders to (although it does expect to own the entire contents of that element.) You can style it however you want (it has no default styling), and if the CSS class names bother you then you can change any of them. There are no "magic" class names or special stylesheets that you need to make it work. Make it look however you'd like. Go nuts. There is an example stylesheet in the tarball. You're welcome to ignore it.

Second, it has a sane event model. You can invoke the control however you'd like. If you're using jQuery or MooTools or something and want to have the calendar render when you focus on an input it's easy to do that -- but I'm not going to force you to. You have exactly one callback to deal with: when the user picks a date or partial date. You're in control of the display/hide logic, so you don't need to give RJCC callbacks for that. It doesn't know when it's visible or not, nor does it need to. So the event model is really damn simple: your callback handles an object that has year, month, and day properties. That's it.

Third, it (optionally) supports partial dates, specifically the selection of a month/year combo (with no day component) or the selection of a year only. If either of those are selected, your callback gets the selected components (year or year/month) and no date.

So those are the major features. The other ones, in no particular order are:

License

BSD 2-clause

Source

Available from this Gitlab repository