├── README.md ├── atc.1.6.3.js ├── atc.1.6.3.min.js ├── docs └── index.html └── example.html /README.md: -------------------------------------------------------------------------------- 1 | # Free add-to-calendar button 😍 2 | 3 | ![add-to-calendar button](https://cdn.addevent.com/customers/addevent-github-t1.png) 4 | 5 | _The most used and trusted add-to-calendar button functionality on the internet. 6 | Trusted by +150,000 companies around the world. Maintained daily and super reliable. 7 | More than 500 mill events have been added to users calendars using AddEvent._ 8 | 9 | ### Awesome features 10 | - Works with **all major calendar services** (Apple, Google Calendar, Outlook, Outlook (online), Office 365, Yahoo) 11 | - **Use** for websites and apps. For e-mails, use our [add-to-calendar links](https://www.addevent.com/solutions/share-events) on AddEvent.com 12 | - **Time zone and daylight saving time compatible**. Make sure date/time is correct across time zones. 13 | - **Supports**: Normal events, recurring events, fluid events, event reminders, include attendees, busy or free state. 14 | - **Touch- and user-friendly**: Designed and tested to work with desktops, tablets and mobile devices. Optimized for touch devices, user-friendly and easy to understand calendar options. 15 | - **Keyboard Accessible**: Fully keyboard accessible. WAI compliant (W3C). Useful to people with disabilities. Accessibility is required by law in many countries. 16 | - **No dependencies**: Written in pure javascript. No need to install anything on your server. Using backwards compatible technologies to support older browsers (down to IE6). 17 | - **Legal**: Fully GDPR, CCPA, and LGPD compatible 18 | - **Design**: Download a predefined theme or customize the design to fit your needs with simple CSS changes 19 | - **Centralized end-point**: Historically the calendar vendors update/change their calendar software a couple of times per year. With AddEvent as a centralized end-point, it's our task to make sure everything is working and not your task. 20 | - **Free**: It's free, super reliable, and proven by millions of people ❤️ (we also offer a paid version with awesome technical support) 21 | 22 | ## Demo 23 | 24 | Go to [https://addeventinc.github.io/add-to-calendar-button](https://addeventinc.github.io/add-to-calendar-button) for a live demo. 25 | 26 | ![Demo Screenshot](https://cdn.addevent.com/customers/gh-add-to-calendar-button-t2.gif) 27 | 28 | ## Install 29 | 30 | The add-to-calendar button snippet is a simple piece of HTML where you fill in your event details dynamically. Here's a full example you can try out in your browser. 31 | 💥 View more examples and themes on [AddEvent.com](https://www.addevent.com/documentation/add-to-calendar-button#anchor-themes) 32 | 33 | ```html 34 | html 35 | 36 | 37 | 38 | 40 | --> 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 50 | --> 51 | 52 | 53 |
54 | Add to Calendar 55 | 10/20/2022 08:00 AM 56 | 10/20/2022 10:00 AM 57 | America/Los_Angeles 58 | Summary of the event 59 | Description of the event 60 | Location of the event 61 |
62 | 63 | 64 | 65 | ``` 66 | 67 |
68 | 69 | ### Parameters 70 | 71 | | Parameter | Description 72 | |:------------------ |:----------------------------------------------------------- 73 | | start 💥 | **REQUIRED**. `10/20/2022 03:00 PM`

Start date of the event. Accepts most date/time formats, e.g. `10/20/2022 03:00 PM` (12-hour format) or `20-10-2022 15:00` (24-hour format). Use numeric values to describe the date, e.g. "10/20/2022" and not textual, e.g. "October 20th, 2022". Dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed. If, however, the year is given in a two digit format and the separator is a dash (-, the date string is parsed as y-m-d. To avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD) dates.

Date examples: `10/20/2022 03:00 PM` or `20-10-2022 15:00` or `2022/10/20 03:00 PM` or `2022-10-20 15:00` 74 | | end | `10/20/2022 05:00 PM`

End date of the event. Accepts most date/time formats, e.g. `10/20/2022 05:00 PM` (12-hour format) or `20-10-2022 17:00` (24-hour format). Use numeric values to describe the date, e.g. "10/20/2022" and not textual, e.g. "October 20th, 2022". Dates in the m/d/y or d-m-y formats are disambiguated by looking at the separator between the various components: if the separator is a slash (/), then the American m/d/y is assumed; whereas if the separator is a dash (-) or a dot (.), then the European d-m-y format is assumed. If, however, the year is given in a two digit format and the separator is a dash (-, the date string is parsed as y-m-d. To avoid potential ambiguity, it's best to use ISO 8601 (YYYY-MM-DD) dates.

Date examples: `10/20/2022 05:00 PM` or `20-10-2022 17:00` or `2022/10/20 05:00 PM` or `2022-10-20 17:00`. If end is not defined, the end date is automatically set to start date plus one hour. 75 | | timezone | `Europe/Paris`

The events time zone, e.g. Europe/Paris or America/Los_Angeles. If timezone is applied (highly recommended), date/time will be converted to Zulu time / GMT / UTC. If timezone is not applied, date/time will be parsed as is (fluid date/time). ** Please notice: We're currently using the Microsoft Events API for inserting events into Outlook.com and Office 365. Those options does not allow fluid time and a timezone is required. Explanation: The timezone parameter makes sure the date/time is correct no matter if you are in New York or Sydney. If your event has users from multiple time zones in the world, it's highly recommended to use the parameter. 76 | | title 💥 | **REQUIRED**. `Title of event`

Title of the event. Single line string. 77 | | description | `Description of event`

Description of the event. Use `
` to separate lines. The field accepts plain text or simplified HTML. Simplified HTML is supported by calendar clients like Outlook and Apple Calendar. If the calendar client does accept HTML, the content of the field is automatically converted into readable text. Keep the description short and to the point. Link to a website for further details if the event description is long. Maximum 500 characters recommended. Reason: Most modern browsers allow an unlimited number of characters to be transferred by the browser. Internet Explorer / Edge only allows ~2000 characters. A 500 characters maximum is recommended to make sure your event is cross browser compatible. 78 | | location | `Eiffel Tower`

Event location, e.g. "Eiffel Tower, Paris". 79 | | organizer | `John Johnson`

Event organizer, e.g. "John Johnson". If you fill out organizer you must also include the organizer_email field. If you include an organizer and an organizer_email, the event is considered to be a "meeting" by calendar clients like Outlook. If you don't include the fields, the event is considered to be an "appointment". 80 | | organizer_email | `john@example.com`

Event organizer e-mail, e.g. "your@email.com". If you fill out organizer_email you must also include the organizer field. If you include an organizer and an organizer_email, the event is considered to be a "meeting" by calendar clients like Outlook. If you don't include the fields, the event is considered to be an "appointment". 81 | | all_day_event | `true`

All day event. Accepts `true` or `false`. 82 | | date_format | `MM/DD/YYYY`

The format of the date in start and end. Accepts the values `MM/DD/YYYY` or `DD/MM/YYYY` only. Lets the engine know how to handle the date, e.g. 12-hour format (MM/DD/YYYY) or 24-hour format (DD/MM/YYYY). 83 | | alarm_reminder | `15`

Event reminder. Trigger an event reminder e.g. "15" minutes before the event starts. Accepted input: Number. Example: Reminder "15" minutes before event starts = 15 or one day before event starts : 60 minutes x 24 hours = 1440.

Event reminders are currently supported by: Apple Calendar, Google Calendar (using Google Events API), Outlook, Outlook.com (using Microsoft Events API) 84 | | recurring | `FREQ=DAILY;INTERVAL=2;COUNT=5`

Make the event repeat for a number of times. Please notice: The start date/time must match the recurrence rule in order to work in strict calendar systems like Outlook and Apple Calendar.

Recurring rules are currently supported by: Apple Calendar, Google Calendar (using "Direct" and Google Events API), Office 365 (using the Microsoft Events API), Outlook, Outlook.com (using Microsoft Events API).

On AddEvent.com you can find a brilliant RRule generator: https://www.addevent.com/documentation/add-to-calendar-button 85 | | calname | `use-title`

Custom filenaming of the .ics file used for e.g. Outlook and Apple Calendar. If not specified the name defaults to "event.ics". Use the phrase use-title to use the title from the title parameter or enter a custom filename. 86 | | attendees | `joe@example.com`

Add one or multiple attendees (pre-populated) to the event. Enables the pre-populated attendee(s) to get a response from the attendee. Separate multiple attendees (email addresses) with a comma.

Example: `joe@example.com,jack@example.com` 87 | | uid | `my-unique-id123@addevent.com`

Define your own UID for the event. If not specified, a system UID is generated. Please notice; Yahoo Calendar reports error 404 if an UID is defined. We therefore don't include UID's in Yahoo Calendar. Warning. Use this option only if it serves a purpose in your coding. 88 | | sequence | `3`

Sequence is the number of times your event has been changed/updated and should be used in combination with an UID. Warning. Use this option only if it serves a purpose in your coding. 89 | | status | `CONFIRMED`

Define the status parameter in the .ics file used for e.g. Outlook and Apple Calendar.

The options can be `CONFIRMED`, `TENTATIVE`, `CANCELLED`, `NEEDS-ACTION`, `COMPLETED`, `IN-PROCESS` according to the iCalendar guidelines.

If the value is not defined (recommended), the system defaults to "CONFIRMED". Warning. Use this option only if it serves a purpose in your coding. 90 | | client | `ACCOUNT-CLIENT-ID`

The client field refers to your account ID. If you want the domain on which your "Add to Calendar" button appears to be automatically added to your accounts list of domains, then include the client tag in the button code. 91 | | method | `PUBLISH`

If defined, a method parameter is added in the .ics file used by e.g. Outlook and Apple Calendar. If not defined, no method parameter is added in the .ics file. http://www.kanzaki.com/docs/ical/method.html + https://tools.ietf.org/html/rfc2446.

Examples of usage: `PUBLISH`, `REQUEST`, `CANCEL`, `REFRESH`.

Warning. Use this option only if it serves a purpose in your coding. 92 | | transp | `TRANSPARENT`

Determines whether the event appears as "free" or "busy" on the users calendar. Default value is OPAQUE (busy).

Accepted values: `TRANSPARENT` or `OPAQUE`. 93 | 94 |
95 | 96 | ### Button controls (HTML attributes) 97 | 98 | | Parameter | Description 99 | |:------------------- |:----------------------------------------------------------- 100 | | data-direct | `
`

The attribute disables the dropdown and makes the button a direct link to the service specified.

Accepted values: `apple` or `google` or `office365` or `outlook` or `outlookcom` or `yahoo` 101 | | data-dropdown-x | `
`

Control the horizontal position of the dropdown.

Accepted values: `left` or `right` or `auto` 102 | | data-dropdown-y | `
`

Control the vertical position of the dropdown.

Accepted values: `up` or `down` or `auto` 103 | | data-render | `
`

The attribute ensures that the options are generated and displayed at load. The attribute furthermore disables the default CSS.

Accepted value: `inline-buttons` 104 | | data-styling | `
`

The attribute disables the default CSS.

Accepted value: `none` 105 | | data-intel | `
`

If we can detect which device the user is on (e.g. an iDevice) it makes sense to automatically select the "Apple" option on click instead of showing the dropdown option. The behavior can be disabled by setting "data-intel" to "false".

Accepts: `true` or `false`. Default is true. 106 | 107 |
108 | 109 | ### Button controls (Javascript) 110 | 111 | #### Example: Change labels in drop-down 112 | 113 | ```html 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 133 | 134 | 135 | 136 | 137 | 138 |
139 | Add to Calendar 140 | 10/20/2022 08:00 AM 141 | 10/20/2022 10:00 AM 142 | America/Los_Angeles 143 | Summary of the event 144 | Description of the event 145 |
146 | 147 | 148 | 149 | ``` 150 | 151 | #### Example: Remove AddEvent from the drop-down 152 | 153 | ```html 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 165 | 166 | 169 | 170 | 171 | 178 | 179 | 180 | 181 | 182 | 183 |
184 | Add to Calendar 185 | 10/20/2022 08:00 AM 186 | 10/20/2022 10:00 AM 187 | America/Los_Angeles 188 | Summary of the event 189 | Description of the event 190 |
191 | 192 | 193 | 194 | ``` 195 | 196 | #### Example: No CSS. Unstyled button 197 | 198 | ```html 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 213 | 214 | 218 | 219 | 220 | 221 | 222 | 223 |
224 | Add to Calendar 225 | 10/20/2022 08:00 AM 226 | 10/20/2022 10:00 AM 227 | America/Los_Angeles 228 | Summary of the event 229 | Description of the event 230 |
231 | 232 | 233 | 234 | ``` 235 | 236 | #### Example: Show options drop-down on mouseover 237 | 238 | ```html 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 253 | 254 | 255 | 256 | 257 | 258 |
259 | Add to Calendar 260 | 10/20/2022 08:00 AM 261 | 10/20/2022 10:00 AM 262 | America/Los_Angeles 263 | Summary of the event 264 | Description of the event 265 |
266 | 267 | 268 | 269 | ``` 270 | 271 | #### Example: Sort order of drop-down options 272 | 273 | ```html 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 288 | 289 | 290 | 291 | 292 | 293 |
294 | Add to Calendar 295 | 10/20/2022 08:00 AM 296 | 10/20/2022 10:00 AM 297 | America/Los_Angeles 298 | Summary of the event 299 | Description of the event 300 |
301 | 302 | 303 | 304 | ``` 305 | 306 | ## Who we are 307 | 308 | Behind AddEvent, Inc. there is a team of passionate people building event and calendar service software. 309 | 310 | With a suite of services ([Share Events](https://www.addevent.com/solutions/share-events), [Collect RSVPs](https://www.addevent.com/solutions/collect-rsvp-events), [Subscription calendar](https://www.addevent.com/solutions/subscription-calendars), [Embeddable calendar](https://www.addevent.com/solutions/embeddable-calendar), [Automated events](https://www.addevent.com/solutions/automated-events)) and their powerful APIs, we power customer communication and attendance. 311 | 312 | ## Thank you 313 | * Thousands of customers providing useful feedback and users using cryptic computer/browser setups where the "Add to Calendar" button also needs to work. ❤️ 314 | * Millions of end-users using and breaking our services on a daily basis ❤️ 315 | * DEV team on AddEvent.com (United States, Spain, Denmark, Romania, Malaysia) for daily making sure everything is in mint condition 316 | * [Michael Nilsson](https://nilsson.co) Original creator (Denmark) 317 | 318 | ## Contact us 319 | - Send us an email at support@addevent.com 320 | -------------------------------------------------------------------------------- /atc.1.6.3.js: -------------------------------------------------------------------------------- 1 | /* Singleline functions 2 | ---------------------------------------------------------------- */ 3 | 4 | function $d(d){ 5 | return document.getElementById(d); 6 | } 7 | 8 | var addeventatc = function(){ 9 | 10 | // Variables 11 | var atc_loaded = false, protocol, base_path, base_dom, icon_path, dropzcx = 1, license, mouseover = false, css = true, btn_found = false, btn_expo = false, btn_obj, mouseover_active = false, mouseover_timer, zindex = 1; 12 | var dropdown_order = '', drop_appleical = true, drop_google = true, drop_office365 = true, drop_outlook = true, drop_outlookcom = true, drop_yahoo = true, drop_facebook = true; 13 | var label_appleical = 'Apple', label_google = 'Google (online)', label_office365 = 'Office 365 (online)', label_outlook = 'Outlook', label_outlookcom = 'Outlook.com (online)', label_yahoo = 'Yahoo (online)', label_fb_event = 'Facebook Event'; 14 | var reg_button_click = null, reg_button_mouseover = null, reg_button_mouseout = null, reg_button_dropdown_show = null, reg_button_dropdown_hide = null, reg_button_dropdown_click = null, keyboardnav = false, reg_timer; 15 | 16 | return { 17 | initialize:function(){ 18 | 19 | // Loaded? 20 | if(!atc_loaded){ 21 | 22 | // Set loaded 23 | atc_loaded = true; 24 | 25 | // Set async ready 26 | try{addeventasync();}catch(e){} 27 | 28 | // Get protocol 29 | protocol = 'https:'; 30 | 31 | // Set base domain 32 | base_dom = 'addevent.com'; 33 | 34 | // Set path 35 | base_path = protocol + '//' + base_dom; 36 | 37 | // Icon path, SVG supported? 38 | icon_path = (typeof SVGRect != 'undefined' ? 'https://cdn.addevent.com/libs/imgs/icon-calendar-t1.svg' : 'https://cdn.addevent.com/libs/imgs/icon-calendar-t5.png'); 39 | 40 | // Apply temporary css 41 | addeventatc.trycss(); 42 | 43 | // Get buttons 44 | addeventatc.generate(); 45 | 46 | } 47 | 48 | }, 49 | generate:function(){ 50 | 51 | // Get items 52 | var items = document.getElementsByTagName('*'); 53 | 54 | // Loop 55 | for(var d=0;d'+label_appleical+'';} 428 | if(drop_google && dda[a]=='google'){drop_cont += ''+label_google+'';} 429 | if(drop_office365 && dda[a]=='office365'){drop_cont += ''+label_office365+'';} 430 | if(drop_outlook && dda[a]=='outlook'){drop_cont += ''+label_outlook+'';} 431 | if(drop_outlookcom && dda[a]=='hotmail' || drop_outlookcom && dda[a]=='outlookcom'){drop_cont += ''+label_outlookcom+'';} 432 | if(drop_yahoo && dda[a]=='yahoo' && !rcrl){drop_cont += ''+label_yahoo+'';} 433 | 434 | // Facebook event? 435 | if(fbevent && dda[a]=='facebook'){ 436 | if(drop_facebook && dda[a]=='facebook'){drop_cont += ''+label_fb_event+'';} 437 | } 438 | 439 | } 440 | 441 | // Credits 442 | if(!addeventatc.getlicense(license)){ 443 | drop_cont += 'AddEvent.com'; 444 | } 445 | 446 | // Drop down container 447 | var delm = $d(fid+'-drop'); 448 | 449 | // No drop down, create one 450 | if(!delm){ 451 | 452 | // Create element 453 | var nd = document.createElement('span'); 454 | 455 | // Attributes 456 | nd.id = fid+'-drop'; 457 | nd.className = 'addeventatc_dropdown'; 458 | nd.setAttribute('aria-hidden', 'true'); 459 | nd.setAttribute('aria-labelledby', fid); 460 | nd.setAttribute('role', 'menu'); 461 | 462 | // Set content 463 | nd.innerHTML = drop_cont; 464 | 465 | // Append 466 | obj.appendChild(nd); 467 | 468 | //if(obj.getAttribute('data-render')=='inline-buttons'){ 469 | // obj.appendChild(nd); 470 | //}else{ 471 | // document.getElementsByTagName('body')[0].appendChild(nd); 472 | //} 473 | 474 | } 475 | 476 | // Append click 477 | if($d(fid+'-appleical')){$d(fid+'-appleical').onclick = function(){addeventatc.click({button:fid,service:'appleical',id:opts.id});};} 478 | if($d(fid+'-google')){$d(fid+'-google').onclick = function(){addeventatc.click({button:fid,service:'google',id:opts.id});};} 479 | if($d(fid+'-office365')){$d(fid+'-office365').onclick = function(){addeventatc.click({button:fid,service:'office365',id:opts.id});};} 480 | if($d(fid+'-outlook')){$d(fid+'-outlook').onclick = function(){addeventatc.click({button:fid,service:'outlook',id:opts.id});};} 481 | if($d(fid+'-outlookcom')){$d(fid+'-outlookcom').onclick = function(){addeventatc.click({button:fid,service:'outlookcom',id:opts.id});};} 482 | if($d(fid+'-yahoo')){$d(fid+'-yahoo').onclick = function(){addeventatc.click({button:fid,service:'yahoo',id:opts.id});};} 483 | if($d(fid+'-facebook')){$d(fid+'-facebook').onclick = function(){addeventatc.click({button:fid,service:'facebook',id:opts.id});};} 484 | if($d(fid+'-home')){$d(fid+'-home').onclick = function(){addeventatc.click({button:fid,service:'home',id:opts.id});};} 485 | 486 | // Show 487 | addeventatc.show(fid,opts); 488 | 489 | } 490 | 491 | } 492 | 493 | // Set current button object 494 | btn_obj = obj; 495 | 496 | // Return 497 | return false; 498 | 499 | } 500 | 501 | }, 502 | click:function(opts){ 503 | 504 | // Variables 505 | var obj, burl, new_window = true, service_url; 506 | 507 | // Reference 508 | var ref = window.location.href; 509 | //var ref = location.origin; 510 | 511 | // Ref backup 512 | //if(typeof location.origin === 'undefined'){ref = location.protocol + '//' + location.host;} 513 | 514 | // Object 515 | obj = $d(opts.button); 516 | 517 | // Does object exists? 518 | if(obj){ 519 | 520 | // Go to AddEvent.com? 521 | if(opts.service == 'home'){ 522 | 523 | // Service URL 524 | if(window.configAeBaseUrl){ 525 | service_url = 'https://' + window.configAeBaseUrl; 526 | }else{ 527 | service_url = 'https://www.addevent.com'; 528 | } 529 | 530 | }else{ 531 | 532 | // Get burl 533 | burl = addeventatc.getburl({id:opts.button,facebook:false}); 534 | 535 | // Service URL 536 | if(window.configAeBaseUrl){ 537 | service_url = 'https://' + window.configAeBaseUrl + '/create/?service=' + opts.service + burl + '&reference=' + ref; 538 | }else{ 539 | service_url = 'https://www.addevent.com/create/?service=' + opts.service + burl + '&reference=' + ref; 540 | } 541 | 542 | // Change new window object 543 | if(opts.service == 'outlook' || opts.service == 'appleical'){ 544 | 545 | // Set 546 | new_window = false; 547 | 548 | // Override service URL (if on iOS Chrome, Facebook webapp etc) 549 | if(addeventatc.usewebcal()){ 550 | if(window.configAeBaseUrl){ 551 | service_url = 'webcal://' + window.configAeBaseUrl + '/create/?uwc=on&service=' + opts.service + burl + '&reference=' + ref; 552 | }else{ 553 | service_url = 'webcal://www.addevent.com/create/?uwc=on&service=' + opts.service + burl + '&reference=' + ref; 554 | } 555 | } 556 | 557 | } 558 | 559 | // Any "data-id"? 560 | var btnfid = obj.getAttribute('data-id'); 561 | 562 | // Any "data-single"? 563 | var btnsingle = obj.getAttribute('data-single'), qsgl1 = '', qsgl2 = ''; 564 | 565 | // Any queries? 566 | if(btnsingle!==null){ 567 | if(btnsingle == 'true'){ 568 | qsgl1 = 'single/'; 569 | qsgl2 = '/single'; 570 | } 571 | } 572 | 573 | // In case there is, override the service_url 574 | if(btnfid!==null){ 575 | 576 | if(addeventatc.usewebcal()){ 577 | if(window.configAeBaseUrl){ 578 | service_url = 'webcal://' + window.configAeBaseUrl + '/event/' + btnfid + '+' + opts.service + '/' + qsgl1 + '?uwc=on'; 579 | }else{ 580 | service_url = 'webcal://www.addevent.com/event/' + btnfid + '+' + opts.service + '/' + qsgl1 + '?uwc=on'; 581 | } 582 | }else{ 583 | if(window.configAeBaseUrl){ 584 | service_url = 'https://' + window.configAeBaseUrl + '/event/' + btnfid + '+' + opts.service + qsgl2; 585 | }else{ 586 | service_url = 'https://www.addevent.com/event/' + btnfid + '+' + opts.service + qsgl2; 587 | } 588 | } 589 | 590 | } 591 | 592 | } 593 | 594 | // Create ghost link if it doesn't exists 595 | if(!$d('atecllink')){ 596 | 597 | // Create a tag 598 | var atecl = document.createElement("a"); 599 | 600 | // Set attributes 601 | atecl.id = 'atecllink'; 602 | atecl.rel = 'external'; 603 | atecl.setAttribute('data-role','none'); 604 | atecl.innerHTML = '{addeventatc-ghost-link}'; 605 | atecl.style.display = 'none'; 606 | 607 | // Append 608 | document.body.appendChild(atecl); 609 | 610 | } 611 | 612 | // Set ghost link 613 | var ategl = $d('atecllink'); 614 | 615 | // Set target 616 | if(new_window){ 617 | ategl.target = '_blank'; 618 | }else{ 619 | ategl.target = '_self'; 620 | } 621 | 622 | // Target override? 623 | if(window.configAeATCTarget){ 624 | ategl.target = window.configAeATCTarget; 625 | } 626 | 627 | // Update href 628 | ategl.href = service_url; 629 | 630 | // Click the ghost link 631 | addeventatc.eclick('atecllink'); 632 | 633 | // Track click 634 | addeventatc.track({ 635 | typ:'click', 636 | cal:opts.service 637 | }); 638 | 639 | // Callback trigger: Button dropdown click 640 | if(reg_button_dropdown_click!=null){ 641 | 642 | // Trigger 643 | addeventatc.trigger('button_dropdown_click',{id:opts.button,service:opts.service}); 644 | 645 | // Cancel other trigger events 646 | try{ 647 | var wevt = event || window.event; 648 | wevt.stopPropagation(); 649 | }catch(e){} 650 | 651 | } 652 | 653 | } 654 | 655 | }, 656 | mouseout:function(f,opts){ 657 | 658 | // Set 659 | mouseover_active = false; 660 | 661 | // Hide all 662 | addeventatc.hideandreset(); 663 | 664 | // Callback trigger: Button mouseover 665 | if(reg_button_mouseout!=null){addeventatc.trigger('button_mouseout',{id:opts.id});} 666 | 667 | }, 668 | show:function(id,opts){ 669 | 670 | // Get object and drop down 671 | var obj = $d(id); 672 | var dro = $d(id + '-drop'); 673 | 674 | // Object exists 675 | if(obj && dro){ 676 | 677 | // Get display property 678 | var dis = addeventatc.getstyle(dro, 'display'); 679 | 680 | if(dis == 'block'){ 681 | 682 | // Hide all 683 | addeventatc.hideandreset(); 684 | 685 | }else{ 686 | 687 | // Reset all 688 | addeventatc.hideandreset(true); 689 | 690 | // Show 691 | dro.style.display = 'block'; 692 | 693 | // Remove outline 694 | obj.style.outline = '0'; 695 | 696 | // Get highest zindex 697 | zindex = addeventatc.topzindex(); 698 | 699 | // Set zindex 700 | obj.style.zIndex = zindex + 1; 701 | 702 | // Trim spaces 703 | obj.className = obj.className.replace(/\s+/g, ' '); 704 | 705 | // Set arias 706 | dro.setAttribute('aria-hidden', 'false'); 707 | 708 | // Keyboard? 709 | if(opts.keynav){ 710 | addeventatc.keyboard(this,{type:'keyboard',id:id,key:'down'}); 711 | } 712 | 713 | // Any drop down directions? 714 | var dddx = obj.getAttribute('data-dropdown-x'), dddy = obj.getAttribute('data-dropdown-y'), o = 'auto', a = 'auto'; 715 | 716 | // Set if specified 717 | if(dddx!=null){a = dddx;} 718 | if(dddy!=null){o = dddy;} 719 | 720 | // Reset 721 | dro.style.left = '0px'; 722 | dro.style.top = '0px'; 723 | dro.style.display = 'block'; 724 | 725 | // Get dimensions 726 | var oh = parseInt(obj.offsetHeight); 727 | var ow = parseInt(obj.offsetWidth); 728 | var dh = parseInt(dro.offsetHeight); 729 | var dw = parseInt(dro.offsetWidth); 730 | var por = addeventatc.viewport(); 731 | var porW = parseInt(por.w); 732 | var porH = parseInt(por.h); 733 | var porX = parseInt(por.x); 734 | var porY = parseInt(por.y); 735 | var pos = addeventatc.elementposition(dro); 736 | var ox = parseInt(pos.x); 737 | var oy = parseInt(pos.y); 738 | var obs = addeventatc.elementposition(obj); 739 | var obx = obs.x; 740 | var oby = obs.y; 741 | var drohy = oy + dh; 742 | var srchy = porH + porY; 743 | var drowy = ox + dw; 744 | var srcwy = porW + porX; 745 | var drox = 0, dropy = 0; 746 | var d_c = ''; 747 | 748 | // Drop down offset position 749 | var def_y = oby - ((dh / 2) - (oh)), def_x = (obx - 2); 750 | 751 | // Available display 752 | if(o=='down' && a=='left'){ 753 | drox = '-2px';dropy = '-2px';d_c = 'topdown'; 754 | }else if(o=='up' && a=='left'){ 755 | drox = '0px';dropy = -(dh-oh-2) + 'px'; 756 | }else if(o=='down' && a=='right'){ 757 | drox = -(dw-ow-2) + 'px';dropy = '-2px';d_c = 'topdown'; 758 | }else if(o=='up' && a=='right'){ 759 | drox = -(dw - ow - 2) + 'px';dropy = -(dh-oh-2) + 'px'; 760 | }else if(o=='auto' && a=='left'){ 761 | drox = '0px'; 762 | if(def_y < porY){dropy = '-2px';d_c = 'topdown';}else if((def_y + dh) > (porY + porH)){dropy = -(dh-oh-2) + 'px';}else{dropy = -((dh/2)-(oh)) + 'px';} 763 | }else if(o=='auto' && a=='right'){ 764 | drox = -(dw - ow - 2) + 'px'; 765 | if(def_y < porY){dropy = '-2px';d_c = 'topdown';}else if((def_y + dh) > (porY + porH)){dropy = -(dh-oh-2) + 'px';}else{dropy = -((dh/2)-(oh)) + 'px';} 766 | }else if(o=='down' && a=='auto'){ 767 | if(drowy>srcwy){drox = -(dw - ow - 2) + 'px';}else{drox = '-2px';} 768 | dropy = '-2px';d_c = 'topdown'; 769 | }else if(o=='up' && a=='auto'){ 770 | if(drowy>srcwy){drox = -(dw - ow - 2) + 'px';}else{drox = '-2px';} 771 | dropy = -(dh-oh-2) + 'px'; 772 | }else{ 773 | if(def_y < porY){dropy = '-2px';d_c = 'topdown';}else if((def_y + dh) > (porY + porH)){dropy = -(dh-oh-2) + 'px';}else{dropy = -((dh/2)-(oh)) + 'px';} 774 | if(drowy>srcwy){drox = -(dw - ow - 2) + 'px';}else{drox = '-2px';} 775 | } 776 | 777 | // Set top left 778 | dro.style.left = drox; 779 | dro.style.top = dropy; 780 | 781 | // Special direction? 782 | if(d_c != ''){ 783 | dro.className = dro.className + ' ' + d_c; 784 | } 785 | 786 | // Append 787 | setTimeout(function(){ 788 | dro.className = dro.className + ' addeventatc-selected'; 789 | }, 1); 790 | 791 | // Callback trigger: Button click 792 | if(opts.type == 'click'){ 793 | if(reg_button_click!=null){addeventatc.trigger('button_click',{id:id});} 794 | } 795 | 796 | // Callback trigger: Button dropdown show 797 | if(reg_button_dropdown_show!=null){addeventatc.trigger('button_dropdown_show',{id:id});} 798 | 799 | } 800 | 801 | } 802 | 803 | }, 804 | hide:function(cls){ 805 | 806 | // Variables 807 | var anyinstance = false; 808 | 809 | // Any instances of addeventatc? 810 | 811 | if(typeof cls === 'string' && cls !== '' || cls instanceof String && cls !== ''){ 812 | if(cls.indexOf('addeventatc')>-1 || cls.indexOf('atc_node')>-1){ 813 | 814 | // Set 815 | anyinstance = true; 816 | 817 | } 818 | } 819 | 820 | // Reset buttons 821 | if(!anyinstance){ 822 | 823 | // Hide all 824 | addeventatc.hideandreset(); 825 | 826 | } 827 | 828 | }, 829 | hideandreset:function(noreg){ 830 | 831 | // Variables 832 | var button_id = ''; 833 | 834 | // Get items 835 | var items = document.getElementsByTagName('*'); 836 | 837 | // Loop 838 | for(var d=0;dozin){ 1162 | ozin = zin; 1163 | } 1164 | 1165 | } 1166 | 1167 | } 1168 | } 1169 | 1170 | // Return 1171 | return ozin; 1172 | 1173 | }, 1174 | viewport:function(){ 1175 | 1176 | // Variables 1177 | var w = 0, h = 0, y = 0, x = 0; 1178 | 1179 | // Get width + height 1180 | if(typeof(window.innerWidth)=='number'){ 1181 | w = window.innerWidth; 1182 | h = window.innerHeight; 1183 | }else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)){ 1184 | w = document.documentElement.clientWidth; 1185 | h = document.documentElement.clientHeight; 1186 | }else if(document.body && (document.body.clientWidth || document.body.clientHeight)){ 1187 | w = document.body.clientWidth; 1188 | h = document.body.clientHeight; 1189 | } 1190 | 1191 | // Get scroll left + top 1192 | if(document.all){ 1193 | x = (document.documentElement.scrollLeft) ? document.documentElement.scrollLeft : document.body.scrollLeft; 1194 | y = (document.documentElement.scrollTop) ? document.documentElement.scrollTop : document.body.scrollTop; 1195 | }else{ 1196 | x = window.pageXOffset; 1197 | y = window.pageYOffset 1198 | } 1199 | 1200 | // Return 1201 | return {w:w,h:h,x:x,y:y}; 1202 | 1203 | }, 1204 | elementposition:function(obj){ 1205 | 1206 | // Variables 1207 | var x = 0, y = 0; 1208 | 1209 | // Get element position 1210 | if(obj.offsetParent){ 1211 | x=obj.offsetLeft; 1212 | y=obj.offsetTop; 1213 | while(obj=obj.offsetParent){ 1214 | x+=obj.offsetLeft; 1215 | y+=obj.offsetTop; 1216 | } 1217 | } 1218 | 1219 | // Return 1220 | return {x:x,y:y}; 1221 | 1222 | }, 1223 | getstyle:function(el,prop){ 1224 | 1225 | // Variables 1226 | var x = el;var y; 1227 | 1228 | // Get property 1229 | if(x.currentStyle){ 1230 | y = x.currentStyle[prop]; 1231 | }else if (window.getComputedStyle){ 1232 | y = document.defaultView.getComputedStyle(x,null).getPropertyValue(prop); 1233 | } 1234 | 1235 | // Return 1236 | return y; 1237 | 1238 | }, 1239 | getlicense:function(val){ 1240 | 1241 | // Variables 1242 | var ref = location.origin, correct = false; 1243 | 1244 | // Ref backup 1245 | if(typeof location.origin === 'undefined'){ref = location.protocol + '//' + location.host;} 1246 | 1247 | // Any license? 1248 | if(val){ 1249 | 1250 | // Get letters 1251 | var a = val.substring(0,1), z = val.substring(9,10), m = val.substring(17,18); 1252 | 1253 | // Validate 1254 | if(a=='a' && z=='z' && m=='m'){ 1255 | 1256 | // Set 1257 | correct = true; 1258 | 1259 | } 1260 | 1261 | } 1262 | 1263 | // Always allowed on our domains 1264 | if(ref.indexOf('addevent.com')==-1 && val=='aao8iuet5zp9iqw5sm9z' || ref.indexOf('addevent.to')==-1 && val=='aao8iuet5zp9iqw5sm9z' || ref.indexOf('addevent.com')==-1 && val=='aao8iuet5zp9iqw5sm9z'){ 1265 | 1266 | // Set 1267 | correct = true; 1268 | 1269 | } 1270 | 1271 | // Return 1272 | return correct; 1273 | 1274 | }, 1275 | refresh:function(){ 1276 | 1277 | // Get items 1278 | var items = document.getElementsByTagName('*'), elmarray = []; 1279 | 1280 | // Loop 1281 | for(var d=0;d=itemscount){ 1568 | activenum = 1; 1569 | }else{ 1570 | activenum++; 1571 | } 1572 | }else{ 1573 | if(activenum==1){ 1574 | activenum = itemscount; 1575 | }else{ 1576 | activenum--; 1577 | } 1578 | } 1579 | 1580 | } 1581 | 1582 | // Reset 1583 | itemscount = 0; 1584 | 1585 | // Loop list again to set active and clear previous marker classes 1586 | for(var x=0;x -1) || (useragent.indexOf("fbav") > -1) && ios){ 1697 | 1698 | // Set 1699 | extbro = true; 1700 | 1701 | } 1702 | 1703 | // UI webview/embedded browser 1704 | var is_uiwebview = /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent); 1705 | 1706 | // iOS? 1707 | if(ios && is_uiwebview || ios && extbro){ 1708 | 1709 | // Any "subscription mode" cookie value? 1710 | var neq = "atc_sub_mode=", coov = false; 1711 | 1712 | // Split 1713 | var ca = document.cookie.split(';'); 1714 | 1715 | // Search cookies 1716 | for(var i=0;i loadcnt){ 1794 | 1795 | // Refresh 1796 | addeventatc.refresh(); 1797 | 1798 | } 1799 | 1800 | } 1801 | }; 1802 | }(); 1803 | 1804 | (function(funcName, baseObj){ 1805 | "use strict"; 1806 | // The public function name defaults to window.docReady 1807 | // but you can modify the last line of this function to pass in a different object or method name 1808 | // if you want to put them in a different namespace and those will be used instead of 1809 | // window.docReady(...) 1810 | funcName = funcName || "docReady"; 1811 | baseObj = baseObj || window; 1812 | var readyList = []; 1813 | var readyFired = false; 1814 | var readyEventHandlersInstalled = false; 1815 | 1816 | // call this when the document is ready 1817 | // this function protects itself against being called more than once 1818 | function ready() { 1819 | if (!readyFired) { 1820 | // this must be set to true before we start calling callbacks 1821 | readyFired = true; 1822 | for (var i = 0; i < readyList.length; i++) { 1823 | // if a callback here happens to add new ready handlers, 1824 | // the docReady() function will see that it already fired 1825 | // and will schedule the callback to run right after 1826 | // this event loop finishes so all handlers will still execute 1827 | // in order and no new ones will be added to the readyList 1828 | // while we are processing the list 1829 | readyList[i].fn.call(window, readyList[i].ctx); 1830 | } 1831 | // allow any closures held by these functions to free 1832 | readyList = []; 1833 | } 1834 | } 1835 | 1836 | function readyStateChange() { 1837 | if ( document.readyState === "complete" ) { 1838 | ready(); 1839 | } 1840 | } 1841 | 1842 | // This is the one public interface 1843 | // docReady(fn, context); 1844 | // the context argument is optional - if present, it will be passed 1845 | // as an argument to the callback 1846 | baseObj[funcName] = function(callback, context) { 1847 | if (typeof callback !== "function") { 1848 | throw new TypeError("callback for docReady(fn) must be a function"); 1849 | } 1850 | // if ready has already fired, then just schedule the callback 1851 | // to fire asynchronously, but right away 1852 | if (readyFired) { 1853 | setTimeout(function() {callback(context);}, 1); 1854 | return; 1855 | } else { 1856 | // add the function and context to the list 1857 | readyList.push({fn: callback, ctx: context}); 1858 | } 1859 | // if document already ready to go, schedule the ready function to run 1860 | // IE only safe when readyState is "complete", others safe when readyState is "interactive" 1861 | if (document.readyState === "complete" || (!document.attachEvent && document.readyState === "interactive")) { 1862 | setTimeout(ready, 1); 1863 | } else if (!readyEventHandlersInstalled) { 1864 | // otherwise if we don't have event handlers installed, install them 1865 | if (document.addEventListener) { 1866 | // first choice is DOMContentLoaded event 1867 | document.addEventListener("DOMContentLoaded", ready, false); 1868 | // backup is window load event 1869 | window.addEventListener("load", ready, false); 1870 | } else { 1871 | // must be IE 1872 | document.attachEvent("onreadystatechange", readyStateChange); 1873 | window.attachEvent("onload", ready); 1874 | } 1875 | readyEventHandlersInstalled = true; 1876 | } 1877 | } 1878 | })("addeventReady", window); 1879 | 1880 | // Detect touch 1881 | var ate_touch_capable = 'ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch || navigator.maxTouchPoints > 0 || window.navigator.msMaxTouchPoints > 0; 1882 | 1883 | /* Add to "DOM ready" + onload event */ 1884 | if(window.addEventListener){ 1885 | document.addEventListener("click", addeventatc.documentclick, false); 1886 | if(ate_touch_capable){document.addEventListener("touchend", addeventatc.documentclick, false);} 1887 | }else if(window.attachEvent){ 1888 | document.attachEvent("onclick", addeventatc.documentclick); 1889 | if(ate_touch_capable){document.attachEvent("ontouchend", addeventatc.documentclick);} 1890 | }else{ 1891 | document.onclick = function(){addeventatc.documentclick(event);}; 1892 | } 1893 | 1894 | // Load 1895 | addeventReady(function(){ 1896 | 1897 | // Initialize 1898 | addeventatc.initialize(); 1899 | 1900 | }); 1901 | 1902 | // Fallback variables 1903 | var flbckcnt = 0; 1904 | 1905 | // Fallback loading (request for 4,5 seconds) 1906 | var flbckint = setInterval(function(){ 1907 | 1908 | // Add 1909 | flbckcnt++; 1910 | 1911 | // If more than 15 attempts, then stop 1912 | if(flbckcnt >= 15 || addeventatc.isloaded()){ 1913 | 1914 | // Stop interval 1915 | clearInterval(flbckint); 1916 | 1917 | }else{ 1918 | 1919 | // Initialize 1920 | addeventatc.initialize(); 1921 | 1922 | } 1923 | 1924 | }, 300); 1925 | 1926 | // Fallback variables 1927 | var nlbckcnt = 0; 1928 | 1929 | // Pickup any async loaded buttons (request for 4,5 seconds) 1930 | var nlbckint = setInterval(function(){ 1931 | 1932 | // Add 1933 | nlbckcnt++; 1934 | 1935 | // If more than 15 attempts, then stop 1936 | if(nlbckcnt >= 15){ 1937 | 1938 | // Stop interval 1939 | clearInterval(nlbckint); 1940 | 1941 | }else{ 1942 | 1943 | // Initialize 1944 | addeventatc.notloadedcnt(); 1945 | 1946 | } 1947 | 1948 | }, 300); -------------------------------------------------------------------------------- /atc.1.6.3.min.js: -------------------------------------------------------------------------------- 1 | function $d(e){return document.getElementById(e)}var addeventatc=function(){var p,u,i,b,t,e=!1,s=1,l=!1,r=!0,v=!1,m=!1,g=!1,f="",h=!0,w=!0,k=!0,x=!0,y=!0,_=!0,T=!0,N="Apple",E="Google (online)",z="Office 365 (online)",A="Outlook",I="Outlook.com (online)",C="Yahoo (online)",$="Facebook Event",S=null,L=null,a=null,H=null,U=null,R=null;return{initialize:function(){if(!e){e=!0;try{addeventasync()}catch(e){}addeventatc.trycss(),addeventatc.generate()}},generate:function(){for(var d=document.getElementsByTagName("*"),c=0;c'+N+""),w&&"google"==l[r]&&(n+=''+E+""),k&&"office365"==l[r]&&(n+=''+z+""),x&&"outlook"==l[r]&&(n+=''+A+""),(y&&"hotmail"==l[r]||y&&"outlookcom"==l[r])&&(n+=''+I+""),_&&"yahoo"==l[r]&&!o&&(n+=''+C+""),a&&"facebook"==l[r]&&T&&"facebook"==l[r]&&(n+=''+$+"");addeventatc.getlicense(p)||(n+='AddEvent.com'),$d(d+"-drop")||((s=document.createElement("span")).id=d+"-drop",s.className="addeventatc_dropdown",s.setAttribute("aria-hidden","true"),s.setAttribute("aria-labelledby",d),s.setAttribute("role","menu"),s.innerHTML=n,c.appendChild(s)),$d(d+"-appleical")&&($d(d+"-appleical").onclick=function(){addeventatc.click({button:d,service:"appleical",id:t.id})}),$d(d+"-google")&&($d(d+"-google").onclick=function(){addeventatc.click({button:d,service:"google",id:t.id})}),$d(d+"-office365")&&($d(d+"-office365").onclick=function(){addeventatc.click({button:d,service:"office365",id:t.id})}),$d(d+"-outlook")&&($d(d+"-outlook").onclick=function(){addeventatc.click({button:d,service:"outlook",id:t.id})}),$d(d+"-outlookcom")&&($d(d+"-outlookcom").onclick=function(){addeventatc.click({button:d,service:"outlookcom",id:t.id})}),$d(d+"-yahoo")&&($d(d+"-yahoo").onclick=function(){addeventatc.click({button:d,service:"yahoo",id:t.id})}),$d(d+"-facebook")&&($d(d+"-facebook").onclick=function(){addeventatc.click({button:d,service:"facebook",id:t.id})}),$d(d+"-home")&&($d(d+"-home").onclick=function(){addeventatc.click({button:d,service:"home",id:t.id})}),addeventatc.show(d,t)}return u=c,!1}},click:function(e){var t,a,n,o=!0,d=window.location.href,c=$d(e.button);if(c){"home"==e.service?t=window.configAeBaseUrl?"https://"+window.configAeBaseUrl:"https://www.addevent.com":(n=addeventatc.getburl({id:e.button,facebook:!1}),t=window.configAeBaseUrl?"https://"+window.configAeBaseUrl+"/create/?service="+e.service+n+"&reference="+d:"https://www.addevent.com/create/?service="+e.service+n+"&reference="+d,"outlook"!=e.service&&"appleical"!=e.service||(o=!1,addeventatc.usewebcal()&&(t=window.configAeBaseUrl?"webcal://"+window.configAeBaseUrl+"/create/?uwc=on&service="+e.service+n+"&reference="+d:"webcal://www.addevent.com/create/?uwc=on&service="+e.service+n+"&reference="+d)),a=c.getAttribute("data-id"),d=n="",null!==(c=c.getAttribute("data-single"))&&"true"==c&&(n="single/",d="/single"),null!==a&&(t=addeventatc.usewebcal()?window.configAeBaseUrl?"webcal://"+window.configAeBaseUrl+"/event/"+a+"+"+e.service+"/"+n+"?uwc=on":"webcal://www.addevent.com/event/"+a+"+"+e.service+"/"+n+"?uwc=on":window.configAeBaseUrl?"https://"+window.configAeBaseUrl+"/event/"+a+"+"+e.service+d:"https://www.addevent.com/event/"+a+"+"+e.service+d)),$d("atecllink")||((i=document.createElement("a")).id="atecllink",i.rel="external",i.setAttribute("data-role","none"),i.innerHTML="{addeventatc-ghost-link}",i.style.display="none",document.body.appendChild(i));var i=$d("atecllink");if(i.target=o?"_blank":"_self",window.configAeATCTarget&&(i.target=window.configAeATCTarget),i.href=t,addeventatc.eclick("atecllink"),addeventatc.track({typ:"click",cal:e.service}),null!=R){addeventatc.trigger("button_dropdown_click",{id:e.button,service:e.service});try{(event||window.event).stopPropagation()}catch(e){}}}},mouseout:function(e,t){g=!1,addeventatc.hideandreset(),null!=a&&addeventatc.trigger("button_mouseout",{id:t.id})},show:function(e,t){var a,n,o,d,c,i,s,l,r,p,u,v,m,g,f=$d(e),h=$d(e+"-drop");f&&h&&("block"==addeventatc.getstyle(h,"display")?addeventatc.hideandreset():(addeventatc.hideandreset(!0),h.style.display="block",f.style.outline="0",b=addeventatc.topzindex(),f.style.zIndex=b+1,f.className=f.className.replace(/\s+/g," "),h.setAttribute("aria-hidden","false"),t.keynav&&addeventatc.keyboard(this,{type:"keyboard",id:e,key:"down"}),a="auto",n=null!=(u=f.getAttribute("data-dropdown-x"))?u:"auto",null!=(p=f.getAttribute("data-dropdown-y"))&&(a=p),h.style.left="0px",h.style.top="0px",h.style.display="block",o=parseInt(f.offsetHeight),d=parseInt(f.offsetWidth),c=parseInt(h.offsetHeight),i=parseInt(h.offsetWidth),g=addeventatc.viewport(),v=parseInt(g.w),s=parseInt(g.h),m=parseInt(g.x),l=parseInt(g.y),r=addeventatc.elementposition(h),u=parseInt(r.x),p=parseInt(r.y),r=(g=addeventatc.elementposition(f)).x,f=u+i,p=v+m,v=u=0,m="",g=g.y-(c/2-o),"down"==a&&"left"==n?(v=u="-2px",m="topdown"):"up"==a&&"left"==n?(u="0px",v=-(c-o-2)+"px"):"down"==a&&"right"==n?(u=-(i-d-2)+"px",v="-2px",m="topdown"):"up"==a&&"right"==n?(u=-(i-d-2)+"px",v=-(c-o-2)+"px"):"auto"==a&&"left"==n?(u="0px",gt&&addeventatc.refresh()}}}();!function(e){"use strict";e=e||window;var a=[],n=!1,o=!1;function d(){if(!n){n=!0;for(var e=0;e 2 | 3 | 4 | Add to Calendar button 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 |
22 |
23 | 24 | AddEvent 25 | 26 |
27 |
28 |

Theme

29 | 33 |
34 | 41 |
42 |
43 | 44 |
45 |
46 |
47 |

Add-to-calendar button 😍

48 |

49 | A simple and powerful add-to-calendar button for your website. 50 | Offer your users a quick and effortless way to add your events to their calendars. 51 |

52 |

53 | The “Add to Calendar” button for events on websites and calendars is easy to install, language independent, 54 | time zone and DST compatible. It works perfectly in all modern browsers, tablets and mobile devices, 55 | and with Apple Calendar, Google Calendar, Outlook, Outlook.com, Office 365, and Yahoo Calendar. 56 |

57 |
58 |
59 |
60 |

White mode brush

61 |

We've added a lot of button styles below. See anything you like?
Hit the "Get the code" button, copy it, and easily install the button and style on your website.

62 |
63 |
64 | 65 |
66 |
67 |
68 |
69 | 70 |
71 |
72 |
73 |
74 |

Design:   Our beautiful standard button

75 |
76 | 77 | 78 |
79 |
80 |
81 |
82 | 83 |
84 |
85 |
86 |
87 | 88 |
89 |
90 |
91 |
92 |

Design:   Our beautiful standard button (slightly bigger)

93 |
94 | 95 | 96 |
97 |
98 |
99 |
100 | 101 |
102 |
103 |
104 |
105 | 106 |
107 |
108 |
109 |
110 |

Design:   Date banner

111 |
112 | 113 | 114 |
115 |
116 |
117 |
118 | 119 |
120 |
121 |
122 |
123 | 124 |
125 |
126 |
127 |
128 |

Design:   Inline icons

129 |
130 | 131 | 132 |
133 |
134 |
135 |
136 | 137 |
138 |
139 |
140 |
141 | 142 |
143 |
144 |
145 |
146 |

Design:   Inline options

147 |
148 | 149 | 150 |
151 |
152 |
153 |
154 | 155 |
156 |
157 |
158 |
159 | 160 |
161 |
162 |
163 |
164 |

Design:   Microsoft UI, blue button with arrow

165 |
166 | 167 | 168 |
169 |
170 |
171 |
172 | 173 |
174 |
175 |
176 |
177 | 178 |
179 |
180 |
181 |
182 |

Design:   Plain text

183 |
184 | 185 | 186 |
187 |
188 |
189 |
190 | 191 |
192 |
193 |
194 |
195 | 196 |
197 |
198 |
199 |
200 |

Design:   Single icons

201 |
202 | 203 | 204 |
205 |
206 |
207 |
208 | 209 |
210 |
211 |
212 |
213 | 214 |
215 |
216 |
217 |
218 |

Design:   Google UI themed button

219 |
220 | 221 | 222 |
223 |
224 |
225 |
226 | 227 |
228 |
229 |
230 |
231 | 232 |
233 |
234 |
235 |
236 |

Design:   Google UI themed button (outline)

237 |
238 | 239 | 240 |
241 |
242 |
243 |
244 | 245 |
246 |
247 |
248 |
249 | 250 |
251 |
252 |
253 |
254 |

Design:   Blue button (skewed)

255 |
256 | 257 | 258 |
259 |
260 |
261 |
262 | 263 |
264 |
265 |
266 |
267 | 268 |
269 |
270 |
271 |
272 |

Design:   Blue button (skewed, outlined)

273 |
274 | 275 | 276 |
277 |
278 |
279 |
280 | 281 |
282 |
283 |
284 |
285 | 286 |
287 |
288 |
289 |
290 |

Design:   Blue button (rounded, outlined)

291 |
292 | 293 | 294 |
295 |
296 |
297 |
298 | 299 |
300 |
301 |
302 |
303 | 304 |
305 |
306 |
307 |
308 |

Design:   Blue button (rounded)

309 |
310 | 311 | 312 |
313 |
314 |
315 |
316 | 317 |
318 |
319 |
320 |
321 | 322 |
323 |
324 |
325 |
326 |

Design:   Text with dotted underline

327 |
328 | 329 | 330 |
331 |
332 |
333 |
334 | 335 |
336 |
337 |
338 |
339 | 340 |
341 |
342 |
343 |
344 |

Design:   Text with yellow underline

345 |
346 | 347 | 348 |
349 |
350 |
351 |
352 | 353 |
354 |
355 |
356 |
357 | 358 |
359 |
360 |
361 |
362 |

Design:   Plain simple button, fixed width

363 |
364 | 365 | 366 |
367 |
368 |
369 |
370 | 371 |
372 |
373 |
374 |
375 | 376 |
377 |
378 |
379 |
380 |

Design:   Blue button with arrow effect

381 |
382 | 383 | 384 |
385 |
386 |
387 |
388 | 389 |
390 |
391 | 392 |
393 |
394 | 395 |
396 |
397 |
398 |
399 |

Dark mode brush

400 |

Dark theme is becoming popular. Below you'll find the same themes as above - in dark mode.
Hit the "Get the code" button, copy it, and easily install the button and style on your website.

401 |
402 |
403 | 404 |
405 |
406 |
407 |
408 | 409 |
410 |
411 |
412 |
413 |

Design:   Our beautiful standard button

414 |
415 | 416 | 417 |
418 |
419 |
420 |
421 | 422 |
423 |
424 |
425 |
426 | 427 |
428 |
429 |
430 |
431 |

Design:   Our beautiful standard button (slightly bigger)

432 |
433 | 434 | 435 |
436 |
437 |
438 |
439 | 440 |
441 |
442 |
443 |
444 | 445 |
446 |
447 |
448 |
449 |

Design:   Date banner

450 |
451 | 452 | 453 |
454 |
455 |
456 |
457 | 458 |
459 |
460 |
461 |
462 | 463 |
464 |
465 |
466 |
467 |

Design:   Inline icons

468 |
469 | 470 | 471 |
472 |
473 |
474 |
475 | 476 |
477 |
478 |
479 |
480 | 481 |
482 |
483 |
484 |
485 |

Design:   Inline options

486 |
487 | 488 | 489 |
490 |
491 |
492 |
493 | 494 |
495 |
496 |
497 |
498 | 499 |
500 |
501 |
502 |
503 |

Design:   Microsoft UI, blue button with arrow

504 |
505 | 506 | 507 |
508 |
509 |
510 |
511 | 512 |
513 |
514 |
515 |
516 | 517 |
518 |
519 |
520 |
521 |

Design:   Plain text

522 |
523 | 524 | 525 |
526 |
527 |
528 |
529 | 530 |
531 |
532 |
533 |
534 | 535 |
536 |
537 |
538 |
539 |

Design:   Single icons

540 |
541 | 542 | 543 |
544 |
545 |
546 |
547 | 548 |
549 |
550 |
551 |
552 | 553 |
554 |
555 |
556 |
557 |

Design:   Google UI themed button

558 |
559 | 560 | 561 |
562 |
563 |
564 |
565 | 566 |
567 |
568 |
569 |
570 | 571 |
572 |
573 |
574 |
575 |

Design:   Google UI themed button (outline)

576 |
577 | 578 | 579 |
580 |
581 |
582 |
583 | 584 |
585 |
586 |
587 |
588 | 589 |
590 |
591 |
592 |
593 |

Design:   Blue button (skewed)

594 |
595 | 596 | 597 |
598 |
599 |
600 |
601 | 602 |
603 |
604 |
605 |
606 | 607 |
608 |
609 |
610 |
611 |

Design:   Blue button (skewed, outlined)

612 |
613 | 614 | 615 |
616 |
617 |
618 |
619 | 620 |
621 |
622 |
623 |
624 | 625 |
626 |
627 |
628 |
629 |

Design:   Blue button (rounded, outlined)

630 |
631 | 632 | 633 |
634 |
635 |
636 |
637 | 638 |
639 |
640 |
641 |
642 | 643 |
644 |
645 |
646 |
647 |

Design:   Blue button (rounded)

648 |
649 | 650 | 651 |
652 |
653 |
654 |
655 | 656 |
657 |
658 |
659 |
660 | 661 |
662 |
663 |
664 |
665 |

Design:   Text with dotted underline

666 |
667 | 668 | 669 |
670 |
671 |
672 |
673 | 674 |
675 |
676 |
677 |
678 | 679 |
680 |
681 |
682 |
683 |

Design:   Text with yellow underline

684 |
685 | 686 | 687 |
688 |
689 |
690 |
691 | 692 |
693 |
694 |
695 |
696 | 697 |
698 |
699 |
700 |
701 |

Design:   Plain simple button, fixed width

702 |
703 | 704 | 705 |
706 |
707 |
708 |
709 | 710 |
711 |
712 |
713 |
714 | 715 |
716 |
717 |
718 |
719 |

Design:   Blue button with arrow effect

720 |
721 | 722 | 723 |
724 |
725 |
726 |
727 | 728 | 729 |
730 | 731 |
732 |
733 | 734 |
735 |
736 | 737 | 738 | 739 | -------------------------------------------------------------------------------- /example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | AddEvent 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | Add to Calendar 31 | 32 | 06/18/2022 09:00 AM 33 | 06/18/2022 11:00 AM 34 | Europe/Paris 35 | Summary of the event 36 | Description of the event 37 | Location of the event 38 |
39 | 40 | 41 |
42 |
43 | 44 | 45 | --------------------------------------------------------------------------------