summaryrefslogtreecommitdiffstats
path: root/dev/jquery.jtable.dynamiccolumns.js
diff options
context:
space:
mode:
Diffstat (limited to 'dev/jquery.jtable.dynamiccolumns.js')
-rw-r--r--dev/jquery.jtable.dynamiccolumns.js990
1 files changed, 461 insertions, 529 deletions
diff --git a/dev/jquery.jtable.dynamiccolumns.js b/dev/jquery.jtable.dynamiccolumns.js
index 88487fe..fefdb58 100644
--- a/dev/jquery.jtable.dynamiccolumns.js
+++ b/dev/jquery.jtable.dynamiccolumns.js
@@ -1,529 +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,
- saveUserPreferences: 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();
-
- this._cookieKeyPrefix = this._generateCookieKeyPrefix();
- 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 + '%');
- }
- });
- },
-
- /************************************************************************
- * COOKIE *
- *************************************************************************/
-
- /* Sets a cookie with given key.
- *************************************************************************/
- _setCookie: function (key, value) {
- key = this._cookieKeyPrefix + key;
-
- var expireDate = new Date();
- expireDate.setDate(expireDate.getDate() + 30);
- document.cookie = encodeURIComponent(key) + '=' + encodeURIComponent(value) + "; expires=" + expireDate.toUTCString();
- },
-
- /* Gets a cookie with given key.
- *************************************************************************/
- _getCookie: function (key) {
- key = this._cookieKeyPrefix + key;
-
- var equalities = document.cookie.split('; ');
- for (var i = 0; i < equalities.length; i++) {
- if (!equalities[i]) {
- continue;
- }
-
- var splitted = equalities[i].split('=');
- if (splitted.length != 2) {
- continue;
- }
-
- if (decodeURIComponent(splitted[0]) === key) {
- return decodeURIComponent(splitted[1] || '');
- }
- }
-
- return null;
- },
-
- /* Generates a hash key to be prefix for all cookies for this jtable instance.
- *************************************************************************/
- _generateCookieKeyPrefix: function () {
-
- var simpleHash = function (value) {
- var hash = 0;
- if (value.length == 0) {
- return hash;
- }
-
- for (var i = 0; i < value.length; i++) {
- var ch = value.charCodeAt(i);
- hash = ((hash << 5) - hash) + ch;
- hash = hash & hash;
- }
-
- return hash;
- };
-
- var strToHash = '';
- if (this.options.tableId) {
- strToHash = strToHash + this.options.tableId + '#';
- }
-
- strToHash = strToHash + this._columnList.join('$') + '#c' + this._$table.find('thead th').length;
- return 'jtable#' + simpleHash(strToHash);
- }
-
- });
-
-})(jQuery);
+/************************************************************************
+* 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);