1/* 2* Page Cache Ultimate, Page Cache standard and Speed pack are powered by Jpresta (jpresta . com) 3* 4* @author Jpresta 5* @copyright Jpresta 6* @license See the license of this module in file LICENSE.txt, thank you. 7*/ 8 9function jprestaPcGetParameterValue(e) { 10 let t = "[\\?&]" + e + "=([^&#]*)"; 11 let n = new RegExp(t); 12 let r = n.exec(window.location.href); 13 if (r == null) return ""; 14 else return r[1] 15} 16 17function jprestaPcSplitUri(uri) { 18 let splitRegExp = new RegExp('^' + '(?:' + '([^:/?#.]+)' + ':)?' + '(?://' + '(?:([^/?#]*)@)?' + '([\\w\\d\\-\\u0100-\\uffff.%]*)' + '(?:(:[0-9]+))?' + ')?' + '([^?#]+)?' + '(?:(\\?[^#]*))?' + '(?:(#.*))?' + '$'); 19 let split = uri.match(splitRegExp); 20 for (let i = 1; i < 8; i++) { 21 if (typeof split[i] === 'undefined') { 22 split[i] = ''; 23 } 24 } 25 return { 26 'scheme': split[1], 27 'user_info': split[2], 28 'domain': split[3], 29 'port': split[4], 30 'path': split[5], 31 'query_data': split[6], 32 'fragment': split[7] 33 } 34} 35 36function jprestaPcSetCookie(cname, cvalue, ttl_minutes, path) { 37 let d = new Date(); 38 d.setTime(d.getTime() + (ttl_minutes*60*1000)); 39 let expires = "expires="+ d.toUTCString(); 40 document.cookie = cname + "=" + cvalue + ";" + expires + ";path=" + path; 41} 42 43function jprestaPcGetCookie(cname, defaultValue) { 44 if (defaultValue === undefined) { 45 defaultValue = null; 46 } 47 let name = cname + "="; 48 let decodedCookie = decodeURIComponent(document.cookie); 49 let ca = decodedCookie.split(';'); 50 for(let i = 0; i <ca.length; i++) { 51 let c = ca[i]; 52 while (c.charAt(0) === ' ') { 53 c = c.substring(1); 54 } 55 if (c.indexOf(name) === 0) { 56 return c.substring(name.length, c.length); 57 } 58 } 59 return defaultValue; 60} 61 62function jprestaGetTTFB() { 63 let timing = null; 64 if (typeof window.performance.timing !== 'undefined') { 65 timing = window.performance.timing; 66 } 67 else { 68 timing = window.performance.getEntriesByType('navigation')[0]; 69 } 70 return timing.responseStart - timing.requestStart; 71} 72 73function jprestaIsBot() { 74 return /bot|googlebot|crawler|spider|robot|crawling|gtmetrix|chrome-lighthouse/i.test(navigator.userAgent); 75} 76 77function jprestaGetCacheType() {
78 let cache_type = -2; 79 let timing = null; 80 if (typeof window.performance.getEntriesByType == 'function') { 81 timing = window.performance.getEntriesByType('navigation')[0]; 82 } 83 if (!timing && typeof window.performance.timing !== 'undefined') { 84 timing = window.performance.timing; 85 } 86 if (timing && timing.transferSize === 0) { 87 cache_type = 2; 88 } 89 else if (timing && typeof timing.serverTiming != 'undefined') { 90 for (let i = 0; i < timing.serverTiming.length; i++) { 91 if (timing.serverTiming[i].name === 'jpresta_cache') { 92 cache_type = parseInt(timing.serverTiming[i].description); 93 break; 94 } 95 } 96 } 97 return cache_type; 98} 99 100/** 101 * Forward dbgpagecache parameter 102 */ 103function jprestaPcForwardDbgpagecacheParameter() { 104 try { 105 if (typeof prestashop !== 'undefined' && prestashop.urls && prestashop.urls.base_url) { 106 baseDir = prestashop.urls.base_url; 107 } else if (typeof baseDir === 'undefined') { 108 baseDir = window.location.origin + '/'; 109 } 110 111 if (window.location.href.indexOf("dbgpagecache=") > 0) { 112 $("a:not(.pagecache)").each(function () { 113 let e = $(this).attr("href"); 114 let t = this.search; 115 let n = "dbgpagecache=" + jprestaPcGetParameterValue("dbgpagecache"); 116 let r = baseDir.replace("https", "http"); 117 if (typeof e !== "undefined" && e.substr(0, 1) !== "#" && (e.replace("https", "http").substr(0, r.length) === r || e.indexOf('://') === -1) && e.indexOf('javascript:') === -1 && e.indexOf('mailto:') === -1 && e.indexOf('tel:') === -1 && e.indexOf('callto:') === -1) { 118 if (t.length === 0) this.search = n; 119 else this.search += "&" + n; 120 } 121 }); 122 console.log("Page Cache Ultimate - Parameter dbgpagecache has been added to all links"); 123 } 124 } catch (e) { 125 console.warn("Page Cache Ultimate - Cannot forward dbgpagecache parameter on all links: " + e.message, e); 126 } 127} 128 129jprestaPcStartsWith = function(str, search) { 130 return typeof str === 'string' && str.substr(0, search.length) === search; 131}; 132 133jprestaPcProcessDynamicModules = function(dyndatas) { 134 for (let key in dyndatas) { 135 if (key === 'js') { 136 // Keep spaces arround 'key', some Prestashop removes [key] otherwise (?!) 137 $('body').append(dyndatas[ key ]); 138 } 139 else if (jprestaPcStartsWith(key, 'dyn')) { 140 try { 141 let blockToReplace = $('#' + key); 142 143 if (blockToReplace.length) { 144 // Keep parent if it is an Elementor widget 145 let parentBlock = blockToReplace.parent(); 146 147 // Replace the old block with the new HTML from dyndatas 148 // WARNING: Keep spaces arround 'key', some Prestashop removes [key] otherwise (?!) 149 blockToReplace.replaceWith(dyndatas[ key ]); 150 151 // Check if the parent block is an Elementor widget 152 if (parentBlock.hasClass('elementor-widget')) { 153 try { 154 // Run Elementor JS initialization if available 155 if (window.ceFrontend?.elementsHandler?.runReadyTrigger) { 156 window.ceFrontend.elementsHandler.runReadyTrigger(parentBlock); 157 } 158 } catch (error) { 159 console.error('Page Cache Ultimate - Error while initializing Elementor widget ' + key + ': ' + error); 160 } 161 } 162 } 163 } 164 catch (error) { 165 console.error('Page Cache Ultimate - A javasript error occured during the "eval" of the refreshed content ' + key + ': ' + error); 166 } 167 } 168 } 169 if (typeof pcRunDynamicModulesJs == 'function') { 170 pcRunDynamicModulesJs(); 171 } 172 $('header a[href]').each(function() { 173 $(this).attr('href', $(this).attr('href') 174 .replace(/(%26|%3F|\?|&)ajax(%3D|=)1(%26|&)page_cache_dynamics_mods(%3D|=)1(%26|&)action(%3D|=)refresh_dynamic_mods/, '') 175 ); 176 }); 177 console.timeEnd('Page Cache Ultimate - Dynamic modules have been refreshed in ') 178 if (typeof prestashop != 'undefined' && typeof prestashop.emit == 'function') { 179 prestashop.emit('jprestaDynamicContentLoaded'); 180 } 181}; 182 183/** 184 * Refresh dynamic modules 185 */ 186function jprestaPcRefreshDynamicModules(cacheSource) { 187 try { 188 console.time('Page Cache Ultimate - Dynamic modules have been refreshed in ') 189 let dynDatas = {};
190 dynDatas['cache_source'] = cacheSource; 191 dynDatas['ttfb'] = jprestaGetTTFB(); 192 $('.dynhook').each(function(index, domhook){ 193 let el = this; // native element to be faster 194 dynDatas['hk_' + index] = 195 (el.getAttribute('id') || '') + '|' + 196 (el.dataset.hooktype || '') + '|' + 197 (el.dataset.module || '') + '|' + 198 (el.dataset.hook || '') + '|' + 199 (el.dataset.hookargs || ''); 200 }); 201 let urlparts = jprestaPcSplitUri(document.URL); 202 let url = urlparts['scheme'] + '://' + urlparts['domain'] + urlparts['port'] + urlparts['path'] + urlparts['query_data']; 203 let indexEnd = url.indexOf('?'); 204 if (indexEnd >= 0 && indexEnd < url.length) { 205 url += '&ajax=1&page_cache_dynamics_mods=1&action=refresh_dynamic_mods'; 206 } 207 else { 208 url += '?ajax=1&page_cache_dynamics_mods=1&action=refresh_dynamic_mods'; 209 } 210 let headers = {}; 211 if (document.referrer) { 212 headers['x-jpresta-referer'] = document.referrer; 213 } 214 $.ajax({url: url, type: 'POST', data: dynDatas, dataType: 'json', cache: false, headers: headers, 215 success: jprestaPcProcessDynamicModules, 216 error: function(jqXHR, textStatus, errorThrown) { 217 let dyndatas; 218 try { 219 let indexStart = jqXHR.responseText.indexOf('{'); 220 let responseFixed = jqXHR.responseText.substring(indexStart, jqXHR.responseText.length); 221 dyndatas = $.parseJSON(responseFixed); 222 if (dyndatas != null) { 223 jprestaPcProcessDynamicModules(dyndatas); 224 return; 225 } 226 } catch (err) { 227 console.error("Page Cache Ultimate - Cannot parse data of error=" + err, err); 228 } 229 console.error("Page Cache Ultimate - Cannot display dynamic modules: error=" + textStatus + " exception=" + errorThrown); 230 console.log("Page Cache Ultimate - Dynamic module URL: " + url); 231 }}); 232 } catch (e) { 233 console.error("Page Cache Ultimate - Cannot display dynamic modules: " + e.message, e); 234 } 235} 236 237/** 238 * Stats TTFB (when using back/forward cache) 239 */ 240function jprestaPcSendStats(cacheSource, ttfb) { 241 try { 242 console.time('Page Cache Ultimate - Sending stats in '); 243 let dynDatas = {}; 244 dynDatas['cache_source'] = cacheSource; 245 dynDatas['ttfb'] = ttfb; 246 let urlparts = jprestaPcSplitUri(document.URL); 247 let url = urlparts['scheme'] + '://' + urlparts['domain'] + urlparts['port'] + urlparts['path'] + urlparts['query_data']; 248 let indexEnd = url.indexOf('?'); 249 if (indexEnd >= 0 && indexEnd < url.length) { 250 url += '&ajax=1&page_cache_dynamics_mods=1&action=refresh_dynamic_mods&stats'; 251 } 252 else { 253 url += '?ajax=1&page_cache_dynamics_mods=1&action=refresh_dynamic_mods&stats'; 254 } 255 $.ajax({url: url, type: 'POST', data: dynDatas, dataType: 'json', cache: false, 256 error: function(jqXHR, textStatus, errorThrown) { 257 console.error("Page Cache Ultimate - Cannot display dynamic modules: error=" + textStatus + " exception=" + errorThrown); 258 console.log("Page Cache Ultimate - Stats URL: " + url); 259 }, 260 complete: function() { 261 console.timeEnd('Page Cache Ultimate - Sending stats in '); 262 } 263 }); 264 } catch (e) { 265 console.error("Page Cache Ultimate - Cannot stats: " + e.message, e); 266 } 267} 268 269let jprestaUpdateCartTryCount = 0; 270 271function jprestaUpdateCart() { 272 // Refresh the cart 273 if (typeof prestashop !== 'undefined' && typeof prestashop.emit == 'function') { 274 if (typeof prestashop._events['updateCart'] == 'undefined') { 275 if (jprestaUpdateCartTryCount < 10) { 276 // The cart is not yet attch to the event so we do it a little bit later 277 jprestaUpdateCartTryCount++; 278 console.log('Page Cache Ultimate - Cart is not ready, retrying...'); 279 setTimeout(jprestaUpdateCart, 100); 280 return; 281 } 282 else { 283 console.log('Page Cache Ultimate - Cart is not ready, NOT retrying because we tried too many times.'); 284 } 285 } 286 if (typeof jprestaUseCreativeElements == 'undefined' || !jprestaUseCreativeElements) { 287 // >= PS 1.7 288 console.log('Page Cache Ultimate - Refreshing the cart (PS >= 1.7)...'); 289 // Need to put it in a setTimeout to let other modules subscribes to the event 290 setTimeout("prestashop.emit('updateCart', {reason: {linkAction: 'refresh'}, resp: {errors: []}})", 10); 291 } 292 else { 293 // For CreativeElements 294 console.log('Page Cache Ultimate - Refreshing the cart (CreativeElements)...'); 295 $.ajax({ 296 url: prestashop.urls.pages.cart, 297 method: 'POST', 298 dataType: 'json', 299 data: { 300 ajax: 1, 301 action: 'update' 302 } 303 }).then(function(resp) { 304 if (resp.success && resp.cart) { 305 prestashop.emit('updateCart', { 306 reason: { 307 linkAction: 'refresh' 308 }, 309 resp: resp 310 }); 311 } 312 }); 313 } 314 } 315 else if(typeof ajaxCart !== 'undefined') { 316 // < PS 1.7 317 console.log('Page Cache Ultimate - Refreshing the cart (PS 1.5/1.6)...'); 318 $.ajax({ 319 type: 'POST', 320 headers: {"cache-control": "no-cache"}, 321 url: baseUri + '?rand=' + new Date().getTime(), 322 async: true, 323 cache: false, 324 dataType: "json",
325 data: 'controller=cart&ajax=1&token=' + static_token, 326 success: function (jsonData) { 327 ajaxCart.updateCart(jsonData); 328 } 329 }); 330 } 331} 332 333function jprestaInitCreativeElementsWidgets() { 334 // List of widget types to make dynamic 335 let widgetTypes = [ 336 'sign-in.default', 337 'shopping-cart.default', 338 'product-add-to-wishlist.default' 339 ]; 340 341 widgetTypes.forEach(function(type) { 342 $('[data-widget_type="' + type + '"]').each(function(index) { 343 let widget = $(this); 344 345 let elementorId = widget.closest('[data-elementor-id]').attr('data-elementor-id'); 346 let widgetId = widget.attr('data-id'); 347 let widgetContainer = widget.children().first(); 348 349 widgetContainer.attr('data-hooktype', 'ce'); 350 widgetContainer.attr('data-hookargs', elementorId + ',' + widgetId); 351 widgetContainer.addClass('dynhook'); 352 353 if (!widgetContainer.attr('id')) { 354 // Add widgetId + index to ensure uniqueness 355 let uniqueId = 'dyn' + widgetId + '_' + index; 356 widgetContainer.attr('id', uniqueId); 357 } 358 }); 359 }); 360} 361 362window.addEventListener('load', function(event) { 363 if (jprestaIsBot()) { 364 // For bots just send stats 365 jprestaPcSendStats(jprestaGetCacheType(), jprestaGetTTFB()); 366 return; 367 } 368 if (typeof jprestaUpdateCartDirectly != 'undefined' && jprestaUpdateCartDirectly) { 369 // Refresh the cart right now instead of waiting after dynamic modules are refreshed 370 if (typeof $ == 'function') { 371 // This hack makes sure the event "updateCart" will be emitted after all modules are attached "on" it 372 $(document).ready(jprestaUpdateCart); 373 } 374 else { 375 jprestaUpdateCart(); 376 } 377 } 378 // Make some creative elements as dynamic widgets 379 jprestaInitCreativeElementsWidgets(); 380 // jpresta_cache_source => -1=cannot be cached; 0=no cache; 1=server cache; 2=browser cache, 3=static cache, 4=back/forward cache 381 let cacheSource = jprestaGetCacheType(); 382 switch (cacheSource) { 383 case -2: 384 jprestaPcRefreshDynamicModules(cacheSource); 385 console.log('Page Cache Ultimate - Cannot determine the cache type :-('); 386 break; 387 case -1: 388 console.log('Page Cache Ultimate - Cannot be cached'); 389 break; 390 case 0: 391 jprestaPcRefreshDynamicModules(cacheSource); 392 console.log('Page Cache Ultimate - No cache was used'); 393 break; 394 case 1: 395 jprestaPcRefreshDynamicModules(cacheSource); 396 console.log('Page Cache Ultimate - Server cache was used'); 397 break; 398 case 2: 399 jprestaPcRefreshDynamicModules(cacheSource); 400 console.log('Page Cache Ultimate - Browser cache was used'); 401 break; 402 case 3: 403 jprestaPcRefreshDynamicModules(cacheSource); 404 console.log('Page Cache Ultimate - Static cache was used'); 405 break; 406 case 4: 407 // Handled by 'pageshow' event 408 break; 409 } 410 $('.pctype' + cacheSource).show(); 411 jprestaPcForwardDbgpagecacheParameter(); 412 let ctxUuid = jprestaPcGetCookie('jpresta_cache_context', false); 413 if (ctxUuid) { 414 console.log('Page Cache Ultimate - Displaying the page with context \x1B[1;4m' + ctxUuid + '\x1B[m'); 415 } 416}); 417 418// Refresh the cart when back/forward cache is used 419// pageshow is not always executed, only when the back/forward cache is used 420window.addEventListener('pageshow', function(event) { 421 if (event.persisted) { 422 jprestaPcSendStats(4, 0); 423 // Refresh the cart 424 console.log('Page Cache Ultimate - Back/forward cache is used'); 425 jprestaUpdateCart(); 426 } 427}); 428 429window.addEventListener('resize', function(event) { 430 document.cookie = "jpresta_cache_context=;path=/;expires=Thu, 01 Jan 1970 00:00:00 GMT"; 431});
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.