552 lines
17 KiB
JavaScript
552 lines
17 KiB
JavaScript
|
|
/**
|
||
|
|
* This file is a part of MyWebSQL package
|
||
|
|
*
|
||
|
|
* @file: js/tables.js
|
||
|
|
* @author Samnan ur Rehman
|
||
|
|
* @copyright (c) 2008-2014 Samnan ur Rehman
|
||
|
|
* @web http://mywebsql.net
|
||
|
|
* @license http://mywebsql.net/license
|
||
|
|
*/
|
||
|
|
|
||
|
|
var curEditField = null; // current edited field
|
||
|
|
var curEditType = null;
|
||
|
|
var fieldInfo = null; // information about fields in record set
|
||
|
|
var editOptions = { sortable:true, highlight:true, selectable:true, editEvent:'dblclick', editFunc:editTableCell };
|
||
|
|
|
||
|
|
var selectedRow = -1;
|
||
|
|
var res_modified = false; // is the result modified?
|
||
|
|
|
||
|
|
var editHorizontal = false;
|
||
|
|
|
||
|
|
var editListOpen = false;
|
||
|
|
|
||
|
|
// options can include
|
||
|
|
// highlight: boolean: highlights row on mouse over
|
||
|
|
// selectable: boolean: makes row selectable
|
||
|
|
// editable: boolean: makes grid editable
|
||
|
|
// sortable: boolean: makes table sorting possible using its header
|
||
|
|
|
||
|
|
function setupTable(id, opt) {
|
||
|
|
res_modified = false;
|
||
|
|
|
||
|
|
if (!opt.editEvent) opt.editEvent = 'dblclick';
|
||
|
|
if (!opt.editFunc) opt.editFunc = editTableCell;
|
||
|
|
|
||
|
|
// only sort if there is more than one row
|
||
|
|
if (opt.sortable && $('#'+id+' tbody tr').length > 2 ) {
|
||
|
|
createTableHeader(id.substr(0,4));
|
||
|
|
|
||
|
|
if (opt.sortable == true) {
|
||
|
|
$('#dataHeader thead th').live('click', function() {
|
||
|
|
if ($(this).attr('class').match(/tch|th_nosort/)) {
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
var sort_column = $(this).index();
|
||
|
|
if (editTableName && editTableName != '') {
|
||
|
|
sort_column--;
|
||
|
|
}
|
||
|
|
goSort(sort_column);
|
||
|
|
});
|
||
|
|
} else if (opt.sortable == 'inline') {
|
||
|
|
var DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;
|
||
|
|
$("#"+id).sorttable();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (opt.highlight) {
|
||
|
|
$('#'+id+' > tbody > tr').live('mouseenter', function() {
|
||
|
|
$(this).addClass("ui-state-hover");
|
||
|
|
});
|
||
|
|
$('#'+id+' > tbody > tr').live('mouseleave', function() {
|
||
|
|
$(this).removeClass('ui-state-hover');
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if (opt.selectable) {
|
||
|
|
$('#'+id+' > tbody > tr').live('click', function() {
|
||
|
|
if (selectedRow != null)
|
||
|
|
$(selectedRow).removeClass('ui-state-active');
|
||
|
|
$(this).addClass("ui-state-active");
|
||
|
|
selectedRow = this;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
if (opt.editable) {
|
||
|
|
editOptions = opt;
|
||
|
|
$('#'+id+' td.edit').bind(opt.editEvent, opt.editFunc);
|
||
|
|
// for mobile devices
|
||
|
|
if(jQuery.support.touch){
|
||
|
|
$('#'+id+' td.edit').bind("taphold", opt.editFunc);
|
||
|
|
}
|
||
|
|
$('#inplace-text textarea').unbind('keydown').bind('keydown', checkEditField);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function editTableCell() {
|
||
|
|
td = $(this);
|
||
|
|
if (curEditField != null)
|
||
|
|
closeEditor(true);
|
||
|
|
|
||
|
|
isBlob = td.find('span.i').length;
|
||
|
|
isText = td.find('span.d').length;
|
||
|
|
txt = isText ? td.find('span.d').text() : (isBlob ? td.find('span.i').text() : td.text());
|
||
|
|
tstyle = td.hasClass('tr') ? "right" : "left";
|
||
|
|
|
||
|
|
td.data('defText', txt);
|
||
|
|
|
||
|
|
curEditField = this;
|
||
|
|
index = td.index()-2;
|
||
|
|
fi = getFieldInfo(index);
|
||
|
|
w = td.width() - (isBlob ? 22 : 0);
|
||
|
|
h = td.height();
|
||
|
|
td.attr('width', w);
|
||
|
|
|
||
|
|
input = createCellEditor(td, fi, txt, w, h, tstyle);
|
||
|
|
|
||
|
|
if(input) {
|
||
|
|
setTimeout( function() {
|
||
|
|
input.focus();
|
||
|
|
td.ensureVisible($("#results-div"), editHorizontal);
|
||
|
|
}, 50 );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function closeEditor(upd, value) {
|
||
|
|
if (!curEditField)
|
||
|
|
return;
|
||
|
|
|
||
|
|
obj = $(curEditField);
|
||
|
|
txt = '';
|
||
|
|
var xt = new Object();
|
||
|
|
if (upd) {
|
||
|
|
if (arguments.length > 1 && value == null) {
|
||
|
|
xt.value = "NULL";
|
||
|
|
xt.setNull = true;
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
txt = xt.value = (curEditType == 'simple') ? obj.find('input').val() : $('#inplace-text textarea').val();
|
||
|
|
xt.setNull = false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// if not modified, don't bother
|
||
|
|
if ( (xt.value != obj.data('defText')) || (xt.setNull && !obj.hasClass("tnl"))
|
||
|
|
|| (!xt.setNull && obj.hasClass('tnl')) ) {
|
||
|
|
if (!obj.parent().hasClass('n'))
|
||
|
|
obj.parent().addClass('x');
|
||
|
|
obj.data('edit', xt).addClass('x');
|
||
|
|
res_modified = true;
|
||
|
|
|
||
|
|
if (typeof showNavBtn == "function")
|
||
|
|
showNavBtn('update', 'gensql');
|
||
|
|
|
||
|
|
if(xt.setNull)
|
||
|
|
obj.removeClass('tl').addClass('tnl');
|
||
|
|
else
|
||
|
|
obj.removeClass('tnl').addClass('tl');
|
||
|
|
|
||
|
|
txt = xt.value;
|
||
|
|
//txt = str_replace("<", "<", xt.value);
|
||
|
|
//txt = str_replace(">", ">", txt);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
txt = obj.data('defText');
|
||
|
|
|
||
|
|
if (curEditType == 'text') {
|
||
|
|
if (xt.setNull)
|
||
|
|
obj.find('span.i').text('NULL').removeClass('tl').addClass('tnl');
|
||
|
|
else {
|
||
|
|
obj.find('span.i')
|
||
|
|
.text(txt.length == 0 ? '' :
|
||
|
|
( txt.length <= MAX_TEXT_LENGTH_DISPLAY ? txt : 'Text Data [' + formatBytes(txt.length) + ']') )
|
||
|
|
.removeClass('tnl');
|
||
|
|
}
|
||
|
|
obj.find('span.d').text(txt);
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
if (obj.find('span.i').length == 0)
|
||
|
|
obj.text(txt);
|
||
|
|
else
|
||
|
|
obj.find('span.i').text(txt);
|
||
|
|
}
|
||
|
|
|
||
|
|
obj.removeAttr('width');
|
||
|
|
curEditField = null;
|
||
|
|
|
||
|
|
if (curEditType == 'text')
|
||
|
|
$('#inplace-text').hide();
|
||
|
|
|
||
|
|
editListOpen = false;
|
||
|
|
resizeTableHeader('data');
|
||
|
|
}
|
||
|
|
|
||
|
|
function checkEditField(event) {
|
||
|
|
editHorizontal = false;
|
||
|
|
// enter, tab, up arrow, down arrow
|
||
|
|
keys = (curEditType == 'text') ? [9] : [13,9,38,40];
|
||
|
|
if (keys.indexOf(event.keyCode) != -1) {
|
||
|
|
event.preventDefault();
|
||
|
|
elem = false;
|
||
|
|
if (event.keyCode == 9) {
|
||
|
|
elem = event.shiftKey ? $(curEditField).prev('.edit') : $(curEditField).next('.edit');
|
||
|
|
// move to next/previous record if possible
|
||
|
|
if (!elem.length) {
|
||
|
|
tr = event.shiftKey ? $(curEditField).parent().prev() : $(curEditField).parent().next();
|
||
|
|
if (tr.length)
|
||
|
|
elem = event.shiftKey ? tr.find('td.edit:last') : tr.find('td.edit:first');
|
||
|
|
}
|
||
|
|
editHorizontal = true;
|
||
|
|
}
|
||
|
|
else if (event.keyCode == 38 || event.keyCode == 40) {
|
||
|
|
tr = event.keyCode == 38 ? $(curEditField).parent().prev() : $(curEditField).parent().next();
|
||
|
|
if (tr.length)
|
||
|
|
elem = tr.find('td').eq($(curEditField).index());
|
||
|
|
}
|
||
|
|
$('#inplace-text textarea').unbind('blur');
|
||
|
|
closeEditor(true);
|
||
|
|
if (elem && elem.length) // edit next or previous element
|
||
|
|
elem.trigger(editOptions.editEvent);
|
||
|
|
}
|
||
|
|
else if (event.keyCode == 27)
|
||
|
|
closeEditor(false);
|
||
|
|
/*else if ($(this).attr('readonly') != '' && event.keyCode == 32 ) {
|
||
|
|
// focus is on a blob editor, need to open dialog for blob editing
|
||
|
|
oldEditField = curEditField;
|
||
|
|
closeEditor(false);
|
||
|
|
$(oldEditField).find('span.blob').click();
|
||
|
|
}*/
|
||
|
|
}
|
||
|
|
|
||
|
|
function createCellEditor(td, fi, txt, w, h, align) {
|
||
|
|
curEditType = 'simple';
|
||
|
|
keyEvent = 'keydown';
|
||
|
|
input = null;
|
||
|
|
code = '<form name="cell_editor_form" class="cell_editor_form" action="javascript:void(0);">';
|
||
|
|
if (fi['blob'] == 1) {
|
||
|
|
if (fi['type'] == 'binary') {
|
||
|
|
code += '<input type="text" readonly="readonly" name="cell_editor" class="cell_editor" style="text-align:' + align + ';width: ' + (w-2) + 'px;" />';
|
||
|
|
code += '</form>';
|
||
|
|
td.find('span.i').html(code);
|
||
|
|
input = td.find('input');
|
||
|
|
input.val(txt).bind(keyEvent, checkEditField ).blur( function() { closeEditor(true); } );
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
span = $(td).find('span.d');
|
||
|
|
txt = span.text();
|
||
|
|
|
||
|
|
if ( optionsGet('ui-edit-popup') ) {
|
||
|
|
// show dialog text editor to make large text editing easier
|
||
|
|
$("#dialog-text-editor").dialog({
|
||
|
|
autoOpen: true,
|
||
|
|
width: 500,
|
||
|
|
height: 300,
|
||
|
|
modal: true,
|
||
|
|
open: function() {
|
||
|
|
$("#text-editor").val( txt );
|
||
|
|
// suspend hotkeys while the popup editor is active
|
||
|
|
window.hotkeys.suspend(true);
|
||
|
|
},
|
||
|
|
buttons: [ {
|
||
|
|
text: __('Cancel'),
|
||
|
|
click: function() { window.hotkeys.suspend(false); $(this).dialog('close'); }
|
||
|
|
}, {
|
||
|
|
text: __('Save'),
|
||
|
|
click: function() {
|
||
|
|
txt = $("#text-editor").val();
|
||
|
|
span.text( txt );
|
||
|
|
td.find('span.i').text(txt.length == 0 ? '' :
|
||
|
|
( txt.length <= MAX_TEXT_LENGTH_DISPLAY ? txt : 'Text Data [' + formatBytes(txt.length) + ']') )
|
||
|
|
.removeClass('tnl');
|
||
|
|
var xt = new Object();
|
||
|
|
xt.value = txt;
|
||
|
|
xt.setNull = false;
|
||
|
|
if (!td.parent().hasClass('n'))
|
||
|
|
td.parent().addClass('x');
|
||
|
|
td.data('edit', xt).addClass('x');
|
||
|
|
if (typeof showNavBtn == "function")
|
||
|
|
showNavBtn('update', 'gensql');
|
||
|
|
curEditField = null;
|
||
|
|
window.hotkeys.suspend(false);
|
||
|
|
$(this).dialog('close');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
]
|
||
|
|
});
|
||
|
|
input = null;
|
||
|
|
} else {
|
||
|
|
w = td.width()-20;
|
||
|
|
if (w < 200) w = 200;
|
||
|
|
textarea = $('#inplace-text textarea');
|
||
|
|
textarea.width(w).val(txt);
|
||
|
|
|
||
|
|
$('#inplace-text').show().position({ of: td, my: "left top", at: "left top", offset: 0 });
|
||
|
|
$('#inplace-text textarea').blur( function() { closeEditor(true); } );
|
||
|
|
curEditType = 'text';
|
||
|
|
input = textarea;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
switch(fi['type']) {
|
||
|
|
default:
|
||
|
|
code += '<input type="text" name="cell_editor" class="cell_editor" style="text-align:' + align + ';width: ' + (w-2) + 'px;" />';
|
||
|
|
if( fi['list'] && fi['list'].length > 0 ) {
|
||
|
|
code += '<a href="javascript:void(0)" class="cell_editlist">▾</a>';
|
||
|
|
} else if ( fi['type'] && ( fi['type'] == "datetime" || fi['type'] == "date" ) ) {
|
||
|
|
code += '<div class="dp"></div><a href="javascript:void(0)" class="cell_editlist">▾</a>;';
|
||
|
|
}
|
||
|
|
code += '</form>';
|
||
|
|
td.html(code);
|
||
|
|
input = td.find('input');
|
||
|
|
input.val(txt).select().bind(keyEvent, checkEditField ).blur( function(e) { if (!editListOpen) closeEditor(true); } );
|
||
|
|
if( fi['list'] && fi['list'].length > 0 ) {
|
||
|
|
$(".cell_editor").css({width:(w-20)+'px'}).autocomplete({
|
||
|
|
minLength: 0,
|
||
|
|
source: fi['list'],
|
||
|
|
open: function( event, ui ) { $(".cell_editor").autocomplete( "widget" ).css({width:(w>160?w-2:160)+"px"}); },
|
||
|
|
close: function( event, ui ) { $(".cell_editor").focus(); editListOpen = false; }
|
||
|
|
});
|
||
|
|
$(".cell_editlist").mousedown(function(e) {
|
||
|
|
e.preventDefault();
|
||
|
|
editListOpen = true;
|
||
|
|
$(".cell_editor").focus().autocomplete("search", "");
|
||
|
|
return false;
|
||
|
|
});
|
||
|
|
} else if ( fi['type'] && ( fi['type'] == "datetime" || fi['type'] == "date" ) ) {
|
||
|
|
$(".cell_editor").css({width:(w-20)+'px'});
|
||
|
|
$(".dp").datepicker({
|
||
|
|
dateFormat:"yy-mm-dd",
|
||
|
|
changeMonth: true,
|
||
|
|
changeYear: true,
|
||
|
|
onSelect: function(d, o) {
|
||
|
|
$(".dp").fadeOut(300);
|
||
|
|
d += $(".cell_editor").data("datetime");
|
||
|
|
$(".cell_editor").val(d).focus();
|
||
|
|
editListOpen = false;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
$(".cell_editlist").mousedown(function(e) {
|
||
|
|
e.preventDefault();
|
||
|
|
editListOpen = true;
|
||
|
|
var d = $(".cell_editor").val();
|
||
|
|
$(".cell_editor").data("datetime", d.substr(10));
|
||
|
|
$(".dp").datepicker("setDate", d.substr(0, 10));
|
||
|
|
$(".dp").fadeIn(300);
|
||
|
|
$(".cell_editor").focus();
|
||
|
|
return false;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return input;
|
||
|
|
}
|
||
|
|
|
||
|
|
function createTableHeader(name) {
|
||
|
|
var table = "#" + name + "Table";
|
||
|
|
if ($(table + ' tbody tr').length <= 2)
|
||
|
|
return;
|
||
|
|
|
||
|
|
var header = "#" + name + "Header";
|
||
|
|
var div = name == "data" ? '#results-div' : "#info-div";
|
||
|
|
$(header).remove(); // just in case we have it created and not yet destroyed
|
||
|
|
var tableHeader = $(table).clone();
|
||
|
|
tableHeader.find('tbody').remove();
|
||
|
|
tableHeader.attr('id', name + "Header").appendTo(div);
|
||
|
|
|
||
|
|
$(div).scroll(function () {
|
||
|
|
var t = parseInt($(this).scrollTop());
|
||
|
|
tableHeader.css({top: t + 'px'})
|
||
|
|
});
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
function resizeTableHeader(name) {
|
||
|
|
var table = "#" + name + "Table";
|
||
|
|
if ($(table + ' tbody tr').length <= 2)
|
||
|
|
return;
|
||
|
|
|
||
|
|
var header = "#" + name + "Header";
|
||
|
|
var tableHeader = $(header);
|
||
|
|
tableHeader.width($(table).width());
|
||
|
|
var ths = $(table + " thead th");
|
||
|
|
var l = ths.length;
|
||
|
|
for (i = 0; i < l; i++) {
|
||
|
|
var w = $(ths[i]).width();
|
||
|
|
tableHeader.find("thead th").eq(i).width(w);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
$.fn.ensureVisible = function(el, horiz) {
|
||
|
|
if (horiz) {
|
||
|
|
pl = el.prop("scrollLeft");
|
||
|
|
pw = el.width();
|
||
|
|
p = this.position();
|
||
|
|
w = this.width();
|
||
|
|
if( pw < (p.left+w) )
|
||
|
|
el.prop("scrollLeft", p.left + w);
|
||
|
|
else if( p.left < 0 )
|
||
|
|
el.prop("scrollLeft", p.left);
|
||
|
|
} else {
|
||
|
|
pt = el.prop("scrollTop");
|
||
|
|
ph = el.height();
|
||
|
|
p = this.position();
|
||
|
|
h = this.height();
|
||
|
|
if( ph < (p.top+h) )
|
||
|
|
el.prop("scrollTop", p.top + h);
|
||
|
|
else if( p.top < 0 )
|
||
|
|
el.prop("scrollTop", p.top);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// quick table search filter functionality
|
||
|
|
$.fn.setSearchFilter = function(text) {
|
||
|
|
if (text == '')
|
||
|
|
$('tr', this).removeClass('ui-helper-hidden');
|
||
|
|
else {
|
||
|
|
string = text.toUpperCase();
|
||
|
|
$('tbody tr', this).each(function(){
|
||
|
|
var found = false;
|
||
|
|
$('td', this).each(function(){
|
||
|
|
var contents = $(this).text().toUpperCase();
|
||
|
|
// check the string against that cell
|
||
|
|
if ( contents.match(string) ) {
|
||
|
|
found = true;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
if (found)
|
||
|
|
$(this).removeClass('ui-helper-hidden')
|
||
|
|
else
|
||
|
|
$(this).addClass('ui-helper-hidden');
|
||
|
|
});
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
/* Quick inline sorttable
|
||
|
|
based on the 'stupid-table' jQuery plugin by joequery
|
||
|
|
*/
|
||
|
|
|
||
|
|
(function($) {
|
||
|
|
|
||
|
|
$.fn.sorttable = function(sortFns) {
|
||
|
|
return this.each(function() {
|
||
|
|
var $table = $(this);
|
||
|
|
var $header = $ ("#" + $table.attr('id').replace("Table", "Header"));
|
||
|
|
sortFns = sortFns || {};
|
||
|
|
|
||
|
|
// Merge sort functions with some default sort functions.
|
||
|
|
sortFns = $.extend({}, $.fn.sorttable.default_sort_fns, sortFns);
|
||
|
|
|
||
|
|
$header.on("click.sorttable", "thead th", function() {
|
||
|
|
var $this = $(this);
|
||
|
|
var th_index = 0;
|
||
|
|
var dir = $.fn.sorttable.dir;
|
||
|
|
|
||
|
|
// Account for colspans
|
||
|
|
$this.parents("tr").find("th").slice(0, $this.index()).each(function() {
|
||
|
|
var cols = $(this).attr("colspan") || 1;
|
||
|
|
th_index += parseInt(cols,10);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Determine (and/or reverse) sorting direction, default `asc`
|
||
|
|
var sort_dir = $this.data("sort-default") || dir.ASC;
|
||
|
|
if ($this.data("sort-dir"))
|
||
|
|
sort_dir = $this.data("sort-dir") === dir.ASC ? dir.DESC : dir.ASC;
|
||
|
|
|
||
|
|
// Choose appropriate sorting function.
|
||
|
|
var type = $this.data("sort") || null;
|
||
|
|
|
||
|
|
// Prevent sorting if no type defined
|
||
|
|
if (type === null) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Trigger `beforetablesort` event that calling scripts can hook into;
|
||
|
|
// pass parameters for sorted column index and sorting direction
|
||
|
|
//$table.trigger("beforetablesort", {column: th_index, direction: sort_dir});
|
||
|
|
// More reliable method of forcing a redraw
|
||
|
|
$table.css("display");
|
||
|
|
|
||
|
|
// Run sorting asynchronously on a timout to force browser redraw after
|
||
|
|
// `beforetablesort` callback. Also avoids locking up the browser too much.
|
||
|
|
setTimeout(function() {
|
||
|
|
// Gather the elements for this column
|
||
|
|
var column = [];
|
||
|
|
var sortMethod = sortFns[type];
|
||
|
|
var trs = $table.children("tbody").children("tr");
|
||
|
|
|
||
|
|
// Extract the data for the column that needs to be sorted and pair it up
|
||
|
|
// with the TR itself into a tuple
|
||
|
|
trs.each(function(index,tr) {
|
||
|
|
var $e = $(tr).children().eq(th_index);
|
||
|
|
var sort_val = $e.data("sort-value");
|
||
|
|
var order_by = typeof(sort_val) !== "undefined" ? sort_val : $e.text();
|
||
|
|
column.push([order_by, tr]);
|
||
|
|
});
|
||
|
|
|
||
|
|
// Sort by the data-order-by value
|
||
|
|
column.sort(function(a, b) { return sortMethod(a[0], b[0]); });
|
||
|
|
if (sort_dir != dir.ASC)
|
||
|
|
column.reverse();
|
||
|
|
|
||
|
|
// Replace the content of tbody with the sorted rows. Strangely (and
|
||
|
|
// conveniently!) enough, .append accomplishes this for us.
|
||
|
|
trs = $.map(column, function(kv) { return kv[1]; });
|
||
|
|
$table.children("tbody").append(trs);
|
||
|
|
|
||
|
|
// Reset siblings
|
||
|
|
$table.find("th").data("sort-dir", null).removeClass("sorting-desc sorting-asc");
|
||
|
|
$this.data("sort-dir", sort_dir).addClass("sorting-"+sort_dir);
|
||
|
|
$this.parent().find("span").remove();
|
||
|
|
$table.find("thead span").remove();
|
||
|
|
$this.find("div").append( sort_dir == dir.ASC ? "<span> ▴<span>" : "<span> ▾<span>");
|
||
|
|
$table.find("thead th:eq("+th_index+") div").append( sort_dir == dir.ASC ? "<span> ▴<span>" : "<span> ▾<span>");
|
||
|
|
resizeTableHeader('info');
|
||
|
|
|
||
|
|
// reset first index numbering
|
||
|
|
$("tbody tr", $table).each(function(i) { $("td:eq(0)", this).html(i+1); });
|
||
|
|
// Trigger `aftertablesort` event. Similar to `beforetablesort`
|
||
|
|
//$table.trigger("aftertablesort", {column: th_index, direction: sort_dir});
|
||
|
|
// More reliable method of forcing a redraw
|
||
|
|
$table.css("display");
|
||
|
|
}, 10);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
};
|
||
|
|
|
||
|
|
// Enum containing sorting directions
|
||
|
|
$.fn.sorttable.dir = {ASC: "asc", DESC: "desc"};
|
||
|
|
|
||
|
|
$.fn.sorttable.default_sort_fns = {
|
||
|
|
"numeric": function(a, b) {
|
||
|
|
if (a != "NULL" && b != "NULL")
|
||
|
|
return parseInt(a, 10) - parseInt(b, 10);
|
||
|
|
if (a == "NULL")
|
||
|
|
return -1;
|
||
|
|
return 1;
|
||
|
|
},
|
||
|
|
"float": function(a, b) {
|
||
|
|
if (a != "NULL" && b != "NULL")
|
||
|
|
return parseFloat(a) - parseFloat(b);
|
||
|
|
if (a == "NULL")
|
||
|
|
return -1;
|
||
|
|
return 1;
|
||
|
|
},
|
||
|
|
"text": function(a, b) {
|
||
|
|
if (a != "NULL" && b != "NULL")
|
||
|
|
return a.localeCompare(b);
|
||
|
|
if (a == "NULL")
|
||
|
|
return -1;
|
||
|
|
return 1;
|
||
|
|
},
|
||
|
|
"text-ins": function(a, b) {
|
||
|
|
a = a.toLocaleLowerCase();
|
||
|
|
b = b.toLocaleLowerCase();
|
||
|
|
return a.localeCompare(b);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
})(jQuery);
|