1// Needed to ensure correct timing. 2document.addEventListener("DOMContentLoaded", function () { 3 // so many constants 4 const DEU_LANG = "de-DE"; 5 const DEU_ENG_PROFILE = "Choose your concern"; 6 const ENG_PROFILE = "Chat with"; 7 const CAN_ISO = "CAN"; 8 const DEU_ISO = "DEU"; 9 const GBR_ISO = "GBR"; 10 const IRL_ISO = "IRL"; 11 const USA_ISO = "USA"; 12 const AUT_ISO = "AUT"; 13 const WEEKDAYS = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; 14 const UK_LOCATION = "Europe/London"; 15 const US_LOCATION = "America/Chicago"; 16 const DEU_LOCATION = "Europe/Berlin"; 17 const AUT_LOCATION = "Europe/Vienna"; 18 const LANGUAGE_COOKIE = "PreferredLanguage"; 19 const COUNTRY_COOKIE = "PromegaCountry"; 20 const US_TECH_FOOTER_PLACEHOLDER = "US Tech"; 21 const US_TECH_PROFILE = "Technical Service - US"; 22 const US_CUST_FOOTER_PLACEHOLDER = "US Cust"; 23 const US_CUST_PROFILE = "Customer Service - US"; 24 const UK_TECH_FOOTER_PLACEHOLDER = "UK Tech"; 25 const UK_TECH_PROFILE = "Technical Service - UK"; 26 const UK_CUST_FOOTER_PLACEHOLDER = "UK Cust"; 27 const UK_CUST_PROFILE = "Customer Service - UK"; 28 const IE_CUST_FOOTER_PLACEHOLDER = "IE Cust"; 29 const IE_CUST_PROFILE = "Customer Service - IE"; 30 const IE_TECH_FOOTER_PLACEHOLDER = "IE Tech"; 31 const IE_TECH_PROFILE = "Technical Service - IE"; 32 const DEU_TECH_FOOTER_PLACEHOLDER = "Germany Tech"; 33 const DEU_TECH_PROFILE = "Frage zu Produktanwendungen"; 34 const DEU_ENG_TECH_PROFILE = "Question about product applications"; 35 const DEU_CUST_FOOTER_PLACEHOLDER = "Germany Cust"; 36 const DEU_CUST_PROFILE = "Frage zu Bestellungen"; 37 const DEU_ENG_CUST_PROFILE = "Question about orders"; 38 const HIDDEN_TECH_INPUT = ".customer-support__url--techserv"; 39 const HIDDEN_CUST_INPUT = ".customer-support__url--custserv"; 40 const CHAT_BTN_CLASS = ".launch-chat"; 41 const PROMEGA_STILL_WATER = "#455DA0"; 42 const IS_CUST_ONLY = true; 43 const IS_TECH_ONLY = false;
44 45 // Main Five9 config object that determines options for chat widget. 46 const five9Config = { 47 rootUrl: "https://app.five9.com/consoles/", 48 type: "chat", 49 title: "Promega", 50 tenant: "Promega", 51 profiles: [], 52 showProfiles: true, 53 autostart: true, 54 theme: "https://scv10mr-cdnpre-p-cus-00.azureedge.net/-/media/files/stylesheets/chatstyles.css", 55 logo: "https://scv10mr-cdnpre-p-cus-00.azureedge.net/assets/images/logos/promega-logo-wide.svg", 56 surveyOptions: { 57 showComment: true, 58 requireComment: false, 59 }, 60 fields: { 61 name: { 62 value: "", 63 show: true, 64 label: "Name", 65 }, 66 email: { 67 value: "", 68 show: true, 69 label: "Email", 70 }, 71 Institution: { 72 value: "", 73 show: true, 74 label: "Institution", 75 required: true, 76 }, 77 }, 78 playSoundOnMessage: true, 79 allowCustomerToControlSoundPlay: true, 80 showEmailButton: false, 81 hideDuringAfterHours: true, 82 useBusinessHours: true, 83 showPrintButton: false, 84 allowUsabilityMenu: true, 85 enableCallback: false, 86 callbackList: "", 87 allowRequestLiveAgent: false, 88 }; 89 90 // Helper func to get cookie for geolocations 91 const getCookie = (name) => { 92 const value = `; ${document.cookie}`; 93 const parts = value.split(`; ${name}=`); 94 if (parts.length === 2) return parts.pop().split(";").shift(); 95 }; 96 97 const languageCookie = getCookie(LANGUAGE_COOKIE); 98 const countryCookie = getCookie(COUNTRY_COOKIE); 99 100 if (countryCookie) { 101 // anticipating future language support? 102 switch (countryCookie) { 103 case DEU_ISO: 104 case AUT_ISO: 105 if (languageCookie === DEU_LANG) { 106 five9Config.lang = 107 "https://scv10mr-cdnpre-p-cus-00.azureedge.net/-/media/files/javascript/five9/chat-de-localization-v1.js"; 108 } else { 109 five9Config.profileLabel = DEU_ENG_PROFILE; 110 } 111 break; 112 default: 113 five9Config.profileLabel = ENG_PROFILE; 114 break; 115 } 116 } 117 118 // Data and methods required to hide chat buttons after hours. 119 const branchHours = { 120 [USA_ISO]: {}, 121 [CAN_ISO]: {}, 122 [GBR_ISO]: {}, 123 [IRL_ISO]: {}, 124 [DEU_ISO]: {}, 125 [AUT_ISO]: {}, 126 }; 127 WEEKDAYS.slice(1, WEEKDAYS.length - 1).forEach((day) => { 128 branchHours[USA_ISO][day] = ["0800", "1700"]; 129 }); 130 WEEKDAYS.slice(1, WEEKDAYS.length - 1).forEach((day) => { 131 branchHours[CAN_ISO][day] = ["0800", "1700"]; 132 }); 133 WEEKDAYS.slice(1, WEEKDAYS.length - 2).forEach((day) => { 134 branchHours[GBR_ISO][day] = ["0830", "1700"]; 135 }); 136 branchHours[GBR_ISO][WEEKDAYS[5]] = ["0830", "1530"]; 137 WEEKDAYS.slice(1, WEEKDAYS.length - 2).forEach((day) => { 138 branchHours[IRL_ISO][day] = ["0830", "1700"]; 139 }); 140 branchHours[IRL_ISO][WEEKDAYS[5]] = ["0830", "1530"]; 141 WEEKDAYS.slice(1, WEEKDAYS.length - 2).forEach((day) => { 142 branchHours[DEU_ISO][day] = ["0800", "1800"]; 143 }); 144 branchHours[DEU_ISO][WEEKDAYS[5]] = ["0800", "1700"]; 145 WEEKDAYS.slice(1, WEEKDAYS.length - 2).forEach((day) => { 146 branchHours[AUT_ISO][day] = ["0800", "1800"]; 147 }); 148 branchHours[AUT_ISO][WEEKDAYS[5]] = ["0800", "1700"]; 149 150 const hideChatButtons = () => { 151 const chatButtons = document.querySelectorAll(CHAT_BTN_CLASS); 152 if (chatButtons.length > 0) { 153 for (let i = 0, j = chatButtons.length; i < j; i++) { 154 // chatButtons[i].classList.add("chat-disabled"); 155 chatButtons[i].style.display = "none"; 156 } 157 } 158 }; 159 160 const showChatButtons = () => { 161 const chatButtons = document.querySelectorAll(CHAT_BTN_CLASS); 162 if (chatButtons.length > 0) { 163 for (let i = 0, j = chatButtons.length; i < j; i++) { 164 // chatButtons[i].classList.remove("chat-disabled"); 165 chatButtons[i].style.display = "inline-block"; 166 } 167 } 168 }; 169 170 const GetDatetime = (location) => { 171 let options = { 172 timeZone: location, 173 weekday: "long", 174 hour: "numeric", 175 minute: "numeric", 176 second: "numeric", 177 hour12: false, 178 }; 179 formatter = new Intl.DateTimeFormat([], options); 180 result = formatter.format(new Date()); 181 return result; 182 }; 183 184 // Fixes existing clarity buttons 185 const buttonHax = () => { 186 const techBtns = document.querySelectorAll(".trigger--techserv-chat"); 187 if (techBtns.length > 0) { 188 for (let i = 0, j = techBtns.length; i < j; i++) { 189 techBtns[i].setAttribute("href", "javascript:;"); 190 techBtns[i].removeAttribute("hidden"); 191 techBtns[i].classList.remove("trigger--techserv-chat"); 192 techBtns[i].classList.add("launch-chat"); 193 } 194 } 195 196 const custBtns = document.querySelectorAll(".trigger--custserv-chat"); 197 if (custBtns.length > 0) { 198 for (let i = 0, j = custBtns.length; i < j; i++) { 199 custBtns[i].setAttribute("href", "javascript:;"); 200 custBtns[i].removeAttribute("hidden"); 201 custBtns[i].classList.remove("trigger--custserv-chat"); 202 custBtns[i].classList.add("launch-chat"); 203 } 204 } 205 }; 206 207 // matches location, day and time against branchHours 208 const checkIfOpen = (isoCode, currentDay, currentTime) => { 209 if (typeof branchHours[isoCode][currentDay] === "undefined") { 210 return false;
211 } 212 if ( 213 parseInt(currentTime) >= parseInt(branchHours[isoCode][currentDay][0]) && 214 parseInt(currentTime) <= parseInt(branchHours[isoCode][currentDay][1]) 215 ) { 216 return true; 217 } 218 return false; 219 }; 220 221 // Possibly needed to continiously check time? 222 const poll = async ({ fn, validate, interval, location }) => { 223 const executePoll = async (resolve, reject) => { 224 const dateResult = fn(location); 225 const currentDay = dateResult.match(/^[a-zA-Z]+/)[0]; 226 const currentTime = dateResult.substring(t.length - 3, t.length - 8).replace(":", ""); 227 228 if (validate(countryCookie, currentDay, currentTime)) { 229 return resolve(result); 230 } else { 231 setTimeout(executePoll, interval, resolve, reject); 232 } 233 }; 234 return new Promise(executePoll); 235 }; 236 237 const timezoneLocations = { 238 [USA_ISO]: US_LOCATION, 239 [CAN_ISO]: US_LOCATION, 240 [GBR_ISO]: UK_LOCATION, 241 [IRL_ISO]: UK_LOCATION, 242 [DEU_ISO]: DEU_LOCATION, 243 [AUT_ISO]: AUT_LOCATION, 244 }; 245 246 const currentLocation = timezoneLocations[countryCookie]; 247 if (currentLocation) { 248 const currentDatetime = GetDatetime(currentLocation); 249 const currentDay = currentDatetime.match(/^[a-zA-Z]+/)[0]; 250 const currentTime = currentDatetime 251 .substring(currentDatetime.length - 3, currentDatetime.length - 8) 252 .replace(":", ""); 253 const IsOpenNow = checkIfOpen(countryCookie, currentDay, currentTime); 254 if (IsOpenNow) { 255 showChatButtons(); 256 } else { 257 hideChatButtons(); 258 } 259 } 260 261 // Helper func to get hidden footer inputs 262 const getLocalChatLink = (linkClass) => { 263 const inputElement = document.querySelector(linkClass); 264 if (inputElement && inputElement.value) { 265 return inputElement.value; 266 } 267 return undefined; 268 }; 269 270 // Creative way to selectively enable chat on specific pages 271 const localChatValues = new Map(); 272 localChatValues.set(US_TECH_FOOTER_PLACEHOLDER, US_TECH_PROFILE); 273 localChatValues.set(US_CUST_FOOTER_PLACEHOLDER, US_CUST_PROFILE); 274 localChatValues.set(UK_TECH_FOOTER_PLACEHOLDER, UK_TECH_PROFILE); 275 localChatValues.set(UK_CUST_FOOTER_PLACEHOLDER, UK_CUST_PROFILE); 276 localChatValues.set(IE_TECH_FOOTER_PLACEHOLDER, IE_TECH_PROFILE); 277 localChatValues.set(IE_CUST_FOOTER_PLACEHOLDER, IE_CUST_PROFILE); 278 localChatValues.set( 279 DEU_TECH_FOOTER_PLACEHOLDER, 280 languageCookie === DEU_LANG ? DEU_TECH_PROFILE : DEU_ENG_TECH_PROFILE 281 ); 282 localChatValues.set( 283 DEU_CUST_FOOTER_PLACEHOLDER, 284 languageCookie === DEU_LANG ? DEU_CUST_PROFILE : DEU_ENG_CUST_PROFILE 285 ); 286 287 const techServLink = getLocalChatLink(HIDDEN_TECH_INPUT); 288 const custServLink = getLocalChatLink(HIDDEN_CUST_INPUT); 289 290 let techProfile; 291 if (techServLink) { 292 techProfile = localChatValues.get(techServLink); 293 } 294 295 if (techProfile) { 296 document.querySelector(HIDDEN_TECH_INPUT).value = techProfile; 297 } 298 299 let custProfile; 300 if (custServLink) { 301 custProfile = localChatValues.get(custServLink); 302 } 303 304 if (custProfile) { 305 document.querySelector(HIDDEN_CUST_INPUT).value = custProfile; 306 } 307 308 const setupChatSupportBtns = () => { 309 const chatSupportBtns = document.querySelectorAll('[class*="launch-chat"]'); 310 const chatMaximizeBtn = document.querySelector("#five9-maximize-button"); 311 const chatMinimizeBtn = document.querySelector("#five9-minimize-button"); 312 313 chatMaximizeBtn.style.background = PROMEGA_STILL_WATER; 314 chatMinimizeBtn.style.background = PROMEGA_STILL_WATER; 315 316 if (chatSupportBtns && chatMaximizeBtn) { 317 for (let i = 0, j = chatSupportBtns.length; i < j; i++) 318 chatSupportBtns[i].addEventListener("click", function (event) { 319 chatMaximizeBtn.click(); 320 event.preventDefault(); 321 }); 322 } 323 }; 324 325 const setupChatWidget = () => { 326 const techServLink = getLocalChatLink(HIDDEN_TECH_INPUT); 327 const custServLink = getLocalChatLink(HIDDEN_CUST_INPUT); 328 329 // Customer link first as per specification 330 if (custServLink && !IS_TECH_ONLY) { 331 five9Config.profiles.push(custServLink); 332 } 333 334 if (techServLink && !IS_CUST_ONLY) { 335 five9Config.profiles.push(techServLink); 336 } 337 338 if (window.__five9Initialized) return; 339 340 if ( 341 (languageCookie !== DEU_LANG && countryCookie === DEU_ISO) || 342 (languageCookie !== DEU_LANG && countryCookie === AUT_ISO) 343 ) { 344 if (/applications/.test(techServLink) || /orders/.test(custServLink)) { 345 const target = document.body; 346 const observer = new MutationObserver(function (mutations) { 347 mutations.forEach(function (mutation) { 348 if (mutation.addedNodes.length && mutation.addedNodes[0].className === "five9-frame") { 349 buttonHax(); 350 setupChatSupportBtns(); 351 observer.disconnect(); 352 } 353 }); 354 }); 355 356 const config = { attributes: false, childList: true, characterData: false }; 357 observer.observe(target, config); 358 window.__five9Initialized = true; 359 window.Five9SocialWidget.addWidget(five9Config); 360 } 361 } else if (languageCookie === DEU_LANG) { 362 if (/Produktanwendungen/.test(techServLink) || /Bestellungen/.test(custServLink)) { 363 const target = document.body; 364 const observer = new MutationObserver(function (mutations) { 365 mutations.forEach(function (mutation) { 366 if (mutation.addedNodes.length && mutation.addedNodes[0].className === "five9-frame") { 367 buttonHax(); 368 setupChatSupportBtns(); 369 observer.disconnect(); 370 } 371 }); 372 }); 373 374 const config = { attributes: false, childList: true, characterData: false }; 375 observer.observe(target, config); 376 window.__five9Initialized = true; 377 window.Five9SocialWidget.addWidget(five9Config); 378 } 379 } else { 380 if (/Technical/.test(techServLink) || /Customer/.test(custServLink)) { 381 const target = document.body; 382 const observer = new MutationObserver(function (mutations) { 383 mutations.forEach(function (mutation) { 384 if (mutation.addedNodes.length && mutation.addedNodes[0].className === "five9-frame") { 385 buttonHax(); 386 setupChatSupportBtns(); 387 observer.disconnect(); 388 } 389 }); 390 }); 391 392 const config = { attributes: false, childList: true, characterData: false }; 393 observer.observe(target, config); 394 window.__five9Initialized = true; 395 window.Five9SocialWidget.addWidget(five9Config); 396 } 397 } 398 }; 399 400 const init = () => { 401 setupChatWidget(); 402 }; 403 404 function loadScript(url, callback) { 405 var script = document.createElement("script"); 406 script.type = "text/javascript"; 407 if (script.readyState) { 408 // only required for IE <9 409 script.onreadystatechange = function () { 410 if (script.readyState === "loaded" || script.readyState === "complete") { 411 script.onreadystatechange = null; 412 callback(); 413 } 414 }; 415 } else { 416 script.onload = function () { 417 callback(); 418 }; 419 } 420 421 script.src = url; 422 document.getElementsByTagName("head")[0].appendChild(script); 423 } 424 425 loadScript( 426 "https://app.five9.com/five9_clients/consoles_latest/SocialWidget/five9-social-widget.min.js", 427 init 428 ); 429});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.