DEV Community

Connor Tangney
Connor Tangney

Posted on

Another Javascript Event Calendar?...

Yes. Another Javascript event calendar.

"But Couch3ater... Why?! There are hundreds, if not thousands, readily available for you to use on the internet!"

You're right. There sure are. That said, there are a couple reasons I decided that I wanted to go ahead and make yet another:

  1. A lot of the event calendars that support the features I am looking for come with some sort of pay-to-play model, offering a few of the features for free while only offering the "premium" features after paying a one-time or subscription fee. I can't stand these types of "Freemium" models.
  2. Many of the free event calendars that do offer all the features I am looking for do not support the ability to apply custom themes, or even make basic color changes. Not altogether useful when I'm trying to drop a free component into a white-label website!

Rationality aside, let's just jump into it. As with any problem that I am aim to solve, I try to break things down into their core elements. At its most basic, an event calendar really only needs a few things to work and look good (at least in this implementation 😅):

  • Data.
  • A list view.
  • A details view.

Let's start with the data.

At the end of the day, unless you connect your calendar to some data, it's not really going to be that useful. In my case, this calendar is likely going to be communicating with a JSON document store, so for the sake of example, I will just have a smattering of event data stored in an array.

const _EVENTS = [
  {
    id: 1,
    name: 'PARK EVENT 1',
    date: '2019/10/20',
    desc: 'Short description of the event here. Displays on event LISTING.',
    info: 'Longer, more verbose description of the event. Displays on event MODAL in the content body.',
    type: 'park',
    img: 'https://placehold.it/150x150'
  },
  ...
]

For the sake of brevity, I have only included one event object, but that should be enough to give you a good idea of how I have structured my data. I am on the fence about adding an additional field labeled "thumbnail" that would allow users to upload a separate image to be used as the thumbnail for the event listing. Right now, the "img" field is used as both the listing thumbnail and the modal header. Luckily, where I've spun this up myself, changing this is easily accomplished 😁

Now on to the looks.

With a rough layout for my data hammered down, it was time to move onto the more exciting part -- designing the actual calendar! As someone who has used event calendars in the past, I have formed some opinions on what I like to see from them, namely that I hate the standard "calendar" view. Nowadays, when I see a calendar interface, my mind immediately defaults to "Oh, this is a DatePicker," and I find myself trying to select a range of dates. This is just my personal experience, but I'd be lying if I said it didn't impact my design choice. After all, you're looking at a list view layout, now aren't you?

Calendar list view

It was necessary to also inlude a secondary view for the calendar in order to display the expanded details about the event. For this, I just went with a pretty simple modal that opens when a user selects the Learn More button. Through some black-magic trickery (also read: regex), information from the event data is pulled from the array by index...

Calendar details view

  const target = event.target;

  let eventId = target.closest('section.event-listing');
  eventId = eventId.getAttribute('data-event-id')
  eventId = eventId.match(/\d+/g)[0];

  const eventListing = _EVENTS[eventId - 1];

Then dumped into the modal. You'll notice I'm subtracting one from my eventId value. This is because my ID's are not zero-indexed. If I were to use this in a production setting, I would almost certainly normalize these indexes to reduce confusion, but for the time being, this footnote will have to be good enough to remind me! 😆

Tie it all together...

Once I had everything mostly planned out, I set out to writing the code to make it all work. As I had set the foundations nicely, all I really needed to do was loop through my events and append a new child to the DOM for each one. I made it a goal to not use innerHTML for anything because I mean, why should I be using that in the first place? Where I am not connecting this to an API for the moment, I won't go over how to fetch your data, nor will I go over any implementation of a "loading" state, but setting something like that up should be child's play if you comfortably read this far!

If there's any interest, I can certainly do a quick write up of how I went about plugging this in to my current project and tying it to backend data.

Thanks for reading!

Top comments (5)

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

Great effort, I can appreciate the pay to play model is a blocker, I think maybe turn this into a booking system and sell it?

Collapse
 
couch3ater profile image
Connor Tangney

This was actually more of a plug in / module I had started working on for a website prototype I was messing around with in my spare time.

I've actually since started working on a custom Google Maps implementation that I'd like to write something up on... If I can find enough hours in a given day!

Perhaps I will come back to this at a later date. It was certainly fun to mess around with initially and can definitely be expanded upon.

Collapse
 
adam_cyclones profile image
Adam Crockett 🌀

I'm picking up react lately because the company uses it and I need to pay the bills. But I have enjoyed writing a blood glucose monitoring app today because it's got lots of state, visual and interesting to play around with. I can appreciate your perspective with PAIN haha.

Thread Thread
 
couch3ater profile image
Connor Tangney

I'm a huge React fan boy, though I must admit, I have not worked with it in quite some time -- at least since the birth of hooks.

Thread Thread
 
adam_cyclones profile image
Adam Crockett 🌀

Hmmm that is why I'm not standing on a mountain shouting, it looks like magic. I don't understand the move to do this.