PageSourceSearch

https://akgs.biz/bitrix/js/main/core/core_ajax.js?177320554935278

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