PageSourceSearch

https://www.esri.com/etc.clientlibs/esri-sites/components/core/emb…/experience-builder/clientlibs.js

js esri.com collected 2026-09-24 06:52:12 UTC 4,747 bytes, 122 lines download raw bytes

1/**
2 * @file experience-builder.js
3 * @component Experience Builder Embed
4 *
5 * @description
6 * Initializes the Experience Builder embedded iFrame and synchronizes its
7 * language code with the current page's locale. On DOMContentLoaded, the
8 * routine locates the embed wrapper, extracts the iFrame src, and checks
9 * whether the authored src contains a recognized lang-code path segment.
10 * If it does, the page URL is checked for a matching lang-code segment and
11 * the iFrame src is rewritten to match. If the src has no lang-code segment,
12 * no changes are made.
13 *
14 * @routine DOMContentLoaded
15 *
16 * @variables
17 * @var {Element} xprBuilder       - DOM element matching '.experience-builder'. Entry point for
18 *                                   all subsequent queries within this component instance.
19 * @var {string|undefined} mapSrc  - The raw src attribute value from the iFrame inside xprBuilder.
20 *                                   Undefined if no matching iframe[src] is found.
21 * @var {Set<string>} validLangCodes - Allowlist of supported BCP-47 locale strings used to
22 *                                   identify lang segments within URL paths.
23 * @var {Function} escapeRegExp    - Escapes special regex characters in a string so it can be
24 *                                   safely used inside a RegExp constructor.
25 * @var {Function} replaceSrcLangCode - Replaces the first matching lang-code path segment in a
26 *                                   src URL, preserving surrounding slashes and query strings.
27 * @var {string|undefined} srcLangCode  - Language code found in the iFrame src path (e.g. 'fr-fr').
28 *                                   Undefined if no lang segment is present; triggers early return.
29 * @var {string|undefined} pageLangCode - Language code found in the current page URL.
30 *                                   When present, used to rewrite the iFrame src.
31 * @var {Element}  iframe          - The iframe[src] element re-queried from xprBuilder when a
32 *                                   lang code swap is needed; avoids stale reference from mapSrc.
33 * @var {string}   newSrc          - Rewritten src value after substituting srcLangCode → pageLangCode.
34 *
35 * @logic
36 * 1. Query '.experience-builder'; bail early if not present on the page.
37 * 2. Read the iFrame src via optional chaining; bail early if no src found.
38 * 3. Scan the src path segments against validLangCodes to identify the embedded locale.
39 *    If no lang segment is found in the src, bail early — nothing to update.
40 * 4. Set a 'lang' attribute on xprBuilder for accessibility and downstream targeting.
41 * 5. Extract the page locale from window.location.href using the same validLangCodes set.
42 * 6. When pageLangCode is resolved, rewrite the iFrame src using replaceSrcLangCode —
43 *    a regex that matches the lang segment bounded by slashes, '?', or '#' to avoid
44 *    false matches on similar substrings elsewhere in the URL. Update 'lang' attribute
45 *    to reflect the new locale.
46 */
47document.addEventListener('DOMContentLoaded', () => {
48  const xprBuilder = document.querySelector('.experience-builder');
49  if (!xprBuilder) {
50    return;
51  }
52
53  const mapSrc = xprBuilder.querySelector('iframe[src]')?.getAttribute('src');
54  if (!mapSrc) {
55    return;
56  }
57
58  const validLangCodes = new Set([
59    'en',
60    'en-us',
61    'ar-sa',
62    'zh-cn',
63    'fr-fr',
64    'de-de',
65    'it-it',
66    'ja-jp',
67    'ko-kr',
68    'pl-pl',
69    'pt-br',
70    'ru-ru',
71    'es-es',
72    'nl-nl',
73    'he-il',
74    'id-id',
75    'sv-se',
76    'bs-ba',
77    'ca-es',
78    'cs-cz',
79    'da-dk',
80    'fi-fi',
81    'hu-hu',
82    'nb-no',
83    'el-gr',
84    'et-ee',
85    'hr-hr',
86    'lt-lt',
87    'lv-lv',
88    'pt-pt',
89    'ro-ro',
90    'sl-sl',
91    'sr-rs',
92    'th-th',
93    'tr-tr',
94    'vi-vn',
95    'zh-hk',
96    'zh-tw',
97    'uk-ua',
98  ]);
99  const escapeRegExp = value => value.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
100  const replaceSrcLangCode = (src, currentLangCode, newLangCode) => {
101    const langCodePattern = new RegExp(`(^|/)${escapeRegExp(currentLangCode)}(?=$|[/?#])`, 'i');
102
103    return src.replace(langCodePattern, `$1${newLangCode}`);
104  };
105
106  const srcLangCode = mapSrc.split('/').find(part => validLangCodes.has(part.toLowerCase()));
107  if (!srcLangCode) {
108    return;
109  }
110
111  xprBuilder.setAttribute('lang', srcLangCode);
112
113  const pageLangCode = globalThis.location.href.split('/').find(part => validLangCodes.has(part.toLowerCase()));
114  if (pageLangCode) {
115    const iframe = xprBuilder.querySelector('iframe[src]');
116    if (iframe) {
117      const newSrc = replaceSrcLangCode(iframe.getAttribute('src'), srcLangCode, pageLangCode);
118      iframe.setAttribute('src', newSrc);
119      xprBuilder.setAttribute('lang', pageLangCode);
120    }
121  }
122});

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.