The Table navigation functionality was factored out to the Navigation class. Minor table performance fixes.
This commit is contained in:
parent
917958bc4c
commit
2bd40037d1
|
|
@ -63,6 +63,7 @@ class Table extends WidgetBase
|
|||
{
|
||||
$this->addCss('css/table.css', 'core');
|
||||
$this->addJs('js/table.js', 'core');
|
||||
$this->addJs('js/table.helper.navigation.js', 'core');
|
||||
$this->addJs('js/table.datasource.base.js', 'core');
|
||||
$this->addJs('js/table.datasource.client.js', 'core');
|
||||
$this->addJs('js/table.processor.base.js', 'core');
|
||||
|
|
|
|||
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* Navigation helper for the table widget.
|
||||
* Implements the keyboard navigation within the current page
|
||||
* and pagination.
|
||||
*/
|
||||
+function ($) { "use strict";
|
||||
|
||||
// NAMESPACE CHECK
|
||||
// ============================
|
||||
|
||||
if ($.oc.table === undefined)
|
||||
throw new Error("The $.oc.table namespace is not defined. Make sure that the table.js script is loaded.");
|
||||
|
||||
if ($.oc.table.helper === undefined)
|
||||
$.oc.table.helper = {}
|
||||
|
||||
// NAVIGATION CLASS DEFINITION
|
||||
// ============================
|
||||
|
||||
var Navigation = function(tableObj) {
|
||||
// Reference to the table object
|
||||
this.tableObj = tableObj
|
||||
|
||||
// Event handlers
|
||||
this.keydownHandler = this.onKeydown.bind(this)
|
||||
|
||||
this.init()
|
||||
};
|
||||
|
||||
Navigation.prototype.init = function() {
|
||||
this.registerHandlers()
|
||||
}
|
||||
|
||||
Navigation.prototype.dispose = function() {
|
||||
// Unregister event handlers
|
||||
this.unregisterHandlers()
|
||||
|
||||
// Remove the reference to the table object
|
||||
this.tableObj = null
|
||||
}
|
||||
|
||||
Navigation.prototype.registerHandlers = function() {
|
||||
this.tableObj.el.addEventListener('keydown', this.keydownHandler)
|
||||
}
|
||||
|
||||
Navigation.prototype.unregisterHandlers = function() {
|
||||
this.tableObj.el.removeEventListener('keydown', this.keydownHandler);
|
||||
this.keydownHandler = null
|
||||
}
|
||||
|
||||
// KEYBOARD NAVIGATION
|
||||
// ============================
|
||||
|
||||
Navigation.prototype.navigateDown = function(ev) {
|
||||
if (!this.tableObj.activeCell)
|
||||
return
|
||||
|
||||
if (this.tableObj.activeCellProcessor && !this.tableObj.activeCellProcessor.keyNavigationAllowed(ev, 'down'))
|
||||
return
|
||||
|
||||
var row = this.tableObj.activeCell.parentNode,
|
||||
newRow = !ev.shiftKey ?
|
||||
row.nextElementSibling :
|
||||
row.parentNode.children[row.parentNode.children.length - 1]
|
||||
|
||||
if (!newRow)
|
||||
return
|
||||
|
||||
var cell = newRow.children[this.tableObj.activeCell.cellIndex]
|
||||
|
||||
if (cell)
|
||||
this.tableObj.focusCell(cell)
|
||||
}
|
||||
|
||||
Navigation.prototype.navigateUp = function(ev) {
|
||||
if (!this.tableObj.activeCell)
|
||||
return
|
||||
|
||||
if (this.tableObj.activeCellProcessor && !this.tableObj.activeCellProcessor.keyNavigationAllowed(ev, 'up'))
|
||||
return
|
||||
|
||||
var row = this.tableObj.activeCell.parentNode,
|
||||
newRow = !ev.shiftKey ?
|
||||
row.previousElementSibling :
|
||||
row.parentNode.children[0]
|
||||
|
||||
if (!newRow)
|
||||
return
|
||||
|
||||
var cell = newRow.children[this.tableObj.activeCell.cellIndex]
|
||||
|
||||
if (cell)
|
||||
this.tableObj.focusCell(cell)
|
||||
}
|
||||
|
||||
Navigation.prototype.navigateLeft = function(ev) {
|
||||
if (!this.tableObj.activeCell)
|
||||
return
|
||||
|
||||
if (this.tableObj.activeCellProcessor && !this.tableObj.activeCellProcessor.keyNavigationAllowed(ev, 'left'))
|
||||
return
|
||||
|
||||
var row = this.tableObj.activeCell.parentNode,
|
||||
newIndex = !ev.shiftKey ?
|
||||
this.tableObj.activeCell.cellIndex-1 :
|
||||
0
|
||||
|
||||
var cell = row.children[newIndex]
|
||||
|
||||
if (cell)
|
||||
this.tableObj.focusCell(cell)
|
||||
}
|
||||
|
||||
Navigation.prototype.navigateRight = function(ev) {
|
||||
if (!this.tableObj.activeCell)
|
||||
return
|
||||
|
||||
if (this.tableObj.activeCellProcessor && !this.tableObj.activeCellProcessor.keyNavigationAllowed(ev, 'right'))
|
||||
return
|
||||
|
||||
var row = this.tableObj.activeCell.parentNode,
|
||||
newIndex = !ev.shiftKey ?
|
||||
this.tableObj.activeCell.cellIndex+1 :
|
||||
row.children.length-1
|
||||
|
||||
var cell = row.children[newIndex]
|
||||
|
||||
if (cell)
|
||||
this.tableObj.focusCell(cell)
|
||||
}
|
||||
|
||||
Navigation.prototype.navigateNext = function(ev) {
|
||||
if (!this.tableObj.activeCell)
|
||||
return
|
||||
|
||||
if (this.tableObj.activeCellProcessor && !this.tableObj.activeCellProcessor.keyNavigationAllowed(ev, 'tab'))
|
||||
return
|
||||
|
||||
var row = this.tableObj.activeCell.parentNode,
|
||||
cellCount = row.children.length,
|
||||
cellIndex = this.tableObj.activeCell.cellIndex
|
||||
|
||||
if (!ev.shiftKey) {
|
||||
if (cellIndex < cellCount-1)
|
||||
this.tableObj.focusCell(row.children[cellIndex+1])
|
||||
else {
|
||||
if (row.nextElementSibling)
|
||||
this.tableObj.focusCell(row.nextElementSibling.children[0])
|
||||
}
|
||||
} else {
|
||||
if (cellIndex > 0)
|
||||
this.tableObj.focusCell(row.children[cellIndex-1])
|
||||
else {
|
||||
if (row.previousElementSibling)
|
||||
this.tableObj.focusCell(row.previousElementSibling.children[cellCount-1])
|
||||
}
|
||||
}
|
||||
|
||||
this.tableObj.stopEvent(ev)
|
||||
}
|
||||
|
||||
// EVENT HANDLERS
|
||||
// ============================
|
||||
|
||||
Navigation.prototype.onKeydown = function(ev) {
|
||||
// Handle keyboard navigation events.
|
||||
|
||||
if (ev.keyCode == 40)
|
||||
return this.navigateDown(ev)
|
||||
else if (ev.keyCode == 38)
|
||||
return this.navigateUp(ev)
|
||||
else if (ev.keyCode == 37)
|
||||
return this.navigateLeft(ev)
|
||||
if (ev.keyCode == 39)
|
||||
return this.navigateRight(ev)
|
||||
if (ev.keyCode == 9)
|
||||
return this.navigateNext(ev)
|
||||
}
|
||||
|
||||
$.oc.table.helper.navigation = Navigation;
|
||||
}(window.jQuery);
|
||||
|
|
@ -52,14 +52,16 @@
|
|||
|
||||
// Event handlers
|
||||
this.clickHandler = this.onClick.bind(this)
|
||||
this.keydownHandler = this.onKeydown.bind(this)
|
||||
|
||||
// Navigation helper
|
||||
this.navigation = null
|
||||
|
||||
//
|
||||
// Initialization
|
||||
//
|
||||
|
||||
this.init()
|
||||
};
|
||||
}
|
||||
|
||||
// INTERNAL METHODS
|
||||
// ============================
|
||||
|
|
@ -71,6 +73,9 @@
|
|||
// Create cell processors
|
||||
this.initCellProcessors()
|
||||
|
||||
// Initialize helpers
|
||||
this.navigation = new $.oc.table.helper.navigation(this)
|
||||
|
||||
// Create header and data tables
|
||||
this.buildTables()
|
||||
|
||||
|
|
@ -109,12 +114,12 @@
|
|||
|
||||
Table.prototype.registerHandlers = function() {
|
||||
this.el.addEventListener('click', this.clickHandler)
|
||||
this.el.addEventListener('keydown', this.keydownHandler)
|
||||
}
|
||||
|
||||
Table.prototype.unregisterHandlers = function() {
|
||||
this.el.removeEventListener('click', this.clickHandler);
|
||||
this.el.removeEventListener('keydown', this.keydownHandler);
|
||||
|
||||
this.clickHandler = null
|
||||
}
|
||||
|
||||
Table.prototype.initCellProcessors = function() {
|
||||
|
|
@ -293,114 +298,6 @@
|
|||
cellElement.parentNode.setAttribute('data-dirty', 1)
|
||||
}
|
||||
|
||||
Table.prototype.navigateDown = function(ev) {
|
||||
if (!this.activeCell)
|
||||
return
|
||||
|
||||
if (this.activeCellProcessor && !this.activeCellProcessor.keyNavigationAllowed(ev, 'down'))
|
||||
return
|
||||
|
||||
var row = this.activeCell.parentNode,
|
||||
newRow = !ev.shiftKey ?
|
||||
row.nextElementSibling :
|
||||
row.parentNode.children[row.parentNode.children.length - 1]
|
||||
|
||||
if (!newRow)
|
||||
return
|
||||
|
||||
var cell = newRow.children[this.activeCell.cellIndex]
|
||||
|
||||
if (cell)
|
||||
this.focusCell(cell)
|
||||
}
|
||||
|
||||
Table.prototype.navigateUp = function(ev) {
|
||||
if (!this.activeCell)
|
||||
return
|
||||
|
||||
if (this.activeCellProcessor && !this.activeCellProcessor.keyNavigationAllowed(ev, 'up'))
|
||||
return
|
||||
|
||||
var row = this.activeCell.parentNode,
|
||||
newRow = !ev.shiftKey ?
|
||||
row.previousElementSibling :
|
||||
row.parentNode.children[0]
|
||||
|
||||
if (!newRow)
|
||||
return
|
||||
|
||||
var cell = newRow.children[this.activeCell.cellIndex]
|
||||
|
||||
if (cell)
|
||||
this.focusCell(cell)
|
||||
}
|
||||
|
||||
Table.prototype.navigateLeft = function(ev) {
|
||||
if (!this.activeCell)
|
||||
return
|
||||
|
||||
if (this.activeCellProcessor && !this.activeCellProcessor.keyNavigationAllowed(ev, 'left'))
|
||||
return
|
||||
|
||||
var row = this.activeCell.parentNode,
|
||||
newIndex = !ev.shiftKey ?
|
||||
this.activeCell.cellIndex-1 :
|
||||
0
|
||||
|
||||
var cell = row.children[newIndex]
|
||||
|
||||
if (cell)
|
||||
this.focusCell(cell)
|
||||
}
|
||||
|
||||
Table.prototype.navigateRight = function(ev) {
|
||||
if (!this.activeCell)
|
||||
return
|
||||
|
||||
if (this.activeCellProcessor && !this.activeCellProcessor.keyNavigationAllowed(ev, 'right'))
|
||||
return
|
||||
|
||||
var row = this.activeCell.parentNode,
|
||||
newIndex = !ev.shiftKey ?
|
||||
this.activeCell.cellIndex+1 :
|
||||
row.children.length-1
|
||||
|
||||
var cell = row.children[newIndex]
|
||||
|
||||
if (cell)
|
||||
this.focusCell(cell)
|
||||
}
|
||||
|
||||
Table.prototype.navigateNext = function(ev) {
|
||||
if (!this.activeCell)
|
||||
return
|
||||
|
||||
if (this.activeCellProcessor && !this.activeCellProcessor.keyNavigationAllowed(ev, 'tab'))
|
||||
return
|
||||
|
||||
var row = this.activeCell.parentNode,
|
||||
cellCount = row.children.length,
|
||||
cellIndex = this.activeCell.cellIndex
|
||||
|
||||
if (!ev.shiftKey) {
|
||||
if (cellIndex < cellCount-1)
|
||||
this.focusCell(row.children[cellIndex+1])
|
||||
else {
|
||||
if (row.nextElementSibling)
|
||||
this.focusCell(row.nextElementSibling.children[0])
|
||||
}
|
||||
} else {
|
||||
if (cellIndex > 0)
|
||||
this.focusCell(row.children[cellIndex-1])
|
||||
else {
|
||||
if (row.previousElementSibling)
|
||||
this.focusCell(row.previousElementSibling.children[cellCount-1])
|
||||
}
|
||||
}
|
||||
|
||||
this.stopEvent(ev)
|
||||
}
|
||||
|
||||
// EVENT HANDLERS
|
||||
// ============================
|
||||
|
||||
|
|
@ -416,24 +313,6 @@
|
|||
this.focusCell(target)
|
||||
}
|
||||
|
||||
Table.prototype.onKeydown = function(ev) {
|
||||
// Handle keyboard navigation events.
|
||||
// Cell processor editors should stop the keydown event
|
||||
// bubbling if they handle the up/down/left/right
|
||||
// keys by themselves.
|
||||
|
||||
if (ev.keyCode == 40)
|
||||
return this.navigateDown(ev)
|
||||
else if (ev.keyCode == 38)
|
||||
return this.navigateUp(ev)
|
||||
else if (ev.keyCode == 37)
|
||||
return this.navigateLeft(ev)
|
||||
if (ev.keyCode == 39)
|
||||
return this.navigateRight(ev)
|
||||
if (ev.keyCode == 9)
|
||||
return this.navigateNext(ev)
|
||||
}
|
||||
|
||||
// PUBLIC METHODS
|
||||
// ============================
|
||||
|
||||
|
|
@ -451,6 +330,10 @@
|
|||
// Dispose cell processors
|
||||
this.disposeCellProcessors()
|
||||
|
||||
// Dispose helpers and remove references
|
||||
this.navigation.dispose()
|
||||
this.navigation = null
|
||||
|
||||
// Delete the reference to the control HTML element.
|
||||
// The script doesn't remove any DOM elements themselves.
|
||||
// If it's needed it should be done by the outer script,
|
||||
|
|
|
|||
|
|
@ -157,15 +157,19 @@
|
|||
if (document.selection) {
|
||||
var range = input.createTextRange()
|
||||
|
||||
range.collapse(true)
|
||||
range.moveStart("character", position)
|
||||
range.moveEnd("character", 0)
|
||||
range.select()
|
||||
setTimeout(function(){
|
||||
range.collapse(true)
|
||||
range.moveStart("character", position)
|
||||
range.moveEnd("character", 0)
|
||||
range.select()
|
||||
}, 0)
|
||||
}
|
||||
|
||||
if (input.selectionStart !== undefined) {
|
||||
input.selectionStart = position
|
||||
input.selectionEnd = position
|
||||
setTimeout(function(){
|
||||
input.selectionStart = position
|
||||
input.selectionEnd = position
|
||||
}, 0)
|
||||
}
|
||||
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -302,4 +302,4 @@
|
|||
|
||||
?>
|
||||
|
||||
<div data-control="table" data-columns="<?= e(json_encode($columns)) ?>" data-data="<?= e(json_encode($data)) ?>"></div>
|
||||
<div data-control="table" data-columns="<?= e(json_encode($columns)) ?>" data-data="<?= e(json_encode($data)) ?>" data-records-per-page="10"></div>
|
||||
Loading…
Reference in New Issue