blob: e59b6e97d5f42ce175ed2ccc4dcf96c527dfe459 [file] [log] [blame]
// 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 reattachTable = function() {
var $mainContainer = $('<div>')
.addClass('data-table')
.appendTo($table.parent())
.append($table.detach()
);
};
/**
* 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) {
var direction = 'asc';
if ($table.find('thead tr:last th').hasClass('sorted ' + direction)) {
direction = 'desc';
}
$table.find('thead tr:last th').removeClass('sorted desc asc');
$($table.find('thead tr:last th')[columnIndex]).addClass('sorted').addClass(direction);
var $elems = $table.find('tbody td').filter(function() {
return $(this).index() == columnIndex;
});
if ($elems.length < 2) {
return;
}
var stringComparator = function(a,b) {
return a.html().localeCompare(b.html());
};
var numericComparator = function(a,b) {
return parseFloat(a.children().html()) < parseFloat(b.children().html()) ? 1 : -1;
};
var stateComparator = function(a,b) {
return a.attr('title').localeCompare(b.attr('title'));
};
var isNumeric = function(obj) {
return !$.isArray(obj) && !isNaN(parseFloat(obj)) && isFinite(parseFloat(obj));
}
var comparator = stringComparator;
var hasAllRowsSameValue = true;
var firstElem = $($elems[0]).html();
var sortData = [];
var numericDataCount = 0;
$elems.each(function() {
var text = $(this);
if (hasAllRowsSameValue) {
if (firstElem !== text.html()) {
hasAllRowsSameValue = false;
}
}
if (text.children()) {
text = text.children().html();
} else {
text = text.html();
}
if (isNumeric(text) || !text) {
numericDataCount += 1;
}
sortData.push($(this));
});
if ($($elems[0]).hasClass('state')) {
comparator = stateComparator;
} else {
if (hasAllRowsSameValue) {
return;
}
if (columnIndex != 0 && numericDataCount > ($elems.length / 4)) {
comparator = numericComparator;
}
}
sortData.sort(comparator);
if (direction == 'asc') {
sortData.reverse();
}
var elements = [];
$(sortData).each(function() {
elements.push($(this).parent().clone(true));
});
var $tbody = $table.find('tbody');
$tbody.empty();
$(elements).each(function() {
$(this).appendTo($tbody);
});
computeEvenOddRows();
};
var resizeHeaders = function() {
var $thead = $table.hasClass('no-split') ? $table.find('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 ($table.hasClass('no-split')) {
$tbody.width($thead.width());
}
if ($ths.length > $tds.length) {
$ths.width(
$table.width() / $ths.length
);
return false;
}
$ths.each(function() {
var $th = $(this);
if ($th.hasClass('collapsible-column')) {
return true;
}
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').length && !$table.hasClass('no-split')) {
reattachTable();
$table.find('tbody').closest('table').addClass('body');
}
if (!$table.hasClass('horizontal-overflow')) {
$table.find('th:not(:has(input))').bind('mousemove mouseout', hoverResizableEvent);
$table.find('th:not(:has(input))').bind('mousedown mousemove mouseup mouseout', resizeDragEvent);
}
$table.find('thead tr:last th:not(:has(input)):not(.collapsible-column):not(.quick-view)').unbind('click').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.length || 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));