add-to-calendar-button 1.4.3 → 1.5.0

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
@@ -88,8 +88,8 @@ Mind that with Angular, you might need to escape the { with `{{ '{' }}` and } wi
88
88
  <div class="atcb" style="display:none;">
89
89
  {
90
90
  "name":"Add the title of your event",
91
- "startDate":"02-21-2022",
92
- "endDate":"03-24-2022",
91
+ "startDate":"2022-02-21",
92
+ "endDate":"2022-03-24",
93
93
  "options":[
94
94
  "Google"
95
95
  ]
@@ -104,8 +104,8 @@ Mind that with Angular, you might need to escape the { with `{{ '{' }}` and } wi
104
104
  {
105
105
  "name":"Add the title of your event",
106
106
  "description":"A nice description does not hurt",
107
- "startDate":"02-21-2022",
108
- "endDate":"03-24-2022",
107
+ "startDate":"2022-02-21",
108
+ "endDate":"2022-03-24",
109
109
  "startTime":"10:13",
110
110
  "endTime":"17:57",
111
111
  "location":"Somewhere over the rainbow",
@@ -139,8 +139,8 @@ You can use startTime and endTime in the event block, but it is recommended to r
139
139
  "@type":"Event",
140
140
  "name":"Add the title of your event",
141
141
  "description":"A nice description does not hurt",
142
- "startDate":"02-21-2022T10:13",
143
- "endDate":"03-24-2022T17:57",
142
+ "startDate":"2022-02-21T10:13",
143
+ "endDate":"2022-03-24T17:57",
144
144
  "location":"Somewhere over the rainbow"
145
145
  },
146
146
  "label":"Add to Calendar",
@@ -186,9 +186,9 @@ const AddToCalendar = () => {
186
186
  ### Important information and hidden features
187
187
 
188
188
  * The "label" is optional, but enables you to customize the button text. Default: "Add to Calendar".
189
- * Dates need to be formatted as MM-DD-YYYY.
189
+ * Dates need to be formatted as YYYY-MM-DD ([ISO-8601](https://en.wikipedia.org/wiki/ISO_8601)).
190
190
  * You can also use the word "today" as date. It will then dynamically use the current day at click.
191
- * Add "+5" at the end of the date to dynamically add 5 days (or any other number). "01-30-2022+12" would generate the 11th of February 2022. This can be interesting, when combined with "today".
191
+ * Add "+5" at the end of the date to dynamically add 5 days (or any other number). "2022-01-30+12" would generate the 11th of February 2022. This can be interesting, when combined with "today".
192
192
  * Times need to be formatted as HH:MM.
193
193
  * Times are optional. If not set, the button generates all-day events.
194
194
  * 1 option is required. You can add as many as you want. The supported formats are listed above.
@@ -202,6 +202,7 @@ const AddToCalendar = () => {
202
202
  * You can set the trigger to "click". This makes the button open on click at desktop. Otherwise, the default would be to open on hover. On touch devices, this makes no difference.
203
203
  * If you want to define a specific name for any generated ics file (iCal), you can specify it via the "iCalFileName" option. The default would be "event-to-save-in-my-calendar".
204
204
  * You can use the option "inline":true in order to make the button appear with inline-block instead of block style.
205
+ * Formatting a URL in the description like `[url]https://....[/url]` makes it clickable.
205
206
  * If you require line breaks within the description, use `\n` or `<br>`.
206
207
 
207
208
 
@@ -223,6 +224,7 @@ The code is available under the [MIT license (with “Commons Clause” License
223
224
 
224
225
  ## Changelog (without bug fixes)
225
226
 
227
+ * v1.5 : update to date format and better accesibility
226
228
  * v1.4 : schema.org support (also changed some keys in the JSON!)
227
229
  * v1.3 : new license (MIT with “Commons Clause”)
228
230
  * v1.2 : inline and line break support
@@ -3,7 +3,7 @@
3
3
  * Add-to-Calendar Button
4
4
  * ++++++++++++++++++++++
5
5
  *
6
- * Version: 1.4.3
6
+ * Version: 1.5.0
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
@@ -45,6 +45,9 @@
45
45
  -webkit-tap-highlight-color: transparent;
46
46
  width: auto;
47
47
  }
48
+ .atcb_button:hover {
49
+ background: rgb(255, 255, 255);
50
+ }
48
51
  @media only screen and (max-width: 575px) {
49
52
  .atcb_button {
50
53
  font-size: 14px;
@@ -1,2 +1,2 @@
1
- .atcb{display:none}.atcb_button_wrapper{display:inline-block;position:relative}.atcb_button{background:#f5f5f5;border:1px solid #d2d2d2;border-radius:6px;-webkit-box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);color:#333;cursor:pointer;display:inline-block;font-size:16px;font-weight:600;line-height:24px;margin:10px auto;max-width:300px;min-width:150px;padding:10px 16px 11px 16px;position:relative;text-align:center;touch-action:manipulation;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;width:auto}@media only screen and (max-width:575px){.atcb_button{font-size:14px}}.atcb_button.active{background:#fff;border-radius:6px 6px 3px 3px;-webkit-box-shadow:1px 5px 15px 0 rgba(0,0,0,.5);box-shadow:1px 5px 15px 0 rgba(0,0,0,.5);margin:7px auto 9px auto;padding:12px 20px 13px 20px;z-index:90}.atcb_icon{height:16px;display:inline-flex;margin-bottom:4px;margin-right:10px;vertical-align:middle}.atcb_icon svg{height:100%;color:#333;width:auto}.atcb_list{box-sizing:border-box;color:#333;display:block;margin:-10px auto 0 auto;max-width:100%;position:absolute;padding:0 3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%;z-index:80}.atcb_list_item{background:#fafafa;border:1px solid #d2d2d2;border-top:0;-webkit-box-shadow:1px 2px 8px 0 rgba(0,0,0,.3);box-shadow:1px 2px 8px 0 rgba(0,0,0,.3);box-sizing:border-box;cursor:pointer;font-size:16px;left:50%;position:relative;padding:12px 18px;text-align:left;transform:translate(-50%);touch-action:manipulation;-webkit-tap-highlight-color:transparent}.atcb_list_item:hover{background:#fff;-webkit-box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);color:#000}@media only screen and (max-width:575px){.atcb_list_item{font-size:14px}}.atcb_list_item:first-child{padding-top:25px}.atcb_list_item:last-child{border-radius:0 0 6px 6px}.atcb_list_item .atcb_icon{margin-right:8px}.atcb_bgoverlay{background:rgba(20,20,20,.2);backdrop-filter:blur(2px);height:100%;left:0;position:fixed;top:0;width:100%;z-index:70}
1
+ .atcb{display:none}.atcb_button_wrapper{display:inline-block;position:relative}.atcb_button{background:#f5f5f5;border:1px solid #d2d2d2;border-radius:6px;-webkit-box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);color:#333;cursor:pointer;display:inline-block;font-size:16px;font-weight:600;line-height:24px;margin:10px auto;max-width:300px;min-width:150px;padding:10px 16px 11px 16px;position:relative;text-align:center;touch-action:manipulation;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;width:auto}.atcb_button:hover{background:#fff}@media only screen and (max-width:575px){.atcb_button{font-size:14px}}.atcb_button.active{background:#fff;border-radius:6px 6px 3px 3px;-webkit-box-shadow:1px 5px 15px 0 rgba(0,0,0,.5);box-shadow:1px 5px 15px 0 rgba(0,0,0,.5);margin:7px auto 9px auto;padding:12px 20px 13px 20px;z-index:90}.atcb_icon{height:16px;display:inline-flex;margin-bottom:4px;margin-right:10px;vertical-align:middle}.atcb_icon svg{height:100%;color:#333;width:auto}.atcb_list{box-sizing:border-box;color:#333;display:block;margin:-10px auto 0 auto;max-width:100%;position:absolute;padding:0 3px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%;z-index:80}.atcb_list_item{background:#fafafa;border:1px solid #d2d2d2;border-top:0;-webkit-box-shadow:1px 2px 8px 0 rgba(0,0,0,.3);box-shadow:1px 2px 8px 0 rgba(0,0,0,.3);box-sizing:border-box;cursor:pointer;font-size:16px;left:50%;position:relative;padding:12px 18px;text-align:left;transform:translate(-50%);touch-action:manipulation;-webkit-tap-highlight-color:transparent}.atcb_list_item:hover{background:#fff;-webkit-box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);box-shadow:1px 2px 10px 0 rgba(0,0,0,.4);color:#000}@media only screen and (max-width:575px){.atcb_list_item{font-size:14px}}.atcb_list_item:first-child{padding-top:25px}.atcb_list_item:last-child{border-radius:0 0 6px 6px}.atcb_list_item .atcb_icon{margin-right:8px}.atcb_bgoverlay{background:rgba(20,20,20,.2);backdrop-filter:blur(2px);height:100%;left:0;position:fixed;top:0;width:100%;z-index:70}
2
2
  /*# sourceMappingURL=atcb.min.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["assets\\css\\atcb.css"],"names":[],"mappings":"AAYA,MACE,QAAS,KAGX,qBACE,QAAS,aACT,SAAU,SAGZ,aACE,WAAY,QACZ,OAAQ,IAAI,MAAM,QAClB,cAAe,IACf,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,MAAO,KACP,OAAQ,QACR,QAAS,aACT,UAAW,KACX,YAAa,IACb,YAAa,KACb,OAAQ,KAAK,KACb,UAAW,MACX,UAAW,MACX,QAAS,KAAK,KAAK,KAAK,KACxB,SAAU,SACV,WAAY,OACZ,aAAc,aACd,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KACb,4BAA6B,YAC7B,MAAO,KAET,yCACE,aACE,UAAW,MAIf,oBACE,WAAY,KACZ,cAAe,IAAI,IAAI,IAAI,IAC3B,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,OAAQ,IAAI,KAAK,IAAI,KACrB,QAAS,KAAK,KAAK,KAAK,KACxB,QAAS,GAGX,WACE,OAAQ,KACR,QAAS,YACT,cAAe,IACf,aAAc,KACd,eAAgB,OAElB,eACE,OAAQ,KACR,MAAO,KACP,MAAO,KAGT,WACE,WAAY,WACZ,MAAO,KACP,QAAS,MACT,OAAQ,MAAM,KAAK,EAAE,KACrB,UAAW,KACX,SAAU,SACV,QAAS,EAAE,IACX,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KACb,MAAO,KACP,QAAS,GAGX,gBACE,WAAY,QACZ,OAAQ,IAAI,MAAM,QAClB,WAAY,EACZ,mBAAoB,IAAI,IAAI,IAAI,EAAI,eACpC,WAAY,IAAI,IAAI,IAAI,EAAI,eAC5B,WAAY,WACZ,OAAQ,QACR,UAAW,KACX,KAAM,IACN,SAAU,SACV,QAAS,KAAK,KACd,WAAY,KACZ,UAAW,gBACX,aAAc,aACd,4BAA6B,YAE/B,sBACE,WAAY,KACZ,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,MAAO,KAET,yCACE,gBACE,UAAW,MAIf,4BACE,YAAa,KAGf,2BACE,cAAe,EAAE,EAAE,IAAI,IAIzB,2BACE,aAAc,IAGhB,gBACE,WAAY,kBACZ,gBAAiB,UACjB,OAAQ,KACR,KAAM,EACN,SAAU,MACV,IAAK,EACL,MAAO,KACP,QAAS"}
1
+ {"version":3,"sources":["assets\\css\\atcb.css"],"names":[],"mappings":"AAYA,MACE,QAAS,KAGX,qBACE,QAAS,aACT,SAAU,SAGZ,aACE,WAAY,QACZ,OAAQ,IAAI,MAAM,QAClB,cAAe,IACf,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,MAAO,KACP,OAAQ,QACR,QAAS,aACT,UAAW,KACX,YAAa,IACb,YAAa,KACb,OAAQ,KAAK,KACb,UAAW,MACX,UAAW,MACX,QAAS,KAAK,KAAK,KAAK,KACxB,SAAU,SACV,WAAY,OACZ,aAAc,aACd,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KACb,4BAA6B,YAC7B,MAAO,KAET,mBACE,WAAY,KAEd,yCACE,aACE,UAAW,MAIf,oBACE,WAAY,KACZ,cAAe,IAAI,IAAI,IAAI,IAC3B,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,OAAQ,IAAI,KAAK,IAAI,KACrB,QAAS,KAAK,KAAK,KAAK,KACxB,QAAS,GAGX,WACE,OAAQ,KACR,QAAS,YACT,cAAe,IACf,aAAc,KACd,eAAgB,OAElB,eACE,OAAQ,KACR,MAAO,KACP,MAAO,KAGT,WACE,WAAY,WACZ,MAAO,KACP,QAAS,MACT,OAAQ,MAAM,KAAK,EAAE,KACrB,UAAW,KACX,SAAU,SACV,QAAS,EAAE,IACX,oBAAqB,KACrB,iBAAkB,KAClB,gBAAiB,KACjB,YAAa,KACb,MAAO,KACP,QAAS,GAGX,gBACE,WAAY,QACZ,OAAQ,IAAI,MAAM,QAClB,WAAY,EACZ,mBAAoB,IAAI,IAAI,IAAI,EAAI,eACpC,WAAY,IAAI,IAAI,IAAI,EAAI,eAC5B,WAAY,WACZ,OAAQ,QACR,UAAW,KACX,KAAM,IACN,SAAU,SACV,QAAS,KAAK,KACd,WAAY,KACZ,UAAW,gBACX,aAAc,aACd,4BAA6B,YAE/B,sBACE,WAAY,KACZ,mBAAoB,IAAI,IAAI,KAAK,EAAI,eACrC,WAAY,IAAI,IAAI,KAAK,EAAI,eAC7B,MAAO,KAET,yCACE,gBACE,UAAW,MAIf,4BACE,YAAa,KAGf,2BACE,cAAe,EAAE,EAAE,IAAI,IAIzB,2BACE,aAAc,IAGhB,gBACE,WAAY,kBACZ,gBAAiB,UACjB,OAAQ,KACR,KAAM,EACN,SAAU,MACV,IAAK,EACL,MAAO,KACP,QAAS"}
@@ -3,7 +3,7 @@
3
3
  * Add-to-Calendar Button
4
4
  * ++++++++++++++++++++++
5
5
  */
6
- const atcbVersion = '1.4.3';
6
+ const atcbVersion = '1.5.0';
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
@@ -46,7 +46,7 @@ function atcb_init() {
46
46
  atcbConfig['deleteJSON'] = true;
47
47
  }
48
48
  // rewrite config for backwards compatibility - you can remove this, if you did not use this script before v1.4.0.
49
- atcbConfig = atcb_rewrite_config(atcbConfig);
49
+ atcbConfig = atcb_patch_config(atcbConfig);
50
50
  // check, if all required data is available
51
51
  if (atcb_check_required(atcbConfig)) {
52
52
  // calculate the real date values in case that there are some special rules included (e.g. adding days dynamically)
@@ -91,7 +91,7 @@ function atcb_clean_schema_json(atcbConfig) {
91
91
 
92
92
 
93
93
  // BACKWARDS COMPATIBILITY REWRITE - you can remove this, if you did not use this script before v1.4.0.
94
- function atcb_rewrite_config(atcbConfig) {
94
+ function atcb_patch_config(atcbConfig) {
95
95
  const keyChanges = {
96
96
  'title': 'name',
97
97
  'dateStart': 'startDate',
@@ -138,11 +138,15 @@ function atcb_date_calculation(dateString) {
138
138
  // check for any dynamic additions and adjust
139
139
  const dateStringParts = dateString.split('+');
140
140
  const dateParts = dateStringParts[0].split('-');
141
- let newDate = new Date(dateParts[2], dateParts[0] - 1, dateParts[1]);
141
+ let newDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
142
+ if (dateParts[0].length < 4) {
143
+ // backwards compatibility for version <1.5.0
144
+ newDate = new Date(dateParts[2], dateParts[0] - 1, dateParts[1]);
145
+ }
142
146
  if (dateStringParts[1] != null && dateStringParts[1] > 0) {
143
147
  newDate.setDate(newDate.getDate() + parseInt(dateStringParts[1]));
144
148
  }
145
- return (((newDate.getMonth() + 1) < 10 ? '0' : '') + (newDate.getMonth() + 1)) + '-' + (newDate.getDate() < 10 ? '0' : '') + newDate.getDate() + '-' + newDate.getFullYear();
149
+ return newDate.getFullYear() + '-' + (((newDate.getMonth() + 1) < 10 ? '0' : '') + (newDate.getMonth() + 1)) + '-' + (newDate.getDate() < 10 ? '0' : '') + newDate.getDate();
146
150
  }
147
151
 
148
152
 
@@ -170,7 +174,7 @@ function atcb_validate(data) {
170
174
  console.log("add-to-calendar button generation failed: date misspelled [" + date + ": " + data[date] + "]");
171
175
  return false;
172
176
  }
173
- newDate[date] = new Date(dateParts[2], dateParts[0] - 1, dateParts[1]);
177
+ newDate[date] = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);
174
178
  return true;
175
179
  })) {
176
180
  return false;
@@ -231,7 +235,7 @@ function atcb_generate(button, buttonId, data) {
231
235
  buttonTriggerWrapper.classList.add('atcb_button_wrapper');
232
236
  button.appendChild(buttonTriggerWrapper);
233
237
  // generate the button trigger div
234
- let buttonTrigger = document.createElement('div');
238
+ let buttonTrigger = document.createElement('button');
235
239
  buttonTrigger.id = 'atcb_button_' + buttonId;
236
240
  buttonTrigger.classList.add('atcb_button');
237
241
  buttonTrigger.dataset.atcbtn = buttonId;
@@ -240,13 +244,21 @@ function atcb_generate(button, buttonId, data) {
240
244
  buttonTrigger.innerHTML += '<span class="atcb_text">' + (data['label'] || 'Add to Calendar') + '</span>';
241
245
  // set event listeners for the button trigger
242
246
  if (data['trigger'] == 'click') {
243
- buttonTrigger.addEventListener('click', atcb_toggle, {passive: true});
247
+ buttonTrigger.addEventListener('mousedown', atcb_toggle);
244
248
  } else {
245
249
  buttonTrigger.addEventListener('touchstart', atcb_toggle, {passive: true});
246
- buttonTrigger.addEventListener('mouseenter', atcb_open, false);
250
+ buttonTrigger.addEventListener('mouseenter', atcb_open);
247
251
  }
248
- // standardize any line breaks in the description
252
+ buttonTrigger.addEventListener('focus', atcb_open);
253
+ buttonTrigger.addEventListener('keydown', function(event) { // trigger click on enter as well
254
+ if (event.key == 'Enter') {
255
+ atcb_toggle.call(event.target);
256
+ }
257
+ });
258
+ // standardize any line breaks in the description and transform URLs (but keep a clean copy without the URL magic for iCal)
249
259
  data['description'] = data['description'].replace(/<br\s*\/?>/gmi, '\n');
260
+ data['description_iCal'] = data['description'].replace('[url]','').replace('[/url]','');
261
+ data['description'] = data['description'].replace(/\[url\](.*?)\[\/url\]/g, "<a href='$1' target='_blank' rel='noopener'>$1</a>");
250
262
  // generate the options list
251
263
  let optionsList = document.createElement('div');
252
264
  optionsList.id = 'atcb_list_' + buttonId;
@@ -257,7 +269,8 @@ function atcb_generate(button, buttonId, data) {
257
269
  data['options'].forEach(function(option) {
258
270
  let optionParts = option.split('|');
259
271
  let optionItem = document.createElement('div');
260
- optionItem.classList.add('atcb_list_item');
272
+ optionItem.classList.add('atcb_list_item');
273
+ optionItem.tabIndex = 0;
261
274
  optionsList.appendChild(optionItem);
262
275
  switch (optionParts[0]) {
263
276
  case "Apple":
@@ -268,7 +281,7 @@ function atcb_generate(button, buttonId, data) {
268
281
  optionItem.addEventListener('click', function() {
269
282
  atcb_generate_ical(data);
270
283
  atcb_close_all();
271
- }, false);
284
+ });
272
285
  break;
273
286
  case "Google":
274
287
  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>';
@@ -278,7 +291,7 @@ function atcb_generate(button, buttonId, data) {
278
291
  optionItem.addEventListener('click', function() {
279
292
  atcb_generate_google(data);
280
293
  atcb_close_all();
281
- }, false);
294
+ });
282
295
  break;
283
296
  case "iCal":
284
297
  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>';
@@ -288,7 +301,7 @@ function atcb_generate(button, buttonId, data) {
288
301
  optionItem.addEventListener('click', function() {
289
302
  atcb_generate_ical(data);
290
303
  atcb_close_all();
291
- }, false);
304
+ });
292
305
  break;
293
306
  case "Microsoft365":
294
307
  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>';
@@ -298,7 +311,7 @@ function atcb_generate(button, buttonId, data) {
298
311
  optionItem.addEventListener('click', function() {
299
312
  atcb_generate_microsoft(data, '365');
300
313
  atcb_close_all();
301
- }, false);
314
+ });
302
315
  break;
303
316
  case "Outlook.com":
304
317
  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>';
@@ -308,7 +321,7 @@ function atcb_generate(button, buttonId, data) {
308
321
  optionItem.addEventListener('click', function() {
309
322
  atcb_generate_microsoft(data, 'outlook');
310
323
  atcb_close_all();
311
- }, false);
324
+ });
312
325
  break;
313
326
  case "Yahoo":
314
327
  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>';
@@ -318,19 +331,26 @@ function atcb_generate(button, buttonId, data) {
318
331
  optionItem.addEventListener('click', function() {
319
332
  atcb_generate_yahoo(data);
320
333
  atcb_close_all();
321
- }, false);
334
+ });
322
335
  break;
323
336
  }
337
+ optionItem.addEventListener('keydown', function(event) { // trigger click on enter as well
338
+ if (event.key == 'Enter') {
339
+ this.click();
340
+ }
341
+ });
324
342
  });
325
343
  // create the background overlay, which also acts as trigger to close any dropdowns
326
344
  let bgOverlay = document.createElement('div');
327
345
  bgOverlay.id = 'atcb_bgoverlay_' + buttonId;
328
346
  bgOverlay.classList.add('atcb_bgoverlay');
329
- bgOverlay.style.display = 'none';
347
+ bgOverlay.style.display = 'none';
348
+ bgOverlay.tabIndex = 0;
330
349
  button.appendChild(bgOverlay);
331
- bgOverlay.addEventListener('click', atcb_close_all, {passive: true});
350
+ bgOverlay.addEventListener('click', atcb_close_all);
332
351
  bgOverlay.addEventListener('touchstart', atcb_close_all, {passive: true});
333
- bgOverlay.addEventListener('mouseenter', atcb_close_all, false);
352
+ bgOverlay.addEventListener('mousemove', atcb_close_all);
353
+ bgOverlay.addEventListener('focus', atcb_close_all);
334
354
  // update the placeholder class to prevent multiple initializations
335
355
  button.classList.remove('atcb');
336
356
  button.classList.add('atcb_initialized');
@@ -372,7 +392,6 @@ function atcb_close() {
372
392
  document.getElementById('atcb_bgoverlay_' + this.dataset.atcbtn).style.display = 'none';
373
393
  }
374
394
 
375
-
376
395
  function atcb_close_all() {
377
396
  // get all buttons
378
397
  let atcButtons = document.querySelectorAll('.atcb_button');
@@ -479,7 +498,7 @@ function atcb_generate_ical(data) {
479
498
  "DTSTAMP:" + formattedDate['start'],
480
499
  "DTSTART" + timeslot + ":" + formattedDate['start'],
481
500
  "DTEND" + timeslot + ":" + formattedDate['end'],
482
- "DESCRIPTION:" + data['description'].replace(/\n/g, '\\n'),
501
+ "DESCRIPTION:" + data['description_iCal'].replace(/\n/g, '\\n'),
483
502
  "SUMMARY:" + data['name'],
484
503
  "LOCATION:" + data['location'],
485
504
  "STATUS:CONFIRMED",
@@ -500,7 +519,7 @@ function atcb_generate_ical(data) {
500
519
  'bubbles': true,
501
520
  'cancelable': false
502
521
  });
503
- save.dispatchEvent(evt);
522
+ save.dispatchEvent(evt);
504
523
  (window.URL || window.webkitURL).revokeObjectURL(save.href);
505
524
  }
506
525
  } catch(e) {
@@ -521,8 +540,8 @@ function atcb_generate_time(data, style = 'delimiters', targetCal = 'general') {
521
540
  // 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)
522
541
  if (data['timeZoneOffset'] != null && data['timeZoneOffset'] != '') {
523
542
  // if we have a timezone offset given, consider it
524
- start = new Date( startDate[2] + '-' + startDate[0] + '-' + startDate[1] + 'T' + data['startTime'] + ':00.000' + data['timeZoneOffset'] );
525
- end = new Date( endDate[2] + '-' + endDate[0] + '-' + endDate[1] + 'T' + data['endTime'] + ':00.000' + data['timeZoneOffset'] );
543
+ start = new Date( startDate[0] + '-' + startDate[1] + '-' + startDate[2] + 'T' + data['startTime'] + ':00.000' + data['timeZoneOffset'] );
544
+ end = new Date( endDate[0] + '-' + endDate[1] + '-' + endDate[2] + 'T' + data['endTime'] + ':00.000' + data['timeZoneOffset'] );
526
545
  start = start.toISOString().replace('.000', '');
527
546
  end = end.toISOString().replace('.000', '');
528
547
  if (style == 'clean') {
@@ -531,8 +550,8 @@ function atcb_generate_time(data, style = 'delimiters', targetCal = 'general') {
531
550
  }
532
551
  } else {
533
552
  // if there is no offset, we prepare the time, assuming it is UTC formatted
534
- start = new Date( startDate[2] + '-' + startDate[0] + '-' + startDate[1] + 'T' + data['startTime'] + ':00.000+00:00' );
535
- end = new Date( endDate[2] + '-' + endDate[0] + '-' + endDate[1] + 'T' + data['endTime'] + ':00.000+00:00' );
553
+ start = new Date( startDate[0] + '-' + startDate[1] + '-' + startDate[2] + 'T' + data['startTime'] + ':00.000+00:00' );
554
+ end = new Date( endDate[0] + '-' + endDate[1] + '-' + endDate[2] + 'T' + data['endTime'] + ':00.000+00:00' );
536
555
  if (data['timeZone'] != null && data['timeZone'] != '') {
537
556
  // if a timezone is given, we adjust dynamically with the modern toLocaleString function
538
557
  let utcDate = new Date(start.toLocaleString('en-US', { timeZone: "UTC" }));
@@ -553,10 +572,10 @@ function atcb_generate_time(data, style = 'delimiters', targetCal = 'general') {
553
572
  }
554
573
  } else { // would be an allday event then
555
574
  allday = true;
556
- start = new Date( startDate[2], startDate[0] - 1, startDate[1]);
575
+ start = new Date( startDate[0], startDate[1] - 1, startDate[2]);
557
576
  start.setDate(start.getDate() + 1); // increment the day by 1
558
577
  let breakStart = start.toISOString().split('T');
559
- end = new Date( endDate[2], endDate[0] - 1, endDate[1]);
578
+ end = new Date( endDate[0], endDate[1] - 1, endDate[2]);
560
579
  if (targetCal == 'google' || targetCal == 'microsoft' || targetCal == 'ical') {
561
580
  end.setDate(end.getDate() + 2); // increment the day by 2 for Google Calendar, iCal and Outlook
562
581
  } else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "add-to-calendar-button",
3
- "version": "1.4.3",
3
+ "version": "1.5.0",
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/atcb_npm.js",
6
6
  "types": "index.d.ts",