Friday, June 19, 2009

Sample Grid

jQuery.fn.mygrid = function(d, settings)
{
//*************************************************************************************************************************
//*************************************************************************************************************************
// INITIALIZE PARAMETERS
//*************************************************************************************************************************
//*************************************************************************************************************************
var data = d;
var s = {
mode : 'edit', //values: edit, display
totalWidth : 220,
colNum : 2,
colWidths : ['50%', '50%'],

hasData : false,
hasHeader : false,
hasBody : false,

colResize : false,
col : {
n : -1,
c : null, //the current resize column object
nc : null, //the next column object
//g : null, //the current resize colgroup's col object
ow : 0, //resize column original Width
ox : 0, //resize column original X
ncow : 0 //next column original width
}
};

$.extend(s, settings);

if (data)
{
if (data.header)
{
if (data.header.length > 0)
{
s.hasData = true;
s.hasHeader = true;
s.colNum = data.header[0].length;
}
}
if (data.body)
{
if (data.body.length > 0)
{
s.hasData = true;
s.hasBody = true;
s.colNum = data.body[0].length;
}
}
}
//*************************************************************************************************************************
//*************************************************************************************************************************
// INITIALIZE CONTAINER, TOOLBAR & TABLE
//*************************************************************************************************************************
//*************************************************************************************************************************
//initialize container and table
var $container = $(this);
var $toolbar = $('
').addClass('mygrid_toolbar').appendTo($container);
var $table = $("
").addClass("mygrid").appendTo($container);
$table.width(s.totalWidth).addClass('unselectable');

//*************************************************************************************************************************
//*************************************************************************************************************************
// TOOLBAR
//*************************************************************************************************************************
//*************************************************************************************************************************


var $toolbar_add = $('
').addClass('mygrid_toolbar_item').addClass('mygrid_toolbar_add').appendTo($toolbar)
.click(function() {
var $collection = $('td.selectedGlobalHeader', $table);
if ($collection.length != 1) { alert('Too many objects selected.'); return; }
$collection.each(function() {
if ($(this).hasClass('mygrid_GlobalColumnHeaderCell'))
{
var columnIndex = this.cellIndex;

$('tr', $table).each(function(row) {
var $thisCell = $('td', this).filter(':eq('+columnIndex+')');
$thisCell.clone(true).html('').insertAfter($thisCell);
});

$('td', $gcHeaderRow).filter(':eq('+(columnIndex+1)+')').html('
');
}
else if ($(this).hasClass('mygrid_GlobalRowHeaderCell'))
{
var $thisRow = $(this).parent();
$thisRow.clone(true).children('td').each(function() { $(this).html(''); }).end().insertAfter($thisRow);
}
});
func_clearToolbar();
});
var $toolbar_add_submenu = $('
').addClass('mygrid_toolbar_submenu').appendTo($toolbar)
.click(function() {
var $collection = $('td.selectedGlobalHeader', $table);
if ($collection.length != 1) { alert('Too many objects selected.'); return; }
$collection.each(function() {
if ($(this).hasClass('mygrid_GlobalColumnHeaderCell'))
{
var columnIndex = this.cellIndex;
$('tr', $table).each(function(row) {
var $thisCell = $('td', this).filter(':eq('+columnIndex+')');
$thisCell.clone(true).html('').insertAfter($thisCell);
});
}
else if ($(this).hasClass('mygrid_GlobalRowHeaderCell'))
{
var $thisRow = $(this).parent();
$thisRow.clone(true).children('td').each(function() { $(this).html(''); }).end().insertAfter($thisRow);
}
});
func_clearToolbar();
});

var $toolbar_delete = $('
').addClass('mygrid_toolbar_item').addClass('mygrid_toolbar_delete').appendTo($toolbar)
.click(function() {
var $collection = $('td.selectedGlobalHeader', $table);
if ($collection.length != 1) { alert('Too many objects selected.'); return; }
$collection.each(function() {
if ($(this).hasClass('mygrid_GlobalColumnHeaderCell'))
{
var columnIndex = this.cellIndex;
$('tr', $table).each(function(row) { $('td', this).filter(':eq('+columnIndex+')').remove();});
}
else if ($(this).hasClass('mygrid_GlobalRowHeaderCell'))
{
//var rowIndex = $(this).parent().get(0).rowIndex;
$(this).parent().remove();
}
});
func_clearToolbar();
});
var $toolbar_move_up = $('
').addClass('mygrid_toolbar_item').addClass('mygrid_toolbar_move_up').appendTo($toolbar)
.click(function() {
var $collection = $('td.selectedGlobalHeader', $table);
if ($collection.length != 1) { alert('Only one Column or Row can be selected.'); return; }
$collection.each(function() {
if ($(this).hasClass('mygrid_GlobalRowHeaderCell'))
{
$(this).parent().insertBefore($(this).parent().prev());
}
});
//func_clearToolbar();
});

var $toolbar_move_down = $('
').addClass('mygrid_toolbar_item').addClass('mygrid_toolbar_move_down').appendTo($toolbar)
.click(function() {
var $collection = $('td.selectedGlobalHeader', $table);
if ($collection.length != 1) { alert('Only one Column or Row can be selected.'); return; }
$collection.each(function() {
if ($(this).hasClass('mygrid_GlobalRowHeaderCell'))
{
$(this).parent().insertAfter($(this).parent().next());
}
});
//func_clearToolbar();
});

var $toolbar_move_left = $('
').addClass('mygrid_toolbar_item').addClass('mygrid_toolbar_move_left').appendTo($toolbar)
.click(function() {
var $collection = $('td.selectedGlobalHeader', $table);
if ($collection.length != 1) { alert('Only one Column or Row can be selected.'); return; }
$collection.each(function() {
if ($(this).hasClass('mygrid_GlobalColumnHeaderCell'))
{
var columnIndex = this.cellIndex;
$('tr', $table).each(function(row) {
var $thisCell = $('td', this).filter(':eq('+columnIndex+')');
$thisCell.insertBefore($thisCell.prev());
});
}
});
//func_clearToolbar();
});

var $toolbar_move_right = $('
').addClass('mygrid_toolbar_item').addClass('mygrid_toolbar_move_right').appendTo($toolbar)
.click(function() {
var $collection = $('td.selectedGlobalHeader', $table);
if ($collection.length != 1) { alert('Only one Column or Row can be selected.'); return; }
$collection.each(function() {
if ($(this).hasClass('mygrid_GlobalColumnHeaderCell'))
{
var columnIndex = this.cellIndex;
$('tr', $table).each(function(row) {
var $thisCell = $('td', this).filter(':eq('+columnIndex+')');
$thisCell.insertAfter($thisCell.next());
});
}
});
//func_clearToolbar();
});

//*************************************************************************************************************************
//*************************************************************************************************************************
// DATA
//*************************************************************************************************************************
//*************************************************************************************************************************

// COLGROUP to define Column Widths
/*
$gcGroup = $('').appendTo($table);
$gcGroup.attr('span', s.colNum);
$('').attr('width', 20).appendTo($gcGroup);

if (s.colWidths.length == s.colNum)
{
$.each(s.colWidths, function(i, v) {
$('').attr('width', s.totalWidth*parseFloat(v)/100).appendTo($gcGroup);
});
}
*/
//GLOBAL COLUMN HEADER
var $gcHeader = $("").appendTo($table);
var $gcHeaderRow = $("").appendTo($gcHeader);
// add the most top-left cell
var $gcTopCell = $("").addClass("mygrid_GlobalTopCell").appendTo($gcHeaderRow).width(20);
for (var i=0; i {
$("").addClass("mygrid_GlobalColumnHeaderCell").append('
').appendTo($gcHeaderRow)
.width(s.totalWidth*parseFloat(s.colWidths[i])/100);
}

if (s.hasData)
{
if (s.hasHeader)
{
//add the grid header as a TBODY
$header = $("").attr('id', 'mygrid_Header').appendTo($table);

$.each(data.header,
function(i, r) {
//add a new header row
var $row = $("").appendTo($header);
//for the new header row, add a global row header cell
$("").addClass("mygrid_GlobalRowHeaderCell").appendTo($row);
//inside the new header row, create cells
$.each(r, function(j, c) {
$("").addClass('mygrid_HeaderCell').html(c).appendTo($row); });
});
}

if (s.hasBody)
{
//add the grid body as a TBODY
$body = $("").attr('id', 'mygrid_Body').appendTo($table);

$.each(data.body,
function(i, r) {
var $row = $("").appendTo($body);
//for the new row, add a Global Row Header Cell
$("").addClass("mygrid_GlobalRowHeaderCell").appendTo($row);
$.each(r, function(j, c) { $("").addClass('mygrid_BodyCell').html(c).appendTo($row) });
});
}
}
else //if no data passed in
{
$header = $("").attr('id', 'mygrid_Header').appendTo($table);
$("").appendTo($header)
.append($("").addClass("mygrid_GlobalRowHeaderCell"))
.append($("").addClass('mygrid_HeaderCell').html(''))
.append($("").addClass('mygrid_HeaderCell').html(''));

$body = $("").attr('id', 'mygrid_Body').appendTo($table);
$("").appendTo($body)
.append($("").addClass("mygrid_GlobalRowHeaderCell"))
.append($("").addClass('mygrid_BodyCell').html(''))
.append($("").addClass('mygrid_BodyCell').html(''));
}
//*************************************************************************************************************************
//*************************************************************************************************************************
// BIND EVENTS
//*************************************************************************************************************************
//*************************************************************************************************************************
//general function to clear
var func_clear=function() {
$('td.edit', $table).each(function() {
var cellValue = $('.mygrid_TextBox', this).eq(0).val();
$(this).empty().html(cellValue);
} );
$('td', $table).removeClass('selected').removeClass('selectedGlobalHeader').removeClass('edit');
func_clearToolbar();
};
//general to clear toolbar
var func_clearToolbar=function() {
$('div.mygrid_toolbar_item', $toolbar).hide();
};
//##################################### RESIZE - BEGIN################################

var $moveBar = $('
').addClass('moveBar').appendTo($('body'));

$gcHeader.mousedown(function(e) {
var $t = $(e.target);
if ($t.hasClass('resizeBar'))
{
s.colResize = true;
var _bar = $t;
var _col = _bar.parent();
s.col.n = $('div.resizeBar').index(_bar);
s.col.c = _col;
s.col.nc = _col.next();
//s.col.g = $gcGroup.children('col').eq(s.col.n+1);
s.col.ow = _col.width();
s.col.ox = e.pageX;
s.col.ncow = _col.next().width();
$moveBar.css('left', s.col.ox).css('top', _col.parent().offset().top+'px').height($table.height()).show();
//$table.addClass('unselectable');
//('body').bind('select', function() { return false; });
//$('#log').html($moveBar.css('left') + '---'+$moveBar.css('top')+'--'+JSON.stringify(_col.parent().offset()));
}
});

$(document)
.mousemove(function(e) {
if (s.colResize)
{
//$gcGroup.children('col').eq(s.col.n+1).attr('width', s.col.ow + _diff);
//s.col.c.width( s.col.ow + _diff);
//s.col.nc.width(s.col.ncow - _diff);
if (s.col.nc.length>0)
{
var _diff = e.pageX - s.col.ox; //the new width, original width + different

$moveBar.css('left', s.col.ox + _diff);
}
//$table.width(s.totalWidth + _diff);

}
})
.mouseup(function(e) {
if (s.colResize)
{
var _diff = parseInt(e.pageX) - parseInt(s.col.ox);
//$table.width(s.totalWidth + _diff);
var _nw = s.col.ow + _diff;
var _ncnw = s.col.ncow - _diff;

if (_nw > 20 && _ncnw > 20)
{
s.col.nc.width(_ncnw);
s.col.c.width(_nw);
}
//$table.width(s.totalWidth);

s.colResize = false;
//s.totalWidth = $table.width();
s.col.n = -1;
s.col.ow = 0;
s.col.ox = 0;
$moveBar.hide();
//$table.removeClass('unselectable');
}
})
.bind('selectstart', function(e) {
if (s.colResize)
{
return false;
}
});
//##################################### RESIZE - END#####################################

var $cellinput = $('').addClass('mygrid_TextBox').appendTo($('body'));

$table
.click(function(e) {
var t = e.target;
var $t = $(t);

if ($t.hasClass('mygrid_GlobalColumnHeaderCell')) //highlight the column when clicking on column header
{
func_clear();
var column = t.cellIndex;
$('tr', $table).each(function(row) { $('td', this).filter(':eq('+column+')').addClass('selected');});
$t.removeClass('selected').addClass('selectedGlobalHeader');

func_clearToolbar();
$toolbar_move_left.show();
$toolbar_move_right.show();
$toolbar_delete.show();
$toolbar_add.show();
}
else if ($t.hasClass('mygrid_GlobalRowHeaderCell')) //highlight the row when clicking on the row header
{
func_clear();
$t.siblings().addClass('selected');
$t.removeClass('selected').addClass('selectedGlobalHeader');

func_clearToolbar();
$toolbar_move_up.show();
$toolbar_move_down.show();
$toolbar_delete.show();
$toolbar_add.show();
}
else if ($t.hasClass('mygrid_BodyCell')) //click: highlight the cell which users click on
{
func_clear();
$t.addClass('selected');
//highlight global row header
$t.siblings('.mygrid_GlobalRowHeaderCell').addClass('selectedGlobalHeader');
//highlight global column header
var column = t.cellIndex;
$('td', $gcHeaderRow).filter(':eq('+column+')').addClass('selectedGlobalHeader');
}
})
.dblclick(function(e) {
var t = e.target;
var $t = $(t);

if ($t.hasClass('mygrid_BodyCell')) //double-click: highlight the cell which users click on and also create a text box;
{
var $cell = $t;
$cellinput.val($cell.html());

$.blockUI({ message: $cellinput,
css: { left: $cell.offset().left + 'px', top: $cell.offset().top + 'px',
width: $cell.width() + 'px', height: $cell.height() + 'px',
textAlign: 'left' },
overlayCSS: { opacity: 0.3 }
});
$('.blockOverlay').attr('title','Click to quit edit mode').click(function() {
$cell.html($cellinput.val());
$.unblockUI();
});
}
else if ($t.hasClass('mygrid_GlobalColumnHeaderCell')) //sort the column when double-clicking on column header
{
func_clear();
var sortDirection;
if ($t.hasClass('sorted_asc')) sortDirection = -1;
else if ($t.hasClass('sorted_desc')) sortDirection = 0;
else sortDirection = 1;

$("td.mygrid_GlobalColumnHeaderCell", $table).removeClass('sorted_asc').removeClass('sorted_desc');

var column = t.cellIndex;
var rows = $('tr', $body).each(function(i) { $(this).data('defaultKey', i); }).get();

$.each(rows, function(i, row) {
var key = $(row).children('td').eq(column).text().toUpperCase();
var numericKey = parseFloat(key);
key = isNaN(numericKey) ? key : numericKey;
$(row).data('sortKey', key);
});
if (sortDirection == 0)
{
rows.sort(function(a, b) {
if ($(a).data('defaultKey') < $(b).data('defaultKey')) return -1;
if ($(a).data('defaultKey') > $(b).data('defaultKey')) return 1;
return 0;
});
}
else
{
rows.sort(function(a, b) {
if ($(a).data('sortKey') < $(b).data('sortKey')) return -sortDirection;
if ($(a).data('sortKey') > $(b).data('sortKey')) return sortDirection;
return 0;
});
}
$.each(rows, function(i, row) {
$body.append(row);
$(row).removeData('sortKey');
});

if (sortDirection == 1)
$t.removeClass('sorted_desc').addClass('sorted_asc');
else if (sortDirection == -1)
$t.removeClass('sorted_asc').addClass('sorted_desc');
else
$t.removeClass('sorted_asc').removeClass('sorted_desc');

$('tr', $table).each(function(row) { $('td', this).filter(':eq('+column+')').addClass('selected');});
$t.removeClass('selected').addClass('selectedGlobalHeader');
}
});
};

No comments: