1(function (window) 2{ 3 if (window.BX.frameCache) return; 4 5 var BX = window.BX; 6 var localStorageKey = "compositeCache"; 7 var lolalStorageTTL = 1440; 8 var compositeMessageIds = ["bitrix_sessid", "USER_ID", "SERVER_TIME", "USER_TZ_OFFSET", "USER_TZ_AUTO"]; 9 var compositeDataFile = "/bitrix/tools/composite_data.php"; 10 var sessidWasUpdated = false; 11 12 BX.frameCache = function() 13 { 14 }; 15 16 BX.frameCache.localStorage = new BX.LocalStorage({ prefix: '' }); 17 18 BX.frameCache.init = function() 19 { 20 this.cacheDataBase = null; 21 this.tableParams = 22 { 23 tableName: "composite", 24 fields: [ 25 {name: "id", unique: true}, 26 "content", 27 "hash", 28 "props" 29 ] 30 }; 31 32 this.frameDataReceived = false; 33 this.frameDataInserted = false; 34 35 if (BX.type.isString(window.frameDataString) && window.frameDataString.length > 0) 36 { 37 BX.frameCache.onFrameDataReceived(window.frameDataString); 38 } 39 40 this.vars = window.frameCacheVars ? window.frameCacheVars : { 41 dynamicBlocks: {}, 42 page_url: "", 43 params: {}, 44 storageBlocks: [] 45 }; 46 47 //local storage warming up 48 var lsCache = BX.frameCache.localStorage.get(localStorageKey) || {}; 49 for (var i = 0; i < compositeMessageIds.length; i++) 50 { 51 var messageId = compositeMessageIds[i]; 52 if (typeof(BX.message[messageId]) != "undefined") 53 { 54 lsCache[messageId] = BX.message[messageId]; 55 } 56 } 57 BX.frameCache.localStorage.set(localStorageKey, lsCache, lolalStorageTTL); 58 59 BX.addCustomEvent("onBXMessageNotFound", function(mess) 60 { 61 if (BX.util.in_array(mess, compositeMessageIds)) 62 { 63 var cache = BX.frameCache.localStorage.get(localStorageKey); 64 if (cache && typeof(cache[mess]) != "undefined") 65 { 66 BX.message[mess] = cache[mess]; 67 } 68 else 69 { 70 BX.frameCache.getCompositeMessages(); 71 } 72 } 73 }); 74 75 if (!window.frameUpdateInvoked) 76 { 77 this.update(false); 78 window.frameUpdateInvoked = true; 79 } 80 81 if (window.frameRequestStart) 82 { 83 BX.ready(function() { 84 BX.onCustomEvent("onCacheDataRequestStart"); 85 BX.frameCache.tryUpdateSessid(); 86 }); 87 } 88 89 if (window.frameRequestFail) 90 { 91 BX.ready(function() { 92 setTimeout(function() { 93 BX.onCustomEvent("onFrameDataRequestFail", [window.frameRequestFail]); 94 }, 0); 95 }); 96 } 97 98 BX.frameCache.insertBanner(); 99 }; 100 101 BX.frameCache.getCompositeMessages = function() 102 { 103 try { 104 BX.ajax({ 105 method: "GET", 106 dataType: "json", 107 url: compositeDataFile, 108 async : false, 109 data: '', 110 onsuccess: function(json) 111 { 112 BX.frameCache.setCompositeVars(json); 113 } 114 }); 115 } 116 catch (exeption) 117 { 118 BX.debug("Composite sync request failed."); 119 } 120 }; 121 122 BX.frameCache.setCompositeVars = function(vars) 123 { 124 if (!vars) 125 { 126 return; 127 } 128 else if (vars.lang) 129 { 130 vars = vars.lang; 131 } 132 133 var lsCache = BX.frameCache.localStorage.get(localStorageKey) || {}; 134 for (var name in vars) 135 { 136 if (vars.hasOwnProperty(name)) 137 { 138 BX.message[name] = vars[name]; 139 140 if (BX.util.in_array(name, compositeMessageIds)) 141 { 142 lsCache[name] = vars[name]; 143 } 144 } 145 } 146 147 BX.frameCache.localStorage.set(localStorageKey, lsCache, lolalStorageTTL); 148 }; 149 150 BX.frameCache.insertBlock = function(block) 151 { 152 if (!block) 153 { 154 return; 155 } 156 157 let container = null; 158 const autoContainerPrefix = 'bxdynamic_'; 159 if (block.ID.startsWith(autoContainerPrefix)) 160 { 161 const dynamicStart = BX(`${block.ID}_start`); 162 const dynamicEnd = BX(`${block.ID}_end`); 163 if (!dynamicStart || !dynamicEnd) 164 { 165 BX.debug(`Dynamic area ${block.ID} was not found`); 166 167 return; 168 } 169 170 container = [dynamicStart, dynamicEnd]; 171 } 172 else 173 { 174 container = BX(block.ID); 175 if (!container) 176 { 177 BX.debug(`Container ${block.ID} was not found`); 178 179 return; 180 } 181 } 182 183 this.insertHTML(container, block); 184 this.processInlineJS(block); 185 }; 186 187 BX.frameCache.insertHTML = function(container, block) 188 { 189 if (BX.Type.isArray(container)) 190 { 191 const [dynamicStart, dynamicEnd] = container; 192 BX.frameCache.removeNodes(dynamicStart, dynamicEnd); 193 dynamicStart.insertAdjacentHTML('afterEnd', block.CONTENT); 194 } 195 else 196 {
197 if (block.PROPS.USE_ANIMATION) 198 { 199 container.style.opacity = 0; 200 container.innerHTML = block.CONTENT; 201 (new BX.easing({ 202 duration: 1500, 203 start: { opacity: 0 }, 204 finish: { opacity: 100 }, 205 transition: BX.easing.makeEaseOut(BX.easing.transitions.quart), 206 step: (state) => { 207 container.style.opacity = state.opacity / 100; 208 }, 209 complete: () => { 210 container.style.cssText = ''; 211 }, 212 })).animate(); 213 } 214 else 215 { 216 container.innerHTML = block.CONTENT; 217 } 218 } 219 }; 220 221 BX.frameCache.processInlineJS = function(block) 222 { 223 BX.ajax.processRequestData(block.CONTENT, { scriptsRunFirst: false, dataType: 'HTML' }); 224 225 if (BX.Type.isArray(block.PROPS.BUNDLE_JS)) 226 { 227 BX.setJSList(block.PROPS.BUNDLE_JS); 228 } 229 230 if (BX.Type.isArray(block.PROPS.BUNDLE_CSS)) 231 { 232 BX.setCSSList(block.PROPS.BUNDLE_CSS); 233 } 234 }; 235 236 BX.frameCache.loadAssets = function(blocks, callback) 237 { 238 const scripts = []; 239 const styles = []; 240 for (const block of blocks) 241 { 242 const assets = this.getStringAssets(block); 243 if (BX.Type.isStringFilled(assets.html)) 244 { 245 document.head.insertAdjacentHTML('beforeend', assets.html); 246 } 247 248 BX.evalGlobal(assets.inlineJS.join(';')); 249 250 styles.push(...assets.styles); 251 if (BX.Type.isArrayFilled(block.PROPS.CSS)) 252 { 253 styles.push(...block.PROPS.CSS); 254 } 255 256 scripts.push(...assets.externalJS); 257 if (BX.Type.isArrayFilled(block.PROPS.JS)) 258 { 259 scripts.push(...block.PROPS.JS); 260 } 261 } 262 263 const items = [...styles.map((style) => ({ url: style, ext: 'css' })), ...scripts]; 264 if (items.length > 0) 265 { 266 BX.load(items, callback); 267 } 268 else 269 { 270 callback(); 271 } 272 }; 273 274 BX.frameCache.getStringAssets = function(block) 275 { 276 const result = { styles: [], inlineJS: [], externalJS: [], html: '' }; 277 if (!BX.Type.isArrayFilled(block.PROPS.STRINGS)) 278 { 279 return result; 280 } 281 282 const parts = BX.processHTML(block.PROPS.STRINGS.join('\n'), false); 283 for (let i = 0, l = parts.SCRIPT.length; i < l; i++) 284 { 285 const script = parts.SCRIPT[i]; 286 if (script.isInternal) 287 { 288 result.inlineJS.push(script.JS); 289 } 290 else 291 { 292 result.externalJS.push(script.JS); 293 } 294 } 295 296 result.styles = parts.STYLE; 297 result.html = parts.HTML; 298 299 return result; 300 }; 301 302 BX.frameCache.removeNodes = function(fromElement, toElement) 303 { 304 var startFound = false; 305 var parent = fromElement.parentNode; 306 var nodes = Array.prototype.slice.call(parent.childNodes); 307 for (var i = 0, length = nodes.length; i < length; i++) 308 { 309 if (startFound) 310 { 311 if (nodes[i] === toElement) 312 { 313 break; 314 } 315 else 316 { 317 parent.removeChild(nodes[i]); 318 } 319 } 320 else if (nodes[i] === fromElement) 321 { 322 startFound = true; 323 } 324 } 325 }; 326 327 BX.frameCache.update = function(makeRequest, noInvoke) 328 { 329 noInvoke = !!noInvoke; 330 makeRequest = typeof(makeRequest) == "undefined" ? true : makeRequest; 331 if (makeRequest) 332 { 333 this.requestData(); 334 } 335 336 if (!noInvoke) 337 { 338 BX.ready(BX.proxy(function() { 339 if (!this.frameDataReceived) 340 { 341 this.invokeCache(); 342 } 343 }, this)); 344 } 345 }; 346 347 BX.frameCache.invokeCache = function() 348 { 349 //getting caching dynamic blocks 350 if (this.vars.storageBlocks && this.vars.storageBlocks.length > 0) 351 { 352 BX.onCustomEvent(this, "onCacheInvokeBefore", [this.vars.storageBlocks]); 353 this.readCacheWithID(this.vars.storageBlocks, BX.proxy(this.insertFromCache, this)); 354 } 355 }; 356 357 BX.frameCache.handleResponse = function(json) 358 { 359 if (json == null) 360 return; 361 362 BX.onCustomEvent("onFrameDataReceivedBefore", [json]); 363 364 if (BX.Type.isArray(json.dynamicBlocks)) 365 { 366 this.insertBlocks(json.dynamicBlocks, false); 367 this.writeCache(json.dynamicBlocks); 368 } 369 370 BX.onCustomEvent("onFrameDataReceived", [json]); 371 372 if ( 373 json.isManifestUpdated == "1" 374 && this.vars.CACHE_MODE === "APPCACHE" 375 && window.applicationCache 376 && ( 377 window.applicationCache.status == window.applicationCache.IDLE 378 || window.applicationCache.status == window.applicationCache.UPDATEREADY 379 ) 380 ) //the manifest has been changed 381 { 382 window.applicationCache.update(); 383 } 384 385 if (json.htmlCacheChanged === true && this.vars.CACHE_MODE === "HTMLCACHE") 386 { 387 BX.onCustomEvent("onHtmlCacheChanged", [json]); 388 } 389 390 if (BX.type.isArray(json.spread)) 391 { 392 for (var i = 0; i < json.spread.length; i++) 393 { 394 new Image().src = json.spread[i]; 395 } 396 } 397 398 }; 399 400 BX.frameCache.requestData = function() 401 { 402 var headers = [ 403 { name: "BX-ACTION-TYPE", value: "get_dynamic" }, 404 { name: "BX-REF", value: document.referrer }, 405 { name: "BX-CACHE-MODE", value: this.vars.CACHE_MODE }, 406 { name: "BX-CACHE-BLOCKS", value: this.vars.dynamicBlocks ? JSON.stringify(this.vars.dynamicBlocks) : "" } 407 ]; 408 409 if (this.vars.AUTO_UPDATE === false && this.vars.AUTO_UPDATE_TTL && this.vars.AUTO_UPDATE_TTL > 0) 410 { 411 var lastModified = Date.parse(document.lastModified); 412 if (!isNaN(lastModified)) 413 { 414 var now = new Date().getTime(); 415 if ((lastModified + this.vars.AUTO_UPDATE_TTL * 1000) < now) 416 { 417 headers.push({ name: "BX-INVALIDATE-CACHE", value: "Y" }); 418 } 419 } 420 } 421 422 if (this.vars.CACHE_MODE === "APPCACHE") 423 { 424 headers.push({ name: "BX-APPCACHE-PARAMS", value: JSON.stringify(this.vars.PARAMS) }); 425 headers.push({ name: "BX-APPCACHE-URL", value: this.vars.PAGE_URL ? this.vars.PAGE_URL : "" }); 426 } 427 428 BX.onCustomEvent("onCacheDataRequestStart"); 429 430 var requestURI = window.location.href; 431 var index = requestURI.indexOf("#"); 432 if (index > 0) 433 { 434 requestURI = requestURI.substring(0, index); 435 } 436 requestURI += (requestURI.indexOf("?") >= 0 ? "&" : "?") + "bxrand=" + new Date().getTime(); 437 438 BX.ajax({ 439 timeout: 60, 440 method: "GET", 441 url: requestURI, 442 data: {}, 443 headers: headers, 444 skipBxHeader : true, 445 processData: false, 446 onsuccess: BX.proxy(BX.frameCache.onFrameDataReceived, this), 447 onfailure: function() 448 { 449 window.frameRequestFail = { 450 error: true, 451 reason: "bad_response", 452 url : requestURI, 453 xhr: this.xhr, 454 status: this.xhr ? this.xhr.status : 0 455 }; 456 457 BX.onCustomEvent("onFrameDataRequestFail", [window.frameRequestFail]); 458 } 459 }); 460 }; 461 462 BX.frameCache.onFrameDataReceived = function(response) 463 { 464 var result = null; 465 try 466 { 467 result = JSON.parse(response); 468 } 469 catch (e) 470 { 471 var error = { 472 error: true, 473 reason: "bad_eval", 474 response: response 475 }; 476 477 window.frameRequestFail = error; 478 479 BX.ready(function() { 480 setTimeout(function() { 481 BX.onCustomEvent("onFrameDataRequestFail", [error]); 482 }, 0); 483 }); 484 485 return; 486 } 487 488 this.frameDataReceived = true; 489 490 if (result && BX.type.isNotEmptyString(result.redirect_url)) 491 { 492 window.location = result.redirect_url; 493 return; 494 } 495 496 if (result && result.error === true) 497 { 498 window.frameRequestFail = result; 499 500 BX.ready(BX.proxy(function() { 501 setTimeout(BX.proxy(function() { 502 BX.onCustomEvent("onFrameDataRequestFail", [result]); 503 }, this), 0); 504 }, this)); 505 506 return; 507 } 508 509 BX.frameCache.setCompositeVars(result); 510 BX.ready(BX.proxy(function() { 511 this.handleResponse(result); 512 this.tryUpdateSessid(); 513 }, this)); 514 }; 515 516 BX.frameCache.insertFromCache = function(resultSet, transaction) 517 { 518 if (!this.frameDataReceived) 519 { 520 var items = resultSet.items; 521 if (items.length > 0) 522 { 523 for (var i = 0; i < items.length; i++) 524 { 525 items[i].PROPS = JSON.parse(items[i].PROPS); 526 } 527 528 this.insertBlocks(items, true); 529 } 530 531 BX.onCustomEvent(this, "onCacheInvokeAfter", [this.vars.storageBlocks, resultSet]); 532 } 533 }; 534 535 BX.frameCache.insertBlocks = function(blocks, fromCache) 536 { 537 const blocksToInsert = new Set(); 538 for (const block of blocks) 539 { 540 BX.onCustomEvent('onBeforeDynamicBlockUpdate', [block, fromCache]); 541 if (block.PROPS.AUTO_UPDATE === false) 542 { 543 continue; 544 } 545 546 if (block && block.HASH && block.PROPS && block.PROPS.ID) 547 { 548 this.vars.dynamicBlocks[block.PROPS.ID] = block.HASH; 549 } 550 551 blocksToInsert.add(block); 552 } 553 554 this.loadAssets(blocksToInsert, () => { 555 for (const blockToInsert of blocksToInsert) 556 { 557 this.insertBlock(blockToInsert); 558 } 559 560 if (window.performance) 561 { 562 const entries = performance.getEntries();
563 for (const entry of entries) 564 { 565 if (entry.initiatorType === 'xmlhttprequest' && entry.name && /bxrand=\d+/.test(entry.name)) 566 { 567 // uses in ba.js 568 this.requestTiming = entry; 569 } 570 } 571 572 if (window.performance.measure) 573 { 574 window.performance.measure('Composite:LCP'); 575 576 const lcpEntries = performance.getEntriesByName('Composite:LCP'); 577 if (lcpEntries.length > 0 && lcpEntries[0].duration) 578 { 579 // uses in ba.js 580 this.lcp = Math.ceil(lcpEntries[0].duration); 581 } 582 } 583 } 584 585 BX.onCustomEvent('onFrameDataProcessed', [blocks, fromCache]); 586 this.frameDataInserted = true; 587 }); 588 }; 589 590 BX.frameCache.writeCache = function(blocks) 591 { 592 for (var i = 0; i < blocks.length; i++) 593 { 594 if (blocks[i].PROPS.USE_BROWSER_STORAGE === true) 595 { 596 this.writeCacheWithID( 597 blocks[i].ID, 598 blocks[i].CONTENT, 599 blocks[i].HASH, 600 JSON.stringify(blocks[i].PROPS) 601 ); 602 } 603 } 604 }; 605 606 BX.frameCache.openDatabase = function() 607 { 608 var isDatabaseOpened = (this.cacheDataBase != null); 609 610 if(!isDatabaseOpened) 611 { 612 this.cacheDataBase = new BX.Dexie("composite"); 613 if(this.cacheDataBase != null) 614 { 615 this.cacheDataBase.version(1).stores({ 616 composite: '&ID,CONTENT,HASH,PROPS' 617 }); 618 isDatabaseOpened = true; 619 } 620 } 621 622 return isDatabaseOpened; 623 }; 624 625 BX.frameCache.writeCacheWithID = function(id, content, hash, props) 626 { 627 if(BX.frameCache.openDatabase()) 628 { 629 if (typeof props == "object") 630 { 631 props = JSON.stringify(props); 632 } 633 634 this.cacheDataBase.composite.put({ 635 ID: id, 636 CONTENT: content, 637 HASH: hash, 638 PROPS : props 639 }); 640 } 641 }; 642 643 BX.frameCache.readCacheWithID = function(id, callback) 644 { 645 if(BX.frameCache.openDatabase()) 646 { 647 this.cacheDataBase.composite 648 .where("ID").anyOf(id).toArray() 649 .then((function(items){ 650 callback({items:items}); 651 }).bind(this)); 652 } 653 else if(typeof callback != "undefined") 654 { 655 callback({items:[]}); 656 } 657 }; 658 659 BX.frameCache.insertBanner = function() 660 { 661 if (!this.vars.banner || !BX.type.isNotEmptyString(this.vars.banner.text)) 662 { 663 return; 664 } 665 666 BX.ready(BX.proxy(function() { 667 var banner = BX.create("a", { 668 props : { 669 className : "bx-composite-btn" + ( 670 BX.type.isNotEmptyString(this.vars.banner.style) ? 671 " bx-btn-" + this.vars.banner.style : 672 "" 673 ), 674 href : this.vars.banner.url 675 }, 676 attrs : { 677 target : "_blank" 678 }, 679 text : this.vars.banner.text 680 }); 681 682 if (BX.type.isNotEmptyString(this.vars.banner.bgcolor)) 683 { 684 banner.style.backgroundColor = this.vars.banner.bgcolor; 685 if (BX.util.in_array(this.vars.banner.bgcolor.toUpperCase(), ["#FFF", "#FFFFFF", "WHITE"])) 686 { 687 BX.addClass(banner, "bx-btn-border"); 688 } 689 } 690 691 var container = BX("bx-composite-banner"); 692 if (container) 693 { 694 container.appendChild(banner); 695 } 696 else 697 { 698 BX.addClass(banner, "bx-composite-btn-fixed"); 699 document.body.appendChild(BX.create("div", { 700 style : { position: "relative" }, 701 children: [ banner ] 702 })); 703 } 704 }, this)); 705 }; 706 707 BX.frameCache.tryUpdateSessid = function() 708 { 709 if (sessidWasUpdated) 710 { 711 return; 712 } 713 714 var name = "bitrix_sessid"; 715 var sessid = false; 716 717 if (typeof(BX.message[name]) != "undefined") 718 { 719 sessid = BX.message[name]; 720 } 721 else 722 { 723 var cache = BX.frameCache.localStorage.get(localStorageKey) || {}; 724 if (typeof(cache[name]) != "undefined") 725 { 726 sessid = cache[name]; 727 } 728 } 729 730 if (sessid !== false) 731 { 732 sessidWasUpdated = true; 733 this.updateSessid(sessid); 734 } 735 }; 736 737 BX.frameCache.updateSessid = function(sessid) 738 { 739 var inputs = document.getElementsByName("sessid"); 740 for (var i = 0; i < inputs.length; i++) 741 { 742 inputs[i].value = sessid; 743 } 744 }; 745 746 //initialize 747 BX.frameCache.init(); 748 749})(window); 750
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.