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