function GolikGrid(gridId,columnsWSize, gridHeight , gridWidth ,idHolder)
{
/****** Constants *****/
var asc = "asc";
var desc = "desc";
var styleCellData = "border-right:solid 2px white; padding-top:5px;background-color: white; font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;white-space:nowrap";
var styleCellAlterData = "border-right:solid 2px whitesmoke; padding-top:5px;background-color: whitesmoke;font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;white-space:nowrap";
var styleCellSelectedData = "border-right:solid 2px DarkBlue;padding-top:5px;background-color: DarkBlue;color:white;font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;white-space:nowrap";
var styleHeaderCellData = "font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;font-weight:bold;border-bottom:groove 2px lightgrey;border-right:groove 2px lightgrey;background-color:lightgrey;white-space:nowrap;"
var styleDragHeaderCellData = "filter:progid:DXImageTransform.Microsoft.Alpha( Opacity=40);font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;font-weight:bold;border:solid 1px black;background-color:darkgray;white-space:nowrap;";
var styleHighlightLeftHeaderData = "font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;font-weight:bold;border-bottom:groove 2px lightgrey;border-right:groove 2px lightgrey;border-left:solid 2px blue; background-color:lightgrey;white-space:nowrap;";
var styleHighlightRightHeaderData = "font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;font-weight:bold;border-bottom:groove 2px lightgrey;border-right:solid 2px blue;background-color:lightgrey;white-space:nowrap;";
var styleStubHeaderCellData = "background-color:lightgrey;white-space:nowrap;border-bottom:groove 2px lightgrey;border-right:solid 2px lightgrey;font-size:11px;";
var styleStubCellData = "background-color: white;font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;white-space:nowrap;border-right:solid 2px white";
var styleStubCellAlterData = "background-color: whitesmoke;font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;white-space:nowrap;border-right:solid 2px whitesmoke";
var styleUpdateInput = "font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;border:solid 1px DarkGray";
var styleUpdateCancelBtn = "font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;background-color:silver";
var styleAddInput = "font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;border:solid 1px DarkGray";
var styleAddCancelBtn = "font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;background-color:silver";
var styleMenuItem = "padding-left:5px; padding-right:5px;padding-top:3px;padding-bottom:2px;white-space:nowrap;background-color:lightgrey;"
var styleMenuSelectedItem = "padding-left:5px; padding-right:5px;padding-top:3px;padding-bottom:2px;white-space:nowrap;background-color:DarkBlue;color:white;"
var styleMenu = "width:120px;border-right:groove 2px lightgrey;border-left:groove 2px white;border-top:groove 2px white;border-bottom:groove 2px lightgrey;font-family: Verdana, Arial, 'Microsoft Sans Serif';font-size:11px;cursor:pointer";
var scrollBarColor = "silver";
var headerResizePointer = 'col-resize';
var headerDragPointer = 'move';
var minColumnSize = 25;
var junkFault = 2;
var defaultColumnSize = 100;
var maxChildDepth = 10;
var maxRowsCount = 300;
var stubColumnSize = 150;
var updateBtnOffset = 5;
//offset between cursor and dragging column
var offsetDragDrop = 35;
//delay in pixel to start dragDrop
var pixelDelayDragDrop = 20;
var columnLeftOffset = 5;
var sortArrowFontSize = 10;
var sortPointerOffset = 8;
var ascPointer = "↑";
var descPointer ="↓";
var defaultGridHeight = 500;
var defaultGridWidth = 500;
var defaultGridId="uxGolikGrid"
if(gridId!=null)
defaultGridId = gridId;
//Constants
var dataSource = new DataSource();
var view = new View(idHolder,columnsWSize,dataSource);
var controller = new Controller(view, dataSource , this);
/************ Delegates *************/
this.onRowUpdated;
this.onRowAdded;
this.getDataSource = function()
{
return dataSource;
}
this.getSelectedRowId = function()
{
return view.selectedRowId;
}
this.dataBind = function()
{
//fire event
controller.onDataBind();
}
this.setItemMenu = function(menuItems)
{
//fire event
controller.onSetItemMenu(menuItems);
}
this.setGridMenu = function(menuItems)
{
controller.onSetGridMenu(menuItems);
}
this.removeRow = function(rowId)
{ //fire event
controller.onRemoveRow(rowId);
}
this.updateRow = function(rowId)
{ //fire event
controller.onUpdateRow(rowId);
}
this.addRow = function()
{
//fire event
controller.onAddRow();
}
/********** Utility ************/
function isGridChild(child)
{
var gridHolder = document.getElementById(defaultGridId);
var tries = 0;
while(child!=gridHolder)
{
if(child.parentElement==null)
return false;
if(tries==maxChildDepth)
return false;
child = child.parentElement;
tries++;
}
return true;
}
function junkTextToWSize(str , wSize , cssText)
{
var textLabel = document.getElementById("uxTextLabel");
if(textLabel==null)
{
textLabel = document.createElement("<span>");
textLabel.id = "uxTextLabel";
document.body.appendChild(textLabel);
}
textLabel.innerText = str;
textLabel.style.cssText = cssText;
textLabel.style.visibility = "hidden";
textLabel.style.position = "absolute";
if(textLabel.offsetWidth>=(wSize-junkFault))
{
textLabel.innerText = "..."+textLabel.innerText
while(textLabel.offsetWidth>=(wSize-junkFault))
{
textLabel.innerText = textLabel.innerText.substr(0,textLabel.innerText.length-1);
}
var retString = textLabel.innerText.substr(3,textLabel.innerText.length-3)+"...";
return retString;
}
else
return str;
}
/******** View class *******/
function View(idHolder,columnsWSize,dataSrc)
{
/****** Init ******/
var dataSource = dataSrc;
this.selectedRowId = null;
gridHeight = (gridHeight==null)?defaultGridHeight:gridHeight;
gridWidth = (gridWidth==null)?defaultGridWidth:gridWidth;
var holder = document.createElement("<div id='"+defaultGridId+"' style='display:inline;width:"+gridWidth+";height:"+gridHeight+"' >");
if(idHolder==null)
document.body.appendChild(holder);
else
document.getElementById(idHolder).appendChild(holder);
var grid = document.createElement("<div oncontextmenu='return false;' >")
holder.appendChild(grid);
var width = holder.offsetWidth;
var height = holder.offsetHeight;
var headerContent = document.createElement("<table cellspacing='0' cellpadding='0' style='display:inline;position:relative;font-size:1px;' >");
//create the temp stub cell to count offsetHeight of header
var stubTextCell = headerContent.insertRow().insertCell();
stubTextCell.style.cssText = styleHeaderCellData;
stubTextCell.innerHTML = " <span style='font-size:"+sortArrowFontSize+"' >"+ascPointer+"<span>";
var header = document.createElement("<div onselectstart='return false;' style='cursor:pointer;white-space:nowrap;width:"+width+";height:1px;overflow-x:hidden;' >");
header.appendChild(headerContent);
grid.appendChild(header);
var dataHeight = height - header.offsetHeight
//remove temp stub cell
headerContent.deleteRow(0);
var dataContent = document.createElement("<table cellspacing='0' border='0' cellpadding='0' style='display:inline;position:relative;font-size:1px;' >");
var data = document.createElement("<div style='width:"+width+";height:"+dataHeight+";overflow:scroll;scrollbar-base-color:"+scrollBarColor+"' >");
data.appendChild(dataContent);
grid.appendChild(data);
//set the stub for header
var stubScrollWidth = data.offsetWidth - data.clientWidth;
var stub = document.createElement("<table cellspacing='0' style='display:inline;font-size:1px;height:100% ' cellpadding='0' >");
var stubCell = stub.insertRow().insertCell();
stubCell.style.cssText = styleStubHeaderCellData;
stubCell.innerHTML=" "
stubCell.style.width = stubScrollWidth;
stub.style.width = stubScrollWidth;
header.appendChild(stub);
/****** Delegates ******/
this.sortEventHandler;
this.startResizeColumnEventHandler;
this.startDragColumnEventHandler;
this.rowMenuClickedEventHandler;
this.rowUpdateClickedEventHandler;
this.rowUpdateKeyEnteredEventHandler;
this.rowUpdateCancelClickedEventHandler;
this.rowAddMenuClickedEventHandler;
this.rowAddClikedEventHandler;
this.rowAddCancelClickedEventHandler;
this.rowAddKeyEnteredEventHandler;
this.gridContextMenuClickedEventHandler;
this.dataClickedEventHandler;
this.dataScrollEventHandler;
/****** Methods ******/
this.dataBind = function()
{
this.clearView();
var headerItems = dataSource.getHeaderItems();
for(var index=0;index < headerItems.length; index++)
{
this.addHeaderItem(headerItems[index]);
}
var rowItems = dataSource.getRowItems();
for(var index=0; index < rowItems.length; index++)
{
this.addRowItem(rowItems[index]);
}
//fixing the layout
this.fixCellLabels();
this.fixHeaderSortItem();
}
this.bindEvents = function()
{ //we have to call this function to bind events, we can do it only after
//controller class implements these handlers. So these events can only be initialized
//on controller creation.
data.onclick = this.dataClickedEventHandler;
data.onscroll = this.dataScrollEventHandler;
data.oncontextmenu = this.gridContextMenuClickedEventHandler;
}
this.sortItems = function()
{
function getRowById(rowId)
{
for(var index=0; index < dataContent.rows.length; index++)
{
if(dataContent.rows[index].rowId == rowId )
return dataContent.rows[index];
}
}
//force grid to be not in write state
//otherwise sorting is impossible as
//one need to have junked labels
this.setGridUnselectedState();
this.setGridReadState();
var rowItems = dataSource.getRowItems();
for(var index=0; index < rowItems.length; index++)
{
if(rowItems[index].rowId == dataContent.rows[index].rowId)
continue;
var row = getRowById(rowItems[index].rowId);
var rowId = dataContent.rows[index].rowId;
dataContent.rows[index].rowId = row.rowId;
row.rowId = rowId;
for(var index1 = 0; index1< dataContent.rows[index].cells.length-1; index1++)
{
var innerText = dataContent.rows[index].cells[index1].firstChild.children[1].innerText;
var title = dataContent.rows[index].cells[index1].firstChild.children[1].title;
dataContent.rows[index].cells[index1].firstChild.children[1].innerText = row.cells[index1].firstChild.children[1].innerText;
dataContent.rows[index].cells[index1].firstChild.children[1].title = row.cells[index1].firstChild.children[1].title;
row.cells[index1].firstChild.children[1].innerText = innerText;
row.cells[index1].firstChild.children[1].title = title;
}
}
this.fixHeaderSortItem();
}
this.isRowWriteState = function(rowId)
{
for(var index=0;index<dataContent.rows.length;index++)
{ //if the stub column has buttons that means the row is in write state
if(dataContent.rows[index].cells[dataContent.rows[index].cells.length-1].firstChild.children[1]!=null && dataContent.rows[index].rowId == rowId)
return true;
}
}
this.setRowSelectedState = function(rowId)
{
for(var index=0; index < dataContent.rows.length; index++)
{
if(dataContent.rows[index].rowId==rowId)
{
for(var index1 = 0; index1 < dataContent.rows[index].cells.length; index1++)
{
var width = dataContent.rows[index].cells[index1].style.width;
dataContent.rows[index].cells[index1].style.cssText = styleCellSelectedData;
dataContent.rows[index].cells[index1].style.width = width;
}
break;
}
}
this.selectedRowId = rowId;
}
this.setGridReadState = function()
{
for(var index=0;index<dataContent.rows.length;index++)
{ //if the stub column has buttons that means the row is in write state
if(dataContent.rows[index].cells[dataContent.rows[index].cells.length-1].firstChild.children[1]!=null)
{
this.setRowReadState(dataContent.rows[index].rowId);
}
}
}
this.setGridNotAddState = function()
{
if(data.children.length==2)
data.children[0].parentElement.removeChild(data.children[0]);
}
this.setGridUnselectedState = function()
{
if(this.selectedRowId==null)
return;
for(var index=0; index < dataContent.rows.length; index++)
{
if(dataContent.rows[index].rowId==this.selectedRowId)
{
for(var index1 = 0; index1 < dataContent.rows[index].cells.length; index1++)
{
var width = dataContent.rows[index].cells[index1].style.width;
dataContent.rows[index].cells[index1].style.cssText = (index % 2 != 0)?styleCellAlterData:styleCellData;
dataContent.rows[index].cells[index1].style.width = width;
}
break;
}
}
this.selectedRowId = null;
}
this.saveAddedRowItem = function()
{
//check if there is add row in grid
if(data.children.length==2)
{
var obj = new Object();
for(var index=0;index < data.children[0].rows[0].cells.length-1;index++)
{
var cellValue = data.children[0].rows[0].cells[index].firstChild.children[1].value;
obj[index] = cellValue;
obj[headerContent.rows[0].cells[index].firstChild.children[1].title] = cellValue;
}
return obj;
}
return null;
}
this.saveUpdatedRowItem = function(rowId)
{
var rowUpdate = null;
for(var index=0; index < dataContent.rows.length; index++)
{
if(dataContent.rows[index].rowId==rowId)
{
rowUpdate = dataContent.rows[index];
break;
}
}
if(rowUpdate==null)
return;
if(rowUpdate.cells[rowUpdate.cells.length-1].firstChild.children[1]==null)
//that means the row is in read state, this function should be called only at write state
return null;
var obj = new Object();
for(var index=0; index < rowUpdate.cells.length-1;index++)
{
rowUpdate.cells[index].firstChild.children[1].title = rowUpdate.cells[index].firstChild.children[1].value;
obj[headerContent.rows[0].cells[index].firstChild.children[1].title] = rowUpdate.cells[index].firstChild.children[1].value;
obj[index] = rowUpdate.cells[index].firstChild.children[1].value;
}
obj.id = rowId;
return obj;
}
this.setRowReadState = function(rowId)
{
var rowUpdate = null;
for(var index=0; index < dataContent.rows.length; index++)
{
if(dataContent.rows[index].rowId==rowId)
{
rowUpdate = dataContent.rows[index];
break;
}
}
if(rowUpdate==null)
return;
if(rowUpdate.cells[rowUpdate.cells.length-1].firstChild.children[1]==null)
//if the stub column hasn't buttons that means the row is already in read state
return;
for(var index=0; index < rowUpdate.cells.length-1;index++)
{
var title = rowUpdate.cells[index].firstChild.children[1].title;
var text = document.createElement("<span>");
text.innerText = title;
text.title = title;
rowUpdate.cells[index].firstChild.children[1].parentElement.removeChild( rowUpdate.cells[index].firstChild.children[1]);
rowUpdate.cells[index].firstChild.appendChild(text);
}
while(rowUpdate.cells[rowUpdate.cells.length-1].firstChild.children[1]!=null)
{
rowUpdate.cells[rowUpdate.cells.length-1].firstChild.children[1].parentElement.removeChild(rowUpdate.cells[rowUpdate.cells.length-1].firstChild.children[1]);
}
this.fixCellLabels(rowId);
}
this.setRowAddState = function()
{
if(data.children.length==2)
//do nothing as the add row already exists
return;
var addTable = document.createElement("<table style='position:relative;' cellspacing='0' cellpadding='0' border='0' >");
data.insertAdjacentElement("afterBegin",addTable);
var addRow = addTable.insertRow();
addRow.oncontextmenu = this.rowAddMenuClickedEventHandler;
for(var index=0; index < headerContent.rows[0].cells.length-1; index++)
{
var cell = addRow.insertCell();
cell.style.cssText = styleCellAlterData;
cell.style.width = parseInt(headerContent.rows[0].cells[index].style.width);
var holder = document.createElement("<span>");
holder.style.whiteSpace = "nowrap";
cell.appendChild(holder);
var offsetItem = document.createElement("<span>");
offsetItem.innerHTML = " ";
offsetItem.style.width = columnLeftOffset;
holder.appendChild(offsetItem);
var input = document.createElement("<input type='text' >");
input.style.cssText = styleAddInput;
input.style.width = parseInt(headerContent.rows[0].cells[index].style.width)-columnLeftOffset;
input.onkeydown = this.rowAddKeyEnteredEventHandler;
holder.appendChild(input);
if(index==0)
input.focus();
}
var stubCell = addRow.insertCell();
stubCell.style.cssText = styleStubCellAlterData;
stubCell.style.width= headerContent.rows[0].cells[headerContent.rows[0].cells.length-1].style.width;
var holder = document.createElement("<span>");
holder.style.whiteSpace = "nowrap";
offsetItem = document.createElement("<span>");
offsetItem.innerHTML = " ";
offsetItem.style.width = columnLeftOffset;
holder.appendChild(offsetItem);
stubCell.appendChild(holder);
addTable.style.width = headerContent.style.width;
var addInput = document.createElement("<input type='button' value='Add' >");
var cancelInput = document.createElement("<input type='button' value='Cancel' >");
addInput.style.cssText = styleUpdateCancelBtn;
addInput.style.width = (stubColumnSize-updateBtnOffset-columnLeftOffset)/2;
cancelInput.style.cssText = styleUpdateCancelBtn;
cancelInput.style.width = (stubColumnSize-updateBtnOffset-columnLeftOffset)/2;
addInput.onclick = this.rowAddClikedEventHandler;;
cancelInput.onclick = this.rowAddCancelClickedEventHandler;
var offset = document.createElement("<span>");
offset.innerHTML = " ";
offset.style.width = updateBtnOffset;
addRow.cells[addRow.cells.length-1].firstChild.appendChild(addInput);
addRow.cells[addRow.cells.length-1].firstChild.appendChild(offset);
addRow.cells[addRow.cells.length-1].firstChild.appendChild(cancelInput);
}
this.setRowWriteState = function(rowId)
{
var rowUpdate = null;
for(var index=0; index < dataContent.rows.length; index++)
{
if(dataContent.rows[index].rowId==rowId)
{
rowUpdate = dataContent.rows[index];
break;
}
}
if(rowUpdate==null)
return
if(rowUpdate.cells[rowUpdate.cells.length-1].firstChild.children[1]!=null)
//if the stub column has buttons that means the row is already in write state
return;
for(var index=0; index < rowUpdate.cells.length-1;index++)
{
var title = rowUpdate.cells[index].firstChild.children[1].title;
var input = document.createElement("<input type='text' >");
input.onkeydown = this.rowUpdateKeyEnteredEventHandler;
input.rowId = rowId;
input.value = title;
input.title = title;
input.style.cssText = styleUpdateInput;
input.style.width = parseInt(rowUpdate.cells[index].style.width)-columnLeftOffset;
rowUpdate.cells[index].firstChild.children[1].parentElement.removeChild( rowUpdate.cells[index].firstChild.children[1]);
rowUpdate.cells[index].firstChild.appendChild(input);
if(index==0)
input.focus();
}
var updateInput = document.createElement("<input type='button' value='Update' >");
var cancelInput = document.createElement("<input type='button' value='Cancel' >");
updateInput.style.cssText = styleUpdateCancelBtn;
updateInput.style.width = (stubColumnSize-updateBtnOffset-columnLeftOffset)/2;
cancelInput.style.cssText = styleUpdateCancelBtn;
cancelInput.style.width = (stubColumnSize-updateBtnOffset-columnLeftOffset)/2;
updateInput.onclick = this.rowUpdateClickedEventHandler;
cancelInput.onclick = this.rowUpdateCancelClickedEventHandler;
updateInput.rowId = rowId;
cancelInput.rowId = rowId;
var offset = document.createElement("<span>");
offset.innerHTML = " ";
offset.style.width = updateBtnOffset;
rowUpdate.cells[rowUpdate.cells.length-1].firstChild.appendChild(updateInput);
rowUpdate.cells[rowUpdate.cells.length-1].firstChild.appendChild(offset);
rowUpdate.cells[rowUpdate.cells.length-1].firstChild.appendChild(cancelInput);
}
this.removeRow = function(rowId)
{
if(this.selectedRowId==rowId)
this.selectedRowId=null;
for(index=0; index < dataContent.rows.length; index++)
{
if(dataContent.rows[index].rowId == rowId)
{
dataContent.rows[index].parentElement.removeChild(dataContent.rows[index]);
break;
}
}
for(index=0; index < dataContent.rows.length; index++)
{
for(index1=0; index1 < dataContent.rows[index].cells.length; index1++)
{
var width = dataContent.rows[index].cells[index1].style.width;
dataContent.rows[index].cells[index1].style.cssText = (index % 2 != 0)?styleCellAlterData:styleCellData;
dataContent.rows[index].cells[index1].style.width = width;
}
}
}
this.stopDragColumn = function(columnNumber)
{
if(document.getElementById("uxDragColumn")!=null)
{
header.removeChild(document.getElementById("uxDragColumn"));
}
//fix the headers
for(var index=0; index < headerContent.rows[0].cells.length-1;index++)
{
var width = headerContent.rows[0].cells[index].style.width;
var headerItem = headerContent.rows[0].cells[index];
headerItem.style.cssText = styleHeaderCellData;;
headerItem.style.width = width;
}
}
//drag column to specified offset and count a new cell
this.dragColumn = function(columnNumber, offsetLeft)
{
//fix the headers
for(var index=0; index < headerContent.rows[0].cells.length-1;index++)
{
var width = headerContent.rows[0].cells[index].style.width;
var headerItem = headerContent.rows[0].cells[index];
headerItem.style.cssText = styleHeaderCellData;;
headerItem.style.width = width;
}
if(document.getElementById("uxDragColumn")==null)
{
//set the style for draging column
var dragColumn = document.createElement("<table cellspacing='0' cellpadding='0' border='0' style='display:inline' >");
var cell = dragColumn.insertRow().insertCell();
dragColumn.id= "uxDragColumn";
dragColumn.style.position = "relative";
dragColumn.style.display = "inline";
cell.style.cssText = styleDragHeaderCellData;
var stubCell = dragColumn.rows[0].insertCell();
stubCell.innerText = "hey";
stubCell.style.cssText = styleDragHeaderCellData;
stubCell.style.visibility = "hidden";
var sortArrow = document.createElement("<span>");
sortArrow.style.width = sortPointerOffset;
sortArrow.style.fontSize = sortArrowFontSize;
sortArrow.innerHTML =(dataSource.getSortDirection()==asc)?ascPointer:descPointer;
stubCell.appendChild(sortArrow);
header.appendChild(dragColumn);
}
var dragColumn = document.getElementById("uxDragColumn");
//set private properties of dragging column
var columnLabel = headerContent.rows[0].cells[columnNumber].firstChild.children[1].innerText;
dragColumn.rows[0].cells[0].innerText = columnLabel;
dragColumn.rows[0].cells[0].width = parseInt(headerContent.rows[0].cells[columnNumber].style.width);
var headerOffset = parseInt(header.children[0].style.width) + parseInt(header.children[1].style.width);
headerContent.rows[0].cells[columnNumber].style.cursor = headerDragPointer;
var newCellIndex = null;
for(var index=0; index < header.firstChild.rows[0].cells.length-1;index++)
{
var headerItem = header.firstChild.rows[0].cells[index];
var headerItemWidth = parseInt(headerItem.style.width);
var headerItemOffsetLeft = headerItem.offsetLeft;
var headerItemOffsetRight = headerItemOffsetLeft + headerItemWidth;
if(offsetLeft>headerItemOffsetLeft && offsetLeft<headerItemOffsetRight)
{
if(this.cellIndex != headerItem.cellIndex)
{
//get the x relative to headerItem
var x = offsetLeft-headerItem.offsetLeft;
var relativeTo = headerItemWidth/x;
if(relativeTo<2)
{
var width = headerItem.style.width;
headerItem.style.cssText = styleHighlightRightHeaderData;
headerItem.style.width = width;
newCellIndex = headerItem.cellIndex+1;
}
else
{
if(headerItem.cellIndex!=0){
var previousHeaderItem = header.firstChild.rows[0].cells[headerItem.cellIndex-1];
var width = previousHeaderItem.style.width;
previousHeaderItem.style.cssText = styleHighlightRightHeaderData;
previousHeaderItem.style.width = width;
newCellIndex = headerItem.cellIndex;
}
else
{
var width = headerItem.style.width;
headerItem.style.cssText = styleHighlightLeftHeaderData;
headerItem.style.width = width;
newCellIndex = headerItem.cellIndex;
}
}
break;
}
}
}// for(var index=0; index < header.firstChild.rows[0].cells.length-1;index++)
dragColumn.style.left = offsetLeft - headerOffset+offsetDragDrop;
return newCellIndex;
}
this.resizeColumn = function(columnNumber,width)
{
//resize columns, and restore the text labels
headerContent.rows[0].cells[columnNumber].style.width = width;
headerContent.rows[0].cells[columnNumber].firstChild.children[1].innerText = headerContent.rows[0].cells[columnNumber].firstChild.children[1].title;
if(data.children.length==2)
{
//that means that add row is exists in grid
var addTable = data.children[0];
addTable.rows[0].cells[columnNumber].firstChild.children[1].style.width = width-columnLeftOffset;
addTable.rows[0].cells[columnNumber].style.width = width;
}
for(var index=0; index < dataContent.rows.length;index++)
{
if(dataContent.rows[index].cells[columnNumber].firstChild.children[1].tagName=="SPAN")
{
dataContent.rows[index].cells[columnNumber].firstChild.children[1].innerText = dataContent.rows[index].cells[columnNumber].firstChild.children[1].title;
}
else
if(dataContent.rows[index].cells[columnNumber].firstChild.children[1].tagName=="INPUT")
{
dataContent.rows[index].cells[columnNumber].firstChild.children[1].style.width = width-columnLeftOffset;
}
dataContent.rows[index].cells[columnNumber].style.width=width;
}
this.fixCellLabels();
}
this.fixHeaderScrolling = function()
{
header.scrollLeft = data.scrollLeft;
}
this.fixHeaderSortItem = function()
{
//set sorting arrow
for(var index = 0; index < headerContent.rows[0].cells.length; index++)
{
if(headerContent.rows[0].cells[index].firstChild.children[2]!=null)
headerContent.rows[0].cells[index].firstChild.children[2].parentElement.removeChild(headerContent.rows[0].cells[index].firstChild.children[2]);
}
var sortArrow = document.createElement("<span>");
sortArrow.style.width = sortPointerOffset;
sortArrow.style.fontSize = sortArrowFontSize;
if(dataSource.getSortDirection()==asc)
sortArrow.innerHTML = ascPointer;
else
sortArrow.innerHTML = descPointer;
headerContent.rows[0].cells[dataSource.getSortIndex()].firstChild.appendChild(sortArrow);
}
this.fixCellLabels = function(supposedRowId)
{
//fix the stub at the end of grid
var headerWidth = parseInt(header.style.width);
var headerContentWidth = countDataCellsWidth()+stubColumnSize+parseInt(headerContent.rows[0].cells[headerContent.rows[0].cells.length-1].style.borderRightWidth);
if(headerWidth>headerContentWidth)
{
headerContent.rows[0].cells[headerContent.rows[0].cells.length-1].style.width = (headerWidth-headerContentWidth-stubScrollWidth)+stubColumnSize;
if(data.children.length==2)
{
var addTable = data.children[0];
addTable.rows[0].cells[addTable.rows[0].cells.length-1].style.width = (headerWidth - headerContentWidth-stubScrollWidth)+stubColumnSize;
}
for(var index=0; index<dataContent.rows.length; index++)
{
var stubDataCell = dataContent.rows[index].cells[dataContent.rows[index].cells.length-1];
stubDataCell.style.width = (headerWidth - headerContentWidth-stubScrollWidth)+stubColumnSize;
}
}
else
if(headerWidth<headerContentWidth)
{
headerContent.rows[0].cells[headerContent.rows[0].cells.length-1].style.width = stubColumnSize;
if(data.children.length==2)
{
var addTable = data.children[0];
addTable.rows[0].cells[addTable.rows[0].cells.length-1].style.width = stubColumnSize;
}
for(var index=0; index<dataContent.rows.length; index++)
{
var stubDataCell = dataContent.rows[index].cells[dataContent.rows[index].cells.length-1];
stubDataCell.style.width = stubColumnSize;
}
}
var totalGridWidth = countGridWidth();
headerContent.style.width = totalGridWidth;
dataContent.style.width = totalGridWidth;
if(data.children.length==2)
data.children[0].style.width = totalGridWidth;
//fix the cells' labels
for(var index=0; index < headerContent.rows[0].cells.length-1; index++)
{
var width = parseInt(headerContent.rows[0].cells[index].style.width);
var actualWidth = headerContent.rows[0].cells[index].offsetWidth - parseInt(headerContent.rows[0].cells[index].style.borderRightWidth);
if(actualWidth > width)
{
if(dataSource.getSortIndex()!=index)
headerContent.rows[0].cells[index].firstChild.children[1].innerText = junkTextToWSize(headerContent.rows[0].cells[index].firstChild.children[1].title,width-columnLeftOffset,styleHeaderCellData);
else
headerContent.rows[0].cells[index].firstChild.children[1].innerText = junkTextToWSize(headerContent.rows[0].cells[index].firstChild.children[1].title,width-(columnLeftOffset+sortPointerOffset),styleHeaderCellData);
}
}
if(dataContent.rows.length>0)
{
var supposedIndex = -1;
for(var index=0; index < dataContent.rows[0].cells.length-1; index++)
{
var width = parseInt(dataContent.rows[0].cells[index].style.width);
var actualWidth = dataContent.rows[0].cells[index].offsetWidth - parseInt(dataContent.rows[0].cells[index].style.borderRightWidth);
if(actualWidth > width)
{
//alert("actualWidth:"+actualWidth+";width"+width+";index"+index);
if(supposedRowId!=null)
{
if(supposedIndex == -1)
{
//first find the supposed row index that causes the offset of cells
for(var index3=0; index3 < dataContent.rows.length; index3++)
{
if(dataContent.rows[index3].rowId == supposedRowId)
{
supposedIndex = index3;
break;
}
}
}
//junk the supposed row
if(dataContent.rows[supposedIndex].cells[index].firstChild.children[1].tagName=="SPAN")
dataContent.rows[supposedIndex].cells[index].firstChild.children[1].innerText = junkTextToWSize(dataContent.rows[supposedIndex].cells[index].firstChild.children[1].title,width-columnLeftOffset,(supposedIndex % 2 != 0)?styleCellAlterData:styleCellData);
else
if(dataContent.rows[supposedIndex].cells[index].firstChild.children[1].tagName=="INPUT")
continue;
if((dataContent.rows[0].cells[index].offsetWidth - parseInt(dataContent.rows[0].cells[index].style.borderRightWidth))<= width)
{
continue;
}
}//if(supposedRowId!=null)
for(var index1 = 0; index1 < dataContent.rows.length; index1++ )
{
if(supposedIndex == index1)
continue;
if(dataContent.rows[index1].cells[index].firstChild.children[1].tagName=="SPAN")
dataContent.rows[index1].cells[index].firstChild.children[1].innerText = junkTextToWSize(dataContent.rows[index1].cells[index].firstChild.children[1].title,width-columnLeftOffset,(index1 % 2 != 0)?styleCellAlterData:styleCellData);
else
if(dataContent.rows[index1].cells[index].firstChild.children[1].tagName=="INPUT")
continue;
if((dataContent.rows[0].cells[index].offsetWidth - parseInt(dataContent.rows[0].cells[index].style.borderRightWidth))<= width)
{
break;
}
}
}//if(actualWidth > width)
}//for(var index=0; index < dataContent.rows[0].cells.length-1; index++)
}
}
this.changeColumnOrder = function(sourceOrder,destinationOrder)
{
//replace header columns
var sourceColumn = headerContent.rows[0].cells[sourceOrder];
var destinationColumn = headerContent.rows[0].insertCell(destinationOrder);
for(var index=0; index<sourceColumn.children.length; index++)
{
destinationColumn.appendChild(sourceColumn.children[index]);
}
destinationColumn.onmousedown = this.startDragColumnEventHandler;
destinationColumn.ondblclick = this.sortEventHandler;
destinationColumn.oncontextmenu = this.gridContextMenuClickedEventHandler;
destinationColumn.style.cssText = sourceColumn.style.cssText;
destinationColumn.style.width = sourceColumn.style.width;
if(destinationOrder>sourceOrder)
headerContent.rows[0].deleteCell(sourceOrder);
else
headerContent.rows[0].deleteCell(sourceOrder+1);
for(var index=0; index < headerContent.rows[0].cells.length; index++ )
{
if(headerContent.rows[0].cells[index].firstChild.children[2]!=null)
{//that means that it's header cell containing sort arrow
dataSource.setSortIndex(index)
break;
}
}
//replace add columns
if(data.children.length==2)
{
var addTable = data.children[0];
var sourceColumn = addTable.rows[0].cells[sourceOrder];
var destinationColumn = addTable.rows[0].insertCell(destinationOrder);
for(var index=0; index<sourceColumn.children.length; index++)
{
destinationColumn.appendChild(sourceColumn.children[index]);
}
destinationColumn.style.cssText = sourceColumn.style.cssText;
destinationColumn.style.width = sourceColumn.style.width;
if(destinationOrder>sourceOrder)
addTable.rows[0].deleteCell(sourceOrder);
else
addTable.rows[0].deleteCell(sourceOrder+1);
}
//replace data columns
for(var index=0; index<dataContent.rows.length;index++)
{
var sourceColumn = dataContent.rows[index].cells[sourceOrder];
var destinationColumn = dataContent.rows[index].insertCell(destinationOrder);
for(var index1=0; index1<sourceColumn.children.length; index1++)
{
destinationColumn.appendChild(sourceColumn.children[index1]);
}
destinationColumn.style.cssText = sourceColumn.style.cssText;
destinationColumn.style.width = sourceColumn.style.width;
if(destinationOrder>sourceOrder)
dataContent.rows[index].deleteCell(sourceOrder);
else
dataContent.rows[index].deleteCell(sourceOrder+1);
}
}
function countGridWidth()
{
var width=0;
for(var index=0;index<headerContent.rows[0].cells.length;index++)
{
var borderWidth = parseInt(headerContent.rows[0].cells[index].style.borderRightWidth);
borderWidth = isNaN(borderWidth)?0:borderWidth;
width+=parseInt(headerContent.rows[0].cells[index].style.width)+borderWidth;
}
return width;
}
function countDataCellsWidth()
{
var width=0;
for(var index=0;index<headerContent.rows[0].cells.length-1;index++)
{
var borderWidth = parseInt(headerContent.rows[0].cells[index].style.borderRightWidth);
borderWidth = isNaN(borderWidth)?0:borderWidth;
width+=parseInt(headerContent.rows[0].cells[index].style.width)+borderWidth;
}
return width;
}
this.addHeaderItem = function(headerText)
{
if(headerContent.rows.length==0)
headerContent.insertRow();
if(headerContent.rows[0].cells.length==0)
{
var stubCell = headerContent.rows[0].insertCell();
stubCell.style.cssText = styleStubHeaderCellData
stubCell.style.width = stubColumnSize;
stubCell.oncontextmenu = this.gridContextMenuClickedEventHandler;
var holder = document.createElement("<span>");
holder.style.whiteSpace = "nowrap";
var resizeCol = document.createElement("<span>");
resizeCol.innerHTML=" ";
resizeCol.style.cursor=headerResizePointer;
resizeCol.style.width=columnLeftOffset;
resizeCol.onmousedown= this.startResizeColumnEventHandler;
resizeCol.ondblclick = function(){event.cancelBubble=true;};
holder.appendChild(resizeCol);
var headerEntry = document.createElement("<span>");
headerEntry.innerHTML = " ";
holder.appendChild(headerEntry);
stubCell.appendChild(holder);
}
var cell = headerContent.rows[0].insertCell(headerContent.rows[0].cells.length-1);
var width = (columnsWSize[cell.cellIndex]==null)?defaultColumnSize:columnsWSize[cell.cellIndex];
if(width<minColumnSize)
width = minColumnSize;
cell.style.cssText = styleHeaderCellData
cell.style.width = width;
cell.onmousedown = this.startDragColumnEventHandler;
cell.ondblclick = this.sortEventHandler;
cell.oncontextmenu = this.gridContextMenuClickedEventHandler;
var holder = document.createElement("<span>");
holder.style.whiteSpace = "nowrap";
var resizeCol = document.createElement("<span>");
resizeCol.innerHTML=" ";
resizeCol.style.width=columnLeftOffset;
resizeCol.style.cursor= headerResizePointer;
resizeCol.ondblclick = function(){event.cancelBubble=true;};
resizeCol.onmousedown= this.startResizeColumnEventHandler;
holder.appendChild(resizeCol);
var headerEntry = document.createElement("<span>");
headerEntry.title = headerText;
headerEntry.innerText = headerText;
holder.appendChild(headerEntry);
cell.appendChild(holder);
}
this.addRowItem = function(rowData)
{
var row = dataContent.insertRow();
row.rowId = rowData.rowId;
row.oncontextmenu = this.rowMenuClickedEventHandler;
var isAlter = false;
if(row.rowIndex % 2 != 0)
isAlter = true;
for(var index=0; index < headerContent.rows[0].cells.length-1; index++)
{
var width = (columnsWSize[index]==null)?defaultColumnSize:columnsWSize[index];
if(width<minColumnSize)
width = minColumnSize;
var cell = row.insertCell();
cell.style.cssText =(isAlter)?styleCellAlterData:styleCellData;
cell.style.width = width;
var holder = document.createElement("<span>");
holder.style.whiteSpace = "nowrap";
var offsetItem = document.createElement("<span>");
offsetItem.innerHTML = " ";
offsetItem.style.width = columnLeftOffset;
holder.appendChild(offsetItem);
var dataEntry = document.createElement("<span>");
dataEntry.innerText = (rowData[index]==null)?" ":rowData[index];
dataEntry.title=(rowData[index]==null)?"":rowData[index];
holder.appendChild(dataEntry);
cell.appendChild(holder);
}
var stubCell = dataContent.rows[dataContent.rows.length-1].insertCell();
stubCell.style.cssText =(isAlter)?styleStubCellAlterData:styleStubCellData;
stubCell.style.width=stubColumnSize;
var holder = document.createElement("<span>");
holder.style.whiteSpace = "nowrap";
offsetItem = document.createElement("<span>");
offsetItem.innerHTML = " ";
offsetItem.style.width = columnLeftOffset;
holder.appendChild(offsetItem);
stubCell.appendChild(holder);
}
this.clearView = function()
{
if(headerContent.rows.length>0)
headerContent.deleteRow();
while(dataContent.rows.length!=0)
{
dataContent.deleteRow();
}
}
}//View class
/******** Menu View class **********/
function MenuView(menuItems)
{
var menuContent = document.body.appendChild(document.createElement("<table border='0' cellspacing='0' cellpadding='0' onselectstart='return false;' oncontextmenu='return false;' >"));
menuContent.style.cssText = styleMenu;
menuContent.style.display = "none";
menuContent.style.position = "absolute";
var thisRef = this;
for(key in menuItems)
{
var menuItem = menuContent.insertRow().insertCell();
menuItem.innerText = key;
menuItem.onclick = function()
{
menuItems[this.innerText]();
menuContent.style.display = 'none';
}
menuItem.style.cssText = styleMenuItem;
}
this.onMouseMove = function()
{
if(event.srcElement.tagName=="TD")
{
thisRef.select(event.srcElement.parentElement.rowIndex);
}
}
this.onMouseLeave = function()
{
if(event.srcElement.tagName=="TABLE")
{
thisRef.deselect();
}
}
menuContent.onmousemove = this.onMouseMove;
menuContent.onmouseleave = this.onMouseLeave;
this.show = function()
{
menuContent.style.display = "inline";
menuContent.style.left = event.clientX;
menuContent.style.top = event.clientY;
}
this.hide = function()
{
this.deselect();
menuContent.style.display = "none";
}
this.deselect = function()
{
for(index=0; index < menuContent.rows.length; index++)
{
menuContent.rows[index].cells[0].style.cssText = styleMenuItem;
}
}
this.select = function(index)
{
this.deselect();
menuContent.rows[index].cells[0].style.cssText = styleMenuSelectedItem;
}
}//MenuView
/******** DataSource class *********/
function DataSource()
{
/****** Init ******/
var dataHeaders = new Array();
var dataRows = new Array();
var sortDirection= asc;
var sortIndex = 0;
/******* Methods *******/
function sortItems(data1,data2)
{
var data1Value = data1[sortIndex];
var data2Value = data2[sortIndex];
if(data1Value==null)
data1Value = "";
if(data2Value==null)
data2Value = "";
data1Value = data1Value.toUpperCase();
data2Value = data2Value.toUpperCase();
if(sortDirection==asc)
{
if(data1Value<data2Value)
return -1;
else
if(data1Value>data2Value)
return 1;
else
return 0;
}
else
{
if(data1Value>data2Value)
return -1;
else
if(data1Value<data2Value)
return 1;
else
return 0;
}
}
this.clear = function()
{
dataHeaders = new Array();
dataRows = new Array();
sortDirection= asc;
sortIndex = 0;
}
this.changeColumnOrder = function(sourceOrder, destinationOrder)
{
var sourceHeader = dataHeaders[sourceOrder];
var newDataHeaders = new Array();
for(var index=0; index < dataHeaders.length; index++)
{
if(index == sourceOrder)
continue;
if(index == destinationOrder)
newDataHeaders.push(sourceHeader);
newDataHeaders.push(dataHeaders[index]);
}
if(destinationOrder==dataHeaders.length)
newDataHeaders.push(sourceHeader);
dataHeaders = newDataHeaders;
for(var index=0;index<dataRows.length;index++)
{
var dataRow = dataRows[index];
var sourceData = dataRow[sourceOrder];
var newDataRow = new Array();
for(var index1=0; index1<dataRow.length; index1++)
{
if(index1==sourceOrder)
continue;
if(index1 == destinationOrder)
newDataRow.push(sourceData);
newDataRow.push(dataRow[index1]);
}
if(destinationOrder==dataRow.length)
newDataRow.push(sourceData);
newDataRow.rowId = dataRow.rowId;
dataRows[index] = newDataRow;
}
}
this.updateRow = function(obj)
{
for(index=0; index < dataRows.length; index++)
{
if(dataRows[index].rowId==obj.id)
{
for(var index1=0;index1<dataRows[index].length;index1++)
{
dataRows[index][index1] = obj[index1];
}
}
}
}
this.removeRow = function(rowId)
{
for(index=0; index < dataRows.length; index++)
{
if(dataRows[index].rowId==rowId)
dataRows.splice(index,1);
}
}
this.getSortIndex = function()
{
return sortIndex;
}
this.setSortIndex = function(value)
{
sortIndex = value;
}
this.getSortDirection = function()
{
return sortDirection;
}
this.setSortDirection = function(value)
{
sortDirection = value;
}
this.addRowItem = function(rowId , arr)
{
if(maxRowsCount == dataRows.length)
alert("Unable to add row to the data source object due to the max number rows is "+maxRowsCount+".");
else{
for(var index=0; index<dataRows.length; index++)
{
if(dataRows[index].rowId == rowId)
{
alert("Unable to add row due to row Id - "+rowId+" already exists.");
return;
}
}
arr.rowId = rowId;
dataRows.push(arr);
}
}
this.addHeaderItem = function(headerText)
{
dataHeaders.push(headerText);
}
this.getRowItems = function()
{
return dataRows.sort(sortItems);
}
this.getHeaderItems = function()
{
return dataHeaders;
}
}//DataSource class
/********** Controller class ***********/
function Controller(view , dataSource , grid)
{
var itemMenu = null;
var gridMenu = null;
var thisRef = this;
this.hideAllMenu = function()
{
if(itemMenu!=null)
itemMenu.hide();
if(gridMenu!=null)
gridMenu.hide();
}
this.showItemMenu = function()
{
if(itemMenu!=null)
itemMenu.show();
}
this.showGridMenu = function()
{
if(gridMenu!=null)
gridMenu.show();
}
this.onSetItemMenu = function (menuItems)
{
itemMenu = new MenuView(menuItems);
}
this.onSetGridMenu = function(menuItems)
{
gridMenu = new MenuView(menuItems);
}
/********** Grid View Events ****************/
this.onDataBind = function()
{
view.dataBind();
}
this.onRemoveRow = function(rowId)
{
view.removeRow(rowId);
dataSource.removeRow(rowId);
}
this.onUpdateRow = function(rowID)
{
view.setGridUnselectedState();
view.setRowWriteState(rowID);
}
this.onAddRow = function()
{
view.setGridUnselectedState();
view.setRowAddState();
}
view.dataClickedEventHandler = function()
{
thisRef.hideAllMenu();
view.setGridUnselectedState();
event.cancelBubble = true;
}
view.rowUpdateKeyEnteredEventHandler = function()
{
if(event.keyCode == 13 )
{
var obj = view.saveUpdatedRowItem(this.rowId);
view.setRowReadState(this.rowId);
dataSource.updateRow(obj);
if(grid.onRowUpdated!=null)
grid.onRowUpdated(obj);
}
else
if(event.keyCode == 27)
{
view.setRowReadState(this.rowId);
}
event.cancelBubble = true;
}
view.rowUpdateClickedEventHandler = function()
{
var obj = view.saveUpdatedRowItem(this.rowId);
view.setRowReadState(this.rowId);
dataSource.updateRow(this.rowId,obj);
if(grid.onRowUpdated!=null)
grid.onRowUpdated(obj);
event.cancelBubble = true;
}
view.rowUpdateCancelClickedEventHandler = function()
{
view.setRowReadState(this.rowId);
event.cancelBubble = true;
}
view.rowAddClikedEventHandler = function()
{
var obj = view.saveAddedRowItem();
view.setGridNotAddState();
if(grid.onRowAdded!=null)
grid.onRowAdded(obj);
event.cancelBubble = true;
}
view.rowAddCancelClickedEventHandler = function()
{
view.setGridNotAddState();
event.cancelBubble = true;
}
view.rowAddKeyEnteredEventHandler = function()
{
if(event.keyCode == 13 )
{
var obj = view.saveAddedRowItem();
view.setGridNotAddState();
if(grid.onRowAdded!=null)
grid.onRowAdded(obj);
}
else
if(event.keyCode == 27)
{
view.setGridNotAddState();
}
event.cancelBubble = true;
}
view.rowAddMenuClickedEventHandler = function()
{
event.cancelBubble = true;
//do nothing
}
view.rowMenuClickedEventHandler = function(rowId)
{
if(!view.isRowWriteState(this.rowId)){
thisRef.hideAllMenu();
thisRef.showItemMenu();
view.setGridUnselectedState();
view.setRowSelectedState(this.rowId);
}
event.cancelBubble = true;
return false;
}
view.gridContextMenuClickedEventHandler = function()
{
thisRef.hideAllMenu();
view.setGridUnselectedState();
thisRef.showGridMenu();
event.cancelBubble = true;
return false;
}
view.sortEventHandler = function()
{
event.cancelBubble = true;
var columnIndex = this.cellIndex;
if(columnIndex == dataSource.getSortIndex())
{
if(dataSource.getSortDirection()==asc)
dataSource.setSortDirection(desc);
else
dataSource.setSortDirection(asc);
}
else{
dataSource.setSortIndex(columnIndex);
dataSource.setSortDirection(asc);
}
thisRef.hideAllMenu();
view.setGridUnselectedState();
view.sortItems();
event.cancelBubble = true;
}
view.dataScrollEventHandler = function()
{
thisRef.hideAllMenu();
view.setGridUnselectedState();
view.fixHeaderScrolling();
event.cancelBubble = true;
}
view.startResizeColumnEventHandler = function()
{
thisRef.hideAllMenu();
view.setGridUnselectedState();
function onResizeColumnEventHandler()
{
event.cancelBubble = true;
if(!isGridChild(event.srcElement))
{
this.click();
return;
}
//force to release capture if header index is the first cell
if(this.parentElement.parentElement.cellIndex==0)
{
this.click();
return;
}
var sizableColumn = this.parentElement.parentElement.parentElement.cells[this.parentElement.parentElement.cellIndex-1];
var newWidth = parseInt(sizableColumn.style.width)+event.screenX-this.previousX;
this.previousX = event.screenX;
if(newWidth<minColumnSize)
newWidth = minColumnSize;
view.resizeColumn(sizableColumn.cellIndex,newWidth);
}
function onResizeLeaveColumnEventHandler()
{
event.cancelBubble = true;
this.onmousemove = null;
this.onclick= null;
this.releaseCapture();
}
if(event.button==1)
{
this.onmousemove = onResizeColumnEventHandler;
this.onclick= onResizeLeaveColumnEventHandler;
this.previousX = event.screenX
this.setCapture(false);
}
event.cancelBubble = true;
}
view.startDragColumnEventHandler = function()
{
thisRef.hideAllMenu();
view.setGridUnselectedState();
function onPrepareDrag()
{
if(this.previous==null)
{
event.cancelBubble = true;
this.previous = event.screenX;
}
var span = this.previous-event.screenX;
if(span > pixelDelayDragDrop || span < -pixelDelayDragDrop)
{
this.onmousemove = onDragColumn;
this.previous = null;
}
}
function onDragColumn()
{
event.cancelBubble = true;
if(!isGridChild(event.srcElement))
{
this.newCellIndex = null;
this.click();
return;
}
this.newCellIndex = view.dragColumn(this.cellIndex,event.x);
}
function onDragColumnLeave()
{
event.cancelBubble = true;
view.stopDragColumn(this.cellIndex);
this.onmousemove = null;
this.onclick = null;
this.releaseCapture();
//replace columns in dataSource and view
var cellIndex = this.cellIndex;
var newCellIndex = this.newCellIndex;
if(newCellIndex!=null)
{
view.changeColumnOrder(cellIndex,newCellIndex);
dataSource.changeColumnOrder(cellIndex,newCellIndex);
}
this.newCellIndex = null;
}
if(event.button==1)
{
this.setCapture(false);
this.onmousemove = onPrepareDrag;
this.onclick = onDragColumnLeave;
}
event.cancelBubble = true;
}
view.bindEvents();
}//Controller class
}