add-to-calendar-button 1.7.4 → 1.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -58,15 +58,22 @@ See [jekuer.github.io/add-to-calendar-button](https://jekuer.github.io/add-to-ca
58
58
 
59
59
  ## 🌱 Setup
60
60
 
61
- ### Option 1: simple
61
+ ### Option 1: simple (self-hosted)
62
62
 
63
63
  1. Simply **download** the code from GitHub **or clone** the git repository.
64
64
  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).
65
65
  3. Include those files in your project. As usual, the css goes into the <head> (`<link rel="stylesheet" href="./assets/css/atcb.min.css">`), the js into the <body> footer (`<script src="./assets/js/atcb.min.js" defer></script>`). You can also combine them with other files, if you want to.
66
66
  4. Create your button as can be seen in the "Configuration" section below.
67
- 5. That is it. The script takes care of all the rest. :)
67
+ 5. That is it. The script takes care of all the rest.
68
68
 
69
- ### Option 2: npm
69
+ ### Option 2: simple (CDN)
70
+
71
+ 1. Instead of downloading the files, you can use the jsDeliver CDN.
72
+ 3. Put `<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/add-to-calendar-button@1.7/assets/css/atcb.min.css">` into the <head> and `<script src="https://cdn.jsdelivr.net/npm/add-to-calendar-button@1.7" defer></script>` into the <body> footer of your website.
73
+ 4. Create your button as can be seen in the "Configuration" section below.
74
+ 5. Done. And this setup also automatically keeps track of any bug fixes and minor updates!
75
+
76
+ ### Option 3: npm
70
77
 
71
78
  1. Requires Node, npm, and a project, which builds on it (e.g. React or Angular).
72
79
  2. Run **`npm install add-to-calendar-button`**.
@@ -76,7 +83,7 @@ See [jekuer.github.io/add-to-calendar-button](https://jekuer.github.io/add-to-ca
76
83
  2. 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());`
77
84
  5. 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'`;
78
85
  6. Create your button as can be seen in the "Configuration" section below.
79
- 7. That is it. The script takes care of all the rest. :)
86
+ 7. You're all done.
80
87
 
81
88
  <br />
82
89
 
@@ -3,7 +3,7 @@
3
3
  * Add-to-Calendar Button
4
4
  * ++++++++++++++++++++++
5
5
  *
6
- * Version: 1.7.4
6
+ * Version: 1.7.7
7
7
  * Creator: Jens Kuerschner (https://jenskuerschner.de)
8
8
  * Project: https://github.com/jekuer/add-to-calendar-button
9
9
  * License: MIT with “Commons Clause” License Condition v1.0
@@ -0,0 +1,756 @@
1
+ /**
2
+ * ++++++++++++++++++++++
3
+ * Add-to-Calendar Button
4
+ * ++++++++++++++++++++++
5
+ */
6
+ const atcbVersion = '1.7.7';
7
+ /* Creator: Jens Kuerschner (https://jenskuerschner.de)
8
+ * Project: https://github.com/jekuer/add-to-calendar-button
9
+ * License: MIT with “Commons Clause” License Condition v1.0
10
+ *
11
+ */
12
+
13
+
14
+
15
+ // INITIALIZE THE SCRIPT AND FUNCTIONALITY
16
+ function atcb_init() {
17
+ // let's get started
18
+ console.log("add-to-calendar button initialized (version " + atcbVersion + ")");
19
+ console.log ("See https://github.com/jekuer/add-to-calendar-button for details");
20
+ // get all placeholders
21
+ let atcButtons = document.querySelectorAll('.atcb');
22
+ // if there are some, move on
23
+ if (atcButtons.length > 0) {
24
+ // get the amount of already initialized ones first
25
+ let atcButtonsInitialized = document.querySelectorAll('.atcb_initialized');
26
+ // generate the buttons one by one
27
+ for (let i = 0; i < atcButtons.length; i++) {
28
+ // skip already initialized ones
29
+ if (atcButtons[i].classList.contains('atcb_initialized')) {
30
+ continue;
31
+ }
32
+ let atcbConfig;
33
+ // check if schema.org markup is present
34
+ let schema = atcButtons[i].querySelector('script');
35
+ // get their JSON content first
36
+ if (schema && schema.innerHTML) {
37
+ // get schema.org event markup and flatten the event block
38
+ atcbConfig = JSON.parse(schema.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(/(<(?!br)([^>]+)>)/gi, "")); // remove real code line breaks before parsing. Use <br> or \n explicitely in the description to create a line break. Also strip HTML tags (especially since stupid Safari adds stuff).
39
+ atcbConfig = atcb_parse_schema_json(atcbConfig);
40
+ // set flag to not delete HTML content later
41
+ atcbConfig['deleteJSON'] = false;
42
+ } else {
43
+ // get JSON from HTML block
44
+ atcbConfig = JSON.parse(atcButtons[i].innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(/(<(?!br)([^>]+)>)/gi, "")); // remove real code line breaks before parsing. Use <br> or \n explicitely in the description to create a line break. Also strip HTML tags (especially since stupid Safari adds stuff).
45
+ // set flag to delete HTML content later
46
+ atcbConfig['deleteJSON'] = true;
47
+ }
48
+ // rewrite config for backwards compatibility - you can remove this, if you did not use this script before v1.4.0.
49
+ atcbConfig = atcb_patch_config(atcbConfig);
50
+ // check, if all required data is available
51
+ if (atcb_check_required(atcbConfig)) {
52
+ // Rewrite dynamic dates, standardize line breaks and transform urls in the description
53
+ atcbConfig = atcb_decorate_data(atcbConfig);
54
+ // validate the config (JSON iput) ...
55
+ if (atcb_validate(atcbConfig)) {
56
+ // ... and generate the button on success
57
+ atcb_generate(atcButtons[i], i + atcButtonsInitialized.length, atcbConfig);
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+
65
+
66
+ // NORMALIZE AND PARSE JSON FROM SCHEMA.ORG MARKUP
67
+ function atcb_parse_schema_json(atcbConfig) {
68
+ try {
69
+ Object.keys(atcbConfig['event']).forEach(key => {
70
+ // move entries one level up, but skip schema types
71
+ if (key.charAt(0) !== '@') {
72
+ atcbConfig[key] = atcbConfig['event'][key];
73
+ }
74
+ });
75
+ // drop the event block and return
76
+ delete atcbConfig.event;
77
+ }
78
+ catch(err) {
79
+ console.error("add-to-calendar button problem: it seems like you use the schema.org style, but did not define it properly");
80
+ }
81
+ return atcbConfig;
82
+ }
83
+
84
+
85
+
86
+ // BACKWARDS COMPATIBILITY REWRITE - you can remove this, if you did not use this script before v1.4.0.
87
+ function atcb_patch_config(atcbConfig) {
88
+ const keyChanges = {
89
+ 'title': 'name',
90
+ 'dateStart': 'startDate',
91
+ 'dateEnd': 'endDate',
92
+ 'timeStart': 'startTime',
93
+ 'timeEnd': 'endTime',
94
+ };
95
+ Object.keys(keyChanges).forEach(key => {
96
+ if (atcbConfig[keyChanges[key]] == null && atcbConfig[key] != null) {
97
+ atcbConfig[keyChanges[key]] = atcbConfig[key];
98
+ }
99
+ });
100
+ return atcbConfig;
101
+ }
102
+
103
+
104
+
105
+ // CLEAN DATA BEFORE FURTHER VALIDATION (CONSIDERING SPECIAL RULES AND SCHEMES)
106
+ function atcb_decorate_data(atcbConfig) {
107
+ // cleanup different date-time formats
108
+ atcbConfig = atcb_date_cleanup(atcbConfig);
109
+ // calculate the real date values in case that there are some special rules included (e.g. adding days dynamically)
110
+ atcbConfig['startDate'] = atcb_date_calculation(atcbConfig['startDate']);
111
+ atcbConfig['endDate'] = atcb_date_calculation(atcbConfig['endDate']);
112
+
113
+ // if no description or already decorated, return early
114
+ if (!atcbConfig.description || atcbConfig.description_iCal) return atcbConfig;
115
+
116
+ // make a copy of the given argument rather than mutating in place
117
+ const data = Object.assign({}, atcbConfig);
118
+ // standardize any line breaks in the description and transform URLs (but keep a clean copy without the URL magic for iCal)
119
+ data.description = data.description.replace(/<br\s*\/?>/gmi, '\n');
120
+ data.description_iCal = data.description.replace('[url]','').replace('[/url]','');
121
+ data.description = data.description.replace(/\[url\](.*?)\[\/url\]/g, "<a href='$1' target='_blank' rel='noopener'>$1</a>");
122
+ return data
123
+ }
124
+
125
+
126
+
127
+ // CHECK FOR REQUIRED FIELDS
128
+ function atcb_check_required(data) {
129
+ // check for at least 1 option
130
+ if (data['options'] == null || data['options'].length < 1) {
131
+ console.error("add-to-calendar button generation failed: no options set");
132
+ return false;
133
+ }
134
+ // check for min required data (without "options")
135
+ const requiredField = ['name', 'startDate', 'endDate']
136
+ return requiredField.every(function(field) {
137
+ if (data[field] == null || data[field] == "") {
138
+ console.error("add-to-calendar button generation failed: required setting missing [" + field + "]");
139
+ return false;
140
+ }
141
+ return true;
142
+ });
143
+ }
144
+
145
+
146
+
147
+ // CALCULATE AND CLEAN UP THE ACTUAL DATES
148
+ function atcb_date_cleanup(data) {
149
+ // parse date+time format (default with Schema.org, but also an unofficial alternative to other implementation)
150
+ const endpoints = ['start', 'end'];
151
+ endpoints.forEach(function(point) {
152
+ if (data[point + 'Date'] != null) {
153
+ // remove any milliseconds information
154
+ data[point + 'Date'] = data[point + 'Date'].replace(/\..../, '').replace('Z', '');
155
+ // identify a possible time information within the date string
156
+ let tmpSplitStartDate = data[point + 'Date'].split('T');
157
+ if (tmpSplitStartDate[1] != null) {
158
+ data[point + 'Date'] = tmpSplitStartDate[0];
159
+ data[point + 'Time'] = tmpSplitStartDate[1];
160
+ }
161
+ }
162
+ // remove any seconds from time information
163
+ if (data[point + 'Time'] != null && data[point + 'Time'].length == 8) {
164
+ let timeStr = data[point + 'Time'];
165
+ data[point + 'Time'] = timeStr.substring(0, timeStr.length - 3);
166
+ }
167
+ });
168
+ return data;
169
+ }
170
+
171
+ function atcb_date_calculation(dateString) {
172
+ // replace "today" with the current date first
173
+ let today = new Date();
174
+ let todayString = (today.getMonth() + 1) + '-' + today.getDate() + '-' + today.getFullYear();
175
+ dateString = dateString.replace(/today/ig, todayString);
176
+ // check for any dynamic additions and adjust
177
+ const dateStringParts = dateString.split('+');
178
+ const dateParts = dateStringParts[0].split('-');
179
+ let newDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
180
+ if (dateParts[0].length < 4) {
181
+ // backwards compatibility for version <1.5.0
182
+ newDate = new Date(dateParts[2], dateParts[0] - 1, dateParts[1]);
183
+ }
184
+ if (dateStringParts[1] != null && dateStringParts[1] > 0) {
185
+ newDate.setDate(newDate.getDate() + parseInt(dateStringParts[1]));
186
+ }
187
+ return newDate.getFullYear() + '-' + (((newDate.getMonth() + 1) < 10 ? '0' : '') + (newDate.getMonth() + 1)) + '-' + (newDate.getDate() < 10 ? '0' : '') + newDate.getDate();
188
+ }
189
+
190
+
191
+
192
+ // VALIDATE THE JSON DATA
193
+ function atcb_validate(data) {
194
+ // validate options
195
+ const options = ['Apple', 'Google', 'iCal', 'Microsoft365', 'Outlook.com', 'MicrosoftTeams', 'Yahoo']
196
+ if (!data['options'].every(function(option) {
197
+ let cleanOption = option.split('|');
198
+ if (!options.includes(cleanOption[0])) {
199
+ console.error("add-to-calendar button generation failed: invalid option [" + cleanOption[0] + "]");
200
+ return false;
201
+ }
202
+ return true;
203
+ })) {
204
+ return false;
205
+ }
206
+ // validate date
207
+ const dates = ['startDate', 'endDate'];
208
+ let newDate = dates;
209
+ if (!dates.every(function(date) {
210
+ if (data[date].length != 10) {
211
+ console.error("add-to-calendar button generation failed: date misspelled [-> YYYY-MM-DD]");
212
+ return false;
213
+ }
214
+ const dateParts = data[date].split('-');
215
+ if (dateParts.length < 3 || dateParts.length > 3) {
216
+ console.error("add-to-calendar button generation failed: date misspelled [" + date + ": " + data[date] + "]");
217
+ return false;
218
+ }
219
+ newDate[date] = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
220
+ return true;
221
+ })) {
222
+ return false;
223
+ }
224
+ // validate time
225
+ const times = ['startTime', 'endTime'];
226
+ if (!times.every(function(time) {
227
+ if (data[time] != null) {
228
+ if (data[time].length != 5) {
229
+ console.error("add-to-calendar button generation failed: time misspelled [-> HH:MM]");
230
+ return false;
231
+ }
232
+ const timeParts = data[time].split(':');
233
+ // validate the time parts
234
+ if (timeParts.length < 2 || timeParts.length > 2) {
235
+ console.error("add-to-calendar button generation failed: time misspelled [" + time + ": " + data[time] + "]");
236
+ return false;
237
+ }
238
+ if (timeParts[0] > 23) {
239
+ console.error("add-to-calendar button generation failed: time misspelled - hours number too high [" + time + ": " + timeParts[0] + "]");
240
+ return false;
241
+ }
242
+ if (timeParts[1] > 59) {
243
+ console.error("add-to-calendar button generation failed: time misspelled - minutes number too high [" + time + ": " + timeParts[1] + "]");
244
+ return false;
245
+ }
246
+ // update the date with the time for further validation steps
247
+ if (time == 'startTime') {
248
+ newDate['startDate'] = new Date(newDate['startDate'].getTime() + (timeParts[0] * 3600000) + (timeParts[1] * 60000))
249
+ }
250
+ if (time == 'endTime') {
251
+ newDate['endDate'] = new Date(newDate['endDate'].getTime() + (timeParts[0] * 3600000) + (timeParts[1] * 60000))
252
+ }
253
+ }
254
+ return true;
255
+ })) {
256
+ return false;
257
+ }
258
+ if ((data['startTime'] != null && data['endTime'] == null) || (data['startTime'] == null && data['endTime'] != null)) {
259
+ console.error("add-to-calendar button generation failed: if you set a starting time, you also need to define an end time");
260
+ return false;
261
+ }
262
+ // validate whether end is not before start
263
+ if (newDate['endDate'] < newDate['startDate']) {
264
+ console.error("add-to-calendar button generation failed: end date before start date");
265
+ return false;
266
+ }
267
+ // on passing the validation, return true
268
+ return true;
269
+ }
270
+
271
+
272
+
273
+ // GENERATE THE ACTUAL BUTTON
274
+ function atcb_generate(button, buttonId, data) {
275
+ // clean the placeholder, if flagged that way
276
+ if (data['deleteJSON']) {
277
+ button.innerHTML = '';
278
+ }
279
+ // generate the wrapper div
280
+ let buttonTriggerWrapper = document.createElement('div');
281
+ buttonTriggerWrapper.classList.add('atcb_button_wrapper');
282
+ button.appendChild(buttonTriggerWrapper);
283
+ // generate the button trigger div
284
+ let buttonTrigger = document.createElement('button');
285
+ buttonTrigger.id = 'atcb_button_' + buttonId;
286
+ buttonTrigger.classList.add('atcb_button');
287
+ buttonTriggerWrapper.appendChild(buttonTrigger);
288
+ buttonTrigger.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 122.88"><path d="M81.61 4.73c0-2.61 2.58-4.73 5.77-4.73s5.77 2.12 5.77 4.73v20.72c0 2.61-2.58 4.73-5.77 4.73s-5.77-2.12-5.77-4.73V4.73h0zm-3.65 76.03c1.83 0 3.32 1.49 3.32 3.32s-1.49 3.32-3.32 3.32l-12.95-.04-.04 12.93c0 1.83-1.49 3.32-3.32 3.32s-3.32-1.49-3.32-3.32l.04-12.94-12.93-.05c-1.83 0-3.32-1.49-3.32-3.32s1.49-3.32 3.32-3.32l12.94.04.04-12.93c0-1.83 1.49-3.32 3.32-3.32s3.32 1.49 3.32 3.32l-.04 12.95 12.94.04h0zM29.61 4.73c0-2.61 2.58-4.73 5.77-4.73s5.77 2.12 5.77 4.73v20.72c0 2.61-2.58 4.73-5.77 4.73s-5.77-2.12-5.77-4.73V4.73h0zM6.4 45.32h110.08V21.47c0-.8-.33-1.53-.86-2.07-.53-.53-1.26-.86-2.07-.86H103c-1.77 0-3.2-1.43-3.2-3.2s1.43-3.2 3.2-3.2h10.55c2.57 0 4.9 1.05 6.59 2.74s2.74 4.02 2.74 6.59v27.06 65.03c0 2.57-1.05 4.9-2.74 6.59s-4.02 2.74-6.59 2.74H9.33c-2.57 0-4.9-1.05-6.59-2.74-1.69-1.7-2.74-4.03-2.74-6.6V48.53 21.47c0-2.57 1.05-4.9 2.74-6.59s4.02-2.74 6.59-2.74H20.6c1.77 0 3.2 1.43 3.2 3.2s-1.43 3.2-3.2 3.2H9.33c-.8 0-1.53.33-2.07.86-.53.53-.86 1.26-.86 2.07v23.85h0zm110.08 6.41H6.4v61.82c0 .8.33 1.53.86 2.07.53.53 1.26.86 2.07.86h104.22c.8 0 1.53-.33 2.07-.86.53-.53.86-1.26.86-2.07V51.73h0zM50.43 18.54c-1.77 0-3.2-1.43-3.2-3.2s1.43-3.2 3.2-3.2h21.49c1.77 0 3.2 1.43 3.2 3.2s-1.43 3.2-3.2 3.2H50.43h0z"/></svg></span>';
289
+ buttonTrigger.innerHTML += '<span class="atcb_text">' + (data['label'] || 'Add to Calendar') + '</span>';
290
+ // set event listeners for the button trigger
291
+ if (data['trigger'] == 'click') {
292
+ buttonTrigger.addEventListener('mousedown', () => atcb_toggle(data, buttonTrigger, true, false));
293
+ } else {
294
+ buttonTrigger.addEventListener('touchstart', () => atcb_toggle(data, buttonTrigger, true, false), {passive: true});
295
+ buttonTrigger.addEventListener('mouseenter', () => atcb_open(data, buttonTrigger, true, false));
296
+ }
297
+ buttonTrigger.addEventListener('keydown', function(event) { // trigger click on enter as well
298
+ if (event.key == 'Enter') {
299
+ atcb_toggle(data, buttonTrigger, true);
300
+ }
301
+ });
302
+ // update the placeholder class to prevent multiple initializations
303
+ button.classList.remove('atcb');
304
+ button.classList.add('atcb_initialized');
305
+ // show the placeholder div
306
+ if (data['inline']) {
307
+ button.style.display = 'inline-block';
308
+ } else {
309
+ button.style.display = 'block';
310
+ }
311
+ // console log
312
+ console.log("add-to-calendar button #" + (buttonId + 1) + " created");
313
+ }
314
+
315
+
316
+ function atcb_generate_dropdown_list(data) {
317
+ const optionsList = document.createElement('div');
318
+ optionsList.classList.add('atcb_list');
319
+ // generate the list items
320
+ data['options'].forEach(function(option) {
321
+ let optionParts = option.split('|');
322
+ let optionItem = document.createElement('div');
323
+ optionItem.classList.add('atcb_list_item');
324
+ optionItem.tabIndex = 0;
325
+ optionsList.appendChild(optionItem);
326
+ switch (optionParts[0]) {
327
+ case "Apple":
328
+ optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" shape-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" viewBox="0 0 640 640"><path d="M494.782 340.02c-.803-81.025 66.084-119.907 69.072-121.832-37.595-54.993-96.167-62.552-117.037-63.402-49.843-5.032-97.242 29.362-122.565 29.362-25.253 0-64.277-28.607-105.604-27.85-54.32.803-104.4 31.594-132.403 80.245C29.81 334.457 71.81 479.58 126.816 558.976c26.87 38.882 58.914 82.56 100.997 81 40.512-1.594 55.843-26.244 104.848-26.244 48.993 0 62.753 26.245 105.64 25.406 43.606-.803 71.232-39.638 97.925-78.65 30.887-45.12 43.548-88.75 44.316-90.994-.969-.437-85.029-32.634-85.879-129.439l.118-.035zM414.23 102.178C436.553 75.095 451.636 37.5 447.514-.024c-32.162 1.311-71.163 21.437-94.253 48.485-20.729 24.012-38.836 62.28-33.993 99.036 35.918 2.8 72.591-18.248 94.926-45.272l.036-.047z"/></svg></span>';
329
+ optionItem.innerHTML += '<span class="atcb_text">';
330
+ optionItem.innerHTML += optionParts[1] || 'Apple';
331
+ optionItem.innerHTML += '</span>';
332
+ optionItem.addEventListener('click', function() {
333
+ atcb_generate_ical(data);
334
+ atcb_close();
335
+ });
336
+ break;
337
+ case "Google":
338
+ optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 122.88"><path d="M93.78 29.1H29.1v64.68h64.68V29.1z" fill="#fff"/><path d="M93.78 122.88l29.1-29.1h-29.1v29.1z" fill="#f72a25"/><path d="M122.88 29.1h-29.1v64.68h29.1V29.1z" fill="#fbbc04"/><path d="M93.78 93.78H29.1v29.1h64.68v-29.1z" fill="#34a853"/><path d="M0 93.78v19.4c0 5.36 4.34 9.7 9.7 9.7h19.4v-29.1H0h0z" fill="#188038"/><path d="M122.88 29.1V9.7c0-5.36-4.34-9.7-9.7-9.7h-19.4v29.1h29.1 0z" fill="#1967d2"/><path d="M93.78 0H9.7C4.34 0 0 4.34 0 9.7v84.08h29.1V29.1h64.67V0h.01z" fill="#4285f4"/><path d="M42.37 79.27c-2.42-1.63-4.09-4.02-5-7.17l5.61-2.31c.51 1.94 1.4 3.44 2.67 4.51 1.26 1.07 2.8 1.59 4.59 1.59 1.84 0 3.41-.56 4.73-1.67 1.32-1.12 1.98-2.54 1.98-4.26 0-1.76-.7-3.2-2.09-4.32s-3.14-1.67-5.22-1.67H46.4v-5.55h2.91c1.79 0 3.31-.48 4.54-1.46 1.23-.97 1.84-2.3 1.84-3.99 0-1.5-.55-2.7-1.65-3.6s-2.49-1.35-4.18-1.35c-1.65 0-2.96.44-3.93 1.32s-1.7 2-2.12 3.24l-5.55-2.31c.74-2.09 2.09-3.93 4.07-5.52s4.51-2.39 7.58-2.39c2.27 0 4.32.44 6.13 1.32s3.23 2.1 4.26 3.65c1.03 1.56 1.54 3.31 1.54 5.25 0 1.98-.48 3.65-1.43 5.03-.95 1.37-2.13 2.43-3.52 3.16v.33c1.79.74 3.36 1.96 4.51 3.52 1.17 1.58 1.76 3.46 1.76 5.66s-.56 4.16-1.67 5.88c-1.12 1.72-2.66 3.08-4.62 4.07s-4.17 1.49-6.62 1.49c-2.84 0-5.46-.81-7.88-2.45h0 0zm34.46-27.84l-6.16 4.45-3.08-4.67 11.05-7.97h4.24v37.6h-6.05V51.43h0z" fill="#1a73e8"/></svg></span>';
339
+ optionItem.innerHTML += '<span class="atcb_text">';
340
+ optionItem.innerHTML += optionParts[1] || 'Google';
341
+ optionItem.innerHTML += '</span>';
342
+ optionItem.addEventListener('click', function() {
343
+ atcb_generate_google(data);
344
+ atcb_close();
345
+ });
346
+ break;
347
+ case "iCal":
348
+ optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 122.88"><path d="M81.61 4.73c0-2.61 2.58-4.73 5.77-4.73s5.77 2.12 5.77 4.73v20.72c0 2.61-2.58 4.73-5.77 4.73s-5.77-2.12-5.77-4.73V4.73h0zm-15.5 99.08c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2H81.9c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H66.11h0zM15.85 67.09c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H15.85h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H40.98h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2H81.9c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H66.11h0zm25.14 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H91.25h0zm-75.4 18.36c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H15.85h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H40.98h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2H81.9c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H66.11h0zm25.14 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H91.25h0zm-75.4 18.36c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H15.85h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H40.98h0zM29.61 4.73c0-2.61 2.58-4.73 5.77-4.73s5.77 2.12 5.77 4.73v20.72c0 2.61-2.58 4.73-5.77 4.73s-5.77-2.12-5.77-4.73V4.73h0zM6.4 45.32h110.07V21.47c0-.8-.33-1.53-.86-2.07-.53-.53-1.26-.86-2.07-.86H103c-1.77 0-3.2-1.43-3.2-3.2s1.43-3.2 3.2-3.2h10.55c2.57 0 4.9 1.05 6.59 2.74s2.74 4.02 2.74 6.59v27.06 65.03c0 2.57-1.05 4.9-2.74 6.59s-4.02 2.74-6.59 2.74H9.33c-2.57 0-4.9-1.05-6.59-2.74-1.69-1.7-2.74-4.03-2.74-6.6V48.52 21.47c0-2.57 1.05-4.9 2.74-6.59s4.02-2.74 6.59-2.74H20.6c1.77 0 3.2 1.43 3.2 3.2s-1.43 3.2-3.2 3.2H9.33c-.8 0-1.53.33-2.07.86-.53.53-.86 1.26-.86 2.07v23.85h0zm110.08 6.41H6.4v61.82c0 .8.33 1.53.86 2.07.53.53 1.26.86 2.07.86h104.22c.8 0 1.53-.33 2.07-.86.53-.53.86-1.26.86-2.07V51.73h0zM50.43 18.54c-1.77 0-3.2-1.43-3.2-3.2s1.43-3.2 3.2-3.2h21.49c1.77 0 3.2 1.43 3.2 3.2s-1.43 3.2-3.2 3.2H50.43h0z"/></svg></span>';
349
+ optionItem.innerHTML += '<span class="atcb_text">';
350
+ optionItem.innerHTML += optionParts[1] || 'iCal File';
351
+ optionItem.innerHTML += '</span>';
352
+ optionItem.addEventListener('click', function() {
353
+ atcb_generate_ical(data);
354
+ atcb_close();
355
+ });
356
+ break;
357
+ case "MicrosoftTeams":
358
+ optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 2228.833 2073.333"><g fill="#5059c9"><path d="M1554.637 777.5h575.713c54.391 0 98.483 44.092 98.483 98.483v524.398c0 199.901-162.051 361.952-361.952 361.952h0-1.711c-199.901.028-361.975-162-362.004-361.901v-.052-571.409c.001-28.427 23.045-51.471 51.471-51.471h0z"/><circle cx="1943.75" cy="440.583" r="233.25"/></g><g fill="#7b83eb"><circle cx="1218.083" cy="336.917" r="336.917"/><path d="M1667.323 777.5H717.01c-53.743 1.33-96.257 45.931-95.01 99.676v598.105c-7.505 322.519 247.657 590.16 570.167 598.053 322.51-7.893 577.671-275.534 570.167-598.053V877.176c1.245-53.745-41.268-98.346-95.011-99.676z"/></g><path opacity=".1" d="M1244 777.5v838.145c-.258 38.435-23.549 72.964-59.09 87.598-11.316 4.787-23.478 7.254-35.765 7.257H667.613c-6.738-17.105-12.958-34.21-18.142-51.833-18.144-59.477-27.402-121.307-27.472-183.49V877.02c-1.246-53.659 41.198-98.19 94.855-99.52H1244z"/><path opacity=".2" d="M1192.167 777.5v889.978a91.84 91.84 0 0 1-7.257 35.765c-14.634 35.541-49.163 58.833-87.598 59.09H691.975c-8.812-17.105-17.105-34.21-24.362-51.833s-12.958-34.21-18.142-51.833a631.28 631.28 0 0 1-27.472-183.49V877.02c-1.246-53.659 41.198-98.19 94.855-99.52h475.313z"/><path opacity=".2" d="M1192.167 777.5v786.312c-.395 52.223-42.632 94.46-94.855 94.855h-447.84A631.28 631.28 0 0 1 622 1475.177V877.02c-1.246-53.659 41.198-98.19 94.855-99.52h475.312z"/><path opacity=".2" d="M1140.333 777.5v786.312c-.395 52.223-42.632 94.46-94.855 94.855H649.472A631.28 631.28 0 0 1 622 1475.177V877.02c-1.246-53.659 41.198-98.19 94.855-99.52h423.478z"/><path opacity=".1" d="M1244 509.522v163.275c-8.812.518-17.105 1.037-25.917 1.037s-17.105-.518-25.917-1.037c-17.496-1.161-34.848-3.937-51.833-8.293a336.92 336.92 0 0 1-233.25-198.003 288.02 288.02 0 0 1-16.587-51.833h258.648c52.305.198 94.657 42.549 94.856 94.854z"/><use xlink:href="#C" opacity=".2"/><use xlink:href="#C" opacity=".2"/><path opacity=".2" d="M1140.333 561.355v103.148A336.92 336.92 0 0 1 907.083 466.5h138.395c52.305.199 94.656 42.551 94.855 94.855z"/><linearGradient id="A" gradientUnits="userSpaceOnUse" x1="198.099" y1="392.261" x2="942.234" y2="1681.073"><stop offset="0" stop-color="#5a62c3"/><stop offset=".5" stop-color="#4d55bd"/><stop offset="1" stop-color="#3940ab"/></linearGradient><path fill="url(#A)" d="M95.01 466.5h950.312c52.473 0 95.01 42.538 95.01 95.01v950.312c0 52.473-42.538 95.01-95.01 95.01H95.01c-52.473 0-95.01-42.538-95.01-95.01V561.51c0-52.472 42.538-95.01 95.01-95.01z"/><path fill="#fff" d="M820.211,828.193H630.241v517.297H509.211V828.193H320.123V727.844h500.088V828.193z"/><defs ><path id="C" d="M1192.167 561.355v111.442c-17.496-1.161-34.848-3.937-51.833-8.293a336.92 336.92 0 0 1-233.25-198.003h190.228c52.304.198 94.656 42.55 94.855 94.854z"/></defs></svg></span>';
359
+ optionItem.innerHTML += '<span class="atcb_text">';
360
+ optionItem.innerHTML += optionParts[1] || 'Microsoft Teams';
361
+ optionItem.innerHTML += '</span>';
362
+ optionItem.addEventListener('click', function() {
363
+ atcb_generate_teams(data);
364
+ atcb_close();
365
+ });
366
+ break;
367
+ case "Microsoft365":
368
+ optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 278050 333334" shape-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd"><path fill="#ea3e23" d="M278050 305556l-29-16V28627L178807 0 448 66971l-448 87 22 200227 60865-23821V80555l117920-28193-17 239519L122 267285l178668 65976v73l99231-27462v-316z"/></svg></span>';
369
+ optionItem.innerHTML += '<span class="atcb_text">';
370
+ optionItem.innerHTML += optionParts[1] || 'Microsoft 365';
371
+ optionItem.innerHTML += '</span>';
372
+ optionItem.addEventListener('click', function() {
373
+ atcb_generate_microsoft(data, '365');
374
+ atcb_close();
375
+ });
376
+ break;
377
+ case "Outlook.com":
378
+ optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-0.129793726981 0 33.251996719421 32" width="2500" height="2397"><path d="M28.596 2H11.404A1.404 1.404 0 0 0 10 3.404V5l9.69 3L30 5V3.404A1.404 1.404 0 0 0 28.596 2z" fill="#0364b8"/><path d="M31.65 17.405A11.341 11.341 0 0 0 32 16a.666.666 0 0 0-.333-.576l-.013-.008-.004-.002L20.812 9.24a1.499 1.499 0 0 0-1.479-.083 1.49 1.49 0 0 0-.145.082L8.35 15.415l-.004.002-.012.007A.666.666 0 0 0 8 16a11.344 11.344 0 0 0 .35 1.405l11.492 8.405z" fill="#0a2767"/><path d="M24 5h-7l-2.021 3L17 11l7 6h6v-6z" fill="#28a8ea"/><path d="M10 5h7v6h-7z" fill="#0078d4"/><path d="M24 5h6v6h-6z" fill="#50d9ff"/><path d="M24 17l-7-6h-7v6l7 6 10.832 1.768z" fill="#0364b8"/><path d="M17 11h7v6h-7z" fill="#0078d4"/><path d="M10 17h7v6h-7z" fill="#064a8c"/><path d="M24 17h6v6h-6z" fill="#0078d4"/><path d="M20.19 25.218l-11.793-8.6.495-.87 10.909 6.212a.528.528 0 0 0 .42-.012l10.933-6.23.496.869z" fill="#0a2767" opacity=".5"/><path d="M31.667 16.577l-.014.008-.003.002-10.838 6.174a1.497 1.497 0 0 1-1.46.091l3.774 5.061 8.254 1.797v.004A1.498 1.498 0 0 0 32 28.5V16a.666.666 0 0 1-.333.577z" fill="#1490df"/><path d="M32 28.5v-.738l-9.983-5.688-1.205.687a1.497 1.497 0 0 1-1.46.091l3.774 5.061 8.254 1.797v.004A1.498 1.498 0 0 0 32 28.5z" opacity=".05"/><path d="M31.95 28.883L21.007 22.65l-.195.11a1.497 1.497 0 0 1-1.46.092l3.774 5.061 8.254 1.797v.004a1.501 1.501 0 0 0 .57-.83z" opacity=".1"/><path d="M8.35 16.59v-.01h-.01l-.03-.02A.65.65 0 0 1 8 16v12.5A1.498 1.498 0 0 0 9.5 30h21a1.503 1.503 0 0 0 .37-.05.637.637 0 0 0 .18-.06.142.142 0 0 0 .06-.02 1.048 1.048 0 0 0 .23-.13c.02-.01.03-.01.04-.03z" fill="#28a8ea"/><path d="M18 24.667V8.333A1.337 1.337 0 0 0 16.667 7H10.03v7.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v10h8.667A1.337 1.337 0 0 0 18 24.667z" opacity=".1"/><path d="M17 25.667V9.333A1.337 1.337 0 0 0 15.667 8H10.03v6.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v11h7.667A1.337 1.337 0 0 0 17 25.667z" opacity=".2"/><path d="M17 23.667V9.333A1.337 1.337 0 0 0 15.667 8H10.03v6.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v9h7.667A1.337 1.337 0 0 0 17 23.667z" opacity=".2"/><path d="M16 23.667V9.333A1.337 1.337 0 0 0 14.667 8H10.03v6.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v9h6.667A1.337 1.337 0 0 0 16 23.667z" opacity=".2"/><path d="M1.333 8h13.334A1.333 1.333 0 0 1 16 9.333v13.334A1.333 1.333 0 0 1 14.667 24H1.333A1.333 1.333 0 0 1 0 22.667V9.333A1.333 1.333 0 0 1 1.333 8z" fill="#0078d4"/><path d="M3.867 13.468a4.181 4.181 0 0 1 1.642-1.814A4.965 4.965 0 0 1 8.119 11a4.617 4.617 0 0 1 2.413.62 4.14 4.14 0 0 1 1.598 1.733 5.597 5.597 0 0 1 .56 2.55 5.901 5.901 0 0 1-.577 2.666 4.239 4.239 0 0 1-1.645 1.794A4.8 4.8 0 0 1 7.963 21a4.729 4.729 0 0 1-2.468-.627 4.204 4.204 0 0 1-1.618-1.736 5.459 5.459 0 0 1-.567-2.519 6.055 6.055 0 0 1 .557-2.65zm1.75 4.258a2.716 2.716 0 0 0 .923 1.194 2.411 2.411 0 0 0 1.443.435 2.533 2.533 0 0 0 1.541-.449 2.603 2.603 0 0 0 .897-1.197 4.626 4.626 0 0 0 .286-1.665 5.063 5.063 0 0 0-.27-1.686 2.669 2.669 0 0 0-.866-1.24 2.387 2.387 0 0 0-1.527-.473 2.493 2.493 0 0 0-1.477.439 2.741 2.741 0 0 0-.944 1.203 4.776 4.776 0 0 0-.007 3.44z" fill="#fff"/></svg></span>';
379
+ optionItem.innerHTML += '<span class="atcb_text">';
380
+ optionItem.innerHTML += optionParts[1] || 'Outlook.com';
381
+ optionItem.innerHTML += '</span>';
382
+ optionItem.addEventListener('click', function() {
383
+ atcb_generate_microsoft(data, 'outlook');
384
+ atcb_close();
385
+ });
386
+ break;
387
+ case "Yahoo":
388
+ optionItem.innerHTML = '<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3386.34 3010.5" shape-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd"><path d="M0 732.88h645.84l376.07 962.1 380.96-962.1h628.76l-946.8 2277.62H451.98l259.19-603.53L.02 732.88zm2763.84 768.75h-704.26L2684.65 0l701.69.03-622.5 1501.6zm-519.78 143.72c216.09 0 391.25 175.17 391.25 391.22 0 216.06-175.16 391.23-391.25 391.23-216.06 0-391.19-175.17-391.19-391.23 0-216.05 175.16-391.22 391.19-391.22z" fill="#5f01d1" fill-rule="nonzero"/></svg></span>';
389
+ optionItem.innerHTML += '<span class="atcb_text">';
390
+ optionItem.innerHTML += optionParts[1] || 'Yahoo';
391
+ optionItem.innerHTML += '</span>';
392
+ optionItem.addEventListener('click', function() {
393
+ atcb_generate_yahoo(data);
394
+ atcb_close();
395
+ });
396
+ break;
397
+ }
398
+ optionItem.addEventListener('keydown', function(event) { // trigger click on enter as well
399
+ if (event.key == 'Enter') {
400
+ this.click();
401
+ }
402
+ });
403
+ });
404
+ return optionsList;
405
+ }
406
+
407
+ // create the background overlay, which also acts as trigger to close any dropdowns
408
+
409
+ function atcb_generate_bg_overlay(data) {
410
+ const bgOverlay = document.createElement('div');
411
+ bgOverlay.classList.add('atcb_bgoverlay');
412
+ bgOverlay.tabIndex = 0;
413
+ bgOverlay.addEventListener('click', () => atcb_close(true));
414
+ let fingerMoved = false;
415
+ bgOverlay.addEventListener('touchstart', () => fingerMoved = false, {passive: true});
416
+ bgOverlay.addEventListener('touchmove', () => fingerMoved = true, {passive: true});
417
+ bgOverlay.addEventListener('touchend', function() {
418
+ if (fingerMoved == false) {
419
+ atcb_close(true);
420
+ }
421
+ }, {passive: true});
422
+ bgOverlay.addEventListener('focus', () => atcb_close(false));
423
+ if (data['trigger'] !== 'click') {
424
+ bgOverlay.addEventListener('mousemove', () => atcb_close(true));
425
+ } else {
426
+ bgOverlay.classList.add('atcb_click');
427
+ }
428
+ return bgOverlay;
429
+ }
430
+
431
+
432
+
433
+ // FUNCTIONS TO CONTROL THE INTERACTION
434
+ function atcb_toggle(data, button, buttonGenerated, keyboardTrigger = true) {
435
+ // check for state and adjust accordingly
436
+ if (button.classList.contains('atcb_active')) {
437
+ atcb_close();
438
+ } else {
439
+ atcb_open(data, button, buttonGenerated, keyboardTrigger);
440
+ }
441
+ }
442
+
443
+ // show the dropdown list + background overlay
444
+ function atcb_open(data, button, buttonGenerated = false, keyboardTrigger = true) {
445
+ // abort early if an add-to-calendar dropdown already opened
446
+ if (document.querySelector('.atcb_list')) return
447
+
448
+ // generate list
449
+ const list = atcb_generate_dropdown_list(data, buttonGenerated);
450
+
451
+ // set list styles, set possible button to atcb_active and go for modal mode if no button is set
452
+ if (button) {
453
+ button.classList.add('atcb_active');
454
+
455
+ const rect = button.getBoundingClientRect();
456
+ list.style.width = rect.width + 'px';
457
+ list.style.top = rect.bottom + window.scrollY + 'px';
458
+ list.style.left = rect.left + 'px';
459
+ } else {
460
+ list.classList.add('atcb_modal')
461
+ }
462
+ if (buttonGenerated) {
463
+ list.classList.add('atcb_generated_button');
464
+ }
465
+
466
+ // add list to DOM
467
+ document.body.appendChild(list);
468
+
469
+ // add background overlay right after, so tabbing past last option closes list
470
+ document.body.appendChild(atcb_generate_bg_overlay(data));
471
+
472
+ // give keyboard focus to first item in list, if not blocked, because there is definitely no keyboard trigger
473
+ if (keyboardTrigger) {
474
+ list.firstChild.focus();
475
+ }
476
+ }
477
+
478
+ function atcb_close(blockFocus = false) {
479
+ // 1. Focus triggering button (if not existing, try a custom element)
480
+ if (!blockFocus) {
481
+ let newFocusEl = document.querySelector('.atcb_active');
482
+ if (newFocusEl) {
483
+ newFocusEl.focus();
484
+ } else {
485
+ newFocusEl = document.querySelector('.atcb_customTrigger');
486
+ if (newFocusEl) {
487
+ newFocusEl.focus();
488
+ }
489
+ }
490
+ }
491
+ // 2. Inactivate all buttons
492
+ Array.from(document.querySelectorAll('.atcb_active')).forEach(button => {
493
+ button.classList.remove('atcb_active');
494
+ })
495
+ // 3. Remove dropdowns & bg overlays (should only be one of each)
496
+ Array.from(document.querySelectorAll('.atcb_list')).concat(
497
+ Array.from(document.querySelectorAll('.atcb_bgoverlay'))
498
+ ).forEach(el => el.remove());
499
+ }
500
+
501
+ // prepare data when not using the init function
502
+ function atcb_action(data, button) {
503
+ // validate & decorate data
504
+ if (!atcb_check_required(data)) {
505
+ throw new Error("data missing; see logs")
506
+ }
507
+ data = atcb_decorate_data(data);
508
+ if (!atcb_validate(data)) {
509
+ throw new Error("Invalid data; see logs")
510
+ }
511
+ atcb_open(data, button);
512
+ }
513
+
514
+
515
+
516
+ // FUNCTION TO GENERATE THE GOOGLE URL
517
+ function atcb_generate_google(data) {
518
+ // base url
519
+ let url = 'https://calendar.google.com/calendar/render?action=TEMPLATE';
520
+ // generate and add date
521
+ let formattedDate = atcb_generate_time(data, 'clean', 'google');
522
+ url += '&dates=' + formattedDate['start'] + '%2F' + formattedDate['end'];
523
+ // add details (if set)
524
+ if (data['description'] != null && data['description'] != '') {
525
+ url += '&details=' + encodeURIComponent(data['description']);
526
+ }
527
+ if (data['location'] != null && data['location'] != '') {
528
+ url += '&location=' + encodeURIComponent(data['location']);
529
+ }
530
+ if (data['name'] != null && data['name'] != '') {
531
+ url += '&text=' + encodeURIComponent(data['name']);
532
+ }
533
+ window.open(url, '_blank').focus();
534
+ }
535
+
536
+
537
+
538
+ // FUNCTION TO GENERATE THE YAHOO URL
539
+ function atcb_generate_yahoo(data) {
540
+ // base url
541
+ let url = 'https://calendar.yahoo.com/?v=60';
542
+ // generate and add date
543
+ let formattedDate = atcb_generate_time(data, 'clean');
544
+ url += '&st=' + formattedDate['start'] + '&et=' + formattedDate['end'];
545
+ if (formattedDate['allday']) {
546
+ url += '&dur=allday';
547
+ }
548
+ // add details (if set)
549
+ if (data['description'] != null && data['description'] != '') {
550
+ url += '&desc=' + encodeURIComponent(data['description']);
551
+ }
552
+ if (data['location'] != null && data['location'] != '') {
553
+ url += '&in_loc=' + encodeURIComponent(data['location']);
554
+ }
555
+ if (data['name'] != null && data['name'] != '') {
556
+ url += '&title=' + encodeURIComponent(data['name']);
557
+ }
558
+ window.open(url, '_blank').focus();
559
+ }
560
+
561
+
562
+
563
+ // FUNCTION TO GENERATE THE MICROSOFT 365 OR OUTLOOK WEB URL
564
+ function atcb_generate_microsoft(data, type = '365') {
565
+ // base url
566
+ let url = 'https://';
567
+ if (type == 'outlook') {
568
+ url += 'outlook.live.com';
569
+ } else {
570
+ url += 'outlook.office.com';
571
+ }
572
+ url += '/calendar/0/deeplink/compose?path=%2Fcalendar%2Faction%2Fcompose&rru=addevent';
573
+ // generate and add date
574
+ let formattedDate = atcb_generate_time(data, 'delimiters', 'microsoft');
575
+ url += '&startdt=' + formattedDate['start'] + '&enddt=' + formattedDate['end'];
576
+ if (formattedDate['allday']) {
577
+ url += '&allday=true';
578
+ }
579
+ // add details (if set)
580
+ if (data['description'] != null && data['description'] != '') {
581
+ url += '&body=' + encodeURIComponent(data['description'].replace(/\n/g, '<br>'));
582
+ }
583
+ if (data['location'] != null && data['location'] != '') {
584
+ url += '&location=' + encodeURIComponent(data['location']);
585
+ }
586
+ if (data['name'] != null && data['name'] != '') {
587
+ url += '&subject=' + encodeURIComponent(data['name']);
588
+ }
589
+ window.open(url, '_blank').focus();
590
+ }
591
+
592
+
593
+
594
+ // FUNCTION TO GENERATE THE MICROSOFT TEAMS URL
595
+ // Mind that this is still in development mode by Microsoft! (https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/build-and-test/deep-links#deep-linking-to-the-scheduling-dialog)
596
+ // Location, html tags and linebreaks in the description are not supported yet.
597
+ function atcb_generate_teams(data) {
598
+ // base url
599
+ let url = 'https://teams.microsoft.com/l/meeting/new?';
600
+ // generate and add date
601
+ let formattedDate = atcb_generate_time(data, 'delimiters', 'microsoft');
602
+ url += '&startTime=' + formattedDate['start'] + '&endTime=' + formattedDate['end'];
603
+ // add details (if set)
604
+ let locationString = '';
605
+ if (data['location'] != null && data['location'] != '') {
606
+ locationString = encodeURIComponent(data['location']);
607
+ url += '&location=' + locationString; // workaround putting the location into the description, since the native field is not supported yet
608
+ locationString += ' // ';
609
+ }
610
+ if (data['description_iCal'] != null && data['description_iCal'] != '') { // using description_iCal instead of description, since Teams does not support html tags
611
+ url += '&content=' + locationString + encodeURIComponent(data['description_iCal']);
612
+ }
613
+ if (data['name'] != null && data['name'] != '') {
614
+ url += '&subject=' + encodeURIComponent(data['name']);
615
+ }
616
+ window.open(url, '_blank').focus();
617
+ }
618
+
619
+
620
+
621
+ // FUNCTION TO GENERATE THE iCAL FILE (also for the Apple option)
622
+ function atcb_generate_ical(data) {
623
+ let now = new Date();
624
+ now = now.toISOString().replace(/\..../g, '').replace(/[^a-z0-9]/gi,'');
625
+ let formattedDate = atcb_generate_time(data, 'clean', 'ical');
626
+ let timeslot = '';
627
+ if (formattedDate['allday']) {
628
+ timeslot = ';VALUE=DATE';
629
+ }
630
+ let ics_lines = [
631
+ "BEGIN:VCALENDAR",
632
+ "VERSION:2.0",
633
+ "CALSCALE:GREGORIAN",
634
+ "BEGIN:VEVENT",
635
+ "DTSTAMP:" + formattedDate['start'],
636
+ "DTSTART" + timeslot + ":" + formattedDate['start'],
637
+ "DTEND" + timeslot + ":" + formattedDate['end'],
638
+ "SUMMARY:" + data['name']
639
+ ];
640
+ if (data['description_iCal'] != null && data['description_iCal'] != '') {
641
+ ics_lines.push("DESCRIPTION:" + data['description_iCal'].replace(/\n/g, '\\n'));
642
+ }
643
+ if (data['location'] != null && data['location'] != '') {
644
+ ics_lines.push("LOCATION:" + data['location']);
645
+ }
646
+ ics_lines.push(
647
+ "STATUS:CONFIRMED",
648
+ "LAST-MODIFIED:" + now,
649
+ "SEQUENCE:0",
650
+ "END:VEVENT",
651
+ "END:VCALENDAR"
652
+ );
653
+ let dlurl = 'data:text/calendar;charset=utf-8,'+encodeURIComponent(ics_lines.join('\r\n'));
654
+ try {
655
+ if (!window.ActiveXObject) {
656
+ let save = document.createElement('a');
657
+ save.href = dlurl;
658
+ save.target = '_blank';
659
+ save.download = data['iCalFileName'] || 'event-to-save-in-my-calendar';
660
+ let evt = new MouseEvent('click', {
661
+ 'view': window,
662
+ 'bubbles': true,
663
+ 'cancelable': false
664
+ });
665
+ save.dispatchEvent(evt);
666
+ (window.URL || window.webkitURL).revokeObjectURL(save.href);
667
+ }
668
+ } catch(e) {
669
+ console.error(e);
670
+ }
671
+ }
672
+
673
+
674
+
675
+ // SHARED FUNCTION TO GENERATE A TIME STRING
676
+ function atcb_generate_time(data, style = 'delimiters', targetCal = 'general') {
677
+ let startDate = data['startDate'].split('-');
678
+ let endDate = data['endDate'].split('-');
679
+ let start = '';
680
+ let end = '';
681
+ let allday = false;
682
+ if (data['startTime'] != null && data['endTime'] != null) {
683
+ // Adjust for timezone, if set (see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for either the TZ name or the offset)
684
+ if (data['timeZoneOffset'] != null && data['timeZoneOffset'] != '') {
685
+ // if we have a timezone offset given, consider it
686
+ start = new Date( startDate[0] + '-' + startDate[1] + '-' + startDate[2] + 'T' + data['startTime'] + ':00.000' + data['timeZoneOffset'] );
687
+ end = new Date( endDate[0] + '-' + endDate[1] + '-' + endDate[2] + 'T' + data['endTime'] + ':00.000' + data['timeZoneOffset'] );
688
+ start = start.toISOString().replace('.000', '');
689
+ end = end.toISOString().replace('.000', '');
690
+ if (style == 'clean') {
691
+ start = start.replace(/\-/g, '').replace(/\:/g, '');
692
+ end = end.replace(/\-/g, '').replace(/\:/g, '');
693
+ }
694
+ } else {
695
+ // if there is no offset, we prepare the time, assuming it is UTC formatted
696
+ start = new Date( startDate[0] + '-' + startDate[1] + '-' + startDate[2] + 'T' + data['startTime'] + ':00.000+00:00' );
697
+ end = new Date( endDate[0] + '-' + endDate[1] + '-' + endDate[2] + 'T' + data['endTime'] + ':00.000+00:00' );
698
+ if (data['timeZone'] != null && data['timeZone'] != '') {
699
+ // if a timezone is given, we adjust dynamically with the modern toLocaleString function
700
+ let utcDate = new Date(start.toLocaleString('en-US', { timeZone: "UTC" }));
701
+ if (data['timeZone'] == 'currentBrowser') {
702
+ data['timeZone'] = Intl.DateTimeFormat().resolvedOptions().timeZone;
703
+ }
704
+ let tzDate = new Date(start.toLocaleString('en-US', { timeZone: data['timeZone'] }));
705
+ let offset = utcDate.getTime() - tzDate.getTime();
706
+ start.setTime( start.getTime() + offset );
707
+ end.setTime( end.getTime() + offset );
708
+ }
709
+ start = start.toISOString().replace('.000', '');
710
+ end = end.toISOString().replace('.000', '');
711
+ if (style == 'clean') {
712
+ start = start.replace(/\-/g, '').replace(/\:/g, '');
713
+ end = end.replace(/\-/g, '').replace(/\:/g, '');
714
+ }
715
+ }
716
+ } else { // would be an allday event then
717
+ allday = true;
718
+ start = new Date( startDate[0], startDate[1] - 1, startDate[2]);
719
+ start.setDate(start.getDate() + 1); // increment the day by 1
720
+ let breakStart = start.toISOString().split('T');
721
+ end = new Date( endDate[0], endDate[1] - 1, endDate[2]);
722
+ if (targetCal == 'google' || targetCal == 'microsoft' || targetCal == 'ical') {
723
+ end.setDate(end.getDate() + 2); // increment the day by 2 for Google Calendar, iCal and Outlook
724
+ } else {
725
+ end.setDate(end.getDate() + 1); // otherwise by 1
726
+ }
727
+ let breakEnd = end.toISOString().split('T');
728
+ if (style == 'clean') {
729
+ breakStart[0] = breakStart[0].replace(/\-/g, '');
730
+ breakEnd[0] = breakEnd[0].replace(/\-/g, '');
731
+ }
732
+ start = breakStart[0];
733
+ end = breakEnd[0];
734
+ }
735
+ let returnObject = {'start':start, 'end':end, 'allday':allday};
736
+ return returnObject;
737
+ }
738
+
739
+ const isBrowser=new Function("try {return this===window;}catch(e){ return false;}");
740
+
741
+ if (isBrowser()) {
742
+ // Global listener to ESC key to close dropdown
743
+ document.addEventListener('keydown', evt => {
744
+ if (evt.key === 'Escape') {
745
+ atcb_close();
746
+ }
747
+ });
748
+ }
749
+
750
+
751
+
752
+ // START INIT
753
+ if (isBrowser()) {
754
+ document.addEventListener('DOMContentLoaded', atcb_init, false); // init the magic as soon as the DOM has been loaded
755
+ }
756
+ // END INIT
@@ -0,0 +1,2 @@
1
+ const atcbVersion="1.7.7";function atcb_init(){console.log("add-to-calendar button initialized (version "+atcbVersion+")"),console.log("See https://github.com/jekuer/add-to-calendar-button for details");let a=document.querySelectorAll(".atcb");if(0<a.length){var c=document.querySelectorAll(".atcb_initialized");for(let n=0;n<a.length;n++)if(!a[n].classList.contains("atcb_initialized")){let e,t=a[n].querySelector("script");t&&t.innerHTML?(e=JSON.parse(t.innerHTML.replace(/(\r\n|\n|\r)/gm,"").replace(/(<(?!br)([^>]+)>)/gi,"")),e=atcb_parse_schema_json(e),e.deleteJSON=!1):(e=JSON.parse(a[n].innerHTML.replace(/(\r\n|\n|\r)/gm,"").replace(/(<(?!br)([^>]+)>)/gi,"")),e.deleteJSON=!0),e=atcb_patch_config(e),atcb_check_required(e)&&(e=atcb_decorate_data(e),atcb_validate(e)&&atcb_generate(a[n],n+c.length,e))}}}function atcb_parse_schema_json(t){try{Object.keys(t.event).forEach(e=>{"@"!==e.charAt(0)&&(t[e]=t.event[e])}),delete t.event}catch(e){console.error("add-to-calendar button problem: it seems like you use the schema.org style, but did not define it properly")}return t}function atcb_patch_config(t){const n={title:"name",dateStart:"startDate",dateEnd:"endDate",timeStart:"startTime",timeEnd:"endTime"};return Object.keys(n).forEach(e=>{null==t[n[e]]&&null!=t[e]&&(t[n[e]]=t[e])}),t}function atcb_decorate_data(e){if((e=atcb_date_cleanup(e)).startDate=atcb_date_calculation(e.startDate),e.endDate=atcb_date_calculation(e.endDate),!e.description||e.description_iCal)return e;const t=Object.assign({},e);return t.description=t.description.replace(/<br\s*\/?>/gim,"\n"),t.description_iCal=t.description.replace("[url]","").replace("[/url]",""),t.description=t.description.replace(/\[url\](.*?)\[\/url\]/g,"<a href='$1' target='_blank' rel='noopener'>$1</a>"),t}function atcb_check_required(t){if(null==t.options||t.options.length<1)return console.error("add-to-calendar button generation failed: no options set"),!1;return["name","startDate","endDate"].every(function(e){return null!=t[e]&&""!=t[e]||(console.error("add-to-calendar button generation failed: required setting missing ["+e+"]"),!1)})}function atcb_date_cleanup(n){return["start","end"].forEach(function(t){var e;if(null!=n[t+"Date"]&&(n[t+"Date"]=n[t+"Date"].replace(/\..../,"").replace("Z",""),null!=(e=n[t+"Date"].split("T"))[1]&&(n[t+"Date"]=e[0],n[t+"Time"]=e[1])),null!=n[t+"Time"]&&8==n[t+"Time"].length){let e=n[t+"Time"];n[t+"Time"]=e.substring(0,e.length-3)}}),n}function atcb_date_calculation(e){let t=new Date;var n=t.getMonth()+1+"-"+t.getDate()+"-"+t.getFullYear();const a=(e=e.replace(/today/gi,n)).split("+");n=a[0].split("-");let c=new Date(n[0],n[1]-1,n[2]);return n[0].length<4&&(c=new Date(n[2],n[0]-1,n[1])),null!=a[1]&&0<a[1]&&c.setDate(c.getDate()+parseInt(a[1])),c.getFullYear()+"-"+(c.getMonth()+1<10?"0":"")+(c.getMonth()+1)+"-"+(c.getDate()<10?"0":"")+c.getDate()}function atcb_validate(n){const t=["Apple","Google","iCal","Microsoft365","Outlook.com","MicrosoftTeams","Yahoo"];if(!n.options.every(function(e){e=e.split("|");return!!t.includes(e[0])||(console.error("add-to-calendar button generation failed: invalid option ["+e[0]+"]"),!1)}))return!1;const e=["startDate","endDate"];let a=e;if(!e.every(function(e){if(10!=n[e].length)return console.error("add-to-calendar button generation failed: date misspelled [-> YYYY-MM-DD]"),!1;var t=n[e].split("-");return t.length<3||3<t.length?(console.error("add-to-calendar button generation failed: date misspelled ["+e+": "+n[e]+"]"),!1):(a[e]=new Date(t[0],t[1]-1,t[2]),!0)}))return!1;return!!["startTime","endTime"].every(function(e){if(null!=n[e]){if(5!=n[e].length)return console.error("add-to-calendar button generation failed: time misspelled [-> HH:MM]"),!1;var t=n[e].split(":");if(t.length<2||2<t.length)return console.error("add-to-calendar button generation failed: time misspelled ["+e+": "+n[e]+"]"),!1;if(23<t[0])return console.error("add-to-calendar button generation failed: time misspelled - hours number too high ["+e+": "+t[0]+"]"),!1;if(59<t[1])return console.error("add-to-calendar button generation failed: time misspelled - minutes number too high ["+e+": "+t[1]+"]"),!1;"startTime"==e&&(a.startDate=new Date(a.startDate.getTime()+36e5*t[0]+6e4*t[1])),"endTime"==e&&(a.endDate=new Date(a.endDate.getTime()+36e5*t[0]+6e4*t[1]))}return!0})&&(null!=n.startTime&&null==n.endTime||null==n.startTime&&null!=n.endTime?(console.error("add-to-calendar button generation failed: if you set a starting time, you also need to define an end time"),!1):!(a.endDate<a.startDate)||(console.error("add-to-calendar button generation failed: end date before start date"),!1))}function atcb_generate(e,t,n){n.deleteJSON&&(e.innerHTML="");let a=document.createElement("div"),c=(a.classList.add("atcb_button_wrapper"),e.appendChild(a),document.createElement("button"));c.id="atcb_button_"+t,c.classList.add("atcb_button"),a.appendChild(c),c.innerHTML='<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 122.88"><path d="M81.61 4.73c0-2.61 2.58-4.73 5.77-4.73s5.77 2.12 5.77 4.73v20.72c0 2.61-2.58 4.73-5.77 4.73s-5.77-2.12-5.77-4.73V4.73h0zm-3.65 76.03c1.83 0 3.32 1.49 3.32 3.32s-1.49 3.32-3.32 3.32l-12.95-.04-.04 12.93c0 1.83-1.49 3.32-3.32 3.32s-3.32-1.49-3.32-3.32l.04-12.94-12.93-.05c-1.83 0-3.32-1.49-3.32-3.32s1.49-3.32 3.32-3.32l12.94.04.04-12.93c0-1.83 1.49-3.32 3.32-3.32s3.32 1.49 3.32 3.32l-.04 12.95 12.94.04h0zM29.61 4.73c0-2.61 2.58-4.73 5.77-4.73s5.77 2.12 5.77 4.73v20.72c0 2.61-2.58 4.73-5.77 4.73s-5.77-2.12-5.77-4.73V4.73h0zM6.4 45.32h110.08V21.47c0-.8-.33-1.53-.86-2.07-.53-.53-1.26-.86-2.07-.86H103c-1.77 0-3.2-1.43-3.2-3.2s1.43-3.2 3.2-3.2h10.55c2.57 0 4.9 1.05 6.59 2.74s2.74 4.02 2.74 6.59v27.06 65.03c0 2.57-1.05 4.9-2.74 6.59s-4.02 2.74-6.59 2.74H9.33c-2.57 0-4.9-1.05-6.59-2.74-1.69-1.7-2.74-4.03-2.74-6.6V48.53 21.47c0-2.57 1.05-4.9 2.74-6.59s4.02-2.74 6.59-2.74H20.6c1.77 0 3.2 1.43 3.2 3.2s-1.43 3.2-3.2 3.2H9.33c-.8 0-1.53.33-2.07.86-.53.53-.86 1.26-.86 2.07v23.85h0zm110.08 6.41H6.4v61.82c0 .8.33 1.53.86 2.07.53.53 1.26.86 2.07.86h104.22c.8 0 1.53-.33 2.07-.86.53-.53.86-1.26.86-2.07V51.73h0zM50.43 18.54c-1.77 0-3.2-1.43-3.2-3.2s1.43-3.2 3.2-3.2h21.49c1.77 0 3.2 1.43 3.2 3.2s-1.43 3.2-3.2 3.2H50.43h0z"/></svg></span>',c.innerHTML+='<span class="atcb_text">'+(n.label||"Add to Calendar")+"</span>","click"==n.trigger?c.addEventListener("mousedown",()=>atcb_toggle(n,c,!0,!1)):(c.addEventListener("touchstart",()=>atcb_toggle(n,c,!0,!1),{passive:!0}),c.addEventListener("mouseenter",()=>atcb_open(n,c,!0,!1))),c.addEventListener("keydown",function(e){"Enter"==e.key&&atcb_toggle(n,c,!0)}),e.classList.remove("atcb"),e.classList.add("atcb_initialized"),n.inline?e.style.display="inline-block":e.style.display="block",console.log("add-to-calendar button #"+(t+1)+" created")}function atcb_generate_dropdown_list(a){const c=document.createElement("div");return c.classList.add("atcb_list"),a.options.forEach(function(e){var t=e.split("|");let n=document.createElement("div");switch(n.classList.add("atcb_list_item"),n.tabIndex=0,c.appendChild(n),t[0]){case"Apple":n.innerHTML='<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" shape-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" viewBox="0 0 640 640"><path d="M494.782 340.02c-.803-81.025 66.084-119.907 69.072-121.832-37.595-54.993-96.167-62.552-117.037-63.402-49.843-5.032-97.242 29.362-122.565 29.362-25.253 0-64.277-28.607-105.604-27.85-54.32.803-104.4 31.594-132.403 80.245C29.81 334.457 71.81 479.58 126.816 558.976c26.87 38.882 58.914 82.56 100.997 81 40.512-1.594 55.843-26.244 104.848-26.244 48.993 0 62.753 26.245 105.64 25.406 43.606-.803 71.232-39.638 97.925-78.65 30.887-45.12 43.548-88.75 44.316-90.994-.969-.437-85.029-32.634-85.879-129.439l.118-.035zM414.23 102.178C436.553 75.095 451.636 37.5 447.514-.024c-32.162 1.311-71.163 21.437-94.253 48.485-20.729 24.012-38.836 62.28-33.993 99.036 35.918 2.8 72.591-18.248 94.926-45.272l.036-.047z"/></svg></span>',n.innerHTML+='<span class="atcb_text">',n.innerHTML+=t[1]||"Apple",n.innerHTML+="</span>",n.addEventListener("click",function(){atcb_generate_ical(a),atcb_close()});break;case"Google":n.innerHTML='<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 122.88"><path d="M93.78 29.1H29.1v64.68h64.68V29.1z" fill="#fff"/><path d="M93.78 122.88l29.1-29.1h-29.1v29.1z" fill="#f72a25"/><path d="M122.88 29.1h-29.1v64.68h29.1V29.1z" fill="#fbbc04"/><path d="M93.78 93.78H29.1v29.1h64.68v-29.1z" fill="#34a853"/><path d="M0 93.78v19.4c0 5.36 4.34 9.7 9.7 9.7h19.4v-29.1H0h0z" fill="#188038"/><path d="M122.88 29.1V9.7c0-5.36-4.34-9.7-9.7-9.7h-19.4v29.1h29.1 0z" fill="#1967d2"/><path d="M93.78 0H9.7C4.34 0 0 4.34 0 9.7v84.08h29.1V29.1h64.67V0h.01z" fill="#4285f4"/><path d="M42.37 79.27c-2.42-1.63-4.09-4.02-5-7.17l5.61-2.31c.51 1.94 1.4 3.44 2.67 4.51 1.26 1.07 2.8 1.59 4.59 1.59 1.84 0 3.41-.56 4.73-1.67 1.32-1.12 1.98-2.54 1.98-4.26 0-1.76-.7-3.2-2.09-4.32s-3.14-1.67-5.22-1.67H46.4v-5.55h2.91c1.79 0 3.31-.48 4.54-1.46 1.23-.97 1.84-2.3 1.84-3.99 0-1.5-.55-2.7-1.65-3.6s-2.49-1.35-4.18-1.35c-1.65 0-2.96.44-3.93 1.32s-1.7 2-2.12 3.24l-5.55-2.31c.74-2.09 2.09-3.93 4.07-5.52s4.51-2.39 7.58-2.39c2.27 0 4.32.44 6.13 1.32s3.23 2.1 4.26 3.65c1.03 1.56 1.54 3.31 1.54 5.25 0 1.98-.48 3.65-1.43 5.03-.95 1.37-2.13 2.43-3.52 3.16v.33c1.79.74 3.36 1.96 4.51 3.52 1.17 1.58 1.76 3.46 1.76 5.66s-.56 4.16-1.67 5.88c-1.12 1.72-2.66 3.08-4.62 4.07s-4.17 1.49-6.62 1.49c-2.84 0-5.46-.81-7.88-2.45h0 0zm34.46-27.84l-6.16 4.45-3.08-4.67 11.05-7.97h4.24v37.6h-6.05V51.43h0z" fill="#1a73e8"/></svg></span>',n.innerHTML+='<span class="atcb_text">',n.innerHTML+=t[1]||"Google",n.innerHTML+="</span>",n.addEventListener("click",function(){atcb_generate_google(a),atcb_close()});break;case"iCal":n.innerHTML='<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 122.88 122.88"><path d="M81.61 4.73c0-2.61 2.58-4.73 5.77-4.73s5.77 2.12 5.77 4.73v20.72c0 2.61-2.58 4.73-5.77 4.73s-5.77-2.12-5.77-4.73V4.73h0zm-15.5 99.08c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2H81.9c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H66.11h0zM15.85 67.09c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H15.85h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H40.98h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2H81.9c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H66.11h0zm25.14 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H91.25h0zm-75.4 18.36c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H15.85h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H40.98h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2H81.9c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H66.11h0zm25.14 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H91.25h0zm-75.4 18.36c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H15.85h0zm25.13 0c-.34 0-.61-1.43-.61-3.2s.27-3.2.61-3.2h15.79c.34 0 .61 1.43.61 3.2s-.27 3.2-.61 3.2H40.98h0zM29.61 4.73c0-2.61 2.58-4.73 5.77-4.73s5.77 2.12 5.77 4.73v20.72c0 2.61-2.58 4.73-5.77 4.73s-5.77-2.12-5.77-4.73V4.73h0zM6.4 45.32h110.07V21.47c0-.8-.33-1.53-.86-2.07-.53-.53-1.26-.86-2.07-.86H103c-1.77 0-3.2-1.43-3.2-3.2s1.43-3.2 3.2-3.2h10.55c2.57 0 4.9 1.05 6.59 2.74s2.74 4.02 2.74 6.59v27.06 65.03c0 2.57-1.05 4.9-2.74 6.59s-4.02 2.74-6.59 2.74H9.33c-2.57 0-4.9-1.05-6.59-2.74-1.69-1.7-2.74-4.03-2.74-6.6V48.52 21.47c0-2.57 1.05-4.9 2.74-6.59s4.02-2.74 6.59-2.74H20.6c1.77 0 3.2 1.43 3.2 3.2s-1.43 3.2-3.2 3.2H9.33c-.8 0-1.53.33-2.07.86-.53.53-.86 1.26-.86 2.07v23.85h0zm110.08 6.41H6.4v61.82c0 .8.33 1.53.86 2.07.53.53 1.26.86 2.07.86h104.22c.8 0 1.53-.33 2.07-.86.53-.53.86-1.26.86-2.07V51.73h0zM50.43 18.54c-1.77 0-3.2-1.43-3.2-3.2s1.43-3.2 3.2-3.2h21.49c1.77 0 3.2 1.43 3.2 3.2s-1.43 3.2-3.2 3.2H50.43h0z"/></svg></span>',n.innerHTML+='<span class="atcb_text">',n.innerHTML+=t[1]||"iCal File",n.innerHTML+="</span>",n.addEventListener("click",function(){atcb_generate_ical(a),atcb_close()});break;case"MicrosoftTeams":n.innerHTML='<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 2228.833 2073.333"><g fill="#5059c9"><path d="M1554.637 777.5h575.713c54.391 0 98.483 44.092 98.483 98.483v524.398c0 199.901-162.051 361.952-361.952 361.952h0-1.711c-199.901.028-361.975-162-362.004-361.901v-.052-571.409c.001-28.427 23.045-51.471 51.471-51.471h0z"/><circle cx="1943.75" cy="440.583" r="233.25"/></g><g fill="#7b83eb"><circle cx="1218.083" cy="336.917" r="336.917"/><path d="M1667.323 777.5H717.01c-53.743 1.33-96.257 45.931-95.01 99.676v598.105c-7.505 322.519 247.657 590.16 570.167 598.053 322.51-7.893 577.671-275.534 570.167-598.053V877.176c1.245-53.745-41.268-98.346-95.011-99.676z"/></g><path opacity=".1" d="M1244 777.5v838.145c-.258 38.435-23.549 72.964-59.09 87.598-11.316 4.787-23.478 7.254-35.765 7.257H667.613c-6.738-17.105-12.958-34.21-18.142-51.833-18.144-59.477-27.402-121.307-27.472-183.49V877.02c-1.246-53.659 41.198-98.19 94.855-99.52H1244z"/><path opacity=".2" d="M1192.167 777.5v889.978a91.84 91.84 0 0 1-7.257 35.765c-14.634 35.541-49.163 58.833-87.598 59.09H691.975c-8.812-17.105-17.105-34.21-24.362-51.833s-12.958-34.21-18.142-51.833a631.28 631.28 0 0 1-27.472-183.49V877.02c-1.246-53.659 41.198-98.19 94.855-99.52h475.313z"/><path opacity=".2" d="M1192.167 777.5v786.312c-.395 52.223-42.632 94.46-94.855 94.855h-447.84A631.28 631.28 0 0 1 622 1475.177V877.02c-1.246-53.659 41.198-98.19 94.855-99.52h475.312z"/><path opacity=".2" d="M1140.333 777.5v786.312c-.395 52.223-42.632 94.46-94.855 94.855H649.472A631.28 631.28 0 0 1 622 1475.177V877.02c-1.246-53.659 41.198-98.19 94.855-99.52h423.478z"/><path opacity=".1" d="M1244 509.522v163.275c-8.812.518-17.105 1.037-25.917 1.037s-17.105-.518-25.917-1.037c-17.496-1.161-34.848-3.937-51.833-8.293a336.92 336.92 0 0 1-233.25-198.003 288.02 288.02 0 0 1-16.587-51.833h258.648c52.305.198 94.657 42.549 94.856 94.854z"/><use xlink:href="#C" opacity=".2"/><use xlink:href="#C" opacity=".2"/><path opacity=".2" d="M1140.333 561.355v103.148A336.92 336.92 0 0 1 907.083 466.5h138.395c52.305.199 94.656 42.551 94.855 94.855z"/><linearGradient id="A" gradientUnits="userSpaceOnUse" x1="198.099" y1="392.261" x2="942.234" y2="1681.073"><stop offset="0" stop-color="#5a62c3"/><stop offset=".5" stop-color="#4d55bd"/><stop offset="1" stop-color="#3940ab"/></linearGradient><path fill="url(#A)" d="M95.01 466.5h950.312c52.473 0 95.01 42.538 95.01 95.01v950.312c0 52.473-42.538 95.01-95.01 95.01H95.01c-52.473 0-95.01-42.538-95.01-95.01V561.51c0-52.472 42.538-95.01 95.01-95.01z"/><path fill="#fff" d="M820.211,828.193H630.241v517.297H509.211V828.193H320.123V727.844h500.088V828.193z"/><defs ><path id="C" d="M1192.167 561.355v111.442c-17.496-1.161-34.848-3.937-51.833-8.293a336.92 336.92 0 0 1-233.25-198.003h190.228c52.304.198 94.656 42.55 94.855 94.854z"/></defs></svg></span>',n.innerHTML+='<span class="atcb_text">',n.innerHTML+=t[1]||"Microsoft Teams",n.innerHTML+="</span>",n.addEventListener("click",function(){atcb_generate_teams(a),atcb_close()});break;case"Microsoft365":n.innerHTML='<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 278050 333334" shape-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd"><path fill="#ea3e23" d="M278050 305556l-29-16V28627L178807 0 448 66971l-448 87 22 200227 60865-23821V80555l117920-28193-17 239519L122 267285l178668 65976v73l99231-27462v-316z"/></svg></span>',n.innerHTML+='<span class="atcb_text">',n.innerHTML+=t[1]||"Microsoft 365",n.innerHTML+="</span>",n.addEventListener("click",function(){atcb_generate_microsoft(a,"365"),atcb_close()});break;case"Outlook.com":n.innerHTML='<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="-0.129793726981 0 33.251996719421 32" width="2500" height="2397"><path d="M28.596 2H11.404A1.404 1.404 0 0 0 10 3.404V5l9.69 3L30 5V3.404A1.404 1.404 0 0 0 28.596 2z" fill="#0364b8"/><path d="M31.65 17.405A11.341 11.341 0 0 0 32 16a.666.666 0 0 0-.333-.576l-.013-.008-.004-.002L20.812 9.24a1.499 1.499 0 0 0-1.479-.083 1.49 1.49 0 0 0-.145.082L8.35 15.415l-.004.002-.012.007A.666.666 0 0 0 8 16a11.344 11.344 0 0 0 .35 1.405l11.492 8.405z" fill="#0a2767"/><path d="M24 5h-7l-2.021 3L17 11l7 6h6v-6z" fill="#28a8ea"/><path d="M10 5h7v6h-7z" fill="#0078d4"/><path d="M24 5h6v6h-6z" fill="#50d9ff"/><path d="M24 17l-7-6h-7v6l7 6 10.832 1.768z" fill="#0364b8"/><path d="M17 11h7v6h-7z" fill="#0078d4"/><path d="M10 17h7v6h-7z" fill="#064a8c"/><path d="M24 17h6v6h-6z" fill="#0078d4"/><path d="M20.19 25.218l-11.793-8.6.495-.87 10.909 6.212a.528.528 0 0 0 .42-.012l10.933-6.23.496.869z" fill="#0a2767" opacity=".5"/><path d="M31.667 16.577l-.014.008-.003.002-10.838 6.174a1.497 1.497 0 0 1-1.46.091l3.774 5.061 8.254 1.797v.004A1.498 1.498 0 0 0 32 28.5V16a.666.666 0 0 1-.333.577z" fill="#1490df"/><path d="M32 28.5v-.738l-9.983-5.688-1.205.687a1.497 1.497 0 0 1-1.46.091l3.774 5.061 8.254 1.797v.004A1.498 1.498 0 0 0 32 28.5z" opacity=".05"/><path d="M31.95 28.883L21.007 22.65l-.195.11a1.497 1.497 0 0 1-1.46.092l3.774 5.061 8.254 1.797v.004a1.501 1.501 0 0 0 .57-.83z" opacity=".1"/><path d="M8.35 16.59v-.01h-.01l-.03-.02A.65.65 0 0 1 8 16v12.5A1.498 1.498 0 0 0 9.5 30h21a1.503 1.503 0 0 0 .37-.05.637.637 0 0 0 .18-.06.142.142 0 0 0 .06-.02 1.048 1.048 0 0 0 .23-.13c.02-.01.03-.01.04-.03z" fill="#28a8ea"/><path d="M18 24.667V8.333A1.337 1.337 0 0 0 16.667 7H10.03v7.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v10h8.667A1.337 1.337 0 0 0 18 24.667z" opacity=".1"/><path d="M17 25.667V9.333A1.337 1.337 0 0 0 15.667 8H10.03v6.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v11h7.667A1.337 1.337 0 0 0 17 25.667z" opacity=".2"/><path d="M17 23.667V9.333A1.337 1.337 0 0 0 15.667 8H10.03v6.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v9h7.667A1.337 1.337 0 0 0 17 23.667z" opacity=".2"/><path d="M16 23.667V9.333A1.337 1.337 0 0 0 14.667 8H10.03v6.456l-1.68.958-.005.002-.012.007A.666.666 0 0 0 8 16v.005V16v9h6.667A1.337 1.337 0 0 0 16 23.667z" opacity=".2"/><path d="M1.333 8h13.334A1.333 1.333 0 0 1 16 9.333v13.334A1.333 1.333 0 0 1 14.667 24H1.333A1.333 1.333 0 0 1 0 22.667V9.333A1.333 1.333 0 0 1 1.333 8z" fill="#0078d4"/><path d="M3.867 13.468a4.181 4.181 0 0 1 1.642-1.814A4.965 4.965 0 0 1 8.119 11a4.617 4.617 0 0 1 2.413.62 4.14 4.14 0 0 1 1.598 1.733 5.597 5.597 0 0 1 .56 2.55 5.901 5.901 0 0 1-.577 2.666 4.239 4.239 0 0 1-1.645 1.794A4.8 4.8 0 0 1 7.963 21a4.729 4.729 0 0 1-2.468-.627 4.204 4.204 0 0 1-1.618-1.736 5.459 5.459 0 0 1-.567-2.519 6.055 6.055 0 0 1 .557-2.65zm1.75 4.258a2.716 2.716 0 0 0 .923 1.194 2.411 2.411 0 0 0 1.443.435 2.533 2.533 0 0 0 1.541-.449 2.603 2.603 0 0 0 .897-1.197 4.626 4.626 0 0 0 .286-1.665 5.063 5.063 0 0 0-.27-1.686 2.669 2.669 0 0 0-.866-1.24 2.387 2.387 0 0 0-1.527-.473 2.493 2.493 0 0 0-1.477.439 2.741 2.741 0 0 0-.944 1.203 4.776 4.776 0 0 0-.007 3.44z" fill="#fff"/></svg></span>',n.innerHTML+='<span class="atcb_text">',n.innerHTML+=t[1]||"Outlook.com",n.innerHTML+="</span>",n.addEventListener("click",function(){atcb_generate_microsoft(a,"outlook"),atcb_close()});break;case"Yahoo":n.innerHTML='<span class="atcb_icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3386.34 3010.5" shape-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd"><path d="M0 732.88h645.84l376.07 962.1 380.96-962.1h628.76l-946.8 2277.62H451.98l259.19-603.53L.02 732.88zm2763.84 768.75h-704.26L2684.65 0l701.69.03-622.5 1501.6zm-519.78 143.72c216.09 0 391.25 175.17 391.25 391.22 0 216.06-175.16 391.23-391.25 391.23-216.06 0-391.19-175.17-391.19-391.23 0-216.05 175.16-391.22 391.19-391.22z" fill="#5f01d1" fill-rule="nonzero"/></svg></span>',n.innerHTML+='<span class="atcb_text">',n.innerHTML+=t[1]||"Yahoo",n.innerHTML+="</span>",n.addEventListener("click",function(){atcb_generate_yahoo(a),atcb_close()})}n.addEventListener("keydown",function(e){"Enter"==e.key&&this.click()})}),c}function atcb_generate_bg_overlay(e){const t=document.createElement("div");t.classList.add("atcb_bgoverlay"),t.tabIndex=0,t.addEventListener("click",()=>atcb_close(!0));let n=!1;return t.addEventListener("touchstart",()=>n=!1,{passive:!0}),t.addEventListener("touchmove",()=>n=!0,{passive:!0}),t.addEventListener("touchend",function(){0==n&&atcb_close(!0)},{passive:!0}),t.addEventListener("focus",()=>atcb_close(!1)),"click"!==e.trigger?t.addEventListener("mousemove",()=>atcb_close(!0)):t.classList.add("atcb_click"),t}function atcb_toggle(e,t,n,a=!0){t.classList.contains("atcb_active")?atcb_close():atcb_open(e,t,n,a)}function atcb_open(e,t,n=!1,a=!0){if(!document.querySelector(".atcb_list")){const c=atcb_generate_dropdown_list(e,n);t?(t.classList.add("atcb_active"),t=t.getBoundingClientRect(),c.style.width=t.width+"px",c.style.top=t.bottom+window.scrollY+"px",c.style.left=t.left+"px"):c.classList.add("atcb_modal"),n&&c.classList.add("atcb_generated_button"),document.body.appendChild(c),document.body.appendChild(atcb_generate_bg_overlay(e)),a&&c.firstChild.focus()}}function atcb_close(e=!1){if(!e){let e=document.querySelector(".atcb_active");e?e.focus():(e=document.querySelector(".atcb_customTrigger"),e&&e.focus())}Array.from(document.querySelectorAll(".atcb_active")).forEach(e=>{e.classList.remove("atcb_active")}),Array.from(document.querySelectorAll(".atcb_list")).concat(Array.from(document.querySelectorAll(".atcb_bgoverlay"))).forEach(e=>e.remove())}function atcb_action(e,t){if(!atcb_check_required(e))throw new Error("data missing; see logs");if(!atcb_validate(e=atcb_decorate_data(e)))throw new Error("Invalid data; see logs");atcb_open(e,t)}function atcb_generate_google(e){let t="https://calendar.google.com/calendar/render?action=TEMPLATE";var n=atcb_generate_time(e,"clean","google");t+="&dates="+n.start+"%2F"+n.end,null!=e.description&&""!=e.description&&(t+="&details="+encodeURIComponent(e.description)),null!=e.location&&""!=e.location&&(t+="&location="+encodeURIComponent(e.location)),null!=e.name&&""!=e.name&&(t+="&text="+encodeURIComponent(e.name)),window.open(t,"_blank").focus()}function atcb_generate_yahoo(e){let t="https://calendar.yahoo.com/?v=60";var n=atcb_generate_time(e,"clean");t+="&st="+n.start+"&et="+n.end,n.allday&&(t+="&dur=allday"),null!=e.description&&""!=e.description&&(t+="&desc="+encodeURIComponent(e.description)),null!=e.location&&""!=e.location&&(t+="&in_loc="+encodeURIComponent(e.location)),null!=e.name&&""!=e.name&&(t+="&title="+encodeURIComponent(e.name)),window.open(t,"_blank").focus()}function atcb_generate_microsoft(e,t="365"){let n="https://";n+="outlook"==t?"outlook.live.com":"outlook.office.com",n+="/calendar/0/deeplink/compose?path=%2Fcalendar%2Faction%2Fcompose&rru=addevent";t=atcb_generate_time(e,"delimiters","microsoft");n+="&startdt="+t.start+"&enddt="+t.end,t.allday&&(n+="&allday=true"),null!=e.description&&""!=e.description&&(n+="&body="+encodeURIComponent(e.description.replace(/\n/g,"<br>"))),null!=e.location&&""!=e.location&&(n+="&location="+encodeURIComponent(e.location)),null!=e.name&&""!=e.name&&(n+="&subject="+encodeURIComponent(e.name)),window.open(n,"_blank").focus()}function atcb_generate_teams(e){let t="https://teams.microsoft.com/l/meeting/new?";var n=atcb_generate_time(e,"delimiters","microsoft");t+="&startTime="+n.start+"&endTime="+n.end;let a="";null!=e.location&&""!=e.location&&(a=encodeURIComponent(e.location),t+="&location="+a,a+=" // "),null!=e.description_iCal&&""!=e.description_iCal&&(t+="&content="+a+encodeURIComponent(e.description_iCal)),null!=e.name&&""!=e.name&&(t+="&subject="+encodeURIComponent(e.name)),window.open(t,"_blank").focus()}function atcb_generate_ical(t){let e=new Date;e=e.toISOString().replace(/\..../g,"").replace(/[^a-z0-9]/gi,"");var n=atcb_generate_time(t,"clean","ical");let a="",c=(n.allday&&(a=";VALUE=DATE"),["BEGIN:VCALENDAR","VERSION:2.0","CALSCALE:GREGORIAN","BEGIN:VEVENT","DTSTAMP:"+n.start,"DTSTART"+a+":"+n.start,"DTEND"+a+":"+n.end,"SUMMARY:"+t.name]);null!=t.description_iCal&&""!=t.description_iCal&&c.push("DESCRIPTION:"+t.description_iCal.replace(/\n/g,"\\n")),null!=t.location&&""!=t.location&&c.push("LOCATION:"+t.location),c.push("STATUS:CONFIRMED","LAST-MODIFIED:"+e,"SEQUENCE:0","END:VEVENT","END:VCALENDAR");n="data:text/calendar;charset=utf-8,"+encodeURIComponent(c.join("\r\n"));try{if(!window.ActiveXObject){let e=document.createElement("a");e.href=n,e.target="_blank",e.download=t.iCalFileName||"event-to-save-in-my-calendar";var o=new MouseEvent("click",{view:window,bubbles:!0,cancelable:!1});e.dispatchEvent(o),(window.URL||window.webkitURL).revokeObjectURL(e.href)}}catch(e){console.error(e)}}function atcb_generate_time(n,a="delimiters",c="general"){var o=n.startDate.split("-"),i=n.endDate.split("-");let l="",r="",s=!1;if(null!=n.startTime&&null!=n.endTime)if(null!=n.timeZoneOffset&&""!=n.timeZoneOffset)l=new Date(o[0]+"-"+o[1]+"-"+o[2]+"T"+n.startTime+":00.000"+n.timeZoneOffset),r=new Date(i[0]+"-"+i[1]+"-"+i[2]+"T"+n.endTime+":00.000"+n.timeZoneOffset),l=l.toISOString().replace(".000",""),r=r.toISOString().replace(".000",""),"clean"==a&&(l=l.replace(/\-/g,"").replace(/\:/g,""),r=r.replace(/\-/g,"").replace(/\:/g,""));else{if(l=new Date(o[0]+"-"+o[1]+"-"+o[2]+"T"+n.startTime+":00.000+00:00"),r=new Date(i[0]+"-"+i[1]+"-"+i[2]+"T"+n.endTime+":00.000+00:00"),null!=n.timeZone&&""!=n.timeZone){let e=new Date(l.toLocaleString("en-US",{timeZone:"UTC"})),t=("currentBrowser"==n.timeZone&&(n.timeZone=Intl.DateTimeFormat().resolvedOptions().timeZone),new Date(l.toLocaleString("en-US",{timeZone:n.timeZone})));n=e.getTime()-t.getTime();l.setTime(l.getTime()+n),r.setTime(r.getTime()+n)}l=l.toISOString().replace(".000",""),r=r.toISOString().replace(".000",""),"clean"==a&&(l=l.replace(/\-/g,"").replace(/\:/g,""),r=r.replace(/\-/g,"").replace(/\:/g,""))}else{s=!0,l=new Date(o[0],o[1]-1,o[2]),l.setDate(l.getDate()+1);let e=l.toISOString().split("T"),t=(r=new Date(i[0],i[1]-1,i[2]),"google"==c||"microsoft"==c||"ical"==c?r.setDate(r.getDate()+2):r.setDate(r.getDate()+1),r.toISOString().split("T"));"clean"==a&&(e[0]=e[0].replace(/\-/g,""),t[0]=t[0].replace(/\-/g,"")),l=e[0],r=t[0]}return{start:l,end:r,allday:s}}const isBrowser=new Function("try {return this===window;}catch(e){ return false;}");isBrowser()&&document.addEventListener("keydown",e=>{"Escape"===e.key&&atcb_close()}),isBrowser()&&document.addEventListener("DOMContentLoaded",atcb_init,!1);
2
+ //# sourceMappingURL=atcb.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"atcb.min.js","sources":["atcb.js"],"names":["atcbVersion","atcb_init","console","log","let","atcButtons","document","querySelectorAll","length","atcButtonsInitialized","i","classList","contains","atcbConfig","schema","querySelector","innerHTML","JSON","parse","replace","atcb_parse_schema_json","atcb_patch_config","atcb_check_required","atcb_decorate_data","atcb_validate","atcb_generate","Object","keys","forEach","key","charAt","event","err","error","keyChanges","title","dateStart","dateEnd","timeStart","timeEnd","atcb_date_cleanup","atcb_date_calculation","description","description_iCal","data","assign","every","field","point","tmpSplitStartDate","split","timeStr","substring","dateString","today","Date","todayString","getMonth","getDate","getFullYear","dateStringParts","dateParts","newDate","setDate","parseInt","options","option","cleanOption","includes","dates","date","time","timeParts","getTime","button","buttonId","buttonTriggerWrapper","createElement","buttonTrigger","add","appendChild","id","addEventListener","atcb_toggle","passive","atcb_open","remove","style","display","atcb_generate_dropdown_list","optionsList","optionParts","optionItem","tabIndex","atcb_generate_ical","atcb_close","atcb_generate_google","atcb_generate_teams","atcb_generate_microsoft","atcb_generate_yahoo","this","click","atcb_generate_bg_overlay","bgOverlay","fingerMoved","buttonGenerated","keyboardTrigger","list","rect","getBoundingClientRect","width","top","bottom","window","scrollY","left","body","firstChild","focus","blockFocus","newFocusEl","Array","from","concat","el","atcb_action","Error","url","formattedDate","atcb_generate_time","encodeURIComponent","open","type","locationString","now","toISOString","timeslot","ics_lines","push","dlurl","join","ActiveXObject","save","href","target","download","evt","MouseEvent","view","bubbles","cancelable","dispatchEvent","URL","webkitURL","revokeObjectURL","e","targetCal","startDate","endDate","start","end","allday","utcDate","toLocaleString","timeZone","tzDate","Intl","DateTimeFormat","resolvedOptions","offset","setTime","breakStart","breakEnd","isBrowser","Function"],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  * Add-to-Calendar Button
4
4
  * ++++++++++++++++++++++
5
5
  */
6
- const atcbVersion = '1.7.4';
6
+ const atcbVersion = '1.7.7';
7
7
  /* Creator: Jens Kuerschner (https://jenskuerschner.de)
8
8
  * Project: https://github.com/jekuer/add-to-calendar-button
9
9
  * License: MIT with “Commons Clause” License Condition v1.0
@@ -35,13 +35,13 @@ function atcb_init() {
35
35
  // get their JSON content first
36
36
  if (schema && schema.innerHTML) {
37
37
  // get schema.org event markup and flatten the event block
38
- atcbConfig = JSON.parse(schema.innerHTML.replace(/(\r\n|\n|\r)/gm, "")); // we also remove any real code line breaks from the JSON before parsing it. Use <br> or \n explicitely in the description to create a line break
38
+ atcbConfig = JSON.parse(schema.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(/(<(?!br)([^>]+)>)/gi, "")); // remove real code line breaks before parsing. Use <br> or \n explicitely in the description to create a line break. Also strip HTML tags (especially since stupid Safari adds stuff).
39
39
  atcbConfig = atcb_parse_schema_json(atcbConfig);
40
40
  // set flag to not delete HTML content later
41
41
  atcbConfig['deleteJSON'] = false;
42
42
  } else {
43
43
  // get JSON from HTML block
44
- atcbConfig = JSON.parse(atcButtons[i].innerHTML.replace(/(\r\n|\n|\r)/gm, "")); // we also remove any real code line breaks from the JSON before parsing it. Use <br> or \n explicitely in the description to create a line break
44
+ atcbConfig = JSON.parse(atcButtons[i].innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(/(<(?!br)([^>]+)>)/gi, "")); // remove real code line breaks before parsing. Use <br> or \n explicitely in the description to create a line break. Also strip HTML tags (especially since stupid Safari adds stuff).
45
45
  // set flag to delete HTML content later
46
46
  atcbConfig['deleteJSON'] = true;
47
47
  }
@@ -405,12 +405,20 @@ function atcb_generate_dropdown_list(data) {
405
405
  }
406
406
 
407
407
  // create the background overlay, which also acts as trigger to close any dropdowns
408
+
408
409
  function atcb_generate_bg_overlay(data) {
409
410
  const bgOverlay = document.createElement('div');
410
411
  bgOverlay.classList.add('atcb_bgoverlay');
411
412
  bgOverlay.tabIndex = 0;
412
413
  bgOverlay.addEventListener('click', () => atcb_close(true));
413
- bgOverlay.addEventListener('touchstart', () => atcb_close(true), {passive: true});
414
+ let fingerMoved = false;
415
+ bgOverlay.addEventListener('touchstart', () => fingerMoved = false, {passive: true});
416
+ bgOverlay.addEventListener('touchmove', () => fingerMoved = true, {passive: true});
417
+ bgOverlay.addEventListener('touchend', function() {
418
+ if (fingerMoved == false) {
419
+ atcb_close(true);
420
+ }
421
+ }, {passive: true});
414
422
  bgOverlay.addEventListener('focus', () => atcb_close(false));
415
423
  if (data['trigger'] !== 'click') {
416
424
  bgOverlay.addEventListener('mousemove', () => atcb_close(true));
@@ -3,7 +3,7 @@
3
3
  * Add-to-Calendar Button
4
4
  * ++++++++++++++++++++++
5
5
  */
6
- const atcbVersion = '1.7.4';
6
+ const atcbVersion = '1.7.7';
7
7
  /* Creator: Jens Kuerschner (https://jenskuerschner.de)
8
8
  * Project: https://github.com/jekuer/add-to-calendar-button
9
9
  * License: MIT with “Commons Clause” License Condition v1.0
@@ -35,13 +35,13 @@ function atcb_init() {
35
35
  // get their JSON content first
36
36
  if (schema && schema.innerHTML) {
37
37
  // get schema.org event markup and flatten the event block
38
- atcbConfig = JSON.parse(schema.innerHTML.replace(/(\r\n|\n|\r)/gm, "")); // we also remove any real code line breaks from the JSON before parsing it. Use <br> or \n explicitely in the description to create a line break
38
+ atcbConfig = JSON.parse(schema.innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(/(<(?!br)([^>]+)>)/gi, "")); // remove real code line breaks before parsing. Use <br> or \n explicitely in the description to create a line break. Also strip HTML tags (especially since stupid Safari adds stuff).
39
39
  atcbConfig = atcb_parse_schema_json(atcbConfig);
40
40
  // set flag to not delete HTML content later
41
41
  atcbConfig['deleteJSON'] = false;
42
42
  } else {
43
43
  // get JSON from HTML block
44
- atcbConfig = JSON.parse(atcButtons[i].innerHTML.replace(/(\r\n|\n|\r)/gm, "")); // we also remove any real code line breaks from the JSON before parsing it. Use <br> or \n explicitely in the description to create a line break
44
+ atcbConfig = JSON.parse(atcButtons[i].innerHTML.replace(/(\r\n|\n|\r)/gm, "").replace(/(<(?!br)([^>]+)>)/gi, "")); // remove real code line breaks before parsing. Use <br> or \n explicitely in the description to create a line break. Also strip HTML tags (especially since stupid Safari adds stuff).
45
45
  // set flag to delete HTML content later
46
46
  atcbConfig['deleteJSON'] = true;
47
47
  }
@@ -405,12 +405,20 @@ function atcb_generate_dropdown_list(data) {
405
405
  }
406
406
 
407
407
  // create the background overlay, which also acts as trigger to close any dropdowns
408
+
408
409
  function atcb_generate_bg_overlay(data) {
409
410
  const bgOverlay = document.createElement('div');
410
411
  bgOverlay.classList.add('atcb_bgoverlay');
411
412
  bgOverlay.tabIndex = 0;
412
413
  bgOverlay.addEventListener('click', () => atcb_close(true));
413
- bgOverlay.addEventListener('touchstart', () => atcb_close(true), {passive: true});
414
+ let fingerMoved = false;
415
+ bgOverlay.addEventListener('touchstart', () => fingerMoved = false, {passive: true});
416
+ bgOverlay.addEventListener('touchmove', () => fingerMoved = true, {passive: true});
417
+ bgOverlay.addEventListener('touchend', function() {
418
+ if (fingerMoved == false) {
419
+ atcb_close(true);
420
+ }
421
+ }, {passive: true});
414
422
  bgOverlay.addEventListener('focus', () => atcb_close(false));
415
423
  if (data['trigger'] !== 'click') {
416
424
  bgOverlay.addEventListener('mousemove', () => atcb_close(true));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "add-to-calendar-button",
3
- "version": "1.7.4",
3
+ "version": "1.7.7",
4
4
  "description": "A convenient JavaScript snippet, which lets you create beautiful buttons, where people can add events to their calendars.",
5
5
  "main": "npm_dist/cjs/index.js",
6
6
  "module": "npm_dist/mjs/index.js",
@@ -13,6 +13,7 @@
13
13
  },
14
14
  "types": "index.d.ts",
15
15
  "style": "assets/css/atcb.min.css",
16
+ "jsdelivr": "./assets/js/atcb.min.js",
16
17
  "repository": {
17
18
  "type": "git",
18
19
  "url": "https://github.com/jekuer/add-to-calendar-button.git"