PageSourceSearch

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

js geocad.ru collected 2026-10-02 19:24:58 UTC 35,602 bytes, 1,575 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/* load and execute external file script with onload emulation */
653BX.ajax.loadScriptAjax = function(script_src, callback, bPreload)
654{
655	if (BX.type.isArray(script_src))
656	{
657		for (var i=0,len=script_src.length;i<len;i++)
658		{
659			BX.ajax.loadScriptAjax(script_src[i], callback, bPreload);
660		}
661	}
662	else
663	{
664		var script_src_test = script_src.replace(/\.js\?.*/, '.js');
665
666		if (r.script_self.test(script_src_test)) return;
667		if (r.script_self_window.test(script_src_test) && BX.CWindow) return;
668		if (r.script_self_admin.test(script_src_test) && BX.admin) return;
669
670		if (typeof loadedScripts[script_src_test] == 'undefined')
671		{
672			if (!!bPreload)
673			{
674				loadedScripts[script_src_test] = '';
675				return BX.loadScript(script_src);
676			}
677			else
678			{
679				return BX.ajax({
680					url: script_src,
681					method: 'GET',
682					dataType: 'script',
683					processData: true,
684					emulateOnload: false,
685					scriptsRunFirst: true,
686					async: false,
687					start: true,
688					onsuccess: function(result) {
689						loadedScripts[script_src_test] = result;
690						if (callback)
691							callback(result);
692					}
693				});
694			}
695		}
696		else if (callback)
697		{
698			callback(loadedScripts[script_src_test]);
699		}
700	}
701};
702
703/* non-xhr loadings */
704BX.ajax.loadJSON = function(url, data, callback, callback_failure)
705{
706	if (BX.type.isFunction(data))
707	{
708		callback_failure = callback;
709		callback = data;
710		data = '';
711	}
712
713	data = BX.ajax.prepareData(data);
714
715	if (data)
716	{
717		url += (url.indexOf('?') !== -1 ? "&" : "?") + data;
718		data = '';
719	}
720
721	return BX.ajax({
722		'method': 'GET',
723		'dataType': 'json',
724		'url': url,
725		'onsuccess': callback,
726		'onfailure': callback_failure
727	});
728};
729
730/*
731arObs = [{
732	url: url,
733	type: html|script|json|css,
734	callback: function
735}]
736*/
737BX.ajax.load = function(arObs, callback)
738{
739	if (!BX.type.isArray(arObs))
740		arObs = [arObs];
741
742	var cnt = 0;
743
744	if (!BX.type.isFunction(callback))
745		callback = BX.DoNothing;
746
747	var handler = function(data)
748		{
749			if (BX.type.isFunction(this.callback))
750				this.callback(data);
751
752			if (++cnt >= len)
753				callback();
754		};
755
756	for (var i = 0, len = arObs.length; i<len; i++)
757	{
758		switch(arObs[i].type.toUpperCase())
759		{
760			case 'SCRIPT':
761				BX.loadScript([arObs[i].url], BX.proxy(handler, arObs[i]));
762			break;
763			case 'CSS':
764				BX.loadCSS([arObs[i].url]);
765
766				if (++cnt >= len)
767					callback();
768			break;
769			case 'JSON':
770				BX.ajax.loadJSON(arObs[i].url, BX.proxy(handler, arObs[i]));
771			break;
772
773			default:
774				BX.ajax.get(arObs[i].url, '', BX.proxy(handler, arObs[i]));
775			break;
776		}
777	}
778};
779
780/* ajax form sending */
781BX.ajax.submit = function(obForm, callback)
782{
783	if (!obForm.target)
784	{
785		if (null == obForm.BXFormTarget)
786		{
787			var frame_name = 'formTarget_' + Math.random();
788			obForm.BXFormTarget = document.body.appendChild(BX.create('IFRAME', {
789				props: {
790					name: frame_name,
791					id: frame_name,
792					src: 'javascript:void(0)'
793				},
794				style: {
795					display: 'none'
796				}
797			}));
798		}
799
800		obForm.target = obForm.BXFormTarget.name;
801	}
802
803	obForm.BXFormCallback = callback;
804	BX.bind(obForm.BXFormTarget, 'load', BX.proxy(BX.ajax._submit_callback, obForm));
805
806	BX.submit(obForm);
807
808	return false;
809};
810
811BX.ajax.submitComponentForm = function(obForm, container, bWait)
812{
813	if (!obForm.target)
814	{
815		if (null == obForm.BXFormTarget)
816		{
817			var frame_name = 'formTarget_' + Math.random();
818			obForm.BXFormTarget = document.body.appendChild(BX.create('IFRAME', {
819				props: {
820					name: frame_name,
821					id: frame_name,
822					src: 'javascript:void(0)'
823				},
824				style: {
825					display: 'none'
826				}
827			}));
828		}
829
830		obForm.target = obForm.BXFormTarget.name;
831	}
832
833	if (!!bWait)
834		var w = BX.showWait(container);
835
836	obForm.BXFormCallback = function(d) {
837		if (!!bWait)
838			BX.closeWait(w);
839
840		var callOnload = function(){
841			if(!!window.bxcompajaxframeonload)
842			{
843				setTimeout(function(){window.bxcompajaxframeonload();window.bxcompajaxframeonload=null;}, 10);
844			}
845		};
846
847		BX(container).innerHTML = d;
848		BX.onCustomEvent('onAjaxSuccess', [null,null,callOnload]);
849	};
850
851	BX.bind(obForm.BXFormTarget, 'load', BX.proxy(BX.ajax._submit_callback, obForm));
852
853	return true;
854};
855
856// func will be executed in form context
857BX.ajax._submit_callback = function()
858{
859	//opera and IE8 triggers onload event even on empty iframe
860	try
861	{
862		if(this.BXFormTarget.contentWindow.location.href.indexOf('http') != 0)
863			return;
864	} catch (e) {
865		return;
866	}
867
868	if (this.BXFormCallback)
869		this.BXFormCallback.apply(this, [this.BXFormTarget.contentWindow.document.body.innerHTML]);
870
871	BX.unbindAll(this.BXFormTarget);
872};
873
874BX.ajax.prepareForm = function(obForm, data)
875{
876	data = (!!data ? data : {});
877	var i, ii, el,
878		_data = [],
879		n = obForm.elements.length,
880		files = 0, length = 0;
881	if(!!obForm)
882	{
883		for (i = 0; i < n; i++)
884		{
885			el = obForm.elements[i];
886			if (el.disabled)
887				continue;
888
889			if(!el.type)
890				continue;
891
892			switch(el.type.toLowerCase())
893			{
894				case 'text':
895				case 'textarea':
896				case 'password':
897				case 'number':
898				case 'hidden':
899				case 'select-one':
900					_data.push({name: el.name, value: el.value});
901					length += (el.name.length + el.value.length);
902					break;
903				case 'file':
904					if (!!el.files)
905					{
906						for (ii = 0; ii < el.files.length; ii++)
907						{
908							files++;
909							_data.push({name: el.name, value: el.files[ii], file : true});
910							length += el.files[ii].size;
911						}
912					}
913					break;
914				case 'radio':
915				case 'checkbox':
916					if(el.checked)
917					{
918						_data.push({name: el.name, value: el.value});
919						length += (el.name.length + el.value.length);
920					}
921					break;
922				case 'select-multiple':
923					for (var j = 0; j < el.options.length; j++)
924					{
925						if (el.options[j].selected)
926						{
927							_data.push({name : el.name, value : el.options[j].value});
928							length += (el.name.length + el.options[j].length);
929						}
930					}
931					break;
932				default:
933					break;
934			}
935		}
936
937		i = 0; length = 0;
938		var current = data, name, rest, pp;
939
940		while(i < _data.length)
941		{
942			var p = _data[i].name.indexOf('[');
943			if (p == -1) {
944				current[_data[i].name] = _data[i].value;
945				current = data;
946				i++;
947			}
948			else
949			{
950				name = _data[i].name.substring(0, p);
951				rest = _data[i].name.substring(p+1);
952				pp = rest.indexOf(']');
953
954				if(pp == -1)
955				{
956					if (!current[name])
957						current[name] = [];
958					current = data;
959					i++;
960				}
961				else if(pp == 0)
962				{
963					if (!current[name])
964						current[name] = [];
965					//No index specified - so take the next integer
966					current = current[name];
967					_data[i].name = '' + current.length;
968				}
969				else
970				{
971					if (!current[name])
972						current[name] = {};
973					//Now index name becomes and name and we go deeper into the array
974					current = current[name];
975					_data[i].name = rest.substring(0, pp) + rest.substring(pp+1);
976				}
977			}
978		}
979	}
980	return {data : data, filesCount : files, roughSize : length};
981};
982BX.ajax.submitAjax = function(obForm, config)
983{
984	config = (config !== null && typeof config == "object" ? config : {});
985	config.url = (config["url"] || obForm.getAttribute("action"));
986	config.data = BX.ajax.prepareForm(obForm).data;
987
988	if (!window["FormData"])
989	{
990		BX.ajax(config);
991	}
992	else
993	{
994		var isFile = function(item)
995		{
996			var res = Object.prototype.toString.call(item);
997			return (res == '[object File]' || res == '[object Blob]');
998		},
999		appendToForm = function(fd, key, val)
1000		{
1001			if (!!val && typeof val == "object" && !isFile(val))
1002			{
1003				for (var ii in val)
1004				{
1005					if (val.hasOwnProperty(ii))
1006					{
1007						appendToForm(fd, (key == '' ? ii : key + '[' + ii + ']'), val[ii]);
1008					}
1009				}
1010			}
1011			else
1012				fd.append(key, (!!val ? val : ''));
1013		},
1014		prepareData = function(arData)
1015		{
1016			var data = {};
1017			if (null != arData)
1018			{
1019				if(typeof arData == 'object')
1020				{
1021					for(var i in arData)
1022					{
1023						if (arData.hasOwnProperty(i))
1024						{
1025							var name = BX.util.urlencode(i);
1026							if(typeof arData[i] == 'object' && arData[i]["file"] !== true)
1027								data[name] = prepareData(arData[i]);
1028							else if (arData[i]["file"] === true)
1029								data[name] = arData[i]["value"];
1030							else
1031								data[name] = BX.util.urlencode(arData[i]);
1032						}
1033					}
1034				}
1035				else
1036					data = BX.util.urlencode(arData);
1037			}
1038			return data;
1039		},
1040		fd = new window.FormData();
1041
1042		if (config.method !== 'POST')
1043		{
1044			config.data = BX.ajax.prepareData(config.data);
1045			if (config.data)
1046			{
1047				config.url += (config.url.indexOf('?') !== -1 ? "&" : "?") + config.data;
1048				config.data = '';
1049			}
1050		}
1051		else
1052		{
1053			if (config.preparePost === true)
1054				config.data = prepareData(config.data);
1055			appendToForm(fd, '', config.data);
1056			config.data = fd;
1057		}
1058
1059		config.preparePost = false;
1060		config.start = false;
1061
1062		var xhr = BX.ajax(config);
1063		if (!!config["onprogress"])
1064			xhr.upload.addEventListener(
1065				'progress',
1066				function(e){
1067					var percent = null;
1068					if(e.lengthComputable && (e.total || e["totalSize"])) {
1069						percent = e.loaded * 100 / (e.total || e["totalSize"]);
1070					}
1071					config["onprogress"](e, percent);
1072				}
1073			);
1074		xhr.send(fd);
1075	}
1076};
1077
1078BX.ajax.UpdatePageData = function (arData)
1079{
1080	if (arData.TITLE)
1081		BX.ajax.UpdatePageTitle(arData.TITLE);
1082	if (arData.WINDOW_TITLE || arData.TITLE)
1083		BX.ajax.UpdateWindowTitle(arData.WINDOW_TITLE || arData.TITLE);
1084	if (arData.NAV_CHAIN)
1085		BX.ajax.UpdatePageNavChain(arData.NAV_CHAIN);
1086	if (arData.CSS && arData.CSS.length > 0)
1087		BX.loadCSS(arData.CSS);
1088	if (arData.SCRIPTS && arData.SCRIPTS.length > 0)
1089	{
1090		var f = function(result,config,cb){
1091
1092			if(!!config && BX.type.isArray(config.scripts))
1093			{
1094				for(var i=0,l=arData.SCRIPTS.length;i<l;i++)
1095				{
1096					config.scripts.push({isInternal:false,JS:arData.SCRIPTS[i]});
1097				}
1098			}
1099			else
1100			{
1101				BX.loadScript(arData.SCRIPTS,cb);
1102			}
1103
1104			BX.removeCustomEvent('onAjaxSuccess',f);
1105		};
1106		BX.addCustomEvent('onAjaxSuccess',f);
1107	}
1108	else
1109	{
1110		var f1 = function(result,config,cb){
1111			if(BX.type.isFunction(cb))
1112			{
1113				cb();
1114			}
1115			BX.removeCustomEvent('onAjaxSuccess',f1);
1116		};
1117		BX.addCustomEvent('onAjaxSuccess', f1);
1118	}
1119};
1120
1121BX.ajax.UpdatePageTitle = function(title)
1122{
1123	var obTitle = BX('pagetitle');
1124	if (obTitle)
1125	{
1126		obTitle.removeChild(obTitle.firstChild);
1127		if (!obTitle.firstChild)
1128			obTitle.appendChild(document.createTextNode(title));
1129		else
1130			obTitle.insertBefore(document.createTextNode(title), obTitle.firstChild);
1131	}
1132};
1133
1134BX.ajax.UpdateWindowTitle = function(title)
1135{
1136	document.title = title;
1137};
1138
1139BX.ajax.UpdatePageNavChain = function(nav_chain)
1140{
1141	var obNavChain = BX('navigation');
1142	if (obNavChain)
1143	{
1144		obNavChain.innerHTML = nav_chain;
1145	}
1146};
1147
1148/* user options handling */
1149BX.userOptions = {
1150	options: null,
1151	bSend: false,
1152	delay: 5000,
1153	path: '/bitrix/admin/user_options.php?'
1154};
1155
1156BX.userOptions.setAjaxPath = function(url)
1157{
1158	BX.userOptions.path = url.indexOf('?') == -1? url+'?': url+'&';
1159}
1160BX.userOptions.save = function(sCategory, sName, sValName, sVal, bCommon)
1161{
1162	if (null == BX.userOptions.options)
1163		BX.userOptions.options = {};
1164
1165	bCommon = !!bCommon;
1166	BX.userOptions.options[sCategory+'.'+sName+'.'+sValName] = [sCategory, sName, sValName, sVal, bCommon];
1167
1168	var sParam = BX.userOptions.__get();
1169	if (sParam != '')
1170		document.cookie = BX.message('COOKIE_PREFIX')+"_LAST_SETTINGS=" + sParam + "&sessid="+BX.bitrix_sessid()+"; expires=Thu, 31 Dec 2020 23:59:59 GMT; path=/;";
1171
1172	if(!BX.userOptions.bSend)
1173	{
1174		BX.userOptions.bSend = true;
1175		setTimeout(function(){BX.userOptions.send(null)}, BX.userOptions.delay);
1176	}
1177};
1178
1179BX.userOptions.send = function(callback)
1180{
1181	var sParam = BX.userOptions.__get();
1182	BX.userOptions.options = null;
1183	BX.userOptions.bSend = false;
1184
1185	if (sParam != '')
1186	{
1187		document.cookie = BX.message('COOKIE_PREFIX') + "_LAST_SETTINGS=; path=/;";
1188		BX.ajax({
1189			'method': 'GET',
1190			'dataType': 'html',
1191			'processData': false,
1192			'cache': false,
1193			'url': BX.userOptions.path+sParam+'&sessid='+BX.bitrix_sessid(),
1194			'onsuccess': callback
1195		});
1196	}
1197};
1198
1199BX.userOptions.del = function(sCategory, sName, bCommon, callback)
1200{
1201	BX.ajax.get(BX.userOptions.path+'action=delete&c='+sCategory+'&n='+sName+(bCommon == true? '&common=Y':'')+'&sessid='+BX.bitrix_sessid(), callback);
1202};
1203
1204BX.userOptions.__get = function()
1205{
1206	if (!BX.userOptions.options) return '';
1207
1208	var sParam = '', n = -1, prevParam = '', aOpt, i;
1209
1210	for (i in BX.userOptions.options)
1211	{
1212		if(BX.userOptions.options.hasOwnProperty(i))
1213		{
1214			aOpt = BX.userOptions.options[i];
1215
1216			if (prevParam != aOpt[0]+'.'+aOpt[1])
1217			{
1218				n++;
1219				sParam += '&p['+n+'][c]='+BX.util.urlencode(aOpt[0]);
1220				sParam += '&p['+n+'][n]='+BX.util.urlencode(aOpt[1]);
1221				if (aOpt[4] == true)
1222					sParam += '&p['+n+'][d]=Y';
1223				prevParam = aOpt[0]+'.'+aOpt[1];
1224			}
1225
1226			sParam += '&p['+n+'][v]['+BX.util.urlencode(aOpt[2])+']='+BX.util.urlencode(aOpt[3]);
1227		}
1228	}
1229
1230	return sParam.substr(1);
1231};
1232
1233BX.ajax.history = {
1234	expected_hash: '',
1235
1236	obParams: null,
1237
1238	obFrame: null,
1239	obImage: null,
1240
1241	obTimer: null,
1242
1243	bInited: false,
1244	bHashCollision: false,
1245	bPushState: !!(history.pushState && BX.type.isFunction(history.pushState)),
1246
1247	startState: null,
1248
1249	init: function(obParams)
1250	{
1251		if (BX.ajax.history.bInited)
1252			return;
1253
1254		this.obParams = obParams;
1255		var obCurrentState = this.obParams.getState();
1256
1257		if (BX.ajax.history.bPushState)
1258		{
1259			BX.ajax.history.expected_hash = window.location.pathname;
1260			if (window.location.search)
1261				BX.ajax.history.expected_hash += window.location.search;
1262
1263			BX.ajax.history.put(obCurrentState, BX.ajax.history.expected_hash, '', true);
1264			// due to some strange thing, chrome calls popstate event on page start. so we should delay it
1265			setTimeout(function(){BX.bind(window, 'popstate', BX.ajax.history.__hashListener);}, 500);
1266		}
1267		else
1268		{
1269			BX.ajax.history.expected_hash = window.location.hash;
1270
1271			if (!BX.ajax.history.expected_hash || BX.ajax.history.expected_hash == '#')
1272				BX.ajax.history.expected_hash = '__bx_no_hash__';
1273
1274			jsAjaxHistoryContainer.put(BX.ajax.history.expected_hash, obCurrentState);
1275			BX.ajax.history.obTimer = setTimeout(BX.ajax.history.__hashListener, 500);
1276
1277			if (BX.browser.IsIE())
1278			{
1279				BX.ajax.history.obFrame = document.createElement('IFRAME');
1280				BX.hide_object(BX.ajax.history.obFrame);
1281
1282				document.body.appendChild(BX.ajax.history.obFrame);
1283
1284				BX.ajax.history.obFrame.contentWindow.document.open();
1285				BX.ajax.history.obFrame.contentWindow.document.write(BX.ajax.history.expected_hash);
1286				BX.ajax.history.obFrame.contentWindow.document.close();
1287			}
1288			else if (BX.browser.IsOpera())
1289			{
1290				BX.ajax.history.obImage = document.createElement('IMG');
1291				BX.hide_object(BX.ajax.history.obImage);
1292
1293				document.body.appendChild(BX.ajax.history.obImage);
1294
1295				BX.ajax.history.obImage.setAttribute('src', 'javascript:location.href = \'javascript:BX.ajax.history.__hashListener();\';');
1296			}
1297		}
1298
1299		BX.ajax.history.bInited = true;
1300	},
1301
1302	__hashListener: function(e)
1303	{
1304		e = e || window.event || {state:false};
1305
1306		if (BX.ajax.history.bPushState)
1307		{
1308			BX.ajax.history.obParams.setState(e.state||BX.ajax.history.startState);
1309		}
1310		else
1311		{
1312			if (BX.ajax.history.obTimer)
1313			{
1314				window.clearTimeout(BX.ajax.history.obTimer);
1315				BX.ajax.history.obTimer = null;
1316			}
1317
1318			var current_hash;
1319			if (null != BX.ajax.history.obFrame)
1320				current_hash = BX.ajax.history.obFrame.contentWindow.document.body.innerText;
1321			else
1322				current_hash = window.location.hash;
1323
1324			if (!current_hash || current_hash == '#')
1325				current_hash = '__bx_no_hash__';
1326
1327			if (current_hash.indexOf('#') == 0)
1328				current_hash = current_hash.substring(1);
1329
1330			if (current_hash != BX.ajax.history.expected_hash)
1331			{
1332				var state = jsAjaxHistoryContainer.get(current_hash);
1333				if (state)
1334				{
1335					BX.ajax.history.obParams.setState(state);
1336
1337					BX.ajax.history.expected_hash = current_hash;
1338					if (null != BX.ajax.history.obFrame)
1339					{
1340						var __hash = current_hash == '__bx_no_hash__' ? '' : current_hash;
1341						if (window.location.hash != __hash && window.location.hash != '#' + __hash)
1342							window.location.hash = __hash;
1343					}
1344				}
1345			}
1346
1347			BX.ajax.history.obTimer = setTimeout(BX.ajax.history.__hashListener, 500);
1348		}
1349	},
1350
1351	put: function(state, new_hash, new_hash1, bStartState)
1352	{
1353		if (this.bPushState)
1354		{
1355			if(!bStartState)
1356			{
1357				history.pushState(state, '', new_hash);
1358			}
1359			else
1360			{
1361				BX.ajax.history.startState = state;
1362			}
1363		}
1364		else
1365		{
1366			if (typeof new_hash1 != 'undefined')
1367				new_hash = new_hash1;
1368			else
1369				new_hash = 'view' + new_hash;
1370
1371			jsAjaxHistoryContainer.put(new_hash, state);
1372			BX.ajax.history.expected_hash = new_hash;
1373
1374			window.location.hash = BX.util.urlencode(new_hash);
1375
1376			if (null != BX.ajax.history.obFrame)
1377			{
1378				BX.ajax.history.obFrame.contentWindow.document.open();
1379				BX.ajax.history.obFrame.contentWindow.document.write(new_hash);
1380				BX.ajax.history.obFrame.contentWindow.document.close();
1381			}
1382		}
1383	},
1384
1385	checkRedirectStart: function(param_name, param_value)
1386	{
1387		var current_hash = window.location.hash;
1388		if (current_hash.substring(0, 1) == '#') current_hash = current_hash.substring(1);
1389
1390		var test = current_hash.substring(0, 5);
1391		if (test == 'view/' || test == 'view%')
1392		{
1393			BX.ajax.history.bHashCollision = true;
1394			document.write('<' + 'div id="__ajax_hash_collision_' + param_value + '" style="display: none;">');
1395		}
1396	},
1397
1398	checkRedirectFinish: function(param_name, param_value)
1399	{
1400		document.write('</div>');
1401
1402		var current_hash = window.location.hash;
1403		if (current_hash.substring(0, 1) == '#') current_hash = current_hash.substring(1);
1404
1405		BX.ready(function ()
1406		{
1407			var test = current_hash.substring(0, 5);
1408			if (test == 'view/' || test == 'view%')
1409			{
1410				var obColNode = BX('__ajax_hash_collision_' + param_value);
1411				var obNode = obColNode.firstChild;
1412				BX.cleanNode(obNode);
1413				obColNode.style.display = 'block';
1414
1415				// IE, Opera and Chrome automatically modifies hash with urlencode, but FF doesn't ;-(
1416				if (test != 'view%')
1417					current_hash = BX.util.urlencode(current_hash);
1418
1419				current_hash += (current_hash.indexOf('%3F') == -1 ? '%3F' : '%26') + param_name + '=' + param_value;
1420
1421				var url = '/bitrix/tools/ajax_redirector.php?hash=' + current_hash;
1422
1423				BX.ajax.insertToNode(url, obNode);
1424			}
1425		});
1426	}
1427};
1428
1429BX.ajax.component = function(node)
1430{
1431	this.node = node;
1432};
1433
1434BX.ajax.component.prototype.getState = function()
1435{
1436	var state = {
1437		'node': this.node,
1438		'title': window.document.title,
1439		'data': BX(this.node).innerHTML
1440	};
1441
1442	var obNavChain = BX('navigation');
1443	if (null != obNavChain)
1444		state.nav_chain = obNavChain.innerHTML;
1445
1446	BX.onCustomEvent(BX(state.node), "onComponentAjaxHistoryGetState", [state]);
1447
1448	return state;
1449};
1450
1451BX.ajax.component.prototype.setState = function(state)
1452{
1453	BX(state.node).innerHTML = state.data;
1454	BX.ajax.UpdatePageTitle(state.title);
1455
1456	if (state.nav_chain)
1457	{
1458		BX.ajax.UpdatePageNavChain(state.nav_chain);
1459	}
1460
1461	BX.onCustomEvent(BX(state.node), "onComponentAjaxHistorySetState", [state]);
1462};
1463
1464var jsAjaxHistoryContainer = {
1465	arHistory: {},
1466
1467	put: function(hash, state)
1468	{
1469		this.arHistory[hash] = state;
1470	},
1471
1472	get: function(hash)
1473	{
1474		return this.arHistory[hash];
1475	}
1476};
1477
1478
1479BX.ajax.FormData = function()
1480{
1481	this.elements = [];
1482	this.files = [];
1483	this.features = {};
1484	this.isSupported();
1485	this.log('BX FormData init');
1486};
1487
1488BX.ajax.FormData.isSupported = function()
1489{
1490	var f = new BX.ajax.FormData();
1491	var result = f.features.supported;
1492	f = null;
1493	return result;
1494};
1495
1496BX.ajax.FormData.prototype.log = function(o)
1497{
1498	if (false) {
1499		try {
1500			if (BX.browser.IsIE()) o = JSON.stringify(o);
1501			console.log(o);
1502		} catch(e) {}
1503	}
1504};
1505
1506BX.ajax.FormData.prototype.isSupported = function()
1507{
1508	var f = {};
1509	f.fileReader = (window.FileReader && window.FileReader.prototype.readAsBinaryString);
1510	f.readFormData = f.sendFormData = !!(window.FormData);
1511	f.supported = !!(f.readFormData && f.sendFormData);
1512	this.features = f;
1513	this.log('features:');
1514	this.log(f);
1515
1516	return f.supported;
1517};
1518
1519BX.ajax.FormData.prototype.append = function(name, value)
1520{
1521	if (typeof(value) === 'object') { // seems to be files element
1522		this.files.push({'name': name, 'value':value});
1523	} else {
1524		this.elements.push({'name': name, 'value':value});
1525	}
1526};
1527
1528BX.ajax.FormData.prototype.send = function(url, callbackOk, callbackProgress, callbackError)
1529{
1530	this.log('FD send');
1531	this.xhr = BX.ajax({
1532			'method': 'POST',
1533			'dataType': 'html',
1534			'url': url,
1535			'onsuccess': callbackOk,
1536			'onfailure': callbackError,
1537			'start': false,
1538			'preparePost':false
1539		});
1540
1541	if (callbackProgress)
1542	{
1543		this.xhr.upload.addEventListener(
1544			'progress',
1545			function(e) {
1546				if (e.lengthComputable)
1547					callbackProgress(e.loaded / (e.total || e.totalSize));
1548			},
1549			false
1550		);
1551	}
1552
1553	if (this.features.readFormData && this.features.sendFormData)
1554	{
1555		var fd = new FormData();
1556		this.log('use browser formdata');
1557		for (var i in this.elements)
1558		{
1559			if(this.elements.hasOwnProperty(i))
1560				fd.append(this.elements[i].name,this.elements[i].value);
1561		}
1562		for (i in this.files)
1563		{
1564			if(this.files.hasOwnProperty(i))
1565				fd.append(this.files[i].name, this.files[i].value);
1566		}
1567		this.xhr.send(fd);
1568	}
1569
1570	return this.xhr;
1571};
1572
1573BX.addCustomEvent('onAjaxFailure', BX.debug);
1574})(window);
1575

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.