Noodle Printing Machine

    @acm-will/add-to-calendar-button
    TypeScript icon, indicating that this package has built-in type declarations

    1.8.2 • Public • Published

    📅 Your next Add-to-Calendar Button!

    Add-to-Calendar Button

    A convenient JavaScript snippet, which lets you create beautiful buttons, where people can add events to their calendars.

    #1 Product of the Day on ProductHunt



    😎 Use case // Who this is for

    This is for everybody, who wants to include a button at his/her website or app, which enables users to easily add a specific event to their calendars. It's main goal is to keep this process as easy as possible. Simply define your button configuration via JSON and everything else is automatically generated by the script. It is for this simple use case. No strings attached.


    🔎 Background // Why this repo exists

    While building a personal wedding page, I was confronted with the task to include a button, where invited people could save the event to their calendars. I did not want to build this from scratch (first) and therefore started the usual web research. Unfortunately, all I found where some extremely outdated code snippets, which did not really fit all the modern systems and calendar tools. Beside that, there was only the solution by AddEvent.com - all over the place. I was looking at CodePen and all I found where thousands of pens, which basically only included the AddEvent tool.

    The problems with AddEvent.com:

    • it holds tons of features, which I did not need. I do not want to track my button. I just want it to work.
    • it limits the free tier to 50 event adds per month (consider the wedding case - this is way too less).
    • it brings some data privacy issues, since you basically send your users to their service. GDPR alert!
    • the UX/UI is not ideal (imho).

    Bottom line: Paying for features, which I did not need - at additional privacy concerns - that made me create this solution (for you).


    ▶️ Demo

    See jekuer.github.io/add-to-calendar-button for a live demo.


    Features

    • Simple and convenient integration of multiple buttons - configure them directly within the HTML code.
    • Optimized UX (for desktop and mobile) - adjustable.
    • Beautiful UI (the best combined from experts around the world).
    • Up-to-date integration of all popular calendars:
      • Google Calendar.
      • Yahoo Calender.
      • Microsoft 365, Outlook, and Teams.
      • Automatically generated iCal/ics files (for all other calendars, like Apple).
    • Timed and all-day events.
    • Translatable labels and dynamic dates.
    • Well documented code, to easily understand the processes and build on top of it.

    Demo Screenshot


    🌱 Setup

    Option 1: simple (self-hosted)

    1. Simply download the code from GitHub or clone the git repository.
    2. Copy the css (atcb.min.css) and js (atcb.min.js) files from the assets (not the "npm_dist"!) folders into your project (the .min. files are required, but it is recommended to also copy the raw and map files).
    3. Include those files in your project. As usual, the css goes into the (<link rel="stylesheet" href="./assets/css/atcb.min.css">), the js into the footer (<script src="./assets/js/atcb.min.js" defer></script>). You can also combine them with other files, if you want to.
    4. Create your button as can be seen in the "Configuration" section below.
    5. That is it. The script takes care of all the rest.

    Option 2: simple (CDN)

    1. Instead of downloading the files, you can use the jsDeliver CDN.
    2. Put <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/add-to-calendar-button@1.8/assets/css/atcb.min.css"> into the and <script src="https://cdn.jsdelivr.net/npm/add-to-calendar-button@1.8" defer></script> into the footer of your website.
    3. Create your button as can be seen in the "Configuration" section below.
    4. Done. And this setup also automatically keeps track of any bug fixes and minor updates!

    Option 3: npm

    1. Requires Node, npm, and a project, which builds on it (e.g. React or Angular).
    2. Run npm install add-to-calendar-button.
    3. Import the module into your project/component. For example with Angular/React: import { atcb_action, atcb_init } from 'add-to-calendar-button';.
    4. Either use atcb_action with your own buttons/forms/etc, or run atcb_init after the DOM has been loaded. To determine the right moment and execute, ...
    5. with Angular, you would use ngAfterViewInit() with atcb_init(); (mind that, depending on your app, other hooks might be better);
    6. with React, you might want to include an event listener like document.addEventListener('DOMContentLoaded', atcb_init, false); or using hooks in a functional component like useEffect(() => atcb_init());
    7. Include the css. For example with Angular or React, add the following to the global style.css: @import 'add-to-calendar-button/assets/css/atcb.min';
    8. Create your button as can be seen in the "Configuration" section below.
    9. You're all done.

    🎛️ Configuration

    A button can be easily created by placing a respective placeholder, wherever you want the button to appear. (The style="display:none;" theoretically is not necessary, but should be used for better compatibility.)

    <div class="atcb" style="display:none;">
      (...)
    </div>

    Within this placeholder, you can easily configure the button, by placing a respective JSON structure. Mind that with Angular, you might need to escape the { with {{ '{' }} and } with {{ '}' }}; with React it would be { '{' } and { '}' }.

    Minimal structure (required)

    <div class="atcb" style="display:none;">
      {
        "name":"Add the title of your event",
        "startDate":"2022-02-21",
        "endDate":"2022-03-24",
        "options":[
          "Google"
        ]
      }
    </div>

    Full structure (without schema.org markup)

    <div class="atcb" style="display:none;">
      {
        "name":"Add the title of your event",
        "description":"A nice description does not hurt",
        "startDate":"2022-02-21",
        "endDate":"2022-03-24",
        "startTime":"10:13",
        "endTime":"17:57",
        "location":"Somewhere over the rainbow",
        "label":"Add to Calendar",
        "options":[
          "Apple",
          "Google",
          "iCal",
          "Microsoft365",
          "MicrosoftTeams",
          "Outlook.com",
          "Yahoo"
        ],
        "timeZone":"Europe/Berlin",
        "timeZoneOffset":"+01:00",
        "trigger":"click",
        "iCalFileName":"Reminder-Event"
      }
    </div>

    Full structure (with schema.org markup)

    You can save on the style="display:none;", but mind that you should not use dynamic dates (e.g. "today" or "+1") here! You can use startTime and endTime in the event block, but it is recommended to rather add it to startDate and endDate with "T" as delimiter here.

    <div class="atcb">
      <script type="application/ld+json">
        {
          "event": {
            "@context":"https://schema.org",
            "@type":"Event",
            "name":"Add the title of your event",
            "description":"A nice description does not hurt",
            "startDate":"2022-02-21T10:13",
            "endDate":"2022-03-24T17:57",
            "location":"Somewhere over the rainbow"
          },
          "label":"Add to Calendar",
          "options":[
            "Apple",
            "Google",
            "iCal",
            "Microsoft365",
            "MicrosoftTeams",
            "Outlook.com",
            "Yahoo"
          ],
          "timeZone":"Europe/Berlin",
          "timeZoneOffset":"+01:00",
          "trigger":"click",
          "iCalFileName":"Reminder-Event"
        }
      </script>
    </div>

    React examples

    atcb_action

    If you can't or don't want to use atcb_init, you can use the atcb_action import with your own buttons or other elements/components. If you omit the second argument, the dropdown list will display as a modal in the middle of the viewport - in this case, add the "atcb_customTrigger" class to the submitting element for better keyboard support.

    This may work better with React and other frontend frameworks, but it misses the Schema.org and button specific functionalities.

    import React from 'react'
    import { atcb_action } from 'add-to-calendar-button'
    
    const MyComponent = () => {
      const [name, setName] = React.useState('Some event')
      return (
          <form onSubmit={e => {
            e.preventDefault()
            atcb_action({
              name,
              startDate: "2022-01-14",
              endDate: "2022-01-18",
              options: ['Apple', 'Google', 'iCal', 'Microsoft365', 'Outlook.com', 'MicrosoftTeams', 'Yahoo'],
              trigger: "click",
              iCalFileName: "Reminder-Event",
            })
          }}>
            <input value={name} onChange={setName} />
            <input class="atcb_customTrigger" type="submit" value="save">
          </form>
      );
    }

    atcb_init

    Alternatively, you could use atcb_init with a useEffect hook:

    import React from 'react'
    import { atcb_init } from 'add-to-calendar-button'
    
    const atcb_action = () => {
      React.useEffect(atcb_init, [])
      return (
        <div className='atcb' style={{display: 'none'}}>
          {JSON.stringify({
              name: "Some event",
              startDate: "2022-01-14",
              endDate: "2022-01-18",
              options: ['Apple', 'Google', 'iCal', 'Microsoft365', 'Outlook.com', 'MicrosoftTeams', 'Yahoo'],
              trigger: "click",
              iCalFileName: "Reminder-Event",
            })}
        </div>
      );
    }

    Important information and hidden features

    • The "label" is optional, but enables you to customize the button text. Default: "Add to Calendar".
    • Dates need to be formatted as YYYY-MM-DD (ISO-8601).
    • You can also use the word "today" as date. It will then dynamically use the current day at click (not supported with schema.org style).
    • Add "+5" at the end of the date to dynamically add 5 days (or any other number). "2022-01-30+12" would generate the 11th of February 2022. This can be interesting, when combined with "today".
    • Times need to be formatted as HH:MM.
    • Times are optional. If not set, the button generates all-day events.
    • 1 option is required. You can add as many as you want. The supported formats are listed above.
    • If you want to rename (or translate) a label, use the following schema at the options: optionName + Pipe + yourLabel. "Google|Google Kalender" would generate a Google Calendar option, but label it as "Google Kalender".
    • If no timeZone and no timeZoneOffset is provided, the date refers to UTC time.
    • You can add a timeZoneOffset or timeZone (TZ name). You can find a list of them at Wikipedia.
    • If the timeZoneOffset is set, it will always override the timeZone. It is recommended to only use 1 of them at a time.
    • The timeZone might not work in very old browsers, but also considers dynamic changes like summer/winter time.
    • timeZoneOffset works with older browsers, but is quite static.
    • Use "currentBrowser" as value for timeZone to dynamically use the time of the user's browser. Use this with caution, since it would mean that the date and time will differ per user, which should not be the usual case! (Requires all times to be set.)
    • You can set the trigger to "click". This makes the button open on click at desktop. Otherwise, the default would be to open on hover. On touch devices, this makes no difference.
    • If you want to define a specific name for any generated ics file (iCal), you can specify it via the "iCalFileName" option. The default would be "event-to-save-in-my-calendar".
    • You can use the option "inline":true in order to make the button appear with inline-block instead of block style.
    • Formatting a URL in the description like [url]https://....[/url] makes it clickable.
    • If you require line breaks within the description, use \n or <br>.

    🙌 Contributing

    Anyone is welcome to contribute, but mind the guidelines:

    IMPORTANT NOTE: Run npm install and npm run build to create the minified js and css file, its sourcemap files as well as the npm_dist/ folder and content!


    📃 License

    The code is available under the MIT license (with “Commons Clause” License Condition v1.0).


    Changelog (without minor changes and fixes)

    • v1.8 : new button style
    • v1.7 : new code structure and options + tons of optimizations
    • v1.6 : supporting Microsoft Teams
    • v1.5 : update to date format and better accesibility
    • v1.4 : schema.org support (also changed some keys in the JSON!)
    • v1.3 : new license (MIT with “Commons Clause”)
    • v1.2 : inline and line break support
    • v1.1 : npm functionality
    • v1.0 : initial release

    💜 Kudos go to

    Install

    npm i @acm-will/add-to-calendar-button

    DownloadsWeekly Downloads

    5

    Version

    1.8.2

    License

    SEE LICENSE IN LICENSE.txt

    Unpacked Size

    201 kB

    Total Files

    15

    Last publish

    Collaborators

    • acm-will