PageSourceSearch

https://ambumed.ru/bitrix/js/main/core/core_frame_cache.js?178003798016066

js ambumed.ru collected 2026-10-06 20:11:25 UTC 16,066 bytes, 750 lines download raw bytes

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.