// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
(function($) {
/**
* Convert table to be resizable and sortable
*
*/
$.fn.dataTable = function(method, options) {
var $table = this;
/**
* Check if position is in 'resize zone'
*
* @return boolean, true if position is within bounds
*/
var withinResizeBounds = function($elem, posX) {
var leftBound = $elem.offset().left + $elem.width() / 1.2;
return posX > leftBound;
};
/**
* Handles actual resizing of table headers
*/
var resizeDragEvent = function(event) {
var $elem = $(this);
if (event.type == 'mousedown') {
$elem.addClass('dragging');
return false;
} else if (event.type == 'mouseup') {
$table.find('th').removeClass('dragging');
return false;
}
var isDraggable = $elem.hasClass('dragging');
if (!isDraggable) {
return false;
}
var columnIndex = $elem.index();
// Get all TDs from column
var columnCells = [];
$table.find('tbody tr:first').each(function() {
var targetCell = $($(this).find('td')[columnIndex]);
columnCells.push(targetCell);
});
var tolerance = 25;
var targetWidth = event.pageX - $elem.offset().left + tolerance;
$(columnCells).each(function() {
$(this).css({
width: targetWidth
});
});
resizeHeaders();
return true;
};
var splitTable = function() {
var $mainContainer = $('
')
.addClass('data-table')
.appendTo($table.parent())
.append(
$table.remove()
);
$table = $mainContainer;
var $theadContainer = $('
').addClass('fixed-header').prependTo($table);
var $theadTable = $('
').appendTo($theadContainer).attr('nowrap', 'nowrap');
var $thead = $table.find('thead').remove().appendTo($theadTable);
return $thead;
};
/**
* Event to set resizable appearance on hover
*/
var hoverResizableEvent = function(event) {
var $elem = $(this);
var posX = event.pageX;
if (event.type != 'mouseout' && withinResizeBounds($elem, posX)) {
$elem.addClass('resizable');
} else {
$elem.removeClass('resizable');
}
return true;
};
/**
* Make row at specified index selected or unselected
*
* @param rowIndex Row's index, starting at 1
*/
var toggleSelectRow = function(rowIndex) {
var $rows = $table.find('tbody tr');
var $row = $($rows[rowIndex]);
$row.siblings().removeClass('selected');
return $row.addClass('selected');
};
var computeEvenOddRows = function() {
var currentRowType = 'even';
$table.find('tbody tr').each(function() {
var $row = $(this);
$row.removeClass('even').removeClass('odd');
$row.addClass(currentRowType);
if (currentRowType == 'even') currentRowType = 'odd';
else currentRowType = 'even';
});
};
/**
* Sort table by column
*
* @param columnIndex Index of column (starting at 0) to sort by
*/
var sortTable = function(columnIndex) {
return false;
var direction = 'asc';
if ($table.find('thead th').hasClass('sorted ' + direction)) {
direction = 'desc';
}
$table.find('thead th').removeClass('sorted desc asc');
$($table.find('thead th')[columnIndex]).addClass('sorted').addClass(direction);
var $elems = $table.find('tbody td').filter(function() {
return $(this).index() == columnIndex;
});
var sortData = [];
$elems.each(function() {
sortData.push($(this).html());
sortData.sort();
if (direction == 'asc') {
sortData.reverse();
}
});
$(sortData).each(function() {
var sortKey = this;
var $targetCell = $elems.filter(function() {
return $(this).html() == sortKey;
});
var $targetContainer = $targetCell.parent();
$targetContainer.remove().appendTo($table.find('tbody'));
});
computeEvenOddRows();
};
var resizeHeaders = function() {
var $thead = $table.closest('div.data-table').find('thead');
var $tbody = $table.find('tbody');
var $ths = $thead.find('th');
var $tds = $tbody.find('tr:first td');
if ($ths.size() > $tds.size()) {
$ths.width(
$table.width() / $ths.size()
);
return false;
}
$ths.each(function() {
var $th = $(this);
var $td = $tds.filter(function() {
return $(this).index() == $th.index();
});
$th.width($td.width());
return true;
});
return $ths;
};
var methods = {
removeRow: function(rowIndex) {
var $row = $($table.find('tbody tr')[rowIndex]);
$row.fadeOut(function() {
$row.remove();
computeEvenOddRows();
});
return $row;
},
refresh: function() {
resizeHeaders();
computeEvenOddRows();
},
selectRow: function(rowIndex) {
var $row = $($table.find('tbody tr')[rowIndex]);
$row.siblings().removeClass('selected');
$row.addClass('selected');
}
};
var init = function() {
var noSelect = options && options.noSelect == true ? true : false;
if (!$table.closest('div.data-table').size() && !$table.hasClass('no-split')) {
splitTable();
$table.find('tbody').closest('table').addClass('body');
}
$table.find('th').bind('mousemove mouseout', hoverResizableEvent);
$table.find('th').bind('mousedown mousemove mouseup mouseout', resizeDragEvent);
$table.find('th').bind('click', function(event) {
if ($(this).hasClass('resizable')) {
return false;
}
sortTable($(event.target).index());
return false;
});
$table.bind('click', function(event) {
var $tr = $(event.target).closest('tr');
if (!$tr.size() || noSelect) return true;
var rowIndex = $tr.index();
toggleSelectRow(rowIndex);
return true;
});
computeEvenOddRows();
resizeHeaders();
};
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (!method) {
init();
} else {
$.error('Method ' + method + ' does not exist on jQuery.dataTable');
}
return $table;
};
}(jQuery));