{"version":3,"file":"atcb.js","names":["atcbVersion","isBrowser","Function","isiOS","atcb_init","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","console","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","getUTCMonth","getUTCDate","getUTCFullYear","dateStringParts","dateParts","newDate","setDate","getDate","parseInt","getFullYear","getMonth","options","option","cleanOption","includes","dates","date","time","timeParts","getTime","button","buttonId","buttonTriggerWrapper","createElement","add","appendChild","buttonTrigger","id","setAttribute","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","isInViewport","clientHeight","element","innerHeight","documentElement","right","innerWidth","clientWidth","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","Intl","DateTimeFormat","resolvedOptions","tzDate","offset","setTime","UTC","breakStart","breakEnd","stateCheck","setInterval","clearInterval","modal","getElementsByClassName","config","attributes","childList","subtree","searchResultObserver","MutationObserver","mutations","mutation","observe"],"sources":["site/Components/AddToCalendar/atcb.js"],"mappings":"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","sourcesContent":["/**\r\n * ++++++++++++++++++++++\r\n * Add-to-Calendar Button\r\n * ++++++++++++++++++++++\r\n */\r\nconst atcbVersion = '1.8.9';\r\n/* Creator: Jens Kuerschner (https://jenskuerschner.de)\r\n * Project: https://github.com/jekuer/add-to-calendar-button\r\n * License: MIT with “Commons Clause” License Condition v1.0\r\n * \r\n */\r\n\r\n\r\n\r\nconst isBrowser = new Function(\"try { return this===window; }catch(e){ return false; }\");\r\nconst isiOS = isBrowser() ? new Function(\"if ((/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)){ return true; }else{ return false; }\") : new Function(\"return false;\");\r\n\r\n// INITIALIZE THE SCRIPT AND FUNCTIONALITY\r\nfunction atcb_init() {\r\n // let's get started\r\n // console.log(\"add-to-calendar button initialized (version \" + atcbVersion + \")\");\r\n // console.log(\"See https://github.com/jekuer/add-to-calendar-button for details\");\r\n // get all placeholders\r\n let atcButtons = document.querySelectorAll('.atcb');\r\n // if there are some, move on\r\n if (atcButtons.length > 0) {\r\n // get the amount of already initialized ones first\r\n let atcButtonsInitialized = document.querySelectorAll('.atcb_initialized');\r\n // generate the buttons one by one\r\n for (let i = 0; i < atcButtons.length; i++) {\r\n // skip already initialized ones\r\n if (atcButtons[i].classList.contains('atcb_initialized')) {\r\n continue;\r\n }\r\n let atcbConfig;\r\n // check if schema.org markup is present\r\n let schema = atcButtons[i].querySelector('script');\r\n // get their JSON content first\r\n if (schema && schema.innerHTML) {\r\n // get schema.org event markup and flatten the event block\r\n atcbConfig = JSON.parse(schema.innerHTML.replace(/(\\r\\n|\\n|\\r)/gm, \"\").replace(/(<(?!br)([^>]+)>)/gi, \"\")); // remove real code line breaks before parsing. Use
or \\n explicitely in the description to create a line break. Also strip HTML tags (especially since stupid Safari adds stuff).\r\n atcbConfig = atcb_parse_schema_json(atcbConfig);\r\n // set flag to not delete HTML content later\r\n atcbConfig['deleteJSON'] = false;\r\n } else {\r\n // get JSON from HTML block\r\n atcbConfig = JSON.parse(atcButtons[i].innerHTML.replace(/(\\r\\n|\\n|\\r)/gm, \"\").replace(/(<(?!br)([^>]+)>)/gi, \"\")); // remove real code line breaks before parsing. Use
or \\n explicitely in the description to create a line break. Also strip HTML tags (especially since stupid Safari adds stuff).\r\n // set flag to delete HTML content later\r\n atcbConfig['deleteJSON'] = true;\r\n }\r\n // rewrite config for backwards compatibility - you can remove this, if you did not use this script before v1.4.0.\r\n atcbConfig = atcb_patch_config(atcbConfig);\r\n // check, if all required data is available\r\n if (atcb_check_required(atcbConfig)) {\r\n // Rewrite dynamic dates, standardize line breaks and transform urls in the description\r\n atcbConfig = atcb_decorate_data(atcbConfig);\r\n // validate the config (JSON iput) ...\r\n if (atcb_validate(atcbConfig)) {\r\n // ... and generate the button on success\r\n atcb_generate(atcButtons[i], i + atcButtonsInitialized.length, atcbConfig);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\n\r\n\r\n// NORMALIZE AND PARSE JSON FROM SCHEMA.ORG MARKUP\r\nfunction atcb_parse_schema_json(atcbConfig) {\r\n try {\r\n Object.keys(atcbConfig['event']).forEach(key => {\r\n // move entries one level up, but skip schema types\r\n if (key.charAt(0) !== '@') {\r\n atcbConfig[key] = atcbConfig['event'][key];\r\n }\r\n });\r\n // drop the event block and return\r\n delete atcbConfig.event;\r\n }\r\n catch (err) {\r\n console.error(\"add-to-calendar button problem: it seems like you use the schema.org style, but did not define it properly\");\r\n }\r\n return atcbConfig;\r\n}\r\n\r\n\r\n\r\n// BACKWARDS COMPATIBILITY REWRITE - you can remove this, if you did not use this script before v1.4.0.\r\nfunction atcb_patch_config(atcbConfig) {\r\n const keyChanges = {\r\n 'title': 'name',\r\n 'dateStart': 'startDate',\r\n 'dateEnd': 'endDate',\r\n 'timeStart': 'startTime',\r\n 'timeEnd': 'endTime',\r\n };\r\n Object.keys(keyChanges).forEach(key => {\r\n if (atcbConfig[keyChanges[key]] == null && atcbConfig[key] != null) {\r\n atcbConfig[keyChanges[key]] = atcbConfig[key];\r\n }\r\n });\r\n return atcbConfig;\r\n}\r\n\r\n\r\n\r\n// CLEAN DATA BEFORE FURTHER VALIDATION (CONSIDERING SPECIAL RULES AND SCHEMES)\r\nfunction atcb_decorate_data(atcbConfig) {\r\n // cleanup different date-time formats\r\n atcbConfig = atcb_date_cleanup(atcbConfig);\r\n // calculate the real date values in case that there are some special rules included (e.g. adding days dynamically)\r\n atcbConfig['startDate'] = atcb_date_calculation(atcbConfig['startDate']);\r\n atcbConfig['endDate'] = atcb_date_calculation(atcbConfig['endDate']);\r\n\r\n // if no description or already decorated, return early\r\n if (!atcbConfig.description || atcbConfig.description_iCal) return atcbConfig;\r\n\r\n // make a copy of the given argument rather than mutating in place\r\n const data = Object.assign({}, atcbConfig);\r\n // standardize any line breaks in the description and transform URLs (but keep a clean copy without the URL magic for iCal)\r\n data.description = data.description.replace(//gmi, '\\n');\r\n data.description_iCal = data.description.replace('[url]', '').replace('[/url]', '');\r\n data.description = data.description.replace(/\\[url\\](.*?)\\[\\/url\\]/g, \"$1\");\r\n return data\r\n}\r\n\r\n\r\n\r\n// CHECK FOR REQUIRED FIELDS\r\nfunction atcb_check_required(data) {\r\n // check for at least 1 option\r\n if (data['options'] == null || data['options'].length < 1) {\r\n console.error(\"add-to-calendar button generation failed: no options set\");\r\n return false;\r\n }\r\n // check for min required data (without \"options\")\r\n const requiredField = ['name', 'startDate', 'endDate']\r\n return requiredField.every(function (field) {\r\n if (data[field] == null || data[field] == \"\") {\r\n console.error(\"add-to-calendar button generation failed: required setting missing [\" + field + \"]\");\r\n return false;\r\n }\r\n return true;\r\n });\r\n}\r\n\r\n\r\n\r\n// CALCULATE AND CLEAN UP THE ACTUAL DATES\r\nfunction atcb_date_cleanup(data) {\r\n // parse date+time format (default with Schema.org, but also an unofficial alternative to other implementation)\r\n const endpoints = ['start', 'end'];\r\n endpoints.forEach(function (point) {\r\n if (data[point + 'Date'] != null) {\r\n // remove any milliseconds information\r\n data[point + 'Date'] = data[point + 'Date'].replace(/\\..../, '').replace('Z', '');\r\n // identify a possible time information within the date string\r\n let tmpSplitStartDate = data[point + 'Date'].split('T');\r\n if (tmpSplitStartDate[1] != null) {\r\n data[point + 'Date'] = tmpSplitStartDate[0];\r\n data[point + 'Time'] = tmpSplitStartDate[1];\r\n }\r\n }\r\n // remove any seconds from time information\r\n if (data[point + 'Time'] != null && data[point + 'Time'].length == 8) {\r\n let timeStr = data[point + 'Time'];\r\n data[point + 'Time'] = timeStr.substring(0, timeStr.length - 3);\r\n }\r\n });\r\n return data;\r\n}\r\n\r\nfunction atcb_date_calculation(dateString) {\r\n // replace \"today\" with the current date first\r\n let today = new Date();\r\n let todayString = (today.getUTCMonth() + 1) + '-' + today.getUTCDate() + '-' + today.getUTCFullYear();\r\n dateString = dateString.replace(/today/ig, todayString);\r\n // check for any dynamic additions and adjust\r\n const dateStringParts = dateString.split('+');\r\n const dateParts = dateStringParts[0].split('-');\r\n let newDate = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);\r\n if (dateParts[0].length < 4) {\r\n // backwards compatibility for version <1.5.0\r\n newDate = new Date(dateParts[2], dateParts[0] - 1, dateParts[1]);\r\n }\r\n if (dateStringParts[1] != null && dateStringParts[1] > 0) {\r\n newDate.setDate(newDate.getDate() + parseInt(dateStringParts[1]));\r\n }\r\n return newDate.getFullYear() + '-' + (((newDate.getMonth() + 1) < 10 ? '0' : '') + (newDate.getMonth() + 1)) + '-' + (newDate.getDate() < 10 ? '0' : '') + newDate.getDate();\r\n}\r\n\r\n\r\n\r\n// VALIDATE THE JSON DATA\r\nfunction atcb_validate(data) {\r\n // validate options\r\n const options = ['Apple', 'Google', 'iCal', 'Microsoft365', 'Outlook.com', 'MicrosoftTeams', 'Yahoo']\r\n if (!data['options'].every(function (option) {\r\n let cleanOption = option.split('|');\r\n if (!options.includes(cleanOption[0])) {\r\n console.error(\"add-to-calendar button generation failed: invalid option [\" + cleanOption[0] + \"]\");\r\n return false;\r\n }\r\n return true;\r\n })) {\r\n return false;\r\n }\r\n // validate date\r\n const dates = ['startDate', 'endDate'];\r\n let newDate = dates;\r\n if (!dates.every(function (date) {\r\n if (data[date].length != 10) {\r\n console.error(\"add-to-calendar button generation failed: date misspelled [-> YYYY-MM-DD]\");\r\n return false;\r\n }\r\n const dateParts = data[date].split('-');\r\n if (dateParts.length < 3 || dateParts.length > 3) {\r\n console.error(\"add-to-calendar button generation failed: date misspelled [\" + date + \": \" + data[date] + \"]\");\r\n return false;\r\n }\r\n newDate[date] = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]);\r\n return true;\r\n })) {\r\n return false;\r\n }\r\n // validate time\r\n const times = ['startTime', 'endTime'];\r\n if (!times.every(function (time) {\r\n if (data[time] != null) {\r\n if (data[time].length != 5) {\r\n console.error(\"add-to-calendar button generation failed: time misspelled [-> HH:MM]\");\r\n return false;\r\n }\r\n const timeParts = data[time].split(':');\r\n // validate the time parts\r\n if (timeParts.length < 2 || timeParts.length > 2) {\r\n console.error(\"add-to-calendar button generation failed: time misspelled [\" + time + \": \" + data[time] + \"]\");\r\n return false;\r\n }\r\n if (timeParts[0] > 23) {\r\n console.error(\"add-to-calendar button generation failed: time misspelled - hours number too high [\" + time + \": \" + timeParts[0] + \"]\");\r\n return false;\r\n }\r\n if (timeParts[1] > 59) {\r\n console.error(\"add-to-calendar button generation failed: time misspelled - minutes number too high [\" + time + \": \" + timeParts[1] + \"]\");\r\n return false;\r\n }\r\n // update the date with the time for further validation steps\r\n if (time == 'startTime') {\r\n newDate['startDate'] = new Date(newDate['startDate'].getTime() + (timeParts[0] * 3600000) + (timeParts[1] * 60000))\r\n }\r\n if (time == 'endTime') {\r\n newDate['endDate'] = new Date(newDate['endDate'].getTime() + (timeParts[0] * 3600000) + (timeParts[1] * 60000))\r\n }\r\n }\r\n return true;\r\n })) {\r\n return false;\r\n }\r\n if ((data['startTime'] != null && data['endTime'] == null) || (data['startTime'] == null && data['endTime'] != null)) {\r\n console.error(\"add-to-calendar button generation failed: if you set a starting time, you also need to define an end time\");\r\n return false;\r\n }\r\n // validate whether end is not before start\r\n if (newDate['endDate'] < newDate['startDate']) {\r\n console.error(\"add-to-calendar button generation failed: end date before start date\");\r\n return false;\r\n }\r\n // on passing the validation, return true\r\n return true;\r\n}\r\n\r\n\r\n\r\n// GENERATE THE ACTUAL BUTTON\r\nfunction atcb_generate(button, buttonId, data) {\r\n // clean the placeholder, if flagged that way\r\n if (data['deleteJSON']) {\r\n button.innerHTML = '';\r\n }\r\n // generate the wrapper div\r\n let buttonTriggerWrapper = document.createElement('div');\r\n buttonTriggerWrapper.classList.add('atcb_button_wrapper');\r\n button.appendChild(buttonTriggerWrapper);\r\n // generate the button trigger div\r\n let buttonTrigger = document.createElement('button');\r\n buttonTrigger.id = 'atcb_button_' + buttonId;\r\n buttonTrigger.classList.add('atcb_button');\r\n buttonTrigger.setAttribute('type', 'button');\r\n buttonTriggerWrapper.appendChild(buttonTrigger);\r\n buttonTrigger.innerHTML = '';\r\n buttonTrigger.innerHTML += '' + (data['label'] || 'Add to Calendar') + '';\r\n // set event listeners for the button trigger\r\n if (data['trigger'] == 'click') {\r\n buttonTrigger.addEventListener('mousedown', () => atcb_toggle(data, buttonTrigger, true, false));\r\n } else {\r\n buttonTrigger.addEventListener('touchstart', () => atcb_toggle(data, buttonTrigger, true, false), { passive: true });\r\n buttonTrigger.addEventListener('mouseenter', () => atcb_open(data, buttonTrigger, true, false));\r\n }\r\n buttonTrigger.addEventListener('keydown', function (event) { // trigger click on enter as well\r\n if (event.key == 'Enter') {\r\n atcb_toggle(data, buttonTrigger, true);\r\n }\r\n });\r\n // update the placeholder class to prevent multiple initializations\r\n button.classList.remove('atcb');\r\n button.classList.add('atcb_initialized');\r\n // show the placeholder div\r\n if (data['inline']) {\r\n button.style.display = 'inline-block';\r\n } else {\r\n button.style.display = 'block';\r\n }\r\n // console log\r\n // console.log(\"add-to-calendar button #\" + (buttonId + 1) + \" created\");\r\n}\r\n\r\n\r\nfunction atcb_generate_dropdown_list(data) {\r\n const optionsList = document.createElement('div');\r\n optionsList.classList.add('atcb_list');\r\n // generate the list items\r\n data['options'].forEach(function (option) {\r\n let optionParts = option.split('|');\r\n let optionItem = document.createElement('div');\r\n optionItem.classList.add('atcb_list_item');\r\n optionItem.tabIndex = 0;\r\n optionsList.appendChild(optionItem);\r\n switch (optionParts[0]) {\r\n case \"Apple\":\r\n optionItem.innerHTML = '';\r\n optionItem.innerHTML += '';\r\n optionItem.innerHTML += optionParts[1] || 'Apple';\r\n optionItem.innerHTML += '';\r\n optionItem.addEventListener('click', function () {\r\n atcb_generate_ical(data);\r\n atcb_close();\r\n });\r\n break;\r\n case \"Google\":\r\n optionItem.innerHTML = '';\r\n optionItem.innerHTML += '';\r\n optionItem.innerHTML += optionParts[1] || 'Google';\r\n optionItem.innerHTML += '';\r\n optionItem.addEventListener('click', function () {\r\n atcb_generate_google(data);\r\n atcb_close();\r\n });\r\n break;\r\n case \"iCal\":\r\n optionItem.innerHTML = '';\r\n optionItem.innerHTML += '';\r\n optionItem.innerHTML += optionParts[1] || 'Outlook';\r\n optionItem.innerHTML += '';\r\n optionItem.addEventListener('click', function () {\r\n atcb_generate_ical(data);\r\n atcb_close();\r\n });\r\n break;\r\n case \"MicrosoftTeams\":\r\n optionItem.innerHTML = '';\r\n optionItem.innerHTML += '';\r\n optionItem.innerHTML += optionParts[1] || 'Microsoft Teams';\r\n optionItem.innerHTML += '';\r\n optionItem.addEventListener('click', function () {\r\n atcb_generate_teams(data);\r\n atcb_close();\r\n });\r\n break;\r\n case \"Microsoft365\":\r\n optionItem.innerHTML = '';\r\n optionItem.innerHTML += '';\r\n optionItem.innerHTML += optionParts[1] || 'Microsoft 365';\r\n optionItem.innerHTML += '';\r\n optionItem.addEventListener('click', function () {\r\n atcb_generate_microsoft(data, '365');\r\n atcb_close();\r\n });\r\n break;\r\n case \"Outlook.com\":\r\n optionItem.innerHTML = '';\r\n optionItem.innerHTML += '';\r\n optionItem.innerHTML += optionParts[1] || 'Outlook.com';\r\n optionItem.innerHTML += '';\r\n optionItem.addEventListener('click', function () {\r\n atcb_generate_microsoft(data, 'outlook');\r\n atcb_close();\r\n });\r\n break;\r\n case \"Yahoo\":\r\n optionItem.innerHTML = '';\r\n optionItem.innerHTML += '';\r\n optionItem.innerHTML += optionParts[1] || 'Yahoo';\r\n optionItem.innerHTML += '';\r\n optionItem.addEventListener('click', function () {\r\n atcb_generate_yahoo(data);\r\n atcb_close();\r\n });\r\n break;\r\n }\r\n optionItem.addEventListener('keydown', function (event) { // trigger click on enter as well\r\n if (event.key == 'Enter') {\r\n this.click();\r\n }\r\n });\r\n });\r\n return optionsList;\r\n}\r\n\r\n// create the background overlay, which also acts as trigger to close any dropdowns\r\n\r\nfunction atcb_generate_bg_overlay(data) {\r\n const bgOverlay = document.createElement('div');\r\n bgOverlay.classList.add('atcb_bgoverlay');\r\n bgOverlay.tabIndex = 0;\r\n bgOverlay.addEventListener('click', () => atcb_close(true));\r\n let fingerMoved = false;\r\n bgOverlay.addEventListener('touchstart', () => fingerMoved = false, { passive: true });\r\n bgOverlay.addEventListener('touchmove', () => fingerMoved = true, { passive: true });\r\n bgOverlay.addEventListener('touchend', function () {\r\n if (fingerMoved == false) {\r\n atcb_close(true);\r\n }\r\n }, { passive: true });\r\n bgOverlay.addEventListener('focus', () => atcb_close(false));\r\n if (data['trigger'] !== 'click') {\r\n bgOverlay.addEventListener('mousemove', () => atcb_close(true));\r\n } else {\r\n bgOverlay.classList.add('atcb_click');\r\n }\r\n return bgOverlay;\r\n}\r\n\r\n\r\n\r\n// FUNCTIONS TO CONTROL THE INTERACTION\r\nfunction atcb_toggle(data, button, buttonGenerated, keyboardTrigger = true) {\r\n // check for state and adjust accordingly\r\n if (button.classList.contains('atcb_active')) {\r\n atcb_close();\r\n } else {\r\n atcb_open(data, button, buttonGenerated, keyboardTrigger);\r\n }\r\n}\r\n\r\n// show the dropdown list + background overlay\r\nfunction atcb_open(data, button, buttonGenerated = false, keyboardTrigger = true) {\r\n // abort early if an add-to-calendar dropdown already opened\r\n if (document.querySelector('.atcb_list')) return\r\n\r\n // generate list\r\n const list = atcb_generate_dropdown_list(data, buttonGenerated);\r\n\r\n // set list styles, set possible button to atcb_active and go for modal mode if no button is set\r\n if (button) {\r\n button.classList.add('atcb_active');\r\n const rect = button.getBoundingClientRect();\r\n list.style.width = rect.width + 'px';\r\n list.style.top = rect.bottom + window.scrollY - 3 + 'px';\r\n list.style.left = rect.left + 'px';\r\n } else {\r\n list.classList.add('atcb_modal')\r\n }\r\n if (buttonGenerated) {\r\n list.classList.add('atcb_generated_button');\r\n }\r\n\r\n // add list to DOM\r\n document.body.appendChild(list);\r\n\r\n // add background overlay right after, so tabbing past last option closes list\r\n document.body.appendChild(atcb_generate_bg_overlay(data));\r\n\r\n // give keyboard focus to first item in list, if not blocked, because there is definitely no keyboard trigger\r\n if (keyboardTrigger) {\r\n list.firstChild.focus();\r\n }\r\n //TEK code to move the dropdown up if part of it is not visible\r\n if (!isInViewport(list)) {\r\n list.style.top = parseInt(list.style.top) - list.clientHeight - button.clientHeight + \"px\";\r\n }\r\n //END TEK code\r\n}\r\n\r\nfunction isInViewport(element) {\r\n const rect = element.getBoundingClientRect();\r\n return (\r\n rect.top >= 0 &&\r\n rect.left >= 0 &&\r\n rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&\r\n rect.right <= (window.innerWidth || document.documentElement.clientWidth)\r\n );\r\n}\r\n\r\nfunction atcb_close(blockFocus = false) {\r\n // 1. Focus triggering button (if not existing, try a custom element)\r\n if (!blockFocus) {\r\n let newFocusEl = document.querySelector('.atcb_active');\r\n if (newFocusEl) {\r\n newFocusEl.focus();\r\n } else {\r\n newFocusEl = document.querySelector('.atcb_customTrigger');\r\n if (newFocusEl) {\r\n newFocusEl.focus();\r\n }\r\n }\r\n }\r\n // 2. Inactivate all buttons\r\n Array.from(document.querySelectorAll('.atcb_active')).forEach(button => {\r\n button.classList.remove('atcb_active');\r\n })\r\n // 3. Remove dropdowns & bg overlays (should only be one of each)\r\n Array.from(document.querySelectorAll('.atcb_list')).concat(\r\n Array.from(document.querySelectorAll('.atcb_bgoverlay'))\r\n ).forEach(el => el.remove());\r\n}\r\n\r\n// prepare data when not using the init function\r\nfunction atcb_action(data, button) {\r\n // validate & decorate data\r\n if (!atcb_check_required(data)) {\r\n throw new Error(\"data missing; see logs\")\r\n }\r\n data = atcb_decorate_data(data);\r\n if (!atcb_validate(data)) {\r\n throw new Error(\"Invalid data; see logs\")\r\n }\r\n atcb_open(data, button);\r\n}\r\n\r\n\r\n\r\n// FUNCTION TO GENERATE THE GOOGLE URL\r\nfunction atcb_generate_google(data) {\r\n // base url\r\n let url = 'https://calendar.google.com/calendar/render?action=TEMPLATE';\r\n // generate and add date\r\n let formattedDate = atcb_generate_time(data, 'clean', 'google');\r\n url += '&dates=' + formattedDate['start'] + '%2F' + formattedDate['end'];\r\n // add details (if set)\r\n if (data['name'] != null && data['name'] != '') {\r\n url += '&text=' + encodeURIComponent(data['name']);\r\n }\r\n if (data['location'] != null && data['location'] != '') {\r\n url += '&location=' + encodeURIComponent(data['location']);\r\n // TODO: Find a better solution for the next temporary workaround.\r\n if (isiOS()) { // workaround to cover a bug, where, when using Google Calendar on an iPhone, the location is not recognized. So, for the moment, we simply add it to the description.\r\n if (data['description'] == null || data['description'] == '') {\r\n data['description'] = '';\r\n } else {\r\n data['description'] += '

';\r\n }\r\n data['description'] += '📍: ' + data['location'];\r\n }\r\n }\r\n if (data['description'] != null && data['description'] != '') {\r\n url += '&details=' + encodeURIComponent(data['description']);\r\n }\r\n window.open(url, '_blank').focus();\r\n}\r\n\r\n\r\n\r\n// FUNCTION TO GENERATE THE YAHOO URL\r\nfunction atcb_generate_yahoo(data) {\r\n // base url\r\n let url = 'https://calendar.yahoo.com/?v=60';\r\n // generate and add date\r\n let formattedDate = atcb_generate_time(data, 'clean');\r\n url += '&st=' + formattedDate['start'] + '&et=' + formattedDate['end'];\r\n if (formattedDate['allday']) {\r\n url += '&dur=allday';\r\n }\r\n // add details (if set)\r\n if (data['name'] != null && data['name'] != '') {\r\n url += '&title=' + encodeURIComponent(data['name']);\r\n }\r\n if (data['location'] != null && data['location'] != '') {\r\n url += '&in_loc=' + encodeURIComponent(data['location']);\r\n }\r\n if (data['description'] != null && data['description'] != '') {\r\n url += '&desc=' + encodeURIComponent(data['description']);\r\n }\r\n window.open(url, '_blank').focus();\r\n}\r\n\r\n\r\n\r\n// FUNCTION TO GENERATE THE MICROSOFT 365 OR OUTLOOK WEB URL\r\nfunction atcb_generate_microsoft(data, type = '365') {\r\n // base url\r\n let url = 'https://';\r\n if (type == 'outlook') {\r\n url += 'outlook.live.com';\r\n } else {\r\n url += 'outlook.office.com';\r\n }\r\n url += '/calendar/0/deeplink/compose?path=%2Fcalendar%2Faction%2Fcompose&rru=addevent';\r\n // generate and add date\r\n let formattedDate = atcb_generate_time(data, 'delimiters', 'microsoft');\r\n url += '&startdt=' + formattedDate['start'] + '&enddt=' + formattedDate['end'];\r\n if (formattedDate['allday']) {\r\n url += '&allday=true';\r\n }\r\n // add details (if set)\r\n if (data['name'] != null && data['name'] != '') {\r\n url += '&subject=' + encodeURIComponent(data['name']);\r\n }\r\n if (data['location'] != null && data['location'] != '') {\r\n url += '&location=' + encodeURIComponent(data['location']);\r\n }\r\n if (data['description'] != null && data['description'] != '') {\r\n url += '&body=' + encodeURIComponent(data['description'].replace(/\\n/g, '
'));\r\n }\r\n window.open(url, '_blank').focus();\r\n}\r\n\r\n\r\n\r\n// FUNCTION TO GENERATE THE MICROSOFT TEAMS URL\r\n// 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)\r\n// Location, html tags and linebreaks in the description are not supported yet.\r\nfunction atcb_generate_teams(data) {\r\n // base url\r\n let url = 'https://teams.microsoft.com/l/meeting/new?';\r\n // generate and add date\r\n let formattedDate = atcb_generate_time(data, 'delimiters', 'microsoft');\r\n url += '&startTime=' + formattedDate['start'] + '&endTime=' + formattedDate['end'];\r\n // add details (if set)\r\n let locationString = '';\r\n if (data['name'] != null && data['name'] != '') {\r\n url += '&subject=' + encodeURIComponent(data['name']);\r\n }\r\n if (data['location'] != null && data['location'] != '') {\r\n locationString = encodeURIComponent(data['location']);\r\n url += '&location=' + locationString;\r\n locationString += ' // '; // preparing the workaround putting the location into the description, since the native field is not supported yet\r\n }\r\n if (data['description_iCal'] != null && data['description_iCal'] != '') { // using description_iCal instead of description, since Teams does not support html tags\r\n url += '&content=' + locationString + encodeURIComponent(data['description_iCal']);\r\n }\r\n window.open(url, '_blank').focus();\r\n}\r\n\r\n\r\n\r\n// FUNCTION TO GENERATE THE iCAL FILE (also for the Apple option)\r\nfunction atcb_generate_ical(data) {\r\n let now = new Date();\r\n now = now.toISOString().replace(/\\..../g, '').replace(/[^a-z0-9]/gi, '');\r\n let formattedDate = atcb_generate_time(data, 'clean', 'ical');\r\n let timeslot = '';\r\n if (formattedDate['allday']) {\r\n timeslot = ';VALUE=DATE';\r\n }\r\n let ics_lines = [\r\n \"BEGIN:VCALENDAR\",\r\n \"VERSION:2.0\",\r\n \"CALSCALE:GREGORIAN\",\r\n \"BEGIN:VEVENT\",\r\n \"DTSTAMP:\" + formattedDate['start'],\r\n \"DTSTART\" + timeslot + \":\" + formattedDate['start'],\r\n \"DTEND\" + timeslot + \":\" + formattedDate['end'],\r\n \"SUMMARY:\" + data['name']\r\n ];\r\n if (data['description_iCal'] != null && data['description_iCal'] != '') {\r\n ics_lines.push(\"DESCRIPTION:\" + data['description_iCal'].replace(/\\n/g, '\\\\n'));\r\n }\r\n if (data['location'] != null && data['location'] != '') {\r\n ics_lines.push(\"LOCATION:\" + data['location']);\r\n }\r\n ics_lines.push(\r\n \"STATUS:CONFIRMED\",\r\n \"LAST-MODIFIED:\" + now,\r\n \"SEQUENCE:0\",\r\n \"END:VEVENT\",\r\n \"END:VCALENDAR\"\r\n );\r\n let dlurl = 'data:text/calendar;charset=utf-8,' + encodeURIComponent(ics_lines.join('\\r\\n'));\r\n try {\r\n if (!window.ActiveXObject) {\r\n let save = document.createElement('a');\r\n save.href = dlurl;\r\n save.target = '_blank';\r\n save.download = data['iCalFileName'] || 'event-to-save-in-my-calendar';\r\n let evt = new MouseEvent('click', {\r\n 'view': window,\r\n 'bubbles': true,\r\n 'cancelable': false\r\n });\r\n save.dispatchEvent(evt);\r\n (window.URL || window.webkitURL).revokeObjectURL(save.href);\r\n }\r\n } catch (e) {\r\n console.error(e);\r\n }\r\n}\r\n\r\n\r\n\r\n// SHARED FUNCTION TO GENERATE A TIME STRING\r\nfunction atcb_generate_time(data, style = 'delimiters', targetCal = 'general') {\r\n let startDate = data['startDate'].split('-');\r\n let endDate = data['endDate'].split('-');\r\n let start = '';\r\n let end = '';\r\n let allday = false;\r\n if (data['startTime'] != null && data['endTime'] != null) {\r\n // 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)\r\n if (data['timeZoneOffset'] != null && data['timeZoneOffset'] != '') {\r\n // if we have a timezone offset given, consider it\r\n start = new Date(startDate[0] + '-' + startDate[1] + '-' + startDate[2] + 'T' + data['startTime'] + ':00.000' + data['timeZoneOffset']);\r\n end = new Date(endDate[0] + '-' + endDate[1] + '-' + endDate[2] + 'T' + data['endTime'] + ':00.000' + data['timeZoneOffset']);\r\n start = start.toISOString().replace('.000', '');\r\n end = end.toISOString().replace('.000', '');\r\n if (style == 'clean') {\r\n start = start.replace(/\\-/g, '').replace(/\\:/g, '');\r\n end = end.replace(/\\-/g, '').replace(/\\:/g, '');\r\n }\r\n } else {\r\n // if there is no offset, we prepare the time, assuming it is UTC formatted\r\n start = new Date(startDate[0] + '-' + startDate[1] + '-' + startDate[2] + 'T' + data['startTime'] + ':00.000+00:00');\r\n end = new Date(endDate[0] + '-' + endDate[1] + '-' + endDate[2] + 'T' + data['endTime'] + ':00.000+00:00');\r\n if (data['timeZone'] != null && data['timeZone'] != '') {\r\n // if a timezone is given, we adjust dynamically with the modern toLocaleString function\r\n let utcDate = new Date(start.toLocaleString('en-US', { timeZone: \"UTC\" }));\r\n if (data['timeZone'] == 'currentBrowser') {\r\n data['timeZone'] = Intl.DateTimeFormat().resolvedOptions().timeZone;\r\n }\r\n let tzDate = new Date(start.toLocaleString('en-US', { timeZone: data['timeZone'] }));\r\n let offset = utcDate.getTime() - tzDate.getTime();\r\n start.setTime(start.getTime() + offset);\r\n end.setTime(end.getTime() + offset);\r\n }\r\n start = start.toISOString().replace('.000', '');\r\n end = end.toISOString().replace('.000', '');\r\n if (style == 'clean') {\r\n start = start.replace(/\\-/g, '').replace(/\\:/g, '');\r\n end = end.replace(/\\-/g, '').replace(/\\:/g, '');\r\n }\r\n }\r\n } else { // would be an allday event then\r\n allday = true;\r\n start = new Date(Date.UTC(startDate[0], startDate[1] - 1, startDate[2]));\r\n let breakStart = start.toISOString().replace(/T(.+)Z/g, '');\r\n end = new Date(Date.UTC(endDate[0], endDate[1] - 1, endDate[2]));\r\n if (targetCal == 'google' || targetCal == 'microsoft' || targetCal == 'ical') {\r\n end.setDate(end.getDate() + 1); // increment the day by 1 for Google Calendar, iCal and Outlook\r\n }\r\n let breakEnd = end.toISOString().replace(/T(.+)Z/g, '');\r\n if (style == 'clean') {\r\n breakStart = breakStart.replace(/\\-/g, '');\r\n breakEnd = breakEnd.replace(/\\-/g, '');\r\n }\r\n start = breakStart;\r\n end = breakEnd;\r\n }\r\n let returnObject = { 'start': start, 'end': end, 'allday': allday };\r\n return returnObject;\r\n}\r\n\r\nif (isBrowser()) {\r\n // Global listener to ESC key to close dropdown\r\n document.addEventListener('keydown', evt => {\r\n if (evt.key === 'Escape') {\r\n atcb_close();\r\n }\r\n });\r\n // Global listener to any screen changes, where we need to close all buttons in order to prevent any bad renderings (more \"expensive\" alternative would be to re-render them)\r\n window.addEventListener('resize', () => {\r\n atcb_close(true);\r\n });\r\n}\r\n\r\n\r\n\r\n// START INIT\r\n// TEK Code Block\r\nif (isBrowser()) {\r\n document.addEventListener('DOMContentLoaded', atcb_init, false);\r\n let stateCheck = setInterval(() => {\r\n if (document.querySelectorAll('.global-search-results').length > 0) {\r\n clearInterval(stateCheck);\r\n atcb_init();\r\n }\r\n }, 100);\r\n};\r\n\r\n// Select the target node that will be observed for mutations\r\nconst modal = document.getElementsByClassName(\"js-search-results\")[0];\r\n\r\n// Set the options for the observer (which mutations to observe)\r\nconst config = { attributes: true, childList: true, subtree: true };\r\n\r\n// Create an observer instance linked to the callback function\r\nconst searchResultObserver = new MutationObserver(function (mutations) {\r\n mutations.forEach(function (mutation) {\r\n if (mutation.type !== \"attributes\") {\r\n return;\r\n }\r\n if (document.getElementsByClassName(\"atcb_list\")) {\r\n atcb_init();\r\n }\r\n });\r\n});\r\n\r\n\r\nif (modal) {\r\n // Start observing the target node for configured mutations\r\n searchResultObserver.observe(modal, config);\r\n}\r\n\r\n// END INIT\r\n// END TEK Code Block\r\n"]}