text: ;(function()
  {
  	'use strict';
  
  	BX.namespace('BX.Calendar.UserField');
  
  	if(typeof BX.Calendar.UserField.ResourceBooking !== 'undefined' || !BX.Main.UF || !BX.Main.UF.BaseType)
  	{
  		return;
  	}
  
  	var
  		DAY_LENGTH = 86400000,
  		TIME_FORMAT, TIME_FORMAT_SHORT,
  		DATE_FORMAT = BX.date.convertBitrixFormat(BX.message("FORMAT_DATE")),
  		DATETIME_FORMAT = BX.date.convertBitrixFormat(BX.message("FORMAT_DATETIME"));
  
  	if ((DATETIME_FORMAT.substr(0, DATE_FORMAT.length) === DATE_FORMAT))
  		TIME_FORMAT = BX.util.trim(DATETIME_FORMAT.substr(DATE_FORMAT.length));
  	else
  		TIME_FORMAT = BX.date.convertBitrixFormat(BX.isAmPmMode() ? 'H:MI:SS T' : 'HH:MI:SS');
  	TIME_FORMAT_SHORT = TIME_FORMAT.replace(':s', '');
  
  	BX.Calendar.UserField.ResourceBooking = function(params)
  	{
  		this.params = params;
  
  		this.DOM = {
  			outerWrap: BX(params.controlId),
  			valueInputs: []
  		};
  
  		this.isNew = !this.params.value || !this.params.value.DATE_FROM;
  
  		if (this.params.socnetDestination)
  		{
  			BX.Calendar.UserField.ResourceBooking.prototype.socnetDestination = this.params.socnetDestination;
  		}
  	};
  	BX.extend(BX.Calendar.UserField.ResourceBooking, BX.Main.UF.BaseType);
  
  	BX.Calendar.UserField.ResourceBooking.prototype.showEditLayout = function()
  	{
  		this.allValuesValue = '';
  		this.DOM.dateTimeWrap = this.DOM.outerWrap.appendChild(BX.create("div", {props: { className: "calendar-resourcebook-content-block-detail-wrap calendar-resourcebook-content-block-detail-wrap-flex"}}));
  
  		var
  			dateFrom,
  			duration,
  			defaultDuration = this.params.fullDay ? 1440 : 60, // One day or one hour as default
  			dateTo;
  
  		if (this.isNew)
  		{
  			var params = BX.Calendar.UserField.ResourceBooking.getParamsFromHash(this.params.userfieldId);
  			if (params && params.length > 1)
  			{
  				dateFrom = BX.parseDate(params[0]);
  				dateTo = BX.parseDate(params[1]);
  				if (dateFrom && dateTo)
  				{
  					duration = Math.round(Math.max((dateTo.getTime() - dateFrom.getTime()) / 60000, 0));
  				}
  			}
  
  			if (!dateFrom)
  			{
  				dateFrom = new Date();
  				var
  					roundMin = 30,
  					r = (roundMin || 10) * 60 * 1000,
  					timestamp = Math.ceil(dateFrom.getTime() / r) * r;
  				dateFrom = new Date(timestamp);
  			}
  		}
  		else
  		{
  			dateFrom = BX.parseDate(this.params.value.DATE_FROM);
  			dateTo = BX.parseDate(this.params.value.DATE_TO);
  			duration = Math.round(Math.max((dateTo.getTime() - dateFrom.getTime()) / 60000, 0));
  		}
  
  		if (!duration)
  		{
  			duration = defaultDuration;
  		}
  
  		// region Date
  		this.DOM.dateWrap = this.DOM.dateTimeWrap
  			.appendChild(BX.create("div", {props: { className: "calendar-resourcebook-content-block-detail-inner calendar-resourcebook-content-block-detail-wrap-down"}}))
  			.appendChild(BX.create("div", {
  				props: { className: "calendar-resourcebook-content-block-detail"},
  				html: '<div class="calendar-resourcebook-content-block-title"><span class="calendar-resourcebook-content-block-title-text">' + BX.message('USER_TYPE_RESOURCE_DATE_LABEL') + '</span></div>'
  			}));
  
  		this.DOM.fromInput = this.DOM.dateWrap.appendChild(BX.create('INPUT', {
  			attrs: {
  				value: BX.date.format(DATE_FORMAT, dateFrom.getTime() / 1000),
  				placeholder: BX.message('USER_TYPE_RESOURCE_DATE_LABEL'),
  				type: 'text'
  			},
  			events: {
  				click: BX.proxy(this.showSmallCalendar, this),
  				change: BX.proxy(this.triggerUpdatePlanner, this)
  			},
  			props: {className: 'calendar-resbook-date-input calendar-resbook-field-datetime'}
  		}));
  		// endregion
  
  		// region Time
  		if (!this.params.fullDay)
  		{
  			this.DOM.timeWrap = this.DOM.dateTimeWrap
  				.appendChild(BX.create("div", {props: { className: "calendar-resourcebook-content-block-detail-inner calendar-resourcebook-content-block-detail-wrap-down"}}))
  				.appendChild(BX.create("div", {
  					props: { className: "calendar-resourcebook-content-block-detail"},
  					html: '<div class="calendar-resourcebook-content-block-title"><span class="calendar-resourcebook-content-block-title-text">' + BX.message('USER_TYPE_RESOURCE_TIME_LABEL') + '</span></div>'
  				}));
  
  			this.DOM.timeFromInput = this.DOM.timeWrap.appendChild(BX.create('INPUT', {
  				attrs: {
  					value: BX.date.format(TIME_FORMAT_SHORT, dateFrom.getTime() / 1000),
  					placeholder: BX.message('USER_TYPE_RESOURCE_TIME_LABEL'),
  					type: 'text'
  				},
  				style: {width: '100px'},
  				props: {className: 'calendar-resbook-date-input calendar-resbook-field-datetime-menu'}
  			}));
  
  			this.fromTime = new SelectInput({
  				input: this.DOM.timeFromInput,
  				values: BX.Calendar.UserField.ResourceBooking.getSimpleTimeList(),
  				onChangeCallback: BX.proxy(function()
  				{
  					this.triggerUpdatePlanner();
  				}, this),
  				onAfterMenuOpen: BX.proxy(function(ind, popupMenu)
  				{
  					if (!ind && popupMenu)
  					{
  						var
  							i, menuItem,
  							nearestTimeValue = BX.Calendar.UserField.ResourceBooking.adaptTimeValue({h: dateFrom.getHours(), m: dateFrom.getMinutes()});
  
  						if (nearestTimeValue && nearestTimeValue.label)
  						{
  							for (i = 0; i < popupMenu.menuItems.length; i++)
  							{
  								menuItem = popupMenu.menuItems[i];
  								if (menuItem
  									&& nearestTimeValue.label === menuItem.text
  									&& menuItem.layout)
  								{
  									popupMenu.layout.menuContainer.scrollTop = menuItem.layout.item.offsetTop - 2;
  								}
  							}
  						}
  					}
  				}, this)
  			});
  		}
  		// endregion
  
  		// region Service
  		if (this.params.useServices && BX.type.isArray(this.params.serviceList) && this.params.serviceList.length > 0)
  		{
  			if (this.params.fullDay)
  			{
  				this.DOM.durationWrap = this.DOM.dateTimeWrap;
  			}
  			else
  			{
  				this.DOM.durationWrap = this.DOM.outerWrap.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-detail-wrap calendar-resourcebook-content-block-detail-wrap-flex"}}));
  			}
  
  			this.DOM.servicesWrap = this.DOM.durationWrap
  				.appendChild(BX.create("div", {props: { className: "calendar-resourcebook-content-block-detail-inner calendar-resourcebook-content-block-detail-wrap-down"}}))
  				.appendChild(BX.create("div", {
  					props: { className: "calendar-resourcebook-content-block-detail"},
  					html: '<div class="calendar-resourcebook-content-block-title"><span class="calendar-resourcebook-content-block-title-text">' + BX.message('USER_TYPE_RESOURCE_SERVICE_LABEL') + '</span></div>'
  				}));
  
  			this.DOM.serviceInput = this.DOM.servicesWrap.appendChild(BX.create('INPUT', {
  				attrs: {
  					value: this.params.value.SERVICE_NAME || '',
  					placeholder: BX.message('USER_TYPE_RESOURCE_SERVICE_LABEL'),
  					type: 'text'
  				},
  				style: {width: '200px'},
  				props: {className: 'calendar-resbook-date-input calendar-resbook-field-datetime-menu'}
  			}));
  
  			var serviceListValues = [];
  			this.params.serviceList.forEach(function(service)
  			{
  				if (service.name !== '')
  				{
  					serviceListValues.push({value: service.duration, label: service.name});
  				}
  			});
  
  			if (this.isNew && serviceListValues.length >= 1)
  			{
  				this.DOM.serviceInput.value = serviceListValues[0].label;
  				duration = parseInt(serviceListValues[0].value);
  			}
  
  			this.serviceList = new SelectInput({
  				input: this.DOM.serviceInput,
  				values: serviceListValues,
  				onChangeCallback: BX.proxy(function(state)
  				{
  					if (BX.type.isPlainObject(state) && state.realValue)
  					{
  						this.durationList.setValue(parseInt(state.realValue));
  						this.duration = BX.Calendar.UserField.ResourceBooking.parseDuration(this.DOM.durationInput.value);
  						this.triggerUpdatePlanner();
  					}
  				}, this)
  			});
  		}
  		// endregion
  
  		if (!this.DOM.durationWrap)
  		{
  			this.DOM.durationWrap = this.DOM.dateTimeWrap;
  		}
  
  		// region Duration
  		this.DOM.durationControlWrap = this.DOM.durationWrap
  			.appendChild(BX.create("div", {props: { className: "calendar-resourcebook-content-block-detail-inner calendar-resourcebook-content-block-detail-wrap-down"}}))
  			.appendChild(BX.create("div", {
  				props: { className: "calendar-resourcebook-content-block-detail"},
  				html: '<div class="calendar-resourcebook-content-block-title"><span class="calendar-resourcebook-content-block-title-text">' + BX.message('USER_TYPE_RESOURCE_DURATION_LABEL') + '</span></div>'
  			}));
  
  		this.DOM.durationInput = this.DOM.durationControlWrap.appendChild(BX.create('INPUT', {
  			attrs: {
  				value: duration,
  				placeholder: BX.message('USER_TYPE_RESOURCE_DURATION_LABEL'),
  				type: 'text'
  			},
  			style: {width: '90px'},
  			props: {className: 'calendar-resbook-date-input calendar-resbook-field-datetime-menu'}
  		}));
  
  		this.duration = parseInt(duration);
  		this.durationList = new SelectInput({
  			input: this.DOM.durationInput,
  			values: BX.Calendar.UserField.ResourceBooking.getDurationList(this.params.fullDay),
  			value: duration,
  			onChangeCallback: BX.proxy(function()
  			{
  				this.duration = BX.Calendar.UserField.ResourceBooking.parseDuration(this.DOM.durationInput.value);
  				this.triggerUpdatePlanner();
  			}, this)
  		});
  		// endregion
  
  		BX.bind(this.DOM.outerWrap, 'click', BX.proxy(this.showPlannerPopup, this));
  		BX.bind(this.DOM.fromInput, 'focus', BX.proxy(this.showPlannerPopup, this));
  		BX.bind(this.DOM.durationInput, 'focus', BX.proxy(this.showPlannerPopup, this));
  
  		// region User Selector
  		if (this.params.useUsers)
  		{
  			this.DOM.userSelectorWrap = this.DOM.outerWrap.appendChild(BX.create('DIV', {
  				props: {className: 'calendar-resbook-users-selector-wrap'}
  			}));
  
  			this.DOM.userSelectorWrap = this.DOM.outerWrap.appendChild(BX.create('DIV', {props: {className: 'calendar-resourcebook-content-block-control-field'}}));
  
  			var userSelectorTitle = BX.message('USER_TYPE_RESOURCE_USERS_CONTROL_DEFAULT_NAME');
  			this.DOM.userSelectorWrap
  				.appendChild(BX.create('DIV', {props: {className: 'calendar-resourcebook-content-block-title'}}))
  				.appendChild(BX.create('SPAN', {props: {className: 'calendar-resourcebook-content-block-title-text'}, text: userSelectorTitle}));
  			this.DOM.userListWrap = this.DOM.userSelectorWrap.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-control custom-field-item"}}));
  
  			var itemsSelected = [];
  			if (this.params.value && BX.type.isArray(this.params.value.ENTRIES))
  			{
  				this.params.value.ENTRIES.forEach(function(entry)
  				{
  					if (entry.TYPE === 'user')
  					{
  						itemsSelected.push('U' + parseInt(entry.RESOURCE_ID));
  					}
  				});
  			}
  
  			this.userSelector = new UserSelector({
  				wrapNode: this.DOM.userListWrap,
  				socnetDestination: this.params.socnetDestination,
  				itemsSelected: itemsSelected,
  				addMessage: BX.message('USER_TYPE_RESOURCE_SELECT_USER'),
  				checkLimitCallback: BX.proxy(this.checkResourceCountLimitForNewEntries, this)
  			});
  
  			BX.addCustomEvent('OnResourceBookDestinationAddNewItem', BX.proxy(this.triggerUpdatePlanner, this));
  			BX.addCustomEvent('OnResourceBookDestinationUnselect', BX.proxy(this.triggerUpdatePlanner, this));
  		}
  		// endregion
  
  		// region Resources selector
  		if (this.params.useResources)
  		{
  			this.DOM.resourcesWrap = this.DOM.outerWrap.appendChild(BX.create("div", {props: { className: "calendar-resourcebook-content-block-control-field calendar-resourcebook-content-block-control-field-add" }}));
  
  			var resSelectorTitle = BX.message('USER_TYPE_RESOURCE_RESOURCE_CONTROL_DEFAULT_NAME');
  			this.DOM.resourcesWrap
  				.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-title"}}))
  				.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-title-text"}, text: resSelectorTitle}));
  			this.DOM.resourcesListWrap = this.DOM.resourcesWrap.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-control custom-field-item"}}));
  
  			var values = [];
  			if (this.params.value && BX.type.isArray(this.params.value.ENTRIES))
  			{
  				this.params.value.ENTRIES.forEach(function(entry)
  				{
  					if (entry.TYPE !== 'user')
  					{
  						values.push({
  							type: entry.TYPE,
  							id: parseInt(entry.RESOURCE_ID)
  						});
  					}
  				});
  			}
  
  			this.resourceSelector = new ResourceListSelector({
  				outerWrap: this.DOM.resourcesWrap,
  				blocksWrap: this.DOM.resourcesListWrap,
  				values: values,
  				resourceList: this.params.resourceList,
  				onChangeCallback: BX.proxy(function()
  				{
  					this.triggerUpdatePlanner();
  				}, this),
  				checkLimitCallback: BX.proxy(this.checkResourceCountLimit, this)
  			});
  		}
  		// endregion
  
  		var _this = this;
  		setTimeout(BX.delegate(function(){
  			BX.onCustomEvent(window, 'onCrmEntityEditorUserFieldSetValidator', [this.params.controlId, function(result)
  			{
  				if (!_this.params.allowOverbooking && _this.isOverbooked())
  				{
  					if (result && result.addError && BX.Crm && BX.Crm.EntityValidationError)
  					{
  						result.addError(BX.Crm.EntityValidationError.create({field: this}));
  					}
  				}
  
  				var _validationPromise = new BX.Promise();
  				_validationPromise.fulfill();
  				return _validationPromise;
  			}]);
  		}, this), 100);
  
  		setTimeout(BX.proxy(this.onChangeValues, this), 100);
  
  		// Mantis:107646
  		setTimeout(BX.proxy(function(){
  			BX.fireEvent(this.DOM.fromInput, 'change');
  		}, this), 100);
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.showSmallCalendar = function(e)
  	{
  		var target = e.target || e.srcElement;
  		BX.calendar({node: target, field: target, bTime: false});
  		BX.focus(target);
  		//if (BX.calendar.get().popup)
  		//{
  		//	BX.removeCustomEvent(BX.calendar.get().popup, 'onPopupClose', BX.proxy(_this.allowSliderClose, _this));
  		//}
  		//BX.addCustomEvent(BX.calendar.get().popup, 'onPopupClose', BX.proxy(_this.allowSliderClose, _this));
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.onChangeValues = function()
  	{
  		var
  			allValuesValue = '',
  			formatDatetime = BX.isAmPmMode() ? BX.message("FORMAT_DATETIME").replace(':SS', '') : BX.message("FORMAT_DATETIME"),
  			dateFrom, dateFromValue = '',
  			duration = this.duration * 60,// Duration in minutes
  			serviceName = this.DOM.serviceInput ? this.DOM.serviceInput.value : '',
  			entries = [];
  
  		dateFrom = this.params.fullDay ? BX.parseDate(this.DOM.fromInput.value) : BX.parseDate(this.DOM.fromInput.value + ' ' + this.DOM.timeFromInput.value, false, false, formatDatetime);
  
  		if (BX.type.isDate(dateFrom))
  		{
  			if (this.params.useResources)
  			{
  				entries = entries.concat(this.getSelectedResourceList());
  			}
  
  			if (this.params.useUsers)
  			{
  				entries = entries.concat(this.getSelectedUserList());
  			}
  			dateFromValue = BX.date.format(DATETIME_FORMAT, dateFrom.getTime() / 1000);
  		}
  
  		// Clear inputs
  		this.DOM.valueInputs.forEach(function(input){BX.remove(input);});
  		this.DOM.valueInputs = [];
  
  		entries.forEach(function(entry)
  		{
  			var value = entry.type + '|' + entry.id + '|' + dateFromValue + '|' + duration + '|' + serviceName;
  			allValuesValue += value + '#';
  
  			this.DOM.valueInputs.push(this.DOM.outerWrap.appendChild(
  				BX.create('INPUT', {
  					attrs:{
  						name: this.params.inputName,
  						value: value,
  						type: 'hidden'
  					}})));
  		}, this);
  
  
  		if (!entries.length)
  		{
  			this.DOM.valueInputs.push(this.DOM.outerWrap.appendChild(
  				BX.create('INPUT', {
  					attrs:{
  						name: this.params.inputName,
  						value: 'empty',
  						type: 'hidden'
  					}})));
  		}
  
  		if (!this.allValuesValue)
  		{
  			this.allValuesValue = allValuesValue;
  		}
  		else if (this.allValuesValue !== allValuesValue)
  		{
  			BX.onCustomEvent(window, 'onCrmEntityEditorUserFieldExternalChanged', [this.params.controlId]);
  		}
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.showPlannerPopup = function()
  	{
  		var currentEventList = [];
  		if (this.params.value && BX.type.isArray(this.params.value.ENTRIES))
  		{
  			this.params.value.ENTRIES.forEach(function(entry)
  			{
  				currentEventList.push(entry.EVENT_ID);
  			});
  		}
  
  		BX.Calendar.UserField.ResourceBooking.plannerPopup.show({
  			plannerId: this.params.plannerId,
  			bindNode: this.DOM.outerWrap,
  			plannerConfig: this.getPlannerConfig(),
  			selector: this.getSelectorData(),
  			selectorOnChangeCallback: BX.proxy(this.plannerSelectorOnChange, this),
  			selectEntriesOnChangeCallback: BX.proxy(this.plannerSelectedEntriesOnChange, this),
  			checkSelectorStatusCallback: BX.proxy(this.checkSelectorStatusCallback, this),
  			currentEventList: currentEventList
  		});
  
  		this.triggerUpdatePlanner();
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.triggerUpdatePlanner = function()
  	{
  		if (BX.Calendar.UserField.ResourceBooking.plannerPopup.plannerId === this.params.plannerId
  			&& BX.Calendar.UserField.ResourceBooking.plannerPopup.isShown())
  		{
  			BX.Calendar.UserField.ResourceBooking.plannerPopup.update({
  				plannerId: this.params.plannerId,
  				plannerConfig: this.getPlannerConfig(),
  				selector: this.getSelectorData(),
  				resourceList: this.getResourceList(),
  				selectedResources: this.resourceSelector ? this.resourceSelector.getSelectedValues() : false,
  				userList: this.getUserList(),
  				selectedUsers: this.userSelector ? this.userSelector.getSelectedValues() : false
  			},
  			true);
  		}
  
  		this.onChangeValues();
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.getPlannerConfig = function()
  	{
  		if (!this.params.plannerConfig)
  		{
  			this.params.plannerConfig = {
  				id: this.params.plannerId,
  				selectEntriesMode: true,
  				scaleLimitOffsetLeft: 2,
  				scaleLimitOffsetRight: 2,
  				maxTimelineSize: 300,
  				minEntryRows: 300,
  				entriesListWidth: 120,
  				timelineCellWidth: 49,
  				minWidth: 300,
  				accuracy: 300,
  				workTime: [parseInt(this.params.workTime[0]), parseInt(this.params.workTime[1])]
  			};
  		}
  
  		this.params.plannerConfig.clickSelectorScaleAccuracy = Math.max((this.duration * 60) || 300, 3600);
  
  		return this.params.plannerConfig;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.plannerSelectorOnChange = function(params)
  	{
  		if (params.plannerId === this.params.plannerId)
  		{
  			var
  				dateFrom = params.dateFrom,
  				dateTo = params.dateTo;
  
  			this.DOM.fromInput.value =  BX.date.format(DATE_FORMAT, dateFrom.getTime() / 1000);
  			if (this.DOM.timeFromInput)
  			{
  				this.DOM.timeFromInput.value = BX.date.format(TIME_FORMAT_SHORT, dateFrom.getTime() / 1000);
  			}
  
  			// Duration in minutes
  			if (this.params.fullDay)
  			{
  				this.duration = (dateTo.getTime() - dateFrom.getTime() + DAY_LENGTH) / 60000;
  			}
  			else
  			{
  				this.duration = (dateTo.getTime() - dateFrom.getTime()) / 60000;
  			}
  			this.duration = parseInt(Math.round(Math.max(this.duration, 0)));
  			this.durationList.setValue(this.duration);
  
  			this.onChangeValues();
  		}
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.plannerSelectedEntriesOnChange = function(params)
  	{
  		if (params.plannerId === this.params.plannerId && BX.type.isArray(params.entries))
  		{
  			var
  				selectedResources = [],
  				selectedUsers = [];
  
  			params.entries.forEach(function(entry)
  			{
  				if (entry.selected)
  				{
  					if (entry.type === 'user')
  					{
  						selectedUsers.push(entry.id);
  					}
  					else
  					{
  						selectedResources.push({
  							id: entry.id,
  							type: entry.type
  						});
  					}
  				}
  			});
  
  			if (this.resourceSelector)
  			{
  				this.resourceSelector.setValues(selectedResources, false);
  			}
  			if (this.userSelector)
  			{
  				this.userSelector.setValues(selectedUsers, false);
  			}
  
  			this.onChangeValues();
  		}
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.checkSelectorStatusCallback = function(params)
  	{
  		if (params.plannerId === this.params.plannerId && !this.params.allowOverbooking)
  		{
  			var errorClass = 'calendar-resbook-error';
  			this.overbooked = params.status === 'busy';
  
  			if (this.overbooked)
  			{
  				if (!this.DOM.errorNode)
  				{
  					this.DOM.errorNode = this.DOM.dateTimeWrap.appendChild(BX.create("div", {
  						props: {className: "calendar-resbook-content-error-text"},
  						text: BX.message('USER_TYPE_RESOURCE_BOOKED_ERROR')
  					}));
  				}
  
  				if (this.DOM.fromInput)
  				{
  					BX.addClass(this.DOM.fromInput, errorClass);
  				}
  				if (this.DOM.timeFromInput)
  				{
  					BX.addClass(this.DOM.timeFromInput, errorClass);
  				}
  				setTimeout(BX.delegate(function(){BX.focus(this.DOM.fromInput)}, this), 50);
  			}
  			else
  			{
  				if (this.DOM.errorNode)
  				{
  					BX.remove(this.DOM.errorNode);
  					this.DOM.errorNode = null;
  				}
  
  				if (this.DOM.fromInput)
  				{
  					BX.removeClass(this.DOM.fromInput, errorClass);
  				}
  				if (this.DOM.timeFromInput)
  				{
  					BX.removeClass(this.DOM.timeFromInput, errorClass);
  				}
  			}
  		}
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.getSelectorData = function()
  	{
  		var
  			formatDatetime = BX.isAmPmMode() ? BX.message("FORMAT_DATETIME").replace(':SS', '') : BX.message("FORMAT_DATETIME"),
  			selector, dateTo,
  			duration = this.duration,
  			dateFrom = BX.parseDate(this.DOM.fromInput.value + (this.DOM.timeFromInput ? ' ' + this.DOM.timeFromInput.value : ''), false, false, formatDatetime);
  
  		if (!duration)
  		{
  			duration = this.params.fullDay ? 1440 : 60;
  		}
  
  		if (!BX.type.isDate(dateFrom))
  		{
  			dateFrom = new Date();
  		}
  
  		if (this.params.fullDay)
  		{
  			dateTo = new Date(dateFrom.getTime() + duration * 60000 - DAY_LENGTH)
  		}
  		else
  		{
  			dateTo = new Date(dateFrom.getTime() + duration * 60000);
  		}
  
  		selector = {
  			from: dateFrom,
  			to: dateTo,
  			fullDay: this.params.fullDay,
  			updateScaleLimits: true
  		};
  
  		return selector;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.getResourceList = function()
  	{
  		var entries = [];
  		if (this.resourceSelector)
  		{
  			this.resourceSelector.getValues().forEach(function(value)
  			{
  				entries.push(
  					{
  						id: parseInt(value.id),
  						type : value.type,
  						name : value.title
  					}
  				);
  			});
  		}
  
  		return entries;
  	};
  	BX.Calendar.UserField.ResourceBooking.prototype.getSelectedResourceList = function()
  	{
  		var entries = [];
  		if (this.resourceSelector)
  		{
  			this.resourceSelector.getSelectedValues().forEach(function(value)
  			{
  				entries.push(
  					{
  						id: parseInt(value.id),
  						type : value.type,
  						name : value.title
  					}
  				);
  			});
  		}
  
  		return entries;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.getUserList = function()
  	{
  		var entries = [], index = {}, userId;
  		if (this.userSelector)
  		{
  			if (BX.type.isArray(this.params.userList))
  			{
  				this.params.userList.forEach(function(userId){
  					if (!index[userId])
  					{
  						entries.push({id: userId, type : 'user'});
  						index[userId] = true;
  					}
  				});
  			}
  
  			this.userSelector.getAttendeesCodesList().forEach(function(code)
  			{
  				if (code.substr(0, 1) === 'U')
  				{
  					userId = parseInt(code.substr(1));
  					if (!index[userId])
  					{
  						entries.push({id: userId, type : 'user'});
  						index[userId] = true;
  					}
  				}
  			});
  		}
  
  		return entries;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.getSelectedUserList = function()
  	{
  		var entries = [];
  		if (this.userSelector)
  		{
  			this.userSelector.getAttendeesCodesList().forEach(function(code)
  			{
  				if (code.substr(0, 1) === 'U')
  				{
  					entries.push(
  						{
  							id: parseInt(code.substr(1)),
  							type : 'user'
  						}
  					);
  				}
  			});
  		}
  		return entries;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.USER_TYPE_ID = 'resourcebooking';
  
  	BX.Calendar.UserField.ResourceBooking.openExternalSettingsSlider = function(params)
  	{
  		var settingsSlider = new SettingsSlider();
  		settingsSlider.show(params);
  	};
  
  
  	BX.Calendar.UserField.ResourceBooking.getDurationList = function(fullDay)
  	{
  		var
  			values = [5, 10, 15, 20, 25, 30, 40, 45, 50, 60, 90,
  				120, 180, 240, 300, 360,
  				1440, 1440 * 2, 1440 * 3, 1440 * 4, 1440 * 5, 1440 * 6, 1440 * 7, 1440 * 10],
  			val, i, res = [];
  
  		for (i = 0; i < values.length; i++)
  		{
  			val = values[i];
  			if (fullDay && val % 1440 !== 0)
  			{
  				continue;
  			}
  
  			res.push({
  				value: val,
  				label: this.getDurationLabel(val)
  			});
  		}
  		return res;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.getDurationLabel = function(val)
  	{
  		var label;
  		if (val % 1440 === 0) // Days
  		{
  			label = BX.message('USER_TYPE_DURATION_X_DAY').replace('#NUM#', val / 1440);
  		}
  		else if (val % 60 === 0 && val !== 60) // Hours
  		{
  			label = BX.message('USER_TYPE_DURATION_X_HOUR').replace('#NUM#', val / 60);
  		}
  		// Minutes
  		else
  		{
  			label = BX.message('USER_TYPE_DURATION_X_MIN').replace('#NUM#', val);
  		}
  		return label
  	};
  
  	BX.Calendar.UserField.ResourceBooking.parseDuration = function(value)
  	{
  		var
  			stringValue = value,
  			numValue = parseInt(value),
  			parsed = false,
  			dayRegexp = new RegExp('(\\d)\\s*(' + BX.message('USER_TYPE_DURATION_REGEXP_DAY') + ').*', 'ig'),
  			hourRegexp = new RegExp('(\\d)\\s*(' + BX.message('USER_TYPE_DURATION_REGEXP_HOUR') + ').*', 'ig');
  
  		value = value.replace(dayRegexp, function(str, num){parsed = true;return num;});
  		// It's days
  		if (parsed)
  		{
  			value = numValue * 1440;
  		}
  		else
  		{
  			value = stringValue.replace(hourRegexp, function(str, num){parsed = true;return num;});
  			// It's hours
  			if (parsed)
  			{
  				value = numValue * 60;
  			}
  			else // Minutes
  			{
  				value = numValue;
  			}
  		}
  
  		return parseInt(value) || 0;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.getSimpleTimeList = function(params)
  	{
  		var i, res = [];
  		for (i = 0; i < 24; i++)
  		{
  			res.push({value: i * 60, label: this.formatTime(i, 0)});
  			res.push({value: i * 60 + 30, label: this.formatTime(i, 30)});
  		}
  		BX.Calendar.UserField.ResourceBooking.getSimpleTimeList = function(){return res;};
  		return res;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.adaptTimeValue = function(timeValue)
  	{
  		timeValue = parseInt(timeValue.h * 60) + parseInt(timeValue.m);
  		var
  			timeList = BX.Calendar.UserField.ResourceBooking.getSimpleTimeList(),
  			diff = 24 * 60,
  			ind = false,
  			i;
  
  		for (i = 0; i < timeList.length; i++)
  		{
  			if (Math.abs(timeList[i].value - timeValue) < diff)
  			{
  				diff = Math.abs(timeList[i].value - timeValue);
  				ind = i;
  				if (diff <= 15)
  					break;
  			}
  		}
  
  		return timeList[ind || 0];
  	};
  
  	BX.Calendar.UserField.ResourceBooking.formatTime = function(h, m)
  	{
  		var d = new Date();
  		d.setHours(h, m, 0);
  		return BX.date.format(TIME_FORMAT_SHORT, d.getTime() / 1000);
  	};
  
  	BX.Calendar.UserField.ResourceBooking.getSocnetDestination = function()
  	{
  		if (this.prototype.socnetDestination)
  		{
  			return this.prototype.socnetDestination;
  		}
  		return null;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.getLoader = function(size, className)
  	{
  		return BX.create('DIV', {props:{className: className || 'calendar-loader'}, html: '<svg class="calendar-loader-circular"' +
  			(size ? 'style="width: '+ parseInt(size) +'px; height: '+ parseInt(size) +'px;"' : '') +
  			' viewBox="25 25 50 50">' +
  			'<circle class="calendar-loader-path" cx="50" cy="50" r="20" fill="none" stroke-miterlimit="10"/>' +
  			'<circle class="calendar-loader-inner-path" cx="50" cy="50" r="20" fill="none" stroke-miterlimit="10"/>' +
  			'</svg>'});
  	};
  
  	BX.Calendar.UserField.ResourceBooking.getParamsFromHash = function(userfieldId)
  	{
  		var
  			params, regRes,
  			hash = unescape(window.location.hash);
  
  		if (hash)
  		{
  			regRes = new RegExp('#calendar:' + userfieldId + '\\|(.*)', 'ig').exec(hash);
  			if (regRes && regRes.length > 1)
  			{
  				params = regRes[1].split('|');
  			}
  		}
  		return params;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.showLimitationPopup = function()
  	{
  		if (window.B24 && B24.licenseInfoPopup)
  		{
  			BX.ajax.runAction('calendar.api.resourcebookingajax.initb24limitation', {})
  				.then(function (response)
  				{
  					if (BX.type.isPlainObject(response.data))
  					{
  						B24.licenseInfoPopup.init(response.data);
  						B24.licenseInfoPopup.show(
  							'calendar_resourcebooking',
  							BX.message('USER_TYPE_RESOURCE_B24_LIMITATION_TITLE'),
  							BX.message('USER_TYPE_RESOURCE_B24_LIMITATION') +
  								' <a href="javascript:void(0);" onclick="if(top.BX.Helper){top.BX.Helper.show(\'redirect=detail&code=7481073\')}">' +
  							BX.message('USER_TYPE_RESOURCE_B24_LIMITATION_LINK') + '</a>');
  					}
  				});
  		}
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.checkResourceCountLimitForNewEntries = function(checkForNewEntry)
  	{
  		return this.params.resourceLimit <= 0 || this.getTotalResourceCount() < this.params.resourceLimit;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.checkResourceCountLimit = function(checkForNewEntry)
  	{
  		return this.params.resourceLimit <= 0 || this.getTotalResourceCount() <= this.params.resourceLimit;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.getTotalResourceCount = function()
  	{
  		var result = 0;
  		if (this.params.useResources && this.resourceSelector)
  		{
  			result += this.resourceSelector.getValues().length;
  		}
  
  		if (this.params.useUsers)
  		{
  			result += this.getSelectedUserList().length;
  		}
  
  		return result;
  	};
  
  	BX.Calendar.UserField.ResourceBooking.prototype.isOverbooked = function(params)
  	{
  		return this.overbooked;
  	};
  
  	/**
  	 * Creates instance of Resourcebooking field for webform settings (not for live form)
  	 * Used in CRM webform to display and tune resourcebooking field
  	 *
  	 * @param {array} params - incoming data params
  	 */
  	BX.Calendar.UserField.getResourceBookingCrmFormField = function(params)
  	{
  		var bookingFieldParams = {};
  		if (params.field.node && BX.type.isDomNode(params.field.node))
  		{
  			bookingFieldParams.outerWrap = params.field.node;
  		}
  		else
  		{
  			throw new Error("The argument \"params.field.node\" must be a DOM node.");
  		}
  
  		bookingFieldParams.innerWrap = bookingFieldParams.outerWrap.querySelector('.crm-webform-resourcebooking-wrap');
  		if (!bookingFieldParams.innerWrap)
  		{
  			throw new Error("Can't find necessary DOM node \"div.crm-webform-resourcebooking-wrap\"");
  		}
  
  		bookingFieldParams.name = params.field.name;
  		bookingFieldParams.formName = 'FIELD[' + params.field.name + ']';
  		bookingFieldParams.captionNode = params.field.lblCaption;
  		bookingFieldParams.entityFieldName = params.field.entity_field_name;
  		bookingFieldParams.entityName = params.field.dict.entity_field_name;
  
  		bookingFieldParams.settings = {
  			caption: params.field.captionValue || params.field.dict.caption,
  			required: params.field.isRequired || params.field.dict.required,
  			data: params.field.settingsData || []
  		};
  
  		return new BX.Calendar.UserField.CrmFormResourceBookingField(bookingFieldParams);
  	};
  
  
  	/**
  	 * Creates instance of Resourcebooking field for live webform
  	 * Used in CRM webform to fill forms and book users/resources
  	 *
  	 * @param {array} params - incoming data params
  	 */
  	BX.Calendar.UserField.getResourceBookingFieldLive = function(params)
  	{
  		if (!params.wrap || !BX.type.isDomNode(params.wrap))
  		{
  			throw new Error("The argument \"params.wrap\" must be a DOM node.");
  		}
  		return new BX.Calendar.UserField.CrmFormResourceBookingFieldLiveController(params);
  	};
  
  
  	BX.Calendar.UserField.fieldParamsCache = {};
  	BX.Calendar.UserField.getUserFieldParams = function(params)
  	{
  		params = params || {};
  		var
  			fieldName = params.fieldName || '',
  			promise = new BX.Promise();
  
  		if (params.clearCache || !BX.Calendar.UserField.fieldParamsCache[params.fieldName])
  		{
  			BX.ajax.runAction('calendar.api.resourcebookingajax.getfieldparams', {
  				data: {
  					fieldname: params.fieldName,
  					selectedUsers: params.selectedUsers || []
  				}
  			}).then(BX.delegate(function (response)
  				{
  					BX.Calendar.UserField.fieldParamsCache[fieldName] = response.data;
  					promise.fulfill(response.data);
  				}, this),
  				function (response) {
  					/**
  					 {
  						 "status": "error",
  						 "errors": [...]
  					 }
  					 **/
  				});
  		}
  		else
  		{
  			promise.fulfill(BX.Calendar.UserField.fieldParamsCache[fieldName]);
  		}
  
  		return promise;
  	};
  
  	BX.Calendar.UserField.getPluralMessage = function(messageId, number)
  	{
  		var pluralForm, langId;
  
  		langId = BX.message('LANGUAGE_ID') || 'en';
  		number = parseInt(number);
  
  		if (number < 0)
  		{
  			number = -1*number;
  		}
  
  		if (langId)
  		{
  			switch (langId)
  			{
  				case 'de':
  				case 'en':
  					pluralForm = ((number !== 1) ? 1 : 0);
  					break;
  				case 'ru':
  				case 'ua':
  					pluralForm = (((number%10 === 1) && (number%100 !== 11)) ? 0 : (((number%10 >= 2) && (number%10 <= 4) && ((number%100 < 10) || (number%100 >= 20))) ? 1 : 2));
  					break;
  				default:
  					pluralForm = 1;
  					break;
  			}
  		}
  		else
  		{
  			pluralForm = 1;
  		}
  
  		return BX.message(messageId + '_PLURAL_' + pluralForm);
  	};
  
  
  
  	// region ** Planner popup **
  	function PlannerPopup() {}
  	PlannerPopup.prototype = {
  		show: function (params)
  		{
  			if (!params)
  			{
  				params = {};
  			}
  			this.params = params;
  			this.bindNode = params.bindNode;
  			this.plannerId = this.params.plannerId;
  			this.config = this.params.plannerConfig;
  
  			if (this.isShown() || !this.bindNode)
  			{
  				return;
  			}
  
  			if (this.lastPlannerIdShown && this.lastPlannerIdShown !== this.plannerId)
  			{
  				this.close({animation: false});
  			}
  
  			this.currentEntries = [];
  
  			this.plannerWrap = BX.create('DIV', {
  				attrs: {
  					id: this.plannerId,
  					className: 'calendar-planner-wrapper'
  				}
  			});
  
  			this.popup = new BX.PopupWindow(this.plannerId + "_popup",
  				this.bindNode,
  				{
  					autoHide: false,
  					closeByEsc: true,
  					offsetTop: - parseInt(this.bindNode.offsetHeight) - 20,
  					offsetLeft: this.bindNode.offsetWidth + 38,
  					lightShadow: true,
  					content: this.plannerWrap
  				});
  
  			this.popup.setAngle({offset: 100, position: 'left'});
  			this.popup.show(true);
  			this.lastPlannerIdShown = this.plannerId;
  
  			var
  				bindPos = BX.pos(this.bindNode),
  				winSize = BX.GetWindowSize();
  
  			this.plannerWidth = winSize.innerWidth - bindPos.right - 160;
  			this.config.width = this.plannerWidth;
  
  			setTimeout(BX.delegate(function(){
  				if (this.popup && this.popup.popupContainer)
  				{
  					BX.addClass(this.popup.popupContainer, 'calendar-resbook-planner-popup');
  					this.popup.popupContainer.style.width = 0;
  				}
  			}, this), 1);
  			setTimeout(BX.delegate(function(){
  				if (this.popup && this.popup.popupContainer)
  				{
  					this.popup.popupContainer.style.width = (this.plannerWidth + 40) + 'px';
  					BX.addClass(this.popup.popupContainer, 'show');
  				}
  				BX.bind(document, 'click', BX.proxy(this.handleClick, this));
  			}, this), 50);
  			setTimeout(BX.proxy(this.showPlanner, this), 350);
  
  			BX.addCustomEvent(this.popup, 'onPopupClose', BX.proxy(this.close, this));
  		},
  
  		update: function (params, refreshParams)
  		{
  			if (!this.isShown())
  			{
  				return;
  			}
  
  			var
  				codes = [], i, k, code,
  				codeIndex = {},
  				_this = this,
  				plannerConfig = BX.clone(_this.config, true),
  				fromTimestamp, toTimestamp,
  				dateFrom, dateTo;
  
  			if (BX.type.isPlainObject(this.lastUpdateParams) && BX.type.isPlainObject(params) && refreshParams !== true)
  			{
  				for (k in params)
  				{
  					if (params.hasOwnProperty(k))
  					{
  						this.lastUpdateParams[k] = params[k];
  					}
  				}
  				params = this.lastUpdateParams;
  			}
  
  			// Save selector information
  			if (BX.type.isPlainObject(params))
  			{
  				this.lastUpdateParams = params;
  			}
  
  			params.focusSelector = params.focusSelector !== false;
  
  			if (params.from && params.to)
  			{
  				dateFrom = BX.parseDate(params.from);
  				dateTo = BX.parseDate(params.to);
  				fromTimestamp = dateFrom.getTime();
  				toTimestamp = dateTo.getTime();
  			}
  			else
  			{
  				if (params.selector.fullDay)
  				{
  					fromTimestamp = params.selector.from.getTime() - DAY_LENGTH * 12;
  					toTimestamp = params.selector.from.getTime() + DAY_LENGTH * 14;
  				}
  				else
  				{
  					fromTimestamp = params.selector.from.getTime() - DAY_LENGTH * 3;
  					toTimestamp = params.selector.from.getTime() + DAY_LENGTH * 5;
  				}
  
  				dateFrom = new Date(fromTimestamp);
  				dateTo = new Date(toTimestamp);
  
  				plannerConfig.scaleDateFrom = dateFrom;
  				plannerConfig.scaleDateTo = dateTo;
  			}
  
  			if (BX.type.isArray(params.userList))
  			{
  				for (i = 0; i < params.userList.length; i++)
  				{
  					code = 'U' + params.userList[i].id;
  					if (!codeIndex[code])
  					{
  						codes.push(code);
  						codeIndex[code] = true;
  					}
  				}
  			}
  
  			if (BX.type.isArray(params.selectedUsers))
  			{
  				for (i = 0; i < params.selectedUsers.length; i++)
  				{
  					code = 'U' + params.selectedUsers[i];
  					if (!codeIndex[code])
  					{
  						codes.push(code);
  						codeIndex[code] = true;
  					}
  				}
  			}
  
  			var requestData = {
  				codes: codes,
  				resources: params.resourceList,
  				from: BX.date.format(DATE_FORMAT, fromTimestamp / 1000),
  				to: BX.date.format(DATE_FORMAT, toTimestamp / 1000),
  				currentEventList: this.params.currentEventList || []
  			};
  
  			if (this.checkUpdateParams(requestData) && this.isShown())
  			{
  				this.showPlannerLoader();
  				BX.ajax.runAction('calendar.api.resourcebookingajax.getplannerdata', {
  					data: requestData
  				}).then(function (response)
  				{
  					_this.hidePlannerLoader();
  
  					if (_this.lastRequestData)
  					{
  						_this.lastRequestData.response = response;
  					}
  
  					_this.currentEntries = response.data.entries;
  					_this.currentAccessibility = response.data.accessibility;
  					_this.currentLoadedDataFrom = dateFrom;
  					_this.currentLoadedDataTo = dateTo;
  
  					if (BX.type.isArray(response.data.entries))
  					{
  						response.data.entries.forEach(function(entry){
  							if ((entry.type === 'user'
  								&& params.selectedUsers.find(function(userId){return parseInt(entry.id) === parseInt(userId);}))
  								||
  								(entry.type === 'resource'
  								&& params.selectedResources.find(function(item){return entry.type === item.type && parseInt(entry.id) === parseInt(item.id);}))
  							)
  							{
  								entry.selected = true;
  							}
  							else
  							{
  								entry.selected = false;
  							}
  						});
  					}
  
  					if (_this.isShown())
  					{
  						BX.onCustomEvent('OnCalendarPlannerDoUpdate', [
  							{
  								plannerId: _this.plannerId,
  								config: plannerConfig,
  								focusSelector: params.focusSelector,
  								selector: {
  									from: params.selector.from,
  									to: params.selector.to,
  									fullDay: params.selector.fullDay,
  									animation: params.focusSelector,
  									updateScaleLimits: params.focusSelector
  								},
  								data: {
  									entries: response.data.entries,
  									accessibility: response.data.accessibility
  								},
  								loadedDataFrom: dateFrom,
  								loadedDataTo: dateTo,
  								show: false
  							}
  						]);
  					}
  				},
  				function (response) {
  					/**
  					 {
  						 "status": "error",
  						 "errors": [...]
  					 }
  					 **/
  				});
  			}
  			else if (BX.type.isPlainObject(this.lastRequestData.response))
  			{
  				var response = this.lastRequestData.response;
  				_this.currentEntries = response.data.entries;
  				_this.currentAccessibility = response.data.accessibility;
  				_this.currentLoadedDataFrom = dateFrom;
  				_this.currentLoadedDataTo = dateTo;
  
  				if (BX.type.isArray(response.data.entries))
  				{
  					response.data.entries.forEach(function(entry){
  						if ((entry.type === 'user'
  							&& params.selectedUsers.find(function(userId){return parseInt(entry.id) == parseInt(userId);}))
  							||
  							(entry.type === 'resource'
  							&& params.selectedResources.find(function(item){return entry.type === item.type && parseInt(entry.id) === parseInt(item.id);}))
  						)
  						{
  							entry.selected = true;
  						}
  						else
  						{
  							entry.selected = false;
  						}
  					});
  				}
  
  				if (this.isShown())
  				{
  					BX.onCustomEvent('OnCalendarPlannerDoUpdate', [
  						{
  							plannerId: _this.plannerId,
  							config: plannerConfig,
  							focusSelector: params.focusSelector,
  							selector: {
  								from: params.selector.from,
  								to: params.selector.to,
  								fullDay: params.selector.fullDay,
  								animation: params.focusSelector,
  								updateScaleLimits: params.focusSelector
  							},
  							data: {
  								entries: response.data.entries,
  								accessibility: response.data.accessibility
  							},
  							loadedDataFrom: dateFrom,
  							loadedDataTo: dateTo,
  							show: false
  						}
  					]);
  				}
  			}
  		},
  
  		checkUpdateParams: function (requestData)
  		{
  			var requestPlannerUpdate = false;
  			if (!this.lastRequestData || this.lastRequestPlannerId !== this.plannerId)
  			{
  				requestPlannerUpdate = true;
  			}
  
  			// 1. Compare dates
  			if (!requestPlannerUpdate && requestData.from !== this.lastRequestData.from)
  			{
  				requestPlannerUpdate = true;
  			}
  			// 2. Compare users
  			if (!requestPlannerUpdate
  				&& BX.type.isArray(requestData.codes) && BX.type.isArray(this.lastRequestData.codes)
  				&& BX.util.array_diff(requestData.codes, this.lastRequestData.codes).length > 0
  			)
  			{
  				requestPlannerUpdate = true;
  			}
  
  			// 3. Compare resources
  			if (!requestPlannerUpdate && BX.type.isArray(requestData.resources) && BX.type.isArray(this.lastRequestData.resources))
  			{
  				if (requestData.resources.length !== this.lastRequestData.resources.length)
  				{
  					requestPlannerUpdate = true;
  				}
  				else
  				{
  					var resIndex = {};
  					requestData.resources.forEach(function (res)
  					{
  						resIndex[res.type + '_' + res.id] = true
  					});
  
  					this.lastRequestData.resources.forEach(function(res)
  					{
  						if (!resIndex[res.type + '_' + res.id])
  						{
  							requestPlannerUpdate = true;
  						}
  					});
  				}
  			}
  
  			// Save request data for future comparing
  			if (requestPlannerUpdate)
  			{
  				this.lastRequestData = requestData;
  				this.lastRequestPlannerId = this.plannerId;
  			}
  
  			return requestPlannerUpdate;
  		},
  
  		showPlanner: function ()
  		{
  			this.planner = new CalendarPlanner(
  				this.params.plannerConfig,
  				{
  					config: this.config,
  					data: {
  						accessibility: this.currentAccessibility || {},
  						entries: this.currentEntries
  					},
  					selector: {
  						from: this.params.selector.from,
  						to: this.params.selector.to,
  						fullDay: this.params.selector.fullDay,
  						updateScaleLimits: true,
  						updateScaleType: false,
  						focus: true,
  						RRULE: false,
  						animation: false
  					},
  					loadedDataFrom: this.currentLoadedDataFrom,
  					loadedDataTo: this.currentLoadedDataTo,
  					focusSelector: true,
  					plannerId: this.plannerId,
  					show: true
  				}
  			);
  
  			// planner events
  			if (BX.type.isFunction(this.params.selectorOnChangeCallback))
  			{
  				BX.addCustomEvent('OnCalendarPlannerSelectorChanged', this.params.selectorOnChangeCallback);
  			}
  			if (BX.type.isFunction(this.params.selectEntriesOnChangeCallback))
  			{
  				BX.addCustomEvent('OnCalendarPlannerSelectedEntriesOnChange', this.params.selectEntriesOnChangeCallback);
  			}
  			if (BX.type.isFunction(this.params.checkSelectorStatusCallback))
  			{
  				BX.addCustomEvent('OnCalendarPlannerSelectorStatusOnChange', this.params.checkSelectorStatusCallback);
  			}
  
  			BX.addCustomEvent('OnCalendarPlannerScaleChanged', BX.proxy(function(params)
  			{
  				this.update({
  					from: params.from,
  					to: params.to,
  					focusSelector: params.focusSelector === true
  				});
  			}, this));
  
  		},
  
  		showPlannerLoader: function ()
  		{
  			if (this.planner && this.planner.outerWrap)
  			{
  				if (this.loader)
  				{
  					BX.remove(this.loader);
  				}
  				this.loader = this.planner.outerWrap.appendChild(BX.Calendar.UserField.ResourceBooking.getLoader(150));
  			}
  		},
  
  		hidePlannerLoader: function ()
  		{
  			if (this.loader)
  			{
  				BX.remove(this.loader);
  				this.loader = false;
  			}
  		},
  
  		close: function(params)
  		{
  			if (this.popup)
  			{
  				if (params && params.animation)
  				{
  					BX.removeClass(this.popup.popupContainer, 'show');
  					setTimeout(BX.delegate(function()
  					{
  						params.animation = false;
  						this.close(params);
  					}, this), 300);
  				}
  				else
  				{
  					BX.unbind(document, 'click', BX.proxy(this.handleClick, this));
  					BX.removeCustomEvent(this.popup, 'onPopupClose', BX.proxy(this.close, this));
  					this.popup.destroy();
  					this.planner = null;
  					this.popup = null;
  				}
  			}
  		},
  
  		isShown: function()
  		{
  			return this.lastPlannerIdShown === this.plannerId
  				&& this.popup && this.popup.isShown && this.popup.isShown();
  		},
  
  		getPlannerId: function()
  		{
  			if (typeof this.plannerId === 'undefined')
  			{
  				this.plannerId = 'calendar-planner-' + Math.round(Math.random() * 100000);
  			}
  			return this.plannerId;
  		},
  
  		getPlannerContainer: function()
  		{
  			return BX('calendar-planner-outer' + this.getPlannerId(), true);
  		},
  
  		refreshDateTimeView: function(params)
  		{
  		},
  
  		handleClick: function(e)
  		{
  			var target = e.target || e.srcElement;
  			if (this.isShown()
  				&& !BX.isParentForNode(this.bindNode, target)
  				&& !BX.isParentForNode(BX('BXSocNetLogDestination'), target)
  				&& !BX.isParentForNode(this.popup.popupContainer, target)
  			)
  			{
  				if (!document.querySelector('div.popup-window-resource-select'))
  				{
  					this.close({animation: true});
  				}
  			}
  		}
  	};
  	// endregion
  
  	function SettingsSlider()
  	{
  		this.id = 'calendar_custom_settings_' + Math.round(Math.random() * 1000000);
  		this.zIndex = 3100;
  		this.sliderId = "calendar:resbook-settings-slider";
  
  		this.SLIDER_WIDTH = 400;
  		this.SLIDER_DURATION = 80;
  		this.DOM = {};
  	}
  
  	SettingsSlider.prototype = {
  		show: function (params)
  		{
  			this.params = params;
  
  			BX.SidePanel.Instance.open(this.sliderId, {
  				contentCallback: BX.delegate(this.create, this),
  				width: this.SLIDER_WIDTH,
  				animationDuration: this.SLIDER_DURATION
  			});
  
  			BX.addCustomEvent("SidePanel.Slider:onClose", BX.proxy(this.hide, this));
  			BX.addCustomEvent("SidePanel.Slider:onCloseComplete", BX.proxy(this.destroy, this));
  		},
  
  		close: function ()
  		{
  			BX.SidePanel.Instance.close();
  		},
  
  		hide: function (event)
  		{
  			if (event && event.getSliderPage && event.getSliderPage().getUrl() === this.sliderId)
  			{
  				if (this.denyClose)
  				{
  					event.denyAction();
  				}
  				else
  				{
  					BX.removeCustomEvent("SidePanel.Slider:onClose", BX.proxy(this.hide, this));
  				}
  			}
  		},
  
  		destroy: function (event)
  		{
  			if (event && event.getSliderPage && event.getSliderPage().getUrl() === this.sliderId)
  			{
  				BX.removeCustomEvent("SidePanel.Slider:onCloseComplete", BX.proxy(this.destroy, this));
  				BX.SidePanel.Instance.destroy(this.sliderId);
  			}
  		},
  
  		create: function ()
  		{
  			var promise = new BX.Promise();
  
  			var html = '<div class="webform-buttons calendar-form-buttons-fixed">' +
  				'<span id="' + this.id + '_save" class="webform-small-button webform-small-button-blue">' + BX.message('USER_TYPE_RESOURCE_SAVE') + '</span>' +
  				'<span id="' + this.id + '_close" class="webform-button-link">' + BX.message('USER_TYPE_RESOURCE_CLOSE') + '</span>' +
  			'</div>' +
  			'<div class="calendar-slider-calendar-wrap">' +
  				'<div class="calendar-slider-header"><div class="calendar-head-area"><div class="calendar-head-area-inner"><div class="calendar-head-area-title">' +
  				'<span class="calendar-head-area-name">' + BX.message('USER_TYPE_RESOURCE_SETTINGS') + 			'</span>' +
  				'</div></div></div></div>' +
  				'<div class="resource-booking-slider-workarea"><div class="resource-booking-slider-content"><div id="' + this.id + '_content" class="resource-booking-settings"></div></div></div></div>';
  
  			promise.fulfill(BX.util.trim(html));
  			setTimeout(BX.delegate(this.initControls, this), 100);
  
  			return promise;
  		},
  
  		initControls: function ()
  		{
  			this.DOM.content = BX(this.id + '_content');
  
  			BX.bind(BX(this.id + '_save'), 'click', BX.proxy(this.save, this));
  			BX.bind(BX(this.id + '_close'), 'click', BX.proxy(this.close, this));
  
  			// 1. Field
  			if (this.params && BX.type.isArray(this.params.filterSelectValues))
  			{
  				this.DOM.fieldOuterWrap = this.DOM.content.appendChild(BX.create('DIV', {attrs: {className: 'calendar-settings-control'}}));
  				this.DOM.fieldOuterWrap.appendChild(BX.create('DIV', {
  					attrs: {className: 'calendar-settings-control-name'},
  					text: BX.message('USER_TYPE_RESOURCE_FILTER_NAME')
  				}));
  				this.DOM.fieldSelect = this.DOM.fieldOuterWrap.appendChild(BX.create('DIV', {attrs: {className: 'calendar-field-container calendar-field-container-select'}}))
  					.appendChild(BX.create('DIV', {attrs: {className: 'calendar-field-block'}}))
  					.appendChild(BX.create('select', {attrs: {className: 'calendar-field calendar-field-select'}}));
  
  				this.params.filterSelectValues.forEach(function(value){
  					this.DOM.fieldSelect.options.add(
  						new Option(value.TEXT, value.VALUE, this.params.filterSelect === value.VALUE, this.params.filterSelect === value.VALUE));
  				}, this);
  			}
  		},
  
  		save: function ()
  		{
  			var entityType = this.params.entityType || 'none';
  			BX.userOptions.save('calendar', 'resourceBooking', entityType, this.DOM.fieldSelect.value);
  			this.close();
  			BX.reload();
  		}
  	};
  
  
  	function UserSelector(params)
  	{
  		this.params = params || {};
  		this.id = this.params.id || 'user-selector-' + Math.round(Math.random() * 100000);
  		this.wrapNode = this.params.wrapNode;
  		this.zIndex = this.params.zIndex || 3100;
  		this.destinationInputName = this.params.inputName || 'EVENT_DESTINATION';
  		this.params.selectGroups = false;
  		this.addMessage = this.params.addMessage || BX.message('USER_TYPE_RESOURCE_ADD_USER');
  		this.checkLimit = BX.type.isFunction(params.checkLimitCallback) ? params.checkLimitCallback : false;
  
  		if (BX.type.isArray(this.params.itemsSelected))
  		{
  			this.params.itemsSelected = this.convertAttendeesCodes(this.params.itemsSelected);
  		}
  		else
  		{
  			this.params.itemsSelected = this.getSocnetDestinationConfig('itemsSelected');
  		}
  
  		this.DOM = {
  			outerWrap: this.params.outerWrap,
  			wrapNode: this.params.wrapNode
  		};
  
  		this.create();
  	}
  
  	UserSelector.prototype = {
  		create: function ()
  		{
  			if (this.DOM.outerWrap)
  			{
  				BX.addClass(this.DOM.outerWrap, 'calendar-resourcebook-folding-block' + (this.params.shown !== false ? ' shown' : ''));
  			}
  
  			var id = this.id;
  
  			BX.bind(this.wrapNode, 'click', BX.delegate(function (e)
  			{
  				var target = e.target || e.srcElement;
  				if (target.className === 'calendar-resourcebook-content-block-control-delete') // Delete button
  				{
  					BX.SocNetLogDestination.deleteItem(target.getAttribute('data-item-id'), target.getAttribute('data-item-type'), id);
  					var block = BX.findParent(target, {className: 'calendar-resourcebook-content-block-control-inner'});
  					if (block && BX.hasClass(block, 'shown'))
  					{
  						BX.removeClass(block, 'shown');
  						setTimeout(function(){BX.remove(block);}, 300);
  					}
  				}
  				else
  				{
  					BX.SocNetLogDestination.openDialog(id);
  				}
  			}, this));
  
  			this.socnetDestinationInputWrap = this.wrapNode.appendChild(BX.create('SPAN', {props: {className: 'calendar-resourcebook-destination-input-box'}}));
  			this.socnetDestinationInput = this.socnetDestinationInputWrap.appendChild(BX.create('INPUT', {
  				props: {
  					id: id + '-inp',
  					className: 'calendar-resourcebook-destination-input'
  				},
  				attrs: {
  					value: '',
  					type: 'text'
  				},
  				events: {
  					keydown: function (e)
  					{
  						return BX.SocNetLogDestination.searchBeforeHandler(e, {
  							formName: id, inputId: id + '-inp'
  						});
  					}, keyup: function (e)
  					{
  						return BX.SocNetLogDestination.searchHandler(e, {
  							formName: id,
  							inputId: id + '-inp',
  							linkId: 'event-grid-dest-add-link',
  							sendAjax: true
  						});
  					}
  				}
  			}));
  
  			this.socnetDestinationLink = this.wrapNode.appendChild(BX.create('DIV', {
  				props: {className: 'calendar-resourcebook-content-block-control-text calendar-resourcebook-content-block-control-text-add'},
  				text: this.addMessage
  			}));
  
  			this.init();
  		},
  
  		show: function ()
  		{
  			if (this.DOM.outerWrap)
  			{
  				BX.addClass(this.DOM.outerWrap, 'shown');
  			}
  		},
  
  		hide: function ()
  		{
  			if (this.DOM.outerWrap)
  			{
  				BX.removeClass(this.DOM.outerWrap, 'shown');
  			}
  		},
  
  		isShown: function ()
  		{
  			if (this.DOM.outerWrap)
  			{
  				return BX.hasClass(this.DOM.outerWrap, 'shown');
  			}
  		},
  
  		init: function ()
  		{
  			if (!this.socnetDestinationInput || !this.wrapNode)
  				return;
  
  			var _this = this;
  
  			this.params.items = this.getSocnetDestinationConfig('items');
  			this.params.itemsLast = this.getSocnetDestinationConfig('itemsLast');
  
  			if (this.params.selectGroups === false)
  			{
  				this.params.items.groups = {};
  				this.params.items.department = {};
  				this.params.items.sonetgroups = {};
  			}
  
  			BX.SocNetLogDestination.init({
  				name: this.id,
  				searchInput: this.socnetDestinationInput,
  				extranetUser: false,
  				userSearchArea: 'I',
  				bindMainPopup: {
  					node: this.wrapNode, offsetTop: '5px', offsetLeft: '15px'
  				},
  				bindSearchPopup: {
  					node: this.wrapNode, offsetTop: '5px', offsetLeft: '15px'
  				},
  				callback: {
  					select: BX.proxy(this.selectCallback, this),
  					unSelect: BX.proxy(this.unSelectCallback, this),
  					openDialog: BX.proxy(this.openDialogCallback, this),
  					closeDialog: BX.proxy(this.closeDialogCallback, this),
  					openSearch: BX.proxy(this.openDialogCallback, this),
  					closeSearch: function ()
  					{
  						_this.closeDialogCallback(true);
  					}
  				},
  				items: this.params.items,
  				itemsLast: this.params.itemsLast,
  				itemsSelected: this.params.itemsSelected,
  				departmentSelectDisable: this.params.selectGroups === false
  			});
  		},
  
  		closeAll: function ()
  		{
  			if (BX.SocNetLogDestination.isOpenDialog())
  			{
  				BX.SocNetLogDestination.closeDialog();
  			}
  			BX.SocNetLogDestination.closeSearch();
  		},
  
  		selectCallback: function(item, type)
  		{
  			if (type === 'users')
  			{
  				this.addUserBlock(item);
  				BX.onCustomEvent('OnResourceBookDestinationAddNewItem', [item, this.id]);
  				this.socnetDestinationInput.value = '';
  			}
  		},
  
  		addUserBlock: function(item, animation)
  		{
  			if (this.checkLimit && !this.checkLimit())
  			{
  				return BX.Calendar.UserField.ResourceBooking.showLimitationPopup();
  			}
  			var i, blocks = this.wrapNode.querySelectorAll('.calendar-resourcebook-content-block-control-inner.shown');
  			for (i = 0; i < blocks.length; i++)
  			{
  				if (blocks[i].getAttribute('data-id') === item.id)
  				{
  					BX.remove(blocks[i]);
  				}
  			}
  
  			var itemWrap = this.wrapNode.appendChild(BX.create("DIV", {
  				attrs: {
  					'data-id': item.id, className: "calendar-resourcebook-content-block-control-inner green"
  				},
  				html: '<div class="calendar-resourcebook-content-block-control-text">' + item.name + '</div>' + '<div data-item-id="' + item.id + '" data-item-type="users" class="calendar-resourcebook-content-block-control-delete"></div>' + '<input type="hidden" name="' + this.destinationInputName + '[U][]' + '" value="' + item.id + '">'
  			}));
  
  			if (animation !== false)
  			{
  				setTimeout(BX.delegate(function (){BX.addClass(itemWrap, 'shown');}, this), 1);
  			}
  			else
  			{
  				BX.addClass(itemWrap, 'shown');
  			}
  
  			this.wrapNode.appendChild(this.socnetDestinationInputWrap);
  			this.wrapNode.appendChild(this.socnetDestinationLink);
  		},
  
  		unSelectCallback: function(item)
  		{
  			var elements = BX.findChildren(this.wrapNode, {attribute: {'data-id': item.id}}, true);
  			if (elements != null)
  			{
  				for (var j = 0; j < elements.length; j++)
  				{
  					BX.remove(elements[j]);
  				}
  			}
  
  			BX.onCustomEvent('OnResourceBookDestinationUnselect', [item, this.id]);
  			this.socnetDestinationInput.value = '';
  			this.socnetDestinationLink.innerHTML = this.addMessage;
  		},
  
  		openDialogCallback: function ()
  		{
  			if (BX.SocNetLogDestination.popupWindow)
  			{
  				// Fix zIndex for slider issues
  				BX.SocNetLogDestination.popupWindow.params.zIndex = this.zIndex;
  				BX.SocNetLogDestination.popupWindow.popupContainer.style.zIndex = this.zIndex;
  			}
  
  			if (BX.SocNetLogDestination.popupSearchWindow)
  			{
  				// Fix zIndex for slider issues
  				BX.SocNetLogDestination.popupSearchWindow.params.zIndex = this.zIndex;
  				BX.SocNetLogDestination.popupSearchWindow.popupContainer.style.zIndex = this.zIndex;
  			}
  
  			BX.style(this.socnetDestinationInputWrap, 'display', 'inline-block');
  			BX.style(this.socnetDestinationLink, 'display', 'none');
  			BX.focus(this.socnetDestinationInput);
  		},
  
  		closeDialogCallback: function(cleanInputValue)
  		{
  			if (!BX.SocNetLogDestination.isOpenSearch() && this.socnetDestinationInput.value.length <= 0)
  			{
  				BX.style(this.socnetDestinationInputWrap, 'display', 'none');
  				BX.style(this.socnetDestinationLink, 'display', 'inline-block');
  				if (cleanInputValue === true)
  					this.socnetDestinationInput.value = '';
  
  				// Disable backspace
  				if (BX.SocNetLogDestination.backspaceDisable || BX.SocNetLogDestination.backspaceDisable != null)
  					BX.unbind(window, 'keydown', BX.SocNetLogDestination.backspaceDisable);
  
  				BX.bind(window, 'keydown', BX.SocNetLogDestination.backspaceDisable = function(e)
  				{
  					if (e.keyCode === 8)
  					{
  						e.preventDefault();
  						return false;
  					}
  				});
  
  				setTimeout(function()
  				{
  					BX.unbind(window, 'keydown', BX.SocNetLogDestination.backspaceDisable);
  					BX.SocNetLogDestination.backspaceDisable = null;
  				}, 5000);
  			}
  		},
  
  		getCodes: function()
  		{
  			var
  				inputsList = this.wrapNode.getElementsByTagName('INPUT'),
  				codes = [], i, value;
  
  			for (i = 0; i < inputsList.length; i++)
  			{
  				value = BX.util.trim(inputsList[i].value);
  				if (value)
  				{
  					codes.push(inputsList[i].value);
  				}
  			}
  			return codes;
  		},
  
  		getAttendeesCodes: function()
  		{
  			var
  				inputsList = this.wrapNode.getElementsByTagName('INPUT'),
  				values = [],
  				i;
  
  			for (i = 0; i < inputsList.length; i++)
  			{
  				values.push(inputsList[i].value);
  			}
  
  			return this.convertAttendeesCodes(values);
  		},
  
  		convertAttendeesCodes: function(values)
  		{
  			var attendeesCodes = {};
  
  			if (BX.type.isArray(values))
  			{
  				values.forEach(function(code){
  					if (code.substr(0, 2) === 'DR')
  					{
  						attendeesCodes[code] = "department";
  					}
  					else if (code.substr(0, 2) === 'UA')
  					{
  						attendeesCodes[code] = "groups";
  					}
  					else if (code.substr(0, 2) === 'SG')
  					{
  						attendeesCodes[code] = "sonetgroups";
  					}
  					else if (code.substr(0, 1) === 'U')
  					{
  						attendeesCodes[code] = "users";
  					}
  				});
  			}
  
  			return attendeesCodes;
  		},
  
  		getAttendeesCodesList: function(codes)
  		{
  			var result = [];
  			if (!codes)
  				codes = this.getAttendeesCodes();
  			for (var i in codes)
  			{
  				if (codes.hasOwnProperty(i))
  				{
  					result.push(i);
  				}
  			}
  			return result;
  		},
  
  		getSocnetDestinationConfig: function(key)
  		{
  			var
  				res,
  				socnetDestination = this.params.socnetDestination || {};
  
  			if (key === 'items')
  			{
  				res = {
  					users: socnetDestination.USERS || {},
  					groups: socnetDestination.EXTRANET_USER === 'Y' || socnetDestination.DENY_TOALL
  						? {}
  						: {UA: {id: 'UA', name: BX.message('USER_TYPE_RESOURCE_TO_ALL_USERS')}},
  					sonetgroups: socnetDestination.SONETGROUPS || {},
  					department: socnetDestination.DEPARTMENT || {},
  					departmentRelation: socnetDestination.DEPARTMENT_RELATION || {}
  				};
  			}
  			else if (key === 'itemsLast' && socnetDestination.LAST)
  			{
  				res = {
  					users: socnetDestination.LAST.USERS || {},
  					groups: socnetDestination.EXTRANET_USER === 'Y' ? {} : {UA: true},
  					sonetgroups: socnetDestination.LAST.SONETGROUPS || {},
  					department: socnetDestination.LAST.DEPARTMENT || {}
  				};
  			}
  			else if (key === 'itemsSelected')
  			{
  				res = socnetDestination.SELECTED || {};
  			}
  			return res || {};
  		},
  
  		getSelectedValues: function()
  		{
  			var
  				result = [], i,
  				inputs = this.wrapNode.querySelectorAll('input');
  
  			for (i = 0; i < inputs.length; i++)
  			{
  				if (inputs[i].type === 'hidden' && inputs[i].value)
  				{
  					if (inputs[i].value.substr(0, 1) === 'U')
  					{
  						result.push(parseInt(inputs[i].value.substr(1)));
  					}
  				}
  			}
  
  			return result;
  		},
  
  		setValues: function(userList, trigerOnChange)
  		{
  			var blocks, i, user;
  			blocks = this.wrapNode.querySelectorAll('.calendar-resourcebook-content-block-control-inner.shown');
  			for (i = 0; i < blocks.length; i++)
  			{
  				BX.remove(blocks[i]);
  			}
  
  			for (i = 0; i < userList.length; i++)
  			{
  				if (BX.SocNetLogDestination.obItems[this.id]['users'])
  				{
  					user = BX.SocNetLogDestination.obItems[this.id]['users']['U' + userList[i]];
  					if (user)
  					{
  						this.addUserBlock({
  							id: 'U' + userList[i],
  							name: user.name
  						}, false);
  					}
  				}
  			}
  
  			if (trigerOnChange !== false && this.onChangeCallback && BX.type.isFunction(this.onChangeCallback))
  			{
  				setTimeout(BX.proxy(this.onChangeCallback, this), 100);
  			}
  		},
  
  		getId: function()
  		{
  			return this.id;
  		}
  	};
  
  
  	function ResourceListSelector(params)
  	{
  		this.params = params || {};
  		this.editMode = !!this.params.editMode;
  		this.id = this.params.id || 'resource-selector-' + Math.round(Math.random() * 100000);
  		this.resourceList = BX.type.isArray(params.resourceList) ? params.resourceList : [];
  		this.checkLimit = BX.type.isFunction(params.checkLimitCallback) ? params.checkLimitCallback : false;
  		this.checkLimitForNew = BX.type.isFunction(params.checkLimitCallbackForNew) ? params.checkLimitCallbackForNew : false;
  
  		this.selectedValues = [];
  		this.selectedValuesIndex = {};
  
  		this.selectedBlocks = [];
  		this.newValues = [];
  
  		this.DOM = {
  			outerWrap: this.params.outerWrap,
  			blocksWrap: this.params.blocksWrap || false,
  			listWrap: this.params.listWrap
  		};
  
  		if (this.editMode)
  		{
  			this.DOM.controlsWrap = this.params.controlsWrap;
  		}
  		else
  		{
  			this.DOM.arrowNode = BX.create("span", {props: {className: "calendar-resourcebook-content-block-detail-icon calendar-resourcebook-content-block-detail-icon-arrow"}});
  		}
  
  		this.onChangeCallback = this.params.onChangeCallback || null;
  
  		this.create();
  		this.setValues(params.values);
  	}
  
  	ResourceListSelector.prototype = {
  		create: function ()
  		{
  			BX.addClass(this.DOM.outerWrap, 'calendar-resourcebook-resource-list-wrap calendar-resourcebook-folding-block' + (this.params.shown !== false ? ' shown' : ''));
  
  			if (this.editMode)
  			{
  				this.DOM.addButton = this.DOM.controlsWrap.appendChild(BX.create("span", {
  					props: {className: "calendar-resource-content-block-add-link"},
  					text: BX.message('USER_TYPE_RESOURCE_ADD'),
  					events: {click: BX.delegate(this.addResourceBlock, this)}
  				}));
  
  				if (this.resourceList.length > 0)
  				{
  					this.DOM.selectButton = this.DOM.controlsWrap.appendChild(BX.create("span", {
  						props: {className: "calendar-resource-content-block-add-link"},
  						text: BX.message('USER_TYPE_RESOURCE_SELECT'),
  						events: {click: BX.delegate(this.openResourcesPopup, this)}
  					}));
  				}
  			}
  			else
  			{
  				BX.bind(this.DOM.blocksWrap, 'click', BX.delegate(this.handleBlockClick, this));
  			}
  		},
  		show: function ()
  		{
  			BX.addClass(this.DOM.outerWrap, 'shown');
  		},
  
  		hide: function ()
  		{
  			this.DOM.outerWrap.style.maxHeight = '';
  			BX.removeClass(this.DOM.outerWrap, 'shown');
  		},
  
  		isShown: function ()
  		{
  			return BX.hasClass(this.DOM.outerWrap, 'shown');
  		},
  
  		handleBlockClick: function (e)
  		{
  			var target = e.target || e.srcElement;
  
  			if (target)
  			{
  				var blockValue = target.getAttribute('data-bx-remove-block');
  				if (blockValue)
  				{
  					// Remove from blocks
  					this.selectedBlocks.find(function(element, index)
  					{
  						if (element.value === blockValue)
  						{
  							BX.removeClass(element.wrap, 'shown');
  							setTimeout(BX.delegate(function ()
  							{
  								BX.remove(element.wrap)
  							}, this), 300);
  
  							this.selectedBlocks = BX.util.deleteFromArray(this.selectedBlocks, index);
  						}
  					}, this);
  
  					// Remove from values
  					this.selectedValues.find(function(element, index)
  					{
  						if (element.title === blockValue)
  						{
  							this.selectedValues = BX.util.deleteFromArray(this.selectedValues, index);
  						}
  					}, this);
  
  					if (BX.type.isFunction(this.onChangeCallback))
  					{
  						setTimeout(BX.proxy(this.onChangeCallback, this), 100);
  					}
  
  					this.checkBlockWrapState();
  				}
  
  				if (!blockValue)
  				{
  					this.openResourcesPopup();
  				}
  			}
  		},
  
  		openResourcesPopup: function ()
  		{
  			if (!this.resourceList.length)
  			{
  				return this.addResourceBlock();
  			}
  
  			if (this.isResourcesPopupShown())
  			{
  				return;
  			}
  
  			var menuItems = [];
  
  			this.resourceList.forEach(function(resource)
  			{
  				if (resource.deleted)
  				{
  					return;
  				}
  
  				menuItems.push({
  					text: BX.util.htmlspecialchars(resource.title),
  					dataset: {
  						type: resource.type,
  						id: resource.id,
  						title: resource.title
  					},
  					onclick: BX.delegate(function(e, menuItem)
  					{
  						var
  							selectAllcheckbox,
  							target = e.target || e.srcElement,
  							checkbox = menuItem.layout.item.querySelector('.menu-popup-item-resource-checkbox'),
  							foundResource = this.resourceList.find(function(resource)
  							{
  								return parseInt(resource.id) === parseInt(menuItem.dataset.id)
  									&& resource.type === menuItem.dataset.type;
  							}, this);
  
  						if (foundResource)
  						{
  							// Complete removing of the resource
  							if (target && BX.hasClass(target, "calendar-resourcebook-content-block-control-delete"))
  							{
  								this.removeResourceBlock({
  									resource: foundResource,
  									trigerOnChange: true
  								});
  								this.selectedValues = this.getSelectedValues();
  								this.checkResourceInputs();
  
  								selectAllcheckbox = this.popupContainer.querySelector('.menu-popup-item-all-resources-checkbox');
  								this.selectAllChecked = false;
  								if (selectAllcheckbox)
  								{
  									selectAllcheckbox.checked = false;
  								}
  
  								var menuItemNode = BX.findParent(target, {className: 'menu-popup-item'});
  								if (menuItemNode)
  								{
  									BX.addClass(menuItemNode, 'menu-popup-item-resource-remove-loader');
  
  									var loader = menuItemNode.appendChild(BX.Calendar.UserField.ResourceBooking.getLoader(25));
  									var textNode = menuItemNode.querySelector('.menu-popup-item-text');
  									if (textNode)
  									{
  										textNode.innerHTML = BX.message('USER_TYPE_RESOURCE_DELETING');
  									}
  								}
  
  								foundResource.deleted = true;
  								setTimeout(BX.delegate(function()
  								{
  									if (menuItemNode)
  									{
  										menuItemNode.style.maxHeight = '0';
  									}
  
  									if (!this.resourceList.find(function(resource){return !resource.deleted;}))
  									{
  										BX.PopupMenu.destroy(this.id);
  										this.DOM.selectButton.style.opacity = 0;
  
  										setTimeout(BX.delegate(function(){BX.remove(this.DOM.selectButton);}, this), 500);
  									}
  								}, this), 500);
  							}
  							else if (target && (BX.hasClass(target, "menu-popup-item") || BX.hasClass(target, "menu-popup-item-resource-checkbox") || BX.hasClass(target, "menu-popup-item-inner") ))
  							{
  								if (!BX.hasClass(target, "menu-popup-item-resource-checkbox"))
  								{
  									checkbox.checked = !checkbox.checked;
  								}
  
  								if (checkbox.checked)
  								{
  									this.addResourceBlock({
  										resource: foundResource,
  										value: foundResource.title,
  										trigerOnChange: true
  									});
  									this.selectedValues = this.getSelectedValues();
  								}
  								else
  								{
  									this.removeResourceBlock({
  										resource: foundResource,
  										trigerOnChange: true
  									});
  									this.selectedValues = this.getSelectedValues();
  									this.checkResourceInputs();
  
  									selectAllcheckbox = this.popupContainer.querySelector('.menu-popup-item-all-resources-checkbox');
  									this.selectAllChecked = false;
  									if (selectAllcheckbox)
  									{
  										selectAllcheckbox.checked = false;
  									}
  								}
  							}
  						}
  					}, this)
  				});
  			}, this);
  
  			if (menuItems.length > 1)
  			{
  				menuItems.push({
  					text: BX.message('USER_TYPE_RESOURCE_SELECT_ALL'),
  					onclick: BX.delegate(function(e, menuItem)
  					{
  						var target = e.target || e.srcElement;
  						if (target && (BX.hasClass(target, "menu-popup-item") || BX.hasClass(target, "menu-popup-item-resource-checkbox")))
  						{
  							var checkbox = menuItem.layout.item.querySelector('.menu-popup-item-resource-checkbox');
  
  							if (BX.hasClass(target, "menu-popup-item"))
  							{
  								checkbox.checked = !checkbox.checked;
  							}
  
  							var i, checkboxes = this.popupContainer.querySelectorAll('input.menu-popup-item-resource-checkbox');
  							this.selectAllChecked = checkbox.checked;
  
  							for (i = 0; i < checkboxes.length; i++)
  							{
  								checkboxes[i].checked = this.selectAllChecked;
  							}
  
  							this.resourceList.forEach(function(resource){
  								if (resource.deleted)
  								{
  									return;
  								}
  
  								if (this.selectAllChecked)
  								{
  									this.addResourceBlock({
  										resource: resource,
  										value: resource.title,
  										trigerOnChange: true
  									});
  								}
  								else
  								{
  									this.removeResourceBlock({
  										resource: resource,
  										trigerOnChange: true
  									});
  								}
  							}, this);
  
  							this.selectedValues = this.getSelectedValues();
  							this.checkResourceInputs();
  						}
  					}, this)
  				});
  			}
  
  			this.popup = BX.PopupMenu.create(
  				this.id,
  				this.DOM.selectButton || this.DOM.blocksWrap,
  				menuItems,
  				{
  					className: 'popup-window-resource-select',
  					closeByEsc : true,
  					autoHide : false,
  					offsetTop: 0,
  					offsetLeft: 0
  				}
  			);
  
  			this.popup.show(true);
  			this.popupContainer = this.popup.popupWindow.popupContainer;
  			if (!this.editMode)
  			{
  				this.popupContainer.style.width = parseInt(this.DOM.blocksWrap.offsetWidth) + 'px';
  			}
  
  			BX.addCustomEvent(this.popup.popupWindow, 'onPopupClose', BX.proxy(function(){BX.PopupMenu.destroy(this.id);}, this));
  
  			this.popup.menuItems.forEach(function(menuItem)
  			{
  				var checked;
  				if (menuItem.dataset && menuItem.dataset.type)
  				{
  					checked = this.selectedValues.find(function(item)
  					{
  						return parseInt(item.id) === parseInt(menuItem.dataset.id)
  							&& item.type === menuItem.dataset.type;
  					});
  					menuItem.layout.item.className = 'menu-popup-item';
  					menuItem.layout.item.innerHTML = '<div class="menu-popup-item-inner">' +
  						'<div class="menu-popup-item-resource">' +
  							'<input class="menu-popup-item-resource-checkbox" type="checkbox"' + (checked ? 'checked="checked"' : '') + ' id="' + menuItem.id + '">' +
  							'<label class="menu-popup-item-text" for="' + menuItem.id + '">' + BX.util.htmlspecialchars(menuItem.dataset.title) + '</label>' +
  					'</div>' +
  					(this.editMode ? '<div class="calendar-resourcebook-content-block-control-delete"></div>' : '') +
  					'</div>';
  				}
  				else
  				{
  					this.selectAllChecked = !this.resourceList.find(function(resource){
  						return !this.selectedValues.find(function(item)
  						{
  							return parseInt(item.id) === parseInt(resource.id)
  								&& item.type === resource.type
  						});
  					},this);
  
  					menuItem.layout.item.className = 'menu-popup-item menu-popup-item-resource-all';
  					menuItem.layout.item.innerHTML = '<div class="menu-popup-item-inner">' +
  						'<div class="menu-popup-item-resource">' +
  						'<input class="menu-popup-item-resource-checkbox menu-popup-item-all-resources-checkbox" type="checkbox"' + (this.selectAllChecked ? 'checked="checked"' : '') + ' id="' + menuItem.id + '">' +
  						'<label class="menu-popup-item-text" for="' + menuItem.id + '">' + BX.message('USER_TYPE_RESOURCE_SELECT_ALL') + '</label>' +
  						'</div>' +
  						'</div>';
  				}
  			}, this);
  
  			setTimeout(BX.delegate(function(){
  				BX.bind(document, 'click', BX.proxy(this.handleClick, this));
  			}, this), 50);
  		},
  
  		addResourceBlock: function(params)
  		{
  			if (!BX.type.isPlainObject(params))
  			{
  				params = {};
  			}
  
  			if ((params.resource && (this.checkLimit && !this.checkLimit() && window.B24))
  				||
  				(!params.resource && (this.checkLimitForNew && !this.checkLimitForNew() && window.B24)))
  			{
  				return BX.Calendar.UserField.ResourceBooking.showLimitationPopup();
  			}
  
  			var
  				_this = this,
  				blockEntry;
  
  			if (this.editMode)
  			{
  				if (params.resource && this.selectedValues.find(function(val)
  				{
  					return val.id && parseInt(val.id) === parseInt(params.resource.id)
  						&& val.type === params.resource.type;
  				}))
  				{
  					return;
  				}
  
  				if (!params.value)
  				{
  					params.value = '';
  				}
  
  				blockEntry = {
  					value: params.value,
  					wrap : this.DOM.listWrap
  						.appendChild(BX.create("div", {props:{className: "calendar-resourcebook-content-block-detail calendar-resourcebook-outer-resource-wrap"}}))
  						.appendChild(BX.create("div", {props:{className: "calendar-resourcebook-content-block-detail-resource"}}))
  						.appendChild(BX.create("div", {props:{className: "calendar-resourcebook-content-block-detail-resource-inner calendar-resourcebook-content-block-detail-resource-inner-wide"}}))
  				};
  
  				blockEntry.input = blockEntry.wrap.appendChild(BX.create("input", {
  					props:{
  						className: "calendar-resourcebook-content-input",
  						value: params.value,
  						type: 'text',
  						placeholder: BX.message('USER_TYPE_RESOURCE_NAME')
  					},
  					dataset: {
  						resourceType: params.resource ? params.resource.type : '',
  						resourceId: params.resource ? params.resource.id : ''
  					}
  				}));
  				blockEntry.delButton = blockEntry.wrap.appendChild(BX.create("div", {
  					props:{className: "calendar-resourcebook-content-block-control-delete"},
  					events: {click: function(){
  						BX.remove(BX.findParent(this, {className: 'calendar-resourcebook-outer-resource-wrap'}));
  						_this.selectedValues = _this.getSelectedValues();
  						_this.checkResourceInputs();
  					}}
  				}));
  
  				if (params.focusInput !== false)
  				{
  					BX.focus(blockEntry.input);
  				}
  			}
  			else
  			{
  				if (params.value && this.selectedBlocks.find(function(val){return val.value && val.value === params.value;}))
  				{
  					return;
  				}
  
  				blockEntry = {
  					value: params.value,
  					resource: params.resource || false,
  					wrap : this.DOM.blocksWrap.appendChild(BX.create("div", {
  						props:{
  							className: "calendar-resourcebook-content-block-control-inner"
  							+ (params.animation ? '' : ' shown')
  							+ (params.transparent ? ' transparent' : '')
  						},
  						children: [
  							BX.create("div", {
  								props: {className: "calendar-resourcebook-content-block-control-text"},
  								text: params.value || ''
  							}),
  							BX.create("div", {
  								attrs: {'data-bx-remove-block': params.value},
  								props: {className: "calendar-resourcebook-content-block-control-delete"}
  							})
  						]
  					}))
  				};
  
  				this.selectedBlocks.push(blockEntry);
  
  				// Show it with animation
  				if (params.animation)
  				{
  					setTimeout(BX.delegate(function ()
  					{
  						BX.addClass(blockEntry.wrap, 'shown');
  					}, this), 1);
  				}
  
  				if (params.trigerOnChange !== false && this.onChangeCallback && BX.type.isFunction(this.onChangeCallback))
  				{
  					setTimeout(BX.proxy(this.onChangeCallback, this), 100);
  				}
  
  				this.checkBlockWrapState();
  			}
  
  			// Adjust outer wrap max height
  			if (this.DOM.listWrap && this.DOM.outerWrap)
  			{
  				if (BX.hasClass(this.DOM.outerWrap, 'shown'))
  				{
  					this.DOM.outerWrap.style.maxHeight = Math.max(10000, this.DOM.listWrap.childNodes.length * 45 + 100) + 'px';
  				}
  				else
  				{
  					this.DOM.outerWrap.style.maxHeight = '';
  				}
  			}
  
  			return blockEntry;
  		},
  
  		removeResourceBlock: function(params)
  		{
  			if (this.editMode)
  			{
  				var
  					resourceType, resourceId,
  					i, inputs = this.DOM.listWrap.querySelectorAll('.calendar-resourcebook-content-input');
  
  				for (i = 0; i < inputs.length; i++)
  				{
  					resourceType = inputs[i].getAttribute('data-resource-type');
  					resourceId = inputs[i].getAttribute('data-resource-id');
  					if (resourceType === params.resource.type && parseInt(resourceId) === parseInt(params.resource.id))
  					{
  						BX.remove(BX.findParent(inputs[i], {className: 'calendar-resourcebook-outer-resource-wrap'}));
  					}
  				}
  			}
  			else
  			{
  				if (params.resource)
  				{
  					this.selectedBlocks.find(function(element, index)
  					{
  						if (element.value === params.resource.title)
  						{
  							BX.removeClass(element.wrap, 'shown');
  							setTimeout(BX.delegate(function ()
  							{
  								BX.remove(element.wrap)
  							}, this), 300);
  
  							this.selectedBlocks = BX.util.deleteFromArray(this.selectedBlocks, index);
  						}
  					}, this);
  				}
  				this.checkBlockWrapState();
  
  				if (params.trigerOnChange !== false && this.onChangeCallback && BX.type.isFunction(this.onChangeCallback))
  				{
  					setTimeout(BX.proxy(this.onChangeCallback, this), 100);
  				}
  			}
  		},
  
  		checkResourceInputs: function()
  		{
  			if (this.editMode)
  			{
  				if (!this.selectedValues.length)
  				{
  					this.addResourceBlock({animation: true});
  				}
  			}
  		},
  
  		checkBlockWrapState: function()
  		{
  			if (!this.editMode)
  			{
  				if (!this.selectedBlocks.length)
  				{
  					if (!this.DOM.emptyPlaceholder)
  					{
  						this.DOM.emptyPlaceholder = this.DOM.blocksWrap.appendChild(
  							BX.create("DIV", {
  								props : {className : "calendar-resourcebook-content-block-control-empty"},
  								html: '<span class="calendar-resourcebook-content-block-control-text">' + BX.message('USER_TYPE_RESOURCE_LIST_PLACEHOLDER') + '</span>'
  							})
  						);
  					}
  					else
  					{
  						this.DOM.emptyPlaceholder.className = "calendar-resourcebook-content-block-control-empty";
  						this.DOM.blocksWrap.appendChild(this.DOM.emptyPlaceholder);
  					}
  
  					setTimeout(BX.delegate(function(){
  						if (BX.isNodeInDom(this.DOM.emptyPlaceholder))
  						{
  							BX.addClass(this.DOM.emptyPlaceholder, 'show');
  						}
  					}, this), 50);
  				}
  				else if (this.DOM.emptyPlaceholder)
  				{
  					BX.remove(this.DOM.emptyPlaceholder);
  				}
  			}
  		},
  
  		handleClick: function(e)
  		{
  			var target = e.target || e.srcElement;
  			if (this.isResourcesPopupShown() && !BX.isParentForNode(this.popupContainer, target)
  			)
  			{
  				this.closeResourcesPopup({animation: true});
  			}
  		},
  
  		isResourcesPopupShown: function()
  		{
  			return this.popup && this.popup.popupWindow &&
  				this.popup.popupWindow.isShown && this.popup.popupWindow.isShown() &&
  				this.popup.popupWindow.popupContainer &&
  				BX.isNodeInDom(this.popup.popupWindow.popupContainer)
  		},
  
  		closeResourcesPopup: function(params)
  		{
  			if (this.popup)
  			{
  				this.popup.close();
  				this.popupContainer.style.maxHeight = '';
  				BX.unbind(document, 'click', BX.proxy(this.handleClick, this));
  			}
  		},
  
  		getValues: function()
  		{
  			return this.resourceList;
  		},
  
  		addToSelectedValues: function(value)
  		{
  			if (!this.selectedValues.find(function(val){return parseInt(val.id) === parseInt(value.id) && val.type === value.type;}))
  			{
  				this.selectedValues.push(value);
  			}
  		},
  
  		getSelectedValues: function()
  		{
  			this.selectedValues = [];
  			if (this.editMode)
  			{
  				var
  					resourceType, resourceId, i,
  					inputs = this.DOM.listWrap.querySelectorAll('.calendar-resourcebook-content-input');
  
  				for (i = 0; i < inputs.length; i++)
  				{
  					resourceType = inputs[i].getAttribute('data-resource-type');
  					resourceId = inputs[i].getAttribute('data-resource-id');
  					if (resourceType && resourceId)
  					{
  						this.selectedValues.push({type: resourceType, id: resourceId, title: inputs[i].value});
  					}
  					else
  					{
  						this.selectedValues.push({type: 'resource', title: inputs[i].value});
  					}
  				}
  			}
  			else
  			{
  				this.selectedBlocks.forEach(function(element){
  					this.selectedValues.push({type: element.resource.type, id: element.resource.id});
  				}, this);
  			}
  
  			return this.selectedValues;
  		},
  
  		getDeletedValues: function()
  		{
  			return this.resourceList.filter(function(resource){return resource.deleted;});
  		},
  
  		setValues: function(values, trigerOnChange)
  		{
  			this.selectedBlocks.forEach(function(element){BX.remove(element.wrap);});
  			this.selectedBlocks = [];
  			trigerOnChange = trigerOnChange !== false;
  
  			if (BX.type.isArray(values))
  			{
  				values.forEach(function(value)
  				{
  					var foundResource = this.resourceList.find(function(resource)
  					{
  						return parseInt(resource.id) === parseInt(value.id) && resource.type === value.type;
  					}, this);
  
  					if (foundResource)
  					{
  						this.addResourceBlock({
  							resource: foundResource,
  							value: foundResource.title,
  							trigerOnChange: trigerOnChange
  						});
  						this.addToSelectedValues(foundResource);
  					}
  				}, this);
  			}
  
  			if (this.editMode)
  			{
  				this.selectedValues = this.getSelectedValues();
  				this.checkResourceInputs();
  			}
  			else
  			{
  				if (this.DOM.arrowNode)
  				{
  					this.DOM.blocksWrap.appendChild(this.DOM.arrowNode);
  				}
  			}
  
  			this.checkBlockWrapState();
  		}
  	};
  
  	function SelectInput(params)
  	{
  		this.id = params.id || 'bx-select-input-' + Math.round(Math.random() * 1000000);
  
  		if (BX.type.isFunction(params.getValues))
  		{
  			this.getValues = params.getValues;
  			this.values = this.getValues();
  		}
  		else
  		{
  			this.values = params.values || false;
  		}
  
  		this.input = params.input;
  		this.defaultValue = params.defaultValue || '';
  		this.openTitle = params.openTitle || '';
  		this.className = params.className || '';
  		this.currentValue = params.value;
  		this.currentValueIndex = params.valueIndex;
  		this.onChangeCallback = BX.type.isFunction(params.onChangeCallback) ? params.onChangeCallback : null;
  		this.onAfterMenuOpen = params.onAfterMenuOpen || null;
  		this.zIndex = params.zIndex || 1200;
  		this.disabled = params.disabled;
  		this.editable = params.editable !== false;
  		this.setFirstIfNotFound = !!params.setFirstIfNotFound;
  
  		if (this.onChangeCallback)
  		{
  			BX.bind(this.input, 'change', this.onChangeCallback);
  			BX.bind(this.input, 'keyup', this.onChangeCallback);
  		}
  
  		this.curInd = false;
  
  		if (BX.type.isArray(this.values))
  		{
  			BX.bind(this.input, 'click', BX.proxy(this.onClick, this));
  
  			if (this.editable)
  			{
  				BX.bind(this.input, 'focus', BX.proxy(this.onFocus, this));
  				BX.bind(this.input, 'blur', BX.proxy(this.onBlur, this));
  				BX.bind(this.input, 'keyup', BX.proxy(this.onKeyup, this));
  			}
  			else
  			{
  				BX.bind(this.input, 'focus', BX.proxy(function(){this.input.blur();}, this));
  			}
  
  			if (this.currentValueIndex === undefined && this.currentValue !== undefined)
  			{
  				this.currentValueIndex = -1;
  				for (var i = 0; i < this.values.length; i++)
  				{
  					if (parseInt(this.values[i].value) === parseInt(this.currentValue))
  					{
  						this.currentValueIndex = i;
  						break;
  					}
  				}
  
  				if (this.currentValueIndex === -1)
  				{
  					this.currentValueIndex = this.setFirstIfNotFound ? 0 : undefined;
  				}
  			}
  		}
  
  		if (this.currentValueIndex !== undefined && this.values[this.currentValueIndex])
  		{
  			this.input.value = this.values[this.currentValueIndex].label;
  		}
  	}
  
  	SelectInput.prototype = {
  		showPopup: function()
  		{
  			if (this.getValues)
  			{
  				this.values = this.getValues();
  			}
  
  			if (this.shown || this.disabled || !this.values.length)
  			{
  				return;
  			}
  
  			var
  				ind = 0,
  				j = 0,
  				menuItems = [],
  				i, _this = this;
  
  			for (i = 0; i < this.values.length; i++)
  			{
  				if (this.values[i].delimiter)
  				{
  					menuItems.push(this.values[i]);
  				}
  				else
  				{
  					if ((this.currentValue && this.values[i] && this.values[i].value === this.currentValue.value)
  					|| this.input.value === this.values[i].label)
  					{
  						ind = j;
  					}
  
  					menuItems.push({
  						id: this.values[i].value + '_' + i,
  						text: this.values[i].label,
  						onclick: this.values[i].callback || (function (value, label)
  						{
  							return function ()
  							{
  								_this.input.value = label;
  								_this.popupMenu.close();
  								_this.onChange(value, label);
  							}
  						})(this.values[i].value, this.values[i].labelRaw || this.values[i].label)
  					});
  					j++;
  				}
  			}
  
  			this.popupMenu = BX.PopupMenu.create(
  				this.id,
  				this.input,
  				menuItems,
  				{
  					closeByEsc : true,
  					autoHide : true,
  					zIndex: this.zIndex,
  					offsetTop: 0,
  					offsetLeft: 0
  				}
  			);
  			this.popupMenu.popupWindow.setWidth(this.input.offsetWidth - 2);
  
  			var menuContainer = this.popupMenu.layout.menuContainer;
  			BX.addClass(this.popupMenu.layout.menuContainer, 'calendar-resourcebook-select-popup');
  			this.popupMenu.show();
  
  			var menuItem = this.popupMenu.menuItems[ind];
  			if (menuItem && menuItem.layout)
  			{
  				menuContainer.scrollTop = menuItem.layout.item.offsetTop - 2;
  			}
  
  			BX.addCustomEvent(this.popupMenu.popupWindow, 'onPopupClose', function()
  			{
  				BX.PopupMenu.destroy(_this.id);
  				_this.shown = false;
  			});
  
  			this.input.select();
  
  			if (BX.type.isFunction(this.onAfterMenuOpen))
  			{
  				this.onAfterMenuOpen(ind, this.popupMenu);
  			}
  
  			this.shown = true;
  		},
  
  		closePopup: function()
  		{
  			BX.PopupMenu.destroy(this.id);
  			this.shown = false;
  		},
  
  		onFocus: function()
  		{
  			setTimeout(BX.delegate(function(){
  				if (!this.shown)
  				{
  					this.showPopup();
  				}
  			}, this), 200);
  		},
  
  		onClick: function()
  		{
  			if (this.shown)
  			{
  				this.closePopup();
  			}
  			else
  			{
  				this.showPopup();
  			}
  		},
  
  		onBlur: function()
  		{
  			setTimeout(BX.delegate(this.closePopup, this), 200);
  		},
  
  		onKeyup: function()
  		{
  			setTimeout(BX.delegate(this.closePopup, this), 50);
  		},
  
  		onChange: function(value)
  		{
  			var val = this.input.value;
  			BX.onCustomEvent(this, 'onSelectInputChanged', [this, val, value]);
  			if (BX.type.isFunction(this.onChangeCallback))
  			{
  				this.onChangeCallback({value: val, realValue: value});
  			}
  		},
  
  		destroy: function()
  		{
  			if (this.onChangeCallback)
  			{
  				BX.unbind(this.input, 'change', this.onChangeCallback);
  				BX.unbind(this.input, 'keyup', this.onChangeCallback);
  			}
  
  			BX.unbind(this.input, 'click', BX.proxy(this.onClick, this));
  			BX.unbind(this.input, 'focus', BX.proxy(this.onFocus, this));
  			BX.unbind(this.input, 'blur', BX.proxy(this.onBlur, this));
  			BX.unbind(this.input, 'keyup', BX.proxy(this.onKeyup, this));
  
  			if (this.popupMenu)
  				this.popupMenu.close();
  			BX.PopupMenu.destroy(this.id);
  			this.shown = false;
  		},
  
  		setValue: function(value)
  		{
  			this.input.value = value;
  			if (BX.type.isArray(this.values))
  			{
  				var currentValueIndex = -1;
  				for (var i = 0; i < this.values.length; i++)
  				{
  					if (this.values[i].value === value)
  					{
  						currentValueIndex = i;
  						break;
  					}
  				}
  
  				if (currentValueIndex !== -1)
  				{
  					this.input.value = this.values[currentValueIndex].label;
  					this.currentValueIndex = currentValueIndex;
  				}
  			}
  		},
  
  		getValue: function(value)
  		{
  			return this.input.value;
  		}
  	};
  
  	function ModeSelector(params)
  	{
  		this.params = params;
  		this.outerWrap = this.create();
  	}
  
  	ModeSelector.prototype = {
  		create: function()
  		{
  			var
  				wrapNode = BX.create("span",
  					{
  						props:{className: "calendar-resourcebook-content-block-select calendar-resourcebook-mode-selector"}
  					}
  				),
  				menuItems = [
  					{
  						text: BX.message('USER_TYPE_RESOURCE_CHOOSE_RESOURCES'),
  						onclick: BX.delegate(function(e, item){
  							if (BX.type.isFunction(this.params.showResources))
  							{
  								this.params.showResources();
  							}
  							wrapNode.innerHTML = item.text;
  							this.modeSwitcherPopup.close();
  						}, this)
  					},
  					{
  						text: BX.message('USER_TYPE_RESOURCE_CHOOSE_USERS'),
  						onclick: BX.delegate(function(e, item){
  							if (BX.type.isFunction(this.params.showUsers))
  							{
  								this.params.showUsers();
  							}
  							wrapNode.innerHTML = item.text;
  							this.modeSwitcherPopup.close();
  						}, this)
  					},
  					{
  						text: BX.message('USER_TYPE_RESOURCE_CHOOSE_RESOURCES_AND_USERS'),
  						onclick: BX.delegate(function(e, item){
  							if (BX.type.isFunction(this.params.showResourcesAndUsers))
  							{
  								this.params.showResourcesAndUsers();
  							}
  							wrapNode.innerHTML = item.text;
  							this.modeSwitcherPopup.close();
  						}, this)
  					}
  				],
  				switcherId = 'mode-switcher-' + Math.round(Math.random() * 100000);
  
  
  			BX.bind(wrapNode, 'click', BX.proxy(function(){
  				if (this.modeSwitcherPopup && this.modeSwitcherPopup.popupWindow && this.modeSwitcherPopup.popupWindow.isShown())
  				{
  					return this.modeSwitcherPopup.close();
  				}
  
  				this.modeSwitcherPopup = BX.PopupMenu.create(
  					switcherId,
  					wrapNode,
  					menuItems,
  					{
  						closeByEsc : true,
  						autoHide : true,
  						offsetTop: 0,
  						offsetLeft: 20,
  						angle: true
  					}
  				);
  				this.modeSwitcherPopup.show();
  
  				BX.addCustomEvent(this.modeSwitcherPopup.popupWindow, 'onPopupClose', BX.delegate(function()
  				{
  					BX.PopupMenu.destroy(switcherId);
  					this.modeSwitcherPopup = null;
  				}, this));
  			}, this));
  
  			if (this.params.useUsers && !this.params.useResources)
  			{
  				wrapNode.innerHTML = BX.message('USER_TYPE_RESOURCE_CHOOSE_USERS');
  			}
  			else if (this.params.useUsers && this.params.useResources)
  			{
  				wrapNode.innerHTML = BX.message('USER_TYPE_RESOURCE_CHOOSE_RESOURCES_AND_USERS');
  			}
  			else
  			{
  				wrapNode.innerHTML = BX.message('USER_TYPE_RESOURCE_CHOOSE_RESOURCES');
  			}
  
  			return wrapNode;
  		},
  
  		getOuterWrap: function()
  		{
  			return this.outerWrap;
  		}
  	};
  
  
  	function ServiceList(params)
  	{
  		this.params = BX.type.isPlainObject(params) ? params : {};
  		this.outerCont = this.params.outerCont;
  		this.fieldSettings = this.params.fieldSettings || {};
  		this.create();
  	}
  
  	ServiceList.prototype = {
  		create: function()
  		{
  			this.serviceListOuterWrap = this.outerCont.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-detail-wrap calendar-resourcebook-service-list-wrap"}}));
  
  			this.durationTitleId = 'duration-title-wrap-' + Math.round(Math.random() * 100000);
  			this.servicesTitleWrap = this.serviceListOuterWrap
  				.appendChild(BX.create("div", {
  					props: {className: "calendar-resourcebook-content-block-detail-inner"},
  					html: '<div class="calendar-resourcebook-content-block-detail-resource">' +
  					'<div class="calendar-resourcebook-content-block-title">' +
  					'<span class="calendar-resourcebook-content-block-title-text">' + BX.message('USER_TYPE_RESOURCE_SERVICE_LABEL') + '</span>' +
  					'</div>' +
  					'<div id="' + this.durationTitleId + '" class="calendar-resourcebook-content-block-title calendar-resourcebook-content-block-duration-title">' +
  					'<span class="calendar-resourcebook-content-block-title-text">' + BX.message('USER_TYPE_RESOURCE_DURATION_LABEL') + '</span>' +
  					'</div>' +
  					'</div>'
  				}));
  
  			this.serviceListRowsWrap = this.serviceListOuterWrap
  				.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-detail-inner"}}))
  				.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-detail"}}));
  
  			BX.bind(this.serviceListRowsWrap, 'click', BX.delegate(this.handlePopupClick, this));
  			if (BX.type.isArray(this.fieldSettings.SERVICE_LIST) && this.fieldSettings.SERVICE_LIST.length > 0)
  			{
  				this.fieldSettings.SERVICE_LIST.forEach(function(service)
  				{
  					this.addRow(service, false);
  				}, this);
  			}
  			else
  			{
  				this.addRow(false, false);
  			}
  
  			this.serviceListAddWrap = this.serviceListOuterWrap.appendChild(BX.create("div", {props: {className: "calendar-resource-content-block-add-field"}}));
  
  			this.serviceAddButton = this.serviceListAddWrap.appendChild(BX.create("span", {
  				props: {className: "calendar-resource-content-block-add-link calendar-resource-content-block-add-link-icon"},
  				text: BX.message('USER_TYPE_RESOURCE_ADD_SERVICE'),
  				events: {click: BX.delegate(this.addRow, this)}
  			}));
  
  			BX.bind(window, 'resize', BX.proxy(this.checkDurationTitlePosition, this));
  			this.checkDurationTitlePosition();
  
  			this.show(this.fieldSettings.USE_SERVICES === 'Y');
  		},
  
  		show: function(show)
  		{
  			if (show)
  			{
  				this.serviceListOuterWrap.style.display = '';
  				BX.addClass(this.serviceListOuterWrap, 'show');
  			}
  			else
  			{
  				this.serviceListOuterWrap.style.display = 'none';
  				BX.removeClass(this.serviceListOuterWrap, 'show');
  			}
  		},
  
  		addRow: function(row, animation)
  		{
  			animation = animation !== false;
  
  			if (!BX.type.isPlainObject(row))
  			{
  				row = {name: '', duration: this.getDefaultDuration()}
  			}
  
  			var service = {
  				outerWrap: this.serviceListRowsWrap
  					.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-detail-resource calendar-resourcebook-service-row"}}))
  			};
  
  			if (animation)
  			{
  				setTimeout(function(){
  					BX.addClass(service.outerWrap, 'show');
  				}, 1);
  			}
  			else
  			{
  				BX.addClass(service.outerWrap, 'show');
  			}
  
  			service.wrap = service.outerWrap.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-detail-resource-inner"}}));
  
  			service.nameInput = service.wrap.appendChild(BX.create("input", {
  				props: {
  					className: "calendar-resourcebook-content-input calendar-resourcebook-service-input",
  					placeholder: BX.message('USER_TYPE_RESOURCE_SERVICE_PLACEHOLDER'),
  					type: "text",
  					value: row.name
  				},
  				attrs: {}
  			}));
  
  			service.durationInput = service.wrap.appendChild(BX.create("input", {
  				props: {
  					className: "calendar-resbook-duration-input calendar-resbook-field-datetime-menu",
  					type: "text",
  					value: row.duration
  				},
  				attrs: {}
  			}));
  
  			service.durationList = new BX.Calendar.UserField.ResourceBooking.SelectInput({
  				input: service.durationInput,
  				getValues: BX.proxy(function(){
  					var fullday = false;
  					if (BX.type.isFunction(this.params.getFullDayValue))
  					{
  						fullday = this.params.getFullDayValue();
  					}
  					return BX.Calendar.UserField.ResourceBooking.getDurationList(fullday);
  				}, this),
  				value: row.duration
  			});
  
  			service.deleteWrap = service.wrap.appendChild(BX.create("DIV", {
  				props: {className: "calendar-resourcebook-content-block-detail-delete"},
  				html: '<span class="calendar-resourcebook-content-block-control-delete calendar-resourcebook-content-block-control-delete-detail"></span>'
  			}));
  
  			// Adjust outer wrap max height
  			this.serviceListOuterWrap.style.maxHeight = Math.max(600, this.serviceListRowsWrap.childNodes.length * 40 + 100) + 'px';
  		},
  
  		checkDurationTitlePosition: function(timeout)
  		{
  			if (timeout !== false)
  			{
  				if (this.checkDurationTitlePositionTimeout)
  				{
  					clearTimeout(this.checkDurationTitlePositionTimeout);
  				}
  
  				this.checkDurationTitlePositionTimeout = setTimeout(BX.delegate(function(){
  
  					this.checkDurationTitlePosition(false);
  				}, this), 100);
  				return;
  			}
  
  			var durationInput = this.serviceListOuterWrap.querySelector('input.calendar-resbook-duration-input');
  			if (this.durationTitleId && BX(this.durationTitleId) && durationInput)
  			{
  				BX(this.durationTitleId).style.left = (durationInput.offsetLeft + 15) + 'px';
  			}
  		},
  
  		getDefaultDuration: function()
  		{
  			var fullday = false;
  			if (BX.type.isFunction(this.params.getFullDayValue))
  			{
  				fullday = this.params.getFullDayValue();
  			}
  			return fullday ? 1440 : 30;
  		},
  
  		clickHandler: function(e)
  		{
  			var target = e.target || e.srcElement;
  			if (BX.hasClass(target, 'calendar-resourcebook-content-block-control-delete')
  				|| BX.hasClass(target, 'calendar-resourcebook-content-block-detail-delete')) // Delete button
  			{
  				var resWrap = BX.findParent(target, {className: 'calendar-resourcebook-service-row'});
  				if (resWrap)
  				{
  					BX.removeClass(resWrap, 'show');
  					setTimeout(function(){BX.remove(resWrap);}, 500);
  					this.checkServiceRows();
  				}
  			}
  		},
  
  		getValues: function(e)
  		{
  			var
  				serviceList = [],
  				nameInput, durationInput,
  				i, rows = this.serviceListRowsWrap.querySelectorAll('.calendar-resourcebook-service-row');
  
  			for (i = 0; i < rows.length; i++)
  			{
  				if (BX.hasClass(rows[i], 'show'))
  				{
  					nameInput = rows[i].querySelector('input.calendar-resourcebook-service-input');
  					durationInput = rows[i].querySelector('input.calendar-resbook-duration-input');
  
  					if (nameInput && durationInput)
  					{
  						serviceList.push({
  							name: nameInput.value,
  							duration: BX.Calendar.UserField.ResourceBooking.parseDuration(durationInput.value)
  						});
  					}
  				}
  			}
  
  			return serviceList;
  		},
  
  		checkRows: function()
  		{
  			var serviceList = this.getValues();
  			if (!serviceList.length)
  			{
  				this.show(false);
  				if (BX.type.isFunction(this.params.onFullClearHandler))
  				{
  					this.params.onFullClearHandler();
  				}
  				this.addRow(false, false);
  			}
  		},
  
  
  		handlePopupClick: function(e)
  		{
  			var target = e.target || e.srcElement;
  			if (BX.hasClass(target, 'calendar-resourcebook-content-block-control-delete')
  				|| BX.hasClass(target, 'calendar-resourcebook-content-block-detail-delete')) // Delete button
  			{
  				var resWrap = BX.findParent(target, {className: 'calendar-resourcebook-service-row'});
  				if (resWrap)
  				{
  					BX.removeClass(resWrap, 'show');
  					setTimeout(function(){BX.remove(resWrap);}, 500);
  					this.checkRows();
  				}
  			}
  		}
  	};
  
  	function TimezoneSelector(params)
  	{
  		this.params = BX.type.isPlainObject(params) ? params : {};
  		this.DOM = {
  			outerWrap: this.params.outerWrap
  		};
  		BX.addClass(this.DOM.outerWrap, 'fields enumeration field-item');
  		this.create();
  	}
  
  	TimezoneSelector.prototype = {
  		create: function()
  		{
  			this.DOM.select = this.DOM.outerWrap.appendChild(BX.create('select'));
  			this.DOM.select.options.add(
  				new Option(
  					BX.message('USER_TYPE_LOADING_TIMEZONE_LIST'),
  					this.params.selectedValue || '',
  					true,
  					true)
  			);
  
  			this.getTimezoneList().then(
  				BX.delegate(function(timezoneList)
  				{
  					BX.remove(this.DOM.select.options[0]);
  					timezoneList.forEach(function(timezone)
  					{
  						var selected = this.params.selectedValue ? this.params.selectedValue === timezone.value : timezone.selected;
  
  						this.DOM.select.options.add(
  							new Option(
  								timezone.label,
  								timezone.value,
  								selected,
  								selected));
  					}, this);
  				}, this)
  			);
  		},
  
  		getTimezoneList: function(params)
  		{
  			params = params || {};
  			var promise = new BX.Promise();
  
  			if (!this.timezoneList || params.clearCache)
  			{
  				BX.ajax.runAction('calendar.api.calendarajax.getTimezoneList')
  					.then(BX.delegate(function (response)
  					{
  						this.timezoneList = [];
  						for (var key in response.data)
  						{
  							if (response.data.hasOwnProperty(key))
  							{
  								this.timezoneList.push({
  									value: response.data[key].timezone_id,
  									label: response.data[key].title,
  									selected: response.data[key].default
  								});
  							}
  						}
  						promise.fulfill(this.timezoneList);
  					}, this),
  					function (response) {
  						/**
  						 {
  						 "status": "error",
  						 "errors": [...]
  					 }
  						 **/
  					});
  			}
  			else
  			{
  				promise.fulfill(this.timezoneList);
  			}
  
  			return promise;
  		},
  
  		getValue: function()
  		{
  			return this.DOM.select.value;
  		}
  	};
  
  
  	function AdminSettingsViewer(params)
  	{
  		this.params = BX.type.isPlainObject(params) ? params : {};
  
  		this.DOM = {
  			outerWrap: BX(this.params.outerWrapId),
  			form: document.forms[this.params.formName]
  		};
  	}
  	AdminSettingsViewer.prototype = {
  		showLayout: function()
  		{
  			if (!this.DOM.outerWrap || !this.DOM.form)
  				return;
  
  			BX.bind(this.DOM.form, 'submit', BX.proxy(this.onSubmit, this));
  
  			BX.addClass(this.DOM.outerWrap, 'calendar-resourcebook-content calendar-resourcebook-content-admin-settings');
  
  			this.DOM.innerWrap = this.DOM.outerWrap
  				.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-wrap"}}))
  				.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-inner"}}));
  
  			var
  				fieldSettings = BX.type.isPlainObject(this.params.settings) ? this.params.settings : {},
  				resourceList = [],
  				selectedResourceList = [];
  
  			// region Users&Resources Mode selector
  			this.DOM.innerWrap.appendChild(
  				BX.create(
  					"div",
  					{
  						props: { className: "calendar-resourcebook-content-block" },
  						children:
  							[
  								BX.create(
  									"span",
  									{
  										props: {className: "calendar-resourcebook-content-block-title-text"},
  										text: BX.message('USER_TYPE_RESOURCE_CHOOSE')
  									}
  								),
  								new ModeSelector({
  									useResources: fieldSettings.USE_RESOURCES === 'Y',
  									useUsers: fieldSettings.USE_USERS === 'Y',
  									showUsers: BX.delegate(function(){
  										this.resourceList.hide();
  										this.userList.show();
  									}, this),
  									showResources: BX.delegate(function(){
  										this.resourceList.show();
  										this.userList.hide();
  									}, this),
  									showResourcesAndUsers: BX.delegate(function(){
  										this.resourceList.show();
  										this.userList.show();
  									}, this)
  								}).getOuterWrap()
  							]
  					}
  				)
  			);
  			// endregion
  
  			this.DOM.optionWrap = this.DOM.innerWrap.appendChild(BX.create(
  				"div",
  				{
  					props: { className: "calendar-resourcebook-content-block" }
  				}
  			));
  
  			// region Use Resources Option
  			this.resourcesWrap = this.DOM.optionWrap.appendChild(BX.create("div", {props: { className: "calendar-resourcebook-content-block-control-field calendar-resourcebook-content-block-control-field-add"}}));
  
  			this.resourcesTitleWrap = this.resourcesWrap
  				.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-title"}}))
  				.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-title-text"}, text: BX.message('USER_TYPE_RESOURCE_RESOURCE_CONTROL_DEFAULT_NAME') + ':'}));
  
  			this.resourcesListWrap = this.resourcesWrap.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-new-entries-wrap calendar-resourcebook-content-block-detail-inner"}}));
  
  			this.resourcesListLowControls = this.resourcesWrap.appendChild(BX.create("div", {props: {className: "calendar-resource-content-block-add-field"}}));
  
  			if (fieldSettings.RESOURCES
  				&& BX.type.isPlainObject(fieldSettings.RESOURCES['resource'])
  				&& BX.type.isArray(fieldSettings.RESOURCES['resource'].SECTIONS))
  			{
  				fieldSettings.RESOURCES['resource'].SECTIONS.forEach(function(resource)
  				{
  					resourceList.push({
  						id: resource.ID,
  						title: resource.NAME,
  						type: resource.CAL_TYPE
  					});
  				});
  			}
  
  			if (BX.type.isArray(fieldSettings.SELECTED_RESOURCES))
  			{
  				fieldSettings.SELECTED_RESOURCES.forEach(function(resource)
  				{
  					selectedResourceList.push({
  						id: resource.id,
  						type: resource.type
  					});
  				});
  			}
  
  			this.resourceList = new BX.Calendar.UserField.ResourceBooking.ResourceListSelector({
  				shown: fieldSettings.USE_RESOURCES === 'Y',
  				editMode: true,
  				outerWrap: this.resourcesWrap,
  				listWrap: this.resourcesListWrap,
  				controlsWrap: this.resourcesListLowControls,
  				values: selectedResourceList,
  				resourceList: resourceList,
  				checkLimitCallback: BX.proxy(this.checkResourceCountLimit, this)
  			});
  			// endregion
  
  			// region Users Selector
  			this.userSelectorWrap = this.DOM.optionWrap.appendChild(BX.create("div", {props: { className: "calendar-resourcebook-content-block-control-field calendar-resourcebook-content-block-control-field-add"}}));
  
  			this.usersTitleWrap = this.userSelectorWrap
  				.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-title"}}))
  				.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-title-text"}, text: BX.message('USER_TYPE_RESOURCE_USERS_CONTROL_DEFAULT_NAME') + ':'}));
  
  			this.usersListWrap = this.userSelectorWrap.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-control custom-field-item"}}));
  
  			var itemsSelected = [];
  			if (BX.type.isArray(fieldSettings.SELECTED_USERS))
  			{
  				fieldSettings.SELECTED_USERS.forEach(function(user)
  				{
  					itemsSelected.push('U' + parseInt(user));
  				});
  			}
  
  			this.userList = new BX.Calendar.UserField.ResourceBooking.UserSelector({
  				shown: fieldSettings.USE_USERS === 'Y',
  				outerWrap: this.userSelectorWrap,
  				wrapNode: this.usersListWrap,
  				socnetDestination: this.params.socnetDestination,
  				itemsSelected: itemsSelected
  			});
  			// endregion
  
  			// Region Data, Time and services
  			this.DOM.optionWrap.appendChild(
  				BX.create("hr", { props: { className: "calendar-resbook-hr"}})
  			);
  
  			this.datetimeOptionsWrap = this.DOM.optionWrap.appendChild(BX.create("div", {props: { className: "calendar-resourcebook-content-block-control-field calendar-resourcebook-content-block-control-field-add" }}));
  
  			this.datetimeOptionsWrap.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-title"}})).appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-title-text"}, text: BX.message('USER_TYPE_RESOURCE_DATETIME_BLOCK_TITLE') + ':'}));
  
  			this.datetimeOptionsInnerWrap = this.datetimeOptionsWrap.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-options"}}));
  			// endregion
  
  			//region Checkbox "Full day"
  			this.DOM.fulldayCheckBox = BX.create(
  				"input",
  				{
  					props: { type: "checkbox", checked: fieldSettings.FULL_DAY === 'Y'}
  				}
  			);
  
  			this.datetimeOptionsInnerWrap.appendChild(
  				BX.create(
  					"label",
  					{
  						props: {className: 'calendar-resourcebook-content-block-option'},
  						children:
  							[
  								this.DOM.fulldayCheckBox,
  								BX.create("span", { text: BX.message('USER_TYPE_RESOURCE_FULL_DAY') })
  							]
  					}
  				)
  			);
  			//endregion
  
  			//region Checkbox "Add services"
  			this.DOM.useServicedayCheckBox = BX.create(
  				"input",
  				{
  					props: {
  						type: "checkbox",
  						checked: fieldSettings.USE_SERVICES === 'Y'
  					},
  					events: {
  						'click' : BX.delegate(function(){
  							if (this.serviceList)
  							{
  								this.serviceList.show(this.DOM.useServicedayCheckBox.checked);
  							}
  						}, this)
  					}
  				}
  			);
  
  			this.datetimeOptionsInnerWrap.appendChild(
  				BX.create(
  					"label",
  					{
  						props: {className: 'calendar-resourcebook-content-block-option'},
  						children:
  							[
  								this.DOM.useServicedayCheckBox,
  								BX.create("span", { text: BX.message('USER_TYPE_RESOURCE_ADD_SERVICES') })
  							]
  					}
  				)
  			);
  
  			this.serviceList = new ServiceList({
  				outerCont: this.datetimeOptionsInnerWrap,
  				fieldSettings: fieldSettings,
  				getFullDayValue: BX.proxy(function(){return this.DOM.fulldayCheckBox.checked}, this)
  			});
  			//endregion
  
  			// this.timezoneSettingsWrap = this.DOM.optionWrap.appendChild(BX.create("div", {props: { className: "calendar-resourcebook-content-block-control-field calendar-resourcebook-content-block-control-field-add" }}));
  			//
  			// this.timezoneSettingsWrap
  			// 	.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-title"}}))
  			// 	.appendChild(BX.create("div", {props: {className: "calendar-resourcebook-content-block-title-text"}, text: BX.message('USER_TYPE_RESOURCE_TIMEZONE_SETTINGS_TITLE') + ':'}));
  
  			this.DOM.optionWrap.appendChild(
  				BX.create("hr", { props: { className: "calendar-resbook-hr"}})
  			);
  			//region Checkbox "Overbooking"
  			this.DOM.overbookingCheckbox = BX.create("input", {props: {type: "checkbox", checked: fieldSettings.ALLOW_OVERBOOKING === 'Y'}});
  
  			this.DOM.optionWrap.appendChild(
  				BX.create(
  					"label",
  					{
  						props: {className: 'calendar-resourcebook-content-block-option'},
  						children:
  							[
  								this.DOM.overbookingCheckbox,
  								BX.create("span", { text: BX.message('USER_TYPE_RESOURCE_OVERBOOKING') })
  							]
  					}
  				)
  			);
  			//endregion
  		},
  
  		onSubmit: function(e)
  		{
  			if (!this.DOM.inputsWrap)
  			{
  				this.DOM.inputsWrap = this.DOM.outerWrap.appendChild(BX.create("DIV"));
  			}
  			else
  			{
  				BX.cleanNode(this.DOM.inputsWrap);
  			}
  
  			var inputName = this.params.htmlControl.NAME;
  			this.DOM.inputsWrap.appendChild(BX.create('INPUT', {
  				attrs:{
  					name: inputName + '[USE_USERS]',
  					value: this.userList.isShown() ? 'Y' : 'N',
  					type: 'hidden'
  				}}));
  
  			this.DOM.inputsWrap.appendChild(BX.create('INPUT', {
  				attrs:{
  					name: inputName + '[USE_RESOURCES]',
  					value: this.resourceList.isShown() ? 'Y' : 'N',
  					type: 'hidden'
  				}}));
  
  			this.DOM.inputsWrap.appendChild(BX.create('INPUT', {
  				attrs:{
  					name: inputName + '[USE_SERVICES]',
  					value: this.DOM.useServicedayCheckBox.checked ? 'Y' : 'N',
  					type: 'hidden'
  				}}));
  
  			this.DOM.inputsWrap.appendChild(BX.create('INPUT', {
  				attrs:{
  					name: inputName + '[FULL_DAY]',
  					value: this.DOM.fulldayCheckBox.checked ? 'Y' : 'N',
  					type: 'hidden'
  				}}));
  
  			this.DOM.inputsWrap.appendChild(BX.create('INPUT', {
  				attrs:{
  					name: inputName + '[ALLOW_OVERBOOKING]',
  					value: this.DOM.overbookingCheckbox.checked ? 'Y' : 'N',
  					type: 'hidden'
  				}}));
  
  			// Selected resources
  			if (this.resourceList)
  			{
  				this.prepareFormDataInputs(this.DOM.inputsWrap, this.resourceList.getSelectedValues().concat(this.resourceList.getDeletedValues()), inputName + '[SELECTED_RESOURCES]');
  			}
  
  			// // Selected users
  			if (this.userList)
  			{
  				var SELECTED_USERS = [];
  				this.userList.getAttendeesCodesList().forEach(function(code)
  				{
  					if (code.substr(0, 1) === 'U')
  					{
  						SELECTED_USERS.push(parseInt(code.substr(1)));
  					}
  				}, this);
  
  				this.prepareFormDataInputs(this.DOM.inputsWrap, SELECTED_USERS, inputName + '[SELECTED_USERS]');
  			}
  
  			if (this.DOM.useServicedayCheckBox.checked && this.serviceList)
  			{
  				this.prepareFormDataInputs(this.DOM.inputsWrap, this.serviceList.getValues(), inputName + '[SERVICE_LIST]');
  			}
  		},
  
  		prepareFormDataInputs: function(wrap, data, inputName)
  		{
  			data.forEach(function(value, ind)
  			{
  				if (BX.type.isPlainObject(value))
  				{
  					var k;
  					for (k in value)
  					{
  						if (value.hasOwnProperty(k))
  						{
  							wrap.appendChild(BX.create('INPUT', {
  								attrs:{
  									name: inputName + '[' + ind + '][' + k + ']',
  									value: value[k],
  									type: 'hidden'
  								}}));
  						}
  					}
  				}
  				else
  				{
  					wrap.appendChild(BX.create('INPUT', {
  						attrs:{
  							name: inputName + '[' + ind + ']',
  							value: value,
  							type: 'hidden'
  						}}));
  				}
  			}, this);
  		}
  	};
  
  	BX.Calendar.UserField.ResourceBooking.SelectInput = SelectInput;
  	BX.Calendar.UserField.ResourceBooking.ResourceListSelector = ResourceListSelector;
  	BX.Calendar.UserField.ResourceBooking.UserSelector = UserSelector;
  	BX.Calendar.UserField.ResourceBooking.ServiceList = ServiceList;
  	BX.Calendar.UserField.ResourceBooking.ModeSelector = ModeSelector;
  	BX.Calendar.UserField.ResourceBooking.AdminSettingsViewer = AdminSettingsViewer;
  	BX.Calendar.UserField.ResourceBooking.plannerPopup = new PlannerPopup();
  	BX.Calendar.UserField.ResourceBooking.TimezoneSelector = TimezoneSelector;
  
  	if (!Array.prototype.find) {
  		Object.defineProperty(Array.prototype, 'find', {
  			value: function(predicate) {
  				if (this == null) {
  					throw new TypeError('"this" is null or not defined');
  				}
  				var o = Object(this);
  				var len = o.length >>> 0;
  				if (typeof predicate !== 'function') {
  					throw new TypeError('predicate must be a function');
  				}
  				var thisArg = arguments[1];
  				var k = 0;
  				while (k < len) {
  					var kValue = o[k];
  					if (predicate.call(thisArg, kValue, k, o)) {
  						return kValue;
  					}
  					k++;
  				}
  				return undefined;
  			}
  		});
  	}
  })();