PageSourceSearch

https://shepkinskoe.ru/bitrix/js/main/core/core_ajax.js

js shepkinskoe.ru collected 2026-10-02 11:07:22 UTC 36,424 bytes, 1,628 lines download raw bytes

1;(function(window){
2
3if (window.BX.ajax)
4	return;
5
6var
7	BX = window.BX,
8
9	tempDefaultConfig = {},
10	defaultConfig = {
11		method: 'GET', // request method: GET|POST
12		dataType: 'html', // type of data loading: html|json|script
13		timeout: 0, // request timeout in seconds. 0 for browser-default
14		async: true, // whether request is asynchronous or not
15		processData: true, // any data processing is disabled if false, only callback call
16		scriptsRunFirst: false, // whether to run _all_ found scripts before onsuccess call. script tag can have an attribute "bxrunfirst" to turn  this flag on only for itself
17		emulateOnload: true,
18		skipAuthCheck: false, // whether to check authorization failure (SHOUD be set to true for CORS requests)
19		start: true, // send request immediately (if false, request can be started manually via XMLHttpRequest object returned)
20		cache: true, // whether NOT to add random addition to URL
21		preparePost: true, // whether set Content-Type x-www-form-urlencoded in POST
22		headers: false, // add additional headers, example: [{'name': 'If-Modified-Since', 'value': 'Wed, 15 Aug 2012 08:59:08 GMT'}, {'name': 'If-None-Match', 'value': '0'}]
23		lsTimeout: 30, //local storage data TTL. useless without lsId.
24		lsForce: false //wheter to force query instead of using localStorage data. useless without lsId.
25/*
26other parameters:
27	url: url to get/post
28	data: data to post
29	onsuccess: successful request callback. BX.proxy may be used.
30	onfailure: request failure callback. BX.proxy may be used.
31	onprogress: request progress callback. BX.proxy may be used.
32
33	lsId: local storage id - for constantly updating queries which can communicate via localStorage. core_ls.js needed
34
35any of the default parameters can be overridden. defaults can be changed by BX.ajax.Setup() - for all further requests!
36*/
37	},
38	ajax_session = null,
39	loadedScripts = {},
40	loadedScriptsQueue = [],
41	r = {
42		'url_utf': /[^\034-\254]+/g,
43		'script_self': /\/bitrix\/js\/main\/core\/core(_ajax)*.js$/i,
44		'script_self_window': /\/bitrix\/js\/main\/core\/core_window.js$/i,
45		'script_self_admin': /\/bitrix\/js\/main\/core\/core_admin.js$/i,
46		'script_onload': /window.onload/g
47	};
48
49// low-level method
50BX.ajax = function(config)
51{
52	var status, data;
53
54	if (!config || !config.url || !BX.type.isString(config.url))
55	{
56		return false;
57	}
58
59	for (var i in tempDefaultConfig)
60		if (typeof (config[i]) == "undefined") config[i] = tempDefaultConfig[i];
61
62	tempDefaultConfig = {};
63
64	for (i in defaultConfig)
65		if (typeof (config[i]) == "undefined") config[i] = defaultConfig[i];
66
67	config.method = config.method.toUpperCase();
68
69	if (!BX.localStorage)
70		config.lsId = null;
71
72	if (BX.browser.IsIE())
73	{
74		var result = r.url_utf.exec(config.url);
75		if (result)
76		{
77			do
78			{
79				config.url = config.url.replace(result, BX.util.urlencode(result));
80				result = r.url_utf.exec(config.url);
81			} while (result);
82		}
83	}
84
85	if(config.dataType == 'json')
86		config.emulateOnload = false;
87
88	if (!config.cache && config.method == 'GET')
89		config.url = BX.ajax._uncache(config.url);
90
91	if (config.method == 'POST' && config.preparePost)
92	{
93		config.data = BX.ajax.prepareData(config.data);
94	}
95
96	var bXHR = true;
97	if (config.lsId && !config.lsForce)
98	{
99		var v = BX.localStorage.get('ajax-' + config.lsId);
100		if (v !== null)
101		{
102			bXHR = false;
103
104			var lsHandler = function(lsData) {
105				if (lsData.key == 'ajax-' + config.lsId && lsData.value != 'BXAJAXWAIT')
106				{
107					var data = lsData.value,
108						bRemove = !!lsData.oldValue && data == null;
109					if (!bRemove)
110						BX.ajax.__run(config, data);
111					else if (config.onfailure)
112						config.onfailure("timeout");
113
114					BX.removeCustomEvent('onLocalStorageChange', lsHandler);
115				}
116			};
117
118			if (v == 'BXAJAXWAIT')
119			{
120				BX.addCustomEvent('onLocalStorageChange', lsHandler);
121			}
122			else
123			{
124				setTimeout(function() {lsHandler({key: 'ajax-' + config.lsId, value: v})}, 10);
125			}
126		}
127	}
128
129	if (bXHR)
130	{
131		config.xhr = BX.ajax.xhr();
132		if (!config.xhr) return;
133
134		if (config.lsId)
135		{
136			BX.localStorage.set('ajax-' + config.lsId, 'BXAJAXWAIT', config.lsTimeout);
137		}
138
139		config.xhr.open(config.method, config.url, config.async);
140
141		if (!config.skipBxHeader && !BX.ajax.isCrossDomain(config.url))
142		{
143			config.xhr.setRequestHeader('Bx-ajax', 'true');
144		}
145
146		if (config.method == 'POST' && config.preparePost)
147		{
148			config.xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
149		}
150		if (typeof(config.headers) == "object")
151		{
152			for (i = 0; i < config.headers.length; i++)
153				config.xhr.setRequestHeader(config.headers[i].name, config.headers[i].value);
154		}
155
156		if(!!config.onprogress)
157		{
158			BX.bind(config.xhr, 'progress', config.onprogress);
159		}
160
161		var bRequestCompleted = false;
162		var onreadystatechange = config.xhr.onreadystatechange = function(additional)
163		{
164			if (bRequestCompleted)
165				return;
166
167			if (additional === 'timeout')
168			{
169				if (config.onfailure)
170				{
171					config.onfailure("timeout");
172				}
173
174				BX.onCustomEvent(config.xhr, 'onAjaxFailure', ['timeout', '', config]);
175
176				config.xhr.onreadystatechange = BX.DoNothing;
177				config.xhr.abort();
178
179				if (config.async)
180				{
181					config.xhr = null;
182				}
183			}
184			else
185			{
186				if (config.xhr.readyState == 4 || additional == 'run')
187				{
188					status = BX.ajax.xhrSuccess(config.xhr) ? "success" : "error";
189					bRequestCompleted = true;
190					config.xhr.onreadystatechange = BX.DoNothing;
191
192					if (status == 'success')
193					{
194						var authHeader = (!!config.skipAuthCheck || BX.ajax.isCrossDomain(config.url))
195							? false
196							: config.xhr.getResponseHeader('X-Bitrix-Ajax-Status');
197
198						if(!!authHeader && authHeader == 'Authorize')
199						{
200							if (config.onfailure)
201							{
202								config.onfailure("auth", config.xhr.status);
203							}
204
205							BX.onCustomEvent(config.xhr, 'onAjaxFailure', ['auth', config.xhr.status, config]);
206						}
207						else
208						{
209							var data = config.xhr.responseText;
210
211							if (config.lsId)
212							{
213								BX.localStorage.set('ajax-' + config.lsId, data, config.lsTimeout);
214							}
215
216							BX.ajax.__run(config, data);
217						}
218					}
219					else
220					{
221						if (config.onfailure)
222						{
223							config.onfailure("status", config.xhr.status);
224						}
225
226						BX.onCustomEvent(config.xhr, 'onAjaxFailure', ['status', config.xhr.status, config]);
227					}
228
229					if (config.async)
230					{
231						config.xhr = null;
232					}
233				}
234			}
235		};
236
237		if (config.async && config.timeout > 0)
238		{
239			setTimeout(function() {
240				if (config.xhr && !bRequestCompleted)
241				{
242					onreadystatechange("timeout");
243				}
244			}, config.timeout * 1000);
245		}
246
247		if (config.start)
248		{
249			config.xhr.send(config.data);
250
251			if (!config.async)
252			{
253				onreadystatechange('run');
254			}
255		}
256
257		return config.xhr;
258	}
259};
260
261BX.ajax.xhr = function()
262{
263	if (window.XMLHttpRequest)
264	{
265		try {return new XMLHttpRequest();} catch(e){}
266	}
267	else if (window.ActiveXObject)
268	{
269		try { return new window.ActiveXObject("Msxml2.XMLHTTP.6.0"); }
270			catch(e) {}
271		try { return new window.ActiveXObject("Msxml2.XMLHTTP.3.0"); }
272			catch(e) {}
273		try { return new window.ActiveXObject("Msxml2.XMLHTTP"); }
274			catch(e) {}
275		try { return new window.ActiveXObject("Microsoft.XMLHTTP"); }
276			catch(e) {}
277		throw new Error("This browser does not support XMLHttpRequest.");
278	}
279
280	return null;
281};
282
283BX.ajax.isCrossDomain = function(url, location)
284{
285	location = location || window.location;
286
287	//Relative URL gets a current protocol
288	if (url.indexOf("//") === 0)
289	{
290		url = location.protocol + url;
291	}
292
293	//Fast check
294	if (url.indexOf("http") !== 0)
295	{
296		return false;
297	}
298
299	var link = window.document.createElement("a");
300	link.href = url;
301
302	return  link.protocol !== location.protocol ||
303			link.hostname !== location.hostname ||
304			BX.ajax.getHostPort(link.protocol, link.host) !== BX.ajax.getHostPort(location.protocol, location.host);
305};
306
307BX.ajax.getHostPort = function(protocol, host)
308{
309	var match = /:(\d+)$/.exec(host);
310	if (match)
311	{
312		return match[1];
313	}
314	else
315	{
316		if (protocol === "http:")
317		{
318			return "80";
319		}
320		else if (protocol === "https:")
321		{
322			return "443";
323		}
324	}
325
326	return "";
327};
328
329BX.ajax.__prepareOnload = function(scripts)
330{
331	if (scripts.length > 0)
332	{
333		BX.ajax['onload_' + ajax_session] = null;
334
335		for (var i=0,len=scripts.length;i<len;i++)
336		{
337			if (scripts[i].isInternal)
338			{
339				scripts[i].JS = scripts[i].JS.replace(r.script_onload, 'BX.aja
339x.onload_' + ajax_session);
340			}
341		}
342	}
343
344	BX.CaptureEventsGet();
345	BX.CaptureEvents(window, 'load');
346};
347
348BX.ajax.__runOnload = function()
349{
350	if (null != BX.ajax['onload_' + ajax_session])
351	{
352		BX.ajax['onload_' + ajax_session].apply(window);
353		BX.ajax['onload_' + ajax_session] = null;
354	}
355
356	var h = BX.CaptureEventsGet();
357
358	if (h)
359	{
360		for (var i=0; i<h.length; i++)
361			h[i].apply(window);
362	}
363};
364
365BX.ajax.__run = function(config, data)
366{
367	if (!config.processData)
368	{
369		if (config.onsuccess)
370		{
371			config.onsuccess(data);
372		}
373
374		BX.onCustomEvent(config.xhr, 'onAjaxSuccess', [data, config]);
375	}
376	else
377	{
378		data = BX.ajax.processRequestData(data, config);
379	}
380};
381
382
383BX.ajax._onParseJSONFailure = function(data)
384{
385	this.jsonFailure = true;
386	this.jsonResponse = data;
387	this.jsonProactive = /^\[WAF\]/.test(data);
388};
389
390BX.ajax.processRequestData = function(data, config)
391{
392	var result, scripts = [], styles = [];
393	switch (config.dataType.toUpperCase())
394	{
395		case 'JSON':
396
397			BX.addCustomEvent(config.xhr, 'onParseJSONFailure', BX.proxy(BX.ajax._onParseJSONFailure, config));
398			result = BX.parseJSON(data, config.xhr);
399			BX.removeCustomEvent(config.xhr, 'onParseJSONFailure', BX.proxy(BX.ajax._onParseJSONFailure, config));
400
401			if(!!result && BX.type.isArray(result['bxjs']))
402			{
403				for(var i = 0; i < result['bxjs'].length; i++)
404				{
405					if(BX.type.isNotEmptyString(result['bxjs'][i]))
406					{
407						scripts.push({
408							"isInternal": false,
409							"JS": result['bxjs'][i],
410							"bRunFirst": config.scriptsRunFirst
411						});
412					}
413					else
414					{
415						scripts.push(result['bxjs'][i])
416					}
417				}
418			}
419
420			if(!!result && BX.type.isArray(result['bxcss']))
421			{
422				styles = result['bxcss'];
423			}
424
425		break;
426		case 'SCRIPT':
427			scripts.push({"isInternal": true, "JS": data, "bRunFirst": config.scriptsRunFirst});
428			result = data;
429		break;
430
431		default: // HTML
432			var ob = BX.processHTML(data, config.scriptsRunFirst);
433			result = ob.HTML; scripts = ob.SCRIPT; styles = ob.STYLE;
434		break;
435	}
436
437	var bSessionCreated = false;
438	if (null == ajax_session)
439	{
440		ajax_session = parseInt(Math.random() * 1000000);
441		bSessionCreated = true;
442	}
443
444	if (styles.length > 0)
445		BX.loadCSS(styles);
446
447	if (config.emulateOnload)
448			BX.ajax.__prepareOnload(scripts);
449
450	var cb = BX.DoNothing;
451	if(config.emulateOnload || bSessionCreated)
452	{
453		cb = BX.defer(function()
454		{
455			if (config.emulateOnload)
456				BX.ajax.__runOnload();
457			if (bSessionCreated)
458				ajax_session = null;
459			BX.onCustomEvent(config.xhr, 'onAjaxSuccessFinish', [config]);
460		});
461	}
462
463	try
464	{
465		if (!!config.jsonFailure)
466		{
467			throw {type: 'json_failure', data: config.jsonResponse, bProactive: config.jsonProactive};
468		}
469
470		config.scripts = scripts;
471
472		BX.ajax.processScripts(config.scripts, true);
473
474		if (config.onsuccess)
475		{
476			config.onsuccess(result);
477		}
478
479		BX.onCustomEvent(config.xhr, 'onAjaxSuccess', [result, config]);
480
481		BX.ajax.processScripts(config.scripts, false, cb);
482	}
483	catch (e)
484	{
485		if (config.onfailure)
486			config.onfailure("processing", e);
487		BX.onCustomEvent(config.xhr, 'onAjaxFailure', ['processing', e, config]);
488	}
489};
490
491BX.ajax.processScripts = function(scripts, bRunFirst, cb)
492{
493	var scriptsExt = [], scriptsInt = '';
494
495	cb = cb || BX.DoNothing;
496
497	for (var i = 0, length = scripts.length; i < length; i++)
498	{
499		if (typeof bRunFirst != 'undefined' && bRunFirst != !!scripts[i].bRunFirst)
500			continue;
501
502		if (scripts[i].isInternal)
503			scriptsInt += ';' + scripts[i].JS;
504		else
505			scriptsExt.push(scripts[i].JS);
506	}
507
508	scriptsExt = BX.util.array_unique(scriptsExt);
509	var inlineScripts = scriptsInt.length > 0 ? function() { BX.evalGlobal(scriptsInt); } : BX.DoNothing;
510
511	if (scriptsExt.length > 0)
512	{
513		BX.load(scriptsExt, function() {
514			inlineScripts();
515			cb();
516		});
517	}
518	else
519	{
520		inlineScripts();
521		cb();
522	}
523};
524
525// TODO: extend this function to use with any data objects or forms
526BX.ajax.prepareData = function(arData, prefix)
527{
528	var data = '';
529	if (BX.type.isString(arData))
530		data = arData;
531	else if (null != arData)
532	{
533		for(var i in arData)
534		{
535			if (arData.hasOwnProperty(i))
536			{
537				if (data.length > 0)
538					data += '&';
539				var name = BX.util.urlencode(i);
540				if(prefix)
541					name = prefix + '[' + name + ']';
542				if(typeof arData[i] == 'object')
543					data += BX.ajax.prepareData(arData[i], name);
544				else
545					data += name + '=' + BX.util.urlencode(arData[i]);
546			}
547		}
548	}
549	return data;
550};
551
552BX.ajax.xhrSuccess = function(xhr)
553{
554	return (xhr.status >= 200 && xhr.status < 300) || xhr.status === 304 || xhr.status === 1223 || xhr.status === 0;
555};
556
557BX.ajax.Setup = function(config, bTemp)
558{
559	bTemp = !!bTemp;
560
561	for (var i in config)
562	{
563		if (bTemp)
564			tempDefaultConfig[i] = config[i];
565		else
566			defaultConfig[i] = config[i];
567	}
568};
569
570BX.ajax.replaceLocalStorageValue = function(lsId, data, ttl)
571{
572	if (!!BX.localStorage)
573		BX.localStorage.set('ajax-' + lsId, data, ttl);
574};
575
576
577BX.ajax._uncache = function(url)
578{
579	return url + ((url.indexOf('?') !== -1 ? "&" : "?") + '_=' + (new Date()).getTime());
580};
581
582/* simple interface */
583BX.ajax.get = function(url, data, callback)
584{
585	if (BX.type.isFunction(data))
586	{
587		callback = data;
588		data = '';
589	}
590
591	data = BX.ajax.prepareData(data);
592
593	if (data)
594	{
595		url += (url.indexOf('?') !== -1 ? "&" : "?") + data;
596		data = '';
597	}
598
599	return BX.ajax({
600		'method': 'GET',
601		'dataType': 'html',
602		'url': url,
603		'data':  '',
604		'onsuccess': callback
605	});
606};
607
608BX.ajax.getCaptcha = function(callback)
609{
610	return BX.ajax.loadJSON('/bitrix/tools/ajax_captcha.php', callback);
611};
612
613BX.ajax.insertToNode = function(url, node)
614{
615	node = BX(node);
616	if (!!node)
617	{
618		var eventArgs = { cancel: false };
619		BX.onCustomEvent('onAjaxInsertToNode', [{ url: url, node: node, eventArgs: eventArgs }]);
620		if(eventArgs.cancel === true)
621		{
622			return;
623		}
624
625		var show = null;
626		if (!tempDefaultConfig.denyShowWait)
627		{
628			show = BX.showWait(node);
629			delete tempDefaultConfig.denyShowWait;
630		}
631
632		return BX.ajax.get(url, function(data) {
633			node.innerHTML = data;
634			BX.closeWait(node, show);
635		});
636	}
637};
638
639BX.ajax.post = function(url, data, callback)
640{
641	data = BX.ajax.prepareData(data);
642
643	return BX.ajax({
644		'method': 'POST',
645		'dataType': 'html',
646		'url': url,
647		'data':  data,
648		'onsuccess': callback
649	});
650};
651
652/**
653 * BX.ajax with BX.Promise
654 * 
655 * @param config
656 * @returns {BX.Promise|false}
657 */
658BX.ajax.promise = function(config)	
659{
660	var result = new BX.Promise();
661	
662	config.onsuccess = function(data)
663	{
664		result.fulfill(data);
665	};
666	config.onfailure = function(reason, data)
667	{
668		result.reject({
669			reason: reason, 
670			data: data
671		});
672	};
673	config.onprogress = function(data) 
674	{
675		if (data.position == 0 && data.totalSize == 0)
676		{
677			result.reject({
678				reason: 'progress', 
679				data: data
680			});
681		}
682	};
683	
684	var xhr = BX.ajax(config);
685	if (!xhr)
686	{
687		result.reject({
688			reason: "init",
689			data: false
690		});
691	}
692	
693	return result;
694};
695
696/* load and execute external file script with onload emulation */
697BX.ajax.loadScriptAjax = function(script_src, callback, bPreload)
698{
699	if (BX.type.isArray(script_src))
700	{
701		for (var i=0,len=script_src.length;i<len;i++)
702		{
703			BX.ajax.loadScriptAjax(script_src[i], callback, bPreload);
704		}
705	}
706	else
707	{
708		var script_src_test = script_src.replace(/\.js\?.*/, '.js');
709
710		if (r.script_self.test(script_src_test)) return;
711		if (r.script_self_window.test(script_src_test) && BX.CWindow) return;
712		if (r.script_self_admin.test(script_src_test) && BX.admin) return;
713
714		if (typeof loadedScripts[script_src_test] == 'undefined')
715		{
716			if (!!bPreload)
717			{
718				loadedScripts[script_src_test] = '';
719				return BX.loadScript(script_src);
720			}
721			else
722			{
723				return BX.ajax({
724					url: script_src,
725					method: 'GET',
726					dataType: 'script',
727					processData: true,
728					emulateOnload: false,
729					scriptsRunFirst: true,
730					async: false,
731					start: true,
732					onsuccess: function(result) {
733						loadedScripts[script_src_test] = result;
734						if (callback)
735							callback(result);
736					}
737				});
738			}
739		}
740		else if (callback)
741		{
742			callback(loadedScripts[script_src_test]);
743		}
744	}
745};
746
747/* non-xhr loadings */
748BX.ajax.loadJSON = function(url, data, callback, callback_failure)
749{
750	if (BX.type.isFunction(data))
751	{
752		callback_failure = callback;
753		callback = data;
754		data = '';
755	}
756
757	data = BX.ajax.prepareData(data);
758
759	if (data)
760	{
761		url += (url.indexOf('?') !== -1 ? "&" : "?") + data;
762		data = '';
763	}
764
765	return BX.ajax({
766		'method': 'GET',
767		'dataType': 'json',
768		'url': url,
769		'onsuccess': callback,
770		'onfailure': callback_failure
771	});
772};
773
774/*
775arObs = [{
776	url: url,
777	type: html|script|json|css,
778	callback: function
779}]
780*/
781BX.ajax.load = function(arObs, callback)
782{
783	if (!BX.type.isArray(arObs))
784		arObs = [arObs];
785
786	var cnt = 0;
787
788	if (!BX.type.isFunction(callback))
789		callback = BX.DoNothing;
790
791	var handler = function(data)
792		{
793			if (BX.type.isFunction(this.callback))
794				this.callback(data);
795
796			if (++cnt >= len)
797				callback();
798		};
799
800	for (var i = 0, len = arObs.length; i<len; i++)
801	{
802		switch(arObs[i].type.toUpperCase())
803		{
804			case 'SCRIPT':
805				BX.loadScript([arObs[i].url], BX.proxy(handler, arObs[i]));
806			break;
807			case 'CSS':
808				BX.loadCSS([arObs[i].url]);
809
810				if (++cnt >= len)
811					callback();
812			break;
813			case 'JSON':
814				BX.ajax.loadJSON(arObs[i].url, BX.proxy(handler, arObs[i]));
815			break;
816
817			default:
818				BX.ajax.get(arObs[i].url, '', BX.proxy(handler, arObs[i]));
819			break;
820		}
821	}
822};
823
824/* ajax form sending */
825BX.ajax.submit = function(obForm, callback)
826{
827	if (!obForm.target)
828	{
829		if (null == obForm.BXFormTarget)
830		{
831			var frame_name = 'formTarget_' + Math.random();
832			obForm.BXFormTarget = document.body.appendChild(BX.create('IFRAME', {
833				props: {
834					name: frame_name,
835					id: frame_name,
836					src: 'javascript:void(0)'
837				},
838				style: {
839					display: 'none'
840				}
841			}));
842		}
843
844		obForm.target = obForm.BXFormTarget.name;
845	}
846
847	obForm.BXFormCallback = callback;
848	BX.bind(obForm.BXFormTarget, 'load', BX.proxy(BX.ajax._submit_callback, obForm));
849
850	BX.submit(obForm);
851
852	return false;
853};
854
855BX.ajax.submitComponentForm = function(obForm, container, bWait)
856{
857	if (!obForm.target)
858	{
859		if (null == obForm.BXFormTarget)
860		{
861			var frame_name = 'formTarget_' + Math.random();
862			obForm.BXFormTarget = document.body.appendChild(BX.create('IFRAME', {
863				props: {
864					name: frame_name,
865					id: frame_name,
866					src: 'javascript:void(0)'
867				},
868				style: {
869					display: 'none'
870				}
871			}));
872		}
873
874		obForm.target = obForm.BXFormTarget.name;
875	}
876
877	if (!!bWait)
878		var w = BX.showWait(container);
879
880	obForm.BXFormCallback = function(d) {
881		if (!!bWait)
882			BX.closeWait(w);
883
884		var callOnload = function(){
885			if(!!window.bxcompajaxframeonload)
886			{
887				setTimeout(function(){window.bxcompajaxframeonload();window.bxcompajaxframeonload=null;}, 10);
888			}
889		};
890
891		BX(container).innerHTML = d;
892		BX.onCustomEvent('onAjaxSuccess', [null,null,callOnload]);
893	};
894
895	BX.bind(obForm.BXFormTarget, 'load', BX.proxy(BX.ajax._submit_callback, obForm));
896
897	return true;
898};
899
900// func will be executed in form context
901BX.ajax._submit_callback = function()
902{
903	//opera and IE8 triggers onload event even on empty iframe
904	try
905	{
906		if(this.BXFormTarget.contentWindow.location.href.indexOf('http') != 0)
907			return;
908	} catch (e) {
909		return;
910	}
911
912	if (this.BXFormCallback)
913		this.BXFormCallback.apply(this, [this.BXFormTarget.contentWindow.document.body.innerHTML]);
914
915	BX.unbindAll(this.BXFormTarget);
916};
917
918BX.ajax.prepareForm = function(obForm, data)
919{
920	data = (!!data ? data : {});
921	var i, ii, el,
922		_data = [],
923		n = obForm.elements.length,
924		files = 0, length = 0;
925	if(!!obForm)
926	{
927		for (i = 0; i < n; i++)
928		{
929			el = obForm.elements[i];
930			if (el.disabled)
931				continue;
932
933			if(!el.type)
934				continue;
935
936			switch(el.type.toLowerCase())
937			{
938				case 'text':
939				case 'textarea':
940				case 'password':
941				case 'number':
942				case 'hidden':
943				case 'select-one':
944					_data.push({name: el.name, value: el.value});
945					length += (el.name.length + el.value.length);
946					break;
947				case 'file':
948					if (!!el.files)
949					{
950						for (ii = 0; ii < el.files.length; ii++)
951						{
952							files++;
953							_data.push({name: el.name, value: el.files[ii], file : true});
954							length += el.files[ii].size;
955						}
956					}
957					break;
958				case 'radio':
959				case 'checkbox':
960					if(el.checked)
961					{
962						_data.push({name: el.name, value: el.value});
963						length += (el.name.length + el.value.length);
964					}
965					break;
966				case 'select-multiple':
967					for (var j = 0; j < el.options.length; j++)
968					{
969						if (el.options[j].selected)
970						{
971							_data.push({name : el.name, value : el.options[j].value});
972							length += (el.name.length + el.options[j].length);
973						}
974					}
975					break;
976				default:
977					break;
978			}
979		}
980
981		i = 0; length = 0;
982		var current = data, name, rest, pp;
983
984		while(i < _data.length)
985		{
986			var p = _data[i].name.indexOf('[');
987			if (p == -1) {
988				current[_data[i].name] = _data[i].value;
989				current = data;
990				i++;
991			}
992			else
993			{
994				name = _data[i].name.substring(0, p);
995				rest = _data[i].name.substring(p+1);
996				pp = rest.indexOf(']');
997
998				if(pp == -1)
999				{
1000					if (!current[name])
1001						current[name] = [];
1002					current = data;
1003					i++;
1004				}
1005				else if(pp == 0)
1006				{
1007					if (!current[name])
1008						current[name] = [];
1009					//No index specified - so take the next integer
1010					current = current[name];
1011					_data[i].name = '' + current.length;
1012				}
1013				else
1014				{
1015					if (!current[name])
1016						current[name] = {};
1017					//Now index name becomes and name and we go deeper into the array
1018					current = current[name];
1019					_data[i].name = rest.substring(0, pp) + rest.substring(pp+1);
1020				}
1021			}
1022		}
1023	}
1024	return {data : data, filesCount : files, roughSize : length};
1025};
1026BX.ajax.submitAjax = function(obForm, config)
1027{
1028	config = (config !== null && typeof config == "object" ? config : {});
1029	config.url = (config["url"] || obForm.getAttribute("action"));
1030
1031	var additionalData = (config["data"] || {});
1032	config.data = BX.ajax.prepareForm(obForm).data;
1033	for (var ii in additionalData)
1034	{
1035		if (additionalData.hasOwnProperty(ii))
1036		{
1037			config.data[ii] = additionalData[ii];
1038		}
1039	}
1040
1041	if (!window["FormData"])
1042	{
1043		BX.ajax(config);
1044	}
1045	else
1046	{
1047		var isFile = function(item)
1048		{
1049			var res = Object.prototype.toString.call(item);
1050			return (res == '[object File]' || res == '[object Blob]');
1051		},
1052		appendToForm = function(fd, key, val)
1053		{
1054			if (!!val && typeof val == "object" && !isFile(val))
1055			{
1056				for (var ii in val)
1057				{
1058					if (val.hasOwnProperty(ii))
1059					{
1060						appendToForm(fd, (key == '' ? ii : key + '[' + ii + ']'), val[ii]);
1061					}
1062				}
1063			}
1064			else
1065				fd.append(key, (!!val ? val : ''));
1066		},
1067		prepareData = function(arData)
1068		{
1069			var data = {};
1070			if (null != arData)
1071			{
1072				if(typeof arData == 'object')
1073				{
1074					for(var i in arData)
1075					{
1076						if (arData.hasOwnProperty(i))
1077						{
1078							var name = BX.util.urlencode(i);
1079							if(typeof arData[i] == 'object' && arData[i]["file"] !== true)
1080								data[name] = prepareData(arData[i]);
1081							else if (arData[i]["file"] === true)
1082								data[name] = arData[i]["value"];
1083							else
1084								data[name] = BX.util.urlencode(arData[i]);
1085						}
1086					}
1087				}
1088				else
1089					data = BX.util.urlencode(arData);
1090			}
1091			return data;
1092		},
1093		fd = new window.FormData();
1094
1095		if (config.method !== 'POST')
1096		{
1097			config.data = BX.ajax.prepareData(config.data);
1098			if (config.data)
1099			{
1100				config.url += (config.url.indexOf('?') !== -1 ? "&" : "?") + config.data;
1101				config.data = '';
1102			}
1103		}
1104		else
1105		{
1106			if (config.preparePost === true)
1107				config.data = prepareData(config.data);
1108			appendToForm(fd, '', config.data);
1109			config.data = fd;
1110		}
1111
1112		config.preparePost = false;
1113		config.start = false;
1114
1115		var xhr = BX.ajax(config);
1116		if (!!config["onprogress"])
1117			xhr.upload.addEventListener(
1118				'progress',
1119				function(e){
1120					var percent = null;
1121					if(e.lengthComputable && (e.total || e["totalSize"])) {
1122						percent = e.loaded * 100 / (e.total || e["totalSize"]);
1123					}
1124					config["onprogress"](e, percent);
1125				}
1126			);
1127		xhr.send(fd);
1128	}
1129};
1130
1131BX.ajax.UpdatePageData = function (arData)
1132{
1133	if (arData.TITLE)
1134		BX.ajax.UpdatePageTitle(arData.TITLE);
1135	if (arData.WINDOW_TITLE || arData.TITLE)
1136		BX.ajax.UpdateWindowTitle(arData.WINDOW_TITLE || arData.TITLE);
1137	if (arData.NAV_CHAIN)
1138		BX.ajax.UpdatePageNavChain(arData.NAV_CHAIN);
1139	if (arData.CSS && arData.CSS.length > 0)
1140		BX.loadCSS(arData.CSS);
1141	if (arData.SCRIPTS && arData.SCRIPTS.length > 0)
1142	{
1143		var f = function(result,config,cb){
1144
1145			if(!!config && BX.type.isArray(config.scripts))
1146			{
1147				for(var i=0,l=arData.SCRIPTS.length;i<l;i++)
1148				{
1149					config.scripts.push({isInternal:false,JS:arData.SCRIPTS[i]});
1150				}
1151			}
1152			else
1153			{
1154				BX.loadScript(arData.SCRIPTS,cb);
1155			}
1156
1157			BX.removeCustomEvent('onAjaxSuccess',f);
1158		};
1159		BX.addCustomEvent('onAjaxSuccess',f);
1160	}
1161	else
1162	{
1163		var f1 = function(result,config,cb){
1164			if(BX.type.isFunction(cb))
1165			{
1166				cb();
1167			}
1168			BX.removeCustomEvent('onAjaxSuccess',f1);
1169		};
1170		BX.addCustomEvent('onAjaxSuccess', f1);
1171	}
1172};
1173
1174BX.ajax.UpdatePageTitle = function(title)
1175{
1176	var obTitle = BX('pagetitle');
1177	if (obTitle)
1178	{
1179		obTitle.removeChild(obTitle.firstChild);
1180		if (!obTitle.firstChild)
1181			obTitle.appendChild(document.createTextNode(title));
1182		else
1183			obTitle.insertBefore(document.createTextNode(title), obTitle.firstChild);
1184	}
1185};
1186
1187BX.ajax.UpdateWindowTitle = function(title)
1188{
1189	document.title = title;
1190};
1191
1192BX.ajax.UpdatePageNavChain = function(nav_chain)
1193{
1194	var obNavChain = BX('navigation');
1195	if (obNavChain)
1196	{
1197		obNavChain.innerHTML = nav_chain;
1198	}
1199};
1200
1201/* user options handling */
1202BX.userOptions = {
1203	options: null,
1204	bSend: false,
1205	delay: 5000,
1206	path: '/bitrix/admin/user_options.php?'
1207};
1208
1209BX.userOptions.setAjaxPath = function(url)
1210{
1211	BX.userOptions.path = url.indexOf('?') == -1? url+'?': url+'&';
1212}
1213BX.userOptions.save = function(sCategory, sName, sValName, sVal, bCommon)
1214{
1215	if (null == BX.userOptions.options)
1216		BX.userOptions.options = {};
1217
1218	bCommon = !!bCommon;
1219	BX.userOptions.options[sCategory+'.'+sName+'.'+sValName] = [sCategory, sName, sValName, sVal, bCommon];
1220
1221	var sParam = BX.userOptions.__get();
1222	if (sParam != '')
1223		document.cookie = BX.message('COOKIE_PREFIX')+"_LAST_SETTINGS=" + encodeURIComponent(sParam) + "&sessid="+BX.bitrix_sessid()+"; expires=Thu, 31 Dec 2020 23:59:59 GMT; path=/;";
1224
1225	if(!BX.userOptions.bSend)
1226	{
1227		BX.userOptions.bSend = true;
1228		setTimeout(function(){BX.userOptions.send(null)}, BX.userOptions.delay);
1229	}
1230};
1231
1232BX.userOptions.send = function(callback)
1233{
1234	var sParam = BX.userOptions.__get();
1235	BX.userOptions.options = null;
1236	BX.userOptions.bSend = false;
1237
1238	if (sParam != '')
1239	{
1240		document.cookie = BX.message('COOKIE_PREFIX') + "_LAST_SETTINGS=; path=/;";
1241		BX.ajax({
1242			'method': 'GET',
1243			'dataType': 'html',
1244			'processData': false,
1245			'cache': false,
1246			'url': BX.userOptions.path+sParam+'&sessid='+BX.bitrix_sessid(),
1247			'onsuccess': callback
1248		});
1249	}
1250};
1251
1252BX.userOptions.del = function(sCategory, sName, bCommon, callback)
1253{
1254	BX.ajax.get(BX.userOptions.path+'action=delete&c='+sCategory+'&n='+sName+(bCommon == true? '&common=Y':'')+'&sessid='+BX.bitrix_sessid(), callback);
1255};
1256
1257BX.userOptions.__get = function()
1258{
1259	if (!BX.userOptions.options) return '';
1260
1261	var sParam = '', n = -1, prevParam = '', aOpt, i;
1262
1263	for (i in BX.userOptions.options)
1264	{
1265		if(BX.userOptions.options.hasOwnProperty(i))
1266		{
1267			aOpt = BX.userOptions.options[i];
1268
1269			if (prevParam != aOpt[0]+'.'+aOpt[1])
1270			{
1271				n++;
1272				sParam += '&p['+n+'][c]='+BX.util.urlencode(aOpt[0]);
1273				sParam += '&p['+n+'][n]='+BX.util.urlencode(aOpt[1]);
1274				if (aOpt[4] == true)
1275					sParam += '&p['+n+'][d]=Y';
1276				prevParam = aOpt[0]+'.'+aOpt[1];
1277			}
1278
1279			sParam += '&p['+n+'][v]['+BX.util.urlencode(aOpt[2])+']='+BX.util.urlencode(aOpt[3]);
1280		}
1281	}
1282
1283	return sParam.substr(1);
1284};
1285
1286BX.ajax.history = {
1287	expected_hash: '',
1288
1289	obParams: null,
1290
1291	obFrame: null,
1292	obImage: null,
1293
1294	obTimer: null,
1295
1296	bInited: false,
1297	bHashCollision: false,
1298	bPushState: !!(history.pushState && BX.type.isFunction(history.pushState)),
1299
1300	startState: null,
1301
1302	init: function(obParams)
1303	{
1304		if (BX.ajax.history.bInited)
1305			return;
1306
1307		this.obParams = obParams;
1308		var obCurrentState = this.obParams.getState();
1309
1310		if (BX.ajax.history.bPushState)
1311		{
1312			BX.ajax.history.expected_hash = window.location.pathname;
1313			if (window.location.search)
1314				BX.ajax.history.expected_hash += window.location.search;
1315
1316			BX.ajax.history.put(obCurrentState, BX.ajax.history.expected_hash, '', true);
1317			// due to some strange thing, chrome calls popstate event on page start. so we should delay it
1318			setTimeout(function(){BX.bind(window, 'popstate', BX.ajax.history.__hashListener);}, 500);
1319		}
1320		else
1321		{
1322			BX.ajax.history.expected_hash = window.location.hash;
1323
1324			if (!BX.ajax.history.expected_hash || BX.ajax.history.expected_hash == '#')
1325				BX.ajax.history.expected_hash = '__bx_no_hash__';
1326
1327			jsAjaxHistoryContainer.put(BX.ajax.history.expected_hash, obCurrentState);
1328			BX.ajax.history.obTimer = setTimeout(BX.ajax.history.__hashListener, 500);
1329
1330			if (BX.browser.IsIE())
1331			{
1332				BX.ajax.history.obFrame = document.createElement('IFRAME');
1333				BX.hide_object(BX.ajax.history.obFrame);
1334
1335				document.body.appendChild(BX.ajax.history.obFrame);
1336
1337				BX.ajax.history.obFrame.contentWindow.document.open();
1338				BX.ajax.history.obFrame.contentWindow.document.write(BX.ajax.history.expected_hash);
1339				BX.ajax.history.obFrame.contentWindow.document.close();
1340			}
1341			else if (BX.browser.IsOpera())
1342			{
1343				BX.ajax.history.obImage = document.createElement('IMG');
1344				BX.hide_object(BX.ajax.history.obImage);
1345
1346				document.body.appendChild(BX.ajax.history.obImage);
1347
1348				BX.ajax.history.obImage.setAttribute('src', 'javascript:location.href = \'javascript:BX.ajax.history.__hashListener();\';');
1349			}
1350		}
1351
1352		BX.ajax.history.bInited = true;
1353	},
1354
1355	__hashListener: function(e)
1356	{
1357		e = e || window.event || {state:false};
1358
1359		if (BX.ajax.history.bPushState)
1360		{
1361			BX.ajax.history.obParams.setState(e.state||BX.ajax.history.startState);
1362		}
1363		else
1364		{
1365			if (BX.ajax.history.obTimer)
1366			{
1367				window.clearTimeout(BX.ajax.history.obTimer);
1368				BX.ajax.history.obTimer = null;
1369			}
1370
1371			var current_hash;
1372			if (null != BX.ajax.history.obFrame)
1373				current_hash = BX.ajax.history.obFrame.contentWindow.document.body.innerText;
1374			else
1375				current_hash = window.location.hash;
1376
1377			if (!current_hash || current_hash == '#')
1378				current_hash = '__bx_no_hash__';
1379
1380			if (current_hash.indexOf('#') == 0)
1381				current_hash = current_hash.substring(1);
1382
1383			if (current_hash != BX.ajax.history.expected_hash)
1384			{
1385				var state = jsAjaxHistoryContainer.get(current_hash);
1386				if (state)
1387				{
1388					BX.ajax.history.obParams.setState(state);
1389
1390					BX.ajax.history.expected_hash = current_hash;
1391					if (null != BX.ajax.history.obFrame)
1392					{
1393						var __hash = current_hash == '__bx_no_hash__' ? '' : current_hash;
1394						if (window.location.hash != __hash && window.location.hash != '#' + __hash)
1395							window.location.hash = __hash;
1396					}
1397				}
1398			}
1399
1400			BX.ajax.history.obTimer = setTimeout(BX.ajax.history.__hashListener, 500);
1401		}
1402	},
1403
1404	put: function(state, new_hash, new_hash1, bStartState)
1405	{
1406		if (this.bPushState)
1407		{
1408			if(!bStartState)
1409			{
1410				history.pushState(state, '', new_hash);
1411			}
1412			else
1413			{
1414				BX.ajax.history.startState = state;
1415			}
1416		}
1417		else
1418		{
1419			if (typeof new_hash1 != 'undefined')
1420				new_hash = new_hash1;
1421			else
1422				new_hash = 'view' + new_hash;
1423
1424			jsAjaxHistoryContainer.put(new_hash, state);
1425			BX.ajax.history.expected_hash = new_hash;
1426
1427			window.location.hash = BX.util.urlencode(new_hash);
1428
1429			if (null != BX.ajax.history.obFrame)
1430			{
1431				BX.ajax.history.obFrame.contentWindow.document.open();
1432				BX.ajax.history.obFrame.contentWindow.document.write(new_hash);
1433				BX.ajax.history.obFrame.contentWindow.document.close();
1434			}
1435		}
1436	},
1437
1438	checkRedirectStart: function(param_name, param_value)
1439	{
1440		var current_hash = window.location.hash;
1441		if (current_hash.substring(0, 1) == '#') current_hash = current_hash.substring(1);
1442
1443		var test = current_hash.substring(0, 5);
1444		if (test == 'view/' || test == 'view%')
1445		{
1446			BX.ajax.history.bHashCollision = true;
1447			document.write('<' + 'div id="__ajax_hash_collision_' + param_value + '" style="display: none;">');
1448		}
1449	},
1450
1451	checkRedirectFinish: function(param_name, param_value)
1452	{
1453		document.write('</div>');
1454
1455		var current_hash = window.location.hash;
1456		if (current_hash.substring(0, 1) == '#') current_hash = current_hash.substring(1);
1457
1458		BX.ready(function ()
1459		{
1460			var test = current_hash.substring(0, 5);
1461			if (test == 'view/' || test == 'view%')
1462			{
1463				var obColNode = BX('__ajax_hash_collision_' + param_value);
1464				var obNode = obColNode.firstChild;
1465				BX.cleanNode(obNode);
1466				obColNode.style.display = 'block';
1467
1468				// IE, Opera and Chrome automatically modifies hash with urlencode, but FF doesn't ;-(
1469				if (test != 'view%')
1470					current_hash = BX.util.urlencode(current_hash);
1471
1472				current_hash += (current_hash.indexOf('%3F') == -1 ? '%3F' : '%26') + param_name + '=' + param_value;
1473
1474				var url = '/bitrix/tools/ajax_redirector.php?hash=' + current_hash;
1475
1476				BX.ajax.insertToNode(url, obNode);
1477			}
1478		});
1479	}
1480};
1481
1482BX.ajax.component = function(node)
1483{
1484	this.node = node;
1485};
1486
1487BX.ajax.component.prototype.getState = function()
1488{
1489	var state = {
1490		'node': this.node,
1491		'title': window.document.title,
1492		'data': BX(this.node).innerHTML
1493	};
1494
1495	var obNavChain = BX('navigation');
1496	if (null != obNavChain)
1497		state.nav_chain = obNavChain.innerHTML;
1498
1499	BX.onCustomEvent(BX(state.node), "onComponentAjaxHistoryGetState", [state]);
1500
1501	return state;
1502};
1503
1504BX.ajax.component.prototype.setState = function(state)
1505{
1506	BX(state.node).innerHTML = state.data;
1507	BX.ajax.UpdatePageTitle(state.title);
1508
1509	if (state.nav_chain)
1510	{
1511		BX.ajax.UpdatePageNavChain(state.nav_chain);
1512	}
1513
1514	BX.onCustomEvent(BX(state.node), "onComponentAjaxHistorySetState", [state]);
1515};
1516
1517var jsAjaxHistoryContainer = {
1518	arHistory: {},
1519
1520	put: function(hash, state)
1521	{
1522		this.arHistory[hash] = state;
1523	},
1524
1525	get: function(hash)
1526	{
1527		return this.arHistory[hash];
1528	}
1529};
1530
1531
1532BX.ajax.FormData = function()
1533{
1534	this.elements = [];
1535	this.files = [];
1536	this.features = {};
1537	this.isSupported();
1538	this.log('BX FormData init');
1539};
1540
1541BX.ajax.FormData.isSupported = function()
1542{
1543	var f = new BX.ajax.FormData();
1544	var result = f.features.supported;
1545	f = null;
1546	return result;
1547};
1548
1549BX.ajax.FormData.prototype.log = function(o)
1550{
1551	if (false) {
1552		try {
1553			if (BX.browser.IsIE()) o = JSON.stringify(o);
1554			console.log(o);
1555		} catch(e) {}
1556	}
1557};
1558
1559BX.ajax.FormData.prototype.isSupported = function()
1560{
1561	var f = {};
1562	f.fileReader = (window.FileReader && window.FileReader.prototype.readAsBinaryString);
1563	f.readFormData = f.sendFormData = !!(window.FormData);
1564	f.supported = !!(f.readFormData && f.sendFormData);
1565	this.features = f;
1566	this.log('features:');
1567	this.log(f);
1568
1569	return f.supported;
1570};
1571
1572BX.ajax.FormData.prototype.append = function(name, value)
1573{
1574	if (typeof(value) === 'object') { // seems to be files element
1575		this.files.push({'name': name, 'value':value});
1576	} else {
1577		this.elements.push({'name': name, 'value':value});
1578	}
1579};
1580
1581BX.ajax.FormData.prototype.send = function(url, callbackOk, callbackProgress, callbackError)
1582{
1583	this.log('FD send');
1584	this.xhr = BX.ajax({
1585			'method': 'POST',
1586			'dataType': 'html',
1587			'url': url,
1588			'onsuccess': callbackOk,
1589			'onfailure': callbackError,
1590			'start': false,
1591			'preparePost':false
1592		});
1593
1594	if (callbackProgress)
1595	{
1596		this.xhr.upload.addEventListener(
1597			'progress',
1598			function(e) {
1599				if (e.lengthComputable)
1600					callbackProgress(e.loaded / (e.total || e.totalSize));
1601			},
1602			false
1603		);
1604	}
1605
1606	if (this.features.readFormData && this.features.sendFormData)
1607	{
1608		var fd = new FormData();
1609		this.log('use browser formdata');
1610		for (var i in this.elements)
1611		{
1612			if(this.elements.hasOwnProperty(i))
1613				fd.append(this.elements[i].name,this.elements[i].value);
1614		}
1615		for (i in this.files)
1616		{
1617			if(this.files.hasOwnProperty(i))
1618				fd.append(this.files[i].name, this.files[i].value);
1619		}
1620		this.xhr.send(fd);
1621	}
1622
1623	return this.xhr;
1624};
1625
1626BX.addCustomEvent('onAjaxFailure', BX.debug);
1627})(window);
1628

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.