(function (vendor, $, window) {
	var appName = 'Tables',
		elemCss = {
			display: 'none',
			position: 'absolute',
			boxSizing: 'border-box',
			border: '2px solid #ddd',
			resize: 'none',
			overflow: 'hidden',
			padding: '0',
			margin: '0',
			textIndent: '10px'
		},
		dtsCellChangeReqTimeout = {},
		dtsCellEditLock = {};

	if (!(appName in vendor)) {
		vendor[appName] = {};
	}
	vendor[appName].setFrontendFields = (function($table) {
		var $tableWrap = $table.parents('.supsystic-tables-wrap:first'),
			editable = $tableWrap.find('.editable'),
			selectable = $tableWrap.find('.selectable'),
			date = $tableWrap.find('.datefield');

		if($table.data('id')) {
			var currTableId = $table.data('id');
			dtsCellEditLock[currTableId] = 0;
			dtsCellChangeReqTimeout[currTableId] = false;
			$tableWrap.find('.dtsFrontendExport a')
				.on('click', function(event) {
					// prevent clicking on "link"
					if(dtsCellEditLock[currTableId]) {
						event.preventDefault();
					}
				});
		}
		this.createEditableFields($table, editable);
		this.createSelectableFields($table, selectable);
		this.createDateFields($table, date);
	});

	vendor[appName].updateAfterRedraw = (function(table){
		var id = table.data('id'),
			viewId = table.data('view-id'),
			$currentTableWrapper = $('#supsystic-table-' + viewId),
			$currentTable = $currentTableWrapper.find('#supsystic-table-' + id),
			$currentEditableFields = $currentTableWrapper.find('.editable'),
			$currentSelectableFields = $currentTableWrapper.find('.selectable'),
			$currentDateFields = $currentTableWrapper.find('.datefield');

		this.createEditableFields($currentTable, $currentEditableFields);
		this.createSelectableFields($currentTable, $currentSelectableFields);
		this.createDateFields($currentTable, $currentDateFields);
		this.setTooltipCell($currentTable);
		this.setImgLightbox($currentTable);
		if(g_stbServerSideProcessing) {
			this.setCollapsibleCell($currentTable);
		}
	});

	vendor[appName].createEditableFields = (function($table, $fields) {
		var self = this;

		if(this._useFrontendFields($table) && $fields.length) {
			var $tableWrapper = $table.parents('.supsystic-tables-wrap:first'),
				$elem = $tableWrapper.find('.inputArea');

			if(!$elem.length) {
				$elem = $('<textarea class="inputArea" />');
				$elem.css($.extend({}, elemCss, {
					textIndent: '0',
					padding: '5px',
					overflowY: 'auto'
				}));
				$elem.appendTo($tableWrapper);
				$elem = $tableWrapper.find('.inputArea');
			}
			$fields.off('click.sup').on('click.sup', function(event) {
				event.preventDefault();
				self._setEditedValueToCell($(this), $elem, $table);
			});
		}
	});

	vendor[appName].createSelectableFields = (function($table, $fields) {
		var self = this;

		if(this._useFrontendFields($table) && $fields.length) {
			var $tableWrapper = $table.parents('.supsystic-tables-wrap:first'),
				$elem = $tableWrapper.find('.selectArea');

			if(!$elem.length) {
				$elem = $('<select class="selectArea" />');
				$elem.css(elemCss);
				$elem.appendTo($tableWrapper);
				$elem = $tableWrapper.find('.selectArea');
			}
			$fields.off('click.sup').on('click.sup', function(event) {
				event.preventDefault();
				self._setEditedValueToCell($(this), $elem, $table);
			});
		}
	});

	vendor[appName].createDateFields = (function($table, $fields) {
		var self = this;

		if(this._useFrontendFields($table) && $fields.length) {
			var $tableWrapper = $table.parents('.supsystic-tables-wrap:first'),
				$elem = $tableWrapper.find('.datetimeArea');

			if(typeof $.datepicker == 'object') {
				if(!$elem.length) {
					$.datepicker.parseDate = function(format, value) {
						return moment(value, format).toDate();
					};
					$.datepicker.formatDate = function (format, value) {
						return moment(value).format(format);
					};

					$elem = $('<input type="text" class="datetimeArea" />');
					$elem.css(elemCss);
					$elem.appendTo($tableWrapper);
					$elem = $tableWrapper.find('.datetimeArea');
					$elem.datepicker({
						beforeShow: function(input, inst) {
							$('#ui-datepicker-div').addClass('stbDatePicker');	//add custom class to datepicker
						}
					});
				}
				$fields.off('click.sup').on('click.sup', function(event) {
					event.preventDefault();
					self._setEditedValueToCell($(this), $elem, $table);
				});
			}
		}
	});

	vendor[appName].setImgLightbox = (function($table) {
		if($table.data('lightbox-img') && $table.data('lightbox-img') == 'on') {
			$table.parents('.supsystic-tables-wrap:first').find('th img, td img').each(function() {
				var url = $(this).data('full') || $(this).attr('src');
				$(this).attr('href', url).attr('data-featherlight', 'image');
			});
		}
	});

	vendor[appName].setTooltipCell = (function($table) {
		$table.find('.tooltipCell').each(function() {
			var cell = $(this),
				// content = cell.html(),
				content = cell.attr('data-original-value'),
				icon = $('<i class="fa fa-info-circle"></i>');

			cell.html(icon);
			icon.tooltipster({
				content: content,
				contentAsHTML: true,
				interactive: true,
				position: 'top-left',
				updateAnimation: true,
				animation: 'swing'
			});
		});
	});

	vendor[appName]._useFrontendFields = (function($table) {
		var useFrontendFields = false,
			tableId = $table.data('id');

		if((window.useEdit && typeof(window.useEdit) != 'undefined' && typeof(window.useEdit[tableId]) != 'undefined') || (SDT_DATA.isAdmin && SDT_DATA.isPro)) {
			useFrontendFields = true;
		}
		return useFrontendFields;
	});

	vendor[appName]._setElemPosition = (function($elem, $td) {
		var params = [
			{ selector: '.dataTables_scrollHead', scroll: true },
			{ selector: '.dataTables_scrollBody', scroll: true },
			{ selector: '.dataTables_scrollFoot', scroll: true },
			{ selector: '.DTFC_LeftHeadWrapper' },
			{ selector: '.DTFC_LeftBodyWrapper' },
			{ selector: '.DTFC_LeftFootWrapper' },
			{ selector: '.DTFC_RightHeadWrapper' },
			{ selector: '.DTFC_RightBodyWrapper' },
			{ selector: '.DTFC_RightFootWrapper' },
			{ selector: 'td.child' },
			{ selector: '.dataTables_wrapper' }
		], scrollTop, scrollLeft, position;

		for(var i = 0; i < params.length; i++) {
			var parent = $td.parents(params[i].selector + ':first');

			if(parent.length) {
				parent.append($elem);
				scrollTop = params[i].scroll ? parent.scrollTop() : 0;
				scrollLeft = params[i].scroll ? parent.scrollLeft() : 0;
				position = $td.position();
				$elem.css({
					top: position.top + scrollTop,
					left: position.left + scrollLeft
				});
				break;
			}
		}
	});

	vendor[appName]._getCellType = (function($td) {
		var types = ['editable', 'selectable', 'datefield'],
			cellType = 'editable';

		for(var i = 0; i < types.length; i++) {
			if($td.hasClass(types[i])) {
				cellType = types[i];
			}
		}
		return cellType;
	});

	vendor[appName]._setEditedValueToCell = (function($td, $elem, $table) {
		var self = this,
			cellType = this._getCellType($td),
			value = $td.data('formula') ? $td.data('formula') : $td.data('original-value'),
			source = $td.data('source') && $td.data('source').length ? $td.data('source') : [],
			formula = $td.data('formula'),
			useComaAsDelimiter = $table.data('use-comma-as-delimiter'),
			triggerEvent = ((typeof($.browser) != 'undefined' && $.browser.msie) || !!navigator.userAgent.match(/Trident\/7\./))
				? 'focusout'
				: 'blur';

		this._setElemPosition($elem, $td);
		// Set element CSS styles
		$elem.css({
			width: $td.innerWidth() + 1,	// To cover cell right border
			height: $td.innerHeight() + 1,	// To cover cell bottom border
			minHeight: $td.innerHeight() + 1,
			fontSize: $td.css('font-size'),
			lineHeight: $td.css('line-height')
		});
		// To remove unneeded zeros from end of percent values, e.g. 15.230000000001
		if(!formula && $td.data('cell-format-type') == 'percent') {
			value = this._preparePercentValue(value, $td.data('cell-format'));
		}
		switch(cellType) {
			case 'editable':
				if (useComaAsDelimiter && value.toString().match(/^-{0,1}\d+\.{0,1}\d*$/)) {
					value = value.toString().replace('.', ',');
				}
				break;
			case 'selectable':
				$elem.html('');
				for(var i = 0; i < source.length; i++) {
					var selected = source[i] == value ? 'selected="selected"' : '';
					$elem.append('<option ' + selected + '>' + source[i] + '</option>');
				}
				break;
			case 'datefield':
				var isDate = $td.data('cell-format-type') == 'date' && typeof $td.data('cell-format') != 'undefined',
					format = isDate ? $td.data('cell-format') : $table.data('date-format'),
					defDate = isDate && value ? value : moment().format(format);

				value = isDate && value ? value : defDate;
				$elem.datepicker('option', 'dateFormat', format);
				$elem.datepicker('option', 'defaultDate', defDate);
				break;
			default:
				break;
		}
		if(cellType != 'selectable') {
			$elem.off('keypress').on('keypress', function(event) {
				if ((event.keyCode || event.which) == 13) {	// Enter button
					event.preventDefault();
					var $this = $(this);
					$this.trigger(triggerEvent);
					if(cellType == 'datefield') {
						$this.datepicker('hide');
					}
					return true;
				}
			});
			$elem.val(value);
		}
		$elem.off('keydown').on('keydown', function(event) {
			if ((event.keyCode || event.which) == 9) {	// Tab button
				event.preventDefault();
				var $this = $(this),
					$fields = $table.find('.editable, .selectable, .datefield'),
					nextIndex = self._getNextVisibleIndex($fields, $fields.index($td) + 1);

				$this.trigger(triggerEvent);
				if(cellType == 'datefield') {
					$this.datepicker('hide');
				}
				if(nextIndex > 0) {
					$fields.eq(nextIndex).trigger('click');
				}
			}
		});
		if(cellType == 'datefield') {
			$elem.datepicker('option', 'onClose', function() {
				$('#ui-datepicker-div').removeClass('stbDatePicker');
				self._updateTableCell(cellType, $elem, $td, $table);
			});
		} else {
			$elem.off(triggerEvent).on(triggerEvent, function() {
				self._updateTableCell(cellType, $elem, $td, $table);
			});
		}
		$elem.show().focus().select();
	});

	vendor[appName]._updateTableCell = (function(cellType, $elem, $td, $table) {
		var self = this,
			newValue = $.trim($elem.val()),
			originalValue = typeof $td.data('original-value') != 'undefined',
			oldValue = (originalValue ? $td.data('original-value') : ''),
			formula = typeof $td.data('formula') != 'undefined',
			tableId = $table.data('id'),
			history = $table.data('from-history'),
			period = $table.data('history-period'),
			dataTableInstance = this.getTableInstanceById(tableId),
			_ruleJS = this.getRuleJSInstance($table),
			cells = [];

		if ($table.data('use-comma-as-delimiter') && newValue.toString().match(/^-{0,1}\d+\,{0,1}\d*$/)) {
			newValue = newValue.toString().replace(',', '.');
		}

		// Set formula value
		if (formula) {
			$td.data('formula', newValue);
			$td.attr('data-formula', newValue);
		}
		// Set original value for cells without formulas
		if (originalValue && !formula) {
			if(cellType == 'editable' && $td.data('cell-format-type') == 'percent') {
				newValue = this._preparePercentValue(newValue, $td.data('cell-format'), true);
			}
			// We need to update edited cell here for correct work of _ruleJS.init();
			$td.data('original-value',newValue);
			$td.attr('data-original-value',newValue);
			$td.data('order',newValue);
			$td.attr('data-order',newValue);
		}
		$elem.hide();
		$td.html(newValue);
		if($table.data('mark-last-edited-cell')) {
			$table.parents('.supsystic-tables-wrap').find('th, td').removeClass('justEdited');
			$td.addClass('justEdited');
		}

		// Parse formulas
		_ruleJS.init();

		// Set data for edited cell
		var dbEditData = $table.closest('.supsystic-tables-wrap').find('.stbDBEditData'),
			dbTable = '',
			uniqFields = '',
			isDB = (dbEditData.length);

		if (isDB) {
			if(originalValue && oldValue == newValue) {
				return;
			}
			if($table.data('save-editable-fields')) {
				var error = (dbEditData.data('error')),
					dbTable = dbEditData.data('table');
				if(error && error.length > 0){
					alert(error);
				} else if(!dbTable || dbTable.length == 0){
					alert('Table not found.');
				} else {
					var dbFields = dbEditData.data('fields'),
						uniqFields = dbEditData.data('unique-fields'),
						uniqData = dbEditData.data('unique-data'),
						fieldNum = $td.data('x'),
						rowNum = $td.data('y');
					if (fieldNum in dbFields && rowNum in uniqData) {
						cells.push({
							c: fieldNum,
							f: dbFields[fieldNum],
							r: rowNum,
							u: uniqData[rowNum],
							v: formula ? '=' + $td.data('formula') : newValue,
							ov: formula ? $.trim($td.html()) : newValue
						});
					}
				}
			}
		} else {
			cells.push({
				c: $td.data('x'),
				r: $td.data('y'),
				v: formula ? '=' + $td.data('formula') : newValue,
				ov: formula ? $.trim($td.html()) : newValue
			});
		}

		// Set original value for edited cell with formula
		// We need to set unformat value which we get after ruleJS init
		if (originalValue && formula) {
			var newOriginalValue = $.trim($td.html());

			$td.data('original-value', newOriginalValue);
			$td.attr('data-original-value', newOriginalValue);
			$td.data('order',newOriginalValue);
			$td.attr('data-order',newOriginalValue);
		}

		// Update other table cells before setting format to table
		$table.find('th, td').each(function(index, elem) {
			var $elem = $(elem);

			// Break if current cell is current edited cell
			if($elem.data('x') == $td.data('x') && $elem.data('y') == $td.data('y')) return;

			var	$elemValue = $.trim($elem.html()),
				$elemOrValue = $elem.data('original-value') || '',
				$elemFormula = $elem.data('formula') || '';

			if(!isDB && $elemFormula && $elemOrValue != $elemValue) {
				$elem.data('original-value',$elemValue);
				$elem.attr('data-original-value',$elemValue);
				$elem.data('order',$elemValue);
				$elem.attr('data-order',$elemValue);
				cells.push({
					c: $elem.data('x'),
					r: $elem.data('y'),
					v: $elemFormula ? '=' + $elemFormula : $elemValue,
					ov: $elemValue
				});
			}

		});
		// Parse formulas again to correct calculation of formulas, which is dependent to the follow placed cells
		// TODO: find the way to check how many times we need to recalc formulas to get final result
		_ruleJS.init();

		// Set formats
		this.formatDataAtTable($table);

		//save formated values (need for export)
		$.each(cells, function(index, elem) {
			var cell = $table.find('[data-x="' + elem['c'] + '"][data-y="' + elem['r'] + '"]');
			if(cell.length == 1) {
				elem['fv'] = cell.html();
			}
		});

		// Update table sorting
		if(dataTableInstance && !g_stbServerSideProcessing) {
			$table.find('th, td').each(function() {
				dataTableInstance.api().cell($(this)).invalidate();
			});
			if(typeof dataTableInstance.fnAdjustColumnSizing == 'function' ) {
				dataTableInstance.fnAdjustColumnSizing(false);
			}
		}

		// Set conditional formatting
		this.setConditionalFormatting($table, true);

		if($table.data('save-editable-fields') && cells.length > 0) {
			if(dtsCellChangeReqTimeout[tableId]) {
				clearTimeout(dtsCellChangeReqTimeout[tableId]);
			}
			dtsCellChangeReqTimeout[tableId] = setTimeout(function() {
				dtsCellEditLock[tableId]++;
				self.request({
						'module': 'tables',
						'action': 'saveEditableFields'
					}, {
						'id': tableId,
						'isSSP': (g_stbServerSideProcessing ? 1 : 0),
						'isDB': (isDB ? 1 : 0),
						'dbTable': dbTable,
						'uniqFields': JSON.stringify(uniqFields),
						'cells': JSON.stringify(cells),
						'history': history,
						'period': period ? period : null
				})
				.always(function(responce) {
					if(isDB && responce) {
						if(responce.success) {
							var needSave = false,
								uniqNum;

							for(var i = 0; i < cells.length; i++) {
								uniqNum = $.inArray(cells[i].f, uniqFields);
								if(uniqNum >= 0) {
									uniqData[cells[i].r][uniqNum] = cells[i].v;
									needSave = true;
								}
							}
							if(needSave) {
								dbEditData.data('unique-data', uniqData);
							}
						} else {
							alert(responce);
						}
					}
					dtsCellEditLock[tableId]--;
					dtsCellChangeReqTimeout[tableId] = false;
				});
			}, 400);
		}

		//Refresh diagrams
		if(typeof g_stbGoogleCharts != "undefined" && g_stbGoogleCharts.length > 0) {
			for(var i = 0; i < g_stbGoogleCharts.length; i++) {
				if(g_stbGoogleCharts[i].chartData.table_id == tableId) {
					var rangeFrom = g_stbGoogleCharts[i].chartData.selection.from,
						rangeTo = g_stbGoogleCharts[i].chartData.selection.to,
						buffer;
					if (rangeFrom.row > rangeTo.row) {
						buffer = rangeFrom.row;
						rangeFrom.row = rangeTo.row;
						rangeTo.row = buffer;
					}
					if (rangeFrom.col > rangeTo.col) {
						buffer = rangeFrom.col;
						rangeFrom.col = rangeTo.col;
						rangeTo.col = buffer;
					}
					for(var c = 0; c < cells.length; c++) {
						var cell = cells[c];
						if(cell.r >= (rangeFrom.row + 1) && cell.r <= (rangeTo.row + 1) && cell.c >= rangeFrom.col && cell.c <= rangeTo.col) {
							var params = g_stbGoogleCharts[i].chartData.params,
								row = params.switchRowsColumns ? cell.c - rangeFrom.col : cell.r - rangeFrom.row - (params.useFirstRow ? 1 :0),// - 1,
								col = params.switchRowsColumns ? cell.r - rangeFrom.row - (params.useFirstRow ? 1 :0) : cell.c - rangeFrom.col + (params.useFirstColumn ? 0 :1),
								newVar = (typeof g_stbGoogleCharts[i].chartData.rangeData[row][col] == 'string' ? cell.v : Number(cell.v) + 0);

							g_stbGoogleCharts[i].chartData.rangeData[row][col] = (g_stbGoogleCharts[i].chartData.rangeData[row][col] === '' && row == 0 ? '' : newVar);
							drawCharts(g_stbGoogleCharts[i], i);
						}
					}
				}
			}
		}
	});

	vendor[appName]._preparePercentValue = (function(value, format, reverse) {
		reverse = reverse ? reverse : false;

		if(this.isNumber(value)) {
			var round = format.match(/\d+/g),
				index = round.length - 1,
				fixed = round[index] ? round[index].length : 0;

			value = reverse ? (value/100) : (value*100);

			return reverse ? value : value.toFixed(fixed);
		}
		return value;
	});

	vendor[appName]._getNextVisibleIndex = (function($elem, index) {
		if(index >= $elem.length) return -1;

		if(!$elem.eq(index).is(':visible')) {
			index++;
			index = this._getNextVisibleIndex($elem, index);
		}
		return index;
	});

	vendor[appName].initConditions = (function(elem) {
		if(this.Editor && this.Editor._Conditions) {
			this.Editor.Conditions = new this.Editor._Conditions(elem, true);
		}
	});

	vendor[appName].setConditionalFormatting = (function($table, reinit) {
		// Apply conditional formatting
		reinit = reinit ? reinit : false;

		var self = this,
			tableWrapper = $table.parents('.supsystic-tables-wrap:first'),
			conditionsElem = tableWrapper.find('.stbConditionsData'),
			conditionsList = conditionsElem.data('conditions');

		if(typeof(conditionsList) == 'undefined' || conditionsList.length == 0) {
			return;
		}
		var cells = $table.data('responsive-mode') == 2
				? tableWrapper.find('.dataTables_scrollHead th, .dataTables_scrollFoot th, .dataTables_scrollBody td')
				: tableWrapper.find('th, td');

		if(!this.Editor.Conditions) {
			this.initConditions(conditionsElem);
		}
		cells.each(function () {
			self.applyConditionsToCell(this, conditionsList, tableWrapper, reinit);
		});
		if(!reinit) {
			$table.bind('column-visibility.dt draw.dt', function (e) {
				var tableWrapper = $table.parents('.supsystic-tables-wrap:first'),
					cells = $table.data('responsive-mode') == 2
						? tableWrapper.find('.dataTables_scrollHead th, .dataTables_scrollFoot th, .dataTables_scrollBody td')
						: tableWrapper.find('th, td');

				cells.each(function () {
					self.applyConditionsToCell(this, conditionsList, tableWrapper);
				});
			});
		}
	});

	vendor[appName].applyConditionsToCell = (function(cell, conditionsList, tableWrapper, reinit) {
		cell = cell instanceof jQuery ? cell : $(cell);
		reinit = reinit ? reinit : false;

		var conditions = this.Editor.Conditions;

		if(reinit) {
			conditions.clearElemStyles(cell);
			this.setStylesToCell(cell);
		}
		conditions.setConditionToCell(cell.data('y') - 1, cell.data('x'), cell.data('original-value'), cell, conditionsList, tableWrapper);
	});

	vendor[appName].setCollapsibleCell = (function($table) {
		var self = this;

		if($table.has('.collapsibleCell').length) {
			var collapsibleIndex  = Math.floor(Math.random() * 99999),
				collapsibleClass = 'collapsibleRow_' + collapsibleIndex,
				collapsibleGroupMain = true;

			$table.find('tr').each(function() {
				var row = $(this);

				if(row.has('.collapsibleCell').length) {
					row.addClass(collapsibleClass);
					if(collapsibleGroupMain) {
						var curCollapsibleClass = collapsibleClass;
						row.addClass('collapsibleRowMain');
						row.off('click').on('click', function() {
							var curRow = $(this);

							curRow.toggleClass('collapsibleRowOpen');
							$table.find('.' + curCollapsibleClass + ':not(.collapsibleRowMain)').toggleClass('collapsibleRowHide');

							if(curRow.hasClass('collapsibleRowOpen')) {
								curRow.trigger('collapsible.sup');
							}
						});
						collapsibleGroupMain = false;
					} else {
						row.addClass('collapsibleRowHide');
					}
				} else {
					collapsibleIndex++;
					collapsibleClass = 'collapsibleRow_' + collapsibleIndex;
					collapsibleGroupMain = true;
				}
			});
			$table.on('search.dt', function(e) {
				if(g_stbServerSideProcessing) {
					g_stbServerSideProcessingIsActive = true;
				}
				var table = $(this),
					tableSelector = '#supsystic-table-' + table.data('view-id') + ' #supsystic-table-' + table.data('id');
				self.applyTableEventClb(self.searchEventPro, 50, tableSelector);
			});
		}
	});

	vendor[appName].searchEventPro = (function(tableSelector) {
		var table = $(tableSelector),
			searchInput = table.parents('.supsystic-tables-wrap').find('.dataTables_filter input[type="search"]');

		if(searchInput.length) {
			if(searchInput.val()) {
				table.find('.collapsibleRowMain').addClass('collapsibleRowOpen');
				table.find('.collapsibleRowHide').addClass('collapsibleSearchMode');
			} else {
				table.find('.collapsibleRowMain').removeClass('collapsibleRowOpen');
				table.find('.collapsibleRowHide').removeClass('collapsibleSearchMode');
			}
		}
	});

	vendor[appName].drawDiagramsInTable = (function(tableSelector) {
		var table = $(tableSelector),
			tableWrapper = table.parents('.supsystic-tables-wrap:first'),
			$diagramsInTable = tableWrapper.find('.supsystic-table-diagram');

		// search.dt event triggers during first load of table, so drawCharts function may be not existed yet
		if($diagramsInTable.length && typeof drawCharts == 'function') {
			drawCharts($diagramsInTable);
		}
	});

	vendor[appName].globalPageSearchClb = (function(e) {
		// Tab, ArrowUp, ArrowLeft, ArrowRight, ArrowDown buttons
		if (toeInArray((e.keyCode || e.which), [9, 37, 38, 39, 40]) != -1) return false;

		var input = $(this),
			value = $.fn.dataTable.util.escapeRegex(input.val()),
			tables = vendor[appName].getAllTableInstances();

		if(tables.length) {
			for(var i = 0; i < tables.length; i++) {
				tables[i].api().search(value, false, false).draw();
			}
		}
	});

	vendor[appName]._beforeInitializeTable = (function($table) {
		// Add collapsible rows
		this.setCollapsibleCell($table);
	});

	vendor[appName]._beforeShowTable = (function($table) {
		var self = this;

		// Create tooltip cells
		this.setTooltipCell($table);
		if(g_stbServerSideProcessing) {
			// Add collapsible rows
			this.setCollapsibleCell($table);
		}

		//for empty first collapsible row
		$table.find('.collapsibleRowMain').each(function() {
			var row = $(this);
			if(row.height() < 28) {
				row.css('height', parseInt(row.find(':first-child').css('line-height')) + 16 + 'px');
			}
		});

		$table.on('column-visibility.dt page.dt search.dt collapsible.sup', function(e) {
			// Fix of displaying diagrams in the tables with next features: pagination, Automatic Column Hiding response mode, sorting.
			// Fix of displaying diagrams in the tables search results.
			if(e.namespace == 'dt' && toeInArray(e.type, ['page', 'search']) && g_stbServerSideProcessing) {
				g_stbServerSideProcessingIsActive = true;
			}
			var table = $(this),
				tableSelector = '#supsystic-table-' + table.data('view-id') + ' #supsystic-table-' + table.data('id');
			self.applyTableEventClb(self.drawDiagramsInTable, 50, tableSelector);
		});
		if(g_stbServerSideProcessing) {
			var tableSelector = '#supsystic-table-' + $table.data('view-id') + ' #supsystic-table-' + $table.data('id');
			self.applyTableEventClb(self.drawDiagramsInTable, 50, tableSelector);
		}

		// Set conditional formatting
		this.setConditionalFormatting($table);
	});

	vendor[appName].initTablesOnPage = (function() {
		this._initTablesOnPagePro();
		this._initTablesOnPage();
	});

	vendor[appName]._initTablesOnPagePro = (function() {
		var supsysticTables = $('.supsystic-table'),
			globalPageSearchInput = $('.supsystic-tables-global-page-search');

		// Set callbacks to table
		supsysticTables.each(function () {
			var $curTable = $(this);

			$curTable.on('beforeInitializeTable', function() {
				if(globalPageSearchInput.length) {
					vendor[appName].setExtraConfig('searching', true);
				}
				vendor[appName]._beforeInitializeTable($curTable);
			});
			$curTable.on('beforeShowTable', function() {
				vendor[appName]._beforeShowTable($curTable);
			});
		});

		// Global Table Search
		if(globalPageSearchInput.length) {
			var focusOutEvent = ((typeof($.browser) != 'undefined' && $.browser.msie) || !!navigator.userAgent.match(/Trident\/7\./))
				? 'focusout'
				: 'blur';
			globalPageSearchInput.on(focusOutEvent, function(e) {
				vendor[appName].globalPageSearchClb.call(this, e);
			});
			globalPageSearchInput.on('keydown', function(e) {
				var self = this;
				setTimeout(function() {
					vendor[appName].globalPageSearchClb.call(self, e);
				}, 10);
			});
		}
	});
}(window.supsystic = window.supsystic || {}, window.jQuery, window));
