1/** FOXIZ_CORE_SCRIPT */ 2 3/** Ensure RB_VIEWPORT_OBSERVER is available */ 4if (typeof RB_VIEWPORT_OBSERVER === 'undefined') { 5 var RB_VIEWPORT_OBSERVER = { 6 observe: function () { 7 return null; 8 }, 9 unobserve: function () {}, 10 destroy: function () {}, 11 refreshAll: function () {}, 12 has: function () { 13 return false; 14 }, 15 getActiveIds: function () { 16 return []; 17 }, 18 destroyAll: function () {}, 19 }; 20} 21 22var FOXIZ_CORE_SCRIPT = (function (Module, $) { 23 'use strict'; 24 25 Module.init = function () { 26 this.yesStorage = this.isStorageAvailable(); 27 this._body = $('body'); 28 this.themeSettings = foxizCoreParams || {}; 29 this.darkModeID = this.themeSettings.darkModeID || 'RubyDarkMode'; 30 this.mSiteID = this.themeSettings.mSiteID || null; 31 this.isCMode = document.body.classList.contains('is-cmode'); 32 this.personalizeUID = this.getUserUUID(); 33 this.initDarkModeCookie(); 34 this.switchDarkMode(); 35 this.noteToggle(); 36 this.passwordToggle(); 37 this.emailToDownload(); 38 }; 39 40 /** 41 * generate UUID 42 * @returns {string} 43 */ 44 Module.generateUUID = function () { 45 const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789'; 46 let id = ''; 47 for (let i = 0; i < 7; i++) { 48 const randomIndex = Math.floor(Math.random() * alphabet.length); 49 id += alphabet[randomIndex]; 50 } 51 return id; 52 }; 53 54 /** 55 * set cookies 56 * @param name 57 * @param value 58 * @param days 59 */ 60 Module.setCookie = function (name, value, days = 60) { 61 const date = new Date(); 62 date.setTime(date.getTime() + Math.round(days * 24 * 60 * 60 * 1000)); 63 64 const expires = '; expires=' + date.toUTCString(); 65 const cookieDomain = this.themeSettings.cookieDomain || ''; 66 const cookiePath = this.themeSettings.cookiePath || '/'; 67 68 document.cookie = 69 name + '=' + encodeURIComponent(value) + expires + '; path=' + cookiePath + '; domain=' + cookieDomain; 70 }; 71 72 /** 73 * get cookie 74 * @param name 75 * @returns {string|null} 76 */ 77 Module.getCookie = function (name) { 78 const nameEQ = name + '='; 79 const cookies = document.cookie.split(';'); 80 for (let i = 0; i < cookies.length; i++) { 81 let cookie = cookies[i]; 82 while (cookie.charAt(0) == ' ') cookie = cookie.substring(1, cookie.length); 83 if (cookie.indexOf(nameEQ) == 0) return decodeURIComponent(cookie.substring(nameEQ.length, cookie.length)); 84 } 85 return null; 86 }; 87 88 /** 89 * delete cookies 90 * @param name 91 */ 92 Module.deleteCookie = function (name) { 93 const cookieDomain = this.themeSettings.cookieDomain || ''; 94 const cookiePath = this.themeSettings.cookiePath || '/'; 95 document.cookie = 96 name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=' + cookiePath + '; domain=' + cookieDomain; 97 }; 98 99 /** 100 * 101 * @returns {boolean} 102 */ 103 Module.isStorageAvailable = function () { 104 let storage; 105 try { 106 storage = window['localStorage']; 107 storage.setItem('__rbStorageSet', 'x'); 108 storage.removeItem('__rbStorageSet'); 109 return true; 110 } catch (e) { 111 return false; 112 } 113 }; 114 115 /** 116 * set localStorage 117 * @param key 118 * @param data 119 */ 120 Module.setStorage = function (key, data) { 121 this.yesStorage && localStorage.setItem(key, typeof data === 'string' ? data : JSON.stringify(data)); 122 }; 123 124 /** 125 * get localStorage 126 * @param key 127 * @param defaultValue 128 * @returns {any} 129 */ 130 Module.getStorage = function (key, defaultValue) { 131 if (!this.yesStorage) return null; 132 const data = localStorage.getItem(key); 133 if (data === null) return defaultValue; 134 try { 135 return JSON.parse(data); 136 } catch (e) { 137 return data; 138 } 139 }; 140 141 /** 142 * delete localStorage 143 * @param key 144 */ 145 Module.deleteStorage = function (key) { 146 this.yesStorage && localStorage.removeItem(key); 147 }; 148 149 /** 150 * create UUID 151 * @returns {string|*} 152 */ 153 Module.getUserUUID = function () { 154 let uuid; 155 if (this.getCookie('RBUUID')) { 156 uuid = this.getCookie('RBUUID'); 157 } else {
158 uuid = this.getStorage('RBUUID', null); 159 if (null === uuid) { 160 uuid = this.generateUUID(); 161 this.setStorage('RBUUID', uuid); 162 this.themeSettings.yesPersonalized && this.setCookie('personalize_sync', 'yes', 1); 163 } 164 this.themeSettings.yesPersonalized && this.setCookie('RBUUID', uuid); 165 } 166 167 if (this.mSiteID) { 168 uuid = this.mSiteID + uuid; 169 } 170 171 return uuid; 172 }; 173 174 Module.initDarkModeCookie = function () { 175 if (this.isCMode && !this.getCookie(this.darkModeID)) { 176 this.setCookie(this.darkModeID, document.body.getAttribute('data-theme')); 177 } 178 }; 179 180 Module.setDarkModeCookie = function (name, value) { 181 if (this.isCMode) { 182 this.setCookie(name, value); 183 } 184 }; 185 186 Module.switchDarkMode = function () { 187 const self = this; 188 const toggleSelector = '.dark-mode-toggle'; 189 const iconDefault = $('.mode-icon-default'); 190 const iconDark = $('.mode-icon-dark'); 191 192 $(toggleSelector) 193 .off('click') 194 .on('click', function (e) { 195 e.preventDefault(); 196 e.stopPropagation(); 197 198 const target = $(this); 199 if (!target.hasClass('triggered')) { 200 target.addClass('triggered'); 201 } 202 203 const useStorage = !self.isCMode && self.yesStorage; 204 const currentMode = useStorage 205 ? self.getStorage(self.darkModeID) 206 : document.body.getAttribute('data-theme'); 207 208 const isDark = currentMode === 'dark'; 209 const nextMode = isDark ? 'default' : 'dark'; 210 211 if (useStorage) { 212 self.setStorage(self.darkModeID, nextMode); 213 } 214 self.setDarkModeCookie(self.darkModeID, nextMode); 215 self._body.attr('data-theme', nextMode).addClass('switch-smooth'); 216 217 iconDefault.toggleClass('activated', nextMode === 'default'); 218 iconDark.toggleClass('activated', nextMode === 'dark'); 219 }); 220 }; 221 222 /** share action */ 223 Module.shareTrigger = function () { 224 $('a.share-trigger') 225 .off('click') 226 .on('click', function (e) { 227 e.preventDefault(); 228 e.stopPropagation(); 229 window.open($(this).attr('href'), '_blank', 'width=600, height=350'); 230 return false; 231 }); 232 233 const copyButton = $('a.copy-trigger'); 234 if (navigator.clipboard) { 235 copyButton.off('click').on('click', function (e) { 236 e.preventDefault(); 237 e.stopPropagation(); 238 const target = $(this); 239 const link = target.data('link'); 240 const copied = target.data('copied'); 241 if (link) { 242 navigator.clipboard 243 .writeText(link) 244 .then(function () { 245 $('body').find('.tipsy-inner').html(copied); 246 }) 247 .catch(function () {}); 248 } 249 }); 250 } else { 251 copyButton.hide(); 252 } 253 254 const shareButton = $('a.native-share-trigger'); 255 if (navigator.share) { 256 shareButton.on('click', function (e) { 257 e.preventDefault(); 258 e.stopPropagation(); 259 260 const target = $(this); 261 const link = target.data('link'); 262 const title = target.data('ptitle'); 263 navigator.share({ 264 title: title, 265 url: link, 266 }); 267 }); 268 } else { 269 shareButton.hide(); 270 } 271 }; 272 273 /** single infinite load */ 274 Module.loadGoogleAds = function (response) { 275 const googleAds = $(response).find('.adsbygoogle'); 276 if (typeof window.adsbygoogle !== 'undefined' && googleAds.length) { 277 var adsbygoogle; 278 googleAds.each(function () { 279 (adsbygoogle = window.adsbygoogle || []).push({}); 280 }); 281 } 282 }; 283 284 Module.loadInstagram = function (response) { 285 let instEmbed = $(response).find('.instagram-media'); 286 if ('undefined' !== typeof window.instgrm) { 287 window.instgrm.Embeds.process(); 288 } else if (instEmbed.length && 'undefined' === typeof window.instgrm) { 289 const embedJS = document.createElement('script'); 290 embedJS.src = '//platform.instagram.com/en_US/embeds.js'; 291 embedJS.onload = function () { 292 window.instgrm.Embeds.process(); 293 }; 294 this._body.append(embedJS); 295 } 296 }; 297 298 Module.loadTwttr = function () { 299 // X (formerly Twitter) widgets - modern API 300 if (typeof twttr !== 'undefined' && typeof twttr.widgets !== 'undefined') { 301 twttr.ready(function (twttr) { 302 twttr.widgets.load(); 303 }); 304 } 305 }; 306 307 Module.loadTikTok = function (response) { 308 // TikTok embeds 309 const tiktokEmbeds = $(response).find('.tiktok-embed'); 310 if (tiktokEmbeds.length && typeof window.tiktokEmbed !== 'undefined') { 311 window.tiktokEmbed.lib.render(tiktokEmbeds); 312 } 313 }; 314 315 Module.loadThreads = function (response) { 316 // Meta Threads embeds 317 if (typeof window.ThreadsEmbeds !== 'undefined') { 318 window.ThreadsEmbeds.process(); 319 } 320 }; 321 322 Module.loadBluesky = function (response) { 323 // Bluesky embeds 324 const bskyEmbeds = $(response).find('[data-bluesky-embed]'); 325 if (bskyEmbeds.length && typeof window.blueskyEmbed !== 'undefined') { 326 window.blueskyEmbed.render(); 327 } 328 }; 329 330 Module.updateGA = function (article) { 331 const gaURL = article.postURL.replace(/https?:\/\/[^\/]+/i, ''); 332 333 // GA4 (gtag.js) - Primary Google Analytics 334 if (typeof gtag === 'function') { 335 gtag('event', 'page_view', { 336 page_path: gaURL, 337 page_title: article.postTitle, 338 page_location: article.postURL, 339 }); 340 } 341 342 // GA Universal Analytics (analytics.js) - Legacy 343 if (typeof ga === 'function') { 344 ga('send', 'pageview', gaURL); 345 } 346 347 // GA Classic (_gaq) - Very Legacy 348 if (typeof _gaq !== 'undefined' && _gaq !== null) {
349 _gaq.push(['_trackPageview', gaURL]); 350 } 351 352 // MonsterInsights / WordPress GA plugins 353 if (typeof __gaTracker === 'function') { 354 __gaTracker('send', 'pageview', gaURL); 355 } 356 357 // Google Publisher Tag (GPT) - Refresh ads 358 if (window.googletag && googletag.pubadsReady) { 359 googletag.pubads().refresh(); 360 } 361 362 // Meta Pixel (Facebook/Instagram) 363 if (typeof fbq === 'function') { 364 fbq('track', 'PageView'); 365 } 366 367 // X (Twitter) Pixel 368 if (typeof twq === 'function') { 369 twq('track', 'PageView'); 370 } 371 372 // TikTok Pixel 373 if (typeof ttq !== 'undefined' && typeof ttq.track === 'function') { 374 ttq.track('ViewContent', { 375 content_name: article.postTitle, 376 content_id: article.postID, 377 }); 378 } 379 380 // Pinterest Tag 381 if (typeof pintrk === 'function') { 382 pintrk('track', 'pagevisit'); 383 } 384 385 // LinkedIn Insight Tag 386 if (typeof lintrk === 'function') { 387 lintrk('track'); 388 } 389 390 // Microsoft/Bing UET 391 if (typeof uetq !== 'undefined') { 392 uetq.push('event', 'page_view', { 393 page_path: gaURL, 394 }); 395 } 396 397 // Reddit Pixel 398 if (typeof rdt === 'function') { 399 rdt('track', 'PageVisit'); 400 } 401 402 // Snapchat Pixel 403 if (typeof snaptr === 'function') { 404 snaptr('track', 'PAGE_VIEW'); 405 } 406 407 // Plausible Analytics 408 if (typeof plausible === 'function') { 409 plausible('pageview', { u: article.postURL }); 410 } 411 }; 412 413 Module.noteToggle = function () { 414 $('.yes-toggle > .note-header').on('click', function () { 415 let wrapper = $(this).parent(); 416 let timing = wrapper.hasClass('is-inline') ? 0 : 300; 417 418 wrapper.toggleClass('explain'); 419 wrapper.find('.note-content').slideToggle(timing); 420 }); 421 }; 422 423 Module.passwordToggle = function () { 424 $('.rb-password-toggle').on('click', function () { 425 const $this = $(this); 426 const $input = $this.prev('input'); 427 const $icon = $this.find('i'); 428 429 if ($input.attr('type') === 'password') { 430 $input.attr('type', 'text'); 431 $icon.removeClass('rbi-show').addClass('rbi-hide'); 432 } else { 433 $input.attr('type', 'password'); 434 $icon.removeClass('rbi-hide').addClass('rbi-show'); 435 } 436 }); 437 }; 438 439 Module.isValidEmail = function (email) { 440 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 441 return emailRegex.test(email); 442 }; 443 444 Module.emailToDownload = function () { 445 const self = this; 446 447 $('.download-form').each(function () { 448 const form = $(this); 449 const acceptTermsCheckbox = form.find('input[name="acceptTerms"]'); 450 const submitButton = form.find('input[type="submit"]'); 451 const noticeText = form.find('.notice-text'); 452 453 if (acceptTermsCheckbox.length > 0) { 454 acceptTermsCheckbox.change(function () { 455 submitButton.prop('disabled', !this.checked); 456 }); 457 } 458 459 form.submit(function (event) { 460 event.preventDefault(); 461 462 const emailInput = form.find('input[name="EMAIL"]'); 463 const email = emailInput.val(); 464 const label = form.find('input[type="submit"]').val(); 465 noticeText.empty(); 466 467 if (!self.isValidEmail(email)) { 468 const errorNotice = 'Please enter a valid email address.'; 469 noticeText.text(errorNotice); 470 return; 471 } 472 473 const wrapper = form.parents('.gb-download'); 474 wrapper.addClass('submitting'); 475 476 $.ajax({ 477 url: self.themeSettings.ajaxurl || null, 478 method: 'POST', 479 data: form.serialize(), 480 success: function (response) { 481 const fileURL = response.file; 482 if (fileURL) { 483 const link = document.createElement('a'); 484 link.href = fileURL; 485 link.setAttribute('download', ''); 486 link.click(); 487 const newContent = `<div class="fallback-info">${response.message}</div><a href="${response.file}" download="" rel="nofollow" class="is-btn gb-download-btn fallback-download-btn">${label}</a>`; 488 form.replaceWith(newContent); 489 } else { 490 noticeText.text(response.message); 491 } 492 wrapper.removeClass('submitting'); 493 }, 494 }); 495 }); 496 }); 497 }; 498 499 return Module; 500})(FOXIZ_CORE_SCRIPT || {}, jQuery); 501 502jQuery(document).ready(function () {
503 FOXIZ_CORE_SCRIPT.init(); 504}); 505 506jQuery(window).on('load', function () { 507 FOXIZ_CORE_SCRIPT.shareTrigger(); 508});
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.