PageSourceSearch

https://go.ksb.com/rs/050-CAG-466/images/LP-Footer-Scripts-Sandbox.js

js ksb.com collected 2026-10-01 11:26:35 UTC 9,493 bytes, 372 lines download raw bytes

1(() => {
2  let FUNC_INDENTIFIER = "success-message";
3  let DATA_LAYER_TIMEOUT = 4000;
4
5  /**
6   * @param {string} str
7   * @param {number} chunkSize
8   * @param {number} maxChunks
9   * @return {string[] | null}
10   */
11  function splitStringIntoChunks(str, chunkSize, maxChunks) {
12    if (typeof str !== "string" || str.length === 0) {
13      return null;
14    }
15
16    let chunks = [];
17    for (
18      let i = 0;
19      i < str.length && chunks.length < maxChunks;
20      i += chunkSize
21    ) {
22      chunks.push(str.substring(i, i + chunkSize));
23    }
24    return chunks;
25  }
26
27  /**
28   * @param {MktoForm2} mktoForm
29   * @param {{sourceFieldName: string, targetFieldName: string}} options
30   */
31  function splitFieldValue(mktoForm, options) {
32    mktoForm.onSubmit(() => {
33      let formValues = mktoForm.getValues();
34      if (
35        !(options.sourceFieldName in formValues) ||
36        formValues[options.sourceFieldName] == null
37      ) {
38        return;
39      }
40
41      let chunks = splitStringIntoChunks(
42        formValues[options.sourceFieldName],
43        40,
44        4,
45      );
46      if (chunks == null) {
47        return;
48      }
49
50      let hiddenFields = {};
51      for (let i = 0; i < 4; i += 1) {
52        hiddenFields[
53          `${options.targetFieldName}${i === 0 ? "" : i}`
54        ] = chunks[i] ?? null;
55      }
56
57      mktoForm.addHiddenFields(hiddenFields);
58    });
59  }
60
61  /**
62   * @param {string} name
63   * @return {string}
64   */
65  function getCookieValue(name) {
66    return decodeURIComponent(
67      document.cookie.match(
68        `(^|;)\\s*${name}\\s*=\\s*([^;]+)`,
69      )?.pop() ?? "",
70    );
71  }
72
73  /**
74   * @param {string} urlQueryString
75   * @param {string[]} urlParams
76   * @return {boolean}
77   */
78  function hasURLParams(urlQueryString, urlParamNames) {
79    let urlParams = new URLSearchParams(urlQueryString);
80     return urlParamNames.some((urlParamName) => {
81       return urlParams.has(urlParamName);
82     });
83  }
84
85  /**
86   * @param {MktoForm2} mktoForm
87   * @param {Record<string, string>} fieldMapping
88   */
89  function setURLParamsAsHiddenFields(mktoForm, fieldMapping) {
90    let urlParams = Object.values(fieldMapping);
91    let urlQueryString = window.location.search;
92    let sessionQueryString = getCookieValue("gtm_storage_query");
93    let urlSearchParams;
94
95    if (
96      urlQueryString.length > 0 &&
97      hasURLParams(urlQueryString, urlParams)
98    ) {
99      urlSearchParams = new URLSearchParams(urlQueryString);
100    } else if (
101      sessionQueryString.length > 0 &&
102      hasURLParams(sessionQueryString, urlParams)
103    ) {
104      urlSearchParams = new URLSearchParams(sessionQueryString);
105    } else {
106      return;
107    }
108
109    let fields = Object.keys(fieldMapping);
110    let hiddenFields = {};
111    for (let field of fields) {
112      let urlParameterName = fieldMapping[field];
113
114      if (urlSearchParams.has(urlParameterName)) {
115        hiddenFields[field] = urlSearchParams.get(urlParameterName);
116      }
117    }
118
119    mktoForm.addHiddenFields(hiddenFields);
120  }
121
122  /**
123   * @param {Function} callback
124   */
125  function ready(callback) {
126    if (document.readyState !== "loading") {
127      callback();
128    } else {
129      document.addEventListener("DOMContentLoaded", callback);
130    }
131  }
132
133  /**
134   * Compares URLs without considering their query strings or hashes.
135   *
136   * @param {string} firstURL
137   * @param {string} secondURL
138   * @return {boolean}
139   */
140  function isSameURL(firstURL, secondURL) {
141    try {
142      let parsedFirstURL = new URL(firstURL, window.location.href);
143      let parsedSecondURL = new URL(secondURL, window.location.href);
144
145      return (
146        parsedFirstURL.protocol === parsedSecondURL.protocol &&
147        parsedFirstURL.port === parsedSecondURL.port &&
148        parsedFirstURL.hostname === parsedSecondURL.hostname &&
149        parsedFirstURL.pathname === parsedSecondURL.pathname
150      );
151    } catch {
152      return firstURL === secondURL;
153    }
154  }
155
156  /**
157   * @param {Record<string, unknown>} dataLayerEvt
158   * @param {number} timeout
159   * @return {Promise<boolean>}
160   */
161  function sendToDataLayer(
162    dataLayerEvt,
163    timeout = DATA_LAYER_TIMEOUT,
164  ) {
165    return new Promise((resolve) => {
166      if (!Array.isArray(window.dataLayer)) {
167        resolve(false);
168        return;
169      }
170
171      let isPromiseSettled = false;
172      let timeoutId;
173
174      let handleCallback = (isDataLayerPushed) => {
175        if (isPromiseSettled) {
176          return;
177        }
178
179        isPromiseSettled = true;
180        window.clearTimeout(timeoutId);
181        resolve(isDataLayerPushed);
182      };
183
184      timeoutId = window.setTimeout(() => {
185        handleCallback(false);
186      }, timeout);
187
188      try {
189        window.dataLayer.push({
190          ...dataLayerEvt,
191          eventTimeout: timeout,
192          eventCallback() {
193            handleCallback(true);
194          },
195        });
196      } catch {
197        handleCallback(false);
198      }
199    });
200  }
201
202  /**
203   * @param {HTMLFormElement} formEl
204   * @param {{messageFieldset?: string}} options
205   * @return {string | null}
206   */
207  function findSuccessMessage(formEl, options) {
208    let fieldsetEls = formEl.querySelectorAll("fieldset");
209    let successMessage = null;
210
211    if (options.messageFieldset == null) {
212      return successMessage;
213    }
214
215    for (let fieldsetEl of fieldsetEls) {
216      let legendEl = fieldsetEl.querySelector("legend");
217      if (
218        legendEl?.textContent?.trim().toLowerCase() !==
219        options.messageFieldset.trim().toLowerCase()
220      ) {
221        continue;
222      }
223
224      let hasInputEl =
225        fieldsetEl.querySelector("input, select, textarea") !== null;
226      let htmlTextEl = fieldsetEl.querySelector(".mktoHtmlText");
227
228      if (hasInputEl || !htmlTextEl) {
229        continue;
230      }
231
232      let rowEl = fieldsetEl.closest(".mktoFormRow");
233      if (rowEl) {
234        rowEl.style.display = "none";
235      }
236
237      successMessage = htmlTextEl.innerHTML;
238    }
239
240    return successMessage;
241  }
242
243  /**
244   * Waits for the data-layer event and then redirects or displays a message.
245   *
246   * @param {MktoForm2} mktoForm
247   * @param {HTMLFormElement} formEl
248   * @param {{
249   *   messageFieldset?: string,
250   *   defaultMessage?: string
251   * }} options
252   * @param {string} followUpURL
253   * @return {Promise<void>}
254   */
255  async function handleFormSuccess(
256    mktoForm,
257    formEl,
258    options,
259    followUpURL,
260  ) {
261    let storedSuccessMessage = findSuccessMessage(
262      formEl,
263      options,
264    );
265
266    await sendToDataLayer({
267      event: "marketo_form_submit",
268      formId: mktoForm.getId(),
269    });
270
271    if (!isSameURL(followUpURL, window.location.href)) {
272      window.location.href = followUpURL;
273      return;
274    }
275
276    let hasStoredSuccessMessage =
277      typeof storedSuccessMessage === "string" &&
278      storedSuccessMessage.trim().length > 0;
279    let successMessage = hasStoredSuccessMessage
280      ? storedSuccessMessage
281      : options.defaultMessage;
282    let hasSuccessMessage =
283      typeof successMessage === "string" &&
284      successMessage.trim().length > 0;
285    if (hasSuccessMessage) {
286      formEl.innerHTML = successMessage;
287    }
288  }
289
290  /**
291   * @param {MktoForm2} mktoForm
292   * @param {{
293   *   messageFieldset?: string,
294   *   defaultMessage?: string
295   * }} options
296   */
297  function showSuccessMessage(mktoForm, options = {}) {
298    let hasMessageFieldset =
299      Object.prototype.hasOwnProperty.call(
300        options,
301        "messageFieldset",
302      );
303    let hasDefaultMessage =
304      Object.prototype.hasOwnProperty.call(
305        options,
306        "defaultMessage",
307      );
308    if (!hasMessageFieldset && !hasDefaultMessage) {
309      console.warn(
310        "Parameters for the form success message are missing.",
311      );
312      return;
313    }
314
315    let [formEl] = mktoForm.getFormElem();
316    if (!formEl) {
317      return;
318    }
319
320    // Find and hide the success-message fieldset before submission.
321    findSuccessMessage(formEl, options);
322
323    if (
324      formEl.getAttribute(`data-${FUNC_INDENTIFIER}`) === "true"
325    ) {
326      return;
327    }
328
329    formEl.setAttribute(`data-${FUNC_INDENTIFIER}`, "true");
330
331    mktoForm.onSuccess((_formValues, followUpURL) => {
332      handleFormSuccess(
333        mktoForm,
334        formEl,
335        options,
336        followUpURL,
337      );
338      return false;
339    });
340  }
341
342  function initMarketoForms() {
343    if (typeof window.MktoForms2 !== "object") {
344      return;
345    }
346
347    window.MktoForms2.whenReady((mktoForm) => {
348      splitFieldValue(mktoForm, {
349        sourceFieldName: "Company",
350        targetFieldName: "Company_additional_name",
351      });
352
353      setURLParamsAsHiddenFields(mktoForm, {
354        utmsource: "utm_source",
355        utmmedium: "utm_medium",
356        utmcontent: "utm_content",
357        utmcampaign: "utm_campaign",
358        utmterm: "utm_term",
359      });
360    });
361
362    window.MktoForms2.whenRendered((mktoForm) => {
363      showSuccessMessage(mktoForm, {
364        messageFieldset: "Success Message",
365        defaultMessage:
366          "<div class=\"mktoFormSuccessImage\"><img src=\"https://go.ksb.com/rs/050-CAG-466/images/default-tick-box.png\"/></div>",
367      });
368    });
369  }
370
371  ready(initMarketoForms);
372})();

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.