UNPKG

ucbuilder

Version:

For Developing Applications with multiple form/usercontrols etc.. In Single BrowserWindow...

268 lines (267 loc) 10.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TabIndexManager = void 0; const common_1 = require("ucbuilder/build/common"); const keyboard_1 = require("ucbuilder/global/hardware/keyboard"); class TabIndexManager { constructor() { this.allowNodePattern = /INPUT|SELECT|BUTTON|TEXTAREA/i; } init(mainHT) { this.mainHT = mainHT; let htEle; let tIndex; document.addEventListener('keydown', (ev) => { let code = ev.keyCode; switch (code) { case keyboard_1.keyBoard.keys.enter: //console.log(Object.getPrototypeOf(ev.target).constructor.name); if (code == keyboard_1.keyBoard.keys.enter && Object.getPrototypeOf(ev.target).constructor.name == 'HTMLTextAreaElement') { let ele = ev.target; let _val = ele.value; if (_val != '' && _val == ele.getSelectedValue()) { } else { if (!_val.endsWith('\n')) return; else ele.value = _val.slice(0, -1); } } case keyboard_1.keyBoard.keys.tab: if (!ev.shiftKey) this.keymoveNext(ev.target); else this.keymovePrev(ev.target); ev.preventDefault(); break; case keyboard_1.keyBoard.keys.left: htEle = ev.target; tIndex = this.getTindex(htEle); if (tIndex != null) { if (htEle.nodeName.match(this.allowNodePattern) == null && htEle.getAttribute("contenteditable") != "true") { this.keymovePrev(htEle); ev.preventDefault(); } } break; case keyboard_1.keyBoard.keys.right: htEle = ev.target; tIndex = this.getTindex(htEle); if (tIndex != null) { if (htEle.nodeName.match(this.allowNodePattern) == null && htEle.getAttribute("contenteditable") != "true") { this.keymoveNext(htEle); ev.preventDefault(); } } break; } }); document.addEventListener("mousedown", (ev) => { htEle = ev.target; tIndex = this.getTindex(htEle); if (tIndex != null) { if (htEle.nodeName.match(this.allowNodePattern) == null && htEle.getAttribute("contenteditable") != "true") { this.moveNext(htEle, tIndex); ev.preventDefault(); } } }); } keymovePrev(target) { let _this = this; let tIndex = this.getTindex(target); if (tIndex == null) return; tIndex--; this.movePrev(target, tIndex); } movePrev(target, tIndex = -1) { let _this = this; if (tIndex == null) return; if (tIndex == -1) { let container = _this.getClosest(target); tIndex = this.getTindex(container); let pcontainer = _this.getClosest(container); return this.movePrev(pcontainer, tIndex - 1); } else { let container = target; let prevRow = this.getChildIfExist(container, tIndex, true); if (prevRow.element != undefined) { if (this.isFocusableElement(prevRow.element)) this.focusTo(prevRow.element); } else { container = _this.getClosest(target); prevRow = this.getChildIfExist(container, tIndex, true); if (prevRow.element != undefined) this.focusTo(prevRow.element); } } } keymoveNext(target) { let _this = this; let tIndex = this.getTindex(target); if (tIndex == null) return; tIndex++; this.moveNext(target, tIndex); } moveNext(target, tIndex = -1) { let _this = this; if (tIndex == null) return; let row = this.getChildIfExist(target, 0); let container; if (row.element == null) { container = this.getClosest(target); if (container == null) return; let nextRow = this.getChildIfExist(container, tIndex); if (nextRow.element != undefined) { if (this.isFocusableElement(nextRow.element)) { this.focusTo(nextRow.element); } else { doProcessNext(nextRow.element, nextRow.tIndex); } } else { doProcessNext(nextRow.container, this.getTindex(nextRow.container)); } } else { if (this.isFocusableElement(row.element)) { this.focusTo(row.element); } else doProcessNext(row.element, row.tIndex); } function doProcessNext(ele, tIndex) { if (tIndex == null) return; tIndex++; let container = _this.getClosest(ele); if (container == null) { let index = _this.getTindex(ele); index = Math.max(0, index); _this.moveNext(ele, index); return; } let nextRow = _this.getChildIfExist(container, tIndex); if (nextRow.element != undefined) _this.moveNext(nextRow.element, nextRow.tIndex); } } focusTo(htele) { htele.setAttribute('tabindex', '0'); console.log('focusTo'); htele.focus(); common_1.controlOpt.selectAllText(htele); } getTindex(target) { if (target == undefined) return null; let tIndex = target.getAttribute('x-tabindex'); return (tIndex == null) ? null : parseInt(tIndex); } getClosest(target) { return target.parentElement.closest("[x-tabindex]"); } getChildIfExist(container, index, giveMeLastElement = false) { let _this = this; let rtrn = { container: container, element: undefined, tIndex: -1, }; if (container == null) return rtrn; let elements = []; if (!giveMeLastElement) { elements = Array.from(container.querySelectorAll(`[x-tabindex="${index}"]`)); /* , [x-tabindex] * */ for (let i = 0; i < elements.length; i++) { let ele = elements[i]; let sub = this.getChildIfExist(ele, 0); if (sub.element == undefined) { rtrn.element = ele; rtrn.tIndex = this.getTindex(ele); break; } else return sub; } return rtrn; } else { rtrn = getMaxTabIndexElement(container, index); if (rtrn.container != null) { if (!rtrn.container.is(container)) { rtrn.element = rtrn.container; rtrn.container = this.getClosest(rtrn.container); rtrn.tIndex = this.getTindex(rtrn.container); } } return rtrn; } function getMaxTabIndexElement(container, index, elements, calltime = 0) { calltime++; let maxRtrn = { container: container, element: undefined, tIndex: -1, }; if (container == null) return maxRtrn; if (elements == undefined) elements = Array.from(container.querySelectorAll(`[x-tabindex="${index}"]`)); else if (calltime == 2) elements = Array.from(container.querySelectorAll(`[x-tabindex]`)); for (let i = 0; i < elements.length; i++) { let ele = elements[i]; if (_this.isDirectClose(ele, container)) { elements.splice(index, 1); let tIndex = _this.getTindex(ele); if (tIndex >= maxRtrn.tIndex) { maxRtrn.tIndex = tIndex; maxRtrn.element = ele; maxRtrn.container = container; } } } if (maxRtrn.element != undefined) return getMaxTabIndexElement(maxRtrn.element, maxRtrn.tIndex, elements, calltime); return maxRtrn; } } isFocusableElement(htEle) { if (htEle == undefined) return false; let style = window.getComputedStyle(htEle); if (style.pointerEvents == "none") return false; if (htEle.nodeName.match(this.allowNodePattern) != null || htEle.getAttribute("contenteditable") == "true" || htEle.getAttribute("disabled") !== 'true') { return true; } else { return false; } } isDirectClose(child, container) { return container.is(child.parentElement.closest(`[x-tabindex]`)); } } exports.TabIndexManager = TabIndexManager; const elementState = Object.freeze({ Undefined: 0, Editable: 1, Disabled: 2, Container: 3, });