PageSourceSearch

https://ecprofi78.ru/bitrix/cache/js/s1/main/kernel_main/kernel_main_v1.js?1784195790251869

js ecprofi78.ru collected 2026-10-07 10:09:59 UTC 251,869 bytes, 9,321 lines download raw bytes

1; /* /bitrix/js/main/session.js?17415973603701*/
2; /* /bitrix/js/main/pageobject/pageobject.js?1741597360864*/
3; /* /bitrix/js/main/core/core_window.js?174159735698766*/
4; /* /bitrix/js/main/date/main.date.js?174195188562683*/
5; /* /bitrix/js/main/core/core_date.js?174159735536080*/
6; /* /bitrix/js/main/utils.js?174159736029279*/
7; /* /bitrix/js/main/core/core_uf.js?174159735518793*/
8
9; /* Start:"a:4:{s:4:"full";s:47:"/bitrix/js/main/core/core_uf.js?174159735518793";s:6:"source";s:31:"/bitrix/js/main/core/core_uf.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
10;(function ()
11{
12	'use strict';
13
14	BX.namespace('BX.Main.UF');
15
16	if (typeof BX.Main.UF.Manager !== 'undefined')
17	{
18		return;
19	}
20
21	var fieldStack = {};
22
23	/**
24	 * Dynamic form manager. Initilized as singleton below
25	 *
26	 * @constructor
27	 */
28
29	BX.Main.UF.Manager = function ()
30	{
31		this.mode = this.mode || '';
32		this.ajaxUrl = '/bitrix/tools/uf.php';
33	};
34
35
36	BX.Main.UF.Manager.getEdit = function (param, callback)
37	{
38		return BX.Main.UF.EditManager.get(param, callback);
39	};
40
41	BX.Main.UF.Manager.getView = function (param, callback)
42	{
43		return BX.Main.UF.ViewManager.get(param, callback);
44	};
45
46	BX.Main.UF.Manager.prototype.get = function (param, callback)
47	{
48		if (!this.mode)
49		{
50			this.displayError([
51				'No mode set. Use BX.UF.EditManager or BX.UF.ViewManager'
52			]);
53
54			return;
55		}
56
57		return this.query(this.mode, {
58			FIELDS: param.FIELDS,
59			FORM: param.FORM || '',
60			CONTEXT: param.CONTEXT || '',
61			MEDIA_TYPE: param.MEDIA_TYPE || ''
62		}, callback);
63	};
64
65	BX.Main.UF.Manager.prototype.add = function (param, callback)
66	{
67		if (!this.mode)
68		{
69			this.displayError([
70				'No mode set. Use BX.UF.EditManager or BX.UF.ViewManager'
71			]);
72
73			return;
74		}
75
76		return this.query(this.mode, {
77			action: 'add',
78			FIELDS: param.FIELDS,
79			FORM: param.FORM || ''
80		}, callback);
81	};
82
83	BX.Main.UF.Manager.prototype.update = function (param, callback)
84	{
85		if (!this.mode)
86		{
87			this.displayError([
88				'No mode set. Use BX.UF.EditManager or BX.UF.ViewManager'
89			]);
90
91			return;
92		}
93
94		return this.query(this.mode, {
95			action: 'update',
96			FIELDS: param.FIELDS,
97			FORM: param.FORM || ''
98		}, callback);
99	};
100
101	BX.Main.UF.Manager.prototype.delete = function (param, callback)
102	{
103		if (!this.mode)
104		{
105			this.displayError([
106				'No mode set. Use BX.UF.EditManager or BX.UF.ViewManager'
107			]);
108
109			return;
110		}
111
112		return this.query(this.mode, {
113			action: 'delete',
114			FIELDS: param.FIELDS,
115			FORM: param.FORM || ''
116		}, callback);
117	};
118
119	BX.Main.UF.Manager.prototype.query = function (mode, param, callback)
120	{
121		BX.ajax({
122			dataType: 'json',
123			url: this.ajaxUrl,
124			method: 'POST',
125			data: this.prepareQuery(mode, param),
126			onsuccess: this.queryCallback(callback)
127		});
128	};
129
130	BX.Main.UF.Manager.prototype.prepareQuery = function (mode, param)
131	{
132		var p = param || {};
133
134		p.mode = mode;
135		p.lang = BX.message('LANGUAGE_ID') || '';
136		p.tpl = BX.message('UF_SITE_TPL') || '';
137		p.tpls = BX.message('UF_SITE_TPL_SIGN') || '';
138		p.sessid = BX.bitrix_sessid();
139
140		return p;
141	};
142
143	BX.Main.UF.Manager.prototype.queryCallback = function (callback)
144	{
145		var processResult = BX.proxy(this.processResult, this);
146		return function (result)
147		{
148			processResult(result, callback);
149		}
150	};
151
152	BX.Main.UF.Manager.prototype.processResult = function (result, callback)
153	{
154		var asset = '';
155		if (BX.type.isArray(result.ASSET))
156		{
157			asset += result.ASSET.join('\n');
158		}
159
160		if (!!result.ERROR)
161		{
162			this.displayError(result.ERROR);
163		}
164
165		return BX.html(null, asset).then(function ()
166		{
167			if (!!callback)
168			{
169				callback(result.FIELD);
170			}
171		});
172	};
173
174	BX.Main.UF.Manager.prototype.displayError = function (errorList)
175	{
176		for (var i in errorList)
177		{
178			if (errorList.hasOwnProperty(i))
179			{
180				console.error(errorList[i]);
181			}
182		}
183	};
184
185	BX.Main.UF.Manager.prototype.registerField = function (field, fieldDescription, node)
186	{
187		fieldStack[field] = {
188			FIELD: fieldDescription,
189			NODE: node
190		};
191	};
192
193	BX.Main.UF.Manager.prototype.unRegisterField = function (field)
194	{
195		if (!!fieldStack[field])
196		{
197			delete fieldStack[field];
198		}
199	};
200
201
202	BX.Main.UF.ViewManager = function ()
203	{
204		BX.Main.UF.ViewManager.superclass.constructor.apply(this, arguments);
205
206		this.mode = 'main.view';
207	};
208	BX.extend(BX.Main.UF.ViewManager, BX.Main.UF.Manager);
209
210	BX.Main.UF.EditManager = function ()
211	{
212		BX.Main.UF.EditManager.superclass.constructor.apply(this, arguments);
213
214		this.mode = 'main.edit';
215	};
216	BX.extend(BX.Main.UF.EditManager, BX.Main.UF.Manager);
217
218	BX.Main.UF.EditManager.prototype.validate = function (fieldList, callback)
219	{
220		if (fieldList.length > 0)
221		{
222			var request = [];
223			for (var i = 0; i < fieldList.length; i++)
224			{
225				var value = BX.Main.UF.Factory.getValue(fieldList[i]);
226				if (value !== null)
227				{
228					request.push({
229						'ENTITY_ID': fieldStack[fieldList[i]].FIELD.ENTITY_ID,
230						'FIELD': fieldStack[fieldList[i]].FIELD.FIELD,
231						'ENTITY_VALUE_ID': fieldStack[fieldList[i]].FIELD.ENTITY_VALUE_ID,
232						'VALUE': value
233					});
234				}
235			}
236
237			return this.query(this.mode, {
238				action: 'validate',
239				FIELDS: request
240			}, callback);
241		}
242		else
243		{
244			this.queryCallback(callback)({'FIELD': []});
245		}
246	};
247
248	/**
249	 * Base type handler class. Will be initialized in Factory.
250	 *
251	 * @constructor
252	 */
253
254	BX.Main.UF.BaseType = function ()
255	{
256	};
257
258	BX.Main.UF.BaseType.prototype.addRow = function (fieldName, thisButton)
259	{
260		var element = thisButton.parentNode.getElementsByTagName('span');
261		if (element && element.length > 0 && element[0])
262		{
263			var parentElement = element[0].parentNode; // parent
264			var newNode = this.getClone(element[element.length - 1], fieldName);
265
266			if (parentElement === thisButton.parentNode)
267			{
268				parentElement.insertBefore(newNode, thisButton);
269			}
270			else
271			{
272				parentElement.appendChild(newNode);
273			}
274		}
275	};
276
277	/**
278	 * @deprecated
279	 * @param fieldName
280	 * @param thisButton
281	 */
282	BX.Main.UF.BaseType.prototype.addMobileRow = function (fieldName, thisButton)
283	{
284		var element = thisButton.parentNode.getElementsByTagName('span');
285		if (element && element.length && element[0])
286		{
287			var parentElement = element[0].parentNode; // parent
288			var newNode = this.getClone(element[element.length - 1], fieldName);
289			var firstChildren = newNode.firstElementChild;
290			var name = firstChildren.getAttribute('name');
291			var re = /\[(\d)]/;
292			var newName = name.replace(re, function (match, index)
293			{
294				index = parseInt(index) + 1;
295				return '[' + index + ']';
296			});
297			var newItemId = false;
298			var prevItemName = false;
299			var userFieldTypeName = null;
300
301			firstChildren.setAttribute('name', newName);
302
303			if (firstChildren.hasChildNodes())
304			{
305				firstChildren.childNodes.forEach(
306					function (item, index, array)
307					{
308						if (!prevItemName && item.attributes !== undefined && item.tagName === 'INPUT')
309						{
310							item.setAttribute('name', newName);
311							prevItemName = item.getAttribute('id');
312							newItemId = prevItemName + '_1';
313							userFieldTypeName = item.getAttribute('data-user-field-type-name');
314						}
315
316						if (prevItemName && item.attributes !== undefined && item.id !== undefined)
317						{
318							var id = item.getAttribute('id');
319
320							if (id !== prevItemName)
321							{
322								item.setAttribute('id', id.replace(prevItemName, newItemId));
323							}
324							else
325							{
326								item.setAttribute('id', newItemId);
327							}
328						}
329					}
330				);
331			}
332
333			if (parentElement === thisButton.parentNode)
334			{
335				parentElement.insertBefore(newNode, thisButton);
336			}
337			else
338			{
339				parentElement.appendChild(newNode);
340			}
341
342			if (newItemId)
343			{
344				BX.onCustomEvent(
345					'onAddMobileUfField',
346					[newItemId, userFieldTypeName]
347				);
348			}
349
350		}
351	};
352
353	BX.Main.UF.BaseType.prototype.getClone = function (node, fieldName)
354	{
355		var newNode = node.cloneNode(true);
356
357		var inputList = this.findInput(newNode, fieldName);
358		for (var i = 0; i < inputList.length; i++)
359		{
360			inputList[i].value = '';
361		}
362
363		return newNode;
364	};
365
366	BX.Main.UF.BaseType.prototype.findInput = function (node, fieldName)
367	{
368		return BX.findChildren(node, {
369			tagName: /INPUT|TEXTAREA|SELECT/i,
370			attribute: {
371				name: fieldName
372			}
373		}, true);
374	};
375
376	BX.Main.UF.BaseType.prototype.isEmpty = function (field)
377	{
378		var node = this.getNode(field),
379			fieldName = field + (
380				fieldStack[field].FIELD.MULTIPLE === 'Y'
381					? '[]'
382					: ''
383			);
384
385		if (!BX.isNodeInDom(node))
386		{
387			console.error('Node for field ' + field + ' is already removed from DOM');
388		}
389
390		var nodeList = this.findInput(node, fieldName);
391
392		if (nodeList.length <= 0)
393		{
394			console.error('Unable to find field ' + field + ' in the registered node');
395		}
396		else
397		{
398			for (var i = 0; i < nodeList.length; i++)
399			{
400				if (nodeList[i].value !== '')
401				{
402					return false;
403				}
404			}
405		}
406
407		return true;
408	};
409
410	BX.Main.UF.BaseType.prototype.getValue = function (field)
411	{
412		var node = this.getNode(field),
413			fieldName = field + (
414				fieldStack[field].FIELD.MULTIPLE === 'Y'
415					? '[]'
416					: ''
417			),
418			value = fieldStack[field].FIELD.MULTIPLE === 'Y' ? [] : '';
419
420		if (!BX.isNodeInDom(node))
421		{
422			console.error('Node for field ' + field + ' is already removed from DOM');
423		}
424		var nodeList = this.findInput(node, fieldName);
425
426		if (nodeList.length <= 0)
427		{
428			var nodeChildren = (node.children.length ? node.children[0] : false);
429			/**
430			 * @todo remove !BX.util.in_array(fieldStack[field].FIELD.USER_TYPE_ID, ['crm', 'employee'])
431			 * after deploy new Crm and Employee types
432			 */
433			if (
434				!BX.util.in_array(fieldStack[field].FIELD.USER_TYPE_ID, ['crm', 'employee'])
435				&&
436				(
437					!nodeChildren
438					||
439					nodeChildren.getAttribute('data-has-input') !== 'no'
440				)
441			)
442			{
443				console.error('Unable to find field ' + field + ' in the registered node');
444			}
445		}
446		else
447		{
448			for (var i = 0; i < nodeList.length; i++)
449			{
450				if (
451					nodeList[i].tagName === 'INPUT'
452					&& (nodeList[i].type === 'radio' || nodeList[i].type === 'checkbox')
453					&& !nodeList[i].checked
454				)
455				{
456					continue;
457				}
458
459				if (!BX.Type.isStringFilled(nodeList[i].value))
460				{
461					continue;
462				}
463
464				if (fieldStack[field].FIELD.MULTIPLE === 'Y')
465				{
466					value.push(nodeList[i].value);
467				}
468				else
469				{
470					value = nodeList[i].value;
471					break;
472				}
473			}
474		}
475
476		return value;
477	};
478
479	BX.Main.UF.BaseType.prototype.focus = function (field)
480	{
481		var node = this.getNode(field),
482			fieldName = field + (
483				fieldStack[field].FIELD.MULTIPLE === 'Y'
484					? '[]'
485					: ''
486			);
487
488		if (!BX.isNodeInDom(node))
489		{
490			console.error('Node for field ' + field + ' is already removed from DOM');
491		}
492		var nodeList = this.findInput(node, fieldName);
493
494		if (nodeList.length > 0)
495		{
496			BX.focus(nodeList[0]);
497		}
498	};
499
500	BX.Main.UF.BaseType.prototype.getNode = function (field)
501	{
502		return fieldStack[field].NODE;
503	};
504
505	/**
506	 * Integer type handler class. Will be initialized in Factory.
507	 *
508	 * @constructor
509	 */
510	BX.Main.UF.TypeBoolean = function ()
511	{
512	};
513	BX.extend(BX.Main.UF.TypeBoolean, BX.Main.UF.BaseType);
514
515	BX.Main.UF.TypeBoolean.USER_TYPE_ID = 'boolean';
516
517	BX.Main.UF.TypeBoolean.prototype.isEmpty = function (field)
518	{
519		return false;
520	};
521
522	/**
523	 * Integer type handler class. Will be initialized in Factory.
524	 *
525	 * @constructor
526	 */
527	BX.Main.UF.TypeInteger = function ()
528	{
529	};
530	BX.extend(BX.Main.UF.TypeInteger, BX.Main.UF.BaseType);
531
532	BX.Main.UF.TypeInteger.USER_TYPE_ID = 'integer';
533
534	/**
535	 * Double type handler class. Will be initialized in Factory.
536	 *
537	 * @constructor
538	 */
539	BX.Main.UF.TypeDouble = function ()
540	{
541	};
542	BX.extend(BX.Main.UF.TypeDouble, BX.Main.UF.BaseType);
543
544	BX.Main.UF.TypeDouble.USER_TYPE_ID = 'double';
545
546	/**
547	 * String type handler class. Will be initialized in Factory.
548	 *
549	 * @constructor
550	 */
551	BX.Main.UF.TypeSting = function ()
552	{
553	};
554	BX.extend(BX.Main.UF.TypeSting, BX.Main.UF.BaseType);
555
556	BX.Main.UF.TypeSting.USER_TYPE_ID = 'string';
557
558	/**
559	 * URL type handler class. Will be initialized in Factory.
560	 *
561	 * @constructor
562	 */
563	BX.Main.UF.TypeUrl = function ()
564	{
565	};
566	BX.extend(BX.Main.UF.TypeUrl, BX.Main.UF.BaseType);
567
568	BX.Main.UF.TypeUrl.USER_TYPE_ID = 'url';
569
570	/**
571	 * Formatted string type handler class. Will be initialized in Factory.
572	 *
573	 * @constructor
574	 */
575	BX.Main.UF.TypeStingFormatted = function ()
576	{
577	};
578	BX.extend(BX.Main.UF.TypeStingFormatted, BX.Main.UF.TypeSting);
579
580	BX.Main.UF.TypeStingFormatted.USER_TYPE_ID = 'string_formatted';
581
582
583	/**
584	 * Enumeration type handler class. Will be initialized in Factory.
585	 *
586	 * @constructor
587	 */
588	BX.Main.UF.TypeEnumeration = function ()
589	{
590	};
591	BX.extend(BX.Main.UF.TypeEnumeration, BX.Main.UF.BaseType);
592
593	BX.Main.UF.TypeEnumeration.USER_TYPE_ID = 'enumeration';
594
595	BX.Main.UF.TypeEnumeration.prototype.findInput = function (node, fieldName)
596	{
597		var inputList = BX.Main.UF.TypeEnumeration.superclass.findInput.apply(this, arguments);
598
599		if (inputList.length > 0)
600		{
601			for (var i = 0; i < inputList.length; i++)
602			{
603				if (inputList[i].tagName === 'INPUT' && inputList[i].type === 'hidden' && inputList.length > 1)
604				{
605					delete inputList[i];
606					break;
607				}
608			}
609		}
610
611		return BX.util.array_values(inputList);
612	};
613
614	BX.Main.UF.TypeEnumeration.prototype.focus = function (field)
615	{
616		if (fieldStack[field]
617			&& fieldStack[field].FIELD.SETTINGS.DISPLAY === 'UI'
618			&& BX.type.isElementNode(fieldStack[field].NODE)
619		)
620		{
621			BX.fireEvent(fieldStack[field].NODE, 'focus');
622		}
623		else
624		{
625			BX.Main.UF.TypeEnumeration.superclass.focus.apply(this, arguments);
626		}
627	};
628
629	/**
630	 * Date type handler class. Will be initialized in Factory.
631	 *
632	 * @constructor
633	 */
634	BX.Main.UF.TypeDate = function ()
635	{
636	};
637	BX.extend(BX.Main.UF.TypeDate, BX.Main.UF.BaseType);
638
639	BX.Main.UF.TypeDate.USER_TYPE_ID = 'date';
640
641	BX.Main.UF.TypeDate.prototype.focus = function (field)
642	{
643		var fieldName = field + (
644			fieldStack[field].FIELD.MULTIPLE === 'Y'
645				? '[]'
646				: ''
647		);
648		var inputList = this.findInput(this.getNode(field), fieldName);
649
650		if (inputList.length > 0)
651		{
652			BX.fireEvent(inputList[0], 'click');
653		}
654
655		BX.Main.UF.TypeDate.superclass.focus.apply(this, arguments);
656	};
657
658	/**
659	 * Datetime type handler class. Will be initialized in Factory.
660	 *
661	 * @constructor
662	 */
663	BX.Main.UF.TypeDateTime = function ()
664	{
665	};
666	BX.extend(BX.Main.UF.TypeDateTime, BX.Main.UF.TypeDate);
667
668	BX.Main.UF.TypeDateTime.USER_TYPE_ID = 'datetime';
669
670	/**
671	 * Datetime type handler class. Will be initialized in Factory.
672	 *
673	 * @constructor
674	 */
675	BX.Main.UF.TypeFile = function ()
676	{
677	};
678	BX.extend(BX.Main.UF.TypeFile, BX.Main.UF.BaseType);
679
680	BX.Main.UF.TypeFile.USER_TYPE_ID = 'file';
681
682	BX.Main.UF.TypeFile.prototype.findInput = function (node, fieldName)
683	{
684		var inputList = BX.Main.UF.TypeFile.superclass.findInput.apply(this, arguments);
685
686		if (inputList.length <= 0)
687		{
688			inputList = BX.findChildren(node, {
689				tagName: /INPUT/i,
690				attribute: {
691					type: 'file',
692					name: /^bxu_files/
693				}
694			}, true);
695		}
696
697		return inputList;
698	};
699
700	BX.Main.UF.TypeFile.prototype.getValue = function (field)
701	{
702		var
703			baseValue = BX.Main.UF.TypeFile.superclass.getValue.apply(this, arguments),
704			node = fieldStack[field].NODE,
705			deletedNodeList = [],
706			i;
707
708		if (fieldStack[field].FIELD.MULTIPLE === 'Y')
709		{
710			var deletedFieldName = field + '_del[]';
711
712			if (BX.type.isArray(baseValue) && baseValue.length > 0)
713			{
714				deletedNodeList = BX.Main.UF.TypeFile.superclass.findInput.apply(this, [node, deletedFieldName]);
715
716				for (i = 0; i < deletedNodeList.length; i++)
717				{
718					var pos = BX.util.array_search(deletedNodeList[i].value, baseValue);
719					if (pos >= 0)
720					{
721						baseValue[pos] = {'old_id': deletedNodeList[i].value, 'del': 'Y', 'tmp_name': ''};
722					}
723				}
724			}
725
726			return BX.util.array_values(baseValue);
727		}
728
729		if (baseValue > 0)
730		{
731			var deletedFieldName = field + '_del';
732
733			deletedNodeList = BX.Main.UF.TypeFile.superclass.findInput.apply(this, [node, deletedFieldName]);
734
735			for (i = 0; i < deletedNodeList.length; i++)
736			{
737				if (baseValue == deletedNodeList[i].value)
738				{
739					baseValue = {'old_id': baseValue, 'del': 'Y', 'tmp_name': ''};
740					break;
741				}
742			}
743
744			return baseValue;
745		}
746
747		return null;
748	};
749
750
751	/**
752	 * Type handler Factory singleton. Will be initialized below.
753	 *
754	 * @constructor
755	 */
756	BX.Main.UF.Factory = function ()
757	{
758		this.defaultTypeHandler = BX.Main.UF.BaseType;
759
760		this.typeHandlerList = {};
761		this.objectCollection = {};
762	};
763
764	BX.Main.UF.Factory.prototype.setTypeHandler = function (type, handlerClass)
765	{
766		this.typeHandlerList[type] = handlerClass;
767		if (typeof this.objectCollection[type] !== 'undefined')
768		{
769			delete this.objectCollection[type];
770		}
771	};
772
773	BX.Main.UF.Factory.prototype.get = function (type)
774	{
775		if (typeof this.objectCollection[type] === 'undefined')
776		{
777			this.objectCollection[type] = this.getObject(type);
778		}
779
780		return this.objectCollection[type];
781	};
782
783	BX.Main.UF.Factory.prototype.getObject = function (type)
784	{
785		return new (this.typeHandlerList[type] || this.defaultTypeHandler);
786	};
787
788	BX.Main.UF.Factory.prototype.getFieldObject = function (field)
789	{
790		if (typeof fieldStack[field] === 'undefined')
791		{
792			console.error('Field ' + field + 'is not registered. Use BX.Main.UF.Factory.registerField to register');
793
794			return null;
795		}
796
797		return this.get(fieldStack[field]['FIELD']['USER_TYPE_ID']);
798	};
799
800	BX.Main.UF.Factory.prototype.isEmpty = function (field)
801	{
802		if (typeof fieldStack[field] === 'undefined')
803		{
804			console.error('Field ' + field + 'is not registered. Use BX.Main.UF.Factory.registerField to register');
805
806			return true;
807		}
808
809		return this.get(fieldStack[field]['FIELD']['USER_TYPE_ID']).isEmpty(field);
810	};
811
812	BX.Main.UF.Factory.prototype.getValue = function (field)
813	{
814		if (typeof fieldStack[field] === 'undefined')
815		{
816			console.error('Field ' + field + 'is not registered. Use BX.Main.UF.Factory.registerField to register');
817
818			return null;
819		}
820
821		return this.get(fieldStack[field]['FIELD']['USER_TYPE_ID']).getValue(field);
822	};
823
824	BX.Main.UF.Factory.prototype.focus = function (field)
825	{
826		if (typeof fieldStack[field] === 'undefined')
827		{
828			console.error('Field ' + field + 'is not registered. Use BX.Main.UF.Factory.registerField to register');
829		}
830
831		return this.get(fieldStack[field]['FIELD']['USER_TYPE_ID']).focus(field);
832	};
833
834	/**
835	 * Singletons initialization
836	 */
837
838	BX.Main.UF.EditManager = new BX.Main.UF.EditManager();
839	BX.Main.UF.ViewManager = new BX.Main.UF.ViewManager();
840	BX.Main.UF.Factory = new BX.Main.UF.Factory();
841
842	BX.Main.UF.Factory.setTypeHandler(BX.Main.UF.TypeBoolean.USER_TYPE_ID, BX.Main.UF.TypeBoolean);
843	BX.Main.UF.Factory.setTypeHandler(BX.Main.UF.TypeInteger.USER_TYPE_ID, BX.Main.UF.TypeInteger);
844	BX.Main.UF.Factory.setTypeHandler(BX.Main.UF.TypeDouble.USER_TYPE_ID, BX.Main.UF.TypeDouble);
845	BX.Main.UF.Factory.setTypeHandler(BX.Main.UF.TypeSting.USER_TYPE_ID, BX.Main.UF.TypeSting);
846	BX.Main.UF.Factory.setTypeHandler(BX.Main.UF.TypeStingFormatted.USER_TYPE_ID, BX.Main.UF.TypeStingFormatted);
847	BX.Main.UF.Factory.setTypeHandler(BX.Main.UF.TypeEnumeration.USER_TYPE_ID, BX.Main.UF.TypeEnumeration);
848	BX.Main.UF.Factory.setTypeHandler(BX.Main.UF.TypeFile.USER_TYPE_ID, BX.Main.UF.TypeFile);
849	BX.Main.UF.Factory.setTypeHandler(BX.Main.UF.TypeDate.USER_TYPE_ID, BX.Main.UF.TypeDate);
850	BX.Main.UF.Factory.setTypeHandler(BX.Main.UF.TypeDateTime.USER_TYPE_ID, BX.Main.UF.TypeDateTime);
851})();
852
853/* End */
854;
855; /* Start:"a:4:{s:4:"full";s:41:"/bitrix/js/main/session.js?17415973603701";s:6:"source";s:26:"/bitrix/js/main/session.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
856function CBXSession()
857{
858	var _this = this;
859	this.dateInput = new Date();
860	this.dateCheck = new Date();
861	this.dateHit = new Date();
862	this.notifier = null;
863	this.checkInterval = 60;
864	this.checkImmediately = false;
865
866	this.Expand = function(key)
867	{
868		this.key = key;
869
870		BX.ready(function(){
871			BX.bind(document, "keypress", _this.OnUserInput);
872			BX.bind(document.body, "mousemove", _this.OnUserInput);
873			BX.bind(document.body, "click", _this.OnUserInput);
874
875			//check the state once in a minute
876			setInterval(_this.CheckSession, _this.checkInterval*1000);
877		})
878	};
879
880	this.OnUserInput = function()
881	{
882		var currentDate = new Date();
883		_this.dateInput.setTime(currentDate.valueOf());
884
885		if ((currentDate - _this.dateHit)/1000 > (_this.checkInterval + 5) && _this.checkImmediately === false)
886		{
887			// last hit was long time ago, need to recheck immediately
888			_this.checkImmediately = true;
889			_this.CheckSession();
890		}
891	};
892
893	this.CheckSession = function()
894	{
895		var currentDate = new Date();
896
897		if((currentDate - _this.dateCheck)/1000 < (_this.checkInterval - 1) && _this.checkImmediately === false)
898		{
899			//storm protection, e.g. after PC wake-up
900			return;
901		}
902
903		_this.dateCheck.setTime(currentDate.valueOf());
904
905		if(_this.dateInput > _this.dateHit)
906		{
907			//there was input after the last hit, expand/check the session
908			var config = {
909				'method': 'GET',
910				'headers': [
911					{'name': 'X-Bitrix-Csrf-Token', 'value': BX.bitrix_sessid()}
912				],
913				'dataType': 'html',
914				'url': '/bitrix/tools/public_session.php?k='+_this.key,
915				'data':  '',
916				'onsuccess': function(data){_this.CheckResult(data)},
917				'lsId': 'sess_expand', //caching the result in the local storage for multiple tabs
918				'lsTimeout': _this.checkInterval - 5 //some delta for response time
919			};
920			BX.ajax(config);
921		}
922	};
923
924	this.CheckResult = function(data)
925	{
926		var currentDate = new Date();
927		_this.dateHit.setTime(currentDate.valueOf());
928		_this.checkImmediately = false;
929
930		if(data == 'SESSION_EXPIRED')
931		{
932			if(BX.message("SessExpired"))
933			{
934				if(!_this.notifier)
935				{
936					_this.notifier = document.body.appendChild(BX.create('DIV', {
937						props: {className: 'bx-session-message'},
938						style: {
939							top: '0',
940							backgroundColor: '#FFEB41',
941							border: '1px solid #EDDA3C',
942							width: '630px',
943							fontFamily: 'Arial,Helvetica,sans-serif',
944							fontSize: '13px',
945							fontWeight: 'bold',
946							textAlign: 'center',
947							color: 'black',
948							position: 'absolute',
949							zIndex: '10000',
950							padding: '10px'
951						},
952						html: '<a class="bx-session-message-close" ' +
953							'style="display:block; width:12px; height:12px; background:url(/bitrix/js/main/core/images/close.gif) center no-repeat; float:right;" ' +
954							'href="javascript:bxSession.Close()"></a>' +
955							BX.message("SessExpired")
956					}));
957
958					BX.ZIndexManager.register(_this.notifier);
959					BX.ZIndexManager.bringToFront(_this.notifier);
960
961					var windowScroll = BX.GetWindowScrollPos();
962					var windowSize = BX.GetWindowInnerSize();
963
964					_this.notifier.style.left = parseInt(windowScroll.scrollLeft + (windowSize.innerWidth / 2) - (parseInt(_this.notifier.clientWidth) / 2)) + 'px';
965
966					if(BX.browser.IsIE())
967					{
968						_this.notifier.style.top = windowScroll.scrollTop + 'px';
969
970						BX.bind(window, 'scroll', function()
971						{
972							var windowScroll = BX.GetWindowScrollPos();
973							_this.notifier.style.top = windowScroll.scrollTop + 'px';
974						});
975					}
976					else
977					{
978						_this.notifier.style.position='fixed';
979					}
980				}
981
982				_this.notifier.style.display = '';
983			}
984		}
985	};
986
987	this.Close = function()
988	{
989		this.notifier.style.display = 'none';
990	}
991}
992
993var bxSession = new CBXSession();
994
995/* End */
996;
997; /* Start:"a:4:{s:4:"full";s:54:"/bitrix/js/main/pageobject/pageobject.js?1741597360864";s:6:"source";s:40:"/bitrix/js/main/pageobject/pageobject.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
998window.BX = BX || {};
999
1000BX.PageObject = {
1001	getRootWindow: function()
1002	{
1003		return BX.PageObject.getTopWindowOfCurrentHost(window);
1004	},
1005
1006	isCrossOriginObject: function(currentWindow)
1007	{
1008		try
1009		{
1010			void currentWindow.location.host;
1011		}
1012		catch (e)
1013		{
1014			// cross-origin object
1015			return true;
1016		}
1017
1018		return false;
1019	},
1020
1021	getTopWindowOfCurrentHost: function(currentWindow)
1022	{
1023		if (
1024			!BX.PageObject.isCrossOriginObject(currentWindow.parent)
1025			&& currentWindow.parent !== currentWindow
1026			&& currentWindow.parent.location.host === currentWindow.location.host
1027		)
1028		{
1029			return BX.PageObject.getTopWindowOfCurrentHost(currentWindow.parent);
1030		}
1031
1032		return currentWindow;
1033	},
1034
1035	getParentWindowOfCurrentHost: function(currentWindow)
1036	{
1037		if (BX.PageObject.isCrossOriginObject(currentWindow.parent))
1038		{
1039			return currentWindow;
1040		}
1041
1042		return currentWindow.parent;
1043	}
1044};
1045/* End */
1046;
1047; /* Start:"a:4:{s:4:"full";s:51:"/bitrix/js/main/core/core_window.js?174159735698766";s:6:"source";s:35:"/bitrix/js/main/core/core_window.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
1048;(function(window) {
1049if (BX.WindowManager) return;
1050
1051/* windows manager */
1052BX.WindowManager = {
1053	_stack: [],
1054	_runtime_resize: {},
1055	_delta: 2,
1056	_delta_start: 1000,
1057	currently_loaded: null,
1058
1059	settings_category: 'BX.WindowManager.9.5',
1060
1061	register: function (w)
1062	{
1063		this.currently_loaded = null;
1064
1065		w.WM_REG_INDEX = this._stack.length;
1066		this._stack.push(w);
1067
1068		if (this._stack.length < 2)
1069		{
1070			BX.bind(document, 'keyup', BX.proxy(this.__checkKeyPress, this));
1071		}
1072	},
1073
1074	unregister: function (w)
1075	{
1076		if (null == w.WM_REG_INDEX)
1077			return null;
1078
1079		var _current;
1080		if (this._stack.length > 0)
1081		{
1082			while ((_current = this.__pop_stack()) != w)
1083			{
1084				if (!_current)
1085				{
1086					_current = null;
1087					break;
1088				}
1089			}
1090
1091			if (this._stack.length <= 0)
1092			{
1093				this.enableKeyCheck();
1094			}
1095
1096			return _current;
1097		}
1098		else
1099		{
1100			return null;
1101		}
1102	},
1103
1104	__pop_stack: function(clean)
1105	{
1106		if (this._stack.length > 0)
1107		{
1108			var _current = this._stack.pop();
1109			_current.WM_REG_INDEX = null;
1110			BX.onCustomEvent(_current, 'onWindowUnRegister', [clean === true]);
1111
1112			return _current;
1113		}
1114		else
1115			return null;
1116	},
1117
1118	clean: function()
1119	{
1120		while (this.__pop_stack(true)){}
1121		this._stack = [];
1122		this.disableKeyCheck();
1123	},
1124
1125	Get: function()
1126	{
1127		if (this.currently_loaded)
1128			return this.currently_loaded;
1129		else if (this._stack.length > 0)
1130			return this._stack[this._stack.length-1];
1131		else
1132			return null;
1133	},
1134
1135	setStartZIndex: function(value)
1136	{
1137		this._delta_start = value;
1138	},
1139
1140	restoreStartZIndex: function()
1141	{
1142		this._delta_start = 1000;
1143	},
1144
1145	GetZIndex: function()
1146	{
1147		var _current;
1148		return (null != (_current = this._stack[this._stack.length-1])
1149			? parseInt(_current.Get().style.zIndex) + this._delta
1150			: this._delta_start
1151		);
1152	},
1153
1154	__get_check_url: function(url)
1155	{
1156		var pos = url.indexOf('?');
1157		return pos == -1 ? url : url.substring(0, pos);
1158	},
1159
1160	saveWindowSize: function(url, params)
1161	{
1162		var check_url = this.__get_check_url(url);
1163		if (BX.userOptions)
1164		{
1165			BX.userOptions.save(this.settings_category, 'size_' + check_url, 'width', params.width);
1166			BX.userOptions.save(this.settings_category, 'size_' + check_url, 'height', params.height);
1167		}
1168
1169		this._runtime_resize[check_url] = params;
1170	},
1171
1172	saveWindowOptions: function(wnd_id, opts)
1173	{
1174		if (BX.userOptions)
1175		{
1176			for (var i in opts)
1177			{
1178				if(opts.hasOwnProperty(i))
1179				{
1180					BX.userOptions.save(this.settings_category, 'options_' + wnd_id, i, opts[i]);
1181				}
1182			}
1183		}
1184	},
1185
1186	getRuntimeWindowSize: function(url)
1187	{
1188		return this._runtime_resize[this.__get_check_url(url)];
1189	},
1190
1191	disableKeyCheck: function()
1192	{
1193		BX.unbind(document, 'keyup', BX.proxy(this.__checkKeyPress, this));
1194	},
1195
1196	enableKeyCheck: function()
1197	{
1198		BX.bind(document, 'keyup', BX.proxy(this.__checkKeyPress, this));
1199	},
1200
1201	__checkKeyPress: function(e)
1202	{
1203		if (null == e)
1204			e = window.event;
1205
1206		if (e.keyCode == 27)
1207		{
1208			var wnd = BX.WindowManager.Get();
1209			if (wnd && !wnd.unclosable) wnd.Close();
1210		}
1211	}
1212};
1213
1214BX.garbage(BX.WindowManager.clean, BX.WindowManager);
1215
1216/* base button class */
1217BX.CWindowButton = function(params)
1218{
1219	if (params.btn)
1220	{
1221		this.btn = params.btn;
1222		this.parentWindow = params.parentWindow;
1223
1224		if (/save|apply/i.test(this.btn.name))
1225		{
1226			BX.bind(this.btn, 'click', BX.delegate(this.disableUntilError, this));
1227		}
1228	}
1229	else
1230	{
1231		this.title = params.title; // html value attr
1232		this.hint = params.hint; // html title attr
1233		this.id = params.id; // html name and id attrs
1234		this.name = params.name; // html name or value attrs when id and title 're absent
1235		this.className = params.className; // className for button input
1236
1237		this.action = params.action;
1238		this.onclick = params.onclick;
1239
1240		// you can override button creation method
1241		if (params.Button && BX.type.isFunction(params.Button))
1242			this.Button = params.Button;
1243
1244		this.btn = null;
1245	}
1246};
1247
1248BX.CWindowButton.prototype.disable = function()
1249{
1250	if (this.btn)
1251		this.parentWindow.showWait(this.btn);
1252};
1253BX.CWindowButton.prototype.enable = function(){
1254	if (this.btn)
1255		this.parentWindow.closeWait(this.btn);
1256};
1257
1258BX.CWindowButton.prototype.emulate = function()
1259{
1260	if (this.btn && this.btn.disabled)
1261		return;
1262
1263	var act =
1264		this.action
1265		? BX.delegate(this.action, this)
1266		: (
1267			this.onclick
1268			? this.onclick
1269			: (
1270				this.btn
1271				? this.btn.getAttribute('onclick')
1272				: ''
1273			)
1274		);
1275
1276	if (act)
1277	{
1278		setTimeout(act, 50);
1279		if (this.btn && /save|apply/i.test(this.btn.name) && !this.action)
1280		{
1281			this.disableUntilError();
1282		}
1283	}
1284};
1285
1286BX.CWindowButton.prototype.Button = function(parentWindow)
1287{
1288	this.parentWindow = parentWindow;
1289
1290	var btn = {
1291		props: {
1292			'type': 'button',
1293			'name': this.id ? this.id : this.name,
1294			'value': this.title ? this.title : this.name,
1295			'id': this.id
1296		}
1297	};
1298
1299	if (this.hint)
1300		btn.props.title = this.hint;
1301	if (!!this.className)
1302		btn.props.className = this.className;
1303
1304	if (this.action)
1305	{
1306		btn.events = {
1307			'click': BX.delegate(this.action, this)
1308		};
1309	}
1310	else if (this.onclick)
1311	{
1312		if (BX.browser.IsIE())
1313		{
1314			btn.events = {
1315				'click': BX.delegate(function() {eval(this.onclick)}, this)
1316			};
1317		}
1318		else
1319		{
1320			btn.attrs = {
1321				'onclick': this.onclick
1322			};
1323		}
1324	}
1325
1326	this.btn = BX.create('INPUT', btn);
1327
1328	return this.btn;
1329};
1330
1331BX.CWindowButton.prototype.disableUntilError = function() {
1332	this.disable();
1333	if (!this.__window_error_handler_set)
1334	{
1335		BX.addCustomEvent(this.parentWindow, 'onWindowError', BX.delegate(this.enable, this));
1336		this.__window_error_handler_set = true;
1337	}
1338};
1339
1340/* base window class */
1341BX.CWindow = function(div, type)
1342{
1343	this.DIV = div || document.createElement('DIV');
1344
1345	this.SETTINGS = {
1346		resizable: false,
1347		min_height: 0,
1348		min_width: 0,
1349		top: 0,
1350		left: 0,
1351		draggable: false,
1352		drag_restrict: true,
1353		resize_restrict: true
1354	};
1355
1356	this.ELEMENTS = {
1357		draggable: [],
1358		resizer: [],
1359		close: []
1360	};
1361
1362	this.type = type == 'float' ? 'float' : 'dialog';
1363
1364	BX.adjust(this.DIV, {
1365		props: {
1366			className: 'bx-core-window'
1367		},
1368		style: {
1369			'zIndex': 0,
1370			'position': 'absolute',
1371			'display': 'none',
1372			'top': this.SETTINGS.top + 'px',
1373			'left': this.SETTINGS.left + 'px',
1374			'height': '100px',
1375			'width': '100px'
1376		}
1377	});
1378
1379	this.isOpen = false;
1380
1381	BX.addCustomEvent(this, 'onWindowRegister', BX.delegate(this.onRegister, this));
1382	BX.addCustomEvent(this, 'onWindowUnRegister', BX.delegate(this.onUnRegister, this));
1383
1384	this.MOUSEOVER = null;
1385	BX.bind(this.DIV, 'mouseover', BX.delegate(this.__set_msover, this));
1386	BX.bind(this.DIV, 'mouseout', BX.delegate(this.__unset_msover, this));
1387
1388	BX.ready(BX.delegate(function() {
1389		document.body.appendChild(this.DIV);
1390		BX.ZIndexManager.register(this.DIV);
1391	}, this));
1392};
1393
1394BX.CWindow.prototype.Get = function () {return this.DIV};
1395BX.CWindow.prototype.visible = function() {return this.isOpen;};
1396
1397BX.CWindow.prototype.Show = function(bNotRegister)
1398{
1399	this.DIV.style.display = 'block';
1400
1401	if (!bNotRegister)
1402	{
1403		BX.WindowManager.register(this);
1404		BX.onCustomEvent(this, 'onWindowRegister');
1405	}
1406
1407	BX.ZIndexManager.bringToFront(this.DIV);
1408};
1409
1410BX.CWindow.prototype.Hide = function()
1411{
1412	BX.WindowManager.unregister(this);
1413	this.DIV.style.display = 'none';
1414};
1415
1416BX.CWindow.prototype.onRegister = function()
1417{
1418	this.isOpen = true;
1419};
1420
1421BX.CWindow.prototype.onUnRegister = function(clean)
1422{
1423	this.isOpen = false;
1424
1425	if (clean || (this.PARAMS && this.PARAMS.content_url))
1426	{
1427		if (clean) {BX.onCustomEvent(this, 'onWindowClose', [this, true]);}
1428
1429		if (this.DIV.parentNode)
1430			this.DIV.parentNode.removeChild(this.DIV);
1431	}
1432	else
1433	{
1434		this.DIV.style.display = 'none';
1435	}
1436};
1437
1438BX.CWindow.prototype.CloseDialog = // compatibility
1439BX.CWindow.prototype.Close = function(bImmediately)
1440{
1441	BX.onCustomEvent(this, 'onBeforeWindowClose', [this]);
1442	if (bImmediately !== true)
1443	{
1444		if (this.denyClose)
1445			return false;
1446	}
1447
1448	BX.onCustomEvent(this, 'onWindowClose', [this]);
1449
1450	//this crashes vis editor in ie via onWindowResizeExt event handler
1451	//if (this.bExpanded) this.__expand();
1452	// alternative version:
1453	if (this.bExpanded)
1454	{
1455		var pDocElement = BX.GetDocElement();
1456		BX.unbind(window, 'resize', BX.proxy(this.__expand_onresize, this));
1457		pDocElement.style.overflow = this.__expand_settings.overflow;
1458	}
1459
1460	BX.WindowManager.unregister(this);
1461
1462	return true;
1463};
1464
1465BX.CWindow.prototype.SetResize = function(elem)
1466{
1467	elem.style.cursor = 'se-resize';
1468	BX.bind(elem, 'mousedown', BX.proxy(this.__startResize, this));
1469
1470	this.ELEMENTS.resizer.push(elem);
1471	this.SETTINGS.resizable = true;
1472};
1473
1474BX.CWindow.prototype.SetExpand = function(elem, event_name)
1475{
1476	event_name = event_name || 'click';
1477	BX.bind(elem, event_name, BX.proxy(this.__expand, this));
1478};
1479
1480BX.CWindow.prototype.__expand_onresize = function()
1481{
1482	var windowSize = BX.GetWindowInnerSize();
1483	this.DIV.style.width = windowSize.innerWidth + "px";
1484	this.DIV.style.height = windowSize.innerHeight + "px";
1485
1486	BX.onCustomEvent(this, 'onWindowResize');
1487};
1488
1489BX.CWindow.prototype.__expand = function()
1490{
1491	var pDocElement = BX.GetDocElement();
1492
1493	if (!this.bExpanded)
1494	{
1495		var wndScroll = BX.GetWindowScrollPos(),
1496			wndSize = BX.GetWindowInnerSize();
1497
1498		this.__expand_settings = {
1499			resizable: this.SETTINGS.resizable,
1500			draggable: this.SETTINGS.draggable,
1501			width: this.DIV.style.width,
1502			height: this.DIV.style.height,
1503			left: this.DIV.style.left,
1504			top: this.DIV.style.top,
1505			scrollTop: wndScroll.scrollTop,
1506			scrollLeft: wndScroll.scrollLeft,
1507			overflow: BX.style(pDocElement, 'overflow')
1508		};
1509
1510		this.SETTINGS.resizable = false;
1511		this.SETTINGS.draggable = false;
1512
1513		window.scrollTo(0,0);
1514		pDocElement.style.overflow = 'hidden';
1515
1516		this.DIV.style.top = '0px';
1517		this.DIV.style.left = '0px';
1518
1519		this.DIV.style.width = wndSize.innerWidth + 'px';
1520		this.DIV.style.height = wndSize.innerHeight + 'px';
1521
1522		this.bExpanded = true;
1523
1524		BX.onCustomEvent(this, 'onWindowExpand');
1525		BX.onCustomEvent(this, 'onWindowResize');
1526
1527		BX.bind(window, 'resize', BX.proxy(this.__expand_onresize, this));
1528	}
1529	else
1530	{
1531		BX.unbind(window, 'resize', BX.proxy(this.__expand_onresize, this));
1532
1533		this.SETTINGS.resizable = this.__expand_settings.resizable;
1534		this.SETTINGS.draggable = this.__expand_settings.draggable;
1535
1536		pDocElement.style.overflow = this.__expand_settings.overflow;
1537
1538		this.DIV.style.top = this.__expand_settings.top;
1539		this.DIV.style.left = this.__expand_settings.left;
1540		this.DIV.style.width = this.__expand_settings.width;
1541		this.DIV.style.height = this.__expand_settings.height;
1542
1543		window.scrollTo(this.__expand_settings.scrollLeft, this.__expand_settings.scrollTop);
1544
1545		this.bExpanded = false;
1546
1547		BX.onCustomEvent(this, 'onWindowNarrow');
1548		BX.onCustomEvent(this, 'onWindowResize');
1549
1550	}
1551};
1552
1553BX.CWindow.prototype.Resize = function(x, y)
1554{
1555	var new_width = Math.max(x - this.pos.left + this.dx, this.SETTINGS.min_width);
1556	var new_height = Math.max(y - this.pos.top + this.dy, this.SETTINGS.min_height);
1557
1558	if (this.SETTINGS.resize_restrict)
1559	{
1560		var scrollSize = BX.GetWindowScrollSize();
1561
1562		if (this.pos.left + new_width > scrollSize.scrollWidth - this.dw)
1563			new_width = scrollSize.scrollWidth - this.pos.left - this.dw;
1564	}
1565
1566	this.DIV.style.width = new_width + 'px';
1567	this.DIV.style.height = new_height + 'px';
1568
1569	BX.onCustomEvent(this, 'onWindowResize');
1570};
1571
1572BX.CWindow.prototype.__startResize = function(e)
1573{
1574	if (!this.SETTINGS.resizable)
1575		return false;
1576
1577	if(!e) e = window.event;
1578
1579	this.wndSize = BX.GetWindowScrollPos();
1580	this.wndSize.innerWidth = BX.GetWindowInnerSize().innerWidth;
1581
1582	this.pos = BX.pos(this.DIV);
1583
1584	this.x = e.clientX + this.wndSize.scrollLeft;
1585	this.y = e.clientY + this.wndSize.scrollTop;
1586
1587	this.dx = this.pos.left + this.pos.width - this.x;
1588	this.dy = this.pos.top + this.pos.height - this.y;
1589	this.dw = this.pos.width - parseInt(this.DIV.style.width);
1590
1591	BX.bind(document, "mousemove", BX.proxy(this.__moveResize, this));
1592	BX.bind(document, "mouseup", BX.proxy(this.__stopResize, this));
1593
1594	if(document.body.setCapture)
1595		document.body.setCapture();
1596
1597	document.onmousedown = BX.False;
1598
1599	var b = document.body;
1600	b.ondrag = b.onselectstart = BX.False;
1601	b.style.MozUserSelect = this.DIV.style.MozUserSelect = 'none';
1602	b.style.cursor = 'se-resize';
1603
1604	BX.onCustomEvent(this, 'onWindowResizeStart');
1605
1606	return true;
1607};
1608
1609BX.CWindow.prototype.__moveResize = function(e)
1610{
1611	if(!e) e = window.event;
1612
1613	var windowScroll = BX.GetWindowScrollPos();
1614
1615	var x = e.clientX + windowScroll.scrollLeft;
1616	var y = e.clientY + windowScroll.scrollTop;
1617
1618	if(this.x == x && this.y == y)
1619		return;
1620
1621	this.Resize(x, y);
1622
1623	this.x = x;
1624	this.y = y;
1625};
1626
1627BX.CWindow.prototype.__stopResize = function()
1628{
1629	if(document.body.releaseCapture)
1630		document.body.releaseCapture();
1631
1632	BX.unbind(document, "mousemove", BX.proxy(this.__moveResize, this));
1633	BX.unbind(document, "mouseup", BX.proxy(this.__stopResize, this));
1634
1635	document.onmousedown = null;
1636
1637	var b = document.body;
1638	b.ondrag = b.onselectstart = null;
1639	b.style.MozUserSelect = this.DIV.style.MozUserSelect = '';
1640	b.style.cursor = '';
1641
1642	BX.onCustomEvent(this, 'onWindowResizeFinished')
1643};
1644
1645BX.CWindow.prototype.SetClose = function(elem)
1646{
1647	BX.bind(elem, 'click', BX.proxy(this.Close, this));
1648	this.ELEMENTS.close.push(elem);
1649};
1650
1651BX.CWindow.prototype.SetDraggable = function(elem)
1652{
1653	BX.bind(elem, 'mousedown', BX.proxy(this.__startDrag, this));
1654
1655	elem.style.cursor = 'move';
1656
1657	this.ELEMENTS.draggable.push(elem);
1658	this.SETTINGS.draggable = true;
1659};
1660
1661BX.CWindow.prototype.Move = function(x, y)
1662{
1663	var dxShadow = 1; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1664
1665	var left = parseInt(this.DIV.style.left)+x;
1666	var top = parseInt(this.DIV.style.top)+y;
1667
1668	if (this.SETTINGS.drag_restrict)
1669	{
1670		//Left side
1671		if (left < 0)
1672			left = 0;
1673
1674		//Right side
1675		var scrollSize = BX.GetWindowScrollSize();
1676		var floatWidth = this.DIV.offsetWidth;
1677		var floatHeight = this.DIV.offsetHeight;
1678
1679		if (left > (scrollSize.scrollWidth - floatWidth - dxShadow))
1680			left = scrollSize.scrollWidth - floatWidth - dxShadow;
1681
1682		var scrollHeight = Math.max(
1683			document.body.scrollHeight, document.documentElement.scrollHeight,
1684			document.body.offsetHeight, document.documentElement.offsetHeight,
1685			document.body.clientHeight, document.documentElement.clientHeight,
1686			scrollSize.scrollHeight
1687		);
1688
1689		if (top > (scrollHeight - floatHeight - dxShadow))
1690			top = scrollHeight - floatHeight - dxShadow;
1691
1692		//Top side
1693		if (top < 0)
1694			top = 0;
1695	}
1696
1697	this.DIV.style.left = left+'px';
1698	this.DIV.style.top = top+'px';
1699
1700	//this.AdjustShadow(div);
1701};
1702
1703BX.CWindow.prototype.__startDrag = function(e)
1704{
1705	if (!this.SETTINGS.draggable)
1706		return false;
1707
1708	if(!e) e = window.event;
1709
1710	this.x = e.clientX + document.body.scrollLeft;
1711	this.y = e.clientY + document.body.scrollTop;
1712
1713	this.__bWasDragged = false;
1714	BX.bind(document, "mousemove", BX.proxy(this.__moveDrag, this));
1715	BX.bind(document, "mouseup", BX.proxy(this.__stopDrag, this));
1716
1717	if(document.body.setCapture)
1718		document.body.setCapture();
1719
1720	document.onmousedown = BX.False;
1721
1722	var b = document.body;
1723	b.ondrag = b.onselectstart = BX.False;
1724	b.style.MozUserSelect = this.DIV.style.MozUserSelect = 'none';
1725	b.style.cursor = 'move';
1726	return BX.PreventDefault(e);
1727};
1728
1729BX.CWindow.prototype.__moveDrag = function(e)
1730{
1731	if(!e) e = window.event;
1732
1733	var x = e.clientX + document.body.scrollLeft;
1734	var y = e.clientY + document.body.scrollTop;
1735
1736	if(this.x == x && this.y == y)
1737		return;
1738
1739	this.Move((x - this.x), (y - this.y));
1740	this.x = x;
1741	this.y = y;
1742
1743	if (!this.__bWasDragged)
1744	{
1745		BX.onCustomEvent(this, 'onWindowDragStart');
1746		this.__bWasDragged = true;
1747		BX.bind(BX.proxy_context, "click", BX.PreventDefault);
1748	}
1749
1750	BX.onCustomEvent(this, 'onWindowDrag');
1751};
1752
1753BX.CWindow.prototype.__stopDrag = function(e)
1754{
1755	if(document.body.releaseCapture)
1756		document.body.releaseCapture();
1757
1758	BX.unbind(document, "mousemove", BX.proxy(this.__moveDrag, this));
1759	BX.unbind(document, "mouseup", BX.proxy(this.__stopDrag, this));
1760
1761	document.onmousedown = null;
1762
1763	var b = document.body;
1764	b.ondrag = b.onselectstart = null;
1765	b.style.MozUserSelect = this.DIV.style.MozUserSelect = '';
1766	b.style.cursor = '';
1767
1768	if (this.__bWasDragged)
1769	{
1770		BX.onCustomEvent(this, 'onWindowDragFinished');
1771		var _proxy_context = BX.proxy_context;
1772		setTimeout(function(){BX.unbind(_proxy_context, "click", BX.PreventDefault)}, 100);
1773		this.__bWasDragged = false;
1774	}
1775	return BX.PreventDefault(e);
1776};
1777
1778BX.CWindow.prototype.DenyClose = function()
1779{
1780	this.denyClose = true;
1781};
1782
1783BX.CWindow.prototype.AllowClose = function()
1784{
1785	this.denyClose = false;
1786};
1787
1788BX.CWindow.prototype.ShowError = function(str)
1789{
1790	BX.onCustomEvent(this, 'onWindowError', [str]);
1791
1792	if (this._wait)
1793		BX.closeWait(this._wait);
1794
1795	window.alert(str);
1796};
1797
1798BX.CWindow.prototype.__set_msover = function() {this.MOUSEOVER = true;};
1799BX.CWindow.prototype.__unset_msover = function() {this.MOUSEOVER = false;};
1800
1801/* dialog window class extends window class */
1802BX.CWindowDialog = function() {
1803	var a = arguments;
1804	a[1] = 'dialog';
1805	BX.CWindowDialog.superclass.constructor.apply(this, a);
1806
1807	this.DIV.style.top = '10px';
1808	this.OVERLAY = null;
1809};
1810BX.extend(BX.CWindowDialog, BX.CWindow);
1811
1812BX.CWindowDialog.prototype.__resizeOverlay = function()
1813{
1814	var windowSize = BX.GetWindowScrollSize();
1815	this.OVERLAY.style.width = windowSize.scrollWidth + "px";
1816};
1817
1818BX.CWindowDialog.prototype.CreateOverlay = function(zIndex)
1819{
1820	if (null == this.OVERLAY)
1821	{
1822		var windowSize = BX.GetWindowScrollSize();
1823
1824		// scrollHeight in BX.GetWindowScrollSize may be incorrect
1825		var scrollHeight = Math.max(
1826			document.body.scrollHeight, document.documentElement.scrollHeight,
1827			document.body.offsetHeight, document.documentElement.offsetHeight,
1828			document.body.clientHeight, document.documentElement.clientHeight,
1829			windowSize.scrollHeight
1830		);
1831
1832		this.OVERLAY = document.body.appendChild(BX.create("DIV", {
1833			style: {
1834				position: 'absolute',
1835				top: '0px',
1836				left: '0px',
1837				zIndex: zIndex || (parseInt(this.DIV.style.zIndex)-2),
1838				width: windowSize.scrollWidth + "px",
1839				height: scrollHeight + "px"
1840			}
1841		}));
1842
1843		var component = BX.ZIndexManager.getComponent(this.DIV);
1844		if (component)
1845		{
1846			component.setOverlay(this.OVERLAY);
1847		}
1848	}
1849
1850	return this.OVERLAY;
1851};
1852
1853BX.CWindowDialog.prototype.Show = function()
1854{
1855	BX.CWindowDialog.superclass.Show.apply(this, arguments);
1856
1857	this.CreateOverlay();
1858
1859	this.OVERLAY.style.display = 'block';
1860
1861	BX.unbind(window, 'resize', BX.proxy(this.__resizeOverlay, this));
1862	BX.bind(window, 'resize', BX.proxy(this.__resizeOverlay, this));
1863};
1864
1865BX.CWindowDialog.prototype.onUnRegister = function(clean)
1866{
1867	BX.CWindowDialog.superclass.onUnRegister.apply(this, arguments);
1868
1869	if (this.clean)
1870	{
1871		if (this.OVERLAY.parentNode)
1872			this.OVERLAY.parentNode.removeChild(this.OVERLAY);
1873	}
1874	else
1875	{
1876		this.OVERLAY.style.display = 'none';
1877	}
1878
1879	BX.unbind(window, 'resize', BX.proxy(this.__resizeOverlay, this));
1880};
1881
1882/* standard bitrix dialog extends BX.CWindowDialog */
1883/*
1884	arParams = {
1885		(
1886			title: 'dialog title',
1887			head: 'head block html',
1888			content: 'dialog content',
1889			icon: 'head icon classname or filename',
1890
1891			resize_id: 'some id to save resize information'// useless if resizable = false
1892		)
1893		or
1894		(
1895			content_url: url to content load
1896				loaded content scripts can use BX.WindowManager.Get() to get access to the current window object
1897		)
1898
1899		height: window_height_in_pixels,
1900		width: window_width_in_pixels,
1901
1902		draggable: true|false,
1903		resizable: true|false,
1904
1905		min_height: min_window_height_in_pixels, // useless if resizable = false
1906		min_width: min_window_width_in_pixels, // useless if resizable = false
1907
1908		buttons: [
1909			'html_code',
1910			BX.CDialog.btnSave, BX.CDialog.btnCancel, BX.CDialog.btnClose
1911		]
1912	}
1913*/
1914BX.CDialog = function(arParams)
1915{
1916	BX.CDialog.superclass.constructor.apply(this);
1917
1918	this._sender = 'core_window_cdialog';
1919
1920	this.PARAMS = arParams || {};
1921
1922	for (var i in this.defaultParams)
1923	{
1924		if (typeof this.PARAMS[i] == 'undefined')
1925			this.PARAMS[i] = this.defaultParams[i];
1926	}
1927
1928	this.PARAMS.width = (!isNaN(parseInt(this.PARAMS.width)))
1929		? this.PARAMS.width
1930		: this.defaultParams['width'];
1931	this.PARAMS.height = (!isNaN(parseInt(this.PARAMS.height)))
1932		? this.PARAMS.height
1933		: this.defaultParams['height'];
1934
1935	if (this.PARAMS.resize_id || this.PARAMS.content_url)
1936	{
1937		var arSize = BX.WindowManager.getRuntimeWindowSize(this.PARAMS.resize_id || this.PARAMS.content_url);
1938		if (arSize)
1939		{
1940			this.PARAMS.width = arSize.width;
1941			this.PARAMS.height = arSize.height;
1942		}
1943	}
1944
1945	BX.addClass(this.DIV, 'bx-core-adm-dialog');
1946	this.DIV.id = 'bx-admin-prefix';
1947
1948	this.PARTS = {};
1949
1950	this.DIV.style.height = null;
1951	this.DIV.style.width = null;
1952
1953	this.PARTS.TITLEBAR = this.DIV.appendChild(BX.create('DIV', {props: {
1954			className: 'bx-core-adm-dialog-head'
1955		}
1956	}));
1957
1958	this.PARTS.TITLE_CONTAINER = this.PARTS.TITLEBAR.appendChild(BX.create('SPAN', {
1959		props: {className: 'bx-core-adm-dialog-head-inner'},
1960		text: this.PARAMS.title
1961	}));
1962
1963	this.PARTS.TITLEBAR_ICONS = this.PARTS.TITLEBAR.appendChild(BX.create('DIV', {
1964		props: {
1965			className: 'bx-core-adm-dialog-head-icons'
1966		},
1967		children: (this.PARAMS.resizable ? [
1968			BX.create('SPAN', {props: {className: 'bx-core-adm-icon-expand', title: BX.message('JS_CORE_WINDOW_EXPAND')}}),
1969			BX.create('SPAN', {props: {className: 'bx-core-adm-icon-close', title: BX.message('JS_CORE_WINDOW_CLOSE')}})
1970		] : [
1971			BX.create('SPAN', {props: {className: 'bx-core-adm-icon-close', title: BX.message('JS_CORE_WINDOW_CLOSE')}})
1972		])
1973	}));
1974
1975
1976	this.PARTS.CONTENT = this.DIV.appendChild(BX.create('DIV', {
1977		props: {className: 'bx-core-adm-dialog-content-wrap adm-workarea'}
1978	}));
1979
1980	this.PARTS.CONTENT_DATA = this.PARTS.CONTENT.appendChild(BX.create('DIV', {
1981		props: {className: 'bx-core-adm-dialog-content'},
1982		style: {
1983			height: this.PARAMS.height + 'px',
1984			width: this.PARAMS.width + 'px'
1985		}
1986	}));
1987
1988	this.PARTS.HEAD = this.PARTS.CONTENT_DATA.appendChild(BX.create('DIV', {
1989		props: {
1990			className: 'bx-core-adm-dialog-head-block' + (this.PARAMS.icon ? ' ' + this.PARAMS.icon : '')
1991		}
1992	}));
1993
1994	this.SetHead(this.PARAMS.head);
1995	this.SetContent(this.PARAMS.content);
1996	this.SetTitle(this.PARAMS.title);
1997	this.SetClose(this.PARTS.TITLEBAR_ICONS.lastChild);
1998
1999	if (this.PARAMS.resizable)
2000	{
2001		this.SetExpand(this.PARTS.TITLEBAR_ICONS.firstChild);
2002		this.SetExpand(this.PARTS.TITLEBAR, 'dblclick');
2003
2004		BX.addCustomEvent(this, 'onWindowExpand', BX.proxy(this.__onexpand, this));
2005		BX.addCustomEvent(this, 'onWindowNarrow', BX.proxy(this.__onexpand, this));
2006	}
2007
2008	this.PARTS.FOOT = this.PARTS.BUTTONS_CONTAINER = this.PARTS.CONTENT.appendChild(BX.create('DIV', {
2009			props: {
2010				className: 'bx-core-adm-dialog-buttons'
2011			},
2012			//events: {
2013			//	'click': BX.delegateEvent({property:{type: /button|submit/}}, BX.delegate(function() {this.showWait(BX.proxy_context)}, this))
2014			//},
2015			children: this.ShowButtons()
2016		}
2017	));
2018
2019	if (this.PARAMS.draggable)
2020		this.SetDraggable(this.PARTS.TITLEBAR);
2021
2022	if (this.PARAMS.resizable)
2023	{
2024		this.PARTS.RESIZER = this.DIV.appendChild(BX.create('DIV', {
2025			props: {className: 'bx-core-resizer'}
2026		}));
2027
2028		this.SetResize(this.PARTS.RESIZER);
2029
2030		this.SETTINGS.min_width = this.PARAMS.min_width;
2031		this.SETTINGS.min_height = this.PARAMS.min_height;
2032	}
2033
2034	this.auth_callback = BX.delegate(function(){
2035		this.PARAMS.content = '';
2036		this.hideNotify();
2037		this.Show();
2038	}, this)
2039};
2040BX.extend(BX.CDialog, BX.CWindowDialog);
2041
2042BX.CDialog.prototype.defaultParams = {
2043	width: 700,
2044	height: 400,
2045	min_width: 500,
2046	min_height: 300,
2047
2048	resizable: true,
2049	draggable: true,
2050
2051	title: '',
2052	icon: ''
2053};
2054
2055BX.CDialog.prototype.showWait = function(el)
2056{
2057	if (BX.type.isElementNode(el) && (el.type == 'button' || el.type == 'submit'))
2058	{
2059		BX.defer(function(){el.disabled = true})();
2060
2061		var bSave = (BX.hasClass(el, 'adm-btn-save') || BX.hasClass(el, 'adm-btn-save')),
2062			pos = BX.pos(el, true);
2063
2064		el.bxwaiter = this.PARTS.FOOT.appendChild(BX.create('DIV', {
2065			props: {className: 'adm-btn-load-img' + (bSave ? '-green' : '')},
2066			style: {
2067				top: parseInt((pos.bottom + pos.top)/2 - 10) + 'px',
2068				left: parseInt((pos.right + pos.left)/2 - 10) + 'px'
2069			}
2070		}));
2071
2072		BX.addClass(el, 'adm-btn-load');
2073
2074		this.lastWaitElement = el;
2075
2076		return el.bxwaiter;
2077	}
2078	return null;
2079};
2080
2081BX.CDialog.prototype.closeWait = function(el)
2082{
2083	el = el || this.lastWaitElement;
2084
2085	if (BX.type.isElementNode(el))
2086	{
2087		if (el.bxwaiter)
2088		{
2089			if(el.bxwaiter.parentNode)
2090			{
2091				el.bxwaiter.parentNode.removeChild(el.bxwaiter);
2092			}
2093
2094			el.bxwaiter = null;
2095		}
2096
2097		el.disabled = false;
2098		BX.removeClass(el, 'adm-btn-load');
2099
2100		if (this.lastWaitElement == el)
2101			this.lastWaitElement = null;
2102	}
2103};
2104
2105BX.CDialog.prototype.Authorize = function(arAuthResult)
2106{
2107	this.bSkipReplaceContent = true;
2108	this.ShowError(BX.message('JSADM_AUTH_REQ'));
2109
2110	BX.onCustomEvent(this, 'onWindowError', []);
2111
2112	BX.closeWait();
2113
2114	(new BX.CAuthDialog({
2115		content_url: this.PARAMS.content_url,
2116		auth_result: arAuthResult,
2117		callback: BX.delegate(function(){
2118			if (this.auth_callback)
2119				this.auth_callback()
2120		}, this)
2121	})).Show();
2122};
2123
2124BX.CDialog.prototype.ShowError = function(str)
2125{
2126	BX.onCustomEvent(this, 'onWindowError', [str]);
2127
2128	this.closeWait();
2129
2130	if (this._wait)
2131		BX.closeWait(this._wait);
2132
2133	this.Notify(str, true);
2134};
2135
2136
2137BX.CDialog.prototype.__expandGetSize = function()
2138{
2139	var pDocElement = BX.GetDocElement();
2140	pDocElement.style.overflow = 'hidden';
2141
2142	var wndSize = BX.GetWindowInnerSize();
2143
2144	pDocElement.scrollTop = 0;
2145
2146	this.DIV.style.top = '-' + this.dxShadow + 'px';
2147	this.DIV.style.left = '-' + this.dxShadow + 'px';
2148
2149	return {
2150		width: (wndSize.innerWidth - parseInt(BX.style(this.PARTS.CONTENT, 'padding-right')) - parseInt(BX.style(this.PARTS.CONTENT, 'padding-left'))) + this.dxShadow,
2151		height: (wndSize.innerHeight - this.PARTS.TITLEBAR.offsetHeight - this.PARTS.FOOT.offsetHeight - parseInt(BX.style(this.PARTS.CONTENT, 'padding-top')) - parseInt(BX.style(this.PARTS.CONTENT, 'padding-bottom'))) + this.dxShadow
2152	};
2153};
2154
2155BX.CDialog.prototype.__expand = function()
2156{
2157	var pDocElement = BX.GetDocElement();
2158	this.dxShadow = 2;
2159
2160	if (!this.bExpanded)
2161	{
2162		var wndScroll = BX.GetWindowScrollPos();
2163
2164		this.__expand_settings = {
2165			resizable: this.SETTINGS.resizable,
2166			draggable: this.SETTINGS.draggable,
2167			width: this.PARTS.CONTENT_DATA.style.width,
2168			height: this.PARTS.CONTENT_DATA.style.height,
2169			left: this.DIV.style.left,
2170			top: this.DIV.style.top,
2171			scrollTop: wndScroll.scrollTop,
2172			scrollLeft: wndScroll.scrollLeft,
2173			overflow: BX.style(pDocElement, 'overflow')
2174		};
2175
2176		this.SETTINGS.resizable = false;
2177		this.SETTINGS.draggable = false;
2178
2179		var pos = this.__expandGetSize();
2180
2181		this.PARTS.CONTENT_DATA.style.width = pos.width + 'px';
2182		this.PARTS.CONTENT_DATA.style.height = pos.height + 'px';
2183
2184		window.scrollTo(0,0);
2185		pDocElement.style.overflow = 'hidden';
2186
2187		this.bExpanded = true;
2188
2189		BX.onCustomEvent(this, 'onWindowExpand');
2190		BX.onCustomEvent(this, 'onWindowResize');
2191		BX.onCustomEvent(this, 'onWindowResizeExt', [{'width': pos.width, 'height': pos.height}]);
2192
2193		BX.bind(window, 'resize', BX.proxy(this.__expand_onresize, this));
2194	}
2195	else
2196	{
2197		BX.unbind(window, 'resize', BX.proxy(this.__expand_onresize, this));
2198
2199		this.SETTINGS.resizable = this.__expand_settings.resizable;
2200		this.SETTINGS.draggable = this.__expand_settings.draggable;
2201
2202		pDocElement.style.overflow = this.__expand_settings.overflow;
2203
2204		this.DIV.style.top = this.__expand_settings.top;
2205		this.DIV.style.left = this.__expand_settings.left;
2206		this.PARTS.CONTENT_DATA.style.width = this.__expand_settings.width;
2207		this.PARTS.CONTENT_DATA.style.height = this.__expand_settings.height;
2208		window.scrollTo(this.__expand_settings.scrollLeft, this.__expand_settings.scrollTop);
2209		this.bExpanded = false;
2210
2211		BX.onCustomEvent(this, 'onWindowNarrow');
2212		BX.onCustomEvent(this, 'onWindowResize');
2213		BX.onCustomEvent(this, 'onWindowResizeExt', [{'width': parseInt(this.__expand_settings.width), 'height': parseInt(this.__expand_settings.height)}]);
2214	}
2215};
2216
2217BX.CDialog.prototype.__expand_onresize = function()
2218{
2219	var pos = this.__expandGetSize();
2220
2221	this.PARTS.CONTENT_DATA.style.width = pos.width + 'px';
2222	this.PARTS.CONTENT_DATA.style.height = pos.height + 'px';
2223
2224	BX.onCustomEvent(this, 'onWindowResize');
2225	BX.onCustomEvent(this, 'onWindowResizeExt', [pos]);
2226};
2227
2228BX.CDialog.prototype.__onexpand = function()
2229{
2230	var ob = this.PARTS.TITLEBAR_ICONS.firstChild;
2231	ob.className = BX.toggle(ob.className, ['bx-core-adm-icon-expand', 'bx-core-adm-icon-narrow']);
2232	ob.title = BX.toggle(ob.title, [BX.message('JS_CORE_WINDOW_EXPAND'), BX.message('JS_CORE_WINDOW_NARROW')]);
2233
2234	if (this.PARTS.RESIZER)
2235	{
2236		this.PARTS.RESIZER.style.display = this.bExpanded ? 'none' : 'block';
2237	}
2238};
2239
2240
2241BX.CDialog.prototype.__startResize = function(e)
2242{
2243	if (!this.SETTINGS.resizable)
2244		return false;
2245
2246	if(!e) e = window.event;
2247
2248	this.wndSize = BX.GetWindowScrollPos();
2249	this.wndSize.innerWidth = BX.GetWindowInnerSize().innerWidth;
2250
2251	this.pos = BX.pos(this.PARTS.CONTENT_DATA);
2252
2253	this.x = e.clientX + this.wndSize.scrollLeft;
2254	this.y = e.clientY + this.wndSize.scrollTop;
2255
2256	this.dx = this.pos.left + this.pos.width - this.x;
2257	this.dy = this.pos.top + this.pos.height - this.y;
2258
2259
2260	// TODO: suspicious
2261	this.dw = this.pos.width - parseInt(this.PARTS.CONTENT_DATA.style.width) + parseInt(BX.style(this.PARTS.CONTENT, 'padding-right'));
2262
2263	BX.bind(document, "mousemove", BX.proxy(this.__moveResize, this));
2264	BX.bind(document, "mouseup", BX.proxy(this.__stopResize, this));
2265
2266	if(document.body.setCapture)
2267		document.body.setCapture();
2268
2269	document.onmousedown = BX.False;
2270
2271	var b = document.body;
2272	b.ondrag = b.onselectstart = BX.False;
2273	b.style.MozUserSelect = this.DIV.style.MozUserSelect = 'none';
2274	b.style.cursor = 'se-resize';
2275
2276	BX.onCustomEvent(this, 'onWindowResizeStart');
2277
2278	return true;
2279};
2280
2281BX.CDialog.prototype.Resize = function(x, y)
2282{
2283	var new_width = Math.max(x - this.pos.left + this.dx, this.SETTINGS.min_width);
2284	var new_height = Math.max(y - this.pos.top + this.dy, this.SETTINGS.min_height);
2285
2286	if (this.SETTINGS.resize_restrict)
2287	{
2288		var scrollSize = BX.GetWindowScrollSize();
2289
2290		if (this.pos.left + new_width > scrollSize.scrollWidth - this.dw)
2291			new_width = scrollSize.scrollWidth - this.pos.left - this.dw;
2292	}
2293
2294	this.PARTS.CONTENT_DATA.style.width = new_width + 'px';
2295	this.PARTS.CONTENT_DATA.style.height = new_height + 'px';
2296
2297	BX.onCustomEvent(this, 'onWindowResize');
2298	BX.onCustomEvent(this, 'onWindowResizeExt', [{'height': new_height, 'width': new_width}]);
2299};
2300
2301BX.CDialog.prototype.SetSize = function(obSize)
2302{
2303	this.PARTS.CONTENT_DATA.style.width = obSize.width + 'px';
2304	this.PARTS.CONTENT_DATA.style.height = obSize.height + 'px';
2305
2306	BX.onCustomEvent(this, 'onWindowResize');
2307	BX.onCustomEvent(this, 'onWindowResizeExt', [obSize]);
2308};
2309
2310BX.CDialog.prototype.GetParameters = function(form_name)
2311{
2312	var form = this.GetForm();
2313
2314	if(!form)
2315		return "";
2316
2317	var i, s = "";
2318	var n = form.elements.length;
2319
2320	var delim = '';
2321	for(i=0; i<n; i++)
2322	{
2323		if (s != '') delim = '&';
2324		var el = form.elements[i];
2325		if (el.disabled)
2326			continue;
2327
2328		switch(el.type.toLowerCase())
2329		{
2330			case 'text':
2331			case 'textarea':
2332			case 'password':
2333			case 'hidden':
2334				if (null == form_name && el.name.substr(el.name.length-4) == '_alt' && form.elements[el.name.substr(0, el.name.length-4)])
2335					break;
2336				s += delim + el.name + '=' + BX.util.urlencode(el.value);
2337				break;
2338			case 'radio':
2339				if(el.checked)
2340					s += delim + el.name + '=' + BX.util.urlencode(el.value);
2341				break;
2342			case 'checkbox':
2343				s += delim + el.name + '=' + BX.util.urlencode(el.checked ? 'Y':'N');
2344				break;
2345			case 'select-one':
2346				var val = "";
2347				if (null == form_name && form.elements[el.name + '_alt'] && el.selectedIndex == 0)
2348					val = form.elements[el.name+'_alt'].value;
2349				else
2350					val = el.value;
2351				s += delim + el.name + '=' + BX.util.urlencode(val);
2352				break;
2353			case 'select-multiple':
2354				var j, bAdded = false;
2355				var l = el.options.length;
2356				for (j=0; j<l; j++)
2357				{
2358					if (el.options[j].selected)
2359					{
2360						s += delim + el.name + '=' + BX.util.urlencode(el.options[j].value);
2361						bAdded = true;
2362					}
2363				}
2364				if (!bAdded)
2365					s += delim + el.name + '=';
2366				break;
2367			default:
2368				break;
2369		}
2370	}
2371
2372	return s;
2373};
2374
2375BX.CDialog.prototype.PostParameters = function(params)
2376{
2377	var url = this.PARAMS.content_url;
2378
2379	if (null == params)
2380		params = "";
2381
2382	params += (params == "" ? "" : "&") + "bxsender=" + this._sender;
2383
2384	var index = url.indexOf('?');
2385	if (index == -1)
2386		url += '?' + params;
2387	else
2388		url = url.substring(0, index) + '?' + params + "&" + url.substring(index+1);
2389
2390	BX.showWait();
2391
2392	this.auth_callback = BX.delegate(function(){
2393		this.hideNotify();
2394		this.PostParameters(params);
2395	}, this);
2396
2397	BX.ajax.Setup({skipAuthCheck:true},true);
2398	BX.ajax.post(url, this.GetParameters(), BX.delegate(function(result) {
2399		BX.closeWait();
2400		if (!this.bSkipReplaceContent)
2401		{
2402			this.ClearButtons(); // buttons are appended during form reload, so we should clear footer
2403			this.SetContent(result);
2404			this.Show(true);
2405		}
2406
2407		this.bSkipReplaceContent = false;
2408	}, this));
2409};
2410
2411BX.CDialog.prototype.Submit = function(params, url)
2412{
2413	var FORM = this.GetForm();
2414	if (FORM)
2415	{
2416		FORM.onsubmit = null;
2417
2418		FORM.method = 'POST';
2419		if (!FORM.action || url)
2420		{
2421			url = url || this.PARAMS.content_url;
2422			if (null != params)
2423			{
2424				var index = url.indexOf('?');
2425				if (index == -1)
2426					url += '?' + params;
2427				else
2428					url = url.substring(0, index) + '?' + params + "&" + url.substring(index+1);
2429			}
2430
2431			FORM.action = url;
2432		}
2433
2434		if (!FORM._bxsender)
2435		{
2436			FORM._bxsender = FORM.appendChild(BX.create('INPUT', {
2437				attrs: {
2438					type: 'hidden',
2439					name: 'bxsender',
2440					value: this._sender
2441				}
2442			}));
2443		}
2444
2445		this._wait = BX.showWait();
2446
2447		this.auth_callback = BX.delegate(function(){
2448			this.hideNotify();
2449			this.Submit(params);
2450		}, this);
2451
2452		BX.ajax.submit(FORM, BX.delegate(function(){this.closeWait()}, this));
2453	}
2454	else
2455	{
2456		window.alert('no form registered!');
2457	}
2458};
2459
2460BX.CDialog.prototype.GetForm = function()
2461{
2462	if (null == this.__form)
2463	{
2464		var forms = this.PARTS.CONTENT_DATA.getElementsByTagName('FORM');
2465		this.__form = forms[0] ? forms[0] : null;
2466	}
2467
2468	return this.__form;
2469};
2470
2471BX.CDialog.prototype.GetRealForm = function()
2472{
2473	if (null == this.__rform)
2474	{
2475		var forms = this.PARTS.CONTENT_DATA.getElementsByTagName('FORM');
2476		this.__rform = forms[1] ? forms[1] : (forms[0] ? forms[0] : null);
2477	}
2478
2479	return this.__rform;
2480};
2481
2482BX.CDialog.prototype._checkButton = function(btn)
2483{
2484	var arCustomButtons = ['btnSave', 'btnCancel', 'btnClose'];
2485
2486	for (var i = 0; i < arCustomButtons.length; i++)
2487	{
2488		if (this[arCustomButtons[i]] && (btn == this[arCustomButtons[i]]))
2489			return arCustomButtons[i];
2490	}
2491
2492	return false;
2493};
2494
2495BX.CDialog.prototype.ShowButtons = function()
2496{
2497	var result = [];
2498	if (this.PARAMS.buttons)
2499	{
2500		if (this.PARAMS.buttons.title) this.PARAMS.buttons = [this.PARAMS.buttons];
2501
2502		for (var i=0, len=this.PARAMS.buttons.length; i<len; i++)
2503		{
2504			if (BX.type.isNotEmptyString(this.PARAMS.buttons[i]))
2505			{
2506				result.push(this.PARAMS.buttons[i]);
2507			}
2508			else if (BX.type.isElementNode(this.PARAMS.buttons[i]))
2509			{
2510				result.push(this.PARAMS.buttons[i]);
2511			}
2512			else if (this.PARAMS.buttons[i])
2513			{
2514				//if (!(this.PARAMS.buttons[i] instanceof BX.CWindowButton))
2515				if (!BX.is_subclass_of(this.PARAMS.buttons[i], BX.CWindowButton))
2516				{
2517					var b = this._checkButton(this.PARAMS.buttons[i]); // hack to set links to real CWindowButton object in btnSave etc;
2518					this.PARAMS.buttons[i] = new BX.CWindowButton(this.PARAMS.buttons[i]);
2519					if (b) this[b] = this.PARAMS.buttons[i];
2520				}
2521
2522				result.push(this.PARAMS.buttons[i].Button(this));
2523			}
2524		}
2525	}
2526
2527	return result;
2528};
2529
2530BX.CDialog.prototype.setAutosave = function () {
2531	if (!this.bSetAutosaveDelay)
2532	{
2533		this.bSetAutosaveDelay = true;
2534		setTimeout(BX.proxy(this.setAutosave, this), 10);
2535	}
2536};
2537
2538BX.CDialog.prototype.SetTitle = function(title)
2539{
2540	this.PARAMS.title = title;
2541	BX.cleanNode(this.PARTS.TITLE_CONTAINER).appendChild(document.createTextNode(this.PARAMS.title));
2542};
2543
2544BX.CDialog.prototype.SetHead = function(head)
2545{
2546	this.PARAMS.head = BX.util.trim(head);
2547	this.PARTS.HEAD.innerHTML = this.PARAMS.head || "&nbsp;";
2548	this.PARTS.HEAD.style.display = this.PARAMS.head ? 'block' : 'none';
2549	this.adjustSize();
2550};
2551
2552BX.CDialog.prototype.Notify = function(note, bError, html)
2553{
2554	if (!this.PARTS.NOTIFY)
2555	{
2556		this.PARTS.NOTIFY = this.DIV.insertBefore(BX.create('DIV', {
2557			props: {className: 'adm-warning-block'},
2558			children: [
2559				BX.create('SPAN', {
2560					props: {className: 'adm-warning-text'}
2561				}),
2562				BX.create('SPAN', {
2563					props: {className: 'adm-warning-icon'}
2564				}),
2565				BX.create('SPAN', {
2566					props: {className: 'adm-warning-close'},
2567					events: {click: BX.proxy(this.hideNotify, this)}
2568				})
2569			]
2570		}), this.DIV.firstChild);
2571	}
2572
2573	if (bError)
2574		BX.addClass(this.PARTS.NOTIFY, 'adm-warning-block-red');
2575	else
2576		BX.removeClass(this.PARTS.NOTIFY, 'adm-warning-block-red');
2577
2578	if(html !== true)
2579	{
2580		note = BX.util.htmlspecialchars(note);
2581	}
2582
2583	this.PARTS.NOTIFY.firstChild.innerHTML = note || '&nbsp;';
2584	this.PARTS.NOTIFY.firstChild.style.width = (this.PARAMS.width-50) + 'px';
2585	BX.removeClass(this.PARTS.NOTIFY, 'adm-warning-animate');
2586};
2587
2588BX.CDialog.prototype.hideNotify = function()
2589{
2590	BX.addClass(this.PARTS.NOTIFY, 'adm-warning-animate');
2591};
2592
2593BX.CDialog.prototype.__adjustHeadToIcon = function()
2594{
2595	if (!this.PARTS.HEAD.offsetHeight)
2596	{
2597		setTimeout(BX.delegate(this.__adjustHeadToIcon, this), 50);
2598	}
2599	else
2600	{
2601		if (this.icon_image && this.icon_image.height && this.icon_image.height > this.PARTS.HEAD.offsetHeight - 5)
2602		{
2603			this.PARTS.HEAD.style.height = this.icon_image.height + 5 + 'px';
2604			this.adjustSize();
2605		}
2606
2607		this.icon_image.onload = null;
2608		this.icon_image = null;
2609	}
2610};
2611
2612BX.CDialog.prototype.SetIcon = function(icon_class)
2613{
2614	if (this.PARAMS.icon != icon_class)
2615	{
2616		if (this.PARAMS.icon)
2617			BX.removeClass(this.PARTS.HEAD, this.PARAMS.icon);
2618
2619		this.PARAMS.icon = icon_class;
2620
2621		if (this.PARAMS.icon)
2622		{
2623			BX.addClass(this.PARTS.HEAD, this.PARAMS.icon);
2624
2625			var icon_file = (BX.style(this.PARTS.HEAD, 'background-image') || BX.style(this.PARTS.HEAD, 'backgroundImage'));
2626			if (BX.type.isNotEmptyString(icon_file) && icon_file != 'none')
2627			{
2628				var match = icon_file.match(new RegExp('url\\s*\\(\\s*(\'|"|)(.+?)(\\1)\\s*\\)'));
2629				if(match)
2630				{
2631					icon_file = match[2];
2632					if (BX.type.isNotEmptyString(icon_file))
2633					{
2634						this.icon_image = new Image();
2635						this.icon_image.onload = BX.delegate(this.__adjustHeadToIcon, this);
2636						this.icon_image.src = icon_file;
2637					}
2638				}
2639			}
2640		}
2641	}
2642	this.adjustSize();
2643};
2644
2645BX.CDialog.prototype.SetIconFile = function(icon_file)
2646{
2647	this.icon_image = new Image();
2648	this.icon_image.onload = BX.delegate(this.__adjustHeadToIcon, this);
2649	this.icon_image.src = icon_file;
2650
2651	BX.adjust(this.PARTS.HEAD, {style: {backgroundImage: 'url(' + icon_file + ')', backgroundPosition: 'right 9px'/*'99% center'*/}});
2652	this.adjustSize();
2653};
2654
2655/*
2656BUTTON: {
2657	title: 'title',
2658	'action': function executed in window object context
2659}
2660BX.CDialog.btnSave || BX.CDialog.btnCancel - standard buttons
2661*/
2662
2663BX.CDialog.prototype.SetButtons = function(a)
2664{
2665	if (BX.type.isString(a))
2666	{
2667		if (a.length > 0)
2668		{
2669			this.PARTS.BUTTONS_CONTAINER.innerHTML += a;
2670
2671			var btns = this.PARTS.BUTTONS_CONTAINER.getElementsByTagName('INPUT');
2672			if (btns.length > 0)
2673			{
2674				this.PARAMS.buttons = [];
2675				for (var i = 0; i < btns.length; i++)
2676				{
2677					this.PARAMS.buttons.push(new BX.CWindowButton({btn: btns[i], parentWindow: this}));
2678				}
2679			}
2680		}
2681	}
2682	else
2683	{
2684		this.PARAMS.buttons = a;
2685		BX.adjust(this.PARTS.BUTTONS_CONTAINER, {
2686			children: this.ShowButtons()
2687		});
2688	}
2689	this.adjustSize();
2690};
2691
2692BX.CDialog.prototype.ClearButtons = function()
2693{
2694	BX.cleanNode(this.PARTS.BUTTONS_CONTAINER);
2695	this.adjustSize();
2696};
2697
2698BX.CDialog.prototype.SetContent = function(html)
2699{
2700	this.__form = null;
2701
2702	if (BX.type.isElementNode(html))
2703	{
2704		if (html.parentNode)
2705			html.parentNode.removeChild(html);
2706	}
2707	else if (BX.type.isString(html))
2708	{
2709		html = BX.create('DIV', {html: html});
2710	}
2711
2712	this.PARAMS.content = html;
2713	BX.cleanNode(this.PARTS.CONTENT_DATA);
2714
2715	BX.adjust(this.PARTS.CONTENT_DATA, {
2716		children: [
2717			this.PARTS.HEAD,
2718			BX.create('DIV', {
2719				props: {
2720					className: 'bx-core-adm-dialog-content-wrap-inner'
2721				},
2722				children: [this.PARAMS.content]
2723			})
2724		]
2725	});
2726
2727	if (this.PARAMS.content_url && this.GetForm())
2728	{
2729		this.__form.submitbtn = this.__form.appendChild(BX.create('INPUT', {props:{type:'submit'},style:{display:'none'}}));
2730		this.__form.onsubmit = BX.delegate(this.__submit, this);
2731	}
2732};
2733
2734BX.CDialog.prototype.__submit = function(e)
2735{
2736	for (var i=0,len=this.PARAMS.buttons.length; i<len; i++)
2737	{
2738		if (
2739			this.PARAMS.buttons[i]
2740			&& (
2741				this.PARAMS.buttons[i].name && /save|apply/i.test(this.PARAMS.buttons[i].name)
2742				||
2743				this.PARAMS.buttons[i].btn && this.PARAMS.buttons[i].btn.name && /save|apply/i.test(this.PARAMS.buttons[i].btn.name)
2744			)
2745		)
2746		{
2747			this.PARAMS.buttons[i].emulate();
2748			break;
2749		}
2750	}
2751
2752	return BX.PreventDefault(e);
2753};
2754
2755BX.CDialog.prototype.SwapContent = function(cont)
2756{
2757	cont = BX(cont);
2758
2759	BX.cleanNode(this.PARTS.CONTENT_DATA);
2760	cont.parentNode.removeChild(cont);
2761	this.PARTS.CONTENT_DATA.appendChild(cont);
2762	cont.style.display = 'block';
2763	this.SetContent(cont.innerHTML);
2764};
2765
2766// this method deprecated
2767BX.CDialog.prototype.adjustSize = function()
2768{
2769};
2770
2771// this method deprecated
2772BX.CDialog.prototype.__adjustSize = function()
2773{
2774};
2775
2776BX.CDialog.prototype.adjustSizeEx = function()
2777{
2778	BX.defer(this.__adjustSizeEx, this)();
2779};
2780
2781BX.CDialog.prototype.__adjustSizeEx = function()
2782{
2783	var ob = this.PARTS.CONTENT_DATA.firstChild,
2784		new_height = 0,
2785		marginTop,
2786		marginBottom;
2787
2788	while (ob)
2789	{
2790		if (BX.type.isElementNode(ob))
2791		{
2792			marginTop = parseInt(BX.style(ob, 'margin-top'), 10);
2793			if (isNaN(marginTop))
2794				marginTop = 0;
2795			marginBottom = parseInt(BX.style(ob, 'margin-bottom'), 10);
2796			if (isNaN(marginBottom))
2797				marginBottom = 0;
2798			new_height += ob.offsetHeight + marginTop + marginBottom;
2799		}
2800		ob = BX.nextSibling(ob);
2801	}
2802
2803	if (new_height)
2804		this.PARTS.CONTENT_DATA.style.height = new_height + 'px';
2805};
2806
2807
2808BX.CDialog.prototype.__onResizeFinished = function()
2809{
2810	BX.WindowManager.saveWindowSize(
2811		this.PARAMS.resize_id || this.PARAMS.content_url, {height: parseInt(this.PARTS.CONTENT_DATA.style.height), width: parseInt(this.PARTS.CONTENT_DATA.style.width)}
2812	);
2813};
2814
2815BX.CDialog.prototype.Show = function(bNotRegister)
2816{
2817	if ((!this.PARAMS.content) && this.PARAMS.content_url && BX.ajax && !bNotRegister)
2818	{
2819		var wait = BX.showWait();
2820
2821		BX.WindowManager.currently_loaded = this;
2822
2823		this.CreateOverlay();
2824		this.OVERLAY.style.display = 'block';
2825		this.OVERLAY.className = 'bx-core-dialog-overlay';
2826
2827		var post_data = '', method = 'GET';
2828		if (this.PARAMS.content_post)
2829		{
2830			post_data = this.PARAMS.content_post;
2831			method = 'POST';
2832		}
2833
2834		var url = this.PARAMS.content_url
2835			+ (this.PARAMS.content_url.indexOf('?')<0?'?':'&')+'bxsender=' + this._sender;
2836
2837		this.auth_callback = BX.delegate(function(){
2838			this.PARAMS.content = '';
2839			this.hideNotify();
2840			this.Show();
2841		}, this);
2842
2843		BX.ajax({
2844			method: method,
2845			dataType: 'html',
2846			url: url,
2847			data: post_data,
2848			skipAuthCheck: true,
2849			onsuccess: BX.delegate(function(data) {
2850				BX.closeWait(null, wait);
2851
2852				this.SetContent(data || '&nbsp;');
2853				this.Show();
2854			}, this)
2855		});
2856	}
2857	else
2858	{
2859		BX.WindowManager.currently_loaded = null;
2860		BX.CDialog.superclass.Show.apply(this, arguments);
2861
2862		this.adjustPos();
2863
2864		this.OVERLAY.className = 'bx-core-dialog-overlay';
2865
2866		this.__adjustSize();
2867
2868		BX.removeCustomEvent(this, 'onWindowResize', BX.proxy(this.__adjustSize, this));
2869		BX.addCustomEvent(this, 'onWindowResize', BX.proxy(this.__adjustSize, this));
2870
2871		if (this.PARAMS.resizable && (this.PARAMS.content_url || this.PARAMS.resize_id))
2872		{
2873			BX.removeCustomEvent(this, 'onWindowResizeFinished', BX.proxy(this.__onResizeFinished, this));
2874			BX.addCustomEvent(this, 'onWindowResizeFinished', BX.proxy(this.__onResizeFinished, this));
2875		}
2876	}
2877};
2878
2879BX.CDialog.prototype.GetInnerPos = function()
2880{
2881	return {'width': parseInt(this.PARTS.CONTENT_DATA.style.width), 'height': parseInt(this.PARTS.CONTENT_DATA.style.height)};
2882};
2883
2884BX.CDialog.prototype.adjustPos = function()
2885{
2886	if (!this.bExpanded)
2887	{
2888		var currentWindow = window;
2889		var topWindow = BX.PageObject.getRootWindow();
2890		if (topWindow.BX.SidePanel && topWindow.BX.SidePanel.Instance && topWindow.BX.SidePanel.Instance.getTopSlider())
2891		{
2892			currentWindow = topWindow.BX.SidePanel.Instance.getTopSlider().getWindow();
2893		}
2894		var windowSize = currentWindow.BX.GetWindowInnerSize();
2895		var windowScroll = currentWindow.BX.GetWindowScrollPos();
2896
2897		var style = {
2898			left: parseInt(windowScroll.scrollLeft + windowSize.innerWidth / 2 - parseInt(this.DIV.offsetWidth) / 2) + 'px',
2899			top: Math.max(parseInt(windowScroll.scrollTop + windowSize.innerHe
2899ight / 2 - parseInt(this.DIV.offsetHeight) / 2), 0) + 'px'
2900		};
2901
2902		BX.adjust(this.DIV, {
2903			style: style
2904		});
2905	}
2906};
2907
2908BX.CDialog.prototype.GetContent = function () {return this.PARTS.CONTENT_DATA};
2909
2910BX.CDialog.prototype.btnSave = BX.CDialog.btnSave = {
2911	title: BX.message('JS_CORE_WINDOW_SAVE'),
2912	id: 'savebtn',
2913	name: 'savebtn',
2914	className: BX.browser.IsIE() && BX.browser.IsDoctype() && !BX.browser.IsIE10() ? '' : 'adm-btn-save',
2915	action: function () {
2916		this.disableUntilError();
2917		this.parentWindow.PostParameters();
2918	}
2919};
2920
2921BX.CDialog.prototype.btnCancel = BX.CDialog.btnCancel = {
2922	title: BX.message('JS_CORE_WINDOW_CANCEL'),
2923	id: 'cancel',
2924	name: 'cancel',
2925	action: function () {
2926		this.parentWindow.Close();
2927	}
2928};
2929
2930BX.CDialog.prototype.btnClose = BX.CDialog.btnClose = {
2931	title: BX.message('JS_CORE_WINDOW_CLOSE'),
2932	id: 'close',
2933	name: 'close',
2934	action: function () {
2935		this.parentWindow.Close();
2936	}
2937};
2938
2939/* special child for admin forms loaded into public page */
2940BX.CAdminDialog = function(arParams)
2941{
2942	BX.CAdminDialog.superclass.constructor.apply(this, arguments);
2943
2944	this._sender = 'core_window_cadmindialog';
2945
2946	BX.addClass(this.DIV, 'bx-core-adm-admin-dialog');
2947
2948	this.PARTS.CONTENT.insertBefore(this.PARTS.HEAD, this.PARTS.CONTENT.firstChild);
2949	this.PARTS.HEAD.className = 'bx-core-adm-dialog-tabs';
2950};
2951BX.extend(BX.CAdminDialog, BX.CDialog);
2952
2953BX.CAdminDialog.prototype.SetHead = function()
2954{
2955	BX.CAdminDialog.superclass.SetHead.apply(this, arguments);
2956
2957	if (this.PARTS.HEAD.firstChild && BX.type.isElementNode(this.PARTS.HEAD.firstChild))
2958	{
2959		var ob = this.PARTS.HEAD.firstChild, new_width = 0, marginLeft = 0, marginRight = 0;
2960
2961		while (ob)
2962		{
2963			if (BX.type.isElementNode(ob))
2964			{
2965				marginLeft = parseInt(BX.style(ob, 'margin-left'), 10);
2966				if (isNaN(marginLeft))
2967					marginLeft = 0;
2968				marginRight = parseInt(BX.style(ob, 'margin-right'), 10);
2969				if (isNaN(marginRight))
2970					marginRight = 0;
2971				new_width += ob.offsetWidth + marginLeft + marginRight;
2972			}
2973			ob = BX.nextSibling(ob);
2974		}
2975
2976		this.SETTINGS.min_width = Math.max(new_width, this.SETTINGS.min_width) - 2;
2977		if (this.PARAMS.width < this.SETTINGS.min_width)
2978		{
2979			BX.adjust(this.PARTS.CONTENT_DATA, {
2980				style: {
2981					width: this.SETTINGS.min_width + 'px'
2982				}
2983			});
2984		}
2985	}
2986};
2987
2988BX.CAdminDialog.prototype.SetContent = function(html)
2989{
2990	this.__form = null;
2991
2992	if (BX.type.isElementNode(html))
2993	{
2994		if (html.parentNode)
2995			html.parentNode.removeChild(html);
2996	}
2997
2998	this.PARAMS.content = html;
2999	BX.cleanNode(this.PARTS.CONTENT_DATA);
3000
3001	BX.adjust(this.PARTS.CONTENT_DATA, {
3002		children: [
3003			this.PARAMS.content || '&nbsp;'
3004		]
3005	});
3006
3007	if (this.PARAMS.content_url && this.GetForm())
3008	{
3009		this.__form.appendChild(BX.create('INPUT', {props:{type:'submit'},style:{display:'none'}}));
3010		this.__form.onsubmit = BX.delegate(this.__submit, this);
3011	}
3012};
3013
3014BX.CAdminDialog.prototype.__expandGetSize = function()
3015{
3016	var res = BX.CAdminDialog.superclass.__expandGetSize.apply(this, arguments);
3017
3018	res.width -= parseInt(BX.style(this.PARTS.CONTENT_DATA, 'padding-right')) + parseInt(BX.style(this.PARTS.CONTENT_DATA, 'padding-left'));
3019	res.height -= parseInt(BX.style(this.PARTS.CONTENT_DATA, 'padding-top')) + parseInt(BX.style(this.PARTS.CONTENT_DATA, 'padding-bottom'));
3020
3021	res.height -= this.PARTS.HEAD.offsetHeight;
3022
3023	return res;
3024};
3025
3026BX.CAdminDialog.prototype.Submit = function()
3027{
3028	var FORM = this.GetForm();
3029	if (FORM && !FORM['bxpublic'] && !/bxpublic=/.test(FORM.action))
3030	{
3031		FORM.appendChild(BX.create('INPUT', {
3032			props: {
3033				type: 'hidden',
3034				name: 'bxpublic',
3035				value: 'Y'
3036			}
3037		}));
3038	}
3039
3040	return BX.CAdminDialog.superclass.Submit.apply(this, arguments);
3041};
3042
3043BX.CAdminDialog.prototype.btnSave = BX.CAdminDialog.btnSave = {
3044	title: BX.message('JS_CORE_WINDOW_SAVE'),
3045	id: 'savebtn',
3046	name: 'savebtn',
3047	className: 'adm-btn-save',
3048	action: function () {
3049		this.disableUntilError();
3050		this.parentWindow.Submit();
3051	}
3052};
3053
3054BX.CAdminDialog.btnCancel = BX.CAdminDialog.superclass.btnCancel;
3055BX.CAdminDialog.btnClose = BX.CAdminDialog.superclass.btnClose;
3056
3057BX.CDebugDialog = function(arParams)
3058{
3059	BX.CDebugDialog.superclass.constructor.apply(this, arguments);
3060};
3061BX.extend(BX.CDebugDialog, BX.CDialog);
3062
3063BX.CDebugDialog.prototype.ShowDetails = function(div_id)
3064{
3065	var div = BX(div_id);
3066	if (div)
3067	{
3068		if (this.div_detail_current)
3069			this.div_detail_current.style.display = 'none';
3070
3071		div.style.display = 'block';
3072		this.div_detail_current = div;
3073	}
3074};
3075
3076BX.CDebugDialog.prototype.SetContent = function(html)
3077{
3078	if (!html)
3079		return;
3080
3081	var arHtml = html.split('#DIVIDER#');
3082	if (arHtml.length > 1)
3083	{
3084		this.PARAMS.content = arHtml[1];
3085
3086		this.PARTS.CONTENT_DATA.style.overflow = 'hidden';
3087
3088		BX.CDebugDialog.superclass.SetContent.apply(this, [arHtml[1]]);
3089
3090		this.PARTS.CONTENT_INNER = this.PARTS.CONTENT_DATA.firstChild.nextSibling;
3091		this.PARTS.CONTENT_TOP = this.PARTS.CONTENT_DATA.insertBefore(BX.create('DIV', {
3092			props: {
3093				className: 'bx-debug-content-top'
3094			},
3095			html: arHtml[0]
3096		}), this.PARTS.CONTENT_INNER);
3097		this.PARTS.CONTENT_INNER.style.overflow = 'auto';
3098	}
3099	else
3100	{
3101		BX.CDebugDialog.superclass.SetContent.apply(this, arguments);
3102	}
3103};
3104
3105BX.CDebugDialog.prototype.__adjustSize = function()
3106{
3107	BX.CDebugDialog.superclass.__adjustSize.apply(this, arguments);
3108
3109	if (this.PARTS.CONTENT_TOP)
3110	{
3111		var new_height = this.PARTS.CONTENT_DATA.offsetHeight - this.PARTS.HEAD.offsetHeight - this.PARTS.CONTENT_TOP.offsetHeight - 38;
3112
3113		if (new_height > 0)
3114		{
3115			this.PARTS.CONTENT_INNER.style.height = new_height + 'px';
3116		}
3117	}
3118};
3119
3120
3121/* class for dialog window with editors */
3122
3123BX.CEditorDialog = function(arParams)
3124{
3125	BX.CEditorDialog.superclass.constructor.apply(this, arguments);
3126
3127	BX.removeClass(this.PARTS.CONTENT, 'bx-core-adm-dialog-content-wrap');
3128	BX.removeClass(this.PARTS.CONTENT_DATA, 'bx-core-adm-dialog-content');
3129
3130	BX.removeClass(this.PARTS.CONTENT_DATA.lastChild, 'bx-core-adm-dialog-content-wrap-inner');
3131	BX.removeClass(this.PARTS.BUTTONS_CONTAINER, 'bx-core-adm-dialog-buttons');
3132
3133	BX.addClass(this.PARTS.CONTENT, 'bx-core-editor-dialog-content-wrap');
3134	BX.addClass(this.PARTS.CONTENT_DATA, 'bx-core-editor-dialog-content');
3135	BX.addClass(this.PARTS.BUTTONS_CONTAINER, 'bx-core-editor-dialog-buttons');
3136};
3137BX.extend(BX.CEditorDialog, BX.CDialog);
3138
3139BX.CEditorDialog.prototype.SetContent  = function()
3140{
3141	BX.CEditorDialog.superclass.SetContent.apply(this, arguments);
3142
3143	BX.removeClass(this.PARTS.CONTENT_DATA.lastChild, 'bx-core-adm-dialog-content-wrap-inner');
3144};
3145
3146/* class for wizards in admin section */
3147BX.CWizardDialog = function(arParams)
3148{
3149	BX.CWizardDialog.superclass.constructor.apply(this, arguments);
3150
3151	BX.removeClass(this.PARTS.CONTENT, 'bx-core-adm-dialog-content-wrap');
3152	BX.removeClass(this.PARTS.CONTENT_DATA, 'bx-core-adm-dialog-content');
3153	BX.removeClass(this.PARTS.CONTENT_DATA.lastChild, 'bx-core-adm-dialog-content-wrap-inner');
3154	BX.removeClass(this.PARTS.BUTTONS_CONTAINER, 'bx-core-adm-dialog-buttons');
3155
3156	BX.addClass(this.PARTS.CONTENT, 'bx-core-wizard-dialog-content-wrap');
3157};
3158
3159BX.extend(BX.CWizardDialog, BX.CDialog);
3160
3161/* class for auth dialog */
3162BX.CAuthDialog = function(arParams)
3163{
3164	arParams.resizable = false;
3165	arParams.width = 350;
3166	arParams.height = 200;
3167
3168	arParams.buttons = [this.btnSave];
3169
3170	BX.CAuthDialog.superclass.constructor.apply(this, arguments);
3171	this._sender = 'core_window_cauthdialog';
3172
3173	BX.addClass(this.DIV, 'bx-core-auth-dialog');
3174
3175	BX.AUTHAGENT = this;
3176};
3177BX.extend(BX.CAuthDialog, BX.CDialog);
3178
3179BX.CAuthDialog.prototype.btnSave = BX.CAuthDialog.btnSave = {
3180	title: BX.message('JS_CORE_WINDOW_AUTH'),
3181	id: 'savebtn',
3182	name: 'savebtn',
3183	className: 'adm-btn-save',
3184	action: function () {
3185		this.disableUntilError();
3186		this.parentWindow.Submit('', this.parentWindow.PARAMS.content_url);
3187	}
3188};
3189
3190BX.CAuthDialog.prototype.SetError = function(error)
3191{
3192	BX.closeWait();
3193
3194	if (!!error)
3195		this.ShowError(error.MESSAGE || error);
3196};
3197
3198BX.CAuthDialog.prototype.setAuthResult = function(result)
3199{
3200	BX.closeWait();
3201
3202	if (result === false)
3203	{
3204		this.Close();
3205		if (this.PARAMS.callback)
3206			this.PARAMS.callback();
3207	}
3208	else
3209	{
3210		this.SetError(result);
3211	}
3212};
3213
3214/* MENU CLASSES */
3215
3216BX.CWindowFloat = function(node)
3217{
3218	BX.CWindowFloat.superclass.constructor.apply(this, [node, 'float']);
3219
3220	this.SETTINGS.resizable = false;
3221};
3222BX.extend(BX.CWindowFloat, BX.CWindow);
3223
3224BX.CWindowFloat.prototype.adjustPos = function()
3225{
3226	if (this.PARAMS.parent)
3227		this.adjustToNode();
3228	else if (this.PARAMS.x && this.PARAMS.y)
3229		this.adjustToPos([this.PARAMS.x, this.PARAMS.y]);
3230};
3231
3232BX.CWindowFloat.prototype.adjustToPos = function(pos)
3233{
3234	this.DIV.style.left = parseInt(pos[0]) + 'px';
3235	this.DIV.style.top = parseInt(pos[1]) + 'px';
3236};
3237
3238BX.CWindowFloat.prototype.adjustToNodeGetPos = function()
3239{
3240	return BX.pos(this.PARAMS.parent);
3241};
3242
3243BX.CWindowFloat.prototype.adjustToNode = function(el)
3244{
3245	el = el || this.PARAMS.parent;
3246
3247	this.PARAMS.parent = BX(el);
3248
3249	if (this.PARAMS.parent)
3250	{
3251		var pos = this.adjustToNodeGetPos();
3252
3253		this.DIV.style.top = pos.top + 'px';//(pos.top - 26) + 'px';
3254		this.DIV.style.left = pos.left + 'px';
3255
3256		this.PARAMS.parent.OPENER = this;
3257	}
3258};
3259
3260BX.CWindowFloat.prototype.Show = function()
3261{
3262	this.adjustToPos([-1000, -1000]);
3263	BX.CWindowFloat.superclass.Show.apply(this, arguments);
3264	this.adjustPos();
3265};
3266
3267/* menu opener class */
3268/*
3269{
3270	DOMNode DIV,
3271	BX.CMenu or Array MENU,
3272	TYPE = 'hover' | 'click',
3273	TIMEOUT: 1000
3274	ATTACH_MODE: 'top' | 'right'
3275	ACTIVE_CLASS: className for opener element when menu is opened
3276}
3277*/
3278BX.COpener = function(arParams)
3279{
3280	this.PARAMS = arParams || {};
3281
3282	this.MENU = arParams.MENU || [];
3283
3284	this.DIV = arParams.DIV;
3285	this.ATTACH = arParams.ATTACH || arParams.DIV;
3286	this.ATTACH_MODE = arParams.ATTACH_MODE || 'bottom';
3287
3288	this.ACTIVE_CLASS = arParams.ACTIVE_CLASS || '';
3289	this.PUBLIC_FRAME = arParams.PUBLIC_FRAME || 0;
3290	this.LEVEL = arParams.LEVEL || 0;
3291
3292	this.CLOSE_ON_CLICK = typeof arParams.CLOSE_ON_CLICK != 'undefined' ? !!arParams.CLOSE_ON_CLICK : true;
3293	this.ADJUST_ON_CLICK = typeof arParams.ADJUST_ON_CLICK != 'undefined' ? !!arParams.ADJUST_ON_CLICK : true;
3294
3295	this.TYPE = this.PARAMS.TYPE == 'hover' ? 'hover' : 'click';
3296
3297	this._openTimeout = null;
3298
3299	if (this.PARAMS.TYPE == 'hover' && arParams.TIMEOUT !== 0)
3300		this.TIMEOUT = arParams.TIMEOUT || 1000;
3301	else
3302		this.TIMEOUT = 0;
3303
3304	this.bMenuInit = false;
3305
3306	if (!!this.PARAMS.MENU_URL)
3307	{
3308		this.bMenuLoaded = false;
3309		this.bMenuLoading = false;
3310
3311		this.MENU = [{
3312			TEXT: BX.message('JS_CORE_LOADING'),
3313			CLOSE_ON_CLICK: false
3314		}];
3315
3316		if (this.PARAMS.MENU_PRELOAD)
3317		{
3318			BX.defer(this.Load, this)();
3319		}
3320	}
3321
3322	BX.ready(BX.defer(this.Init, this));
3323};
3324
3325BX.COpener.prototype.Init = function()
3326{
3327	this.DIV = BX(this.DIV);
3328
3329	switch (this.TYPE)
3330	{
3331		case 'hover':
3332			BX.bind(this.DIV, 'mouseover', BX.proxy(this.Open, this));
3333			BX.bind(this.DIV, 'click', BX.proxy(this.Toggle, this));
3334		break;
3335
3336		case 'click':
3337			BX.bind(this.DIV, 'click', BX.proxy(this.Toggle, this));
3338		break;
3339	}
3340
3341	//BX.bind(window, 'scroll', BX.delegate(this.__close_immediately, this));
3342
3343	//this.bMenuInit = false;
3344};
3345
3346BX.COpener.prototype.Load = function()
3347{
3348	if (this.PARAMS.MENU_URL && !this.bMenuLoaded)
3349	{
3350		if (!this.bMenuLoading)
3351		{
3352			var url = this.PARAMS.MENU_URL;
3353			if (url.indexOf('sessid=') <= 0)
3354				url += (url.indexOf('?') > 0 ? '&' : '?') + 'sessid=' + BX.bitrix_sessid();
3355
3356			this.bMenuLoading = true;
3357			BX.ajax.loadJSON(url, BX.proxy(this.SetMenu, this), BX.proxy(this.LoadFailed, this));
3358		}
3359	}
3360};
3361
3362BX.COpener.prototype.SetMenu = function(menu)
3363{
3364	this.bMenuLoaded = true;
3365	this.bMenuLoading = false;
3366	if (this.bMenuInit)
3367	{
3368		this.MENU.setItems(menu);
3369	}
3370	else
3371	{
3372		this.MENU = menu;
3373	}
3374};
3375
3376BX.COpener.prototype.LoadFailed = function(type, error)
3377{
3378	this.bMenuLoading = false;
3379	this.SetMenu([{
3380		TEXT: BX.message('JS_CORE_NO_DATA'),
3381		CLOSE_ON_CLICK: true
3382	}]);
3383	BX.debug(arguments);
3384};
3385
3386BX.COpener.prototype.checkAdminMenu = function()
3387{
3388	if (document.documentElement.id == 'bx-admin-prefix')
3389		return true;
3390
3391	return !!BX.findParent(this.DIV, {property: {id: 'bx-admin-prefix'}});
3392};
3393
3394BX.COpener.prototype.Toggle = function(e)
3395{
3396	this.__clear_timeout();
3397
3398	if (!this.bMenuInit || !this.MENU.visible())
3399	{
3400		var t = this.TIMEOUT;
3401		this.TIMEOUT = 0;
3402		this.Open(e);
3403		this.TIMEOUT = t;
3404	}
3405	else
3406	{
3407		this.MENU.Close();
3408	}
3409
3410	return !!(e||window.event) && BX.PreventDefault(e);
3411};
3412
3413BX.COpener.prototype.GetMenu = function()
3414{
3415	if (!this.bMenuInit)
3416	{
3417		if (BX.type.isArray(this.MENU))
3418		{
3419			this.MENU = new BX.CMenu({
3420				ITEMS: this.MENU,
3421				ATTACH_MODE: this.ATTACH_MODE,
3422				SET_ID: this.checkAdminMenu() ? 'bx-admin-prefix' : '',
3423				CLOSE_ON_CLICK: !!this.CLOSE_ON_CLICK,
3424				ADJUST_ON_CLICK: !!this.ADJUST_ON_CLICK,
3425				PUBLIC_FRAME: !!this.PUBLIC_FRAME,
3426				LEVEL: this.LEVEL,
3427				parent: BX(this.DIV),
3428				parent_attach: BX(this.ATTACH)
3429			});
3430
3431			if (this.LEVEL > 0)
3432			{
3433				BX.bind(this.MENU.DIV, 'mouseover', BX.proxy(this._on_menu_hover, this));
3434				BX.bind(this.MENU.DIV, 'mouseout', BX.proxy(this._on_menu_hout, this));
3435			}
3436		}
3437
3438		BX.addCustomEvent(this.MENU, 'onMenuOpen', BX.proxy(this.handler_onopen, this));
3439		BX.addCustomEvent(this.MENU, 'onMenuClose', BX.proxy(this.handler_onclose, this));
3440
3441		BX.addCustomEvent('onMenuItemHover', BX.proxy(this.handler_onover, this));
3442
3443		this.bMenuInit = true;
3444	}
3445
3446	return this.MENU;
3447};
3448
3449BX.COpener.prototype.Open = function()
3450{
3451	this.GetMenu();
3452
3453	this.bOpen = true;
3454
3455	this.__clear_timeout();
3456
3457	if (this.TIMEOUT > 0)
3458	{
3459		BX.bind(this.DIV, 'mouseout', BX.proxy(this.__clear_timeout, this));
3460		this._openTimeout = setTimeout(BX.proxy(this.__open, this), this.TIMEOUT);
3461	}
3462	else
3463	{
3464		this.__open();
3465	}
3466
3467	if (!!this.PARAMS.MENU_URL && !this.bMenuLoaded)
3468	{
3469		this._loadTimeout = setTimeout(BX.proxy(this.Load, this), parseInt(this.TIMEOUT/2));
3470	}
3471
3472	return true;
3473};
3474
3475BX.COpener.prototype.__clear_timeout = function()
3476{
3477	if (!!this._openTimeout)
3478		clearTimeout(this._openTimeout);
3479	if (!!this._loadTimeout)
3480		clearTimeout(this._loadTimeout);
3481
3482	BX.unbind(this.DIV, 'mouseout', BX.proxy(this.__clear_timeout, this));
3483};
3484
3485BX.COpener.prototype._on_menu_hover = function()
3486{
3487	this.bMenuHover = true;
3488
3489	this.__clear_timeout();
3490
3491	if (this.ACTIVE_CLASS)
3492		BX.addClass(this.DIV, this.ACTIVE_CLASS);
3493
3494};
3495
3496BX.COpener.prototype._on_menu_hout = function()
3497{
3498	this.bMenuHover = false;
3499};
3500
3501BX.COpener.prototype.handler_onover = function(level, opener)
3502{
3503	if (this.bMenuHover)
3504		return;
3505
3506	if (opener != this && level == this.LEVEL-1 && this.ACTIVE_CLASS)
3507	{
3508		BX.removeClass(this.DIV, this.ACTIVE_CLASS);
3509	}
3510
3511	if (this.bMenuInit && level <= this.LEVEL-1 && this.MENU.visible())
3512	{
3513		if (opener != this)
3514		{
3515			this.__clear_timeout();
3516			this._openTimeout = setTimeout(BX.proxy(this.Close, this), this.TIMEOUT);
3517		}
3518	}
3519};
3520
3521BX.COpener.prototype.handler_onopen = function()
3522{
3523	this.bOpen = true;
3524
3525	if (this.ACTIVE_CLASS)
3526		BX.addClass(this.DIV, this.ACTIVE_CLASS);
3527
3528	BX.defer(function() {
3529		BX.onCustomEvent(this, 'onOpenerMenuOpen');
3530	}, this)();
3531};
3532
3533BX.COpener.prototype.handler_onclose = function()
3534{
3535	this.bOpen = false;
3536	BX.onCustomEvent(this, 'onOpenerMenuClose');
3537
3538	if (this.ACTIVE_CLASS)
3539		BX.removeClass(this.DIV, this.ACTIVE_CLASS);
3540};
3541
3542BX.COpener.prototype.Close = function()
3543{
3544	if (!this.bMenuInit)
3545		return;
3546
3547	if (!!this._openTimeout)
3548		clearTimeout(this._openTimeout);
3549
3550	this.bOpen = false;
3551
3552	this.__close();
3553};
3554
3555BX.COpener.prototype.__open = function()
3556{
3557	this.__clear_timeout();
3558
3559	if (this.bMenuInit && this.bOpen && !this.MENU.visible())
3560		this.MENU.Show();
3561};
3562
3563BX.COpener.prototype.__close = function()
3564{
3565	if (this.bMenuInit && !this.bOpen && this.MENU.visible())
3566		this.MENU.Hide();
3567};
3568
3569BX.COpener.prototype.__close_immediately = function() {
3570	this.bOpen = false; this.__close();
3571};
3572
3573BX.COpener.prototype.isMenuVisible = function() {
3574	return null != this.MENU.visible && this.MENU.visible()
3575};
3576
3577/* common menu class */
3578
3579BX.CMenu = function(arParams)
3580{
3581	BX.CMenu.superclass.constructor.apply(this);
3582
3583	this.DIV.style.width = 'auto';//this.DIV.firstChild.offsetWidth + 'px';
3584	this.DIV.style.height = 'auto';//this.DIV.firstChild.offsetHeight + 'px';
3585
3586	this.PARAMS = arParams || {};
3587	this.PARTS = {};
3588
3589	this.PARAMS.ATTACH_MODE = this.PARAMS.ATTACH_MODE || 'bottom';
3590	this.PARAMS.CLOSE_ON_CLICK = typeof this.PARAMS.CLOSE_ON_CLICK == 'undefined' ? true : this.PARAMS.CLOSE_ON_CLICK;
3591	this.PARAMS.ADJUST_ON_CLICK = typeof this.PARAMS.ADJUST_ON_CLICK == 'undefined' ? true : this.PARAMS.ADJUST_ON_CLICK;
3592	this.PARAMS.PUBLIC_FRAME = typeof this.PARAMS.PUBLIC_FRAME == 'undefined' ? false : this.PARAMS.PUBLIC_FRAME;
3593	this.PARAMS.LEVEL = this.PARAMS.LEVEL || 0;
3594
3595	this.DIV.className = 'bx-core-popup-menu bx-core-popup-menu-' + this.PARAMS.ATTACH_MODE + ' bx-core-popup-menu-level' + this.PARAMS.LEVEL + (typeof this.PARAMS.ADDITIONAL_CLASS != 'undefined' ? ' ' + this.PARAMS.ADDITIONAL_CLASS : '');
3596	if (!!this.PARAMS.SET_ID)
3597		this.DIV.id = this.PARAMS.SET_ID;
3598
3599	if (this.PARAMS.LEVEL == 0)
3600	{
3601		this.ARROW = this.DIV.appendChild(BX.create('SPAN', {props: {className: 'bx-core-popup-menu-angle'}, style: {left:'15px'}}));
3602	}
3603
3604	if (!!this.PARAMS.CLASS_NAME)
3605		this.DIV.className += ' ' + this.PARAMS.CLASS_NAME;
3606
3607	BX.bind(this.DIV, 'click', BX.eventCancelBubble);
3608
3609	this.ITEMS = [];
3610
3611	this.setItems(this.PARAMS.ITEMS);
3612
3613	BX.addCustomEvent('onMenuOpen', BX.proxy(this._onMenuOpen, this));
3614	BX.addCustomEvent('onMenuItemSelected', BX.proxy(this.Hide, this));
3615};
3616BX.extend(BX.CMenu, BX.CWindowFloat);
3617
3618BX.CMenu.broadcastCloseEvent = function()
3619{
3620	BX.onCustomEvent("onMenuItemSelected");
3621};
3622
3623BX.CMenu._toggleChecked = function()
3624{
3625	BX.toggleClass(this, 'bx-core-popup-menu-item-checked');
3626};
3627
3628BX.CMenu._itemDblClick = function()
3629{
3630	window.location.href = this.href;
3631};
3632
3633BX.CMenu.prototype.toggleArrow = function(v)
3634{
3635	if (!!this.ARROW)
3636	{
3637		if (typeof v == 'undefined')
3638		{
3639			v = this.ARROW.style.visibility == 'hidden';
3640		}
3641
3642		this.ARROW.style.visibility = !!v ? 'visible' : 'hidden';
3643	}
3644};
3645
3646BX.CMenu.prototype.visible = function()
3647{
3648	return this.DIV.style.display !== 'none';
3649};
3650
3651BX.CMenu.prototype._onMenuOpen = function(menu, menu_level)
3652{
3653	if (this.visible())
3654	{
3655		if (menu_level == this.PARAMS.LEVEL && menu != this)
3656		{
3657			this.Hide();
3658		}
3659	}
3660};
3661
3662BX.CMenu.prototype.onUnRegister = function()
3663{
3664	if (!this.visible())
3665		return;
3666
3667	this.Hide();
3668};
3669
3670BX.CMenu.prototype.setItems = function(items)
3671{
3672	this.PARAMS.ITEMS = items;
3673
3674	BX.cleanNode(this.DIV);
3675
3676	if (!!this.ARROW)
3677		this.DIV.appendChild(this.ARROW);
3678
3679	if (this.PARAMS.ITEMS)
3680	{
3681		this.PARAMS.ITEMS = BX.util.array_values(this.PARAMS.ITEMS);
3682
3683		var bIcons = false;
3684		var cnt = 0;
3685		for (var i = 0, len = this.PARAMS.ITEMS.length; i < len; i++)
3686		{
3687			if ((i == 0 || i == len-1) && this.PARAMS.ITEMS[i].SEPARATOR)
3688				continue;
3689
3690			cnt++;
3691
3692			if (!bIcons)
3693				bIcons = !!this.PARAMS.ITEMS[i].GLOBAL_ICON;
3694
3695			this.addItem(this.PARAMS.ITEMS[i], i);
3696		}
3697
3698		// Occam turning in his grave
3699		if (cnt === 1)
3700			BX.addClass(this.DIV, 'bx-core-popup-menu-single-item');
3701		else
3702			BX.removeClass(this.DIV, 'bx-core-popup-menu-single-item');
3703
3704		if (!bIcons)
3705			BX.addClass(this.DIV, 'bx-core-popup-menu-no-icons');
3706		else
3707			BX.removeClass(this.DIV, 'bx-core-popup-menu-no-icons');
3708
3709	}
3710};
3711
3712BX.CMenu.prototype.addItem = function(item)
3713{
3714	this.ITEMS.push(item);
3715
3716	if (item.SEPARATOR)
3717	{
3718		item.NODE = BX.create(
3719			'DIV', {props: {className: 'bx-core-popup-menu-separator'}}
3720		);
3721	}
3722	else
3723	{
3724		var bHasMenu = (!!item.MENU
3725			&& (
3726				(BX.type.isArray(item.MENU) && item.MENU.length > 0)
3727				|| item.MENU instanceof BX.CMenu
3728			) || !!item.MENU_URL
3729		);
3730
3731		if (item.DISABLED)
3732		{
3733			item.CLOSE_ON_CLICK = false;
3734			item.LINK = null;
3735			item.ONCLICK = null;
3736			item.ACTION = null;
3737		}
3738
3739		var attrs = {};
3740		if (!!item.LINK || BX.browser.IsIE() && !BX.browser.IsDoctype())
3741		{
3742			attrs.href = item.LINK || 'javascript:void(0)';
3743		}
3744		if (this.PARAMS.PUBLIC_FRAME)
3745		{
3746			attrs.target = '_top';
3747		}
3748
3749		item.NODE = BX.create(!!item.LINK || BX.browser.IsIE() && !BX.browser.IsDoctype() ? 'A' : 'SPAN', {
3750			props: {
3751				className: 'bx-core-popup-menu-item'
3752					+ (bHasMenu ? ' bx-core-popup-menu-item-opener' : '')
3753					+ (!!item.DEFAULT ? ' bx-core-popup-menu-item-default' : '')
3754					+ (!!item.DISABLED ? ' bx-core-popup-menu-item-disabled' : '')
3755					+ (!!item.CHECKED ? ' bx-core-popup-menu-item-checked' : ''),
3756					title: !!BX.message['MENU_ENABLE_TOOLTIP'] || !!item.SHOW_TITLE ? item.TITLE || '' : '',
3757				BXMENULEVEL: this.PARAMS.LEVEL
3758			},
3759			attrs: attrs,
3760			events: {
3761				mouseover: function()
3762				{
3763					BX.onCustomEvent('onMenuItemHover', [this.BXMENULEVEL, this.OPENER])
3764				}
3765			},
3766			html: '<span class="bx-core-popup-menu-item-icon' + (item.GLOBAL_ICON ? ' '+item.GLOBAL_ICON : '') + '"></span><span class="bx-core-popup-menu-item-text">'+(item.HTML||(item.TEXT? BX.util.htmlspecialchars(item.TEXT) : ''))+'</span>'
3767		});
3768
3769		if (bHasMenu && !item.DISABLED)
3770		{
3771			item.NODE.OPENER = new BX.COpener({
3772				DIV: item.NODE,
3773				ACTIVE_CLASS: 'bx-core-popup-menu-item-opened',
3774				TYPE: 'hover',
3775				MENU: item.MENU,
3776				MENU_URL: item.MENU_URL,
3777				MENU_PRELOAD: !!item.MENU_PRELOAD,
3778				LEVEL: this.PARAMS.LEVEL + 1,
3779				ATTACH_MODE:'right',
3780				TIMEOUT: 500
3781			});
3782		}
3783		else if (this.PARAMS.CLOSE_ON_CLICK && (typeof item.CLOSE_ON_CLICK == 'undefined' || !!item.CLOSE_ON_CLICK))
3784		{
3785			BX.bind(item.NODE, 'click', BX.CMenu.broadcastCloseEvent);
3786		}
3787		else if (this.PARAMS.ADJUST_ON_CLICK && (typeof item.ADJUST_ON_CLICK == 'undefined' || !!item.ADJUST_ON_CLICK))
3788		{
3789			BX.bind(item.NODE, 'click', BX.defer(this.adjustPos, this));
3790		}
3791
3792		if (bHasMenu && !!item.LINK)
3793		{
3794			BX.bind(item.NODE, 'dblclick', BX.CMenu._itemDblClick);
3795		}
3796
3797		if (typeof item.CHECKED != 'undefined')
3798		{
3799			BX.bind(item.NODE, 'click', BX.CMenu._toggleChecked);
3800		}
3801
3802		item.ONCLICK = item.ACTION || item.ONCLICK;
3803		if (!!item.ONCLICK)
3804		{
3805			if (BX.type.isString(item.ONCLICK))
3806			{
3807				item.ONCLICK = new Function("event", item.ONCLICK);
3808			}
3809
3810			BX.bind(item.NODE, 'click', item.ONCLICK);
3811		}
3812	}
3813
3814	this.DIV.appendChild(item.NODE);
3815};
3816
3817BX.CMenu.prototype._documentClickBind = function()
3818{
3819	this._documentClickUnBind();
3820	BX.bind(document, 'click', BX.proxy(this._documentClick, this));
3821};
3822
3823BX.CMenu.prototype._documentClickUnBind = function()
3824{
3825	BX.unbind(document, 'click', BX.proxy(this._documentClick, this));
3826};
3827
3828BX.CMenu.prototype._documentClick = function(e)
3829{
3830	e = e||window.event;
3831	if(!!e && !(BX.getEventButton(e) & BX.MSLEFT))
3832		return;
3833
3834	this.Close();
3835};
3836
3837BX.CMenu.prototype.Show = function()
3838{
3839	BX.onCustomEvent(this, 'onMenuOpen', [this, this.PARAMS.LEVEL]);
3840	BX.CMenu.superclass.Show.apply(this, []);
3841
3842	this.bCloseEventFired = false;
3843
3844	BX.addCustomEvent(this.PARAMS.parent_attach, 'onChangeNodePosition', BX.proxy(this.adjustToNode, this));
3845
3846	(BX.defer(this._documentClickBind, this))();
3847};
3848
3849BX.CMenu.prototype.Close = // we shouldn't 'Close' window - only hide
3850BX.CMenu.prototype.Hide = function()
3851{
3852	if (!this.visible())
3853		return;
3854
3855	BX.removeCustomEvent(this.PARAMS.parent_attach, 'onChangeNodePosition', BX.proxy(this.adjustToNode, this));
3856
3857	this._documentClickUnBind();
3858
3859	if (!this.bCloseEventFired)
3860	{
3861		BX.onCustomEvent(this, 'onMenuClose', [this, this.PARAMS.LEVEL]);
3862		this.bCloseEventFired = true;
3863	}
3864	BX.CMenu.superclass.Hide.apply(this, arguments);
3865
3866
3867//	this.DIV.onclick = null;
3868	//this.PARAMS.parent.onclick = null;
3869};
3870
3871BX.CMenu.prototype.__adjustMenuToNode = function()
3872{
3873	var pos = BX.pos(this.PARAMS.parent_attach),
3874		bFixed = !!BX.findParent(this.PARAMS.parent_attach, BX.is_fixed);
3875
3876	if (bFixed)
3877		this.DIV.style.position = 'fixed';
3878	else
3879		this.DIV.style.position = 'absolute';
3880
3881	if (!pos.top)
3882	{
3883		this.DIV.style.top = '-1000px';
3884		this.DIV.style.left = '-1000px';
3885	}
3886
3887	if (this.bTimeoutSet) return;
3888
3889	var floatWidth = this.DIV.offsetWidth, floatHeight = this.DIV.offsetHeight;
3890	if (!floatWidth)
3891	{
3892		setTimeout(BX.delegate(function(){
3893			this.bTimeoutSet = false; this.__adjustMenuToNode();
3894		}, this), 100);
3895
3896		this.bTimeoutSet = true;
3897		return;
3898	}
3899
3900	var menu_pos = {},
3901		wndSize = BX.GetWindowSize();
3902
3903/*
3904	if (BX.browser.IsIE() && !BX.browser.IsDoctype())
3905	{
3906		pos.top -= 4; pos.bottom -= 4;
3907		pos.left -= 2; pos.right -= 2;
3908	}
3909*/
3910
3911	switch (this.PARAMS.ATTACH_MODE)
3912	{
3913		case 'bottom':
3914			menu_pos.top = pos.bottom + 9;
3915			menu_pos.left = pos.left;
3916
3917			var arrowPos = 0;
3918			if (!!this.ARROW)
3919			{
3920				if (pos.width > floatWidth)
3921					arrowPos = parseInt(floatWidth/2 - 7);
3922				else
3923					arrowPos = parseInt(Math.min(floatWidth, pos.width)/2 - 7);
3924
3925				if (arrowPos < 7)
3926				{
3927					menu_pos.left -= 15;
3928					arrowPos += 15;
3929				}
3930			}
3931
3932			if (menu_pos.left > wndSize.scrollWidth - floatWidth - 10)
3933			{
3934				var orig_menu_pos = menu_pos.left;
3935				menu_pos.left = wndSize.scrollWidth - floatWidth - 10;
3936
3937				if (!!this.ARROW)
3938					arrowPos += orig_menu_pos - menu_pos.left;
3939			}
3940
3941			if (bFixed)
3942			{
3943				menu_pos.left -= wndSize.scrollLeft;
3944			}
3945
3946			if (!!this.ARROW)
3947				this.ARROW.style.left = arrowPos + 'px';
3948		break;
3949		case 'right':
3950			menu_pos.top = pos.top-1;
3951			menu_pos.left = pos.right;
3952
3953			if (menu_pos.left > wndSize.scrollWidth - floatWidth - 10)
3954			{
3955				menu_pos.left = pos.left - floatWidth - 1;
3956			}
3957		break;
3958	}
3959
3960	if (bFixed)
3961	{
3962		menu_pos.top -= wndSize.scrollTop;
3963	}
3964
3965	if (!!this.ARROW)
3966		this.ARROW.className = 'bx-core-popup-menu-angle';
3967
3968	if((menu_pos.top + floatHeight >
3968 wndSize.scrollTop + wndSize.innerHeight)
3969		|| (menu_pos.top + floatHeight > wndSize.scrollHeight))
3970	{
3971		var new_top = this.PARAMS.ATTACH_MODE == 'bottom'
3972			? pos.top - floatHeight - 9
3973			: pos.bottom - floatHeight + 1;
3974
3975		if((new_top > wndSize.scrollTop)
3976			|| (menu_pos.top + floatHeight > wndSize.scrollHeight))
3977		{
3978			if ((menu_pos.top + floatHeight > wndSize.scrollHeight))
3979			{
3980				menu_pos.top = Math.max(0, wndSize.scrollHeight-floatHeight);
3981				this.toggleArrow(false);
3982			}
3983			else
3984			{
3985				menu_pos.top = new_top;
3986
3987				if (!!this.ARROW)
3988					this.ARROW.className = 'bx-core-popup-menu-angle-bottom';
3989			}
3990		}
3991	}
3992
3993	if (menu_pos.top + menu_pos.left == 0)
3994	{
3995		this.Hide();
3996	}
3997	else
3998	{
3999		this.DIV.style.top = menu_pos.top + 'px';
4000		this.DIV.style.left = menu_pos.left + 'px';
4001	}
4002};
4003
4004BX.CMenu.prototype.adjustToNode = function(el)
4005{
4006	this.PARAMS.parent_attach = BX(el) || this.PARAMS.parent_attach || this.PARAMS.parent;
4007	this.__adjustMenuToNode();
4008};
4009
4010
4011/* components toolbar class */
4012
4013BX.CMenuOpener = function(arParams)
4014{
4015	BX.CMenuOpener.superclass.constructor.apply(this);
4016
4017	this.PARAMS = arParams || {};
4018	this.setParent(this.PARAMS.parent);
4019	this.PARTS = {};
4020
4021	this.SETTINGS.drag_restrict = true;
4022
4023	this.defaultAction = null;
4024
4025	this.timeout = 500;
4026
4027	this.DIV.className = 'bx-component-opener';
4028	this.DIV.ondblclick = BX.PreventDefault;
4029
4030	if (this.PARAMS.component_id)
4031	{
4032		this.PARAMS.transform = !!this.PARAMS.transform;
4033	}
4034
4035	this.OPENERS = [];
4036
4037	this.DIV.appendChild(BX.create('SPAN', {
4038		props: {className: 'bx-context-toolbar' + (this.PARAMS.transform ? ' bx-context-toolbar-vertical-mode' : '')}
4039	}));
4040
4041	//set internal structure and register draggable element
4042	this.PARTS.INNER = this.DIV.firstChild.appendChild(BX.create('SPAN', {
4043		props: {className: 'bx-context-toolbar-inner'},
4044		html: '<span class="bx-context-toolbar-drag-icon"></span><span class="bx-context-toolbar-vertical-line"></span><br>'
4045	}));
4046
4047	this.EXTRA_BUTTONS = {};
4048
4049	var btnCount = 0;
4050	for (var i = 0, len = this.PARAMS.menu.length; i < len; i++)
4051	{
4052		var item = this.addItem(this.PARAMS.menu[i]);
4053		if (null != item)
4054		{
4055			btnCount++;
4056			this.PARTS.INNER.appendChild(item);
4057			this.PARTS.INNER.appendChild(BX.create('BR'));
4058		}
4059	}
4060	var bHasButtons = btnCount > 0;
4061
4062	//menu items will be attached here
4063
4064	this.PARTS.ICONS = this.PARTS.INNER.appendChild(BX.create('SPAN', {
4065		props: {className: 'bx-context-toolbar-icons'}
4066	}));
4067
4068	if (this.PARAMS.component_id)
4069	{
4070		this.PARAMS.pin = !!this.PARAMS.pin;
4071
4072		if (bHasButtons)
4073			this.PARTS.ICONS.appendChild(BX.create('SPAN', {props: {className: 'bx-context-toolbar-separator'}}));
4074
4075		this.PARTS.ICON_PIN = this.PARTS.ICONS.appendChild(BX.create('A', {
4076			attrs: {
4077				href: 'javascript:void(0)'
4078			},
4079			props: {
4080				className: this.PARAMS.pin
4081							? 'bx-context-toolbar-pin-fixed'
4082							: 'bx-context-toolbar-pin'
4083			},
4084			events: {
4085				click: BX.delegate(this.__pin_btn_clicked, this)
4086			}
4087		}));
4088	}
4089
4090
4091	if (this.EXTRA_BUTTONS['components2_props'])
4092	{
4093		var btn = this.EXTRA_BUTTONS['components2_props'] || {URL: 'javascript:void(0)'};
4094		if (null == this.defaultAction)
4095		{
4096			this.defaultAction = btn.ONCLICK;
4097			this.defaultActionTitle = btn.TITLE || btn.TEXT;
4098		}
4099
4100		btn.URL = 'javascript:' + BX.util.urlencode(btn.ONCLICK);
4101
4102		this.ATTACH = this.PARTS.ICONS.appendChild(BX.create('SPAN', {
4103			props: {className: 'bx-context-toolbar-button bx-context-toolbar-button-settings' },
4104			children:
4105			[
4106				BX.create('SPAN',
4107				{
4108					props:{className: 'bx-context-toolbar-button-inner'},
4109					children:
4110					[
4111						BX.create('A', {
4112							attrs: {href: btn.URL},
4113							events: {
4114								mouseover: BX.proxy(this.__msover_text, this),
4115								mouseout: BX.proxy(this.__msout_text, this),
4116								mousedown: BX.proxy(this.__msdown_text, this)
4117							},
4118							html: '<span class="bx-context-toolbar-button-icon bx-context-toolbar-settings-icon"></span>'
4119						}),
4120						BX.create('A', {
4121							attrs: {href: 'javascript: void(0)'},
4122							props: {className: 'bx-context-toolbar-button-arrow'},
4123							events: {
4124								mouseover: BX.proxy(this.__msover_arrow, this),
4125								mouseout: BX.proxy(this.__msout_arrow, this),
4126								mousedown: BX.proxy(this.__msdown_arrow, this)
4127							},
4128							html: '<span class="bx-context-toolbar-button-arrow"></span>'
4129						})
4130					]
4131				})
4132			]
4133		}));
4134
4135		this.OPENER = this.ATTACH.firstChild.lastChild;
4136
4137		var opener = this.attachMenu(this.EXTRA_BUTTONS['components2_submenu']['MENU']);
4138
4139		BX.addCustomEvent(opener, 'onOpenerMenuOpen', BX.proxy(this.__menu_open, this));
4140		BX.addCustomEvent(opener, 'onOpenerMenuClose', BX.proxy(this.__menu_close, this));
4141	}
4142
4143	if (btnCount > 1)
4144	{
4145		this.PARTS.ICONS.appendChild(BX.create('span', { props: {className: 'bx-context-toolbar-separator bx-context-toolbar-separator-switcher'}}));
4146
4147		this.ICON_TRANSFORM = this.PARTS.ICONS.appendChild(BX.create('A', {
4148			attrs: {href: 'javascript: void(0)'},
4149			props: {className: 'bx-context-toolbar-switcher'},
4150			events: {
4151				click: BX.delegate(this.__trf_btn_clicked, this)
4152			}
4153		}));
4154	}
4155
4156	if (this.PARAMS.HINT)
4157	{
4158		this.DIV.BXHINT = this.HINT = new BX.CHint({
4159			parent: this.DIV,
4160			hint:this.PARAMS.HINT.TEXT || '',
4161			title: this.PARAMS.HINT.TITLE || '',
4162			hide_timeout: this.timeout/2,
4163			preventHide: false
4164		});
4165	}
4166
4167	BX.addCustomEvent(this, 'onWindowDragFinished', BX.delegate(this.__onMoveFinished, this));
4168	BX.addCustomEvent('onDynamicModeChange', BX.delegate(this.__onDynamicModeChange, this));
4169	BX.addCustomEvent('onTopPanelCollapse', BX.delegate(this.__onPanelCollapse, this));
4170
4171	BX.addCustomEvent('onMenuOpenerMoved', BX.delegate(this.checkPosition, this));
4172	BX.addCustomEvent('onMenuOpenerUnhide', BX.delegate(this.checkPosition, this));
4173
4174	BX.Event.EventEmitter.incrementMaxListeners('onDynamicModeChange');
4175	BX.Event.EventEmitter.incrementMaxListeners('onTopPanelCollapse');
4176	BX.Event.EventEmitter.incrementMaxListeners('onMenuOpenerMoved');
4177	BX.Event.EventEmitter.incrementMaxListeners('onMenuOpenerUnhide');
4178
4179	if (this.OPENERS)
4180	{
4181		for (i=0,len=this.OPENERS.length; i<len; i++)
4182		{
4183			BX.addCustomEvent(this.OPENERS[i], 'onOpenerMenuOpen', BX.proxy(this.__hide_hint, this));
4184		}
4185	}
4186};
4187BX.extend(BX.CMenuOpener, BX.CWindowFloat);
4188
4189BX.CMenuOpener.prototype.setParent = function(new_parent)
4190{
4191	new_parent = BX(new_parent);
4192
4193	if (!new_parent)
4194	{
4195		return;
4196	}
4197
4198	if(new_parent.OPENER && new_parent.OPENER != this)
4199	{
4200		new_parent.OPENER.Close();
4201		new_parent.OPENER.clearHoverHoutEvents();
4202	}
4203
4204	if(this.PARAMS.parent && this.PARAMS.parent != new_parent)
4205	{
4206		this.clearHoverHoutEvents();
4207		this.PARAMS.parent.OPENER = null;
4208	}
4209
4210	this.PARAMS.parent = new_parent;
4211	this.PARAMS.parent.OPENER = this;
4212};
4213
4214BX.CMenuOpener.prototype.setHoverHoutEvents = function(hover, hout)
4215{
4216	if(!this.__opener_events_set)
4217	{
4218		BX.bind(this.Get(), 'mouseover', hover);
4219		BX.bind(this.Get(), 'mouseout', hout);
4220		this.__opener_events_set = true;
4221	}
4222};
4223
4224BX.CMenuOpener.prototype.clearHoverHoutEvents = function()
4225{
4226	if(this.Get())
4227	{
4228		BX.unbindAll(this.Get());
4229		this.__opener_events_set = false;
4230	}
4231};
4232
4233
4234BX.CMenuOpener.prototype.unclosable = true;
4235
4236BX.CMenuOpener.prototype.__check_intersection = function(pos_self, pos_other)
4237{
4238	return !(pos_other.right <= pos_self.left || pos_other.left >= pos_self.right
4239			|| pos_other.bottom <= pos_self.top || pos_other.top >= pos_self.bottom);
4240};
4241
4242
4243BX.CMenuOpener.prototype.__msover_text = function() {
4244	this.bx_hover = true;
4245	if (!this._menu_open)
4246		BX.addClass(this.ATTACH, 'bx-context-toolbar-button-text-hover');
4247};
4248
4249BX.CMenuOpener.prototype.__msout_text = function() {
4250	this.bx_hover = false;
4251	if (!this._menu_open)
4252		BX.removeClass(this.ATTACH, 'bx-context-toolbar-button-text-hover bx-context-toolbar-button-text-active');
4253};
4254
4255BX.CMenuOpener.prototype.__msover_arrow = function() {
4256	this.bx_hover = true;
4257	if (!this._menu_open)
4258		BX.addClass(this.ATTACH, 'bx-context-toolbar-button-arrow-hover');
4259};
4260
4261BX.CMenuOpener.prototype.__msout_arrow = function() {
4262	this.bx_hover = false;
4263	if (!this._menu_open)
4264		BX.removeClass(this.ATTACH, 'bx-context-toolbar-button-arrow-hover bx-context-toolbar-button-arrow-active');
4265};
4266
4267BX.CMenuOpener.prototype.__msdown_text = function() {
4268	this.bx_active = true;
4269	if (!this._menu_open)
4270		BX.addClass(this.ATTACH, 'bx-context-toolbar-button-text-active');
4271};
4272
4273BX.CMenuOpener.prototype.__msdown_arrow = function() {
4274	this.bx_active = true;
4275	if (!this._menu_open)
4276		BX.addClass(this.ATTACH, 'bx-context-toolbar-button-arrow-active');
4277};
4278
4279BX.CMenuOpener.prototype.__menu_close = function() {
4280	this._menu_open = false;
4281	this.bx_active = false;
4282	BX.removeClass(this.ATTACH, 'bx-context-toolbar-button-active bx-context-toolbar-button-text-active bx-context-toolbar-button-arrow-active');
4283	if (!this.bx_hover)
4284	{
4285		BX.removeClass(this.ATTACH, 'bx-context-toolbar-button-hover bx-context-toolbar-button-text-hover bx-context-toolbar-button-arrow-hover');
4286		this.bx_hover = false;
4287	}
4288};
4289
4290BX.CMenuOpener.prototype.__menu_open = function() {
4291	this._menu_open = true;
4292};
4293
4294BX.CMenuOpener.prototype.checkPosition = function()
4295{
4296	if (this.isMenuVisible() || this.DIV.style.display == 'none'
4297		|| this == BX.proxy_context || BX.proxy_context.zIndex > this.zIndex)
4298		return;
4299
4300	this.correctPosition(BX.proxy_context);
4301};
4302
4303BX.CMenuOpener.prototype.correctPosition = function(opener)
4304{
4305	var pos_self = BX.pos(this.DIV), pos_other = BX.pos(opener.Get());
4306	if (this.__check_intersection(pos_self, pos_other))
4307	{
4308		var new_top = pos_other.top - pos_self.height;
4309		if (new_top < 0)
4310			new_top = pos_other.bottom;
4311
4312		this.DIV.style.top = new_top + 'px';
4313
4314		BX.addCustomEvent(opener, 'onMenuOpenerHide', BX.proxy(this.restorePosition, this));
4315		BX.onCustomEvent(this, 'onMenuOpenerMoved');
4316	}
4317};
4318
4319BX.CMenuOpener.prototype.restorePosition = function()
4320{
4321	if (!this.MOUSEOVER && !this.isMenuVisible())
4322	{
4323		if (this.originalPos)
4324			this.DIV.style.top = this.originalPos.top + 'px';
4325
4326		BX.removeCustomEvent(BX.proxy_context, 'onMenuOpenerHide', BX.proxy(this.restorePosition, this));
4327		if (this.restore_pos_timeout) clearTimeout(this.restore_pos_timeout);
4328	}
4329	else
4330	{
4331		this.restore_pos_timeout = setTimeout(BX.proxy(this.restorePosition, this), this.timeout);
4332	}
4333};
4334
4335
4336BX.CMenuOpener.prototype.Show = function()
4337{
4338	BX.CMenuOpener.superclass.Show.apply(this, arguments);
4339
4340	this.SetDraggable(this.PARTS.INNER.firstChild);
4341
4342	this.DIV.style.width = 'auto';
4343	this.DIV.style.height = 'auto';
4344
4345	if (!this.PARAMS.pin)
4346	{
4347		this.DIV.style.left = '-1000px';
4348		this.DIV.style.top = '-1000px';
4349
4350		this.Hide();
4351	}
4352	else
4353	{
4354		this.bPosAdjusted = true;
4355		this.bMoved = true;
4356
4357		if (this.PARAMS.top) this.DIV.style.top = this.PARAMS.top + 'px';
4358		if (this.PARAMS.left) this.DIV.style.left = this.PARAMS.left + 'px';
4359
4360		this.DIV.style.display = (!BX.admin.dynamic_mode || BX.admin.dynamic_mode_show_borders) ? 'block' : 'none';
4361
4362		if (this.DIV.style.display == 'block')
4363		{
4364			setTimeout(BX.delegate(function() {BX.onCustomEvent(this, 'onMenuOpenerUnhide')}, this), 50);
4365		}
4366	}
4367};
4368
4369BX.CMenuOpener.prototype.executeDefaultAction = function()
4370{
4371	if (this.defaultAction)
4372	{
4373		if (BX.type.isFunction(this.defaultAction))
4374			this.defaultAction();
4375		else if(BX.type.isString(this.defaultAction))
4376			BX.evalGlobal(this.defaultAction);
4377	}
4378};
4379
4380BX.CMenuOpener.prototype.__onDynamicModeChange = function(val)
4381{
4382	this.DIV.style.display = val ? 'block' : 'none';
4383};
4384
4385BX.CMenuOpener.prototype.__onPanelCollapse = function(bCollapsed, dy)
4386{
4387	this.DIV.style.top = (parseInt(this.DIV.style.top) + dy) + 'px';
4388	if (this.PARAMS.pin)
4389	{
4390		this.__savePosition();
4391	}
4392};
4393
4394BX.CMenuOpener.prototype.__onMoveFinished = function()
4395{
4396	BX.onCustomEvent(this, 'onMenuOpenerMoved');
4397
4398	this.bMoved = true;
4399
4400	if (this.PARAMS.pin)
4401		this.__savePosition();
4402};
4403
4404BX.CMenuOpener.prototype.__savePosition = function()
4405{
4406	var arOpts = {};
4407
4408	arOpts.pin = this.PARAMS.pin;
4409	if (!this.PARAMS.pin)
4410	{
4411		arOpts.top = false; arOpts.left = false; arOpts.transform = false;
4412	}
4413	else
4414	{
4415		arOpts.transform = this.PARAMS.transform;
4416		if (this.bMoved)
4417		{
4418			arOpts.left = parseInt(this.DIV.style.left);
4419			arOpts.top = parseInt(this.DIV.style.top);
4420		}
4421	}
4422
4423	BX.WindowManager.saveWindowOptions(this.PARAMS.component_id, arOpts);
4424};
4425
4426BX.CMenuOpener.prototype.__pin_btn_clicked = function() {this.Pin()};
4427BX.CMenuOpener.prototype.Pin = function(val)
4428{
4429	if (null == val)
4430		this.PARAMS.pin = !this.PARAMS.pin;
4431	else
4432		this.PARAMS.pin = !!val;
4433
4434	this.PARTS.ICON_PIN.className = (this.PARAMS.pin ? 'bx-context-toolbar-pin-fixed' : 'bx-context-toolbar-pin');
4435
4436	this.__savePosition();
4437};
4438
4439BX.CMenuOpener.prototype.__trf_btn_clicked = function() {this.Transform()};
4440BX.CMenuOpener.prototype.Transform = function(val)
4441{
4442	var pos = {};
4443
4444	if (null == val)
4445		this.PARAMS.transform = !this.PARAMS.transform;
4446	else
4447		this.PARAMS.transform = !!val;
4448
4449	if (this.bMoved)
4450	{
4451		pos = BX.pos(this.DIV);
4452	}
4453
4454	if (this.PARAMS.transform)
4455		BX.addClass(this.DIV.firstChild, 'bx-context-toolbar-vertical-mode');
4456	else
4457		BX.removeClass(this.DIV.firstChild, 'bx-context-toolbar-vertical-mode');
4458
4459	if (!this.bMoved)
4460	{
4461		this.adjustPos();
4462	}
4463	else
4464	{
4465		this.DIV.style.left = (pos.right - this.DIV.offsetWidth - (BX.browser.IsIE() && !BX.browser.IsDoctype() ? 2 : 0)) + 'px';
4466	}
4467
4468	this.__savePosition();
4469};
4470
4471BX.CMenuOpener.prototype.adjustToNodeGetPos = function()
4472{
4473	var pos = BX.pos(this.PARAMS.parent/*, true*/);
4474
4475	var scrollSize = BX.GetWindowScrollSize();
4476	var floatWidth = this.DIV.offsetWidth;
4477
4478	pos.left -= BX.admin.__border_dx;
4479	pos.top -= BX.admin.__border_dx;
4480
4481	if (true || !this.PARAMS.transform)
4482	{
4483		pos.top -= 45;
4484	}
4485
4486	if (pos.left > scrollSize.scrollWidth - floatWidth)
4487	{
4488		pos.left = scrollSize.scrollWidth - floatWidth;
4489	}
4490
4491	return pos;
4492};
4493
4494BX.CMenuOpener.prototype.addItem = function(item)
4495{
4496	if (item.TYPE)
4497	{
4498		this.EXTRA_BUTTONS[item.TYPE] = item;
4499		return null;
4500	}
4501	else
4502	{
4503		var q = new BX.CMenuOpenerItem(item);
4504		if (null == this.defaultAction)
4505		{
4506			if (q.item.ONCLICK)
4507			{
4508				this.defaultAction = item.ONCLICK;
4509			}
4510			else if (q.item.MENU)
4511			{
4512				this.defaultAction = BX.delegate(function() {this.Open()}, q.item.OPENER);
4513			}
4514
4515			this.defaultActionTitle = item.TITLE || item.TEXT;
4516
4517			BX.addClass(q.Get(), 'bx-content-toolbar-default');
4518		}
4519		if (q.item.OPENER) this.OPENERS[this.OPENERS.length] = q.item.OPENER;
4520		return q.Get();
4521	}
4522};
4523
4524BX.CMenuOpener.prototype.attachMenu = function(menu)
4525{
4526	var opener = new BX.COpener({
4527		'DIV':  this.OPENER,
4528		'ATTACH': this.ATTACH,
4529		'MENU': menu,
4530		'TYPE': 'click'
4531	});
4532
4533	this.OPENERS[this.OPENERS.length] = opener;
4534
4535	return opener;
4536};
4537
4538BX.CMenuOpener.prototype.__hide_hint = function()
4539{
4540	if (this.HINT) this.HINT.__hide_immediately();
4541};
4542
4543BX.CMenuOpener.prototype.isMenuVisible = function()
4544{
4545	for (var i=0,len=this.OPENERS.length; i<len; i++)
4546	{
4547		if (this.OPENERS[i].isMenuVisible())
4548			return true;
4549	}
4550
4551	return false;
4552};
4553
4554BX.CMenuOpener.prototype.Hide = function()
4555{
4556	if (!this.PARAMS.pin)
4557	{
4558		this.DIV.style.display = 'none';
4559		BX.onCustomEvent(this, 'onMenuOpenerHide');
4560	}
4561};
4562BX.CMenuOpener.prototype.UnHide = function()
4563{
4564	this.DIV.style.display = 'block';
4565	if (!this.bPosAdjusted && !this.PARAMS.pin)
4566	{
4567		this.adjustPos();
4568		this.bPosAdjusted = true;
4569	}
4570
4571	if (null == this.originalPos && !this.bMoved)
4572	{
4573		this.originalPos = BX.pos(this.DIV);
4574	}
4575
4576	BX.onCustomEvent(this, 'onMenuOpenerUnhide');
4577};
4578
4579BX.CMenuOpenerItem = function(item)
4580{
4581	this.item = item;
4582
4583	if (this.item.ACTION && !this.item.ONCLICK)
4584	{
4585		this.item.ONCLICK = this.item.ACTION;
4586	}
4587
4588	this.DIV = BX.create('SPAN');
4589	this.DIV.appendChild(BX.create('SPAN', {props: {className: 'bx-context-toolbar-button-underlay'}}));
4590
4591	this.WRAPPER = this.DIV.appendChild(BX.create('SPAN', {
4592		props: {className: 'bx-context-toolbar-button-wrapper'},
4593		children: [
4594			BX.create('SPAN', {
4595				props: {className: 'bx-context-toolbar-button', title: item.TITLE},
4596				children: [
4597					BX.create('SPAN', {
4598						props: {className: 'bx-context-toolbar-button-inner'}
4599					})
4600				]
4601			})
4602		]
4603	}));
4604
4605	var btn_icon = BX.create('SPAN', {
4606		props: {className: 'bx-context-toolbar-button-icon' + (this.item.ICON || this.item.ICONCLASS ? ' ' + (this.item.ICON || this.item.ICONCLASS) : '')},
4607		attrs: (
4608				!(this.item.ICON || this.item.ICONCLASS)
4609				&&
4610				(this.item.SRC || this.item.IMAGE)
4611			)
4612			? {
4613				style: 'background: scroll transparent url(' + (this.item.SRC || this.item.IMAGE) + ') no-repeat center center !important;'
4614			}
4615			: {}
4616	}), btn_text = BX.create('SPAN', {
4617		props: {className: 'bx-context-toolbar-button-text'},
4618		text: this.item.TEXT
4619	});
4620
4621	if (this.item.ACTION && !this.item.ONCLICK)
4622	{
4623		this.item.ONCLICK = this.item.ACTION;
4624	}
4625
4626	this.bHasMenu = !!this.item.MENU;
4627	this.bHasAction = !!this.item.ONCLICK;
4628
4629	if (this.bHasAction)
4630	{
4631		this.LINK = this.WRAPPER.firstChild.firstChild.appendChild(BX.create('A', {
4632			attrs: {
4633				'href': 'javascript: void(0)'
4634			},
4635			events: {
4636				mouseover: this.bHasMenu ? BX.proxy(this.__msover_text, this) : BX.proxy(this.__msover, this),
4637				mouseout: this.bHasMenu ? BX.proxy(this.__msout_text, this) : BX.proxy(this.__msout, this),
4638				mousedown: this.bHasMenu ? BX.proxy(this.__msdown_text, this) : BX.proxy(this.__msdown, this)
4639			},
4640			children: [btn_icon, btn_text]
4641		}));
4642
4643		if (this.bHasMenu)
4644		{
4645			this.LINK_MENU = this.WRAPPER.firstChild.firstChild.appendChild(BX.create('A', {
4646				props: {className: 'bx-context-toolbar-button-arrow'},
4647				attrs: {
4648					'href': 'javascript: void(0)'
4649				},
4650				events: {
4651					mouseover: BX.proxy(this.__msover_arrow, this),
4652					mouseout: BX.proxy(this.__msout_arrow, this),
4653					mousedown: BX.proxy(this.__msdown_arrow, this)
4654				},
4655				children: [
4656					BX.create('SPAN', {props: {className: 'bx-context-toolbar-button-arrow'}})
4657				]
4658			}));
4659		}
4660
4661	}
4662	else if (this.bHasMenu)
4663	{
4664		this.item.ONCLICK = null;
4665
4666		this.LINK = this.LINK_MENU = this.WRAPPER.firstChild.firstChild.appendChild(BX.create('A', {
4667			attrs: {
4668				'href': 'javascript: void(0)'
4669			},
4670			events: {
4671				mouseover: BX.proxy(this.__msover, this),
4672				mouseout: BX.proxy(this.__msout, this),
4673				mousedown: BX.proxy(this.__msdown, this)
4674			},
4675			children: [
4676				btn_icon,
4677				btn_text
4678			]
4679		}));
4680
4681		this.LINK.appendChild(BX.create('SPAN', {props: {className: 'bx-context-toolbar-single-button-arrow'}}));
4682
4683	}
4684
4685	if (this.bHasMenu)
4686	{
4687		this.item.SUBMENU = new BX.CMenu({
4688			ATTACH_MODE:'bottom',
4689			ITEMS:this.item['MENU'],
4690			//PARENT_MENU:this.parentMenu,
4691			parent: this.LINK_MENU,
4692			parent_attach: this.WRAPPER.firstChild
4693		});
4694
4695		this.item.OPENER = new BX.COpener({
4696			DIV: this.LINK_MENU,
4697			TYPE: 'click',
4698			MENU: this.item.SUBMENU
4699		});
4700
4701		BX.addCustomEvent(this.item.OPENER, 'onOpenerMenuOpen', BX.proxy(this.__menu_open, this));
4702		BX.addCustomEvent(this.item.OPENER, 'onOpenerMenuClose', BX.proxy(this.__menu_close, this));
4703	}
4704
4705	if (this.bHasAction)
4706	{
4707		BX.bind(this.LINK, 'click', BX.delegate(this.__click, this));
4708	}
4709};
4710
4711BX.CMenuOpenerItem.prototype.Get = function() {return this.DIV;};
4712BX.CMenuOpenerItem.prototype.__msover = function() {
4713	this.bx_hover = true;
4714	if (!this._menu_open)
4715		BX.addClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-hover');
4716};
4717BX.CMenuOpenerItem.prototype.__msout = function() {
4718	this.bx_hover = false;
4719	if (!this._menu_open)
4720		BX.removeClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-hover bx-context-toolbar-button-active');
4721};
4722BX.CMenuOpenerItem.prototype.__msover_text = function() {
4723	this.bx_hover = true;
4724	if (!this._menu_open)
4725		BX.addClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-text-hover');
4726};
4727BX.CMenuOpenerItem.prototype.__msout_text = function() {
4728	this.bx_hover = false;
4729	if (!this._menu_open)
4730		BX.removeClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-text-hover bx-context-toolbar-button-text-active');
4731};
4732BX.CMenuOpenerItem.prototype.__msover_arrow = function() {
4733	this.bx_hover = true;
4734	if (!this._menu_open)
4735		BX.addClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-arrow-hover');
4736};
4737BX.CMenuOpenerItem.prototype.__msout_arrow = function() {
4738	this.bx_hover = false;
4739	if (!this._menu_open)
4740		BX.removeClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-arrow-hover bx-context-toolbar-button-arrow-active');
4741};
4742BX.CMenuOpenerItem.prototype.__msdown = function() {
4743	this.bx_active = true;
4744	if (!this._menu_open)
4745		BX.addClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-active');
4746};
4747BX.CMenuOpenerItem.prototype.__msdown_text = function() {
4748	this.bx_active = true;
4749	if (!this._menu_open)
4750		BX.addClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-text-active');
4751};
4752BX.CMenuOpenerItem.prototype.__msdown_arrow = function() {
4753	this.bx_active = true;
4754	if (!this._menu_open)
4755		BX.addClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-arrow-active');
4756};
4757BX.CMenuOpenerItem.prototype.__menu_close = function() {
4758
4759	this._menu_open = false;
4760	this.bx_active = false;
4761	BX.removeClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-active bx-context-toolbar-button-text-active bx-context-toolbar-button-arrow-active');
4762	if (!this.bx_hover)
4763	{
4764		BX.removeClass(this.LINK.parentNode.parentNode, 'bx-context-toolbar-button-hover bx-context-toolbar-button-text-hover bx-context-toolbar-button-arrow-hover');
4765		this.bx_hover = false;
4766	}
4767};
4768BX.CMenuOpenerItem.prototype.__menu_open = function() {
4769	this._menu_open = true;
4770};
4771
4772BX.CMenuOpenerItem.prototype.__click = function() {BX.evalGlobal(this.item.ONCLICK)};
4773
4774/* global page opener class */
4775BX.CPageOpener = function(arParams)
4776{
4777	//if (null == arParams.pin) arParams.pin = true;
4778	BX.CPageOpener.superclass.constructor.apply(this, arguments);
4779
4780	this.timeout = 505;
4781
4782	window.PAGE_EDIT_CONTROL = this;
4783};
4784BX.extend(BX.CPageOpener, BX.CMenuOpener);
4785
4786BX.CPageOpener.prototype.checkPosition = function()
4787{
4788	if (/*this.isMenuVisible() || this.DIV.style.display == 'none' || */this == BX.proxy_context)
4789		return;
4790
4791	this.correctPosition(BX.proxy_context);
4792};
4793
4794BX.CPageOpener.prototype.correctPosition = function(opener)
4795{
4796	if (this.bPosCorrected) return;
4797	var pos_self;
4798	if (this.DIV.style.display == 'none')
4799	{
4800		pos_self = this.adjustToNodeGetPos();
4801		pos_self.bottom = pos_self.top + 30;
4802		pos_self.right = pos_self.left + 300;
4803	}
4804	else
4805	{
4806		pos_self = BX.pos(this.DIV);
4807	}
4808
4809	var pos_other = BX.pos(opener.Get());
4810	if (this.__check_intersection(pos_self, pos_other))
4811	{
4812		this.DIV.style.display = 'none';
4813
4814		var handler = BX.proxy(this.restorePosition, this);
4815
4816		BX.removeCustomEvent(opener, 'onMenuOpenerHide', handler);
4817		BX.addCustomEvent(opener, 'onMenuOpenerHide', handler);
4818
4819		this.bPosCorrected = true;
4820	}
4821};
4822
4823BX.CPageOpener.prototype.restorePosition = function()
4824{
4825	if (BX.proxy_context && BX.proxy_context.Get().style.display == 'none')
4826	{
4827		this.bPosCorrected = false;
4828
4829		if (this.PARAMS.parent.bx_over || this.PARAMS.pin)
4830			this.UnHide();
4831
4832		BX.removeCustomEvent('onMenuOpenerHide', BX.proxy(this.restorePosition, this));
4833	}
4834};
4835
4836BX.CPageOpener.prototype.UnHide = function()
4837{
4838	if (!this.bPosCorrected)
4839		BX.CPageOpener.superclass.UnHide.apply(this, arguments);
4840};
4841
4842BX.CPageOpener.prototype.Remove = function()
4843{
4844	BX.admin.removeComponentBorder(this.PARAMS.parent);
4845	BX.userOptions.save('global', 'settings', 'page_edit_control_enable', 'N');
4846	this.DIV.style.display = 'none';
4847};
4848
4849/******* HINT ***************/
4850BX.CHintSimple = function()
4851{
4852	BX.CHintSimple.superclass.constructor.apply(this, arguments);
4853};
4854BX.extend(BX.CHintSimple, BX.CHint);
4855
4856BX.CHintSimple.prototype.Init = function()
4857{
4858	this.DIV = document.body.appendChild(BX.create('DIV', {props: {className: 'bx-tooltip-simple'}, style: {display: 'none'}, children: [(this.CONTENT = BX.create('DIV'))]}));
4859
4860	BX.ZIndexManager.register(this.DIV);
4861
4862	if (this.HINT_TITLE)
4863		this.CONTENT.appendChild(BX.create('B', {text: this.HINT_TITLE}));
4864
4865	if (this.HINT)
4866		this.CONTENT_TEXT = this.CONTENT.appendChild(BX.create('DIV')).appendChild(BX.create('SPAN', {html: this.HINT}));
4867
4868	if (this.PARAMS.preventHide)
4869	{
4870		BX.bind(this.DIV, 'mouseout', BX.proxy(this.Hide, this));
4871		BX.bind(this.DIV, 'mouseover', BX.proxy(this.Show, this));
4872	}
4873
4874	this.bInited = true;
4875};
4876
4877/*************************** admin informer **********************************/
4878BX.adminInformer = {
4879
4880	itemsShow: 3,
4881
4882	Init: function (itemsShow)
4883	{
4884		if(itemsShow)
4885			BX.adminInformer.itemsShow = itemsShow;
4886
4887		var informer = BX("admin-informer");
4888
4889		if(informer)
4890		{
4891			document.body.appendChild(informer);
4892			BX.ZIndexManager.register(informer);
4893		}
4894
4895		BX.addCustomEvent("onTopPanelCollapse", BX.proxy(BX.adminInformer.Close, BX.adminInformer));
4896	},
4897
4898	Toggle: function(notifyBlock)
4899	{
4900		var informer = BX("admin-informer");
4901
4902		if(!informer)
4903			return false;
4904
4905		var pos = BX.pos(notifyBlock);
4906
4907		informer.style.top = (parseInt(pos.top)+parseInt(pos.height)+7)+'px';
4908		informer.style.left = pos.left+'px';
4909
4910		if(!BX.hasClass(informer, "adm-informer-active"))
4911			BX.adminInformer.Show(informer);
4912		else
4913			BX.adminInformer.Hide(informer);
4914
4915		return false;
4916	},
4917
4918	Close: function()
4919	{
4920		BX.adminInformer.Hide(BX("admin-informer"));
4921	},
4922
4923	OnInnerClick: function(event)
4924	{
4925		var target = event.target || event.srcElement;
4926
4927		if(target.nodeName.toLowerCase() != 'a' || BX.hasClass(target,"adm-informer-footer"))
4928		{
4929			return BX.PreventDefault(event);
4930		}
4931
4932		return true;
4933	},
4934
4935	ToggleExtra : function()
4936	{
4937		var footerLink = BX("adm-informer-footer");
4938
4939		if (BX.hasClass(footerLink, "adm-informer-footer-collapsed"))
4940			this.ShowAll();
4941		else
4942			this.HideExtra();
4943
4944		return false;
4945	},
4946
4947	ShowAll: function()
4948	{
4949		var informer = BX("admin-informer");
4950		for(var i=0; i<informer.children.length; i++)
4951
4952			if(BX.hasClass(informer.children[i], "adm-informer-item") && informer.children[i].style.display == "none") {
4953				informer.children[i].style.display = "block";
4954			}
4955
4956		var footerLink = BX("adm-informer-footer");
4957
4958		if(footerLink.textContent !== undefined)
4959			footerLink.textContent = BX.message('JSADM_AI_HIDE_EXTRA');
4960		else
4961			footerLink.innerText = BX.message('JSADM_AI_HIDE_EXTRA');
4962
4963		BX.removeClass(footerLink, "adm-informer-footer-collapsed");
4964
4965		return false;
4966	},
4967
4968	HideExtra: function()
4969	{
4970		var informer = BX("admin-informer");
4971		var hided = 0;
4972
4973		for(var i=BX.adminInformer.itemsShow+1; i<informer.children.length; i++)
4974		{
4975			if (BX.hasClass(informer.children[i], "adm-informer-item") && informer.children[i].style.display == "block") {
4976				informer.children[i].style.display = "none";
4977				hided++;
4978			}
4979		}
4980
4981		var footerLink = BX("adm-informer-footer");
4982
4983		var linkText = BX.message('JSADM_AI_ALL_NOTIF')+" ("+(BX.adminInformer.itemsShow+parseInt(hided))+")";
4984
4985		if(footerLink.textContent !== undefined)
4986			footerLink.textContent = linkText;
4987		else
4988			footerLink.innerText = linkText;
4989
4990		BX.addClass(footerLink, "adm-informer-footer-collapsed");
4991
4992		return false;
4993	},
4994
4995	Show: function(informer)
4996	{
4997		var notifButton = BX("adm-header-notif-block");
4998		if (notifButton)
4999			BX.addClass(notifButton, "adm-header-notif-block-active");
5000
5001		BX.onCustomEvent(informer, 'onBeforeAdminInformerShow');
5002		setTimeout(
5003			BX.proxy(function() {
5004					BX.bind(document, "click", BX.proxy(BX.adminInformer.Close, BX.adminInformer));
5005				},
5006				BX.adminInformer
5007			),0
5008		);
5009		BX.addClass(informer, "adm-informer-active");
5010
5011		BX.ZIndexManager.bringToFront(informer);
5012
5013		setTimeout(function() {BX.addClass(informer, "adm-informer-animate");},0);
5014	},
5015
5016	Hide: function(informer)
5017	{
5018		var notifButton = BX("adm-header-notif-block");
5019		if (notifButton)
5020			BX.removeClass(notifButton, "adm-header-notif-block-active");
5021
5022		BX.unbind(document, "click", BX.proxy(BX.adminInformer.Close, BX.adminInformer));
5023
5024		BX.removeClass(informer, "adm-informer-animate");
5025
5026		if (this.IsAnimationSupported())
5027			setTimeout(function() {BX.removeClass(informer, "adm-informer-active");}, 300);
5028		else
5029			BX.removeClass(informer, "adm-informer-active");
5030
5031		BX.onCustomEvent(informer, 'onAdminInformerHide');
5032		//setTimeout(function() {BX.adminInformer.HideExtra();},500);
5033	},
5034
5035	IsAnimationSupported : function()
5036	{
5037		var d = document.body || document.documentElement;
5038		if (typeof(d.style.transition) == "string")
5039			return true;
5040		else if (typeof(d.style.MozTransition) == "string")
5041			return true;
5042		else if (typeof(d.style.OTransition) == "string")
5043			return true;
5044		else if (typeof(d.style.WebkitTransition) == "string")
5045			return true;
5046		else if (typeof(d.style.msTransition) == "string")
5047			return true;
5048
5049		return false;
5050	},
5051
5052
5053	SetItemHtml: function(itemIdx, html)
5054	{
5055		var itemHtmlDiv = BX("adm-informer-item-html-"+itemIdx);
5056
5057		if(!itemHtmlDiv)
5058			return false;
5059
5060		itemHtmlDiv.innerHTML = html;
5061
5062		return true;
5063	},
5064
5065	SetItemFooter: function(itemIdx, html)
5066	{
5067		var itemFooterDiv = BX("adm-informer-item-footer-"+itemIdx);
5068
5069		if(!itemFooterDiv)
5070			return false;
5071
5072		itemFooterDiv.innerHTML = html;
5073
5074		if(html)
5075			itemFooterDiv.style.display = "block";
5076		else
5077			itemFooterDiv.style.display = "none";
5078
5079		return true;
5080	}
5081
5082};
5083
5084}
5084)(window);
5085
5086
5087/* End */
5088;
5089; /* Start:"a:4:{s:4:"full";s:49:"/bitrix/js/main/date/main.date.js?174195188562683";s:6:"source";s:33:"/bitrix/js/main/date/main.date.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
5090/* eslint-disable */
5091this.BX = this.BX || {};
5092(function (exports,main_core) {
5093	'use strict';
5094
5095	function convertBitrixFormat(format) {
5096	  if (!main_core.Type.isStringFilled(format)) {
5097	    return '';
5098	  }
5099	  return format.replace('YYYY', 'Y') // 1999
5100	  .replace('MMMM', 'F') // January - December
5101	  .replace('MM', 'm') // 01 - 12
5102	  .replace('M', 'M') // Jan - Dec
5103	  .replace('DD', 'd') // 01 - 31
5104	  .replace('G', 'g') //  1 - 12
5105	  .replace(/GG/i, 'G') //  0 - 23
5106	  .replace('H', 'h') // 01 - 12
5107	  .replace(/HH/i, 'H') // 00 - 24
5108	  .replace('MI', 'i') // 00 - 59
5109	  .replace('SS', 's') // 00 - 59
5110	  .replace('TT', 'A') // AM - PM
5111	  .replace('T', 'a'); // am - pm
5112	}
5113
5114	const formatsCache = new main_core.Cache.MemoryCache();
5115
5116	/**
5117	 * Returns culture-specific datetime format by code.
5118	 * The full list with examples can be found in config.php of this extension in ['settings']['formats'].
5119	 * All formats are compatible with this.format() without any additional transformations.
5120	 *
5121	 * @param code
5122	 * @returns {string|null}
5123	 */
5124	function getFormat(code) {
5125	  return formatsCache.remember(`main.date.format.${code}`, () => {
5126	    let format = main_core.Extension.getSettings('main.date').get(`formats.${code}`);
5127	    if (main_core.Type.isStringFilled(format) && (code === 'FORMAT_DATE' || code === 'FORMAT_DATETIME')) {
5128	      format = convertBitrixFormat(format);
5129	    }
5130	    return format;
5131	  });
5132	}
5133
5134	/**
5135	 * @memberOf BX.Main
5136	 * @alias Date
5137	 */
5138	let DateTimeFormat = /*#__PURE__*/function () {
5139	  function DateTimeFormat() {
5140	    babelHelpers.classCallCheck(this, DateTimeFormat);
5141	  }
5142	  babelHelpers.createClass(DateTimeFormat, null, [{
5143	    key: "isAmPmMode",
5144	    value: function isAmPmMode(returnConst) {
5145	      if (returnConst === true) {
5146	        return this._getMessage('AMPM_MODE');
5147	      }
5148	      return this._getMessage('AMPM_MODE') !== false;
5149	    }
5150	  }, {
5151	    key: "convertToUTC",
5152	    value: function convertToUTC(date) {
5153	      if (!main_core.Type.isDate(date)) {
5154	        return null;
5155	      }
5156	      return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds()));
5157	    }
5158	    /**
5159	     * Function creates and returns Javascript Date() object from server timestamp regardless of local browser (system) timezone.
5160	     * For example can be used to convert timestamp from some exact date on server to the JS Date object with the same value.
5161	     *
5162	     * @param timestamp - timestamp in seconds
5163	     * @returns {Date}
5164	     */
5165	  }, {
5166	    key: "getNewDate",
5167	    value: function getNewDate(timestamp) {
5168	      return new Date(this.getBrowserTimestamp(timestamp));
5169	    }
5170	    /**
5171	     * Function transforms server timestamp (in sec) to javascript timestamp (calculated depend on local browser timezone offset). Returns timestamp in milliseconds.
5172	     * Also see BX.Main.Date.getNewDate description.
5173	     *
5174	     * @param timestamp - timestamp in seconds
5175	     * @returns {number}
5176	     */
5177	  }, {
5178	    key: "getBrowserTimestamp",
5179	    value: function getBrowserTimestamp(timestamp) {
5180	      timestamp = parseInt(timestamp, 10);
5181	      const browserOffset = new Date(timestamp * 1000).getTimezoneOffset() * 60;
5182	      return (parseInt(timestamp, 10) + parseInt(this._getMessage('SERVER_TZ_OFFSET')) + browserOffset) * 1000;
5183	    }
5184	    /**
5185	     * Function transforms local browser timestamp (in ms) to server timestamp (calculated depend on local browser timezone offset). Returns timestamp in seconds.
5186	     *
5187	     * @param timestamp - timestamp in milliseconds
5188	     * @returns {number}
5189	     */
5190	  }, {
5191	    key: "getServerTimestamp",
5192	    value: function getServerTimestamp(timestamp) {
5193	      timestamp = parseInt(timestamp, 10);
5194	      const browserOffset = new Date(timestamp).getTimezoneOffset() * 60;
5195	      return Math.round(timestamp / 1000 - (parseInt(this._getMessage('SERVER_TZ_OFFSET'), 10) + parseInt(browserOffset, 10)));
5196	    }
5197	  }, {
5198	    key: "formatLastActivityDate",
5199	    value: function formatLastActivityDate(timestamp, now, utc) {
5200	      const ampm = this.isAmPmMode(true);
5201	      const timeFormat = ampm === this.AM_PM_MODE.LOWER ? 'g:i a' : ampm === this.AM_PM_MODE.UPPER ? 'g:i A' : 'H:i';
5202	      const format = [['tomorrow', '#01#' + timeFormat], ['now', '#02#'], ['todayFuture', '#03#' + timeFormat], ['yesterday', '#04#' + timeFormat], ['-', this.convertBitrixFormat(this._getMessage('FORMAT_DATETIME')).replace(/:s/g, '')], ['
5202s60', 'sago'], ['i60', 'iago'], ['H5', 'Hago'], ['H24', '#03#' + timeFormat], ['d31', 'dago'], ['m12>1', 'mago'], ['m12>0', 'dago'], ['', '#05#']];
5203	      let formattedDate = this.format(format, timestamp, now, utc);
5204	      let match = null;
5205	      if ((match = /^#(\d+)#(.*)/.exec(formattedDate)) != null) {
5206	        switch (match[1]) {
5207	          case '01':
5208	            formattedDate = this._getMessage('FD_LAST_SEEN_TOMORROW').replace('#TIME#', match[2]);
5209	            break;
5210	          case '02':
5211	            formattedDate = this._getMessage('FD_LAST_SEEN_NOW');
5212	            break;
5213	          case '03':
5214	            formattedDate = this._getMessage('FD_LAST_SEEN_TODAY').replace('#TIME#', match[2]);
5215	            break;
5216	          case '04':
5217	            formattedDate = this._getMessage('FD_LAST_SEEN_YESTERDAY').replace('#TIME#', match[2]);
5218	            break;
5219	          case '05':
5220	            formattedDate = this._getMessage('FD_LAST_SEEN_MORE_YEAR');
5221	            break;
5222	          default:
5223	            formattedDate = match[2];
5224	            break;
5225	        }
5226	      }
5227	      return formattedDate;
5228	    }
5229	    /**
5230	     * The method is designed to replace the localization storage on sites without Bitrix Framework.
5231	     * It gets overloaded with custom implementation:
5232	     *
5233	     * const CustomDate = Object.create(BX.Main.Date);
5234	     * CustomDate._getMessage = () => ...new implementation...;
5235	     *
5236	     * This class should get messages only via this method.
5237	     * Otherwise, the class won't work on sites without Bitrix Framework.
5238	     *
5239	     * @param message
5240	     * @returns {*}
5241	     * @private
5242	     */
5243	  }, {
5244	    key: "_getMessage",
5245	    value: function _getMessage(message) {
5246	      return main_core.Loc.getMessage(message);
5247	    }
5248	    /**
5249	     * The method used to parse date from string by given format.
5250	     *
5251	     * @param {string} str - date in given format
5252	     * @param {boolean} isUTC - is date in UTC
5253	     * @param {string} formatDate - format of the date without time
5254	     * @param {string} formatDatetime - format of the date with time
5255	     * @returns {Date|null} - returns Date object if string was parsed or null
5256	     */
5257	  }, {
5258	    key: "parse",
5259	    value: function parse(str, isUTC, formatDate, formatDatetime) {
5260	      if (main_core.Type.isStringFilled(str)) {
5261	        if (!formatDate) {
5262	          formatDate = this._getMessage('FORMAT_DATE');
5263	        }
5264	        if (!formatDatetime) {
5265	          formatDatetime = this._getMessage('FORMAT_DATETIME');
5266	        }
5267	        let regMonths = '';
5268	        for (let i = 1; i <= 12; i++) {
5269	          regMonths = regMonths + '|' + this._getMessage('MON_' + i);
5270	        }
5271	        const expr = new RegExp('([0-9]+|[a-z]+' + regMonths + ')', 'ig');
5272	        const aDate = str.match(expr);
5273	        let aFormat = formatDate.match(/(DD|MI|MMMM|MM|M|YYYY)/ig);
5274	        const aDateArgs = [];
5275	        const aFormatArgs = [];
5276	        const aResult = {};
5277	        if (!aDate) {
5278	          return null;
5279	        }
5280	        if (aDate.length > aFormat.length) {
5281	          aFormat = formatDatetime.match(/(DD|MI|MMMM|MM|M|YYYY|HH|H|SS|TT|T|GG|G)/ig);
5282	        }
5283	        for (let i = 0, cnt = aDate.length; i < cnt; i++) {
5284	          if (aDate[i].trim() !== '') {
5285	            aDateArgs[aDateArgs.length] = aDate[i];
5286	          }
5287	        }
5288	        for (let i = 0, cnt = aFormat.length; i < cnt; i++) {
5289	          if (aFormat[i].trim() !== '') {
5290	            aFormatArgs[aFormatArgs.length] = aFormat[i];
5291	          }
5292	        }
5293	        let m = aFormatArgs.findIndex(item => item === 'MMMM');
5294	        if (m > 0) {
5295	          aDateArgs[m] = this.getMonthIndex(aDateArgs[m]);
5296	          aFormatArgs[m] = 'MM';
5297	        } else {
5298	          m = aFormatArgs.findIndex(item => item === 'M');
5299	          if (m > 0) {
5300	            aDateArgs[m] = this.getMonthIndex(aDateArgs[m]);
5301	            aFormatArgs[m] = 'MM';
5302	          }
5303	        }
5304	        for (let i = 0, cnt = aFormatArgs.length; i < cnt; i++) {
5305	          const k = aFormatArgs[i].toUpperCase();
5306	          aResult[k] = k === 'T' || k === 'TT' ? aDateArgs[i] : parseInt(aDateArgs[i], 10);
5307	        }
5308	        if (aResult['DD'] > 0 && aResult['MM'] > 0 && aResult['YYYY'] > 0) {
5309	          const d = new Date();
5310	          if (isUTC) {
5311	            d.setUTCDate(1);
5312	            d.setUTCFullYear(aResult['YYYY']);
5313	            d.setUTCMonth(aResult['MM'] - 1);
5314	            d.setUTCDate(aResult['DD']);
5315	            d.setUTCHours(0, 0, 0, 0);
5316	          } else {
5317	            d.setDate(1);
5318	            d.setFullYear(aResult['YYYY']);
5319	            d.setMonth(aResult['MM'] - 1);
5320	            d.setDate(aResult['DD']);
5321	            d.setHours(0, 0, 0, 0);
5322	          }
5323	          if ((!isNaN(aResult['HH']) || !isNaN(aResult['GG']) || !isNaN(aResult['H']) || !isNaN(aResult['G'])) && !isNaN(aResult['MI'])) {
5324	            if (!isNaN(aResult['H']) || !isNaN(aResult['G'])) {
5325	              const bPM = (aResult['T'] || aResult['TT'] || 'am').toUpperCase() === 'PM',
5326	                h = parseInt(aResult['H'] || aResult['G'] || 0, 10);
5327	              if (bPM) {
5328	                aResult['HH'] = h + (h === 12 ? 0 : 12);
5329	              } else {
5330	                aResult['HH'] = h < 12 ? h : 0;
5331	              }
5332	            } else {
5333	              aResult['HH'] = parseInt(aResult['HH'] || aResult['GG'] || 0, 10);
5334	            }
5335	            if (isNaN(aResult['SS'])) {
5336	              aResult['SS'] = 0;
5337	            }
5338	            if (isUTC) {
5339	              d.setUTCHours(aResult['HH'], aResult['MI'], aResult['SS']);
5340	            } else {
5341	              d.setHours(aResult['HH'], aResult['MI'], aResult['SS']);
5342	            }
5343	          }
5344	          return d;
5345	        }
5346	      }
5347	      return null;
5348	    }
5349	  }, {
5350	    key: "getMonthIndex",
5351	    value: function getMonthIndex(month) {
5352	      const q = month.toUpperCase();
5353	      const wordMonthCut = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
5354	      const wordMonth = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december'];
5355	      for (let i = 1; i <= 12; i++) {
5356	        if (q === this._getMessage('MON_' + i).toUpperCase() || q === this._getMessage('MONTH_' + i).toUpperCase() || q === this._getMessage('MONTH_' + i + '_S').toUpperCase() || q === wordMonthCut[i - 1].toUpperCase() || q === wordMonth[i - 1].toUpperCase()) {
5357	          return i;
5358	        }
5359	      }
5360	      return month;
5361	    }
5362	  }, {
5363	    key: "format",
5364	    value: function format(_format, timestamp, now, utc) {
5365	      /*
5366	      PHP to Javascript:
5367	      	time() = new Date()
5368	      	mktime(...) = new Date(...)
5369	      	gmmktime(...) = new Date(Date.UTC(...))
5370	      	mktime(0,0,0, 1, 1, 1970) != 0          new Date(1970,0,1).getTime() != 0
5371	      	gmmktime(0,0,0, 1, 1, 1970) == 0        new Date(Date.UTC(1970,0,1)).getTime() == 0
5372	      	date('d.m.Y H:i:s') = BX.Main.Date.format('d.m.Y H:i:s')
5373	      	gmdate('d.m.Y H:i:s') = BX.Main.Date.format('d.m.Y H:i:s', null, null, true);
5374	      */
5375	      const date = main_core.Type.isDate(timestamp) ? new Date(timestamp.getTime()) : main_core.Type.isNumber(timestamp) ? new Date(timestamp * 1000) : new Date();
5376	      const nowDate = main_core.Type.isDate(now) ? new Date(now.getTime()) : main_core.Type.isNumber(now) ? new Date(now * 1000) : new Date();
5377	      const isUTC = !!utc;
5378	      // used in hoisting inner functions, like _formatDateInterval
5379	      const thisDateTimeFormat = this;
5380	      if (main_core.Type.isArray(_format)) {
5381	        return _formatDateInterval(_format, date, nowDate, isUTC);
5382	      } else {
5383	        if (!main_core.Type.isStringFilled(_format)) {
5384	          return '';
5385	        }
5386	      }
5387	      const replaceMap = (_format.match(/{{([^{}]*)}}/g) || []).map(x => {
5388	        return (x.match(/[^{}]+/) || [''])[0];
5389	      });
5390	      if (replaceMap.length > 0) {
5391	        replaceMap.forEach((element, index) => {
5392	          _format = _format.replace('{{' + element + '}}', '{{' + index + '}}');
5393	        });
5394	      }
5395	      const formatRegex = /\\?(sago|iago|isago|Hago|dago|mago|Yago|sdiff|idiff|Hdiff|ddiff|mdiff|Ydiff|sshort|ishort|Hshort|dshort|mshort|Yshort|yesterday|today|tommorow|tomorrow|.)/gi;
5396	      const dateFormats = {
5397	        d: () => {
5398	          // Day of the month 01 to 31
5399	          return getDate(date).toString().padStart(2, '0');
5400	        },
5401	        D: () => {
5402	          //Mon through Sun
5403	          return this._getMessage('DOW_' + getDay(date));
5404	        },
5405	        j: () => {
5406	          //Day of the month 1 to 31
5407	          return getDate(date);
5408	        },
5409	        l: () => {
5410	          //Sunday through Saturday
5411	          return this._getMessage('DAY_OF_WEEK_' + getDay(date));
5412	        },
5413	        N: () => {
5414	          //1 (for Monday) through 7 (for Sunday)
5415	          return getDay(date) || 7;
5416	        },
5417	        S: () => {
5418	          //st, nd, rd or th. Works well with j
5419	          if (getDate(date) % 10 == 1 && getDate(date) != 11) {
5420	            return 'st';
5421	          } else if (getDate(date) % 10 == 2 && getDate(date) != 12) {
5422	            return 'nd';
5423	          } else if (getDate(date) % 10 == 3 && getDate(date) != 13) {
5424	            return 'rd';
5425	          } else {
5426	            return 'th';
5427	          }
5428	        },
5429	        w: () => {
5430	          //0 (for Sunday) through 6 (for Saturday)
5431	          return getDay(date);
5432	        },
5433	        z: () => {
5434	          //0 through 365
5435	          const firstDay = new Date(getFullYear(date), 0, 1);
5436	          const currentDay = new Date(getFullYear(date), getMonth(date), getDate(date));
5437	          return Math.ceil((currentDay - firstDay) / (24 * 3600 * 1000));
5438	        },
5439	        W: () => {
5440	          //ISO-8601 week number of year
5441	          const newDate = new Date(date.getTime());
5442	          const dayNumber = (getDay(date) + 6) % 7;
5443	          setDate(newDate, getDate(newDate) - dayNumber + 3);
5444	          const firstThursday = newDate.getTime();
5445	          setMonth(newDate, 0, 1);
5446	          if (getDay(newDate) != 4) {
5447	            setMonth(newDate, 0, 1 + (4 - getDay(newDate) + 7) % 7);
5448	          }
5449	          const weekNumber = 1 + Math.ceil((firstThursday - newDate) / (7 * 24 * 3600 * 1000));
5450	          return weekNumber.toString().padStart(2, '0');
5451	        },
5452	        F: () => {
5453	          //January through December
5454	          return this._getMessage('MONTH_' + (getMonth(date) + 1) + '_S');
5455	        },
5456	        f: () => {
5457	          //January through December
5458	          return this._getMessage('MONTH_' + (getMonth(date) + 1));
5459	        },
5460	        m: () => {
5461	          //Numeric representation of a month 01 through 12
5462	          return (getMonth(date) + 1).toString().padStart(2, '0');
5463	        },
5464	        M: () => {
5465	          //A short textual representation of a month, three letters Jan through Dec
5466	          return this._getMessage('MON_' + (getMonth(date) + 1));
5467	        },
5468	        n: () => {
5469	          //Numeric representation of a month 1 through 12
5470	          return getMonth(date) + 1;
5471	        },
5472	        t: () => {
5473	          //Number of days in the given month 28 through 31
5474	          const lastMonthDay = isUTC ? new Date(Date.UTC(getFullYear(date), getMonth(date) + 1, 0)) : new Date(getFullYear(date), getMonth(date) + 1, 0);
5475	          return getDate(lastMonthDay);
5476	        },
5477	        L: () => {
5478	          //1 if it is a leap year, 0 otherwise.
5479	          const year = getFullYear(date);
5480	          return year % 4 == 0 && year % 100 != 0 || year % 400 == 0 ? 1 : 0;
5481	        },
5482	        o: () => {
5483	          //ISO-8601 year number
5484	          const correctDate = new Date(date.getTime());
5485	          setDate(correctDate, getDate(correctDate) - (getDay(date) + 6) % 7 + 3);
5486	          return getFullYear(correctDate);
5487	        },
5488	        Y: () => {
5489	          //A full numeric representation of a year, 4 digits
5490	          return getFullYear(date);
5491	        },
5492	        y: () => {
5493	          //A two digit representation of a year
5494	          return getFullYear(date).toString().slice(2);
5495	        },
5496	        a: () => {
5497	          //am or pm
5498	          return getHours(date) > 11 ? 'pm' : 'am';
5499	        },
5500	        A: () => {
5501	          //AM or PM
5502	          return getHours(date) > 11 ? 'PM' : 'AM';
5503	        },
5504	        B: () => {
5505	          //000 through 999
5506	          const swatch = (date.getUTCHours() + 1) % 24 + date.getUTCMinutes() / 60 + date.getUTCSeconds() / 3600;
5507	          return Math.floor(swatch * 1000 / 24).toString().padStart(3, '0');
5508	        },
5509	        g: () => {
5510	          //12-hour format of an hour without leading zeros 1 through 12
5511	          return getHours(date) % 12 || 12;
5512	        },
5513	        G: () => {
5514	          //24-hour format of an hour without leading zeros 0 through 23
5515	          return getHours(date);
5516	        },
5517	        h: () => {
5518	          //12-hour format of an hour with leading zeros 01 through 12
5519	          return (getHours(date) % 12 || 12).toString().padStart(2, '0');
5520	        },
5521	        H: () => {
5522	          //24-hour format of an hour with leading zeros 00 through 23
5523	          return getHours(date).toString().padStart(2, '0');
5524	        },
5525	        i: () => {
5526	          //Minutes with leading zeros 00 to 59
5527	          return getMinutes(date).toString().padStart(2, '0');
5528	        },
5529	        s: () => {
5530	          //Seconds, with leading zeros 00 through 59
5531	          return getSeconds(date).toString().padStart(2, '0');
5532	        },
5533	        u: () => {
5534	          //Microseconds
5535	          return (getMilliseconds(date) * 1000).toString().padStart(6, '0');
5536	        },
5537	        e: () => {
5538	          if (isUTC) {
5539	            return 'UTC';
5540	          }
5541	          return '';
5542	        },
5543	        I: () => {
5544	          if (isUTC) {
5545	            return 0;
5546	          }
5547
5548	          //Whether or not the date is in daylight saving time 1 if Daylight Saving Time, 0 otherwise
5549	          const firstJanuary = new Date(getFullYear(date), 0, 1);
5550	          const firstJanuaryUTC = Date.UTC(getFullYear(date), 0, 1);
5551	          const firstJuly = new Date(getFullYear(date), 6, 0);
5552	          const firstJulyUTC = Date.UTC(getFullYear(date), 6, 0);
5553	          return 0 + (firstJanuary - firstJanuaryUTC !== firstJuly - firstJulyUTC);
5554	        },
5555	        O: () => {
5556	          if (isUTC) {
5557	            return '+0000';
5558	          }
5559
5560	          //Difference to Greenwich time (GMT) in hours +0200
5561	          const timezoneOffset = date.getTimezoneOffset();
5562	          const timezoneOffsetAbs = Math.abs(timezoneOffset);
5563	          return (timezoneOffset > 0 ? '-' : '+') + (Math.floor(timezoneOffsetAbs / 60) * 100 + timezoneOffsetAbs % 60).toString().padStart(4, '0');
5564	        },
5565	        //this method references 'O' method of the same object, arrow function is not suitable here
5566	        P: function () {
5567	          if (isUTC) {
5568	            return '+00:00';
5569	          }
5570
5571	          //Difference to Greenwich time (GMT) with colon between hours and minutes +02:00
5572	          const difference = this.O();
5573	          return difference.substr(0, 3) + ':' + difference.substr(3);
5574	        },
5575	        Z: () => {
5576	          if (isUTC) {
5577	            return 0;
5578	          }
5579	          //Timezone offset in seconds. The offset for timezones west of UTC is always negative,
5580	          //and for those east of UTC is always positive.
5581	          return -date.getTimezoneOffset() * 60;
5582	        },
5583	        c: () => {
5584	          //ISO 8601 date
5585	          return 'Y-m-d\\TH:i:sP'.replace(formatRegex, _replaceDateFormat);
5586	        },
5587	        r: () => {
5588	          //RFC 2822 formatted date
5589	          return 'D, d M Y H:i:s O'.replace(formatRegex, _replaceDateFormat);
5590	        },
5591	        U: () => {
5592	          //Seconds since the Unix Epoch
5593	          return Math.floor(date.getTime() / 1000);
5594	        },
5595	        sago: () => {
5596	          return _formatDateMessage(intval((nowDate - date) / 1000), {
5597	            '0': 'FD_SECOND_AGO_0',
5598	            '1': 'FD_SECOND_AGO_1',
5599	            '10_20': 'FD_SECOND_AGO_10_20',
5600	            'MOD_1': 'FD_SECOND_AGO_MOD_1',
5601	            'MOD_2_4': 'FD_SECOND_AGO_MOD_2_4',
5602	            'MOD_OTHER': 'FD_SECOND_AGO_MOD_OTHER'
5603	          });
5604	        },
5605	        sdiff: () => {
5606	          return _formatDateMessage(intval((nowDate - date) / 1000), {
5607	            '0': 'FD_SECOND_DIFF_0',
5608	            '1': 'FD_SECOND_DIFF_1',
5609	            '10_20': 'FD_SECOND_DIFF_10_20',
5610	            'MOD_1': 'FD_SECOND_DIFF_MOD_1',
5611	            'MOD_2_4': 'FD_SECOND_DIFF_MOD_2_4',
5612	            'MOD_OTHER': 'FD_SECOND_DIFF_MOD_OTHER'
5613	          });
5614	        },
5615	        sshort: () => {
5616	          return this._getMessage('FD_SECOND_SHORT').replace(/#VALUE#/g, intval((nowDate - date) / 1000));
5617	        },
5618	        iago: () => {
5619	          return _formatDateMessage(intval((nowDate - date) / 60 / 1000), {
5620	            '0': 'FD_MINUTE_AGO_0',
5621	            '1': 'FD_MINUTE_AGO_1',
5622	            '10_20': 'FD_MINUTE_AGO_10_20',
5623	            'MOD_1': 'FD_MINUTE_AGO_MOD_1',
5624	            'MOD_2_4': 'FD_MINUTE_AGO_MOD_2_4',
5625	            'MOD_OTHER': 'FD_MINUTE_AGO_MOD_OTHER'
5626	          });
5627	        },
5628	        idiff: () => {
5629	          return _formatDateMessage(intval((nowDate - date) / 60 / 1000), {
5630	            '0': 'FD_MINUTE_DIFF_0',
5631	            '1': 'FD_MINUTE_DIFF_1',
5632	            '10_20': 'FD_MINUTE_DIFF_10_20',
5633	            'MOD_1': 'FD_MINUTE_DIFF_MOD_1',
5634	            'MOD_2_4': 'FD_MINUTE_DIFF_MOD_2_4',
5635	            'MOD_OTHER': 'FD_MINUTE_DIFF_MOD_OTHER'
5636	          });
5637	        },
5638	        isago: () => {
5639	          const minutesAgo = intval((nowDate - date) / 60 / 1000);
5640	          let result = _formatDateMessage(minutesAgo, {
5641	            '0': 'FD_MINUTE_0',
5642	            '1': 'FD_MINUTE_1',
5643	            '10_20': 'FD_MINUTE_10_20',
5644	            'MOD_1': 'FD_MINUTE_MOD_1',
5645	            'MOD_2_4': 'FD_MINUTE_MOD_2_4',
5646	            'MOD_OTHER': 'FD_MINUTE_MOD_OTHER'
5647	          });
5648	          result += ' ';
5649	          const secondsAgo = intval((nowDate - date) / 1000) - minutesAgo * 60;
5650	          result += _formatDateMessage(secondsAgo, {
5651	            '0': 'FD_SECOND_AGO_0',
5652	            '1': 'FD_SECOND_AGO_1',
5653	            '10_20': 'FD_SECOND_AGO_10_20',
5654	            'MOD_1': 'FD_SECOND_AGO_MOD_1',
5655	            'MOD_2_4': 'FD_SECOND_AGO_MOD_2_4',
5656	            'MOD_OTHER': 'FD_SECOND_AGO_MOD_OTHER'
5657	          });
5658	          return result;
5659	        },
5660	        ishort: () => {
5661	          return this._getMessage('FD_MINUTE_SHORT').replace(/#VALUE#/g, intval((nowDate - date) / 60 / 1000));
5662	        },
5663	        Hago: () => {
5664	          return _formatDateMessage(intval((nowDate - date) / 60 / 60 / 1000), {
5665	            '0': 'FD_HOUR_AGO_0',
5666	            '1': 'FD_HOUR_AGO_1',
5667	            '10_20': 'FD_HOUR_AGO_10_20',
5668	            'MOD_1': 'FD_HOUR_AGO_MOD_1',
5669	            'MOD_2_4': 'FD_HOUR_AGO_MOD_2_4',
5670	            'MOD_OTHER': 'FD_HOUR_AGO_MOD_OTHER'
5671	          });
5672	        },
5673	        Hdiff: () => {
5674	          return _formatDateMessage(intval((nowDate - date) / 60 / 60 / 1000), {
5675	            '0': 'FD_HOUR_DIFF_0',
5676	            '1': 'FD_HOUR_DIFF_1',
5677	            '10_20': 'FD_HOUR_DIFF_10_20',
5678	            'MOD_1': 'FD_HOUR_DIFF_MOD_1',
5679	            'MOD_2_4': 'FD_HOUR_DIFF_MOD_2_4',
5680	            'MOD_OTHER': 'FD_HOUR_DIFF_MOD_OTHER'
5681	          });
5682	        },
5683	        Hshort: () => {
5684	          return this._getMessage('FD_HOUR_SHORT').replace(/#VALUE#/g, intval((nowDate - date) / 60 / 60 / 1000));
5685	        },
5686	        yesterday: () => {
5687	          return this._getMessage('FD_YESTERDAY');
5688	        },
5689	        today: () => {
5690	          return this._getMessage('FD_TODAY');
5691	        },
5692	        tommorow: () => {
5693	          return this._getMessage('FD_TOMORROW');
5694	        },
5695	        tomorrow: () => {
5696	          return this._getMessage('FD_TOMORROW');
5697	        },
5698	        dago: () => {
5699	          return _formatDateMessage(intval((nowDate - date) / 60 / 60 / 24 / 1000), {
5700	            '0': 'FD_DAY_AGO_0',
5701	            '1': 'FD_DAY_AGO_1',
5702	            '10_20': 'FD_DAY_AGO_10_20',
5703	            'MOD_1': 'FD_DAY_AGO_MOD_1',
5704	            'MOD_2_4': 'FD_DAY_AGO_MOD_2_4',
5705	            'MOD_OTHER': 'FD_DAY_AGO_MOD_OTHER'
5706	          });
5707	        },
5708	        ddiff: () => {
5709	          return _formatDateMessage(intval((nowDate - date) / 60 / 60 / 24 / 1000), {
5710	            '0': 'FD_DAY_DIFF_0',
5711	            '1': 'FD_DAY_DIFF_1',
5712	            '10_20': 'FD_DAY_DIFF_10_20',
5713	            'MOD_1': 'FD_DAY_DIFF_MOD_1',
5714	            'MOD_2_4': 'FD_DAY_DIFF_MOD_2_4',
5715	            'MOD_OTHER': 'FD_DAY_DIFF_MOD_OTHER'
5716	          });
5717	        },
5718	        dshort: () => {
5719	          return this._getMessage('FD_DAY_SHORT').replace(/#VALUE#/g, intval((nowDate - date) / 60 / 60 / 24 / 1000));
5720	        },
5721	        mago: () => {
5722	          return _formatDateMessage(intval((nowDate - date) / 60 / 60 / 24 / 31 / 1000), {
5723	            '0': 'FD_MONTH_AGO_0',
5724	            '1': 'FD_MONTH_AGO_1',
5725	            '10_20': 'FD_MONTH_AGO_10_20',
5726	            'MOD_1': 'FD_MONTH_AGO_MOD_1',
5727	            'MOD_2_4': 'FD_MONTH_AGO_MOD_2_4',
5728	            'MOD_OTHER': 'FD_MONTH_AGO_MOD_OTHER'
5729	          });
5730	        },
5731	        mdiff: () => {
5732	          return _formatDateMessage(intval((nowDate - date) / 60 / 60 / 24 / 31 / 1000), {
5733	            '0': 'FD_MONTH_DIFF_0',
5734	            '1': 'FD_MONTH_DIFF_1',
5735	            '10_20': 'FD_MONTH_DIFF_10_20',
5736	            'MOD_1': 'FD_MONTH_DIFF_MOD_1',
5737	            'MOD_2_4': 'FD_MONTH_DIFF_MOD_2_4',
5738	            'MOD_OTHER': 'FD_MONTH_DIFF_MOD_OTHER'
5739	          });
5740	        },
5741	        mshort: () => {
5742	          return this._getMessage('FD_MONTH_SHORT').replace(/#VALUE#/g, intval((nowDate - date) / 60 / 60 / 24 / 31 / 1000));
5743	        },
5744	        Yago: () => {
5745	          return _formatDateMessage(intval((nowDate - date) / 60 / 60 / 24 / 365 / 1000), {
5746	            '0': 'FD_YEARS_AGO_0',
5747	            '1': 'FD_YEARS_AGO_1',
5748	            '10_20': 'FD_YEARS_AGO_10_20',
5749	            'MOD_1': 'FD_YEARS_AGO_MOD_1',
5750	            'MOD_2_4': 'FD_YEARS_AGO_MOD_2_4',
5751	            'MOD_OTHER': 'FD_YEARS_AGO_MOD_OTHER'
5752	          });
5753	        },
5754	        Ydiff: () => {
5755	          return _formatDateMessage(intval((nowDate - date) / 60 / 60 / 24 / 365 / 1000), {
5756	            '0': 'FD_YEARS_DIFF_0',
5757	            '1': 'FD_YEARS_DIFF_1',
5758	            '10_20': 'FD_YEARS_DIFF_10_20',
5759	            'MOD_1': 'FD_YEARS_DIFF_MOD_1',
5760	            'MOD_2_4': 'FD_YEARS_DIFF_MOD_2_4',
5761	            'MOD_OTHER': 'FD_YEARS_DIFF_MOD_OTHER'
5762	          });
5763	        },
5764	        Yshort: () => {
5765	          return _formatDateMessage(intval((nowDate - date) / 60 / 60 / 24 / 365 / 1000), {
5766	            '0': 'FD_YEARS_SHORT_0',
5767	            '1': 'FD_YEARS_SHORT_1',
5768	            '10_20': 'FD_YEARS_SHORT_10_20',
5769	            'MOD_1': 'FD_YEARS_SHORT_MOD_1',
5770	            'MOD_2_4': 'FD_YEARS_SHORT_MOD_2_4',
5771	            'MOD_OTHER': 'FD_YEARS_SHORT_MOD_OTHER'
5772	          });
5773	        },
5774	        x: () => {
5775	          const ampm = this.isAmPmMode(true);
5776	          const timeFormat = ampm === this.AM_PM_MODE.LOWER ? 'g:i a' : ampm === this.AM_PM_MODE.UPPER ? 'g:i A' : 'H:i';
5777	          return this.format([['tomorrow', 'tomorrow, ' + timeFormat], ['-', this.convertBitrixFormat(this._getMessage('FORMAT_DATETIME')).replace(/:s/g, '')], ['
5777s', 'sago'], ['i', 'iago'], ['today', 'today, ' + timeFormat], ['yesterday', 'yesterday, ' + timeFormat], ['', this.convertBitrixFormat(this._getMessage('FORMAT_DATETIME')).replace(/:s/g, '')]], date, nowDate, isUTC);
5778	        },
5779	        X: () => {
5780	          const ampm = this.isAmPmMode(true);
5781	          const timeFormat = ampm === this.AM_PM_MODE.LOWER ? 'g:i a' : ampm === this.AM_PM_MODE.UPPER ? 'g:i A' : 'H:i';
5782	          const day = this.format([['tomorrow', 'tomorrow'], ['-', this.convertBitrixFormat(this._getMessage('FORMAT_DATE'))], ['today', 'today'], ['yesterday', 'yesterday'], ['', this.convertBitrixFormat(this._getMessage('FORMAT_DATE'))]], date, nowDate, isUTC);
5783	          const time = this.format([['tomorrow', timeFormat], ['today', timeFormat], ['yesterday', timeFormat], ['', '']], date, nowDate, isUTC);
5784	          if (time.length > 0) {
5785	            return this._getMessage('FD_DAY_AT_TIME').replace(/#DAY#/g, day).replace(/#TIME#/g, time);
5786	          } else {
5787	            return day;
5788	          }
5789	        },
5790	        Q: () => {
5791	          const daysAgo = intval((nowDate - date) / 60 / 60 / 24 / 1000);
5792	          if (daysAgo == 0) {
5793	            return this._getMessage('FD_DAY_DIFF_1').replace(/#VALUE#/g, 1);
5794	          } else {
5795	            return this.format([['d', 'ddiff'], ['m', 'mdiff'], ['', 'Ydiff']], date, nowDate);
5796	          }
5797	        }
5798	      };
5799	      let cutZeroTime = false;
5800	      if (_format[0] && _format[0] == '^') {
5801	        cutZeroTime = true;
5802	        _format = _format.substr(1);
5803	      }
5804	      let result = _format.replace(formatRegex, _replaceDateFormat);
5805	      if (cutZeroTime) {
5806	        /* 	15.04.12 13:00:00 => 15.04.12 13:00
5807	        	00:01:00 => 00:01
5808	        	4 may 00:00:00 => 4 may
5809	        	01-01-12 00:00 => 01-01-12
5810	        */
5811
5812	        result = result.replace(/\s*00:00:00\s*/g, '').replace(/(\d\d:\d\d)(:00)/g, '$1').replace(/(\s*00:00\s*)(?!:)/g, '');
5813	      }
5814	      if (replaceMap.length > 0) {
5815	        replaceMap.forEach(function (element, index) {
5816	          result = result.replace('{{' + index + '}}', element);
5817	        });
5818	      }
5819	      return result;
5820	      function _formatDateInterval(formats, date, nowDate, isUTC) {
5821	        const secondsAgo = intval((nowDate - date) / 1000);
5822	        for (let i = 0; i < formats.length; i++) {
5823	          const formatInterval = formats[i][0];
5824	          const formatValue = formats[i][1];
5825	          let match = null;
5826	          if (formatInterval == 's') {
5827	            if (secondsAgo < 60) {
5828	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5829	            }
5830	          } else if ((match = /^s(\d+)\>?(\d+)?/.exec(formatInterval)) != null) {
5831	            if (match[1] && match[2]) {
5832	              if (secondsAgo < match[1] && secondsAgo > match[2]) {
5833	                return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5834	              }
5835	            } else if (secondsAgo < match[1]) {
5836	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5837	            }
5838	          } else if (formatInterval == 'i') {
5839	            if (secondsAgo < 60 * 60) {
5840	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5841	            }
5842	          } else if ((match = /^i(\d+)\>?(\d+)?/.exec(formatInterval)) != null) {
5843	            if (match[1] && match[2]) {
5844	              if (secondsAgo < match[1] * 60 && secondsAgo > match[2] * 60) {
5845	                return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5846	              }
5847	            } else if (secondsAgo < match[1] * 60) {
5848	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5849	            }
5850	          } else if (formatInterval == 'H') {
5851	            if (secondsAgo < 24 * 60 * 60) {
5852	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5853	            }
5854	          } else if ((match = /^H(\d+)\>?(\d+)?/.exec(formatInterval)) != null) {
5855	            if (match[1] && match[2]) {
5856	              if (secondsAgo < match[1] * 60 * 60 && secondsAgo > match[2] * 60 * 60) {
5857	                return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5858	              }
5859	            } else if (secondsAgo < match[1] * 60 * 60) {
5860	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5861	            }
5862	          } else if (formatInterval == 'd') {
5863	            if (secondsAgo < 31 * 24 * 60 * 60) {
5864	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5865	            }
5866	          } else if ((match = /^d(\d+)\>?(\d+)?/.exec(formatInterval)) != null) {
5867	            if (match[1] && match[2]) {
5868	              if (secondsAgo < match[1] * 24 * 60 * 60 && secondsAgo > match[2] * 24 * 60 * 60) {
5869	                return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5870	              }
5871	            } else if (secondsAgo < match[1] * 24 * 60 * 60) {
5872	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5873	            }
5874	          } else if (formatInterval == 'm') {
5875	            if (secondsAgo < 365 * 24 * 60 * 60) {
5876	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5877	            }
5878	          } else if ((match = /^m(\d+)\>?(\d+)?/.exec(formatInterval)) != null) {
5879	            if (match[1] && match[2]) {
5880	              if (secondsAgo < match[1] * 31 * 24 * 60 * 60 && secondsAgo > match[2] * 31 * 24 * 60 * 60) {
5881	                return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5882	              }
5883	            } else if (secondsAgo < match[1] * 31 * 24 * 60 * 60) {
5884	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5885	            }
5886	          } else if (formatInterval == 'now') {
5887	            if (date.getTime() == nowDate.getTime()) {
5888	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5889	            }
5890	          } else if (formatInterval == 'today') {
5891	            const year = getFullYear(nowDate);
5892	            const month = getMonth(nowDate);
5893	            const day = getDate(nowDate);
5894	            const todayStart = isUTC ? new Date(Date.UTC(year, month, day, 0, 0, 0, 0)) : new Date(year, month, day, 0, 0, 0, 0);
5895	            const todayEnd = isUTC ? new Date(Date.UTC(year, month, day + 1, 0, 0, 0, 0)) : new Date(year, month, day + 1, 0, 0, 0, 0);
5896	            if (date >= todayStart && date < todayEnd) {
5897	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5898	            }
5899	          } else if (formatInterval == 'todayFuture') {
5900	            const year = getFullYear(nowDate);
5901	            const month = getMonth(nowDate);
5902	            const day = getDate(nowDate);
5903	            const todayStart = nowDate.getTime();
5904	            const todayEnd = isUTC ? new Date(Date.UTC(year, month, day + 1, 0, 0, 0, 0)) : new Date(year, month, day + 1, 0, 0, 0, 0);
5905	            if (date >= todayStart && date < todayEnd) {
5906	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5907	            }
5908	          } else if (formatInterval == 'yesterday') {
5909	            const year = getFullYear(nowDate);
5910	            const month = getMonth(nowDate);
5911	            const day = getDate(nowDate);
5912	            const yesterdayStart = isUTC ? new Date(Date.UTC(year, month, day - 1, 0, 0, 0, 0)) : new Date(year, month, day - 1, 0, 0, 0, 0);
5913	            const yesterdayEnd = isUTC ? new Date(Date.UTC(year, month, day, 0, 0, 0, 0)) : new Date(year, month, day, 0, 0, 0, 0);
5914	            if (date >= yesterdayStart && date < yesterdayEnd) {
5915	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5916	            }
5917	          } else if (formatInterval == 'tommorow' || formatInterval == 'tomorrow') {
5918	            const year = getFullYear(nowDate);
5919	            const month = getMonth(nowDate);
5920	            const day = getDate(nowDate);
5921	            const tomorrowStart = isUTC ? new Date(Date.UTC(year, month, day + 1, 0, 0, 0, 0)) : new Date(year, month, day + 1, 0, 0, 0, 0);
5922	            const tomorrowEnd = isUTC ? new Date(Date.UTC(year, month, day + 2, 0, 0, 0, 0)) : new Date(year, month, day + 2, 0, 0, 0, 0);
5923	            if (date >= tomorrowStart && date < tomorrowEnd) {
5924	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5925	            }
5926	          } else if (formatInterval == '-') {
5927	            if (secondsAgo < 0) {
5928	              return thisDateTimeFormat.format(formatValue, date, nowDate, isUTC);
5929	            }
5930	          }
5931	        }
5932
5933	        //return formats.length > 0 ? thisDateTimeFormat.format(formats.pop()[1], date, nowDate, isUTC) : '';
5934	        return formats.length > 0 ? thisDateTimeFormat.format(formats[formats.length - 1][1], date, nowDate, isUTC) : '';
5935	      }
5936	      function getFullYear(date) {
5937	        return isUTC ? date.getUTCFullYear() : date.getFullYear();
5938	      }
5939	      function getDate(date) {
5940	        return isUTC ? date.getUTCDate() : date.getDate();
5941	      }
5942	      function getMonth(date) {
5943	        return isUTC ? date.getUTCMonth() : date.getMonth();
5944	      }
5945	      function getHours(date) {
5946	        return isUTC ? date.getUTCHours() : date.getHours();
5947	      }
5948	      function getMinutes(date) {
5949	        return isUTC ? date.getUTCMinutes() : date.getMinutes();
5950	      }
5951	      function getSeconds(date) {
5952	        return isUTC ? date.getUTCSeconds() : date.getSeconds();
5953	      }
5954	      function getMilliseconds(date) {
5955	        return isUTC ? date.getUTCMilliseconds() : date.getMilliseconds();
5956	      }
5957	      function getDay(date) {
5958	        return isUTC ? date.getUTCDay() : date.getDay();
5959	      }
5960	      function setDate(date, dayValue) {
5961	        return isUTC ? date.setUTCDate(dayValue) : date.setDate(dayValue);
5962	      }
5963	      function setMonth(date, monthValue, dayValue) {
5964	        return isUTC ? date.setUTCMonth(monthValue, dayValue) : date.setMonth(monthValue, dayValue);
5965	      }
5966	      function _formatDateMessage(value, messages) {
5967	        const val = value < 100 ? Math.abs(value) : Math.abs(value % 100);
5968	        const dec = val % 10;
5969	        let message = '';
5970	        if (val == 0) {
5971	          message = thisDateTimeFormat._getMessage(messages['0']);
5972	        } else if (val == 1) {
5973	          message = thisDateTimeFormat._getMessage(messages['1']);
5974	        } else if (val >= 10 && val <= 20) {
5975	          message = thisDateTimeFormat._getMessage(messages['10_20']);
5976	        } else if (dec == 1) {
5977	          message = thisDateTimeFormat._getMessage(messages['MOD_1']);
5978	        } else if (2 <= dec && dec <= 4) {
5979	          message = thisDateTimeFormat._getMessage(messages['MOD_2_4']);
5980	        } else {
5981	          message = thisDateTimeFormat._getMessage(messages['MOD_OTHER']);
5982	        }
5983	        return message.replace(/#VALUE#/g, value);
5984	      }
5985	      function _replaceDateFormat(match, matchFull) {
5986	        if (dateFormats[match]) {
5987	          return dateFormats[match]();
5988	        } else {
5989	          return matchFull;
5990	        }
5991	      }
5992	      function intval(number) {
5993	        return number >= 0 ? Math.floor(number) : Math.ceil(number);
5994	      }
5995	    }
5996	  }]);
5997	  return DateTimeFormat;
5998	}();
5999	babelHelpers.defineProperty(DateTimeFormat, "AM_PM_MODE", {
6000	  UPPER: 1,
6001	  LOWER: 2,
6002	  NONE: false
6003	});
6004	babelHelpers.defineProperty(DateTimeFormat, "convertBitrixFormat", convertBitrixFormat);
6005	babelHelpers.defineProperty(DateTimeFormat, "getFormat", getFormat);
6006
6007	function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
6008	function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
6009	function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }
6010
6011	/**
6012	 * Available units: `Y` - years, `m` - months, `d` - days, `H` - hours, `i` - minutes, `s` - seconds.
6013	 */
6014
6015	const defaultOptions = {
6016	  format: 'Y m d H i s',
6017	  style: 'long'
6018	};
6019	var _getSeparator = /*#__PURE__*/new WeakSet();
6020	var _getMaxUnit = /*#__PURE__*/new WeakSet();
6021	var _formatUnit = /*#__PURE__*/new WeakSet();
6022	var _getUnitPropertyModByFormat = /*#__PURE__*/new WeakSet();
6023	var _getUnitPropertyByFormat = /*#__PURE__*/new WeakSet();
6024	var _getUnitDuration = /*#__PURE__*/new WeakSet();
6025	let DurationFormat = /*#__PURE__*/function () {
6026	  function DurationFormat(milliseconds) {
6027	    babelHelpers.classCallCheck(this, DurationFormat);
6028	    _classPrivateMethodInitSpec(this, _getUnitDuration);
6029	    _classPrivateMethodInitSpec(this, _getUnitPropertyByFormat);
6030	    _classPrivateMethodInitSpec(this, _getUnitPropertyModByFormat);
6031	    _classPrivateMethodInitSpec(this, _formatUnit);
6032	    _classPrivateMethodInitSpec(this, _getMaxUnit);
6033	    _classPrivateMethodInitSpec(this, _getSeparator);
6034	    this.milliseconds = Math.abs(milliseconds);
6035	  }
6036	  babelHelpers.createClass(DurationFormat, [{
6037	    key: "format",
6038	    /**
6039	     * @example new DurationFormat(5070000).format() // 1 hour, 24 minutes, 30 seconds
6040	     * @example new DurationFormat(5070000).format({ style: 'short' }) // 1 h 24 m 30 s
6041	     * @example new DurationFormat(5070000).format({ format: 'd H i' }) // 1 hour, 24 minutes
6042	     * @example new DurationFormat(5070000).format({ format: 'i s' }) // 84 minutes, 30 seconds
6043	     */
6044	    value: function format(formatOptions = defaultOptions) {
6045	      const options = {
6046	        ...defaultOptions,
6047	        ...formatOptions
6048	      };
6049	      const orderedUnits = main_core.Loc.getMessage('FD_UNIT_ORDER').split(' ');
6050	      const separator = _classPrivateMethodGet(this, _getSeparator, _getSeparator2).
6050call(this, options.style);
6051	      const formatUnits = new Set(options.format.split(' '));
6052	      const maxUnit = _classPrivateMethodGet(this, _getMaxUnit, _getMaxUnit2).call(this, options.format);
6053	      return orderedUnits.filter(unit => formatUnits.has(unit)).map(unit => _classPrivateMethodGet(this, _formatUnit, _formatUnit2).call(this, unit, unit !== maxUnit, options.style)).filter(unit => unit !== '').join(separator);
6054	    }
6055	    /**
6056	     * @example new DurationFormat(5070000).formatClosest() // 1 hour
6057	     * @example new DurationFormat(5070000).formatClosest({ format: 'i s' }) // 84 minutes
6058	     */
6059	  }, {
6060	    key: "formatClosest",
6061	    value: function formatClosest(formatOptions = defaultOptions) {
6062	      const options = {
6063	        ...defaultOptions,
6064	        ...formatOptions
6065	      };
6066	      const maxUnit = _classPrivateMethodGet(this, _getMaxUnit, _getMaxUnit2).call(this, options.format);
6067	      return _classPrivateMethodGet(this, _formatUnit, _formatUnit2).call(this, maxUnit, false, options.style);
6068	    }
6069	  }, {
6070	    key: "seconds",
6071	    get: function () {
6072	      return Math.floor(this.milliseconds / DurationFormat.getUnitDurations().s);
6073	    }
6074	  }, {
6075	    key: "minutes",
6076	    get: function () {
6077	      return Math.floor(this.milliseconds / DurationFormat.getUnitDurations().i);
6078	    }
6079	  }, {
6080	    key: "hours",
6081	    get: function () {
6082	      return Math.floor(this.milliseconds / DurationFormat.getUnitDurations().H);
6083	    }
6084	  }, {
6085	    key: "days",
6086	    get: function () {
6087	      return Math.floor(this.milliseconds / DurationFormat.getUnitDurations().d);
6088	    }
6089	    /**
6090	     * Considering month is 31 days
6091	     */
6092	  }, {
6093	    key: "months",
6094	    get: function () {
6095	      return Math.floor(this.milliseconds / DurationFormat.getUnitDurations().m);
6096	    }
6097	    /**
6098	     * Considering year is 365 days
6099	     */
6100	  }, {
6101	    key: "years",
6102	    get: function () {
6103	      return Math.floor(this.milliseconds / DurationFormat.getUnitDurations().Y);
6104	    }
6105	  }], [{
6106	    key: "createFromSeconds",
6107	    value: function createFromSeconds(seconds) {
6108	      return new DurationFormat(seconds * DurationFormat.getUnitDurations().s);
6109	    }
6110	  }, {
6111	    key: "createFromMinutes",
6112	    value: function createFromMinutes(minutes) {
6113	      return new DurationFormat(minutes * DurationFormat.getUnitDurations().i);
6114	    }
6115	  }, {
6116	    key: "getUnitDurations",
6117	    value: function getUnitDurations() {
6118	      return {
6119	        s: 1000,
6120	        i: 60000,
6121	        H: 3600000,
6122	        d: 86400000,
6123	        m: 2678400000,
6124	        Y: 31536000000
6125	      };
6126	    }
6127	  }]);
6128	  return DurationFormat;
6129	}();
6130	function _getSeparator2(style) {
6131	  if (style === 'short') {
6132	    return main_core.Loc.getMessage('FD_SEPARATOR_SHORT').replaceAll('&#32;', ' ');
6133	  }
6134	  return main_core.Loc.getMessage('FD_SEPARATOR').replaceAll('&#32;', ' ');
6135	}
6136	function _getMaxUnit2(format) {
6137	  const formatUnits = new Set(format.split(' '));
6138	  const units = Object.entries(DurationFormat.getUnitDurations()).filter(([unit]) => formatUnits.has(unit));
6139	  return units.reduce((closestDuration, unitDuration) => {
6140	    const whole = Math.floor(this.milliseconds / unitDuration[1]) >= 1;
6141	    const max = unitDuration[1] > closestDuration[1];
6142	    return whole && max ? unitDuration : closestDuration;
6143	  }, units[0])[0];
6144	}
6145	function _formatUnit2(unitStr, mod, style) {
6146	  const value = mod ? _classPrivateMethodGet(this, _getUnitPropertyModByFormat, _getUnitPropertyModByFormat2).call(this, unitStr) : _classPrivateMethodGet(this, _getUnitPropertyByFormat, _getUnitPropertyByFormat2).call(this, unitStr);
6147	  if (mod && value === 0) {
6148	    return '';
6149	  }
6150	  const now = Date.now() / 1000;
6151	  const unitDuration = value * _classPrivateMethodGet(this, _getUnitDuration, _getUnitDuration2).call(this, unitStr) / 1000;
6152	  const format = style === 'short' ? `${unitStr}short` : `${unitStr}diff`;
6153	  return DateTimeFormat.format(format, now - unitDuration, now);
6154	}
6155	function _getUnitPropertyModByFormat2(unitStr) {
6156	  const propsMod = {
6157	    s: this.seconds % 60,
6158	    i: this.minutes % 60,
6159	    H: this.hours % 24,
6160	    d: this.days % 31,
6161	    m: this.months % 12,
6162	    Y: this.years
6163	  };
6164	  return propsMod[unitStr];
6165	}
6166	function _getUnitPropertyByFormat2(unitStr) {
6167	  const props = {
6168	    s: this.seconds,
6169	    i: this.minutes,
6170	    H: this.hours,
6171	    d: this.days,
6172	    m: this.months,
6173	    Y: this.years
6174	  };
6175	  return props[unitStr];
6176	}
6177	function _getUnitDuration2(unitStr) {
6178	  return DurationFormat.getUnitDurations()[unitStr];
6179	}
6180
6181	const cache = new main_core.Cache.MemoryCache();
6182	/**
6183	 * @memberOf BX.Main.Timezone
6184	 *
6185	 * WARNING! Don't use this class or any classes from Timezone namespace on sites without Bitrix Framework.
6186	 * It is not designed to handle this case and will definitely break.
6187	 */
6188	const Offset = {
6189	  get SERVER_TO_UTC() {
6190	    return cache.remember('SERVER_TO_UTC', () => {
6191	      return main_core.Text.toInteger(main_core.Loc.getMessage('SERVER_TZ_OFFSET'));
6192	    });
6193	  },
6194	  get USER_TO_SERVER() {
6195	    return cache.remember('USER_TO_SERVER', () => {
6196	      return main_core.Text.toInteger(main_core.Loc.getMessage('USER_TZ_OFFSET'));
6197	    });
6198	  },
6199	  // Date returns timezone offset in minutes by default, change it to seconds
6200	  // Also offset is negative in UTC+ timezones and positive in UTC- timezones.
6201	  // By convention Bitrix uses the opposite approach, so change offset sign.
6202	  get BROWSER_TO_UTC() {
6203	    return cache.remember('BROWSER_TO_UTC', () => {
6204	      const offset = main_core.Text.toInteger(new Date().getTimezoneOffset() * 60);
6205	      return -offset;
6206	    });
6207	  }
6208	};
6209	Object.freeze(Offset);
6210
6211	function normalizeTimeValue(timeValue) {
6212	  if (main_core.Type.isDate(timeValue)) {
6213	    return getTimestampFromDate(timeValue);
6214	  }
6215	  return main_core.Text.toInteger(timeValue);
6216	}
6217	function createDateFromTimestamp(timestampInSeconds) {
6218	  return new Date(timestampInSeconds * 1000);
6219	}
6220	function getTimestampFromDate(date) {
6221	  return Math.floor(date.getTime() / 1000);
6222	}
6223
6224	let offset = Offset;
6225	let now = null;
6226	function getOffset() {
6227	  return offset;
6228	}
6229	function getNowTimestamp() {
6230	  var _now;
6231	  return (_now = now) !== null && _now !== void 0 ? _now : getTimestampFromDate(new Date());
6232	}
6233
6234	/**
6235	 * @memberOf BX.Main.Timezone
6236	 *
6237	 * WARNING! Don't use this class or any classes from Timezone namespace on sites without Bitrix Framework.
6238	 * It is not designed to handle this case and will definitely break.
6239	 */
6240	let BrowserTime = /*#__PURE__*/function () {
6241	  function BrowserTime() {
6242	    babelHelpers.classCallCheck(this, BrowserTime);
6243	  }
6244	  babelHelpers.createClass(BrowserTime, null, [{
6245	    key: "getDate",
6246	    /**
6247	     * Returns a Date object with time and date that represent a specific moment in Browser (device) timezone.
6248	     *
6249	     * @param utcTimestamp - normal utc timestamp in seconds. 'now' by default
6250	     * @returns {Date}
6251	     */
6252	    value: function getDate(utcTimestamp = null) {
6253	      const timestamp = main_core.Type.isNumber(utcTimestamp) ? utcTimestamp : this.getTimestamp();
6254	      return createDateFromTimestamp(timestamp);
6255	    }
6256	    /**
6257	     * Transforms a moment in Browser (device) timezone to a moment in User timezone.
6258	     *
6259	     * ATTENTION! Date.getTime() and Date.getTimezoneOffset() will return inaccurate data. Since a native Date object
6260	     * doesn't support timezone other that device timezone, we have to manually change timestamp to shift time value in
6261	     * a Date object.
6262	     *
6263	     * @param browserTime - a moment in Browser (device) timezone. Either a Date object (recommended way). Or timestamp
6264	     * in seconds in Browser timezone (see this.getTimestamp for details).
6265	     * @returns {Date}
6266	     */
6267	  }, {
6268	    key: "toUserDate",
6269	    value: function toUserDate(browserTime) {
6270	      return createDateFromTimestamp(this.toUser(browserTime));
6271	    }
6272	    /**
6273	     * Transforms a moment in Browser (device) timezone to a moment in Server timezone.
6274	     *
6275	     * ATTENTION! Date.getTime() and Date.getTimezoneOffset() will return inaccurate data. Since a native Date object
6276	     * doesn't support timezone other that device timezone, we have to manually change timestamp to shift time value in
6277	     * a Date object.
6278	     *
6279	     * @param browserTime - a moment in Browser (device) timezone. Either a Date object (recommended way). Or timestamp
6280	     * in seconds in Browser timezone (see this.getTimestamp for details).
6281	     * @returns {Date}
6282	     */
6283	  }, {
6284	    key: "toServerDate",
6285	    value: function toServerDate(browserTime) {
6286	      return createDateFromTimestamp(this.toServer(browserTime));
6287	    }
6288	    /**
6289	     * Transforms a moment in Browser (device) timezone to a timestamp in User timezone.
6290	     * It's recommended to use this.toUserDate for more clear code.
6291	     *
6292	     * @param browserTime - a moment in Browser timezone. Either a Date object (recommended way). Or timestamp in seconds
6293	     * in Browser timezone (see this.getTimestamp for details).
6294	     * @returns {number} - timestamp that when passed to 'new Date' will create an object with absolute time matching
6295	     * the time in User timezone
6296	     */
6297	  }, {
6298	    key: "toUser",
6299	    value: function toUser(browserTime) {
6300	      return this.toServer(browserTime) + getOffset().USER_TO_SERVER;
6301	    }
6302	    /**
6303	     * Transforms a moment in Browser (device) timezone to a timestamp in Server timezone.
6304	     * It's recommended to use this.toServerDate for more clear code.
6305	     *
6306	     * @param browserTime - a moment in Browser timezone. Either a Date object (recommended way). Or timestamp in seconds
6307	     * in Browser timezone (see this.getTimestamp for details).
6308	     * @returns {number} - timestamp that when passed to 'new Date' will create an object with absolute time matching
6309	     * the time in Server timezone
6310	     */
6311	  }, {
6312	    key: "toServer",
6313	    value: function toServer(browserTime) {
6314	      return normalizeTimeValue(browserTime) - getOffset().BROWSER_TO_UTC + getOffset().SERVER_TO_UTC;
6315	    }
6316	    /**
6317	     * Returns 'now' timestamp in Browser (device) timezone - when it's passed to a 'new Date', it will create an object
6318	     * with absolute time matching the time as if it was in Browser (device) timezone.
6319	     *
6320	     * @returns {number}
6321	     */
6322	  }, {
6323	    key: "getTimestamp",
6324	    value: function getTimestamp() {
6325	      // since 'Date' class in JS is hardcoded to use device timezone, 'browser timestamp' is just normal UTC timestamp :)
6326
6327	      return getNowTimestamp();
6328	    }
6329	  }]);
6330	  return BrowserTime;
6331	}();
6332
6333	/**
6334	 * @memberOf BX.Main.Timezone
6335	 *
6336	 * WARNING! Don't use this class or any classes from Timezone namespace on sites without Bitrix Framework.
6337	 * It is not designed to handle this case and will definitely break.
6338	 */
6339	let ServerTime = /*#__PURE__*/function () {
6340	  function ServerTime() {
6341	    babelHelpers.classCallCheck(this, ServerTime);
6342	  }
6343	  babelHelpers.createClass(ServerTime, null, [{
6344	    key: "getDate",
6345	    /**
6346	     * Returns a Date object with time and date that represent a specific moment in Server timezone.
6347	     *
6348	     * ATTENTION! Date.getTime() and Date.getTimezoneOffset() will return inaccurate data. Since a native Date object
6349	     * doesn't support timezone other that device timezone, we have to manually change timestamp to shift time value in
6350	     * a Date object.
6351	     *
6352	     * @param utcTimestamp - normal utc timestamp in seconds. 'now' by default
6353	     * @returns {Date}
6354	     */
6355	    value: function getDate(utcTimestamp = null) {
6356	      if (main_core.Type.isNumber(utcTimestamp)) {
6357	        const browserToServerOffset = getOffset().SERVER_TO_UTC - getOffset().BROWSER_TO_UTC;
6358	        return createDateFromTimestamp(utcTimestamp + browserToServerOffset);
6359	      }
6360	      return BrowserTime.toServerDate(BrowserTime.getDate());
6361	    }
6362	    /**
6363	     * Transforms a moment in Server timezone to a moment in User timezone.
6364	     *
6365	     * ATTENTION! Date.getTime() and Date.getTimezoneOffset() will return inaccurate data. Since a native Date object
6366	     * doesn't support timezone other that device timezone, we have to manually change timestamp to shift time value in
6367	     * a Date object.
6368	     *
6369	     * @param serverTime - a moment in Server timezone. Either a Date object (recommended way). Or timestamp in seconds 
6369in
6370	     * Server timezone (see this.getTimestamp for details).
6371	     * @returns {Date}
6372	     */
6373	  }, {
6374	    key: "toUserDate",
6375	    value: function toUserDate(serverTime) {
6376	      return createDateFromTimestamp(this.toUser(serverTime));
6377	    }
6378	    /**
6379	     * Transforms a moment in Server timezone to a moment in Browser (device) timezone.
6380	     *
6381	     * @param serverTime - a moment in Server timezone. Either a Date object (recommended way). Or timestamp in seconds in
6382	     * Server timezone (see this.getTimestamp for details).
6383	     * @returns {Date}
6384	     */
6385	  }, {
6386	    key: "toBrowserDate",
6387	    value: function toBrowserDate(serverTime) {
6388	      return createDateFromTimestamp(this.toBrowser(serverTime));
6389	    }
6390	    /**
6391	     * Transforms a moment in Server timezone to a timestamp in User timezone.
6392	     * It's recommended to use this.toServerDate for more clear code.
6393	     *
6394	     * @param serverTime - a moment in Server timezone. Either a Date object (recommended way). Or timestamp in seconds in
6395	     * Server timezone (see this.getTimestamp for details).
6396	     * @returns {number} - timestamp that when passed to 'new Date' will create an object with absolute time matching
6397	     * the time in User timezone
6398	     */
6399	  }, {
6400	    key: "toUser",
6401	    value: function toUser(serverTime) {
6402	      return normalizeTimeValue(serverTime) + getOffset().USER_TO_SERVER;
6403	    }
6404	    /**
6405	     * Transforms a moment in Server timezone to a timestamp in Browser (device) timezone.
6406	     * It's recommended to use this.toBrowserDate for more clear code.
6407	     *
6408	     * @param serverTime - a moment in Server timezone. Either a Date object (recommended way). Or timestamp in seconds in
6409	     * Server timezone (see this.getTimestamp for details).
6410	     * @returns {number} - timestamp that when passed to 'new Date' will create an object with absolute time matching
6411	     * the time in Browser (device) timezone
6412	     */
6413	  }, {
6414	    key: "toBrowser",
6415	    value: function toBrowser(serverTime) {
6416	      return normalizeTimeValue(serverTime) + getOffset().BROWSER_TO_UTC - getOffset().SERVER_TO_UTC;
6417	    }
6418	    /**
6419	     * Returns 'now' timestamp in Server timezone - when it's passed to a 'new Date', it will create an object with
6420	     * absolute time matching the time as if it was in Server timezone.
6421	     *
6422	     * @returns {number}
6423	     */
6424	  }, {
6425	    key: "getTimestamp",
6426	    value: function getTimestamp() {
6427	      return BrowserTime.toServer(BrowserTime.getTimestamp());
6428	    }
6429	  }]);
6430	  return ServerTime;
6431	}();
6432
6433	function _classStaticPrivateFieldSpecGet(receiver, classConstructor, descriptor) { _classCheckPrivateStaticAccess(receiver, classConstructor); _classCheckPrivateStaticFieldDescriptor(descriptor, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
6434	function _classCheckPrivateStaticFieldDescriptor(descriptor, action) { if (descriptor === undefined) { throw new TypeError("attempted to " + action + " private static field before its declaration"); } }
6435	function _classCheckPrivateStaticAccess(receiver, classConstructor) { if (receiver !== classConstructor) { throw new TypeError("Private static access of wrong provenance"); } }
6436	function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
6437
6438	/**
6439	 * @memberOf BX.Main.Timezone
6440	 *
6441	 * WARNING! Don't use this class or any classes from Timezone namespace on sites without Bitrix Framework.
6442	 * It is not designed to handle this case and will definitely break.
6443	 *
6444	 * ATTENTION! In Bitrix user timezone !== browser timezone. Users can change their timezone from their profile settings
6445	 * and the timezone will be different from browser timezone.
6446	 */
6447	let UserTime = /*#__PURE__*/function () {
6448	  function UserTime() {
6449	    babelHelpers.classCallCheck(this, UserTime);
6450	  }
6451	  babelHelpers.createClass(UserTime, null, [{
6452	    key: "getDate",
6453	    /**
6454	     * Returns a Date object with time and date that represent a specific moment in User timezone.
6455	     *
6456	     * ATTENTION! Date.getTime() and Date.getTimezoneOffset() will return inaccurate data. Since a native Date object
6457	     * doesn't support timezone other that device timezone, we have to manually change timestamp to shift time value in
6458	     * a Date object.
6459	     *
6460	     * @param utcTimestamp - normal utc timestamp in seconds. 'now' by default
6461	     * @returns {Date}
6462	     */
6463	    value: function getDate(utcTimestamp = null) {
6464	      if (main_core.Type.isNumber(utcTimestamp)) {
6465	        return createDateFromTimestamp(utcTimestamp + _classStaticPrivateFieldSpecGet(this, UserTime, _userToBrowserOffset));
6466	      }
6467	      return createDateFromTimestamp(this.getTimestamp());
6468	    }
6469	  }, {
6470	    key: "toBrowserDate",
6471	    /**
6472	     * Transforms a moment in User timezone to a moment in Browser (device) timezone.
6473	     *
6474	     * @param userTime - a moment in User timezone. Either a Date object (recommended way). Or timestamp in seconds 
6474in
6475	     * User timezone (see this.getTimestamp for details).
6476	     * @returns {Date}
6477	     */
6478	    value: function toBrowserDate(userTime) {
6479	      return createDateFromTimestamp(this.toBrowser(userTime));
6480	    }
6481	    /**
6482	     * Transforms a moment in User timezone to a moment in Server timezone.
6483	     *
6484	     * ATTENTION! Date.getTime() and Date.getTimezoneOffset() will return inaccurate data. Since a native Date object
6485	     * doesn't support timezone other that device timezone, we have to manually change timestamp to shift time value in
6486	     * a Date object.
6487	     *
6488	     * @param userTime - a moment in User timezone. Either a Date object (recommended way). Or timestamp in seconds in
6489	     * User timezone (see this.getTimestamp for details).
6490	     * @returns {Date}
6491	     */
6492	  }, {
6493	    key: "toServerDate",
6494	    value: function toServerDate(userTime) {
6495	      return createDateFromTimestamp(this.toServer(userTime));
6496	    }
6497	  }, {
6498	    key: "toUTCTimestamp",
6499	    value: function toUTCTimestamp(userTime) {
6500	      return normalizeTimeValue(userTime) - _classStaticPrivateFieldSpecGet(this, UserTime, _userToBrowserOffset);
6501	    }
6502	    /**
6503	     * Transforms a moment in User timezone to a timestamp in Browser timezone.
6504	     * It's recommended to use this.toBrowserDate for more clear code.
6505	     *
6506	     * @param userTime - a moment in User timezone. Either a Date object (recommended way). Or timestamp in seconds in
6507	     * User timezone (see this.getTimestamp for details).
6508	     * @returns {number} - timestamp that when passed to 'new Date' will create an object with absolute time matching
6509	     * the time in Browser (device) timezone
6510	     */
6511	  }, {
6512	    key: "toBrowser",
6513	    value: function toBrowser(userTime) {
6514	      return normalizeTimeValue(userTime) + getOffset().BROWSER_TO_UTC - getOffset().SERVER_TO_UTC - getOffset().USER_TO_SERVER;
6515	    }
6516	    /**
6517	     * Transforms a moment in User timezone to a timestamp in Server timezone.
6518	     * It's recommended to use this.toServerDate for more clear code.
6519	     *
6520	     * @param userTime - a moment in User timezone. Either a Date object (recommended way). Or timestamp in seconds in
6521	     * User timezone (see this.getTimestamp for details).
6522	     * @returns {number} - timestamp that when passed to 'new Date' will create an object with absolute time matching
6523	     * the time in Server timezone
6524	     */
6525	  }, {
6526	    key: "toServer",
6527	    value: function toServer(userTime) {
6528	      return normalizeTimeValue(userTime) - getOffset().USER_TO_SERVER;
6529	    }
6530	    /**
6531	     * Returns 'now' timestamp in User timezone - when it's passed to a 'new Date', it will create an object with absolute
6532	     * time matching the time as if it was in User timezone.
6533	     *
6534	     * @returns {number}
6535	     */
6536	  }, {
6537	    key: "getTimestamp",
6538	    value: function getTimestamp() {
6539	      return BrowserTime.toUser(BrowserTime.getTimestamp());
6540	    }
6541	  }]);
6542	  return UserTime;
6543	}();
6544	function _get_userToBrowserOffset() {
6545	  const userToUTCOffset = getOffset().SERVER_TO_UTC + getOffset().USER_TO_SERVER;
6546	  return userToUTCOffset - getOffset().BROWSER_TO_UTC;
6547	}
6548	var _userToBrowserOffset = {
6549	  get: _get_userToBrowserOffset,
6550	  set: void 0
6551	};
6552
6553	const Timezone = Object.freeze({
6554	  BrowserTime,
6555	  Offset,
6556	  ServerTime,
6557	  UserTime
6558	});
6559
6560	exports.Timezone = Timezone;
6561	exports.Date = DateTimeFormat;
6562	exports.DateTimeFormat = DateTimeFormat;
6563	exports.DurationFormat = DurationFormat;
6564
6565}((this.BX.Main = this.BX.Main || {}),BX));
6566//# sourceMappingURL=main.date.js.map
6567
6568/* End */
6569;
6570; /* Start:"a:4:{s:4:"full";s:49:"/bitrix/js/main/core/core_date.js?174159735536080";s:6:"source";s:33:"/bitrix/js/main/core/core_date.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
6571;(function(){
6572
6573if (BX.date)
6574	return;
6575
6576BX.date = BX.Main.Date;
6577
6578/************************************** calendar class **********************************/
6579
6580var obCalendarSingleton = null;
6581
6582/*
6583params: {
6584	node: bind element || document.body
6585
6586	value - start value in site format (using 'field' param if 'value' does not exist)
6587	callback - date check handler. can return false to prevent calendar closing.
6588	callback_after - another handler, called after date picking
6589
6590	field - field to read/write data
6591
6592	bTime = true - whether to enable time control
6593	bHideTime = false - whether to hide time control by default
6594
6595	currentTime - current UTC time()
6596
6597}
6598*/
6599
6600
6601BX.calendar = function(params)
6602{
6603	return BX.calendar.get().Show(params);
6604};
6605
6606BX.calendar.get = function()
6607{
6608	if (!obCalendarSingleton)
6609		obCalendarSingleton = new BX.JCCalendar();
6610
6611	return obCalendarSingleton;
6612};
6613
6614// simple func for compatibility with the oldies
6615BX.calendar.InsertDaysBack = function(input, days)
6616{
6617	if (days != '')
6618	{
6619		var d = new Date();
6620		if(days > 0)
6621		{
6622			d.setTime(d.valueOf() - days*86400000);
6623		}
6624
6625		input.value = BX.date.format(BX.date.convertBitrixFormat(BX.message('FORMAT_DATE')), d, null);
6626	}
6627	else
6628	{
6629		input.value = '';
6630	}
6631};
6632
6633BX.calendar.ValueToString = function(value, bTime, bUTC)
6634{
6635	return BX.date.format(
6636		BX.date.convertBitrixFormat(BX.message(bTime ? 'FORMAT_DATETIME' : 'FORMAT_DATE')),
6637		value,
6638		null,
6639		!!bUTC
6640	);
6641};
6642
6643BX.calendar.ValueToStringFormat = function(value, bitrixFormat, bUTC)
6644{
6645	return BX.date.format(
6646		BX.date.convertBitrixFormat(bitrixFormat),
6647		value,
6648		null,
6649		!!bUTC
6650	);
6651};
6652
6653
6654BX.CalendarPeriod =
6655{
6656	Init: function(inputFrom, inputTo, selPeriod)
6657	{
6658		if((inputFrom.value != "" || inputTo.value != "") && selPeriod.value == "")
6659			selPeriod.value = "interval";
6660
6661		selPeriod.onchange();
6662	},
6663
6664	ChangeDirectOpts: function(peroidValue, selPParent) // "week" || "others"
6665	{
6666		var selDirect = BX.findChild(selPParent, {'className':'adm-select adm-calendar-direction'}, true);
6667
6668		if(peroidValue == "week")
6669		{
6670			selDirect.options[0].text = BX.message('JSADM_CALEND_PREV_WEEK');
6671			selDirect.options[1].text = BX.message('JSADM_CALEND_CURR_WEEK');
6672			selDirect.options[2].text = BX.message('JSADM_CALEND_NEXT_WEEK');
6673		}
6674		else
6675		{
6676			selDirect.options[0].text = BX.message('JSADM_CALEND_PREV');
6677			selDirect.options[1].text = BX.message('JSADM_CALEND_CURR');
6678			selDirect.options[2].text = BX.message('JSADM_CALEND_NEXT');
6679		}
6680	},
6681
6682	SaveAndClearInput: function(oInput)
6683	{
6684		if(!window.SavedPeriodValues)
6685			window.SavedPeriodValues = {};
6686
6687		window.SavedPeriodValues[oInput.id] = oInput.value;
6688		oInput.value="";
6689	},
6690
6691	RestoreInput: function(oInput)
6692	{
6693		if(!window.SavedPeriodValues || !window.SavedPeriodValues[oInput.id])
6694			return;
6695
6696		oInput.value = window.SavedPeriodValues[oInput.id];
6697		delete(window.SavedPeriodValues[oInput.id]);
6698	},
6699
6700	OnChangeP: function(sel)
6701	{
6702		var selPParent = sel.parentNode.parentNode;
6703		var bShowFrom, bShowTo, bShowDirect, bShowSeparate;
6704		bShowFrom = bShowTo = bShowDirect = bShowSeparate = false;
6705
6706		var inputFromWrap = BX.findChild(selPParent, {'className':'adm-input-wrap adm-calendar-inp adm-calendar-first'});
6707		var inputToWrap = BX.findChild(selPParent, {'className':'adm-input-wrap adm-calendar-second'});
6708		var selDirectWrap = BX.findChild(selPParent, {'className':'adm-select-wrap adm-calendar-direction'});
6709		var separator = BX.findChild(selPParent, {'className':'adm-calendar-separate'});
6710		var inputFrom = BX.findChild(selPParent, {'className':'adm-input adm-calendar-from'},true);
6711		var inputTo = BX.findChild(selPParent, {'className':'adm-input adm-calendar-to'},true);
6712
6713		// define who must be shown
6714		switch (sel.value)
6715		{
6716			case "day":
6717			case "week":
6718			case "month":
6719			case "quarter":
6720			case "year":
6721				bShowDirect=true;
6722				BX.CalendarPeriod.OnChangeD(selDirectWrap.children[0]);
6723				break;
6724
6725			case "before":
6726				bShowTo = true;
6727				break;
6728
6729			case "after":
6730				bShowFrom = true;
6731				break;
6732
6733			case "exact":
6734				bShowFrom= true;
6735				break;
6736
6737			case "interval":
6738				bShowFrom = bShowTo = bShowSeparate = true;
6739				BX.CalendarPeriod.RestoreInput(inputFrom);
6740				BX.CalendarPeriod.RestoreInput(inputTo);
6741
6742				break;
6743
6744			case "":
6745				BX.CalendarPeriod.SaveAndClearInput(inputFrom);
6746				BX.CalendarPeriod.SaveAndClearInput(inputTo);
6747				break;
6748
6749			default:
6750				break;
6751
6752		}
6753
6754		BX.CalendarPeriod.ChangeDirectOpts(sel.value, selPParent);
6755
6756		inputFromWrap.style.display = (bShowFrom? 'inline-block':'none');
6757		inputToWrap.style.display = (bShowTo? 'inline-block':'none');
6758		selDirectWrap.style.display = (bShowDirect? 'inline-block':'none');
6759		separator.style.display = (bShowSeparate? 'inline-block':'none');
6760	},
6761
6762
6763	OnChangeD: function(sel)
6764	{
6765		var selPParent = sel.parentNode.parentNode;
6766		var inputFrom = BX.findChild(selPParent, {'className':'adm-input adm-calendar-from'},true);
6767		var inputTo = BX.findChild(selPParent, {'className':'adm-input adm-calendar-to'},true);
6768		var selPeriod = BX.findChild(selPParent, {'className':'adm-select adm-calendar-period'},true);
6769
6770		var offset=0;
6771
6772		switch (sel.value)
6773		{
6774			case "previous":
6775				offset = -1;
6776				break;
6777
6778			case "next":
6779				offset = 1;
6780				break;
6781
6782			case "current":
6783			default:
6784				break;
6785
6786		}
6787
6788		var from = false;
6789		var to = false;
6790
6791		var today = new Date();
6792		var year = today.getFullYear();
6793		var month = today.getMonth();
6794		var day = today.getDate();
6795		var dayW = today.getDay();
6796
6797		if (dayW == 0)
6798				dayW = 7;
6799
6800		switch (selPeriod.value)
6801		{
6802			case "day":
6803				from = new Date(year, month, day+offset, 0, 0, 0);
6804				to = new Date(year, month, day+offset, 23, 59, 59);
6805				break;
6806
6807			case "week":
6808				from = new Date(year, month, day-dayW+1+offset*7, 0, 0, 0);
6809				to = new Date(year, month, day+(7-dayW)+offset*7, 23, 59, 59);
6810				break;
6811
6812			case "month":
6813				from = new Date(year, month+offset, 1, 0, 0, 0);
6814				to = new Date(year, month+1+offset, 0, 23, 59, 59);
6815				break;
6816
6817			case "quarter":
6818				var quarterNum = Math.floor((month/3))+offset;
6819				from = new Date(year, 3*(quarterNum), 1, 0, 0, 0);
6820				to = new Date(year, 3*(quarterNum+1), 0, 23, 59, 59);
6821				break;
6822
6823			case "year":
6824				from = new Date(year+offset, 0, 1, 0, 0, 0);
6825				to = new Date(year+1+offset, 0, 0, 23, 59, 59);
6826				break;
6827
6828			default:
6829				break;
6830		}
6831
6832		var format = window[inputFrom.name+"_bTime"] ? BX.message('FORMAT_DATETIME') : BX.message('FORMAT_DATE');
6833
6834		if(from)
6835		{
6836			inputFrom.value = BX.formatDate(from, format);
6837			BX.addClass(inputFrom,"adm-calendar-inp-setted");
6838		}
6839
6840		if(to)
6841		{
6842			inputTo.value = BX.formatDate(to, format);
6843			BX.addClass(inputTo,"adm-calendar-inp-setted");
6844		}
6845	}
6846};
6847
6848
6849BX.JCCalendar = function()
6850{
6851	this.params = {};
6852
6853	this.bAmPm = BX.isAmPmMode();
6854
6855	this.popup = null;
6856	this.popup_month = null;
6857	this.popup_year = null;
6858	this.month_popup_classname = '';
6859	this.year_popup_classname = '';
6860	this.value = null;
6861	this._layers = {};
6862	this._current_layer = null;
6863
6864	this.DIV = null;
6865	this.PARTS = {};
6866
6867	this.weekStart = 0;
6868	this.numRows = 6;
6869
6870	this._create = function(params)
6871	{
6872		this.popup = new BX.PopupWindow('calendar_popup_' + Math.random(), params.node, {
6873			closeByEsc: true,
6874			autoHide: false,
6875			content: this._get_content(),
6876			bindOptions: {forceBindPosition: true}
6877		});
6878
6879		BX.bind(this.popup.popupContainer, 'click', function(event) {
6880			event.stopPropagation();
6881		});
6882	};
6883
6884	this._auto_hide_disable = function()
6885	{
6886		BX.unbind(document, 'click', BX.proxy(this._auto_hide, this));
6887	};
6888
6889	this._auto_hide_enable = function()
6890	{
6891		BX.bind(document, 'click', BX.proxy(this._auto_hide, this));
6892	};
6893
6894	this._auto_hide = function(e)
6895	{
6896		this._auto_hide_disable();
6897		this.popup.close();
6898	};
6899
6900	this._get_content = function()
6901	{
6902		var _layer_onclick = BX.delegate(function(e) {
6903			e = e||window.event;
6904			this.SetDate(
6905				new Date(parseInt(BX.proxy_context.getAttribute('data-date'))),
6906				(e.type === 'dblclick' || (this.params.bCompatibility && !this.params.bTimeVisibility))
6907			)
6908		}, this);
6909
6910		this.DIV = BX.create('DIV', {
6911			props: {className: 'bx-calendar'},
6912			children: [
6913				BX.create('DIV', {
6914					props: {
6915						className: 'bx-calendar-header'
6916					},
6917					children: [
6918						BX.create('A', {
6919							attrs: {href: 'javascript:void(0)'},
6920							props: {className: 'bx-calendar-left-arrow'},
6921							events: {click: BX.proxy(this._prev, this)}
6922						}),
6923
6924						BX.create('SPAN', {
6925							props: {className: 'bx-calendar-header-content'},
6926							children: [
6927								(this.PARTS.MONTH = BX.create('A', {
6928									attrs: {href: 'javascript:void(0)'},
6929									props: {className: 'bx-calendar-top-month'},
6930									events: {click: BX.proxy(this._menu_month, this)}
6931								})),
6932
6933								(this.PARTS.YEAR = BX.create('A', {
6934									attrs: {href: 'javascript:void(0)'},
6935									props: {className: 'bx-calendar-top-year'},
6936									events: {click: BX.proxy(this._menu_year, this)}
6937								}))
6938							]
6939						}),
6940
6941						BX.create('A', {
6942							attrs: {href: 'javascript:void(0)'},
6943							props: {className: 'bx-calendar-right-arrow'},
6944							events: {click: BX.proxy(this._next, this)}
6945						})
6946					]
6947				}),
6948
6949				(this.PARTS.WEEK = BX.create('DIV', {
6950					props: {
6951						className: 'bx-calendar-name-day-wrap'
6952					}
6953				})),
6954
6955				(this.PARTS.LAYERS = BX.create('DIV', {
6956					props: {
6957						className: 'bx-calendar-cell-block'
6958					},
6959					events: {
6960						click: BX.delegateEvent({className: 'bx-calendar-cell'}, _layer_onclick),
6961						dblclick: BX.delegateEvent({className: 'bx-calendar-cell'}, _layer_onclick)
6962					}
6963				})),
6964
6965				(this.PARTS.TIME = BX.create('DIV', {
6966					props: {
6967						className: 'bx-calendar-set-time-wrap'
6968					},
6969					events: {
6970						click: BX.delegateEvent(
6971							{attr: 'data-action'},
6972							BX.delegate(this._time_actions, this)
6973						)
6974					},
6975					html: '<a href="javascript:void(0)" data-action="time_show" class="bx-calendar-set-time"><i></i>'+BX.message('CAL_TIME_SET')+'</a><div class="bx-calendar-form-block"><span class="bx-calendar-form-text">'+BX.message('CAL_TIME')+'</span><span class="bx-calendar-form"><input type="text" class="bx-calendar-form-input" maxwidth="2" onkeyup="BX.calendar.get()._check_time()" /><span class="bx-calendar-form-separator"></span><input type="text" class="bx-calendar-form-input" maxwidth="2" onkeyup="BX.calendar.get()._check_time()" />'+(this.bAmPm?'<span class="bx-calendar-AM-PM-block"><span class="bx-calendar-AM-PM-text" data-action="time_ampm"></span><span class="bx-calendar-form-arrow-r"><a href="javascript:void(0)" class="bx-calendar-form-arrow-top" data-action="time_ampm_up"><i></i></a><a href="javascript:void(0)" class="bx-calendar-form-arrow-bottom" data-action="time_ampm_down"><i></i></a></span></span>':'')+'</span><a href="javascript:void(0)" data-action="time_hide" class="bx-calendar-form-close"><i></i></a></div>'
6976				})),
6977
6978				(this.PARTS.BUTTONS = BX.create('DIV', {
6979					props: {className: 'bx-calendar-button-block'},
6980					events: {
6981						click: BX.delegateEvent(
6982							{attr: 'data-action'},
6983							BX.delegate(this._button_actions, this)
6984						)
6985					},
6986					html: '<a href="javascript:void(0)" class="bx-calendar-button bx-calendar-button-select" data-action="submit"><span class="bx-calendar-button-left"></span><span class="bx-calendar-button-text">'+BX.message('CAL_BUTTON')+'</span><span class="bx-calendar-button-right"></span></a><a href="javascript:void(0)" class="bx-calendar-button bx-calendar-button-cancel" data-action="cancel"><span class="bx-calendar-button-left"></span><span class="bx-calendar-button-text">'+BX.message('JS_CORE_WINDOW_CLOSE')+'</span><span class="bx-calendar-button-right"></span></a>'
6987				}))
6988			]
6989		});
6990
6991		this.PARTS.TIME_INPUT_H = BX.findChild(this.PARTS.TIME, {tag: 'INPUT'}, true);
6992		this.PARTS.TIME_INPUT_M = this.PARTS.TIME_INPUT_H.nextSibling.nextSibling;
6993
6994		if (this.bAmPm)
6995			this.PARTS.TIME_AMPM = this.PARTS.TIME_INPUT_M.nextSibling.firstChild;
6996
6997		var spinner = (new BX.JCSpinner({
6998			input: this.PARTS.TIME_INPUT_H,
6999			callback_change: BX.proxy(this._check_time, this),
7000			bSaveValue: false
7001		})).Show();
7002		spinner.className = 'bx-calendar-form-arrow-l';
7003		this.PARTS.TIME_INPUT_H.parentNode.insertBefore(spinner, this.PARTS.TIME_INPUT_H);
7004
7005		spinner = (new BX.JCSpinner({
7006			input: this.PARTS.TIME_INPUT_M,
7007			callback_change: BX.proxy(this._check_time, this),
7008			bSaveValue: true
7009		})).Show();
7010		spinner.className = 'bx-calendar-form-arrow-r';
7011		if (!this.PARTS.TIME_INPUT_M.nextSibling)
7012			this.PARTS.TIME_INPUT_M.parentNode.appendChild(spinner);
7013		else
7014			this.PARTS.TIME_INPUT_M.parentNode.insertBefore(spinner, this.PARTS.TIME_INPUT_M.nextSibling);
7015
7016		for (var i = 0; i < 7; i++)
7017		{
7018			this.PARTS.WEEK.appendChild(BX.create('SPAN', {
7019				props: {
7020					className: 'bx-calendar-name-day'
7021				},
7022				text: BX.message('DOW_' + ((i + this.weekStart) % 7))
7023			}));
7024		}
7025
7026		return this.DIV;
7027	};
7028
7029	this._time_actions = function()
7030	{
7031		switch (BX.proxy_context.getAttribute('data-action'))
7032		{
7033			case 'time_show':
7034				BX.addClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
7035				if (this.params.bCompatibility)
7036				{
7037					BX.removeClass(this.PARTS.BUTTONS, 'bx-calendar-buttons-disabled');
7038				}
7039				this.popup.adjustPosition();
7040			break;
7041			case 'time_hide':
7042				BX.removeClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
7043				if (this.params.bCompatibility)
7044				{
7045					this._saveChoice('hide');
7046					BX.addClass(this.PARTS.BUTTONS, 'bx-calendar-buttons-disabled');
7047				}
7048				this.popup.adjustPosition();
7049			break;
7050			case 'time_ampm':
7051				this.PARTS.TIME_AMPM.innerHTML = this.PARTS.TIME_AMPM.innerHTML == 'AM' ? 'PM' : 'AM';
7052			break;
7053			case 'time_ampm_up':
7054				this._check_time({bSaveValue: false}, null, 12);
7055				return;
7056			break;
7057			case 'time_ampm_down':
7058				this._check_time({bSaveValue: false}, null, -12);
7059				return;
7060			break;
7061		}
7062
7063		this._check_time();
7064	};
7065
7066	this._button_actions = function()
7067	{
7068		switch (BX.proxy_context.getAttribute('data-action'))
7069		{
7070			case 'submit':
7071				if (this.params.bCompatibility)
7072				{
7073					this._saveChoice('show');
7074				}
7075				this.SaveValue();
7076			break;
7077			case 'cancel':
7078				this.Close();
7079			break;
7080		}
7081	};
7082
7083	this._saveChoice = function(state)
7084	{
7085		if (this.params.bCategoryTimeVisibilityOption)
7086		{
7087			BX.userOptions.save(
7088				this.params.bCategoryTimeVisibilityOption,
7089				this.params.bNameTimeVisibilityOption,
7090				'visibility',
7091				(state === 'show' ? 'Y' : 'N')
7092			);
7093		}
7094
7095		this._bTimeVisibility = (state === 'show');
7096		this.params.bTimeVisibility = this._bTimeVisibility;
7097	};
7098
7099	this._check_time = function(params, value, direction)
7100	{
7101		var h = parseInt(this.PARTS.TIME_INPUT_H.value.substring(0,5),10)||0,
7102			m = parseInt(this.PARTS.TIME_INPUT_M.value.substring(0,5),10)||0,
7103			bChanged = false;
7104
7105		if (!!params && !params.bSaveValue)
7106		{
7107			this.value.setUTCHours(this.value.getUTCHours() + direction);
7108		}
7109		else if (!isNaN(h))
7110		{
7111			if (this.bAmPm)
7112			{
7113				if (h != 12 && this.PARTS.TIME_AMPM.innerHTML == 'PM')
7114				{
7115					h += 12;
7116				}
7117			}
7118
7119			bChanged = true;
7120			this.value.setUTCHours(h % 24);
7121		}
7122
7123		if (!isNaN(m))
7124		{
7125			bChanged = true;
7126			this.value.setUTCMinutes(m % 60);
7127		}
7128
7129		if (bChanged)
7130		{
7131			this.SetValue(this.value);
7132		}
7133	};
7134
7135	this._set_layer = function()
7136	{
7137		var layerId = parseInt(this.value.getUTCFullYear() + '' + BX.util.str_pad_left(this.value.getUTCMonth()+'', 2, "0"));
7138
7139		if (!this._layers[layerId])
7140		{
7141			this._layers[layerId] = this._create_layer();
7142			this._layers[layerId].BXLAYERID = layerId;
7143		}
7144
7145		if (this._current_layer)
7146		{
7147			var v = new Date(this.value.valueOf());
7148			v.setUTCHours(0); v.setUTCMinutes(0);
7149
7150			var cur_value = BX.findChild(this._layers[layerId], {
7151					tag: 'A',
7152					className: 'bx-calendar-active'
7153				}, true),
7154				new_value = BX.findChild(this._layers[layerId], {
7155					tag: 'A',
7156					attr: {
7157						'data-date' : v.valueOf() + ''
7158					}
7159				}, true);
7160
7161			if (cur_value)
7162			{
7163				BX.removeClass(cur_value, 'bx-calendar-active');
7164			}
7165
7166			if (new_value)
7167			{
7168				BX.addClass(new_value, 'bx-calendar-active');
7169			}
7170
7171			this._replace_layer(this._current_layer, this._layers[layerId]);
7172		}
7173		else
7174		{
7175			this.PARTS.LAYERS.appendChild(this._layers[layerId]);
7176		}
7177
7178		this._current_layer = this._layers[layerId];
7179	};
7180
7181	this._replace_layer = function(old_layer, new_layer)
7182	{
7183		if (old_layer != new_layer)
7184		{
7185			if (!BX.browser.IsIE() || BX.browser.IsDoctype())
7186			{
7187				var dir = old_layer.BXLAYERID > new_layer.BXLAYERID ? 1 : -1;
7188
7189				var old_top = 0;
7190				var new_top = -dir * old_layer.offsetHeight;
7191
7192				old_layer.style.position = 'relative';
7193				old_layer.style.top = "0px";
7194				old_layer.style.zIndex = 5;
7195
7196				new_layer.style.position = 'absolute';
7197				new_layer.style.top = new_top + 'px';
7198				new_layer.style.zIndex = 6;
7199
7200				this.PARTS.LAYERS.appendChild(new_layer);
7201
7202				var delta = 15;
7203
7204				var f;
7205				(f = function() {
7206					new_top += dir * delta;
7207					old_top += dir * delta;
7208
7209					if (dir * new_top < 0)
7210					{
7211						old_layer.style.top = old_top + 'px';
7212						new_layer.style.top = new_top + 'px';
7213						setTimeout(f, 10);
7214					}
7215					else
7216					{
7217						old_layer.parentNode.removeChild(old_layer);
7218
7219						new_layer.style.top = "0px";
7220						new_layer.style.position = 'static';
7221						new_layer.style.zIndex = 0;
7222					}
7223				})();
7224			}
7225			else
7226			{
7227				this.PARTS.LAYERS.replaceChild(new_layer, old_layer);
7228			}
7229		}
7230	};
7231
7232	this._create_layer = function()
7233	{
7234		var l = BX.create('DIV', {
7235			props: {
7236				className: 'bx-calendar-layer'
7237			}
7238		});
7239
7240		var month_start = new Date(this.value);
7241		month_start.setUTCHours(0);
7242		month_start.setUTCMinutes(0);
7243
7244		month_start.setUTCDate(1);
7245
7246		if (month_start.getUTCDay() != this.weekStart)
7247		{
7248			var d = month_start.getUTCDay() - this.weekStart;
7249			d += d < 0 ? 7 : 0;
7250			month_start.setUTCDate(month_start.getUTCDate()-d);
7251		}
7252
7253		var cur_month = this.value.getUTCMonth(),
7254			cur_day = this.value.getUTCDate(),
7255			s = '';
7256		for (var i = 0; i < this.numRows; i++)
7257		{
7258			s += '<div class="bx-calendar-range'
7259				+(i == this.numRows-1 ? ' bx-calendar-range-noline' : '')
7260				+'">';
7261
7262			for (var j = 0; j < 7; j++)
7263			{
7264				d = month_start.getUTCDate();
7265				var wd = month_start.getUTCDay();
7266				var className = 'bx-calendar-cell';
7267
7268				if (cur_month != month_start.getUTCMonth())
7269					className += ' bx-calendar-date-hidden';
7270				else if (cur_day == d)
7271					className += ' bx-calendar-active';
7272
7273
7274				if (wd == 0 || wd == 6)
7275					className += ' bx-calendar-weekend';
7276
7277				s += '<a href="javascript:void(0)" class="'+className+'" data-date="' + month_start.valueOf() + '">' + d + '</a>';
7278
7279				month_start.setUTCDate(month_start.getUTCDate()+1);
7280			}
7281			s += '</div>';
7282		}
7283
7284		l.innerHTML = s;
7285
7286		return l;
7287	};
7288
7289	this._prev = function()
7290	{
7291		this.SetMonth(this.value.getUTCMonth()-1);
7292	};
7293
7294	this._next = function()
7295	{
7296		this.SetMonth(this.value.getUTCMonth()+1);
7297	};
7298
7299	this._menu_month_content = function()
7300	{
7301		var months = '', cur_month = this.value.getMonth(), i;
7302		for (i = 0; i < 12; i++)
7303		{
7304			months += '<span class="bx-calendar-month'+(i == cur_month ? ' bx-calendar-month-active' : '')+'" data-bx-month="' + i + '">' + BX.message('MONTH_' + (i + 1)) + '</span>';
7305		}
7306
7307		return '<div class="bx-calendar-month-popup"><div class="bx-calendar-month-title" data-bx-month="' + this.value.getUTCMonth() + '">' + BX.message('MONTH_' + (this.value.getUTCMonth() + 1)) + '</div><div class="bx-calendar-month-content">' + months + '</div></div>';
7308	};
7309
7310	this._menu_month = function()
7311	{
7312		if (!this.popup_month)
7313		{
7314			this.popup_month = new BX.PopupWindow(
7315				'calendar_popup_month_' + Math.random(), this.PARTS.MONTH,
7316				{
7317					content: this._menu_month_content(),
7318					closeByEsc: true,
7319					autoHide: true,
7320					offsetTop: -29,
7321					offsetLeft: -1,
7322					className: this.month_popup_classname,
7323					events: {
7324						onPopupShow: BX.delegate(function() {
7325							if (this.popup_year)
7326							{
7327								this.popup_year.close();
7328							}
7329						}, this)
7330					}
7331				}
7332			);
7333
7334			BX.bind(this.popup_month.popupContainer, 'click', BX.proxy(this.month_popup_click, this));
7335			this.popup_month.BXMONTH = this.value.getUTCMonth();
7336		}
7337		else if (this.popup_month.BXMONTH != this.value.getUTCMonth())
7338		{
7339			this.popup_month.setContent(this._menu_month_content());
7340			this.popup_month.BXMONTH = this.value.getUTCMonth();
7341		}
7342
7343		this.popup_month.show();
7344	};
7345
7346	this.month_popup_click = function(e)
7347	{
7348		var target = e.target || e.srcElement;
7349		if (target && target.getAttribute && target.getAttribute('data-bx-month'))
7350		{
7351			this.SetMonth(parseInt(target.getAttribute('data-bx-month')));
7352			this.popup_month.close();
7353		}
7354	};
7355
7356	this._menu_year_content = function()
7357	{
7358		var s = '<div class="bx-calendar-year-popup"><div class="bx-calendar-year-title" data-bx-year="' + this.value.getUTCFullYear() + '">' + this.value.getUTCFullYear() + '</div><div class="bx-calendar-year-content" id="bx-calendar-year-content">';
7359
7360		for (var i=-3; i <= 3; i++)
7361		{
7362			s += '<span class="bx-calendar-year-number' + (i == 0?' bx-calendar-year-active' : '') + '" data-bx-year="' + (this.value.getUTCFullYear() - i) + '">' + (this.value.getUTCFullYear() - i)+'</span>';
7363		}
7364
7365		s += '</div><input data-bx-year-input="Y" type="text" class="bx-calendar-year-input" maxlength="4" /></div>';
7366
7367		return s;
7368	};
7369
7370	this._menu_year = function()
7371	{
7372		if (!this.popup_year)
7373		{
7374			this.popup_year = new BX.PopupWindow(
7375				'calendar_popup_year_' + Math.random(), this.PARTS.YEAR,
7376				{
7377					content: this._menu_year_content(),
7378					closeByEsc: true,
7379					autoHide: true,
7380					offsetTop: -29,
7381					offsetLeft: -1,
7382					className: this.year_popup_classname,
7383					events: {
7384						onPopupShow: BX.delegate(function() {
7385							if (this.popup_month)
7386							{
7387								this.popup_month.close();
7388							}
7389						}, this)
7390					}
7391				}
7392			);
7393
7394			BX.bind(this.popup_year.popupContainer, 'click', BX.proxy(this.year_popup_click, this));
7395			BX.bind(this.popup_year.popupContainer, 'keyup', BX.proxy(this.year_popup_keyup, this));
7396			this.popup_year.BXYEAR = this.value.getUTCFullYear();
7397		}
7398		else if (this.popup_year.BXYEAR != this.value.getUTCFullYear())
7399		{
7400			this.popup_year.setContent(this._menu_year_content());
7401			this.popup_year.BXYEAR = this.value.getUTCFullYear();
7402		}
7403
7404		this.popup_year.show();
7405	};
7406
7407	this.year_popup_click = function(e)
7408	{
7409		var target = e.target || e.srcElement;
7410		if (target && target.getAttribute && target.getAttribute('data-bx-year'))
7411		{
7412			this.SetYear(parseInt(target.getAttribute('data-bx-year')));
7413			this.popup_year.close();
7414		}
7415	};
7416	this.year_popup_keyup = function(e)
7417	{
7418		var target = e.target || e.srcElement;
7419		if (target && target.getAttribute && target.getAttribute('data-bx-year-input') == 'Y')
7420		{
7421			var value = parseInt(target.value);
7422			if(value >= 1900 && value <= 2100)
7423			{
7424				this.SetYear(value);
7425				this.popup_year.close();
7426			}
7427		}
7428	};
7429
7430	this._check_date = function(v)
7431	{
7432		var res = v;
7433
7434		if (BX.type.isString(v))
7435		{
7436			res = BX.parseDate(v, true);
7437		}
7438
7439		if (!BX.type.isDate(res) || isNaN(res.valueOf()))
7440		{
7441			res = BX.date.convertToUTC(new Date());
7442			if (this.params.bHideTime)
7443			{
7444				res.setUTCHours(0);
7445				res.setUTCMinutes(0);
7446			}
7447		}
7448
7449		res.setUTCMilliseconds(0);
7450		res.setUTCSeconds(0);
7451
7452		res.BXCHECKED = true;
7453
7454		return res;
7455	};
7456};
7457
7458BX.JCCalendar.prototype.Show = function(params)
7459{
7460	if (!BX.isReady)
7461	{
7462		BX.ready(BX.delegate(function() {this.Show(params)}, this));
7463		return;
7464	}
7465
7466	params.node = params.node||document.body;
7467
7468	if (BX.type.isNotEmptyString(params.node))
7469	{
7470		var n = BX(params.node);
7471		if (!n)
7472		{
7473			n = document.getElementsByName(params.node);
7474			if (n && n.length > 0)
7475			{
7476				n = n[0]
7477			}
7478		}
7479		params.node = n;
7480	}
7481
7482	if (!params.node)
7483		return;
7484
7485	if (!!params.field)
7486	{
7487		if (BX.type.isString(params.field))
7488		{
7489			n = BX(params.field);
7490			if (!!n)
7491			{
7492				params.field = n;
7493			}
7494			else
7495			{
7496				if (params.form)
7497				{
7498					if (BX.type.isString(params.form))
7499					{
7500						params.form = document.forms[params.form];
7501					}
7502				}
7503
7504				if (BX.type.isDomNode(params.form) && !!params.form[params.field])
7505				{
7506					params.field = params.form[params.field];
7507				}
7508				else
7509				{
7510					n = document.getElementsByName(params.field);
7511					if (n && n.length > 0)
7512					{
7513						n = n[0];
7514						params.field = n;
7515					}
7516				}
7517			}
7518
7519			if (BX.type.isString(params.field))
7520			{
7521				params.field = BX(params.field);
7522			}
7523		}
7524	}
7525
7526	var bShow = !this.popup || !this.popup.isShown() || this.params.node != params.node;
7527
7528	this.params = params;
7529
7530	this.params.bCompatibility = (typeof this.params.bCompatibility == 'undefined' ? false : this.params.bCompatibility);
7531	this.params.bTimeVisibility = (typeof this.params.bTimeVisibility == 'undefined' ? !this.params.bCompatibility : this.params.bTimeVisibility);
7532	if (this.params.bCompatibility)
7533	{
7534		this.params.bCategoryTimeVisibilityOption = (
7535			this.params.bCategoryTimeVisibilityOption ? this.params.bCategoryTimeVisibilityOption : ''
7536		);
7537		this.params.bNameTimeVisibilityOption = (
7538			this.params.bNameTimeVisibilityOption ? this.params.bNameTimeVisibilityOption : 'time_visibility'
7539		);
7540
7541		if (typeof this._bTimeVisibility !== 'undefined')
7542		{
7543			this.params.bTimeVisibility = this._bTimeVisibility;
7544		}
7545	}
7546
7547	this.params.bTime = typeof this.params.bTime == 'undefined' ? true : !!this.params.bTime;
7548	this.params.bHideTime = typeof this.params.bHideTime == 'undefined' ? true : !!this.params.bHideTime;
7549	this.params.bUseSecond = typeof this.params.bUseSecond == 'undefined' ? true : !!this.params.bUseSecond;
7550
7551	this.weekStart = parseInt(this.params.weekStart || this.params.weekStart || BX.message('WEEK_START'));
7552	if (isNaN(this.weekStart))
7553		this.weekStart = 1;
7554
7555	if (!this.popup)
7556	{
7557		this._create(this.params);
7558	}
7559	else
7560	{
7561		this.popup.setBindElement(this.params.node);
7562	}
7563
7564	var bHideTime = !!this.params.bHideTime;
7565	if (this.params.value)
7566	{
7567		this.SetValue(this.params.value);
7568		bHideTime = this.value.getUTCHours() <= 0 && this.value.getUTCMinutes() <= 0;
7569	}
7570	else if (this.params.field)
7571	{
7572		this.SetValue(this.params.field.value);
7573		bHideTime = this.value.getUTCHours() <= 0 && this.value.getUTCMinutes() <= 0;
7574	}
7575	else if (!!this.params.currentTime)
7576	{
7577		this.SetValue(this.params.currentTime);
7578	}
7579	else
7580	{
7581		this.SetValue();
7582	}
7583
7584	if (!!this.params.bTime)
7585	{
7586		this.activateTimeStyle(bHideTime);
7587	}
7588	else
7589	{
7590		this.activateDateStyle(bHideTime);
7591	}
7592
7593	if (bShow)
7594	{
7595		this._auto_hide_disable();
7596		this.popup.show();
7597		setTimeout(BX.proxy(this._auto_hide_enable, this), 0);
7598	}
7599
7600	this.params.bSetFocus = typeof this.params.bSetFocus == 'undefined' ? true : !!this.params.bSetFocus;
7601	if(this.params.bSetFocus)
7602	{
7603		params.node.blur();
7604	}
7605	else
7606	{
7607		BX.bind(params.node, 'keyup', BX.defer(function(){
7608			this.SetValue(params.node.value);
7609			if(!!this.params.bTime)
7610			{
7611				if(this.value.getUTCHours() <= 0 && this.value.getUTCMinutes() <= 0)
7612					BX.removeClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
7613				else
7614					BX.addClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
7615			}
7616		}, this));
7617	}
7618
7619	return this;
7620};
7621
7622BX.JCCalendar.prototype.activateDateStyle = function(bHideTime)
7623{
7624	BX.addClass(this.DIV, 'bx-calendar-time-disabled');
7625
7626	if (!!bHideTime)
7627		BX.removeClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
7628	else
7629		BX.addClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
7630};
7631
7632BX.JCCalendar.prototype.activateTimeStyle = function(bHideTime)
7633{
7634	if (this.params.bCompatibility && !this.params.bTimeVisibility)
7635	{
7636		BX.addClass(this.PARTS.BUTTONS, 'bx-calendar-buttons-disabled');
7637		BX.addClass(this.PARTS.TIME, 'bx-calendar-set-time-wrap-simple');
7638		BX.removeClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
7639	}
7640	else
7641	{
7642		BX.removeClass(this.DIV, 'bx-calendar-time-disabled');
7643
7644		if (!!bHideTime)
7645			BX.removeClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
7646		else
7647			BX.addClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
7648	}
7649};
7650
7651BX.JCCalendar.prototype.SetDay = function(d)
7652{
7653	this.value.setUTCDate(d);
7654	return this.SetValue(this.value);
7655};
7656
7657BX.JCCalendar.prototype.SetMonth = function(m)
7658{
7659	if (this.popup_month)
7660		this.popup_month.close();
7661
7662	this.value.setUTCMonth(m);
7663
7664	if(m < 0)
7665		m += 12;
7666	else if (m >= 12)
7667		m -= 12;
7668
7669	while(this.value.getUTCMonth() > m)
7670	{
7671		this.value.setUTCDate(this.value.getUTCDate()-1);
7672	}
7673
7674	return this.SetValue(this.value);
7675};
7676
7677BX.JCCalendar.prototype.SetYear = function(y)
7678{
7679	if (this.popup_year)
7680		this.popup_year.close();
7681	this.value.setUTCFullYear(y);
7682	return this.SetValue(this.value);
7683};
7684
7685BX.JCCalendar.prototype.SetDate = function(v, bSet)
7686{
7687	v = this._check_date(v);
7688	v.setUTCHours(this.value.getUTCHours());
7689	v.setUTCMinutes(this.value.getUTCMinutes());
7690	v.setUTCSeconds(this.value.getUTCSeconds());
7691
7692	if (this.params.bTime && !bSet)
7693	{
7694		return this.SetValue(v);
7695	}
7696	else
7697	{
7698		this.SetValue(v);
7699		this.SaveValue();
7700	}
7701};
7702
7703BX.JCCalendar.prototype.SetValue = function(v)
7704{
7705	this.value = (v && v.BXCHECKED) ? v : this._check_date(v);
7706
7707	this.PARTS.MONTH.innerHTML = BX.message('MONTH_' + (this.value.getUTCMonth()+1));
7708	this.PARTS.YEAR.innerHTML = this.value.getUTCFullYear();
7709
7710	if (!!this.params.bTime)
7711	{
7712		var h = this.value.getUTCHours();
7713		if (this.bAmPm)
7714		{
7715			if (h >= 12)
7716			{
7717				this.PARTS.TIME_AMPM.innerHTML = 'PM';
7718
7719				if (h != 12)
7720					h -= 12;
7721			}
7722			else
7723			{
7724				this.PARTS.TIME_AMPM.innerHTML = 'AM';
7725
7726				if (h == 0)
7727					h = 12;
7728			}
7729		}
7730
7731		this.PARTS.TIME_INPUT_H.value = BX.util.str_pad_left(h.toString(), 2, "0");
7732		this.PARTS.TIME_INPUT_M.value = BX.util.str_pad_left(this.value.getUTCMinutes().toString(), 2, "0");
7733	}
7734
7735	this._set_layer();
7736
7737	return this;
7738};
7739
7740BX.JCCalendar.prototype.SaveValue = function()
7741{
7742	if (this.popup_month)
7743		this.popup_month.close();
7744	if (this.popup_year)
7745		this.popup_year.close();
7746
7747	var bSetValue = true;
7748	if (!!this.params.callback)
7749	{
7750		var res = this.params.callback.apply(this, [new Date(this.value.valueOf()+this.value.getTimezoneOffset()*60000)]);
7751		if (res === false)
7752			bSetValue = false;
7753	}
7754
7755	if (bSetValue)
7756	{
7757		var bTime = !!this.params.bTime && BX.hasClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
7758
7759		if (this.params.field)
7760		{
7761			var format = BX.message(bTime ? 'FORMAT_DATETIME' : 'FORMAT_DATE');
7762
7763			if(bTime && !this.params.bUseSecond)
7764			{
7765				format = format.replace(':SS', '');
7766			}
7767
7768			this.params.field.value = BX.calendar.ValueToStringFormat(this.value, format, true);
7769			BX.fireEvent(this.params.field, 'change');
7770		}
7771
7772		this.popup.close();
7773
7774		if (!!this.params.callback_after)
7775		{
7776			this.params.callback_after.apply(this, [new Date(this.value.valueOf()+this.value.getTimezoneOffset()*60000), bTime]);
7777		}
7778	}
7779
7780	return this;
7781};
7782
7783BX.JCCalendar.prototype.Close = function()
7784{
7785	if (!!this.popup)
7786		this.popup.close();
7787
7788	return this;
7789};
7790
7791BX.JCSpinner = function(params)
7792{
7793	params = params || {};
7794	this.params = {
7795		input: params.input || null,
7796
7797		delta: params.delta || 1,
7798
7799		timeout_start: params.timeout_start || 1000,
7800		timeout_cont: params.timeout_cont || 150,
7801
7802		callback_start: params.callback_start || null,
7803		callback_change: params.callback_change || null,
7804		callback_finish: params.callback_finish || null,
7805
7806		bSaveValue: typeof params.bSaveValue == 'undefined' ? !!params.input : !!params.bSaveValue
7807	};
7808
7809	this.mousedown = false;
7810	this.direction = 1;
7811};
7812
7813BX.JCSpinner.prototype.Show = function()
7814{
7815	this.node = BX.create('span', {
7816		events: {
7817			mousedown: BX.delegateEvent(
7818				{attr: 'data-dir'},
7819				BX.delegate(this.Start, this)
7820			)
7821		},
7822		html: '<a href="javascript:void(0)" class="bx-calendar-form-arrow bx-calendar-form-arrow-top" data-dir="1"><i></i></a><a href="javascript:void(0)" class="bx-calendar-form-arrow bx-calendar-form-arrow-bottom" data-dir="-1"><i></i></a>'
7823	});
7824	return this.node;
7825};
7826
7827BX.JCSpinner.prototype.Start = function()
7828{
7829	this.mousedown = true;
7830	this.direction = BX.proxy_context.getAttribute('data-dir') > 0 ? 1 : -1;
7831	BX.bind(document, "mouseup", BX.proxy(this.MouseUp, this));
7832	this.ChangeValue(true);
7833};
7834
7835BX.JCSpinner.prototype.ChangeValue = function(bFirst)
7836{
7837	if(!this.mousedown)
7838		return;
7839
7840	if (this.params.input)
7841	{
7842		var v = parseInt(this.params.input.value, 10) + this.params.delta * this.direction;
7843
7844		if (this.params.bSaveValue)
7845			this.params.input.value = v;
7846
7847		if (!!bFirst && this.params.callback_start)
7848			this.params.callback_start(this.params, v, this.direction);
7849
7850		if (this.params.callback_change)
7851			this.params.callback_change(this.params, v, this.direction);
7852
7853		setTimeout(
7854			BX.proxy(this.ChangeValue, this),
7855			!!bFirst ? this.params.timeout_start : this.params.timeout_cont
7856		);
7857	}
7858};
7859
7860BX.JCSpinner.prototype.MouseUp = function()
7861{
7862	this.mousedown = false;
7863	BX.unbind(document, "mouseup", BX.proxy(this.MouseUp, this));
7864
7865	if (this.params.callback_finish)
7866		this.params.callback_finish(this.params, this.params.input.value);
7867};
7868
7869/**************** compatibility hacks ***************************/
7870
7871window.jsCalendar = {
7872	Show: function(obj, field, fieldFrom, fieldTo, bTime, serverTime, form_name, bHideTimebar)
7873	{
7874		return BX.calendar({
7875			node: obj, field: field, form: form_name, bTime: !!bTime, currentTime: serverTime, bHideTimebar: !!bHideTimebar
7876		});
7877	},
7878
7879	ValueToString: BX.calendar.ValueToString
7880};
7881
7882
7883/************ clock popup transferred from timeman **************/
7884
7885BX.CClockSelector = function(params)
7886{
7887	this.params = params;
7888
7889	this.params.popup_buttons = this.params.popup_buttons || [
7890		new BX.PopupWindowButton({
7891			text : BX.message('CAL_BUTTON'),
7892			className : "popup-window-button-create",
7893			events : {click : BX.proxy(this.setValue, this)}
7894		})
7895	];
7896
7897	this.isReady = false;
7898
7899	this.WND = new BX.PopupWindow(
7900		this.params.popup_id || 'clock_selector_popup',
7901		this.params.node,
7902		this.params.popup_config || {
7903			titleBar: BX.message('CAL_TIME'),
7904			offsetLeft: -45,
7905			offsetTop: -135,
7906			autoHide: true,
7907			closeIcon: true,
7908			closeByEsc: true
7909		}
7910	);
7911
7912	this.SHOW = false;
7913	BX.addCustomEvent(this.WND, "onPopupClose", BX.delegate(this.onPopupClose, this));
7914
7915	this.obClocks = {};
7916	this.CLOCK_ID = this.params.clock_id || 'clock_selector';
7917};
7918
7919BX.CClockSelector.prototype.Show = function()
7920{
7921	if (!this.isReady)
7922	{
7923		//BX.timeman.showWait(this.parent.DIV);
7924
7925		BX.addCustomEvent('onClockRegister', BX.proxy(this.onClockRegister, this));
7926		return BX.ajax.get('/bitrix/tools/clock_selector.php', {start_time: this.params.start_time, clock_id: this.CLOCK_ID, sessid: BX.bitrix_sessid()}, BX.delegate(this.Ready, this));
7927	}
7928
7929	this.WND.setButtons(this.params.popup_buttons);
7930	this.WND.show();
7931
7932	this.SHOW = true;
7933
7934	if (window['bxClock_' + this.obClocks[this.CLOCK_ID]])
7935	{
7936		setTimeout("window['bxClock_" + this.obClocks[this.CLOCK_ID] + "'].CalculateCoordinates()", 40);
7937	}
7938
7939	return true;
7940};
7941
7942BX.CClockSelector.prototype.onClockRegister = function(obClocks)
7943{
7944	if (obClocks[this.CLOCK_ID])
7945	{
7946		this.obClocks[this.CLOCK_ID] = obClocks[this.CLOCK_ID];
7947		BX.removeCustomEvent('onClockRegister', BX.proxy(this.onClockRegister, this));
7948	}
7949};
7950
7951BX.CClockSelector.prototype.Ready = function(data)
7952{
7953	this.content = this.CreateContent(data);
7954	this.WND.setContent(this.content);
7955
7956	this.isReady = true;
7957	//BX.timeman.closeWait();
7958
7959	setTimeout(BX.proxy(this.Show, this), 30);
7960};
7961
7962BX.CClockSelector.prototype.CreateContent = function(data)
7963{
7964	return BX.create('DIV', {
7965		events: {click: BX.PreventDefault},
7966		html:
7967			'<div class="bx-tm-popup-clock">' + data + '</div>'
7968	});
7969};
7970
7971BX.CClockSelector.prototype.setValue = function(e)
7972{
7973	if (this.params.callback)
7974	{
7975		var input = BX.findChild(this.content, {tagName: 'INPUT'}, true);
7976		this.params.callback.apply(this.params.node, [input.value]);
7977	}
7978
7979	return BX.PreventDefault(e);
7980};
7981
7982BX.CClockSelector.prototype.closeWnd = function(e)
7983{
7984	this.WND.close();
7985	return (e || window.event) ? BX.PreventDefault(e) : true;
7986};
7987
7988BX.CClockSelector.prototype.setNode = function(node)
7989{
7990	this.WND.setBindElement(node);
7991};
7992
7993BX.CClockSelector.prototype.setTime = function(timestamp)
7994{
7995	this.params.start_time = timestamp;
7996	if (window['bxClock_' + this.obClocks[this.CLOCK_ID]])
7997	{
7998		window['bxClock_' +  this.obClocks[this.CLOCK_ID]].SetTime(parseInt(timestamp/3600), parseInt((timestamp%3600)/60));
7999	}
8000};
8001
8002BX.CClockSelector.prototype.setCallback = function(cb)
8003{
8004	this.params.callback = cb;
8005};
8006
8007BX.CClockSelector.prototype.onPopupClose = function()
8008{
8009	this.SHOW = false;
8010};
8011
8012})();
8013
8014/* End */
8015;
8016; /* Start:"a:4:{s:4:"full";s:40:"/bitrix/js/main/utils.js?174159736029279";s:6:"source";s:24:"/bitrix/js/main/utils.js";s:3:"min";s:0:"";s:3:"map";s:0:"";}"*/
8017var phpVars;
8018if(!phpVars)
8019{
8020	phpVars = {
8021		ADMIN_THEME_ID: '.default',
8022		LANGUAGE_ID: 'en',
8023		FORMAT_DATE: 'DD.MM.YYYY',
8024		FORMAT_DATETIME: 'DD.MM.YYYY HH:MI:SS',
8025		opt_context_ctrl: false,
8026		cookiePrefix: 'BITRIX_SM',
8027		titlePrefix: '',
8028		bitrix_sessid: '',
8029		messHideMenu: '',
8030		messShowMenu: '',
8031		messHideButtons: '',
8032		messShowButtons: '',
8033		messFilterInactive: '',
8034		messFilterActive: '',
8035		messFilterLess: '',
8036		messLoading: 'Loading...',
8037		messMenuLoading: '',
8038		messMenuLoadingTitle: '',
8039		messNoData: '',
8040		messExpandTabs: '',
8041		messCollapseTabs: '',
8042		messPanelFixOn: '',
8043		messPanelFixOff: '',
8044		messPanelCollapse: '',
8045		messPanelExpand: ''
8046	};
8047}
8048
8049var jsUtils =
8050{
8051	arEvents: Array(),
8052
8053	addEvent: function(el, evname, func, capture)
8054	{
8055		if(el.attachEvent) // IE
8056			el.attachEvent("on" + evname, func);
8057		else if(el.addEventListener) // Gecko / W3C
8058			el.addEventListener(evname, func, false);
8059		else
8060			el["on" + evname] = func;
8061		this.arEvents[this.arEvents.length] = {'element': el, 'event': evname, 'fn': func};
8062	},
8063
8064	removeEvent: function(el, evname, func)
8065	{
8066		if(el.detachEvent) // IE
8067			el.detachEvent("on" + evname, func);
8068		else if(el.removeEventListener) // Gecko / W3C
8069			el.removeEventListener(evname, func, false);
8070		else
8071			el["on" + evname] = null;
8072	},
8073
8074	removeAllEvents: function(el)
8075	{
8076		var i;
8077		for(i=0; i<this.arEvents.length; i++)
8078		{
8079			if(this.arEvents[i] && (el==false || el==this.arEvents[i].element))
8080			{
8081				jsUtils.removeEvent(this.arEvents[i].element, this.arEvents[i].event, this.arEvents[i].fn);
8082				this.arEvents[i] = null;
8083			}
8084		}
8085		if(el==false)
8086			this.arEvents.length = 0;
8087	},
8088
8089	IsDoctype: function()
8090	{
8091		if (document.compatMode)
8092			return (document.compatMode == "CSS1Compat");
8093
8094		if (document.documentElement && document.documentElement.clientHeight)
8095			return true;
8096
8097		return false;
8098	},
8099
8100	GetRealPos: function(el)
8101	{
8102		if(window.BX)
8103			return BX.pos(el);
8104
8105		if(!el || !el.offsetParent)
8106			return false;
8107
8108		var res = Array();
8109		res["left"] = el.offsetLeft;
8110		res["top"] = el.offsetTop;
8111		var objParent = el.offsetParent;
8112
8113		while(objParent && objParent.tagName != "BODY")
8114		{
8115			res["left"] += objParent.offsetLeft;
8116			res["top"] += objParent.offsetTop;
8117			objParent = objParent.offsetParent;
8118		}
8119		res["right"] = res["left"] + el.offsetWidth;
8120		res["bottom"] = res["top"] + el.offsetHeight;
8121
8122		return res;
8123	},
8124
8125	FindChildObject: function(obj, tag_name, class_name, recursive)
8126	{
8127		if(!obj)
8128			return null;
8129		var tag = tag_name.toUpperCase();
8130		var cl = (class_name? class_name.toLowerCase() : null);
8131		var n = obj.childNodes.length;
8132		for(var j=0; j<n; j++)
8133		{
8134			var child = obj.childNodes[j];
8135			if(child.tagName && child.tagName.toUpperCase() == tag)
8136				if(!class_name || child.className.toLowerCase() == cl)
8137					return child;
8138			if(recursive == true)
8139			{
8140				var deepChild;
8141				if((deepChild = jsUtils.FindChildObject(child, tag_name, class_name, true)))
8142					return deepChild;
8143			}
8144		}
8145		return null;
8146	},
8147
8148	FindParentObject: function(obj, tag_name, class_name)
8149	{
8150		if(!obj)
8151			return null;
8152		var o = obj;
8153		var tag = tag_name.toUpperCase();
8154		var cl = (class_name? class_name.toLowerCase() : null);
8155		while(o.parentNode)
8156		{
8157			var parent = o.parentNode;
8158			if(parent.tagName && parent.tagName.toUpperCase() == tag)
8159				if(!class_name || parent.className.toLowerCase() == cl)
8160					return parent;
8161			o = parent;
8162		}
8163		return null;
8164	},
8165
8166	FindNextSibling: function(obj, tag_name)
8167	{
8168		if(!obj)
8169			return null;
8170		var o = obj;
8171		var tag = tag_name.toUpperCase();
8172		while(o.nextSibling)
8173		{
8174			var sibling = o.nextSibling;
8175			if(sibling.tagName && sibling.tagName.toUpperCase() == tag)
8176				return sibling;
8177			o = sibling;
8178		}
8179		return null;
8180	},
8181
8182	FindPreviousSibling: function(obj, tag_name)
8183	{
8184		if(!obj)
8185			return null;
8186		var o = obj;
8187		var tag = tag_name.toUpperCase();
8188		while(o.previousSibling)
8189		{
8190			var sibling = o.previousSibling;
8191			if(sibling.tagName && sibling.tagName.toUpperCase() == tag)
8192				return sibling;
8193			o = sibling;
8194		}
8195		return null;
8196	},
8197
8198	bOpera : navigator.userAgent.toLowerCase().indexOf('opera') != -1,
8199	bIsIE : document.attachEvent && navigator.userAgent.toLowerCase().indexOf('opera') == -1,
8200
8201	IsIE: function()
8202	{
8203		return this.bIsIE;
8204	},
8205
8206	IsOpera: function()
8207	{
8208		return this.bOpera;
8209	},
8210
8211	IsSafari: function()
8212	{
8213		var userAgent = navigator.userAgent.toLowerCase();
8214		return (/webkit/.test(userAgent));
8215	},
8216
8217	IsEditor: function()
8218	{
8219		var userAgent = navigator.userAgent.toLowerCase();
8220		var version = (userAgent.match( /.+(msie)[\/: ]([\d.]+)/ ) || [])[2];
8221		var safari = /webkit/.test(userAgent);
8222
8223		if (this.IsOpera() || (document.all && !document.compatMode && version < 6) || safari)
8224			return false;
8225
8226		return true;
8227	},
8228
8229	ToggleDiv: function(div)
8230	{
8231		var style = document.getElementById(div).style;
8232		if(style.display!="none")
8233			style.display = "none";
8234		else
8235			style.display = "block";
8236		return (style.display != "none");
8237	},
8238
8239	urlencode: function(s)
8240	{
8241		return escape(s).replace(new RegExp('\\+','g'), '%2B');
8242	},
8243
8244	OpenWindow: function(url, width, height)
8245	{
8246		var w = screen.width, h = screen.height;
8247		if(this.IsOpera())
8248		{
8249			w = document.body.offsetWidth;
8250			h = document.body.offsetHeight;
8251		}
8252		window.open(url, '', 'status=no,scrollbars=yes,resizable=yes,width='+width+',height='+height+',top='+Math.floor((h - height)/2-14)+',left='+Math.floor((w - width)/2-5));
8253	},
8254
8255	SetPageTitle: function(s)
8256	{
8257		document.title = phpVars.titlePrefix+s;
8258		var h1 = document.getElementsByTagName("H1");
8259		if(h1)
8260			h1[0].innerHTML = s;
8261	},
8262
8263	LoadPageToDiv: function(url, div_id)
8264	{
8265		var div = document.getElementById(div_id);
8266		if(!div)
8267			return;
8268		CHttpRequest.Action = function(result)
8269		{
8270			CloseWaitWindow();
8271			document.getElementById(div_id).innerHTML = result;
8272		}
8273		ShowWaitWindow();
8274		CHttpRequest.Send(url);
8275	},
8276
8277	trim: function(s)
8278	{
8279		if (typeof s == 'string' || typeof s == 'object' && s.constructor == String)
8280		{
8281			var r, re;
8282
8283			re = /^[\s\r\n]+/g;
8284			r = s.replace(re, "");
8285			re = /[\s\r\n]+$/g;
8286			r = r.replace(re, "");
8287			return r;
8288		}
8289		else
8290			return s;
8291	},
8292
8293	Redirect: function(args, url)
8294	{
8295		var e = null, bShift = false;
8296		if(args && args.length > 0)
8297			e = args[0];
8298		if(!e)
8299			e = window.event;
8300		if(e)
8301			bShift = e.shiftKey;
8302
8303		if(bShift)
8304			window.open(url);
8305		else
8306		{
8307			window.location.href=url;
8308		}
8309	},
8310
8311	False: function(){return false;},
8312
8313	AlignToPos: function(pos, w, h)
8314	{
8315		var x = pos["left"], y = pos["bottom"];
8316
8317		var scroll = jsUtils.GetWindowScrollPos();
8318		var size = jsUtils.GetWindowInnerSize();
8319
8320		if((size.innerWidth + scroll.scrollLeft) - (pos["left"] + w) < 0)
8321		{
8322			if(pos["right"] - w >= 0 )
8323				x = pos["right"] - w;
8324			else
8325				x = scroll.scrollLeft;
8326		}
8327
8328		if((size.innerHeight + scroll.scrollTop) - (pos["bottom"] + h) < 0)
8329		{
8330			if(pos["top"] - h >= 0)
8331				y = pos["top"] - h;
8332			else
8333				y = scroll.scrollTop;
8334		}
8335
8336		return {'left':x, 'top':y};
8337	},
8338
8339	// evaluate js string in window scope
8340	EvalGlobal: function(script)
8341	{
8342		try {
8343		if (window.execScript)
8344			window.execScript(script, 'javascript');
8345		else if (jsUtils.IsSafari())
8346			window.setTimeout(script, 0);
8347		else
8348			window.eval(script);
8349		} catch (e) {/*alert("Error! jsUtils.EvalGlobal");*/}
8350	},
8351
8352	GetStyleValue: function(el, styleProp)
8353	{
8354		var res;
8355		if(el.currentStyle)
8356			res = el.currentStyle[styleProp];
8357		else if(window.getComputedStyle)
8358			res = document.defaultView.getComputedStyle(el, null).getPropertyValue(styleProp);
8359		if(!res)
8360			res = '';
8361		return res;
8362	},
8363
8364	GetWindowInnerSize: function(pDoc)
8365	{
8366		var width, height;
8367		if (!pDoc)
8368			pDoc = document;
8369
8370		if (self.innerHeight) // all except Explorer
8371		{
8372			width = self.innerWidth;
8373			height = self.innerHeight;
8374		}
8375		else if (pDoc.documentElement && (pDoc.documentElement.clientHeight || pDoc.documentElement.clientWidth)) // Explorer 6 Strict Mode
8376		{
8377			width = pDoc.documentElement.clientWidth;
8378			height = pDoc.documentElement.clientHeight;
8379		}
8380		else if (pDoc.body) // other Explorers
8381		{
8382			width = pDoc.body.clientWidth;
8383			height = pDoc.body.clientHeight;
8384		}
8385		return {innerWidth : width, innerHeight : height};
8386	},
8387
8388	GetWindowScrollPos: function(pDoc)
8389	{
8390		var left, top;
8391		if (!pDoc)
8392			pDoc = document;
8393
8394		if (self.pageYOffset) // all except Explorer
8395		{
8396			left = self.pageXOffset;
8397			top = self.pageYOffset;
8398		}
8399		else if (pDoc.documentElement && (pDoc.documentElement.scrollTop || pDoc.documentElement.scrollLeft)) // Explorer 6 Strict
8400		{
8401			left = document.documentElement.scrollLeft;
8402			top = document.documentElement.scrollTop;
8403		}
8404		else if (pDoc.body) // all other Explorers
8405		{
8406			left = pDoc.body.scrollLeft;
8407			top = pDoc.body.scrollTop;
8408		}
8409		return {scrollLeft : left, scrollTop : top};
8410	},
8411
8412	GetWindowScrollSize: function(pDoc)
8413	{
8414		var width, height;
8415		if (!pDoc)
8416			pDoc = document;
8417
8418		if ( (pDoc.compatMode && pDoc.compatMode == "CSS1Compat"))
8419		{
8420			width = pDoc.documentElement.scrollWidth;
8421			height = pDoc.documentElement.scrollHeight;
8422		}
8423		else
8424		{
8425			if (pDoc.body.scrollHeight > pDoc.body.offsetHeight)
8426				height = pDoc.body.scrollHeight;
8427			else
8428				height = pDoc.body.offsetHeight;
8429
8430			if (pDoc.body.scrollWidth > pDoc.body.offsetWidth ||
8431				(pDoc.compatMode && pDoc.compatMode == "BackCompat") ||
8432				(pDoc.documentElement && !pDoc.documentElement.clientWidth)
8433			)
8434				width = pDoc.body.scrollWidth;
8435			else
8436				width = pDoc.body.offsetWidth;
8437		}
8438		return {scrollWidth : width, scrollHeight : height};
8439	},
8440
8441	GetWindowSize: function()
8442	{
8443		var innerSize = jsUtils.GetWindowInnerSize();
8444		var scrollPos = jsUtils.GetWindowScrollPos();
8445		var scrollSize = jsUtils.GetWindowScrollSize();
8446
8447		return  {
8448			innerWidth : innerSize.innerWidth, innerHeight : innerSize.innerHeight,
8449			scrollLeft : scrollPos.scrollLeft, scrollTop : scrollPos.scrollTop,
8450			scrollWidth : scrollSize.scrollWidth, scrollHeight : scrollSize.scrollHeight
8451		};
8452	},
8453
8454
8455	arCustomEvents: {},
8456
8457	addCustomEvent: function(eventName, eventHandler, arParams, handlerContextObject)
8458	{
8459		if (!this.arCustomEvents[eventName])
8460			this.arCustomEvents[eventName] = [];
8461
8462		if (!arParams)
8463			arParams = [];
8464		if (!handlerContextObject)
8465			handlerContextObject = false;
8466
8467		this.arCustomEvents[eventName].push(
8468			{
8469				handler: eventHandler,
8470				arParams: arParams,
8471				obj: handlerContextObject
8472			}
8473		);
8474	},
8475
8476	removeCustomEvent: function(eventName, eventHandler)
8477	{
8478		if (!this.arCustomEvents[eventName])
8479			return;
8480
8481		var l = this.arCustomEvents[eventName].length;
8482		if (l == 1)
8483		{
8484			delete this.arCustomEvents[eventName];
8485			return;
8486		}
8487
8488		for (var i = 0; i < l; i++)
8489		{
8490			if (!this.arCustomEvents[eventName][i])
8491				continue;
8492			if (this.arCustomEvents[eventName][i].handler == eventHandler)
8493			{
8494				delete this.arCustomEvents[eventName][i];
8495				return;
8496			}
8497		}
8498	},
8499
8500	onCustomEvent: function(eventName, arEventParams)
8501	{
8502		if (!this.arCustomEvents[eventName])
8503			return;
8504
8505		if (!arEventParams)
8506			arEventParams = [];
8507
8508		var h;
8509		for (var i = 0, l = this.arCustomEvents[eventName].length; i < l; i++)
8510		{
8511			h = this.arCustomEvents[eventName][i];
8512			if (!h || !h.handler)
8513				continue;
8514
8515			if (h.obj)
8516				h.handler.call(h.obj, h.arParams, arEventParams);
8517			else
8518				h.handler(h.arParams, arEventParams);
8519		}
8520	},
8521
8522	loadJSFile: function(arJs, oCallBack, pDoc)
8523	{
8524		if (!pDoc)
8525			pDoc = document;
8526		if (typeof arJs == 'string')
8527			arJs = [arJs];
8528		var callback = function()
8529		{
8530			if (!oCallBack)
8531				return;
8532			if (typeof oCallBack == 'function')
8533				return oCallBack();
8534			if (typeof oCallBack != 'object' || !oCallBack.func)
8535				return;
8536			var p = oCallBack.params || {};
8537			if (oCallBack.obj)
8538				oCallBack.func.apply(oCallBack.obj, p);
8539			else
8540				oCallBack.func(p);
8541		};
8542		var load_js = function(ind)
8543		{
8544			if (ind >= arJs.length)
8545				return callback();
8546			var oSript = pDoc.body.appendChild(pDoc.createElement('script'));
8547			oSript.src = arJs[ind];
8548			var bLoaded = false;
8549			oSript.onload = oSript.onreadystatechange = function()
8550			{
8551				if (!bLoaded && (!oSript.readyState || oSript.readyState == "loaded" || oSript.readyState == "complete"))
8552				{
8553					bLoaded = true;
8554					setTimeout(function (){load_js(++ind);}, 50);
8555				}
8556			};
8557		};
8558		load_js(0);
8559	},
8560
8561	loadCSSFile: function(arCSS, pDoc, pWin)
8562	{
8563		if (typeof arCSS == 'string')
8564		{
8565			var bSingle = true;
8566			arCSS = [arCSS];
8567		}
8568		var i, l = arCSS.length, pLnk = [];
8569		if (l == 0)
8570			return;
8571		if (!pDoc)
8572			pDoc = document;
8573		if (!pWin)
8574			pWin = window;
8575		if (!pWin.bxhead)
8576		{
8577			var heads = pDoc.getElementsByTagName('HEAD');
8578			pWin.bxhead = heads[0];
8579		}
8580		if (!pWin.bxhead)
8581			return;
8582		for (i = 0; i < l; i++)
8583		{
8584			var lnk = document.createElement('LINK');
8585			lnk.href = arCSS[i];
8586			lnk.rel = 'stylesheet';
8587			lnk.type = 'text/css';
8588			pWin.bxhead.appendChild(lnk);
8589			pLnk.push(lnk);
8590		}
8591		if (bSingle)
8592			return lnk;
8593		return pLnk;
8594	},
8595
8596	appendBXHint : function(node, html)
8597	{
8598		if (!node || !node.parentNode || !html)
8599			return;
8600		var oBXHint = new BXHint(html);
8601		node.parentNode.insertBefore(oBXHint.oIcon, node);
8602		node.parentNode.removeChild(node);
8603		oBXHint.oIcon.style.marginLeft = "5px";
8604	},
8605
8606	PreventDefault : function(e)
8607	{
8608		if(!e) e = window.event;
8609		if(e.stopPropagation)
8610		{
8611			e.preventDefault();
8612			e.stopPropagation();
8613		}
8614		else
8615		{
8616			e.cancelBubble = true;
8617			e.returnValue = false;
8618		}
8619		return false;
8620	},
8621
8622	CreateElement: function(tag, arAttr, arStyles, pDoc)
8623	{
8624		if (!pDoc)
8625			pDoc = document;
8626		var pEl = pDoc.createElement(tag), p;
8627		if(arAttr)
8628		{
8629			for(p in arAttr)
8630			{
8631				if(p == 'className' || p == 'class')
8632				{
8633					pEl.setAttribute('class', arAttr[p]);
8634					if (jsUtils.IsIE())
8635						pEl.setAttribute('className', arAttr[p]);
8636					continue;
8637				}
8638
8639				if (arAttr[p] != undefined && arAttr[p] != null)
8640					pEl.setAttribute(p, arAttr[p]);
8641			}
8642		}
8643		if(arStyles)
8644		{
8645			for(p in arStyles)
8646				pEl.style[p] = arStyles[p];
8647		}
8648		return pEl;
8649	},
8650
8651	in_array: function(needle, haystack)
8652	{
8653		for(var i=0; i<haystack.length; i++)
8654		{
8655			if(haystack[i] == needle)
8656				return true;
8657		}
8658		return false;
8659	},
8660
8661	htmlspecialchars: function(str)
8662	{
8663		if(!str.replace)
8664			return str;
8665
8666		return str.replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
8667	}
8668}
8669
8670/************************************************/
8671
8672function JCFloatDiv()
8673{
8674	var _this = this;
8675	this.floatDiv = null;
8676	this.x = this.y = 0;
8677
8678	this.Create = function(arParams)
8679	{
8680		var div = document.body.appendChild(document.createElement("DIV"));
8681		div.id = arParams.id;
8682		div.style.position = 'absolute';
8683		div.style.left = '-10000px';
8684		div.style.top = '-10000px';
8685		if(arParams.className)
8686			div.className = arParams.className;
8687		if(arParams.zIndex)
8688			div.style.zIndex = arParams.zIndex;
8689		if(arParams.width)
8690			div.style.width = arParams.width+'px';
8691		if(arParams.height)
8692			div.style.height = arParams.height+'px';
8693		return div;
8694	}
8695
8696	this.Show = function(div, left, top, dxShadow, restrictDrag)
8697	{
8698		var component = BX.ZIndexManager.getComponent(div);
8699		if (!component)
8700		{
8701			BX.ZIndexManager.register(div);
8702		}
8703
8704		BX.ZIndexManager.bringToFront(div);
8705
8706		if (left < 0)
8707			left = 0;
8708
8709		if (top < 0)
8710			top = 0;
8711
8712		div.style.left = parseInt(left) + "px";
8713		div.style.top = parseInt(top) + "px";
8714
8715		/*Restrict drag*/
8716		div.restrictDrag = restrictDrag || false;
8717
8718		/*shadow*/
8719		if(isNaN(dxShadow))
8720			dxShadow = 5;
8721
8722		div.dxShadow = dxShadow;
8723	}
8724
8725	this.Close = function(div)
8726	{
8727		if(!div)
8728			return;
8729		var sh = document.getElementById(div.id+"_shadow");
8730		if(sh)
8731			sh.style.visibility = 'hidden';
8732
8733		var frame = document.getElementById(div.id+"_frame");
8734		if(frame)
8735			frame.style.visibility = 'hidden';
8736	}
8737
8738	this.Move = function(div, x, y)
8739	{
8740		if(!div)
8741			return;
8742
8743		var dxShadow = div.dxShadow;
8744		var left = parseInt(div.style.left)+x;
8745		var top = parseInt(div.style.top)+y;
8746
8747		if (div.restrictDrag)
8748		{
8749			//Left side
8750			if (left < 0)
8751				left = 0;
8752
8753			//Right side
8754			if ( (document.compatMode && document.compatMode == "CSS1Compat"))
8755				windowWidth = document.documentElement.scrollWidth;
8756			else
8757			{
8758				if (document.body.scrollWidth > document.body.offsetWidth ||
8759					(document.compatMode && document.compatMode == "BackCompat") ||
8760					(document.documentElement && !document.documentElement.clientWidth)
8761				)
8762					windowWidth = document.body.scrollWidth;
8763				else
8764					windowWidth = document.body.offsetWidth;
8765			}
8766
8767			var floatWidth = div.offsetWidth;
8768			if (left > (windowWidth - floatWidth - dxShadow))
8769				left = windowWidth - floatWidth - dxShadow;
8770
8771			//Top side
8772			if (top < 0)
8773				top = 0;
8774		}
8775
8776		div.style.left = left+'px';
8777		div.style.top = top+'px';
8778
8779		this.AdjustShadow(div);
8780	}
8781
8782	this.HideShadow = function(div)
8783	{
8784		var sh = document.getElementById(div.id + "_shadow");
8785		sh.style.visibility = 'hidden';
8786	}
8787
8788	this.UnhideShadow = function(div)
8789	{
8790		var sh = document.getElementById(div.id + "_shadow");
8791		sh.style.visibility = 'visible';
8792	}
8793
8794	this.AdjustShadow = function(div)
8795	{
8796		var sh = document.getElementById(div.id + "_shadow");
8797		if(sh && sh.style.visibility != 'hidden')
8798		{
8799			var dxShadow = div.dxShadow;
8800
8801			sh.style.width = div.offsetWidth+'px';
8802			sh.style.height = div.offsetHeight+'px';
8803			sh.style.left = parseInt(div.style.left)+dxShadow+'px';
8804			sh.style.top = parseInt(div.style.top)+dxShadow+'px';
8805		}
8806
8807		var frame = document.getElementById(div.id+"_frame");
8808		if(frame)
8809		{
8810			frame.style.width = div.offsetWidth + "px";
8811			frame.style.height = div.offsetHeight + "px";
8812			frame.style.left = div.style.left;
8813			frame.style.top = div.style.top;
8814		}
8815	}
8816
8817	this.StartDrag = function(e, div)
8818	{
8819		if(!e)
8820			e = window.event;
8821		this.x = e.clientX + document.body.scrollLeft;
8822		this.y = e.clientY + document.body.scrollTop;
8823		this.floatDiv = div;
8824
8825		jsUtils.addEvent(document, "mousemove", this.MoveDrag);
8826		document.onmouseup = this.StopDrag;
8827		if(document.body.setCapture)
8828			document.body.setCapture();
8829
8830		document.onmousedown = jsUtils.False;
8831		var b = document.body;
8832		b.ondrag = jsUtils.False;
8833		b.onselectstart = jsUtils.False;
8834		b.style.MozUserSelect = _this.floatDiv.style.MozUserSelect = 'none';
8835		b.style.cursor = 'move';
8836	}
8837
8838	this.StopDrag = function(e)
8839	{
8840		if(document.body.releaseCapture)
8841			document.body.releaseCapture();
8842
8843		jsUtils.removeEvent(document, "mousemove", _this.MoveDrag);
8844		document.onmouseup = null;
8845
8846		this.floatDiv = null;
8847
8848		document.onmousedown = null;
8849		var b = document.body;
8850		b.ondrag = null;
8851		b.onselectstart = null;
8852		b.style.MozUserSelect = _this.floatDiv.style.MozUserSelect = '';
8853		b.style.cursor = '';
8854	}
8855
8856	this.MoveDrag = function(e)
8857	{
8858		var x = e.clientX + document.body.scrollLeft;
8859		var y = e.clientY + document.body.scrollTop;
8860
8861		if(_this.x == x && _this.y == y)
8862			return;
8863
8864		_this.Move(_this.floatDiv, (x - _this.x), (y - _this.y));
8865		_this.x = x;
8866		_this.y = y;
8867	}
8868}
8869var jsFloatDiv = new JCFloatDiv();
8870
8871/************************************************/
8872
8873var BXHint = function(innerHTML, element, addParams)
8874{
8875	this.oDivOver = false;
8876	this.timeOutID = null;
8877	this.oIcon = null;
8878	this.freeze = false;
8879	this.x = 0;
8880	this.y = 0;
8881	this.time = 700;
8882
8883	if (!innerHTML)
8884		innerHTML = "";
8885	this.Create(innerHTML, element, addParams);
8886}
8887
8888BXHint.prototype.Create = function(innerHTML, element, addParams)
8889{
8890	var
8891		_this = this,
8892		width = 0,
8893		height = 0,
8894		className = null,
8895		type = "icon";
8896	this.bWidth = true;
8897
8898	if (addParams)
8899	{
8900		if (addParams.width === false)
8901			this.bWidth = false;
8902		else if (addParams.width)
8903			width = addParams.width;
8904
8905		if (addParams.height)
8906			height = addParams.height;
8907
8908		if (addParams.className)
8909			className = addParams.className;
8910
8911		if (addParams.type && (addParams.type == "link" || addParams.type == "icon"))
8912			type = addParams.type;
8913		if (addParams.time > 0)
8914			this.time = addParams.time;
8915	}
8916
8917	if (element)
8918		type = "element";
8919
8920	if (type == "icon")
8921	{
8922		var element = document.createElement("IMG");
8923		element.src = (addParams && addParams.iconSrc) ? addParams.iconSrc : "/bitrix/themes/"+phpVars.ADMIN_THEME_ID+"/public/popup/hint.gif";
8924		element.ondrag = jsUtils.False;
8925	}
8926	else if (type == "link")
8927	{
8928		var element = document.createElement("A");
8929		element.href = "";
8930		element.onclick = function(e){return false;}
8931		element.innerHTML = "[?]";
8932	}
8933
8934	this.element = element;
8935	if (type == "element")
8936	{
8937		if(addParams && addParams.show_on_click)
8938		{
8939			jsUtils.addEvent(
8940				element,
8941				"click",
8942				function (event)
8943				{
8944					if (!event)
8945						event = window.event;
8946					_this.GetMouseXY(event);
8947					_this.timeOutID = setTimeout(function () {_this.Show(innerHTML,width,height,className) }, 10);
8948				}
8949			);
8950		}
8951		else
8952		{
8953			jsUtils.addEvent(
8954				element,
8955				"mouseover",
8956				function (event)
8957				{
8958					if (!event)
8959						event = window.event;
8960					_this.GetMouseXY(event);
8961					_this.timeOutID = setTimeout(function () {_this.Show(innerHTML,width,height,className) }, 750);
8962				}
8963			);
8964		}
8965
8966		jsUtils.addEvent(
8967			element,
8968			"mouseout",
8969			function(event)
8970			{
8971				if (_this.timeOutID)
8972					clearTimeout(_this.timeOutID);
8973				_this.SmartHide(_this);
8974			}
8975		);
8976	}
8977	else
8978	{
8979		this.oIcon = element;
8980		element.onmouseover = function(event) {if (!event) event = window.event; _this.GetMouseXY(event); _this.Show(innerHTML,width,height,className)};
8981		element.onmouseout = function() {_this.SmartHide(_this);};
8982	}
8983}
8984
8985BXHint.prototype.IsFrozen = function()
8986{
8987	return this.freeze;
8988}
8989
8990BXHint.prototype.Freeze = function()
8991{
8992	this.freeze = true;
8993	this.Hide();
8994}
8995
8996BXHint.prototype.UnFreeze = function()
8997{
8998	this.freeze = false;
8999}
9000
9001BXHint.prototype.GetMouseXY = function(event)
9002{
9003	if (event.pageX || event.pageY)
9004	{
9005		this.x = event.pageX;
9006		this.y = event.pageY;
9007	}
9008	else if (event.clientX || event.clientY)
9009	{
9010		this.x = event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft) - document.documentElement.clientLeft;
9011		this.y = event.clientY + (document.documentElement.scrollTop || document.body.scrollTop) - document.documentElement.clientTop;
9012	}
9013}
9014
9015BXHint.prototype.Show = function(innerHTML, width, height, className)
9016{
9017	//Delete previous hint
9018	var old = document.getElementById("__BXHint_div");
9019	if (old)
9020		this.Hide();
9021
9022	if (this.freeze)
9023		return;
9024
9025	var _this = this;
9026	var oDiv = document.body.appendChild(document.createElement("DIV"));
9027	oDiv.onmouseover = function(){_this.oDivOver = true};
9028	oDiv.onmouseout = function(){_this.oDivOver = false; _this.SmartHide(_this);}
9029	oDiv.id = "__BXHint_div";
9030	oDiv.className = (className) ? className : "bxhint";
9031	oDiv.style.position = 'absolute';
9032	if (width && this.bWidth)
9033		oDiv.style.width = width + "px";
9034
9035	if (height)
9036		oDiv.style.height = height + "px";
9037	oDiv.innerHTML = innerHTML;
9038
9039	var w = oDiv.offsetWidth;
9040	var h = oDiv.offsetHeight;
9041	if (this.bWidth)
9042	{
9043		if (!width && w>200)
9044			w = Math.round(Math.sqrt(1.618*w*h));
9045		oDiv.style.width = w + "px";
9046		h = oDiv.offsetHeight;
9047	}
9048
9049	var pos = {left : this.x + 10, right : this.x + w, top : this.y, bottom : this.y + h};
9050
9051	pos = this.AlignToPos(pos, w, h);
9052
9053	jsFloatDiv.Show(oDiv, pos.left, pos.top,3);
9054
9055//	oDiv.ondrag = jsUtils.False;
9056//	oDiv.onselectstart = jsUtils.False;
9057//	oDiv.style.MozUserSelect = 'none';
9058	oDiv = null;
9059}
9060
9061BXHint.prototype.AlignToPos = function(pos, w, h)
9062{
9063	var body = document.body;
9064	if((body.clientWidth + body.scrollLeft) < (pos.left + w))
9065		pos.left = (pos.left - w >= 0) ? (pos.left - w) : body.scrollLeft;
9066
9067	if((body.clientHeight + body.scrollTop) - (pos["bottom"]) < 0)
9068		pos.top = (pos.top - h >= 0) ? (pos.top - h) : body.scrollTop;
9069
9070	return pos;
9071}
9072
9073BXHint.prototype.Hide = function()
9074{
9075	var oDiv = document.getElementById("__BXHint_div");
9076
9077	if (!oDiv)
9078		return;
9079
9080	BX.ZIndexManager.unregister(oDiv);
9081
9082	jsFloatDiv.Close(oDiv);
9083	oDiv.parentNode.removeChild(oDiv);
9084	oDiv = null;
9085}
9086
9087BXHint.prototype.SmartHide = function(_this)
9088{
9089	setTimeout(function ()
9090		{
9091			if (!_this.oDivOver)
9092				_this.Hide();
9093		}, 100
9094	);
9095}
9096
9097/************************************************/
9098
9099function WaitOnKeyPress(e)
9100{
9101	if(!e) e = window.event
9102	if(!e) return;
9103	if(e.keyCode == 27)
9104		CloseWaitWindow();
9105}
9106
9107function ShowWaitWindow()
9108{
9109	CloseWaitWindow();
9110
9111	var obWndSize = jsUtils.GetWindowSize();
9112
9113	var div = document.body.appendChild(document.createElement("DIV"));
9114	div.id = "wait_window_div";
9115	div.innerHTML = phpVars.messLoading;
9116	div.className = "waitwindow";
9117	//div.style.left = obWndSize.scrollLeft + (obWndSize.innerWidth - div.offsetWidth) - (jsUtils.IsIE() ? 5 : 20) + "px";
9118	div.style.right = (5 - obWndSize.scrollLeft) + 'px';
9119	div.style.top = obWndSize.scrollTop + 5 + "px";
9120
9121	if(jsUtils.IsIE())
9122	{
9123		var frame = document.createElement("IFRAME");
9124		frame.src = "javascript:''";
9125		frame.id = "wait_window_frame";
9126		frame.className = "waitwindow";
9127		frame.style.width = div.offsetWidth + "px";
9128		frame.style.height = div.offsetHeight + "px";
9129		frame.style.right = div.style.right;
9130		frame.style.top = div.style.top;
9131		document.body.appendChild(frame);
9132	}
9133	jsUtils.addEvent(document, "keypress", WaitOnKeyPress);
9134}
9135
9136function CloseWaitWindow()
9137{
9138	jsUtils.removeEvent(document, "keypress", WaitOnKeyPress);
9139
9140	var frame = document.getElementById("wait_window_frame");
9141	if(frame)
9142		frame.parentNode.removeChild(frame);
9143
9144	var div = document.getElementById("wait_window_div");
9145	if(div)
9146		div.parentNode.removeChild(div);
9147}
9148
9149/************************************************/
9150
9151var jsSelectUtils =
9152{
9153	addNewOption: function(select_id, opt_value, opt_name, do_sort, check_unique)
9154	{
9155		var oSelect = (typeof(select_id) == 'string' || select_id instanceof String? document.getElementById(select_id) : select_id);
9156		if(oSelect)
9157		{
9158			var n = oSelect.length;
9159			if(check_unique !== false)
9160			{
9161				for(var i=0;i<n;i++)
9162					if(oSelect[i].value==opt_value)
9163						return;
9164			}
9165			var newoption = new Option(opt_name, opt_value, false, false);
9166			oSelect.options[n]=newoption;
9167		}
9168		if(do_sort === true)
9169			this.sortSelect(select_id);
9170	},
9171
9172	deleteOption: function(select_id, opt_value)
9173	{
9174		var oSelect = (typeof(select_id) == 'string' || select_id instanceof String? document.getElementById(select_id) : select_id);
9175		if(oSelect)
9176		{
9177			for(var i=0;i<oSelect.length;i++)
9178				if(oSelect[i].value==opt_value)
9179				{
9180					oSelect.remove(i);
9181					break;
9182				}
9183		}
9184	},
9185
9186	deleteSelectedOptions: function(select_id)
9187	{
9188		var oSelect = (typeof(select_id) == 'string' || select_id instanceof String? document.getElementById(select_id) : select_id);
9189		if(oSelect)
9190		{
9191			var i=0;
9192			while(i<oSelect.length)
9193				if(oSelect[i].selected)
9194				{
9195					oSelect[i].selected=false;
9196					oSelect.remove(i);
9197				}
9198				else
9199					i++;
9200		}
9201	},
9202
9203	deleteAllOptions: function(oSelect)
9204	{
9205		if(oSelect)
9206		{
9207			for(var i=oSelect.length-1; i>=0; i--)
9208				oSelect.remove(i);
9209		}
9210	},
9211
9212	optionCompare: function(record1, record2)
9213	{
9214		var value1 = record1.optText.toLowerCase();
9215		var value2 = record2.optText.toLowerCase();
9216		if (value1 > value2) return(1);
9217		if (value1 < value2) return(-1);
9218		return(0);
9219	},
9220
9221	sortSelect: function(select_id)
9222	{
9223		var oSelect = (typeof(select_id) == 'string' || select_id instanceof String? document.getElementById(select_id) : select_id);
9224		if(oSelect)
9225		{
9226			var myOptions = [];
9227			var n = oSelect.options.length;
9228			for (var i=0;i<n;i++)
9229			{
9230				myOptions[i] = {
9231					optText:oSelect[i].text,
9232					optValue:oSelect[i].value
9233				};
9234			}
9235			myOptions.sort(this.optionCompare);
9236			oSelect.length=0;
9237			n = myOptions.length;
9238			for(var i=0;i<n;i++)
9239			{
9240				var newoption = new Option(myOptions[i].optText, myOptions[i].optValue, false, false);
9241				oSelect[i]=newoption;
9242			}
9243		}
9244	},
9245
9246	selectAllOptions: function(select_id)
9247	{
9248		var oSelect = (typeof(select_id) == 'string' || select_id instanceof String? document.getElementById(select_id) : select_id);
9249		if(oSelect)
9250		{
9251			var n = oSelect.length;
9252			for(var i=0;i<n;i++)
9253				oSelect[i].selected=true;
9254		}
9255	},
9256
9257	selectOption: function(select_id, opt_value)
9258	{
9259		var oSelect = (typeof(select_id) == 'string' || select_id instanceof String? document.getElementById(select_id) : select_id);
9260		if(oSelect)
9261		{
9262			var n = oSelect.length;
9263			for(var i=0;i<n;i++)
9264				oSelect[i].selected = (oSelect[i].value == opt_value);
9265		}
9266	},
9267
9268	addSelectedOptions: function(oSelect, to_select_id, check_unique, do_sort)
9269	{
9270		if(!oSelect)
9271			return;
9272		var n = oSelect.length;
9273		for(var i=0; i<n; i++)
9274			if(oSelect[i].selected)
9275				this.addNewOption(to_select_id, oSelect[i].value, oSelect[i].text, do_sort, check_unique);
9276	},
9277
9278	moveOptionsUp: function(oSelect)
9279	{
9280		if(!oSelect)
9281			return;
9282		var n = oSelect.length;
9283		for(var i=0; i<n; i++)
9284		{
9285			if(oSelect[i].selected && i>0 && oSelect[i-1].selected == false)
9286			{
9287				var option1 = new Option(oSelect[i].text, oSelect[i].value);
9288				var option2 = new Option(oSelect[i-1].text, oSelect[i-1].value);
9289				oSelect[i] = option2;
9290				oSelect[i].selected = false;
9291				oSelect[i-1] = option1;
9292				oSelect[i-1].selected = true;
9293			}
9294		}
9295	},
9296
9297	moveOptionsDown: function(oSelect)
9298	{
9299		if(!oSelect)
9300			return;
9301		var n = oSelect.length;
9302		for(var i=n-1; i>=0; i--)
9303		{
9304			if(oSelect[i].selected && i<n-1 && oSelect[i+1].selected == false)
9305			{
9306				var option1 = new Option(oSelect[i].text, oSelect[i].value);
9307				var option2 = new Option(oSelect[i+1].text, oSelect[i+1].value);
9308				oSelect[i] = option2;
9309				oSelect[i].selected = false;
9310				oSelect[i+1] = option1;
9311				oSelect[i+1].selected = true;
9312			}
9313		}
9314	}
9315
9316}
9317
9318/************************************************/
9319
9320/* End */
9321;

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.