UNPKG

tabulator-tables

Version:

Interactive table generation JavaScript library

314 lines (257 loc) 8.02 kB
import Module from '../../core/Module.js'; import Cell from '../../core/cell/Cell.js'; import Column from '../../core/column/Column.js'; class Interaction extends Module{ constructor(table){ super(table); this.eventMap = { //row events rowClick:"row-click", rowDblClick:"row-dblclick", rowContext:"row-contextmenu", rowMouseEnter:"row-mouseenter", rowMouseLeave:"row-mouseleave", rowMouseOver:"row-mouseover", rowMouseOut:"row-mouseout", rowMouseMove:"row-mousemove", rowTap:"row", rowDblTap:"row", rowTapHold:"row", //cell events cellClick:"cell-click", cellDblClick:"cell-dblclick", cellContext:"cell-contextmenu", cellMouseEnter:"cell-mouseenter", cellMouseLeave:"cell-mouseleave", cellMouseOver:"cell-mouseover", cellMouseOut:"cell-mouseout", cellMouseMove:"cell-mousemove", cellTap:"cell", cellDblTap:"cell", cellTapHold:"cell", //column header events headerClick:"column-click", headerDblClick:"column-dblclick", headerContext:"column-contextmenu", headerMouseEnter:"column-mouseenter", headerMouseLeave:"column-mouseleave", headerMouseOver:"column-mouseover", headerMouseOut:"column-mouseout", headerMouseMove:"column-mousemove", headerTap:"column", headerDblTap:"column", headerTapHold:"column", //group header groupClick:"group-click", groupDblClick:"group-dblclick", groupContext:"group-contextmenu", groupMouseEnter:"group-mouseenter", groupMouseLeave:"group-mouseleave", groupMouseOver:"group-mouseover", groupMouseOut:"group-mouseout", groupMouseMove:"group-mousemove", groupTap:"group", groupDblTap:"group", groupTapHold:"group", }; this.subscribers = {}; this.touchSubscribers = {}; this.columnSubscribers = {}; this.touchWatchers = { row:{ tap:null, tapDbl:null, tapHold:null, }, cell:{ tap:null, tapDbl:null, tapHold:null, }, column:{ tap:null, tapDbl:null, tapHold:null, }, group:{ tap:null, tapDbl:null, tapHold:null, } }; this.registerColumnOption("headerClick"); this.registerColumnOption("headerDblClick"); this.registerColumnOption("headerContext"); this.registerColumnOption("headerMouseEnter"); this.registerColumnOption("headerMouseLeave"); this.registerColumnOption("headerMouseOver"); this.registerColumnOption("headerMouseOut"); this.registerColumnOption("headerMouseMove"); this.registerColumnOption("headerTap"); this.registerColumnOption("headerDblTap"); this.registerColumnOption("headerTapHold"); this.registerColumnOption("cellClick"); this.registerColumnOption("cellDblClick"); this.registerColumnOption("cellContext"); this.registerColumnOption("cellMouseEnter"); this.registerColumnOption("cellMouseLeave"); this.registerColumnOption("cellMouseOver"); this.registerColumnOption("cellMouseOut"); this.registerColumnOption("cellMouseMove"); this.registerColumnOption("cellTap"); this.registerColumnOption("cellDblTap"); this.registerColumnOption("cellTapHold"); } initialize(){ this.initializeExternalEvents(); this.subscribe("column-init", this.initializeColumn.bind(this)); this.subscribe("cell-dblclick", this.cellContentsSelectionFixer.bind(this)); } cellContentsSelectionFixer(e, cell){ var range; if(this.table.modExists("edit")){ if (this.table.modules.edit.currentCell === cell){ return; //prevent instant selection of editor content } } e.preventDefault(); try{ if (document.selection) { // IE range = document.body.createTextRange(); range.moveToElementText(cell.getElement()); range.select(); } else if (window.getSelection) { range = document.createRange(); range.selectNode(cell.getElement()); window.getSelection().removeAllRanges(); window.getSelection().addRange(range); } }catch(e){} } initializeExternalEvents(){ for(let key in this.eventMap){ this.subscriptionChangeExternal(key, this.subscriptionChanged.bind(this, key)); } } subscriptionChanged(key, added){ if(added){ if(!this.subscribers[key]){ if(this.eventMap[key].includes("-")){ this.subscribers[key] = this.handle.bind(this, key); this.subscribe(this.eventMap[key], this.subscribers[key]); }else{ this.subscribeTouchEvents(key); } } }else{ if(this.eventMap[key].includes("-")){ if(this.subscribers[key] && !this.columnSubscribers[key] && !this.subscribedExternal(key)){ this.unsubscribe(this.eventMap[key], this.subscribers[key]); delete this.subscribers[key]; } }else{ this.unsubscribeTouchEvents(key); } } } subscribeTouchEvents(key){ var type = this.eventMap[key]; if(!this.touchSubscribers[type + "-touchstart"]){ this.touchSubscribers[type + "-touchstart"] = this.handleTouch.bind(this, type, "start"); this.touchSubscribers[type + "-touchend"] = this.handleTouch.bind(this, type, "end"); this.subscribe(type + "-touchstart", this.touchSubscribers[type + "-touchstart"]); this.subscribe(type + "-touchend", this.touchSubscribers[type + "-touchend"]); } this.subscribers[key] = true; } unsubscribeTouchEvents(key){ var noTouch = true, type = this.eventMap[key]; if(this.subscribers[key] && !this.subscribedExternal(key)){ delete this.subscribers[key]; for(let i in this.eventMap){ if(this.eventMap[i] === type){ if(this.subscribers[i]){ noTouch = false; } } } if(noTouch){ this.unsubscribe(type + "-touchstart", this.touchSubscribers[type + "-touchstart"]); this.unsubscribe(type + "-touchend", this.touchSubscribers[type + "-touchend"]); delete this.touchSubscribers[type + "-touchstart"]; delete this.touchSubscribers[type + "-touchend"]; } } } initializeColumn(column){ var def = column.definition; for(let key in this.eventMap){ if(def[key]){ this.subscriptionChanged(key, true); if(!this.columnSubscribers[key]){ this.columnSubscribers[key] = []; } this.columnSubscribers[key].push(column); } } } handle(action, e, component){ this.dispatchEvent(action, e, component); } handleTouch(type, action, e, component){ var watchers = this.touchWatchers[type]; if(type === "column"){ type = "header"; } switch(action){ case "start": watchers.tap = true; clearTimeout(watchers.tapHold); watchers.tapHold = setTimeout(() => { clearTimeout(watchers.tapHold); watchers.tapHold = null; watchers.tap = null; clearTimeout(watchers.tapDbl); watchers.tapDbl = null; this.dispatchEvent(type + "TapHold", e, component); }, 1000); break; case "end": if(watchers.tap){ watchers.tap = null; this.dispatchEvent(type + "Tap", e, component); } if(watchers.tapDbl){ clearTimeout(watchers.tapDbl); watchers.tapDbl = null; this.dispatchEvent(type + "DblTap", e, component); }else{ watchers.tapDbl = setTimeout(() => { clearTimeout(watchers.tapDbl); watchers.tapDbl = null; }, 300); } clearTimeout(watchers.tapHold); watchers.tapHold = null; break; } } dispatchEvent(action, e, component){ var componentObj = component.getComponent(), callback; if(this.columnSubscribers[action]){ if(component instanceof Cell){ callback = component.column.definition[action]; }else if(component instanceof Column){ callback = component.definition[action]; } if(callback){ callback(e, componentObj); } } this.dispatchExternal(action, e, componentObj); } } Interaction.moduleName = "interaction"; export default Interaction;