mirror of
https://github.com/tuxis-ie/nsedit.git
synced 2025-06-06 00:37:25 +03:00
Merge commit '8997d5b1ff
' as 'jtable'
This commit is contained in:
commit
d90fb0d2a6
155 changed files with 22323 additions and 0 deletions
461
jtable/dev/jquery.jtable.dynamiccolumns.js
Normal file
461
jtable/dev/jquery.jtable.dynamiccolumns.js
Normal file
|
@ -0,0 +1,461 @@
|
|||
/************************************************************************
|
||||
* DYNAMIC COLUMNS extension for jTable *
|
||||
* (Show/hide/resize columns) *
|
||||
*************************************************************************/
|
||||
(function ($) {
|
||||
|
||||
//Reference to base object members
|
||||
var base = {
|
||||
_create: $.hik.jtable.prototype._create,
|
||||
_normalizeFieldOptions: $.hik.jtable.prototype._normalizeFieldOptions,
|
||||
_createHeaderCellForField: $.hik.jtable.prototype._createHeaderCellForField,
|
||||
_createCellForRecordField: $.hik.jtable.prototype._createCellForRecordField
|
||||
};
|
||||
|
||||
//extension members
|
||||
$.extend(true, $.hik.jtable.prototype, {
|
||||
|
||||
/************************************************************************
|
||||
* DEFAULT OPTIONS / EVENTS *
|
||||
*************************************************************************/
|
||||
|
||||
options: {
|
||||
tableId: undefined,
|
||||
columnResizable: true,
|
||||
columnSelectable: true
|
||||
},
|
||||
|
||||
/************************************************************************
|
||||
* PRIVATE FIELDS *
|
||||
*************************************************************************/
|
||||
|
||||
_$columnSelectionDiv: null,
|
||||
_$columnResizeBar: null,
|
||||
_cookieKeyPrefix: null,
|
||||
_currentResizeArgs: null,
|
||||
|
||||
/************************************************************************
|
||||
* OVERRIDED METHODS *
|
||||
*************************************************************************/
|
||||
|
||||
/* Overrides _addRowToTableHead method.
|
||||
*************************************************************************/
|
||||
|
||||
_create: function () {
|
||||
base._create.apply(this, arguments);
|
||||
|
||||
this._createColumnResizeBar();
|
||||
this._createColumnSelection();
|
||||
|
||||
if (this.options.saveUserPreferences) {
|
||||
this._loadColumnSettings();
|
||||
}
|
||||
|
||||
this._normalizeColumnWidths();
|
||||
},
|
||||
|
||||
/* Normalizes some options for a field (sets default values).
|
||||
*************************************************************************/
|
||||
_normalizeFieldOptions: function (fieldName, props) {
|
||||
base._normalizeFieldOptions.apply(this, arguments);
|
||||
|
||||
//columnResizable
|
||||
if (this.options.columnResizable) {
|
||||
props.columnResizable = (props.columnResizable != false);
|
||||
}
|
||||
|
||||
//visibility
|
||||
if (!props.visibility) {
|
||||
props.visibility = 'visible';
|
||||
}
|
||||
},
|
||||
|
||||
/* Overrides _createHeaderCellForField to make columns dynamic.
|
||||
*************************************************************************/
|
||||
_createHeaderCellForField: function (fieldName, field) {
|
||||
var $headerCell = base._createHeaderCellForField.apply(this, arguments);
|
||||
|
||||
//Make data columns resizable except the last one
|
||||
if (this.options.columnResizable && field.columnResizable && (fieldName != this._columnList[this._columnList.length - 1])) {
|
||||
this._makeColumnResizable($headerCell);
|
||||
}
|
||||
|
||||
//Hide column if needed
|
||||
if (field.visibility == 'hidden') {
|
||||
$headerCell.hide();
|
||||
}
|
||||
|
||||
return $headerCell;
|
||||
},
|
||||
|
||||
/* Overrides _createHeaderCellForField to decide show or hide a column.
|
||||
*************************************************************************/
|
||||
_createCellForRecordField: function (record, fieldName) {
|
||||
var $column = base._createCellForRecordField.apply(this, arguments);
|
||||
|
||||
var field = this.options.fields[fieldName];
|
||||
if (field.visibility == 'hidden') {
|
||||
$column.hide();
|
||||
}
|
||||
|
||||
return $column;
|
||||
},
|
||||
|
||||
/************************************************************************
|
||||
* PUBLIC METHODS *
|
||||
*************************************************************************/
|
||||
|
||||
/* Changes visibility of a column.
|
||||
*************************************************************************/
|
||||
changeColumnVisibility: function (columnName, visibility) {
|
||||
this._changeColumnVisibilityInternal(columnName, visibility);
|
||||
this._normalizeColumnWidths();
|
||||
if (this.options.saveUserPreferences) {
|
||||
this._saveColumnSettings();
|
||||
}
|
||||
},
|
||||
|
||||
/************************************************************************
|
||||
* PRIVATE METHODS *
|
||||
*************************************************************************/
|
||||
|
||||
/* Changes visibility of a column.
|
||||
*************************************************************************/
|
||||
_changeColumnVisibilityInternal: function (columnName, visibility) {
|
||||
//Check if there is a column with given name
|
||||
var columnIndex = this._columnList.indexOf(columnName);
|
||||
if (columnIndex < 0) {
|
||||
this._logWarn('Column "' + columnName + '" does not exist in fields!');
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if visibility value is valid
|
||||
if (['visible', 'hidden', 'fixed'].indexOf(visibility) < 0) {
|
||||
this._logWarn('Visibility value is not valid: "' + visibility + '"! Options are: visible, hidden, fixed.');
|
||||
return;
|
||||
}
|
||||
|
||||
//Get the field
|
||||
var field = this.options.fields[columnName];
|
||||
if (field.visibility == visibility) {
|
||||
return; //No action if new value is same as old one.
|
||||
}
|
||||
|
||||
//Hide or show the column if needed
|
||||
var columnIndexInTable = this._firstDataColumnOffset + columnIndex + 1;
|
||||
if (field.visibility != 'hidden' && visibility == 'hidden') {
|
||||
this._$table
|
||||
.find('>thead >tr >th:nth-child(' + columnIndexInTable + '),>tbody >tr >td:nth-child(' + columnIndexInTable + ')')
|
||||
.hide();
|
||||
} else if (field.visibility == 'hidden' && visibility != 'hidden') {
|
||||
this._$table
|
||||
.find('>thead >tr >th:nth-child(' + columnIndexInTable + '),>tbody >tr >td:nth-child(' + columnIndexInTable + ')')
|
||||
.show()
|
||||
.css('display', 'table-cell');
|
||||
}
|
||||
|
||||
field.visibility = visibility;
|
||||
},
|
||||
|
||||
/* Prepares dialog to change settings.
|
||||
*************************************************************************/
|
||||
_createColumnSelection: function () {
|
||||
var self = this;
|
||||
|
||||
//Create a div for dialog and add to container element
|
||||
this._$columnSelectionDiv = $('<div />')
|
||||
.addClass('jtable-column-selection-container')
|
||||
.appendTo(self._$mainContainer);
|
||||
|
||||
this._$table.children('thead').bind('contextmenu', function (e) {
|
||||
if (!self.options.columnSelectable) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
//Make an overlay div to disable page clicks
|
||||
$('<div />')
|
||||
.addClass('jtable-contextmenu-overlay')
|
||||
.click(function () {
|
||||
$(this).remove();
|
||||
self._$columnSelectionDiv.hide();
|
||||
})
|
||||
.bind('contextmenu', function () { return false; })
|
||||
.appendTo(document.body);
|
||||
|
||||
self._fillColumnSelection();
|
||||
|
||||
//Calculate position of column selection list and show it
|
||||
|
||||
var containerOffset = self._$mainContainer.offset();
|
||||
var selectionDivTop = e.pageY - containerOffset.top;
|
||||
var selectionDivLeft = e.pageX - containerOffset.left;
|
||||
|
||||
var selectionDivMinWidth = 100; //in pixels
|
||||
var containerWidth = self._$mainContainer.width();
|
||||
|
||||
//If user clicks right area of header of the table, show list at a little left
|
||||
if ((containerWidth > selectionDivMinWidth) && (selectionDivLeft > (containerWidth - selectionDivMinWidth))) {
|
||||
selectionDivLeft = containerWidth - selectionDivMinWidth;
|
||||
}
|
||||
|
||||
self._$columnSelectionDiv.css({
|
||||
left: selectionDivLeft,
|
||||
top: selectionDivTop,
|
||||
'min-width': selectionDivMinWidth + 'px'
|
||||
}).show();
|
||||
});
|
||||
},
|
||||
|
||||
/* Prepares content of settings dialog.
|
||||
*************************************************************************/
|
||||
_fillColumnSelection: function () {
|
||||
var self = this;
|
||||
|
||||
var $columnsUl = $('<ul></ul>')
|
||||
.addClass('jtable-column-select-list');
|
||||
for (var i = 0; i < this._columnList.length; i++) {
|
||||
var columnName = this._columnList[i];
|
||||
var field = this.options.fields[columnName];
|
||||
|
||||
//Crete li element
|
||||
var $columnLi = $('<li></li>').appendTo($columnsUl);
|
||||
|
||||
//Create label for the checkbox
|
||||
var $label = $('<label for="' + columnName + '"></label>')
|
||||
.append($('<span>' + (field.title || columnName) + '</span>'))
|
||||
.appendTo($columnLi);
|
||||
|
||||
//Create checkbox
|
||||
var $checkbox = $('<input type="checkbox" name="' + columnName + '">')
|
||||
.prependTo($label)
|
||||
.click(function () {
|
||||
var $clickedCheckbox = $(this);
|
||||
var clickedColumnName = $clickedCheckbox.attr('name');
|
||||
var clickedField = self.options.fields[clickedColumnName];
|
||||
if (clickedField.visibility == 'fixed') {
|
||||
return;
|
||||
}
|
||||
|
||||
self.changeColumnVisibility(clickedColumnName, $clickedCheckbox.is(':checked') ? 'visible' : 'hidden');
|
||||
});
|
||||
|
||||
//Check, if column if shown
|
||||
if (field.visibility != 'hidden') {
|
||||
$checkbox.attr('checked', 'checked');
|
||||
}
|
||||
|
||||
//Disable, if column is fixed
|
||||
if (field.visibility == 'fixed') {
|
||||
$checkbox.attr('disabled', 'disabled');
|
||||
}
|
||||
}
|
||||
|
||||
this._$columnSelectionDiv.html($columnsUl);
|
||||
},
|
||||
|
||||
/* creates a vertical bar that is shown while resizing columns.
|
||||
*************************************************************************/
|
||||
_createColumnResizeBar: function () {
|
||||
this._$columnResizeBar = $('<div />')
|
||||
.addClass('jtable-column-resize-bar')
|
||||
.appendTo(this._$mainContainer)
|
||||
.hide();
|
||||
},
|
||||
|
||||
/* Makes a column sortable.
|
||||
*************************************************************************/
|
||||
_makeColumnResizable: function ($columnHeader) {
|
||||
var self = this;
|
||||
|
||||
//Create a handler to handle mouse click event
|
||||
$('<div />')
|
||||
.addClass('jtable-column-resize-handler')
|
||||
.appendTo($columnHeader.find('.jtable-column-header-container')) //Append the handler to the column
|
||||
.mousedown(function (downevent) { //handle mousedown event for the handler
|
||||
downevent.preventDefault();
|
||||
downevent.stopPropagation();
|
||||
|
||||
var mainContainerOffset = self._$mainContainer.offset();
|
||||
|
||||
//Get a reference to the next column
|
||||
var $nextColumnHeader = $columnHeader.nextAll('th.jtable-column-header:visible:first');
|
||||
if (!$nextColumnHeader.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Store some information to be used on resizing
|
||||
var minimumColumnWidth = 10; //A column's width can not be smaller than 10 pixel.
|
||||
self._currentResizeArgs = {
|
||||
currentColumnStartWidth: $columnHeader.outerWidth(),
|
||||
minWidth: minimumColumnWidth,
|
||||
maxWidth: $columnHeader.outerWidth() + $nextColumnHeader.outerWidth() - minimumColumnWidth,
|
||||
mouseStartX: downevent.pageX,
|
||||
minResizeX: function () { return this.mouseStartX - (this.currentColumnStartWidth - this.minWidth); },
|
||||
maxResizeX: function () { return this.mouseStartX + (this.maxWidth - this.currentColumnStartWidth); }
|
||||
};
|
||||
|
||||
//Handle mouse move event to move resizing bar
|
||||
var resizeonmousemove = function (moveevent) {
|
||||
if (!self._currentResizeArgs) {
|
||||
return;
|
||||
}
|
||||
|
||||
var resizeBarX = self._normalizeNumber(moveevent.pageX, self._currentResizeArgs.minResizeX(), self._currentResizeArgs.maxResizeX());
|
||||
self._$columnResizeBar.css('left', (resizeBarX - mainContainerOffset.left) + 'px');
|
||||
};
|
||||
|
||||
//Handle mouse up event to finish resizing of the column
|
||||
var resizeonmouseup = function (upevent) {
|
||||
if (!self._currentResizeArgs) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(document).unbind('mousemove', resizeonmousemove);
|
||||
$(document).unbind('mouseup', resizeonmouseup);
|
||||
|
||||
self._$columnResizeBar.hide();
|
||||
|
||||
//Calculate new widths in pixels
|
||||
var mouseChangeX = upevent.pageX - self._currentResizeArgs.mouseStartX;
|
||||
var currentColumnFinalWidth = self._normalizeNumber(self._currentResizeArgs.currentColumnStartWidth + mouseChangeX, self._currentResizeArgs.minWidth, self._currentResizeArgs.maxWidth);
|
||||
var nextColumnFinalWidth = $nextColumnHeader.outerWidth() + (self._currentResizeArgs.currentColumnStartWidth - currentColumnFinalWidth);
|
||||
|
||||
//Calculate widths as percent
|
||||
var pixelToPercentRatio = $columnHeader.data('width-in-percent') / self._currentResizeArgs.currentColumnStartWidth;
|
||||
$columnHeader.data('width-in-percent', currentColumnFinalWidth * pixelToPercentRatio);
|
||||
$nextColumnHeader.data('width-in-percent', nextColumnFinalWidth * pixelToPercentRatio);
|
||||
|
||||
//Set new widths to columns (resize!)
|
||||
$columnHeader.css('width', $columnHeader.data('width-in-percent') + '%');
|
||||
$nextColumnHeader.css('width', $nextColumnHeader.data('width-in-percent') + '%');
|
||||
|
||||
//Normalize all column widths
|
||||
self._normalizeColumnWidths();
|
||||
|
||||
//Finish resizing
|
||||
self._currentResizeArgs = null;
|
||||
|
||||
//Save current preferences
|
||||
if (self.options.saveUserPreferences) {
|
||||
self._saveColumnSettings();
|
||||
}
|
||||
};
|
||||
|
||||
//Show vertical resize bar
|
||||
self._$columnResizeBar
|
||||
.show()
|
||||
.css({
|
||||
top: ($columnHeader.offset().top - mainContainerOffset.top) + 'px',
|
||||
left: (downevent.pageX - mainContainerOffset.left) + 'px',
|
||||
height: (self._$table.outerHeight()) + 'px'
|
||||
});
|
||||
|
||||
//Bind events
|
||||
$(document).bind('mousemove', resizeonmousemove);
|
||||
$(document).bind('mouseup', resizeonmouseup);
|
||||
});
|
||||
},
|
||||
|
||||
/* Normalizes column widths as percent for current view.
|
||||
*************************************************************************/
|
||||
_normalizeColumnWidths: function () {
|
||||
|
||||
//Set command column width
|
||||
var commandColumnHeaders = this._$table
|
||||
.find('>thead th.jtable-command-column-header')
|
||||
.data('width-in-percent', 1)
|
||||
.css('width', '1%');
|
||||
|
||||
//Find data columns
|
||||
var headerCells = this._$table.find('>thead th.jtable-column-header');
|
||||
|
||||
//Calculate total width of data columns
|
||||
var totalWidthInPixel = 0;
|
||||
headerCells.each(function () {
|
||||
var $cell = $(this);
|
||||
if ($cell.is(':visible')) {
|
||||
totalWidthInPixel += $cell.outerWidth();
|
||||
}
|
||||
});
|
||||
|
||||
//Calculate width of each column
|
||||
var columnWidhts = {};
|
||||
var availableWidthInPercent = 100.0 - commandColumnHeaders.length;
|
||||
headerCells.each(function () {
|
||||
var $cell = $(this);
|
||||
if ($cell.is(':visible')) {
|
||||
var fieldName = $cell.data('fieldName');
|
||||
var widthInPercent = $cell.outerWidth() * availableWidthInPercent / totalWidthInPixel;
|
||||
columnWidhts[fieldName] = widthInPercent;
|
||||
}
|
||||
});
|
||||
|
||||
//Set width of each column
|
||||
headerCells.each(function () {
|
||||
var $cell = $(this);
|
||||
if ($cell.is(':visible')) {
|
||||
var fieldName = $cell.data('fieldName');
|
||||
$cell.data('width-in-percent', columnWidhts[fieldName]).css('width', columnWidhts[fieldName] + '%');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/* Saves field setting to cookie.
|
||||
* Saved setting will be a string like that:
|
||||
* fieldName1=visible;23|fieldName2=hidden;17|...
|
||||
*************************************************************************/
|
||||
_saveColumnSettings: function () {
|
||||
var self = this;
|
||||
var fieldSettings = '';
|
||||
this._$table.find('>thead >tr >th.jtable-column-header').each(function () {
|
||||
var $cell = $(this);
|
||||
var fieldName = $cell.data('fieldName');
|
||||
var columnWidth = $cell.data('width-in-percent');
|
||||
var fieldVisibility = self.options.fields[fieldName].visibility;
|
||||
var fieldSetting = fieldName + "=" + fieldVisibility + ';' + columnWidth;
|
||||
fieldSettings = fieldSettings + fieldSetting + '|';
|
||||
});
|
||||
|
||||
this._setCookie('column-settings', fieldSettings.substr(0, fieldSettings.length - 1));
|
||||
},
|
||||
|
||||
/* Loads field settings from cookie that is saved by _saveFieldSettings method.
|
||||
*************************************************************************/
|
||||
_loadColumnSettings: function () {
|
||||
var self = this;
|
||||
var columnSettingsCookie = this._getCookie('column-settings');
|
||||
if (!columnSettingsCookie) {
|
||||
return;
|
||||
}
|
||||
|
||||
var columnSettings = {};
|
||||
$.each(columnSettingsCookie.split('|'), function (inx, fieldSetting) {
|
||||
var splitted = fieldSetting.split('=');
|
||||
var fieldName = splitted[0];
|
||||
var settings = splitted[1].split(';');
|
||||
columnSettings[fieldName] = {
|
||||
columnVisibility: settings[0],
|
||||
columnWidth: settings[1]
|
||||
};
|
||||
});
|
||||
|
||||
var headerCells = this._$table.find('>thead >tr >th.jtable-column-header');
|
||||
headerCells.each(function () {
|
||||
var $cell = $(this);
|
||||
var fieldName = $cell.data('fieldName');
|
||||
var field = self.options.fields[fieldName];
|
||||
if (columnSettings[fieldName]) {
|
||||
if (field.visibility != 'fixed') {
|
||||
self._changeColumnVisibilityInternal(fieldName, columnSettings[fieldName].columnVisibility);
|
||||
}
|
||||
|
||||
$cell.data('width-in-percent', columnSettings[fieldName].columnWidth).css('width', columnSettings[fieldName].columnWidth + '%');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})(jQuery);
|
Loading…
Add table
Add a link
Reference in a new issue