add-to-calendar-button 2.6.21 → 2.7.1

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/dist/atcb.js CHANGED
@@ -974,15 +974,15 @@ function tzlib_get_timezones(jsonType = false) {
974
974
  * Add to Calendar Button
975
975
  * ++++++++++++++++++++++
976
976
  *
977
- * Version: 2.6.21
977
+ * Version: 2.7.1
978
978
  * Creator: Jens Kuerschner (https://jekuer.com)
979
979
  * Project: https://github.com/add2cal/add-to-calendar-button
980
980
  * License: Elastic License 2.0 (ELv2) (https://github.com/add2cal/add-to-calendar-button/blob/main/LICENSE.txt)
981
981
  * Note: DO NOT REMOVE THE COPYRIGHT NOTICE ABOVE!
982
982
  *
983
983
  */
984
- const atcbVersion = '2.6.21';
985
- const atcbCssTemplate = {
984
+ const atcbVersion = '2.7.1';
985
+ const atcbCssTemplate = {
986
986
  if (typeof window === 'undefined') {
987
987
  return false;
988
988
  } else {
@@ -1515,8 +1515,9 @@ function atcb_decorate_data_description(data, i) {
1515
1515
  description = cleanDescription(description);
1516
1516
  if (data.customVar) {
1517
1517
  for (const key in data.customVar) {
1518
- const sanitizedKey = key.replace(/[^\w\-.]/g, '');
1519
- description = description.replace(new RegExp(`%%${sanitizedKey}%%`, 'g'), data.customVar[`${key}`]);
1518
+ const sanitizedKey = '%%' + key.replace(/[^\w\-.]/g, '') + '%%';
1519
+ // eslint-disable-next-line security/detect-non-literal-regexp
1520
+ description = description.replace(new RegExp(sanitizedKey, 'gi'), data.customVar[`${key}`]);
1520
1521
  }
1521
1522
  }
1522
1523
  const descriptionHtmlFree = atcb_rewrite_html_elements(description, true);
@@ -1574,9 +1575,11 @@ function atcb_decorate_data_extend(data) {
1574
1575
  }
1575
1576
  if (data.customVar) {
1576
1577
  for (const key in data.customVar) {
1577
- const sanitizedKey = key.replace(/[^\w\-.]/g, '');
1578
- data.dates[`${i}`].name = data.dates[`${i}`].name.replace(new RegExp(`%%${sanitizedKey}%%`, 'g'), data.customVar[`${key}`]);
1579
- data.dates[`${i}`].location = data.dates[`${i}`].location.replace(new RegExp(`%%${sanitizedKey}%%`, 'g'), data.customVar[`${key}`]);
1578
+ const sanitizedKey = '%%' + key.replace(/[^\w\-.]/g, '') + '%%';
1579
+ // eslint-disable-next-line security/detect-non-literal-regexp
1580
+ data.dates[`${i}`].name = data.dates[`${i}`].name.replace(new RegExp(sanitizedKey, 'gi'), data.customVar[`${key}`]);
1581
+ // eslint-disable-next-line security/detect-non-literal-regexp
1582
+ data.dates[`${i}`].location = data.dates[`${i}`].location.replace(new RegExp(sanitizedKey, 'gi'), data.customVar[`${key}`]);
1580
1583
  }
1581
1584
  }
1582
1585
  }
@@ -1589,26 +1592,31 @@ function atcb_decorate_data_extend(data) {
1589
1592
  return data;
1590
1593
  }
1591
1594
  function atcb_date_cleanup(dateTimeData) {
1595
+ function isValidDateFormat(dateStr) {
1596
+ return /^\d\d\d\d-\d\d-\d\d(?:T\d\d:\d\d)?(?::\d\d)?(?:.\d\d\d)?Z?$/i.test(dateStr);
1597
+ }
1598
+ function isValidTodayFormat(dateStr) {
1599
+ return /^today(?:\+(?:\d|\d\d|\d\d\d|\d\d\d\d))?$/i.test(dateStr);
1600
+ }
1592
1601
  if (!dateTimeData.endDate || dateTimeData.endDate === '') {
1593
1602
  dateTimeData.endDate = dateTimeData.startDate;
1594
1603
  }
1595
1604
  const endpoints = ['start', 'end'];
1596
1605
  endpoints.forEach(function (point) {
1597
- if (!/^(?:\d{4}-\d{2}-\d{2}T?(?:\d{2}:\d{2})?Z?|today(?:\+\d{1,4})?)$/i.test(dateTimeData[point + 'Date'])) {
1606
+ const dateStr = dateTimeData[point + 'Date'];
1607
+ if (!isValidDateFormat(dateStr) && !isValidTodayFormat(dateStr)) {
1598
1608
  dateTimeData[point + 'Date'] = 'badly-formed';
1599
1609
  } else {
1600
- dateTimeData[point + 'Date'] = atcb_date_calculation(dateTimeData[point + 'Date']);
1610
+ if (isValidTodayFormat(dateStr)) dateTimeData[point + 'Date'] = atcb_date_calculation(dateStr);
1601
1611
  if (dateTimeData[point + 'Date']) {
1602
- dateTimeData[point + 'Date'] = dateTimeData[point + 'Date'].replace(/\.\d{3}/, '').replace('Z', '');
1603
1612
  const tmpSplitStartDate = dateTimeData[point + 'Date'].split('T');
1604
1613
  if (tmpSplitStartDate[1]) {
1605
1614
  dateTimeData[point + 'Date'] = tmpSplitStartDate[0];
1606
1615
  dateTimeData[point + 'Time'] = tmpSplitStartDate[1];
1607
1616
  }
1608
1617
  }
1609
- if (dateTimeData[point + 'Time'] && dateTimeData[point + 'Time'].length === 8) {
1610
- const timeStr = dateTimeData[point + 'Time'];
1611
- dateTimeData[point + 'Time'] = timeStr.substring(0, timeStr.length - 3);
1618
+ if (dateTimeData[point + 'Time'] && dateTimeData[point + 'Time'].length > 5) {
1619
+ dateTimeData[point + 'Time'] = dateTimeData[point + 'Time'].substring(0, 5);
1612
1620
  }
1613
1621
  }
1614
1622
  });
@@ -1653,12 +1661,7 @@ function atcb_date_calculation(dateString) {
1653
1661
  dateString = dateString.replace(/today/gi, todayString);
1654
1662
  const dateStringParts = dateString.split('+');
1655
1663
  const dateParts = dateStringParts[0].split('-');
1656
- let newDate = (function () {
1657
- if (dateParts[0].length < 4) {
1658
- return new Date(Date.UTC(dateParts[2], dateParts[0] - 1, dateParts[1]));
1659
- }
1660
- return new Date(Date.UTC(dateParts[0], dateParts[1] - 1, dateParts[2]));
1661
- })();
1664
+ const newDate = new Date(Date.UTC(dateParts[0], dateParts[1] - 1, dateParts[2].substring(0, 2)));
1662
1665
  if (dateStringParts[1] && dateStringParts[1] > 0) {
1663
1666
  newDate.setDate(newDate.getDate() + parseInt(dateStringParts[1]));
1664
1667
  }
@@ -1701,19 +1704,25 @@ function atcb_decorate_data_button_status_handling(data) {
1701
1704
  return data;
1702
1705
  }
1703
1706
  async function atcb_decorate_data_rsvp(data) {
1704
- if (typeof atcb_check_booked_out !== 'function' || !data.rsvp || Object.keys(data.rsvp).length === 0) return data;
1707
+ if (typeof atcb_check_bookings !== 'function' || !data.rsvp || !data.proKey || Object.keys(data.rsvp).length === 0) return data;
1705
1708
  data.rsvp.expired = (function () {
1706
1709
  if (data.rsvp && data.rsvp.expires && new Date(data.rsvp.expires) < new Date()) {
1707
1710
  return true;
1708
1711
  }
1709
1712
  return false;
1710
1713
  })();
1711
- data.rsvp.bookedOut = await atcb_check_booked_out(data);
1712
- if (data.rsvp.expired || data.rsvp.bookedOut) {
1713
- data.blockInteraction = true;
1714
- }
1715
- if (data.blockInteraction) {
1716
- data.disabled = true;
1714
+ if (data.rsvp.max) {
1715
+ const bookings = await atcb_check_bookings(data.proKey, data.dev);
1716
+ data.rsvp.seatsLeft = data.rsvp.max - bookings;
1717
+ if (data.rsvp.seatsLeft < 1) {
1718
+ data.rsvp.bookedOut = true;
1719
+ }
1720
+ if (data.rsvp.expired || data.rsvp.bookedOut) {
1721
+ data.blockInteraction = true;
1722
+ }
1723
+ if (data.blockInteraction) {
1724
+ data.disabled = true;
1725
+ }
1717
1726
  }
1718
1727
  return data;
1719
1728
  }
@@ -2452,6 +2461,9 @@ async function atcb_generate_rsvp_form(host, data, hostEl, keyboardTrigger = fal
2452
2461
  ' class="atcb-modal-btn atcb-modal-btn-primary atcb-modal-btn-border">' +
2453
2462
  atcb_translate_hook('submit', data) +
2454
2463
  '</button><span id="pro-form-submitting" class="pro-waiting"><span>.</span><span>.</span><span>.</span></span></p>';
2464
+ if (rsvpData.seatsLeft && rsvpData.seatsLeft > 0) {
2465
+ rsvpContent += '<p class="pro-form-fine">' + atcb_translate_hook('form.seatsleft', data) + ': <b>' + rsvpData.seatsLeft + '</b></p>';
2466
+ }
2455
2467
  rsvpContent += '</form>';
2456
2468
  rsvpContent += '</div></div>';
2457
2469
  let rsvpHost = null;
@@ -2691,24 +2703,20 @@ async function atcb_generate_rsvp_button(host, data) {
2691
2703
  }
2692
2704
  return true;
2693
2705
  }
2694
- async function atcb_check_booked_out(data) {
2695
- if (data.rsvp && data.rsvp.max && data.proKey && data.proKey !== '') {
2696
- try {
2697
- const response = await fetch('https://api.add-to-calendar-pro.com/dffb8bbd-ee5e-4a4f-a7ea-503af98ca468?prokey=' + data.proKey + (data.dev ? '&dev=true' : ''), {
2698
- method: 'GET',
2699
- });
2700
- if (!response.ok) {
2701
- throw new Error('Network response was not ok');
2702
- }
2703
- const responseJson = await response.json();
2704
- if (parseInt(responseJson.total) >= data.rsvp.max) {
2705
- return true;
2706
- }
2707
- } catch (error) {
2708
- console.error('Error:', error);
2706
+ async function atcb_check_bookings(proKey, dev = false) {
2707
+ try {
2708
+ const response = await fetch('https://api.add-to-calendar-pro.com/dffb8bbd-ee5e-4a4f-a7ea-503af98ca468?prokey=' + proKey + (dev ? '&dev=true' : ''), {
2709
+ method: 'GET',
2710
+ });
2711
+ if (!response.ok) {
2712
+ throw new Error('Network response was not ok');
2709
2713
  }
2714
+ const responseJson = await response.json();
2715
+ return parseInt(responseJson.total);
2716
+ } catch (error) {
2717
+ console.error('Error:', error);
2710
2718
  }
2711
- return false;
2719
+ return 0;
2712
2720
  }
2713
2721
  function atcb_build_form(fields, identifier = '', disabled = false) {
2714
2722
  /*!
@@ -3828,7 +3836,7 @@ function atcb_generate_subscribe_links(host, linkType, data, keyboardTrigger) {
3828
3836
  atcb_subscribe_ical(data, data.icsFile);
3829
3837
  break;
3830
3838
  }
3831
- atcb_subscribe_ical(data, adjustedFileUrl);
3839
+ atcb_subscribe_ical(data, adjustedFileUrl, host, keyboardTrigger);
3832
3840
  break;
3833
3841
  case 'google':
3834
3842
  atcb_subscribe_google(data, adjustedFileUrl);
@@ -3897,7 +3905,11 @@ function atcb_set_fully_successful(host, data, multiDateModal = false) {
3897
3905
  atcb_toggle(host, 'close');
3898
3906
  }
3899
3907
  }
3900
- function atcb_subscribe_ical(data, fileUrl) {
3908
+ function atcb_subscribe_ical(data, fileUrl, host = null, keyboardTrigger = false) {
3909
+ if ((atcbIsiOS() || data.fakeIOS) && !atcbIsSafari()) {
3910
+ atcb_ical_copy_note(host, fileUrl, data, keyboardTrigger);
3911
+ return;
3912
+ }
3901
3913
  atcb_open_cal_url(data, 'ical', fileUrl, true);
3902
3914
  }
3903
3915
  function atcb_subscribe_google(data, fileUrl) {
@@ -4222,7 +4234,7 @@ function atcb_generate_ical(host, data, subEvent = 'all', keyboardTrigger = fals
4222
4234
  }
4223
4235
  return 'data:text/calendar;charset=utf-8,' + encodeURIComponent(ics_lines.join('\r\n'));
4224
4236
  })();
4225
- if ((atcbIsiOS() && !atcbIsSafari()) || (atcbIsWebView() && (atcbIsiOS() || (atcbIsAndroid() && atcbIsProblematicWebView())))) {
4237
+ if (((atcbIsiOS() || data.fakeIOS) && !atcbIsSafari()) || (atcbIsWebView() && (atcbIsiOS() || data.fakeIOS || ((atcbIsAndroid() || data.fakeAndroid) && atcbIsProblematicWebView())))) {
4226
4238
  atcb_ical_copy_note(host, dataUrl, data, keyboardTrigger);
4227
4239
  return;
4228
4240
  }
@@ -4248,7 +4260,7 @@ function atcb_determine_ical_filename(data, subEvent) {
4248
4260
  }
4249
4261
  function atcb_ical_copy_note(host, dataUrl, data, keyboardTrigger) {
4250
4262
  atcb_copy_to_clipboard(dataUrl);
4251
- if (atcbIsiOS() && !atcbIsSafari()) {
4263
+ if ((atcbIsiOS() || data.fakeIOS) && !atcbIsSafari()) {
4252
4264
  atcb_create_modal(
4253
4265
  host,
4254
4266
  data,
@@ -5765,27 +5777,26 @@ if (atcbIsBrowser()) {
5765
5777
  }
5766
5778
  this.proOverride = !proOverrideVal || proOverrideVal === 'true' || proOverrideVal === '' ? true : false;
5767
5779
  }
5768
- if ((this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') || (this.hasAttribute('prokey') && this.getAttribute('prokey') !== '')) {
5769
- if (this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') {
5770
- this.data = await atcb_get_pro_data(this.getAttribute('proKey'), this);
5780
+ try {
5781
+ if ((this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') || (this.hasAttribute('prokey') && this.getAttribute('prokey') !== '')) {
5782
+ if (this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') {
5783
+ this.data = await atcb_get_pro_data(this.getAttribute('proKey'), this);
5784
+ } else {
5785
+ this.data = await atcb_get_pro_data(this.getAttribute('prokey'), this);
5786
+ }
5787
+ if (this.data.proKey) this.proKey = this.data.proKey;
5771
5788
  } else {
5772
- this.data = await atcb_get_pro_data(this.getAttribute('prokey'), this);
5773
- }
5774
- if (this.data.proKey) this.proKey = this.data.proKey;
5775
- }
5776
- if (!this.data.name || this.data.name === '') {
5777
- this.data.proKey = '';
5778
- try {
5789
+ this.data.proKey = '';
5779
5790
  this.data = await atcb_process_inline_data(this, this.debug);
5780
- } catch (e) {
5781
- if (this.debug) {
5782
- console.error(e);
5783
- atcb_render_debug_msg(this.shadowRoot, e);
5784
- }
5785
- this.state.initializing = false;
5786
- this.state.ready = true;
5787
- return;
5788
5791
  }
5792
+ } catch (e) {
5793
+ if (this.debug) {
5794
+ console.error(e);
5795
+ atcb_render_debug_msg(this.shadowRoot, e);
5796
+ }
5797
+ this.state.initializing = false;
5798
+ this.state.ready = true;
5799
+ return;
5789
5800
  }
5790
5801
  await this.initButton();
5791
5802
  this.state.initializing = false;
@@ -5840,24 +5851,23 @@ if (atcbIsBrowser()) {
5840
5851
  const elem = document.createElement('template');
5841
5852
  elem.innerHTML = template;
5842
5853
  this.shadowRoot.append(elem.content.cloneNode(true));
5843
- if (this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') {
5844
- this.data = await atcb_get_pro_data(this.getAttribute('proKey'), this);
5845
- if (this.data.proKey) this.proKey = this.data.proKey;
5846
- } else if (this.hasAttribute('prokey') && this.getAttribute('prokey') !== '') {
5847
- this.data = await atcb_get_pro_data(this.getAttribute('prokey'), this);
5848
- if (this.data.proKey) this.proKey = this.data.proKey;
5849
- }
5850
- if (!this.data.name || this.data.name === '') {
5851
- try {
5854
+ try {
5855
+ if (this.hasAttribute('proKey') && this.getAttribute('proKey') !== '') {
5856
+ this.data = await atcb_get_pro_data(this.getAttribute('proKey'), this);
5857
+ if (this.data.proKey) this.proKey = this.data.proKey;
5858
+ } else if (this.hasAttribute('prokey') && this.getAttribute('prokey') !== '') {
5859
+ this.data = await atcb_get_pro_data(this.getAttribute('prokey'), this);
5860
+ if (this.data.proKey) this.proKey = this.data.proKey;
5861
+ } else {
5852
5862
  this.data = await atcb_process_inline_data(this, this.debug);
5853
- } catch (e) {
5854
- if (this.debug) {
5855
- console.error(e);
5856
- atcb_render_debug_msg(this.shadowRoot, e);
5857
- }
5858
- this.updatePending = false;
5859
- return;
5860
5863
  }
5864
+ } catch (e) {
5865
+ if (this.debug) {
5866
+ console.error(e);
5867
+ atcb_render_debug_msg(this.shadowRoot, e);
5868
+ }
5869
+ this.updatePending = false;
5870
+ return;
5861
5871
  }
5862
5872
  atcb_cleanup(this.shadowRoot, this.identifier);
5863
5873
  await this.initButton();
@@ -6188,19 +6198,28 @@ async function atcb_action(inputData, triggerElement, keyboardTrigger = false) {
6188
6198
  if (!atcbIsBrowser()) {
6189
6199
  return;
6190
6200
  }
6191
- let data = await (async function () {
6192
- const cleanedInput = atcb_secure_content(inputData);
6193
- if (cleanedInput.prokey && cleanedInput.prokey !== '') {
6194
- cleanedInput.proKey = cleanedInput.prokey;
6195
- }
6196
- if (cleanedInput.proKey && cleanedInput.proKey !== '') {
6197
- const proData = await atcb_get_pro_data(cleanedInput.proKey, null, cleanedInput);
6198
- if (proData.name && proData.name != '') {
6199
- return proData;
6201
+ let data;
6202
+ try {
6203
+ data = await (async function () {
6204
+ const cleanedInput = atcb_secure_content(inputData);
6205
+ if (cleanedInput.prokey && cleanedInput.prokey !== '') {
6206
+ cleanedInput.proKey = cleanedInput.prokey;
6200
6207
  }
6201
- }
6202
- return cleanedInput;
6203
- })();
6208
+ if (cleanedInput.proKey && cleanedInput.proKey !== '') {
6209
+ try {
6210
+ const proData = await atcb_get_pro_data(cleanedInput.proKey, null, cleanedInput);
6211
+ return proData;
6212
+ } catch (e) {
6213
+ throw new Error(e.message);
6214
+ }
6215
+ } else {
6216
+ return cleanedInput;
6217
+ }
6218
+ })();
6219
+ } catch (e) {
6220
+ console.error(e);
6221
+ return;
6222
+ }
6204
6223
  data.debug = data.debug === 'true';
6205
6224
  try {
6206
6225
  await atcb_check_required(data);
@@ -6338,9 +6357,6 @@ async function atcb_get_pro_data(licenseKey, el = null, directData = {}) {
6338
6357
  const response = await fetch((dataOverrides.dev ? 'https://event-dev.caldn.net/' : 'https://event.caldn.net/') + licenseKey + '/config.json');
6339
6358
  if (response.ok) {
6340
6359
  const data = await response.json();
6341
- if (!data.name || data.name === '') {
6342
- throw new Error('Not possible to read proKey config from server...');
6343
- }
6344
6360
  if (proOverride) {
6345
6361
  atcbWcParams.forEach((key) => {
6346
6362
  if (Object.prototype.hasOwnProperty.call(dataOverrides, key) && ['hideBranding', 'hidebranding', 'rsvp', 'ty'].indexOf(key) === -1) {
@@ -6354,13 +6370,16 @@ async function atcb_get_pro_data(licenseKey, el = null, directData = {}) {
6354
6370
  }
6355
6371
  });
6356
6372
  }
6373
+ if (!data.name || data.name === '') {
6374
+ throw new Error('Not possible to read proKey config from server...');
6375
+ }
6357
6376
  data.proKey = licenseKey;
6358
6377
  data.identifier = licenseKey;
6359
6378
  return data;
6360
6379
  }
6361
6380
  throw new Error('Not possible to read proKey config from server...');
6362
6381
  } catch {
6363
- console.error('Add to Calendar Button proKey invalid or server not responding! Falling back to local data...');
6382
+ throw new Error('Add to Calendar Button proKey invalid or server not responding!');
6364
6383
  }
6365
6384
  }
6366
6385
  return {};