michael@0: const nsIDOMKeyEvent = Components.interfaces.nsIDOMKeyEvent; michael@0: michael@0: /** michael@0: * Create grid object based on HTML table. michael@0: */ michael@0: function grid(aTableIdentifier) michael@0: { michael@0: this.getRowCount = function getRowCount() michael@0: { michael@0: return this.table.rows.length - (this.table.tHead ? 1 : 0); michael@0: } michael@0: this.getColsCount = function getColsCount() michael@0: { michael@0: return this.table.rows[0].cells.length; michael@0: } michael@0: michael@0: this.getRowAtIndex = function getRowAtIndex(aIndex) michael@0: { michael@0: return this.table.rows[this.table.tHead ? aIndex + 1 : aIndex]; michael@0: } michael@0: michael@0: this.getMaxIndex = function getMaxIndex() michael@0: { michael@0: return this.getRowCount() * this.getColsCount() - 1; michael@0: } michael@0: michael@0: this.getCellAtIndex = function getCellAtIndex(aIndex) michael@0: { michael@0: var rowCount = this.getRowCount(); michael@0: var colsCount = this.getColsCount(); michael@0: michael@0: var rowIdx = Math.floor(aIndex / colsCount); michael@0: var colIdx = aIndex % colsCount; michael@0: michael@0: var row = this.getRowAtIndex(rowIdx); michael@0: return row.cells[colIdx]; michael@0: } michael@0: michael@0: this.getIndexByCell = function getIndexByCell(aCell) michael@0: { michael@0: var colIdx = aCell.cellIndex; michael@0: michael@0: var rowIdx = aCell.parentNode.rowIndex; michael@0: if (this.table.tHead) michael@0: rowIdx -= 1; michael@0: michael@0: var colsCount = this.getColsCount(); michael@0: return rowIdx * colsCount + colIdx; michael@0: } michael@0: michael@0: this.getCurrentCell = function getCurrentCell() michael@0: { michael@0: var rowCount = this.table.rows.length; michael@0: var colsCount = this.getColsCount(); michael@0: for (var rowIdx = 0; rowIdx < rowCount; rowIdx++) { michael@0: for (var colIdx = 0; colIdx < colsCount; colIdx++) { michael@0: var cell = this.table.rows[rowIdx].cells[colIdx]; michael@0: if (cell.hasAttribute("tabindex")) michael@0: return cell; michael@0: } michael@0: } michael@0: return null; michael@0: } michael@0: michael@0: this.initGrid = function initGrid() michael@0: { michael@0: this.table.addEventListener("keypress", this, false); michael@0: this.table.addEventListener("click", this, false); michael@0: } michael@0: michael@0: this.handleEvent = function handleEvent(aEvent) michael@0: { michael@0: if (aEvent instanceof nsIDOMKeyEvent) michael@0: this.handleKeyEvent(aEvent); michael@0: else michael@0: this.handleClickEvent(aEvent); michael@0: } michael@0: michael@0: this.handleKeyEvent = function handleKeyEvent(aEvent) michael@0: { michael@0: if (aEvent.target.localName != "td") michael@0: return; michael@0: michael@0: var cell = aEvent.target; michael@0: switch(aEvent.keyCode) { michael@0: case nsIDOMKeyEvent.DOM_VK_UP: michael@0: var colsCount = this.getColsCount(); michael@0: var idx = this.getIndexByCell(cell); michael@0: var upidx = idx - colsCount; michael@0: if (upidx >= 0) { michael@0: cell.removeAttribute("tabindex"); michael@0: var upcell = this.getCellAtIndex(upidx); michael@0: upcell.setAttribute("tabindex", "0"); michael@0: upcell.focus(); michael@0: } michael@0: break; michael@0: michael@0: case nsIDOMKeyEvent.DOM_VK_DOWN: michael@0: var colsCount = this.getColsCount(); michael@0: var idx = this.getIndexByCell(cell); michael@0: var downidx = idx + colsCount; michael@0: if (downidx <= this.getMaxIndex()) { michael@0: cell.removeAttribute("tabindex"); michael@0: var downcell = this.getCellAtIndex(downidx); michael@0: downcell.setAttribute("tabindex", "0"); michael@0: downcell.focus(); michael@0: } michael@0: break; michael@0: michael@0: case nsIDOMKeyEvent.DOM_VK_LEFT: michael@0: var idx = this.getIndexByCell(cell); michael@0: if (idx > 0) { michael@0: cell.removeAttribute("tabindex"); michael@0: var prevcell = this.getCellAtIndex(idx - 1); michael@0: prevcell.setAttribute("tabindex", "0"); michael@0: prevcell.focus(); michael@0: } michael@0: break; michael@0: michael@0: case nsIDOMKeyEvent.DOM_VK_RIGHT: michael@0: var idx = this.getIndexByCell(cell); michael@0: if (idx < this.getMaxIndex()) { michael@0: cell.removeAttribute("tabindex"); michael@0: var nextcell = this.getCellAtIndex(idx + 1); michael@0: nextcell.setAttribute("tabindex", "0"); michael@0: nextcell.focus(); michael@0: } michael@0: break; michael@0: } michael@0: } michael@0: michael@0: this.handleClickEvent = function handleClickEvent(aEvent) michael@0: { michael@0: if (aEvent.target.localName != "td") michael@0: return; michael@0: michael@0: var curCell = this.getCurrentCell(); michael@0: var cell = aEvent.target; michael@0: michael@0: if (cell != curCell) { michael@0: curCell.removeAttribute("tabindex"); michael@0: cell.setAttribute("tabindex", "0"); michael@0: cell.focus(); michael@0: } michael@0: } michael@0: michael@0: this.table = getNode(aTableIdentifier); michael@0: this.initGrid(); michael@0: }