PageSourceSearch

https://members.amcp.org/resource/1762538748000/amcpchampionselector?

js amcp.org collected 2026-09-24 17:47:34 UTC 14,692 bytes, 325 lines download raw bytes

1/*
2  Head-only: checkbox-triggered create with re-open support.
3  - Listens for field [data-field-name="I was referred"] change event.
4  - Idempotent: prevents duplicates but allows re-create when user closes and checks again.
5*/
6(function(){
7
8  function log(){ console.log.apply(console, [LOG_PREFIX].concat(Array.from(arguments))); }
9  function warn(){ console.warn.apply(console, [LOG_PREFIX].concat(Array.from(arguments))); }
10  function err(){ console.error.apply(console, [LOG_PREFIX].concat(Array.from(arguments))); }
11
12  // ==== VERSION MARKER (for debugging) ====
13  var HEAD_CHECKBOX_VERSION = "HeadCheckbox v2.1 – Yes/No support";
14  try {
15    log("Loaded script version:", HEAD_CHECKBOX_VERSION, "CHECK_SELECTOR =", (typeof CHECK_SELECTOR !== "undefined" ? CHECK_SELECTOR : "(undefined)"));
16  } catch(e) {
17    // if LOG_PREFIX or CHECK_SELECTOR blow up for some reason, fail silently
18    console.log("[HeadCheckbox] (fallback) Loaded script version:", HEAD_CHECKBOX_VERSION);
19  }
20  // ========================================
21
22  // Field-only guard (URL no longer required)
23  try {
24    if (!CHECK_SELECTOR) {
25      log("Field guard: no field name provided, skipping injection.");
26      return;
27    }
28    log("Field guard passed — monitoring field:", CHECK_SELECTOR);
29  } catch(e){
30    warn("Field guard check failed — skipping.", e);
31    return;
32  }
33
34  // global state for idempotency and lock
35  window.__HeadCreated = window.__HeadCreated || {};
36  window.__HeadCreating = window.__HeadCreating || {};
37
38  // spinner markup
39  var SPINNER_HTML = '<div id="' + SPINNER_ID + '" style="background-color:rgba(0,0,0,0.5); position:fixed; width:100vw; height:100vh; top:0; left:0; z-index:999998; display:flex; align-items:center; justify-content:center;">'
40    + '<div class="slds-spinner_container"><div class="slds-spinner slds-spinner_medium" role="status">'
41    + '<span class="slds-assistive-text">Loading</span><div class="slds-spinner__dot-a"></div><div class="slds-spinner__dot-b"></div>'
42    + '</div></div></div>';
43
44  function waitForBody(timeoutMs, intervalMs){
45    timeoutMs = typeof timeoutMs === 'number' ? timeoutMs : 5000;
46    intervalMs = typeof intervalMs === 'number' ? intervalMs : 50;
47    return new Promise(function(resolve, reject){
48      var start = Date.now();
49      (function poll(){
50        if (document.body) return resolve(document.body);
51        if (Date.now() - start > timeoutMs) return reject(new Error("document.body did not appear"));
52        setTimeout(poll, intervalMs);
53      })();
54    });
55  }
56  function showSpinner(){ return waitForBody(5000,50).then(function(body){ if (!document.getElementById(SPINNER_ID)) body.insertAdjacentHTML('beforeend', SPINNER_HTML); log("Spinner shown"); }).catch(function(e){ warn("Spinner insert failed:", e && e.message); }); }
57  function removeSpinner(){ try { var s = document.getElementById(SPINNER_ID); if (s && s.parentNode) s.parentNode.removeChild(s); log("Spinner removed"); } catch(e){ warn("removeSpinner error:", e); } }
58
59  function cleanupDuplicateTargets(){
60    try {
61      var all = Array.from(document.querySelectorAll('#' + TARGET_ID));
62      if (all.length <= 1) return;
63      log("cleanup: found " + all.length + " targets, removing extras");
64      for (var i = 1; i < all.length; i++) try { all[i].parentNode.removeChild(all[i]); } catch(e){}
65    } catch(e){ warn("cleanupDuplicateTargets error:", e); }
66  }
67
68  function ensureMount(){
69    cleanupDuplicateTargets();
70    var existing = document.getElementById(TARGET_ID);
71    if (existing) return existing;
72    function insert(){
73      if (!document.body) return false;
74      if (document.getElementById(TARGET_ID)) return document.getElementById(TARGET_ID);
75      var el = document.createElement('div');
76      el.id = TARGET_ID;
77      el.style.minHeight = "1px";
78      el.setAttribute('data-head-managed','true');
79      if (document.body.firstChild) document.body.insertBefore(el, document.body.firstChild);
80      else document.body.appendChild(el);
81      log("mount injected into body:", TARGET_ID);
82      return el;
83    }
84    if (document.readyState === 'interactive' || document.readyState === 'complete') return insert();
85    return new Promise(function(resolve){
86      document.addEventListener('DOMContentLoaded', function onDom(){ document.removeEventListener('DOMContentLoaded', onDom); resolve(insert()); });
87      var obs = new MutationObserver(function(){ if (document.body) { try{ obs.disconnect(); }catch(e){}; resolve(insert()); } });
88      obs.observe(document.documentElement, { childList:true, subtree:true });
89      setTimeout(function(){ try{ obs.disconnect(); }catch(e){}; resolve(insert()); }, 5000);
90    });
91  }
92
93  function observeAuraScripts(onFound){
94    try {
95      var found = false;
96      var observer = new MutationObserver(function(muts){
97        muts.forEach(function(m){
98          if (!m.addedNodes) return;
99          m.addedNodes.forEach(function(n){
100            if (n.tagName === 'SCRIPT') {
101              var src = n.src || '';
102              if (/aura|aura_prod|lightning\.out/i.test(src) || /aura|aura_prod/i.test(n.textContent || '')) {
103                if (!found) { found = true; try { observer.disconnect(); } catch(e){}; onFound(src || "(inline)"); }
104              }
105            }
106          });
107        });
108      });
109      observer.observe(document.head || document.documentElement, { childList: true, subtree: true });
110      var scripts = Array.from(document.getElementsByTagName('script'));
111      for (var i=0;i<scripts.length;i++){
112        var s = scripts[i];
113        if (/aura|aura_prod|lightning\.out/i.test(s.src || '') || /aura|aura_prod/i.test(s.textContent || '')) {
114          try { observer.disconnect(); } catch(e){}; onFound(s.src || "(inline)"); break;
115        }
116      }
117      return function cancel(){ try{ observer.disconnect(); }catch(e){}; };
118    } catch(e){ warn("observeAuraScripts error:", e); return function(){}; }
119  }
120
121  function targetHasAuraRenderedContent(){
122    var t = document.getElementById(TARGET_ID);
123    if (!t) return false;
124    if (t.children.length > 0) return true;
125    try { if (t.querySelector('[data-aura],[data-aura-rendered],[data-auraelement]')) return true; } catch(e){}
126    return false;
127  }
128
129  function resetForReopenIfNeeded(){
130    try {
131      var created = !!window.__HeadCreated[COMP_NAME];
132      var popupOpen = !!window.FONChampionPopupOpen;
133      var hasRendered = targetHasAuraRenderedContent();
134
135      if (created && !popupOpen) {
136        if (!hasRendered) {
137          log("Previously created but popup closed + no rendered content — resetting registry to allow reopen");
138          window.__HeadCreated[COMP_NAME] = false;
139          window.__HeadCreating[COMP_NAME] = false;
140          window.__HeadStarted = window.__HeadStarted || {};
141          window.__HeadStarted[COMP_NAME] = false;
142          var t = document.getElementById(TARGET_ID);
143          if (t) {
144            t.removeAttribute('data-head-created');
145            t.innerHTML = '';
146          }
147          return;
148        }
149
150        try {
151          log("Previously created but popup closed and target still has rendered content — cleaning target to allow fresh create");
152          var target = document.getElementById(TARGET_ID);
153          if (target) {
154            while (target.firstChild) {
155              try { target.removeChild(target.firstChild); } catch(e){ break; }
156            }
157            target.removeAttribute('data-head-created');
158            target.removeAttribute('data-head-managed');
159          }
160        } catch(e){ warn("Error while cleaning target for reopen:", e); }
161
162        window.__HeadCreated[COMP_NAME] = false;
163        window.__HeadCreating[COMP_NAME] = false;
164        window.__HeadStarted = window.__HeadStarted || {};
165        window.__HeadStarted[COMP_NAME] = false;
166      }
167    } catch(e){ warn("resetForReopenIfNeeded error:", e); }
168  }
169
170  function tryCreateOnce(attrs){
171    attrs = attrs || {};
172    return new Promise(function(resolve, reject){
173      try {
174        if (window.__HeadCreated[COMP_NAME]) return resolve(null);
175        if (targetHasAuraRenderedContent()) { window.__HeadCreated[COMP_NAME] = true; return resolve(null); }
176        if (window.__HeadCreating[COMP_NAME]) { log("Another creator running — skipping"); return resolve(null); }
177        window.__HeadCreating[COMP_NAME] = true;
178
179        if (!window.$Lightning || typeof window.$Lightning.createComponent !== 'function') {
180          window.__HeadCreating[COMP_NAME] = false;
181          return reject(new Error("$Lightning.createComponent not present"));
182        }
183
184        window.$Lightning.createComponent(COMP_NAME, attrs, TARGET_ID, function(cmp){
185          try {
186            window.__HeadCreated[COMP_NAME] = true;
187            var target = document.getElementById(TARGET_ID);
188            if (target) target.setAttribute('data-head-created', COMP_NAME);
189          } catch(e){}
190          window.__HeadCreating[COMP_NAME] = false;
191          resolve(cmp);
192        });
193
194      } catch(e){
195        try { window.__HeadCreating[COMP_NAME] = false; } catch(_){}
196        reject(e);
197      }
198    });
199  }
200
201  function tryCreateLoop(attrs, onSuccess, onFailure){
202    resetForReopenIfNeeded();
203
204    if (window.__HeadCreated[COMP_NAME]) { log("Already created - skipping"); removeSpinner(); if (onSuccess) onSuccess(null); return function(){}; }
205    if (targetHasAuraRenderedContent() || window.FONChampionPopupOpen) { window.__HeadCreated[COMP_NAME] = true; removeSpinner(); if (onSuccess) onSuccess(null); return function(){}; }
206
207    showSpinner();
208
209    var attempts = 0;
210    var cancelObserver = observeAuraScripts(function(){ log("Aura script observed"); });
211    var timer = setInterval(function(){
212      attempts++;
213      if (window.__HeadCreated[COMP_NAME] || targetHasAuraRenderedContent() || window.FONChampionPopupOpen) {
214        clearInterval(timer); try { cancelObserver(); } catch(e){}; removeSpinner(); if (onSuccess) onSuccess(null); return;
215      }
216
217      try {
218        log("Attempting createComponent (attempt " + attempts + "/" + MAX_CREATE_ATTEMPTS + ")");
219        tryCreateOnce(attrs).then(function(cmp){
220          if (!cmp) {
221            log("Create no-op (other creator handled it)."); window.__HeadCreated[COMP_NAME] = true; clearInterval(timer); try { cancelObserver(); } catch(e){}; removeSpinner(); if (onSuccess) onSuccess(null); return;
222          }
223          clearInterval(timer); try { cancelObserver(); } catch(e){}; removeSpinner(); log("SUCCESS: component created", cmp); window.__HeadCreated[COMP_NAME] = true; if (onSuccess) onSuccess(cmp);
224        }).catch(function(e){
225          warn("create attempt threw:", e && e.message ? e.message : e);
226          if (attempts >= MAX_CREATE_ATTEMPTS) { clearInterval(timer); try { cancelObserver(); } catch(e){}; removeSpinner(); if (onFailure) onFailure(e); }
227        });
228      } catch(eouter){
229        warn("outer error:", eouter);
230        if (attempts >= MAX_CREATE_ATTEMPTS) { clearInterval(timer); try { cancelObserver(); } catch(e){}; removeSpinner(); if (onFailure) onFailure(eouter); }
231      }
232    }, CREATE_RETRY_MS);
233
234    return function cancel(){ clearInterval(timer); try { cancelObserver(); } catch(e){}; };
235  }
236
237  function attachCheckboxWatcher() {
238    var cb = document.querySelector(CHECK_SELECTOR);
239    if (cb) { log("Field found in DOM."); attachOnce(cb); return; }
240
241    var found = false;
242    var obs = new MutationObserver(function(muts){
243      for (var i=0;i<muts.length;i++){
244        var m = muts[i];
245        if (!m.addedNodes) continue;
246        for (var j=0;j<m.addedNodes.length;j++){
247          var n = m.addedNodes[j];
248          if (n.nodeType !== 1) continue;
249          try {
250            if (n.matches && n.matches(CHECK_SELECTOR)) { found = true; obs.disconnect(); attachOnce(n); return; }
251            var desc = n.querySelector && n.querySelector(CHECK_SELECTOR);
252            if (desc) { found = true; obs.disconnect(); attachOnce(desc); return; }
253          } catch(e){}
254        }
255      }
256    });
257    obs.observe(document.documentElement || document, { childList:true, subtree:true });
258    setTimeout(function(){ try{ obs.disconnect(); }catch(e){}; if (!found) log("Field not found within timeout"); }, 30000);
259  }
260
261  // UPDATED for Yes/No support
262  function attachOnce(fieldEl) {
263    if (!fieldEl) return;
264    if (fieldEl.__headWatcherAttached) { log("Watcher already attached for", fieldEl.tagName, fieldEl.type); return; }
265    fieldEl.__headWatcherAttached = true;
266
267    function shouldTrigger(el) {
268      var tag = (el.tagName || '').toLowerCase();
269      var type = (el.type || '').toLowerCase();
270      var val = (el.value || '').toString().toLowerCase();
271
272      if (type === 'checkbox') {
273        log("Evaluating as checkbox. checked =", !!el.checked);
274        return !!el.checked;
275      }
276      log("Evaluating as non-checkbox. value =", val);
277      return (val === 'yes' || val === 'true' || val === '1');
278    }
279
280    fieldEl.addEventListener('change', function(ev){
281      try {
282        log("Field changed — tag:", fieldEl.tagName, "type:", fieldEl.type, "value:", fieldEl.value);
283        if (shouldTrigger(fieldEl)) {
284          resetForReopenIfNeeded();
285          triggerCreate();
286        } else {
287          log("Condition not met — no action.");
288        }
289      } catch(e){ warn("change handler error:", e); }
290    }, { once: false });
291
292    if (shouldTrigger(fieldEl)) {
293      resetForReopenIfNeeded();
294      triggerCreate();
295    }
296  }
297
298  window.__HeadStarted = window.__HeadStarted || {};
299
300  function triggerCreate() {
301    if (window.__HeadStarted[COMP_NAME]) { log("triggerCreate called but already started (global)"); return; }
302    window.__HeadStarted[COMP_NAME] = true;
303
304    var mountRes = ensureMount();
305    var p = (mountRes && typeof mountRes.then === 'function') ? mountRes : Promise.resolve(mountRes);
306    p.then(function(){ 
307      var attrs = { requiredParam: "", requiredValue: "", requiredUrlSubstring: "", substringCaseSensitive: false };
308      try {
309        var meta = document.querySelector('meta[name="recordId"],meta[name="sfdc-recordId"]');
310        if (meta && meta.content) attrs.recordId = meta.content;
311        else { var q = new URLSearchParams(window.location.search); attrs.recordId = q.get('id') || q.get('recordId') || null; }
312      } catch(e){}
313      log("Triggering create loop now with attrs:", attrs);
314      tryCreateLoop(attrs, function(cmp){
315        log("create loop done", cmp);
316      }, function(err){ err("create loop failed", err); });
317    }).catch(function(e){
318      err("ensureMount failed:", e);
319      window.__HeadStarted[COMP_NAME] = false;
320    });
321  }
322
323  try { attachCheckboxWatcher(); } catch(e){ warn("attachCheckboxWatcher error:", e); }
324
325})();

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.