PageSourceSearch

https://gopdailybrief.com/app/themes/patriotjournal/js/script.js?ver=1.0.13

js gopdailybrief.com collected 2026-10-04 21:24:01 UTC 19,481 bytes, 603 lines download raw bytes

1// Session manager with inactivity timeout (30 minutes)
2(function(){
3    try {
4        var INACTIVITY_MS = 30 * 60 * 1000; 
5        var now = Date.now();
6        var ls = window.localStorage;
7
8        var lastActive = Number(ls.getItem('pj_last_active_ts') || 0);
9        var startTs = Number(ls.getItem('pj_session_start_ts') || 0);
10        var sessionId = ls.getItem('pj_session_id');
11
12        var needNewSession = !startTs || (lastActive && (now - lastActive > INACTIVITY_MS));
13        if (needNewSession) {
14            startTs = now;
15            sessionId = (Math.random().toString(36).slice(2) + now.toString(36));
16            ls.setItem('pj_session_start_ts', String(startTs));
17            ls.setItem('pj_session_id', sessionId);
18        }
19
20        ls.setItem('pj_last_active_ts', String(now));
21
22        var lastPing = 0;
23        function pingActive() {
24            var t = Date.now();
25            if (t - lastPing > 30000) { 
26                ls.setItem('pj_last_active_ts', String(t));
27                lastPing = t;
28            }
29        }
30
31        ['click', 'scroll', 'keydown', 'mousemove', 'touchstart', 'visibilitychange'].forEach(function (evt) {
32            window.addEventListener(evt, pingActive, { passive: true });
33        });
34    } catch (e) {}
35})();
36
37// Mark browser session start for cross-tab article count (session cookie, cleared on browser close)
38(function() {
39    try {
40        if (!document.cookie.match(/(?:^|;\s*)pj_session_start=/)) {
41            document.cookie = 'pj_session_start=' + Date.now() + '; path=/; SameSite=Lax';
42        }
43    } catch (e) {}
44})();
45
46// email unput suggestions
47(function(){
48  "use strict";
49
50  // Shared constants for US-popular domains and TLDs
51  var EMAIL_DOMAINS_US = [
52    "gmail.com","yahoo.com","ymail.com","rocketmail.com",
53    "outlook.com","hotmail.com","live.com","msn.com",
54    "icloud.com","me.com","mac.com","aol.com",
55    "comcast.net","verizon.net","att.net","sbcglobal.net",
56    "bellsouth.net","cox.net","charter.net","spectrum.net",
57    "optonline.net","earthlink.net"
58  ];
59  var EMAIL_TLDS_US = ["com","net","org","us","edu","gov","mil"];
60
61  function createHint(container) {
62    var hint = document.createElement("div");
63    hint.className = "email-suggest-hint";
64    hint.style.marginTop = "6px";
65    hint.style.fontSize = "16px";
66    hint.style.display = "none";
67    hint.style.background = "#FEE2E2";          // light red background
68    hint.style.borderRadius = "6px";
69    hint.style.padding = "8px 10px";
70    hint.style.color = "#7F1D1D";               // dark red text
71    hint.style.display = "none";
72    hint.style.alignItems = "center";
73    hint.style.gap = "8px";
74    hint.setAttribute('role', 'alert');
75    hint.setAttribute('aria-live', 'polite');
76
77    // Danger icon
78    var icon = document.createElement("span");
79    icon.setAttribute('aria-hidden', 'true');
80    icon.style.display = "inline-flex";
81    icon.style.verticalAlign = "sub";
82    icon.style.width = "18px";
83    icon.style.height = "18px";
84    icon.style.marginRight = "8px";
85    icon.innerHTML = '<svg width="18" height="18" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M10.29 3.859l-8.4 14.4A2 2 0 003.2 21h17.6a2 2 0 001.71-2.741l-8.4-14.4a2 2 0 00-3.42 0z" fill="#FCA5A5"/><path d="M12 9v4M12 17h.01" stroke="#DC2626" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
86
87    var label = document.createElement("span");
88    label.textContent = "Did you mean: ";
89    label.style.fontWeight = "600";
90
91    var link = document.createElement("a");
92    link.href = "";
93    link.style.textDecoration = "none";
94    link.style.fontWeight = "700";
95    link.style.cursor = "pointer";
96    link.style.color = "#7C2D12";
97
98    hint.appendChild(icon);
99    hint.appendChild(label);
100    hint.appendChild(link);
101    container.appendChild(hint);
102
103    return { box: hint, link: link };
104  }
105
106  function attach(input) {
107    if (!input || input.__mcBound) return;
108    input.__mcBound = true;
109
110    var wrap = input.closest(".ginput_container, .gfield, .form-field") || input.parentNode;
111    var hint = createHint(wrap);
112    var last = null;
113    var blockedOnce = false;
114
115    function run() {
116      var raw = (input.value || "");
117      var normalized = raw.replace(/\s+/g, '').replace(/@{2,}/g, '@').trim();
118      var val = normalized;
119      if (!val || val.indexOf("@") < 1) {
120        hint.box.style.display = "none";
121        last = null;
122        return;
123      }
124      if (!window.Mailcheck) return;
125
126
127      if (normalized !== raw.trim()) {
128        var parts = val.split("@");
129        if (parts.length === 2) {
130          var dom = parts[1];
131          if (dom.indexOf('.') !== -1 || EMAIL_DOMAINS_US.indexOf(dom) !== -1) {
132            last = val;
133            hint.link.textContent = last + "?";
134            hint.box.style.display = "block";
135            return; 
136          }
137        }
138      }
139
140      Mailcheck.run({
141        email: val,
142        domains: EMAIL_DOMAINS_US,
143        topLevelDomains: EMAIL_TLDS_US,
144        suggested: function (s) {
145          if (!s || !s.domain || s.domain.indexOf('.') === -1) {
146            last = null;
147            hint.box.style.display = "none";
148            return;
149          }
150          last = s.full;
151          hint.link.textContent = last + "?";
152          hint.box.style.display = "block";
153        },
154        empty: function () {
155          if (normalized !== raw.trim()) {
156            var parts = val.split("@");
157            if (parts.length === 2) {
158              var dom = parts[1];
159              if (dom.indexOf('.') !== -1) {
160                last = val;
161                hint.link.textContent = last + "?";
162                hint.box.style.display = "block";
163                return;
164              }
165            }
166          }
167          last = null;
168          hint.box.style.display = "none";
169        }
170      });
171    }
172
173    input.addEventListener("input", run);
174    input.addEventListener("blur", run);
175
176    hint.link.addEventListener("click", function (e) {
177      e.preventDefault();
178      if (last) {
179        input.value = last;
180        hint.box.style.display = "none";
181        input.dispatchEvent(new Event("input", { bubbles: true }));
182      }
183    });
184
185    var form = input.form;
186    if (form) {
187      form.addEventListener("submit", function (e) {
188        if (last && input.value.trim() !== last && !blockedOnce) {
189          e.preventDefault();
190          blockedOnce = true;
191          hint.box.style.display = "block";
192          input.focus();
193        }
194      });
195    }
196  }
197
198  function init() {
199    var inputs = document.querySelectorAll("form[id^='gform_'] input#input_137_1[type='email'], form[id^='gform_'] input#input_163_1[type='email']");
200    for (var i = 0; i < inputs.length; i++) attach(inputs[i]);
201
202    var mo = new MutationObserver(function (list) {
203      list.forEach(function (m) {
204        for (var i = 0; i < m.addedNodes.length; i++) {
205          var n = m.addedNodes[i];
206          if (!(n instanceof Element)) continue;
207          var newInputs = n.matches && n.matches("input[type='email']")
208            ? [n]
209            : (n.querySelectorAll && n.querySelectorAll("input[type='email']")) || [];
210          for (var j = 0; j < newInputs.length; j++) attach(newInputs[j]);
211        }
212      });
213    });
214    mo.observe(document.documentElement || document.body, { childList: true, subtree: true });
215  }
216
217  function start() {
218    if (!window.Mailcheck) {
219      setTimeout(start, 50);
220      return;
221    }
222    if (document.readyState === "loading") {
223      document.addEventListener("DOMContentLoaded", init);
224    } else {
225      init();
226    }
227  }
228
229  start();
230})();
231
232// Move read-next-widget to sidebar if needed
233(function(){
234  "use strict";
235
236  function moveReadNextWidget() {
237    try {
238      var readNextWidget = document.querySelector('.read-next-widget');
239      if (!readNextWidget) {
240        return;
241      }
242
243      var location = readNextWidget.getAttribute('data-location') || 'default';
244      
245      if (location !== 'sidebar') {
246        return;
247      }
248
249      var sidebar = document.querySelector('.sidebar');
250      if (!sidebar) {
251        return;
252      }
253
254      // Create wrapper
255      var wrapper = document.createElement('div');
256      wrapper.className = 'widget';
257      wrapper.appendChild(readNextWidget.cloneNode(true));
258
259      // Find first widget in sidebar
260      var firstWidget = sidebar.querySelector('.widget');
261      
262      if (firstWidget) {
263        // Insert after first widget
264        firstWidget.parentNode.insertBefore(wrapper, firstWidget.nextSibling);
265      } else {
266        // Insert at beginning of sidebar
267        sidebar.insertBefore(wrapper, sidebar.firstChild);
268      }
269
270      // Remove original
271      readNextWidget.remove();
272    } catch (e) {
273      // Silent fail
274    }
275  }
276
277  if (document.readyState === 'loading') {
278    document.addEventListener('DOMContentLoaded', moveReadNextWidget);
279  } else {
280    moveReadNextWidget();
281  }
282})();
283
284// plan selection
285function selectPlanByIndex(idx) {
286  const fieldset = document.querySelector('#membership-widget fieldset.gfield--type-product.gfield--type-choice.gfield--input-type-radio');
287  const form = document.querySelector('#membership-widget form');
288  if (!fieldset || !form) return;
289  const radios = fieldset.querySelectorAll('input.gfield-choice-input[type="radio"]');
290  if (!radios.length || !radios[idx]) return;
291  const target = radios[idx];
292  if (!target.checked) {
293    target.checked = true;
294    target.dispatchEvent(new Event('change', { bubbles: true }));
295  }
296  
297  try {
298    const startTs = Number(localStorage.getItem('pj_session_start_ts') || sessionStorage.getItem('pj_session_start_ts') || Date.now());
299    const sec = Math.max(0, Math.round((Date.now() - startTs) / 1000));
300    const durationInput = form.querySelector('input[name="input_16"]');
301    if (durationInput) {
302      durationInput.value = String(sec);
303    }
304  } catch (e) {}
305  if (typeof form.requestSubmit === 'function') {
306    form.requestSubmit();
307  } else {
308    form.submit();
309  }
310}
311
312function setMembershipTracking() {
313    try {
314        const bannerRoot = document.querySelector('#membership-widget');
315        if (bannerRoot) {
316            const fromInput = bannerRoot.querySelector('input[name="input_14"]');
317            if (fromInput) {
318                fromInput.value = sessionStorage.getItem('pj_membership_from') || '';
319            }
320
321            const readsInput = bannerRoot.querySelector('input[name="input_15"]');
322            if (readsInput) {
323                let readCount = 0;
324                try {
325                    const raw = localStorage.getItem('pj_articles_read');
326                    const arr = JSON.parse(raw || '[]');
327                    readCount = Array.isArray(arr) ? arr.length : 0;
328                } catch (e) { readCount = 0; }
329                readsInput.value = String(readCount);
330            }
331        }
332
333        // Set current URL with parameters to hidden field
334        const urlInput = document.querySelector('.widget_membership_widget input[name="input_17"]');
335        if (urlInput) {
336            urlInput.value = window.location.href;
337        }
338
339        const membershipLinks = document.querySelectorAll('a[href*="/membership-plans"]');
340        if (membershipLinks.length) {
341            const deviceType = window.innerWidth < 980 ? 'mobile' : 'desktop';
342            membershipLinks.forEach((link) => {
343                let href = link.getAttribute('href');
344                if (!/utm_source=[^_]+_(mobile|desktop)/.test(href)) {
345                    href = href
346                        .replace('utm_source=sidebar', 'utm_source=sidebar_' + deviceType)
347                        .replace('utm_source=anchor', 'utm_source=anchor_' + deviceType)
348                        .replace('utm_source=demo', 'utm_source=demo_' + deviceType);
349                    link.setAttribute('href', href);
350                }
351            });
352        }
353    } catch (e) {}
354}
355
356// Donation & membership timing tracking for GA4 via GTM
357(function() {
358  'use strict';
359
360  if (typeof pj_forms === 'undefined') return;
361  var donationIds = pj_forms.donation || [];
362  var membershipIds = pj_forms.membership || [];
363  var allFormIds = donationIds.concat(membershipIds);
364  if (!allFormIds.length) return;
365
366  var PREFIX = 'pj_dt_';
367  var pageLoadTime = Date.now();
368  var intentFired = {};
369
370  function getArticlesAllTime() {
371    try {
372      var arr = JSON.parse(localStorage.getItem('pj_articles_read') || '[]');
373      return Array.isArray(arr) ? arr.length : 0;
374    } catch (e) { return 0; }
375  }
376
377  function getArticles7d() {
378    try {
379      var arr = JSON.parse(localStorage.getItem('pj_articles_read') || '[]');
380      var cutoff = Date.now() - 7 * 24 * 60 * 60 * 1000;
381      return Array.isArray(arr) ? arr.filter(function(r) { return r && r.ts > cutoff; }).length : 0;
382    } catch (e) { return 0; }
383  }
384
385  function getArticlesSession() {
386    try {
387      var m = document.cookie.match(/(?:^|;\s*)pj_session_start=([^;]*)/);
388      var sessionStart = m ? (parseInt(m[1], 10) || Date.now()) : Date.now();
389      var maxWindow = 3 * 60 * 60 * 1000;
390      var effectiveStart = Math.max(sessionStart, Date.now() - maxWindow);
391      var arr = JSON.parse(localStorage.getItem('pj_articles_read') || '[]');
392      return Array.isArray(arr) ? arr.filter(function(r) { return r && r.ts > effectiveStart; }).length : 0;
393    } catch (e) { return 0; }
394  }
395
396  var THANK_YOU_PATHS = [
397    '/contribution-make-it-monthly',
398    '/contribution-increase-to-5',
399    '/contribution-thank-you-membership'
400  ];
401
402
403  function trackIntent(formId) {
404    if (intentFired[formId]) return;
405    intentFired[formId] = true;
406
407    var form = document.getElementById('gform_' + formId);
408    if (!form) return;
409
410    var timeToIntent = Math.round((Date.now() - pageLoadTime) / 1000);
411
412    var widgetType = '';
413    var sourceField = form.querySelector('input[name="input_13"]');
414    if (sourceField) widgetType = sourceField.value;
415
416    var amount = 0;
417    var totalField = form.querySelector('input[name="input_5"]');
418    if (totalField) amount = parseFloat(totalField.value.replace(/[^0-9.]/g, '')) || 0;
419
420    var frequency = '';
421    var freqRadios = form.querySelectorAll('input[name="input_7"]');
422    for (var i = 0; i < freqRadios.length; i++) {
423      if (freqRadios[i].checked) { frequency = freqRadios[i].value; break; }
424    }
425
426    try {
427      localStorage.setItem(PREFIX + 'ts', String(Date.now()));
428      localStorage.setItem(PREFIX + 'widget', widgetType);
429    } catch (e) {}
430
431    window.dataLayer = window.dataLayer || [];
432    window.dataLayer.push({
433      event: 'donation_intent',
434      time_to_intent: timeToIntent,
435      widget_type: widgetType,
436      donation_amount: amount,
437      donation_frequency: frequency,
438      articles_all_time: getArticlesAllTime(),
439      articles_7d: getArticles7d(),
440      articles_session: getArticlesSession()
441    });
442  }
443
444  function trackCompletion() {
445    var ts;
446    try { ts = localStorage.getItem(PREFIX + 'ts'); } catch (e) { return; }
447    if (!ts) return;
448
449    var age = Date.now() - parseInt(ts, 10);
450    if (age > 30 * 60 * 1000) { clearData(); return; }
451
452    window.dataLayer = window.dataLayer || [];
453    window.dataLayer.push({
454      event: 'donation_complete',
455      time_to_complete: Math.round(age / 1000),
456      widget_type: localStorage.getItem(PREFIX + 'widget') || '',
457    });
458
459    clearData();
460  }
461
462  function clearData() {
463    ['ts', 'widget'].forEach(function(k) {
464      try { localStorage.removeItem(PREFIX + k); } catch (e) {}
465    });
466  }
467
468  function hasConfirmationMessage() {
469    for (var i = 0; i < allFormIds.length; i++) {
470      if (document.getElementById('gform_confirmation_message_' + allFormIds[i])) return true;
471    }
472    return false;
473  }
474
475  function isCompletionPage() {
476    var path = window.location.pathname.replace(/\/+$/, '');
477    for (var i = 0; i < THANK_YOU_PATHS.length; i++) {
478      if (path === THANK_YOU_PATHS[i]) return true;
479    }
480    return hasConfirmationMessage();
481  }
482
483  document.addEventListener('gform/theme/scripts_loaded', function() {
484    gform.utils.addAsyncFilter('gform/submission/pre_submission', async function(data) {
485      if (data.submissionType !== gform.submission.SUBMISSION_TYPE_SUBMIT) return data;
486      var formId = parseInt(data.form.dataset.formid, 10);
487      if (allFormIds.indexOf(formId) !== -1) {
488        trackIntent(formId);
489      }
490      return data;
491    });
492  });
493
494  // Capture-phase click — backup for popup forms where GF never actually submits
495  document.addEventListener('click', function(e) {
496    var btn = e.target.closest('[id^="gform_submit_button_"]');
497    if (!btn) return;
498    var match = btn.id.match(/gform_submit_button_(\d+)/);
499    if (!match) return;
500    var formId = parseInt(match[1], 10);
501    if (allFormIds.indexOf(formId) === -1) return;
502    setTimeout(function() { trackIntent(formId); }, 0);
503  }, true);
504
505  function init() {
506    if (isCompletionPage()) {
507      trackCompletion();
508      return;
509    }
510
511    // Watch for dynamically appearing GF confirmation messages (e.g. membership)
512    try {
513      if (localStorage.getItem(PREFIX + 'ts')) {
514        var obs = new MutationObserver(function() {
515          if (hasConfirmationMessage()) {
516            trackCompletion();
517            obs.disconnect();
518          }
519        });
520        obs.observe(document.body || document.documentElement, { childList: true, subtree: true });
521      }
522    } catch (e) {}
523  }
524
525  if (document.readyState === 'loading') {
526    document.addEventListener('DOMContentLoaded', init);
527  } else {
528    init();
529  }
530})();
531
532// AB Testing variant selector
533(function(){
534  "use strict";
535
536  function selectVariantForBlock(variantsList) {
537    var variants = variantsList.querySelectorAll('.pj-ab-variant');
538    if (!variants || variants.length === 0) {
539      return;
540    }
541
542    // Collect variants with their percentages
543    var variantData = [];
544    var totalPercentage = 0;
545
546    for (var i = 0; i < variants.length; i++) {
547      var percentage = parseFloat(variants[i].getAttribute('data-variant-percentage')) || 0;
548      if (percentage > 0) {
549        variantData.push({
550          element: variants[i],
551          percentage: percentage
552        });
553        totalPercentage += percentage;
554      }
555    }
556
557    if (variantData.length === 0 || totalPercentage === 0) {
558      // If no valid percentages, show first variant
559      if (variants.length > 0) {
560        variants[0].classList.add('current');
561      }
562      return;
563    }
564
565    // Generate random number between 0 and total percentage
566    var random = Math.random() * totalPercentage;
567    var cumulative = 0;
568
569    // Select variant based on weighted probability
570    for (var j = 0; j < variantData.length; j++) {
571      cumulative += variantData[j].percentage;
572      if (random <= cumulative) {
573        variantData[j].element.classList.add('current');
574        return;
575      }
576    }
577
578    // Fallback: show last variant if something went wrong
579    variantData[variantData.length - 1].element.classList.add('current');
580  }
581
582  function selectABVariants() {
583    try {
584      var variantsLists = document.querySelectorAll('.pj-ab-variants-list');
585      if (!variantsLists || variantsLists.length === 0) {
586        return;
587      }
588
589      // Process each variants list independently
590      for (var i = 0; i < variantsLists.length; i++) {
591        selectVariantForBlock(variantsLists[i]);
592      }
593    } catch (e) {
594      // Silent fail
595    }
596  }
597
598  if (document.readyState === 'loading') {
599    document.addEventListener('DOMContentLoaded', selectABVariants);
600  } else {
601    selectABVariants();
602  }
603})();

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.