PageSourceSearch

https://dvernik.ru/bitrix/js/main/core/core_date.js

js dvernik.ru collected 2026-09-29 17:22:07 UTC 36,080 bytes, 1,442 lines download raw bytes

1;(function(){
2
3if (BX.date)
4	return;
5
6BX.date = BX.Main.Date;
7
8/************************************** calendar class **********************************/
9
10var obCalendarSingleton = null;
11
12/*
13params: {
14	node: bind element || document.body
15
16	value - start value in site format (using 'field' param if 'value' does not exist)
17	callback - date check handler. can return false to prevent calendar closing.
18	callback_after - another handler, called after date picking
19
20	field - field to read/write data
21
22	bTime = true - whether to enable time control
23	bHideTime = false - whether to hide time control by default
24
25	currentTime - current UTC time()
26
27}
28*/
29
30
31BX.calendar = function(params)
32{
33	return BX.calendar.get().Show(params);
34};
35
36BX.calendar.get = function()
37{
38	if (!obCalendarSingleton)
39		obCalendarSingleton = new BX.JCCalendar();
40
41	return obCalendarSingleton;
42};
43
44// simple func for compatibility with the oldies
45BX.calendar.InsertDaysBack = function(input, days)
46{
47	if (days != '')
48	{
49		var d = new Date();
50		if(days > 0)
51		{
52			d.setTime(d.valueOf() - days*86400000);
53		}
54
55		input.value = BX.date.format(BX.date.convertBitrixFormat(BX.message('FORMAT_DATE')), d, null);
56	}
57	else
58	{
59		input.value = '';
60	}
61};
62
63BX.calendar.ValueToString = function(value, bTime, bUTC)
64{
65	return BX.date.format(
66		BX.date.convertBitrixFormat(BX.message(bTime ? 'FORMAT_DATETIME' : 'FORMAT_DATE')),
67		value,
68		null,
69		!!bUTC
70	);
71};
72
73BX.calendar.ValueToStringFormat = function(value, bitrixFormat, bUTC)
74{
75	return BX.date.format(
76		BX.date.convertBitrixFormat(bitrixFormat),
77		value,
78		null,
79		!!bUTC
80	);
81};
82
83
84BX.CalendarPeriod =
85{
86	Init: function(inputFrom, inputTo, selPeriod)
87	{
88		if((inputFrom.value != "" || inputTo.value != "") && selPeriod.value == "")
89			selPeriod.value = "interval";
90
91		selPeriod.onchange();
92	},
93
94	ChangeDirectOpts: function(peroidValue, selPParent) // "week" || "others"
95	{
96		var selDirect = BX.findChild(selPParent, {'className':'adm-select adm-calendar-direction'}, true);
97
98		if(peroidValue == "week")
99		{
100			selDirect.options[0].text = BX.message('JSADM_CALEND_PREV_WEEK');
101			selDirect.options[1].text = BX.message('JSADM_CALEND_CURR_WEEK');
102			selDirect.options[2].text = BX.message('JSADM_CALEND_NEXT_WEEK');
103		}
104		else
105		{
106			selDirect.options[0].text = BX.message('JSADM_CALEND_PREV');
107			selDirect.options[1].text = BX.message('JSADM_CALEND_CURR');
108			selDirect.options[2].text = BX.message('JSADM_CALEND_NEXT');
109		}
110	},
111
112	SaveAndClearInput: function(oInput)
113	{
114		if(!window.SavedPeriodValues)
115			window.SavedPeriodValues = {};
116
117		window.SavedPeriodValues[oInput.id] = oInput.value;
118		oInput.value="";
119	},
120
121	RestoreInput: function(oInput)
122	{
123		if(!window.SavedPeriodValues || !window.SavedPeriodValues[oInput.id])
124			return;
125
126		oInput.value = window.SavedPeriodValues[oInput.id];
127		delete(window.SavedPeriodValues[oInput.id]);
128	},
129
130	OnChangeP: function(sel)
131	{
132		var selPParent = sel.parentNode.parentNode;
133		var bShowFrom, bShowTo, bShowDirect, bShowSeparate;
134		bShowFrom = bShowTo = bShowDirect = bShowSeparate = false;
135
136		var inputFromWrap = BX.findChild(selPParent, {'className':'adm-input-wrap adm-calendar-inp adm-calendar-first'});
137		var inputToWrap = BX.findChild(selPParent, {'className':'adm-input-wrap adm-calendar-second'});
138		var selDirectWrap = BX.findChild(selPParent, {'className':'adm-select-wrap adm-calendar-direction'});
139		var separator = BX.findChild(selPParent, {'className':'adm-calendar-separate'});
140		var inputFrom = BX.findChild(selPParent, {'className':'adm-input adm-calendar-from'},true);
141		var inputTo = BX.findChild(selPParent, {'className':'adm-input adm-calendar-to'},true);
142
143		// define who must be shown
144		switch (sel.value)
145		{
146			case "day":
147			case "week":
148			case "month":
149			case "quarter":
150			case "year":
151				bShowDirect=true;
152				BX.CalendarPeriod.OnChangeD(selDirectWrap.children[0]);
153				break;
154
155			case "before":
156				bShowTo = true;
157				break;
158
159			case "after":
160				bShowFrom = true;
161				break;
162
163			case "exact":
164				bShowFrom= true;
165				break;
166
167			case "interval":
168				bShowFrom = bShowTo = bShowSeparate = true;
169				BX.CalendarPeriod.RestoreInput(inputFrom);
170				BX.CalendarPeriod.RestoreInput(inputTo);
171
172				break;
173
174			case "":
175				BX.CalendarPeriod.SaveAndClearInput(inputFrom);
176				BX.CalendarPeriod.SaveAndClearInput(inputTo);
177				break;
178
179			default:
180				break;
181
182		}
183
184		BX.CalendarPeriod.ChangeDirectOpts(sel.value, selPParent);
185
186		inputFromWrap.style.display = (bShowFrom? 'inline-block':'none');
187		inputToWrap.style.display = (bShowTo? 'inline-block':'none');
188		selDirectWrap.style.display = (bShowDirect? 'inline-block':'none');
189		separator.style.display = (bShowSeparate? 'inline-block':'none');
190	},
191
192
193	OnChangeD: function(sel)
194	{
195		var selPParent = sel.parentNode.parentNode;
196		var inputFrom = BX.findChild(selPParent, {'className':'adm-input adm-calendar-from'},true);
197		var inputTo = BX.findChild(selPParent, {'className':'adm-input adm-calendar-to'},true);
198		var selPeriod = BX.findChild(selPParent, {'className':'adm-select adm-calendar-period'},true);
199
200		var offset=0;
201
202		switch (sel.value)
203		{
204			case "previous":
205				offset = -1;
206				break;
207
208			case "next":
209				offset = 1;
210				break;
211
212			case "current":
213			default:
214				break;
215
216		}
217
218		var from = false;
219		var to = false;
220
221		var today = new Date();
222		var year = today.getFullYear();
223		var month = today.getMonth();
224		var day = today.getDate();
225		var dayW = today.getDay();
226
227		if (dayW == 0)
228				dayW = 7;
229
230		switch (selPeriod.value)
231		{
232			case "day":
233				from = new Date(year, month, day+offset, 0, 0, 0);
234				to = new Date(year, month, day+offset, 23, 59, 59);
235				break;
236
237			case "week":
238				from = new Date(year, month, day-dayW+1+offset*7, 0, 0, 0);
239				to = new Date(year, month, day+(7-dayW)+offset*7, 23, 59, 59);
240				break;
241
242			case "month":
243				from = new Date(year, month+offset, 1, 0, 0, 0);
244				to = new Date(year, month+1+offset, 0, 23, 59, 59);
245				break;
246
247			case "quarter":
248				var quarterNum = Math.floor((month/3))+offset;
249				from = new Date(year, 3*(quarterNum), 1, 0, 0, 0);
250				to = new Date(year, 3*(quarterNum+1), 0, 23, 59, 59);
251				break;
252
253			case "year":
254				from = new Date(year+offset, 0, 1, 0, 0, 0);
255				to = new Date(year+1+offset, 0, 0, 23, 59, 59);
256				break;
257
258			default:
259				break;
260		}
261
262		var format = window[inputFrom.name+"_bTime"] ? BX.message('FORMAT_DATETIME') : BX.message('FORMAT_DATE');
263
264		if(from)
265		{
266			inputFrom.value = BX.formatDate(from, format);
267			BX.addClass(inputFrom,"adm-calendar-inp-setted");
268		}
269
270		if(to)
271		{
272			inputTo.value = BX.formatDate(to, format);
273			BX.addClass(inputTo,"adm-calendar-inp-setted");
274		}
275	}
276};
277
278
279BX.JCCalendar = function()
280{
281	this.params = {};
282
283	this.bAmPm = BX.isAmPmMode();
284
285	this.popup = null;
286	this.popup_month = null;
287	this.popup_year = null;
288	this.month_popup_classname = '';
289	this.year_popup_classname = '';
290	this.value = null;
291	this._layers = {};
292	this._current_layer = null;
293
294	this.DIV = null;
295	this.PARTS = {};
296
297	this.weekStart = 0;
298	this.numRows = 6;
299
300	this._create = function(params)
301	{
302		this.popup = new BX.PopupWindow('calendar_popup_' + Math.random(), params.node, {
303			closeByEsc: true,
304			autoHide: false,
305			content: this._get_content(),
306			bindOptions: {forceBindPosition: true}
307		});
308
309		BX.bind(this.popup.popupContainer, 'click', function(event) {
310			event.stopPropagation();
311		});
312	};
313
314	this._auto_hide_disable = function()
315	{
316		BX.unbind(document, 'click', BX.proxy(this._auto_hide, this));
317	};
318
319	this._auto_hide_enable = function()
320	{
321		BX.bind(document, 'click', BX.proxy(this._auto_hide, this));
322	};
323
324	this._auto_hide = function(e)
325	{
326		this._auto_hide_disable();
327		this.popup.close();
328	};
329
330	this._get_content = function()
331	{
332		var _layer_onclick = BX.delegate(function(e) {
333			e = e||window.event;
334			this.SetDate(
335				new Date(parseInt(BX.proxy_context.getAttribute('data-date'))),
336				(e.type === 'dblclick' || (this.params.bCompatibility && !this.params.bTimeVisibility))
337			)
338		}, this);
339
340		this.DIV = BX.create('DIV', {
341			props: {className: 'bx-calendar'},
342			children: [
343				BX.create('DIV', {
344					props: {
345						className: 'bx-calendar-header'
346					},
347					children: [
348						BX.create('A', {
349							attrs: {href: 'javascript:void(0)'},
350							props: {className: 'bx-calendar-left-arrow'},
351							events: {click: BX.proxy(this._prev, this)}
352						}),
353
354						BX.create('SPAN', {
355							props: {className: 'bx-calendar-header-content'},
356							children: [
357								(this.PARTS.MONTH = BX.create('A', {
358									attrs: {href: 'javascript:void(0)'},
359									props: {className: 'bx-calendar-top-month'},
360									events: {click: BX.proxy(this._menu_month, this)}
361								})),
362
363								(this.PARTS.YEAR = BX.create('A', {
364									attrs: {href: 'javascript:void(0)'},
365									props: {className: 'bx-calendar-top-year'},
366									events: {click: BX.proxy(this._menu_year, this)}
367								}))
368							]
369						}),
370
371						BX.create('A', {
372							attrs: {href: 'javascript:void(0)'},
373							props: {className: 'bx-calendar-right-arrow'},
374							events: {click: BX.proxy(this._next, this)}
375						})
376					]
377				}),
378
379				(this.PARTS.WEEK = BX.create('DIV', {
380					props: {
381						className: 'bx-calendar-name-day-wrap'
382					}
383				})),
384
385				(this.PARTS.LAYERS = BX.create('DIV', {
386					props: {
387						className: 'bx-calendar-cell-block'
388					},
389					events: {
390						click: BX.delegateEvent({className: 'bx-calendar-cell'}, _layer_onclick),
391						dblclick: BX.delegateEvent({className: 'bx-calendar-cell'}, _layer_onclick)
392					}
393				})),
394
395				(this.PARTS.TIME = BX.create('DIV', {
396					props: {
397						className: 'bx-calendar-set-time-wrap'
398					},
399					events: {
400						click: BX.delegateEvent(
401							{attr: 'data-action'},
402							BX.delegate(this._time_actions, this)
403						)
404					},
405					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>'
406				})),
407
408				(this.PARTS.BUTTONS = BX.create('DIV', {
409					props: {className: 'bx-calendar-button-block'},
410					events: {
411						click: BX.delegateEvent(
412							{attr: 'data-action'},
413							BX.delegate(this._button_actions, this)
414						)
415					},
416					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>'
417				}))
418			]
419		});
420
421		this.PARTS.TIME_INPUT_H = BX.findChild(this.PARTS.TIME, {tag: 'INPUT'}, true);
422		this.PARTS.TIME_INPUT_M = this.PARTS.TIME_INPUT_H.nextSibling.nextSibling;
423
424		if (this.bAmPm)
425			this.PARTS.TIME_AMPM = this.PARTS.TIME_INPUT_M.nextSibling.firstChild;
426
427		var spinner = (new BX.JCSpinner({
428			input: this.PARTS.TIME_INPUT_H,
429			callback_change: BX.proxy(this._check_time, this),
430			bSaveValue: false
431		})).Show();
432		spinner.className = 'bx-calendar-form-arrow-l';
433		this.PARTS.TIME_INPUT_H.parentNode.insertBefore(spinner, this.PARTS.TIME_INPUT_H);
434
435		spinner = (new BX.JCSpinner({
436			input: this.PARTS.TIME_INPUT_M,
437			callback_change: BX.proxy(this._check_time, this),
438			bSaveValue: true
439		})).Show();
440		spinner.className = 'bx-calendar-form-arrow-r';
441		if (!this.PARTS.TIME_INPUT_M.nextSibling)
442			this.PARTS.TIME_INPUT_M.parentNode.appendChild(spinner);
443		else
444			this.PARTS.TIME_INPUT_M.parentNode.insertBefore(spinner, this.PARTS.TIME_INPUT_M.nextSibling);
445
446		for (var i = 0; i < 7; i++)
447		{
448			this.PARTS.WEEK.appendChild(BX.create('SPAN', {
449				props: {
450					className: 'bx-calendar-name-day'
451				},
452				text: BX.message('DOW_' + ((i + this.weekStart) % 7))
453			}));
454		}
455
456		return this.DIV;
457	};
458
459	this._time_actions = function()
460	{
461		switch (BX.proxy_context.getAttribute('data-action'))
462		{
463			case 'time_show':
464				BX.addClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
465				if (this.params.bCompatibility)
466				{
467					BX.removeClass(this.PARTS.BUTTONS, 'bx-calendar-buttons-disabled');
468				}
469				this.popup.adjustPosition();
470			break;
471			case 'time_hide':
472				BX.removeClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
473				if (this.params.bCompatibility)
474				{
475					this._saveChoice('hide');
476					BX.addClass(this.PARTS.BUTTONS, 'bx-calendar-buttons-disabled');
477				}
478				this.popup.adjustPosition();
479			break;
480			case 'time_ampm':
481				this.PARTS.TIME_AMPM.innerHTML = this.PARTS.TIME_AMPM.innerHTML == 'AM' ? 'PM' : 'AM';
482			break;
483			case 'time_ampm_up':
484				this._check_time({bSaveValue: false}, null, 12);
485				return;
486			break;
487			case 'time_ampm_down':
488				this._check_time({bSaveValue: false}, null, -12);
489				return;
490			break;
491		}
492
493		this._check_time();
494	};
495
496	this._button_actions = function()
497	{
498		switch (BX.proxy_context.getAttribute('data-action'))
499		{
500			case 'submit':
501				if (this.params.bCompatibility)
502				{
503					this._saveChoice('show');
504				}
505				this.SaveValue();
506			break;
507			case 'cancel':
508				this.Close();
509			break;
510		}
511	};
512
513	this._saveChoice = function(state)
514	{
515		if (this.params.bCategoryTimeVisibilityOption)
516		{
517			BX.userOptions.save(
518				this.params.bCategoryTimeVisibilityOption,
519				this.params.bNameTimeVisibilityOption,
520				'visibility',
521				(state === 'show' ? 'Y' : 'N')
522			);
523		}
524
525		this._bTimeVisibility = (state === 'show');
526		this.params.bTimeVisibility = this._bTimeVisibility;
527	};
528
529	this._check_time = function(params, value, direction)
530	{
531		var h = parseInt(this.PARTS.TIME_INPUT_H.value.substring(0,5),10)||0,
532			m = parseInt(this.PARTS.TIME_INPUT_M.value.substring(0,5),10)||0,
533			bChanged = false;
534
535		if (!!params && !params.bSaveValue)
536		{
537			this.value.setUTCHours(this.value.getUTCHours() + direction);
538		}
539		else if (!isNaN(h))
540		{
541			if (this.bAmPm)
542			{
543				if (h != 12 && this.PARTS.TIME_AMPM.innerHTML == 'PM')
544				{
545					h += 12;
546				}
547			}
548
549			bChanged = true;
550			this.value.setUTCHours(h % 24);
551		}
552
553		if (!isNaN(m))
554		{
555			bChanged = true;
556			this.value.setUTCMinutes(m % 60);
557		}
558
559		if (bChanged)
560		{
561			this.SetValue(this.value);
562		}
563	};
564
565	this._set_layer = function()
566	{
567		var layerId = parseInt(this.value.getUTCFullYear() + '' + BX.util.str_pad_left(this.value.getUTCMonth()+'', 2, "0"));
568
569		if (!this._layers[layerId])
570		{
571			this._layers[layerId] = this._create_layer();
572			this._layers[layerId].BXLAYERID = layerId;
573		}
574
575		if (this._current_layer)
576		{
577			var v = new Date(this.value.valueOf());
578			v.setUTCHours(0); v.setUTCMinutes(0);
579
580			var cur_value = BX.findChild(this._layers[layerId], {
581					tag: 'A',
582					className: 'bx-calendar-active'
583				}, true),
584				new_value = BX.findChild(this._layers[layerId], {
585					tag: 'A',
586					attr: {
587						'data-date' : v.valueOf() + ''
588					}
589				}, true);
590
591			if (cur_value)
592			{
593				BX.removeClass(cur_value, 'bx-calendar-active');
594			}
595
596			if (new_value)
597			{
598				BX.addClass(new_value, 'bx-calendar-active');
599			}
600
601			this._replace_layer(this._current_layer, this._layers[layerId]);
602		}
603		else
604		{
605			this.PARTS.LAYERS.appendChild(this._layers[layerId]);
606		}
607
608		this._current_layer = this._layers[layerId];
609	};
610
611	this._replace_layer = function(old_layer, new_layer)
612	{
613		if (old_layer != new_layer)
614		{
615			if (!BX.browser.IsIE() || BX.browser.IsDoctype())
616			{
617				var dir = old_layer.BXLAYERID > new_layer.BXLAYERID ? 1 : -1;
618
619				var old_top = 0;
620				var new_top = -dir * old_layer.offsetHeight;
621
622				old_layer.style.position = 'relative';
623				old_layer.style.top = "0px";
624				old_layer.style.zIndex = 5;
625
626				new_layer.style.position = 'absolute';
627				new_layer.style.top = new_top + 'px';
628				new_layer.style.zIndex = 6;
629
630				this.PARTS.LAYERS.appendChild(new_layer);
631
632				var delta = 15;
633
634				var f;
635				(f = function() {
636					new_top += dir * delta;
637					old_top += dir * delta;
638
639					if (dir * new_top < 0)
640					{
641						old_layer.style.top = old_top + 'px';
642						new_layer.style.top = new_top + 'px';
643						setTimeout(f, 10);
644					}
645					else
646					{
647						old_layer.parentNode.removeChild(old_layer);
648
649						new_layer.style.top = "0px";
650						new_layer.style.position = 'static';
651						new_layer.style.zIndex = 0;
652					}
653				})();
654			}
655			else
656			{
657				this.PARTS.LAYERS.replaceChild(new_layer, old_layer);
658			}
659		}
660	};
661
662	this._create_layer = function()
663	{
664		var l = BX.create('DIV', {
665			props: {
666				className: 'bx-calendar-layer'
667			}
668		});
669
670		var month_start = new Date(this.value);
671		month_start.setUTCHours(0);
672		month_start.setUTCMinutes(0);
673
674		month_start.setUTCDate(1);
675
676		if (month_start.getUTCDay() != this.weekStart)
677		{
678			var d = month_start.getUTCDay() - this.weekStart;
679			d += d < 0 ? 7 : 0;
680			month_start.setUTCDate(month_start.getUTCDate()-d);
681		}
682
683		var cur_month = this.value.getUTCMonth(),
684			cur_day = this.value.getUTCDate(),
685			s = '';
686		for (var i = 0; i < this.numRows; i++)
687		{
688			s += '<div class="bx-calendar-range'
689				+(i == this.numRows-1 ? ' bx-calendar-range-noline' : '')
690				+'">';
691
692			for (var j = 0; j < 7; j++)
693			{
694				d = month_start.getUTCDate();
695				var wd = month_start.getUTCDay();
696				var className = 'bx-calendar-cell';
697
698				if (cur_month != month_start.getUTCMonth())
699					className += ' bx-calendar-date-hidden';
700				else if (cur_day == d)
701					className += ' bx-calendar-active';
702
703
704				if (wd == 0 || wd == 6)
705					className += ' bx-calendar-weekend';
706
707				s += '<a href="javascript:void(0)" class="'+className+'" data-date="' + month_start.valueOf() + '">' + d + '</a>';
708
709				month_start.setUTCDate(month_start.getUTCDate()+1);
710			}
711			s += '</div>';
712		}
713
714		l.innerHTML = s;
715
716		return l;
717	};
718
719	this._prev = function()
720	{
721		this.SetMonth(this.value.getUTCMonth()-1);
722	};
723
724	this._next = function()
725	{
726		this.SetMonth(this.value.getUTCMonth()+1);
727	};
728
729	this._menu_month_content = function()
730	{
731		var months = '', cur_month = this.value.getMonth(), i;
732		for (i = 0; i < 12; i++)
733		{
734			months += '<span class="bx-calendar-month'+(i == cur_month ? ' bx-calendar-month-active' : '')+'" data-bx-month="' + i + '">' + BX.message('MONTH_' + (i + 1)) + '</span>';
735		}
736
737		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>';
738	};
739
740	this._menu_month = function()
741	{
742		if (!this.popup_month)
743		{
744			this.popup_month = new BX.PopupWindow(
745				'calendar_popup_month_' + Math.random(), this.PARTS.MONTH,
746				{
747					content: this._menu_month_content(),
748					closeByEsc: true,
749					autoHide: true,
750					offsetTop: -29,
751					offsetLeft: -1,
752					className: this.month_popup_classname,
753					events: {
754						onPopupShow: BX.delegate(function() {
755							if (this.popup_year)
756							{
757								this.popup_year.close();
758							}
759						}, this)
760					}
761				}
762			);
763
764			BX.bind(this.popup_month.popupContainer, 'click', BX.proxy(this.month_popup_click, this));
765			this.popup_month.BXMONTH = this.value.getUTCMonth();
766		}
767		else if (this.popup_month.BXMONTH != this.value.getUTCMonth())
768		{
769			this.popup_month.setContent(this._menu_month_content());
770			this.popup_month.BXMONTH = this.value.getUTCMonth();
771		}
772
773		this.popup_month.show();
774	};
775
776	this.month_popup_click = function(e)
777	{
778		var target = e.target || e.srcElement;
779		if (target && target.getAttribute && target.getAttribute('data-bx-month'))
780		{
781			this.SetMonth(parseInt(target.getAttribute('data-bx-month')));
782			this.popup_month.close();
783		}
784	};
785
786	this._menu_year_content = function()
787	{
788		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">';
789
790		for (var i=-3; i <= 3; i++)
791		{
792			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>';
793		}
794
795		s += '</div><input data-bx-year-input="Y" type="text" class="bx-calendar-year-input" maxlength="4" /></div>';
796
797		return s;
798	};
799
800	this._menu_year = function()
801	{
802		if (!this.popup_year)
803		{
804			this.popup_year = new BX.PopupWindow(
805				'calendar_popup_year_' + Math.random(), this.PARTS.YEAR,
806				{
807					content: this._menu_year_content(),
808					closeByEsc: true,
809					autoHide: true,
810					offsetTop: -29,
811					offsetLeft: -1,
812					className: this.year_popup_classname,
813					events: {
814						onPopupShow: BX.delegate(function() {
815							if (this.popup_month)
816							{
817								this.popup_month.close();
818							}
819						}, this)
820					}
821				}
822			);
823
824			BX.bind(this.popup_year.popupContainer, 'click', BX.proxy(this.year_popup_click, this));
825			BX.bind(this.popup_year.popupContainer, 'keyup', BX.proxy(this.year_popup_keyup, this));
826			this.popup_year.BXYEAR = this.value.getUTCFullYear();
827		}
828		else if (this.popup_year.BXYEAR != this.value.getUTCFullYear())
829		{
830			this.popup_year.setContent(this._menu_year_content());
831			this.popup_year.BXYEAR = this.value.getUTCFullYear();
832		}
833
834		this.popup_year.show();
835	};
836
837	this.year_popup_click = function(e)
838	{
839		var target = e.target || e.srcElement;
840		if (target && target.getAttribute && target.getAttribute('data-bx-year'))
841		{
842			this.SetYear(parseInt(target.getAttribute('data-bx-year')));
843			this.popup_year.close();
844		}
845	};
846	this.year_popup_keyup = function(e)
847	{
848		var target = e.target || e.srcElement;
849		if (target && target.getAttribute && target.getAttribute('data-bx-year-input') == 'Y')
850		{
851			var value = parseInt(target.value);
852			if(value >= 1900 && value <= 2100)
853			{
854				this.SetYear(value);
855				this.popup_year.close();
856			}
857		}
858	};
859
860	this._check_date = function(v)
861	{
862		var res = v;
863
864		if (BX.type.isString(v))
865		{
866			res = BX.parseDate(v, true);
867		}
868
869		if (!BX.type.isDate(res) || isNaN(res.valueOf()))
870		{
871			res = BX.date.convertToUTC(new Date());
872			if (this.params.bHideTime)
873			{
874				res.setUTCHours(0);
875				res.setUTCMinutes(0);
876			}
877		}
878
879		res.setUTCMilliseconds(0);
880		res.setUTCSeconds(0);
881
882		res.BXCHECKED = true;
883
884		return res;
885	};
886};
887
888BX.JCCalendar.prototype.Show = function(params)
889{
890	if (!BX.isReady)
891	{
892		BX.ready(BX.delegate(function() {this.Show(params)}, this));
893		return;
894	}
895
896	params.node = params.node||document.body;
897
898	if (BX.type.isNotEmptyString(params.node))
899	{
900		var n = BX(params.node);
901		if (!n)
902		{
903			n = document.getElementsByName(params.node);
904			if (n && n.length > 0)
905			{
906				n = n[0]
907			}
908		}
909		params.node = n;
910	}
911
912	if (!params.node)
913		return;
914
915	if (!!params.field)
916	{
917		if (BX.type.isString(params.field))
918		{
919			n = BX(params.field);
920			if (!!n)
921			{
922				params.field = n;
923			}
924			else
925			{
926				if (params.form)
927				{
928					if (BX.type.isString(params.form))
929					{
930						params.form = document.forms[params.form];
931					}
932				}
933
934				if (BX.type.isDomNode(params.form) && !!params.form[params.field])
935				{
936					params.field = params.form[params.field];
937				}
938				else
939				{
940					n = document.getElementsByName(params.field);
941					if (n && n.length > 0)
942					{
943						n = n[0];
944						params.field = n;
945					}
946				}
947			}
948
949			if (BX.type.isString(params.field))
950			{
951				params.field = BX(params.field);
952			}
953		}
954	}
955
956	var bShow = !this.popup || !this.popup.isShown() || this.params.node != params.node;
957
958	this.params = params;
959
960	this.params.bCompatibility = (typeof this.params.bCompatibility == 'undefined' ? false : this.params.bCompatibility);
961	this.params.bTimeVisibility = (typeof this.params.bTimeVisibility == 'undefined' ? !this.params.bCompatibility : this.params.bTimeVisibility);
962	if (this.params.bCompatibility)
963	{
964		this.params.bCategoryTimeVisibilityOption = (
965			this.params.bCategoryTimeVisibilityOption ? this.params.bCategoryTimeVisibilityOption : ''
966		);
967		this.params.bNameTimeVisibilityOption = (
968			this.params.bNameTimeVisibilityOption ? this.params.bNameTimeVisibilityOption : 'time_visibility'
969		);
970
971		if (typeof this._bTimeVisibility !== 'undefined')
972		{
973			this.params.bTimeVisibility = this._bTimeVisibility;
974		}
975	}
976
977	this.params.bTime = typeof this.params.bTime == 'undefined' ? true : !!this.params.bTime;
978	this.params.bHideTime = typeof this.params.bHideTime == 'undefined' ? true : !!this.params.bHideTime;
979	this.params.bUseSecond = typeof this.params.bUseSecond == 'undefined' ? true : !!this.params.bUseSecond;
980
981	this.weekStart = parseInt(this.params.weekStart || this.params.weekStart || BX.message('WEEK_START'));
982	if (isNaN(this.weekStart))
983		this.weekStart = 1;
984
985	if (!this.popup)
986	{
987		this._create(this.params);
988	}
989	else
990	{
991		this.popup.setBindElement(this.params.node);
992	}
993
994	var bHideTime = !!this.params.bHideTime;
995	if (this.params.value)
996	{
997		this.SetValue(this.params.value);
998		bHideTime = this.value.getUTCHours() <= 0 && this.value.getUTCMinutes() <= 0;
999	}
1000	else if (this.params.field)
1001	{
1002		this.SetValue(this.params.field.value);
1003		bHideTime = this.value.getUTCHours() <= 0 && this.value.getUTCMinutes() <= 0;
1004	}
1005	else if (!!this.params.currentTime)
1006	{
1007		this.SetValue(this.params.currentTime);
1008	}
1009	else
1010	{
1011		this.SetValue();
1012	}
1013
1014	if (!!this.params.bTime)
1015	{
1016		this.activateTimeStyle(bHideTime);
1017	}
1018	else
1019	{
1020		this.activateDateStyle(bHideTime);
1021	}
1022
1023	if (bShow)
1024	{
1025		this._auto_hide_disable();
1026		this.popup.show();
1027		setTimeout(BX.proxy(this._auto_hide_enable, this), 0);
1028	}
1029
1030	this.params.bSetFocus = typeof this.params.bSetFocus == 'undefined' ? true : !!this.params.bSetFocus;
1031	if(this.params.bSetFocus)
1032	{
1033		params.node.blur();
1034	}
1035	else
1036	{
1037		BX.bind(params.node, 'keyup', BX.defer(function(){
1038			this.SetValue(params.node.value);
1039			if(!!this.params.bTime)
1040			{
1041				if(this.value.getUTCHours() <= 0 && this.value.getUTCMinutes() <= 0)
1042					BX.removeClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
1043				else
1044					BX.addClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
1045			}
1046		}, this));
1047	}
1048
1049	return this;
1050};
1051
1052BX.JCCalendar.prototype.activateDateStyle = function(bHideTime)
1053{
1054	BX.addClass(this.DIV, 'bx-calendar-time-disabled');
1055
1056	if (!!bHideTime)
1057		BX.removeClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
1058	else
1059		BX.addClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
1060};
1061
1062BX.JCCalendar.prototype.activateTimeStyle = function(bHideTime)
1063{
1064	if (this.params.bCompatibility && !this.params.bTimeVisibility)
1065	{
1066		BX.addClass(this.PARTS.BUTTONS, 'bx-calendar-buttons-disabled');
1067		BX.addClass(this.PARTS.TIME, 'bx-calendar-set-time-wrap-simple');
1068		BX.removeClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
1069	}
1070	else
1071	{
1072		BX.removeClass(this.DIV, 'bx-calendar-time-disabled');
1073
1074		if (!!bHideTime)
1075			BX.removeClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
1076		else
1077			BX.addClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
1078	}
1079};
1080
1081BX.JCCalendar.prototype.SetDay = function(d)
1082{
1083	this.value.setUTCDate(d);
1084	return this.SetValue(this.value);
1085};
1086
1087BX.JCCalendar.prototype.SetMonth = function(m)
1088{
1089	if (this.popup_month)
1090		this.popup_month.close();
1091
1092	this.value.setUTCMonth(m);
1093
1094	if(m < 0)
1095		m += 12;
1096	else if (m >= 12)
1097		m -= 12;
1098
1099	while(this.value.getUTCMonth() > m)
1100	{
1101		this.value.setUTCDate(this.value.getUTCDate()-1);
1102	}
1103
1104	return this.SetValue(this.value);
1105};
1106
1107BX.JCCalendar.prototype.SetYear = function(y)
1108{
1109	if (this.popup_year)
1110		this.popup_year.close();
1111	this.value.setUTCFullYear(y);
1112	return this.SetValue(this.value);
1113};
1114
1115BX.JCCalendar.prototype.SetDate = function(v, bSet)
1116{
1117	v = this._check_date(v);
1118	v.setUTCHours(this.value.getUTCHours());
1119	v.setUTCMinutes(this.value.getUTCMinutes());
1120	v.setUTCSeconds(this.value.getUTCSeconds());
1121
1122	if (this.params.bTime && !bSet)
1123	{
1124		return this.SetValue(v);
1125	}
1126	else
1127	{
1128		this.SetValue(v);
1129		this.SaveValue();
1130	}
1131};
1132
1133BX.JCCalendar.prototype.SetValue = function(v)
1134{
1135	this.value = (v && v.BXCHECKED) ? v : this._check_date(v);
1136
1137	this.PARTS.MONTH.innerHTML = BX.message('MONTH_' + (this.value.getUTCMonth()+1));
1138	this.PARTS.YEAR.innerHTML = this.value.getUTCFullYear();
1139
1140	if (!!this.params.bTime)
1141	{
1142		var h = this.value.getUTCHours();
1143		if (this.bAmPm)
1144		{
1145			if (h >= 12)
1146			{
1147				this.PARTS.TIME_AMPM.innerHTML = 'PM';
1148
1149				if (h != 12)
1150					h -= 12;
1151			}
1152			else
1153			{
1154				this.PARTS.TIME_AMPM.innerHTML = 'AM';
1155
1156				if (h == 0)
1157					h = 12;
1158			}
1159		}
1160
1161		this.PARTS.TIME_INPUT_H.value = BX.util.str_pad_left(h.toString(), 2, "0");
1162		this.PARTS.TIME_INPUT_M.value = BX.util.str_pad_left(this.value.getUTCMinutes().toString(), 2, "0");
1163	}
1164
1165	this._set_layer();
1166
1167	return this;
1168};
1169
1170BX.JCCalendar.prototype.SaveValue = function()
1171{
1172	if (this.popup_month)
1173		this.popup_month.close();
1174	if (this.popup_year)
1175		this.popup_year.close();
1176
1177	var bSetValue = true;
1178	if (!!this.params.callback)
1179	{
1180		var res = this.params.callback.apply(this, [new Date(this.value.valueOf()+this.value.getTimezoneOffset()*60000)]);
1181		if (res === false)
1182			bSetValue = false;
1183	}
1184
1185	if (bSetValue)
1186	{
1187		var bTime = !!this.params.bTime && BX.hasClass(this.PARTS.TIME, 'bx-calendar-set-time-opened');
1188
1189		if (this.params.field)
1190		{
1191			var format = BX.message(bTime ? 'FORMAT_DATETIME' : 'FORMAT_DATE');
1192
1193			if(bTime && !this.params.bUseSecond)
1194			{
1195				format = format.replace(':SS', '');
1196			}
1197
1198			this.params.field.value = BX.calendar.ValueToStringFormat(this.value, format, true);
1199			BX.fireEvent(this.params.field, 'change');
1200		}
1201
1202		this.popup.close();
1203
1204		if (!!this.params.callback_after)
1205		{
1206			this.params.callback_after.apply(this, [new Date(this.value.valueOf()+this.value.getTimezoneOffset()*60000), bTime]);
1207		}
1208	}
1209
1210	return this;
1211};
1212
1213BX.JCCalendar.prototype.Close = function()
1214{
1215	if (!!this.popup)
1216		this.popup.close();
1217
1218	return this;
1219};
1220
1221BX.JCSpinner = function(params)
1222{
1223	params = params || {};
1224	this.params = {
1225		input: params.input || null,
1226
1227		delta: params.delta || 1,
1228
1229		timeout_start: params.timeout_start || 1000,
1230		timeout_cont: params.timeout_cont || 150,
1231
1232		callback_start: params.callback_start || null,
1233		callback_change: params.callback_change || null,
1234		callback_finish: params.callback_finish || null,
1235
1236		bSaveValue: typeof params.bSaveValue == 'undefined' ? !!params.input : !!params.bSaveValue
1237	};
1238
1239	this.mousedown = false;
1240	this.direction = 1;
1241};
1242
1243BX.JCSpinner.prototype.Show = function()
1244{
1245	this.node = BX.create('span', {
1246		events: {
1247			mousedown: BX.delegateEvent(
1248				{attr: 'data-dir'},
1249				BX.delegate(this.Start, this)
1250			)
1251		},
1252		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>'
1253	});
1254	return this.node;
1255};
1256
1257BX.JCSpinner.prototype.Start = function()
1258{
1259	this.mousedown = true;
1260	this.direction = BX.proxy_context.getAttribute('data-dir') > 0 ? 1 : -1;
1261	BX.bind(document, "mouseup", BX.proxy(this.MouseUp, this));
1262	this.ChangeValue(true);
1263};
1264
1265BX.JCSpinner.prototype.ChangeValue = function(bFirst)
1266{
1267	if(!this.mousedown)
1268		return;
1269
1270	if (this.params.input)
1271	{
1272		var v = parseInt(this.params.input.value, 10) + this.params.delta * this.direction;
1273
1274		if (this.params.bSaveValue)
1275			this.params.input.value = v;
1276
1277		if (!!bFirst && this.params.callback_start)
1278			this.params.callback_start(this.params, v, this.direction);
1279
1280		if (this.params.callback_change)
1281			this.params.callback_change(this.params, v, this.direction);
1282
1283		setTimeout(
1284			BX.proxy(this.ChangeValue, this),
1285			!!bFirst ? this.params.timeout_start : this.params.timeout_cont
1286		);
1287	}
1288};
1289
1290BX.JCSpinner.prototype.MouseUp = function()
1291{
1292	this.mousedown = false;
1293	BX.unbind(document, "mouseup", BX.proxy(this.MouseUp, this));
1294
1295	if (this.params.callback_finish)
1296		this.params.callback_finish(this.params, this.params.input.value);
1297};
1298
1299/**************** compatibility hacks ***************************/
1300
1301window.jsCalendar = {
1302	Show: function(obj, field, fieldFrom, fieldTo, bTime, serverTime, form_name, bHideTimebar)
1303	{
1304		return BX.calendar({
1305			node: obj, field: field, form: form_name, bTime: !!bTime, currentTime: serverTime, bHideTimebar: !!bHideTimebar
1306		});
1307	},
1308
1309	ValueToString: BX.calendar.ValueToString
1310};
1311
1312
1313/************ clock popup transferred from timeman **************/
1314
1315BX.CClockSelector = function(params)
1316{
1317	this.params = params;
1318
1319	this.params.popup_buttons = this.params.popup_buttons || [
1320		new BX.PopupWindowButton({
1321			text : BX.message('CAL_BUTTON'),
1322			className : "popup-window-button-create",
1323			events : {click : BX.proxy(this.setValue, this)}
1324		})
1325	];
1326
1327	this.isReady = false;
1328
1329	this.WND = new BX.PopupWindow(
1330		this.params.popup_id || 'clock_selector_popup',
1331		this.params.node,
1332		this.params.popup_config || {
1333			titleBar: BX.message('CAL_TIME'),
1334			offsetLeft: -45,
1335			offsetTop: -135,
1336			autoHide: true,
1337			closeIcon: true,
1338			closeByEsc: true
1339		}
1340	);
1341
1342	this.SHOW = false;
1343	BX.addCustomEvent(this.WND, "onPopupClose", BX.delegate(this.onPopupClose, this));
1344
1345	this.obClocks = {};
1346	this.CLOCK_ID = this.params.clock_id || 'clock_selector';
1347};
1348
1349BX.CClockSelector.prototype.Show = function()
1350{
1351	if (!this.isReady)
1352	{
1353		//BX.timeman.showWait(this.parent.DIV);
1354
1355		BX.addCustomEvent('onClockRegister', BX.proxy(this.onClockRegister, this));
1356		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));
1357	}
1358
1359	this.WND.setButtons(this.params.popup_buttons);
1360	this.WND.show();
1361
1362	this.SHOW = true;
1363
1364	if (window['bxClock_' + this.obClocks[this.CLOCK_ID]])
1365	{
1366		setTimeout("window['bxClock_" + this.obClocks[this.CLOCK_ID] + "'].CalculateCoordinates()", 40);
1367	}
1368
1369	return true;
1370};
1371
1372BX.CClockSelector.prototype.onClockRegister = function(obClocks)
1373{
1374	if (obClocks[this.CLOCK_ID])
1375	{
1376		this.obClocks[this.CLOCK_ID] = obClocks[this.CLOCK_ID];
1377		BX.removeCustomEvent('onClockRegister', BX.proxy(this.onClockRegister, this));
1378	}
1379};
1380
1381BX.CClockSelector.prototype.Ready = function(data)
1382{
1383	this.content = this.CreateContent(data);
1384	this.WND.setContent(this.content);
1385
1386	this.isReady = true;
1387	//BX.timeman.closeWait();
1388
1389	setTimeout(BX.proxy(this.Show, this), 30);
1390};
1391
1392BX.CClockSelector.prototype.CreateContent = function(data)
1393{
1394	return BX.create('DIV', {
1395		events: {click: BX.PreventDefault},
1396		html:
1397			'<div class="bx-tm-popup-clock">' + data + '</div>'
1398	});
1399};
1400
1401BX.CClockSelector.prototype.setValue = function(e)
1402{
1403	if (this.params.callback)
1404	{
1405		var input = BX.findChild(this.content, {tagName: 'INPUT'}, true);
1406		this.params.callback.apply(this.params.node, [input.value]);
1407	}
1408
1409	return BX.PreventDefault(e);
1410};
1411
1412BX.CClockSelector.prototype.closeWnd = function(e)
1413{
1414	this.WND.close();
1415	return (e || window.event) ? BX.PreventDefault(e) : true;
1416};
1417
1418BX.CClockSelector.prototype.setNode = function(node)
1419{
1420	this.WND.setBindElement(node);
1421};
1422
1423BX.CClockSelector.prototype.setTime = function(timestamp)
1424{
1425	this.params.start_time = timestamp;
1426	if (window['bxClock_' + this.obClocks[this.CLOCK_ID]])
1427	{
1428		window['bxClock_' +  this.obClocks[this.CLOCK_ID]].SetTime(parseInt(timestamp/3600), parseInt((timestamp%3600)/60));
1429	}
1430};
1431
1432BX.CClockSelector.prototype.setCallback = function(cb)
1433{
1434	this.params.callback = cb;
1435};
1436
1437BX.CClockSelector.prototype.onPopupClose = function()
1438{
1439	this.SHOW = false;
1440};
1441
1442})();

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.