PageSourceSearch

https://www.mhs.net/-/media/bootstrapLoader.js

js mhs.net collected 2026-09-24 19:58:48 UTC 6,808 bytes, 300 lines download raw bytes

1function isMobile() {
2	return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
3	  navigator.userAgent
4	);
5  }
6  
7  const defaultOptions = {
8	withWelcomeScreen: false,
9	welcomeMessage: "GetStarted", //First message sent to Studio when the user start the chat
10	openAfterTimeout: isMobile(true) ? undefined : 3000, //Value in miliseconds. Remove this line if you don't want to a start chat when user clicks in the chat bubble
11	withLocation: false
12  };
13  
14  function bootstrapLoader(webchat, options = defaultOptions) {
15	const { welcomeMessage, withWelcomeScreen, openAfterTimeout, withLocation } = {
16	  ...defaultOptions,
17	  ...options
18	};
19  
20	if (!webchat.isLiveChat) {
21	  return;
22	}
23  
24	const cssFile = document.createElement("link");
25	cssFile.rel = "stylesheet";
26	cssFile.href = "/-/media/scripts/loader.css";
27  
28	const shadowRoot = webchat.injector.shadowRoot;
29	shadowRoot.appendChild(cssFile);
30  
31	// Create panel and loader
32	const panel = document.createElement("div");
33	panel.className = "botonic-loader-panel";
34  
35	var template = document.createElement("template");
36	template.innerHTML =
37	  '<div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div>';
38	const loader = template.content;
39	panel.appendChild(loader);
40	panel.style.display = "none";
41  
42	// MonkeyPatch the onOpen event
43	const onOpen = webchat.onOpenWebchat;
44  
45	function hideLoader() {
46	  panel.style.display = "none";
47	}
48  
49	function showLoader() {
50	  panel.style.display = "block";
51  
52	  setTimeout(hideLoader, 6000);
53	}
54  
55	let initialized = false;
56  
57	const startProcess = () => {
58	  showLoader();
59  
60	  let firstMessage = welcomeMessage;
61
62	  if(withLocation){
63		const l = withLocation
64		? localStorage.getItem("currentLocation")
65		: undefined;
66
67		firstMessage = withLocation
68		? l
69		  ? "Hello from " + l
70		  : "Helloã…¤"
71		: firstMessage;
72
73	  }
74  
75	  setTimeout(() => {
76		webchat.selfHostedApp.addUserMessage({
77			data: firstMessage,
78		  type: "postback"
79		});
80	  }, 100);
81	};
82  
83	const hasClass = (path, cls) => {
84	  return path?.some((p) => {
85	    try {
86	       return p?.className?.startsWith(cls);
87	    } catch (e) {
88	       return false;
89	    }
90	  });
91        };
92  
93	const startButtonClass = "customStartChatButton_";
94  
95	const getForm = () => webchat.injector.shadowRoot.querySelector("form");
96
97	const onSubmit = (e) => {
98		const form = getForm();
99	
100		if (form) {
101		  form.removeEventListener("submit", onSubmit);
102		}
103	
104		if (!isFormValid()) {
105		  e.preventDefault();
106		} else {
107		  startProcess();
108		}
109	  };
110
111	  const isFormValid = () => {
112		return (
113		  webchat.injector.shadowRoot.querySelectorAll('[class*="isError"]')
114			.length === 0
115		);
116	  };
117
118	// Add event listeners
119	webchat.injector.addEventListener("click", (e) => {
120	  if (hasClass(e.composedPath(), "submitButton_")) {
121	      if (withWelcomeScreen) {
122		startProcess();
123	      }
124	      return;
125    	  }	
126  
127	  // When the user clicks on the "Start new chat"
128	  if (hasClass(e.composedPath(), startButtonClass) && e.isTrusted) {
129		if (!withWelcomeScreen) {
130		  setTimeout(startProcess);
131		}
132  
133		// const ref = webchat.selfHostedApp.webchatRef.current;
134		// ref.updateWebchatSettings({ enableUserInput: false });
135	  }
136	});
137  
138	window.showLoader = showLoader;
139  
140	const defaultConfig = {
141	  // Undefined on purpose
142	  livechatConversationEnded: undefined
143	};
144  
145	const getWebchatConfig = () => {
146	  try {
147		const item = localStorage.getItem("webchatConfig");
148  
149		if (item) {
150		  return JSON.parse(item);
151		}
152  
153		return defaultConfig;
154	  } catch (e) {
155		console.error(e);
156		return defaultConfig;
157	  }
158	};
159  
160	const querySelector = (selector) =>
161	  webchat.injector.shadowRoot.querySelector(selector);
162  
163	const getByClass = (className) => querySelector("." + className);
164  
165	const getStartButton = () => {
166	  return querySelector(`[class^="${startButtonClass}"]`);
167	};
168  
169	const getLocation = () => {
170	  if (!withLocation) {
171		return undefined;
172	  }
173  
174	  const currentLocation = localStorage.getItem("currentLocation");
175  
176	  if (currentLocation) {
177		return Promise.resolve(currentLocation);
178	  }
179  
180	  return fetch("https://ipapi.co/json/")
181		.then((apiResult) => apiResult.json())
182		.then((jsonData) => jsonData.city + " - " + jsonData.country_name)
183		.then((l) => {
184		  localStorage.setItem("currentLocation", l);
185		  return l;
186		})
187		.catch(() => {
188		  return undefined;
189		});
190	};
191  
192	const restartSession = async () => {
193	  // Wait until the start button is visible
194	  await new Promise((resolve) => {
195		const interval = setInterval(() => {
196		  const $startButton = getStartButton();
197		  const $endChat = getByClass("end-chat-message");
198  
199		  if ($startButton) {
200			$startButton.style.display = "none";
201		  }
202  
203		  if (!$startButton || !$endChat) {
204			return;
205		  }
206  
207		  // Remove the interval
208		  clearInterval(interval);
209  
210		  // Click on the start button
211		  $startButton.click();
212		  resolve();
213		}, 1);
214	  });
215  
216	  // Wait until the Webchat SDK updates the config
217	  await new Promise((resolve) => {
218		const interval = setInterval(() => {
219		  const { livechatConversationEnded } = getWebchatConfig();
220  
221		  if (!livechatConversationEnded) {
222			clearInterval(interval);
223			resolve();
224		  }
225		}, 1);
226	  });
227	};
228  
229	const onOpenWebchat = async () => {
230	  const botonic = shadowRoot.getElementById("botonic-webchat");
231  
232	  if (!botonic) {
233		console.warn("Couldn't initialize the loader for botonic and live chat");
234		return;
235	  }
236  
237	  // Check if the loader is correctly loaded
238	  if (panel.parentElement !== botonic) {
239		// Append loader
240		botonic.appendChild(panel);
241	  }
242  
243	  if (initialized) {
244		return;
245	  }
246  
247	  initialized = true;
248	  await getLocation();
249  
250	  // Let's see if the conversation ended from config
251	  const { livechatConversationEnded } = getWebchatConfig();
252  
253	  if (livechatConversationEnded) {
254		showLoader();
255		//await restartSession();
256  
257		if (!withWelcomeScreen) {
258		  startProcess();
259		} else {
260		  hideLoader();
261		}
262  
263		return;
264	  }
265  
266	  const lastReadMessageIndex = localStorage.getItem("lastReadMessageIndex");
267  
268	  if (!lastReadMessageIndex || lastReadMessageIndex === "null") {
269		if (!withWelcomeScreen) {
270		  // Show the loader and send the payload
271		  // When opening the widget on the first time
272		  startProcess();
273		}
274	  }
275	};
276  
277	webchat.onOpenWebchat = function () {
278	  onOpen.call(webchat);
279	  onOpenWebchat();
280	};
281  
282	// Open the web widget after a specified timeout
283	if (openAfterTimeout) {
284	  const $button = webchat.injector.shadowRoot.querySelector(
285		"[data-qa='trigger-button']"
286	  );
287  
288	  const { wasChatOpened } = getWebchatConfig();
289  
290	  if (wasChatOpened === undefined && $button) {
291		setTimeout(() => {
292		  $button.click();
293		}, openAfterTimeout);
294	  }
295	}
296  }
297  
298  window.virtualAgentBootstrapLoader = bootstrapLoader;
299  
300// JavaScript Document

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.