mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-14 11:37:43 +00:00
Merge pull request #4638 from keymanapp/fix/web/4614-event-element-tracking
fix(web): event handling for TouchAliasElement's blinking caret
This commit is contained in:
commit
27066c59da
2 changed files with 66 additions and 16 deletions
|
|
@ -204,6 +204,10 @@ namespace com.keyman.dom {
|
|||
Ltarg = Ltarg['body']; // Occurs in Firefox for design-mode iframes.
|
||||
}
|
||||
|
||||
// Makes sure we properly detect the TouchAliasElement root,
|
||||
// rather than one of its constituent children.
|
||||
Ltarg = findTouchAliasTarget(Ltarg) || Ltarg;
|
||||
|
||||
if(DOMEventHandlers.states._IgnoreBlurFocus) {
|
||||
// Prevent triggering other blur-handling events (as possible)
|
||||
e.cancelBubble = true;
|
||||
|
|
@ -531,9 +535,15 @@ namespace com.keyman.dom {
|
|||
tEvent=(e as TouchEvent).touches[0];
|
||||
} else { // Allow external code to set focus and thus display the OSK on touch devices if required (KMEW-123)
|
||||
tEvent={clientX:0, clientY:0}
|
||||
|
||||
// Will usually be called from setActiveElement, which should define DOMEventHandlers.states.lastActiveElement
|
||||
if(DOMEventHandlers.states.lastActiveElement) {
|
||||
tEvent.target = DOMEventHandlers.states.lastActiveElement['kmw_ip'];
|
||||
tEvent.target = DOMEventHandlers.states.lastActiveElement;
|
||||
// Shouldn't happen, but... just in case. Implemented late in 14.0 beta, so
|
||||
// this detail was kept, though it's likely safe to eliminate.
|
||||
if(tEvent.target['kmw_ip']) {
|
||||
tEvent.target = tEvent.target['kmw_ip'];
|
||||
}
|
||||
// but will default to first input or text area on page if DOMEventHandlers.states.lastActiveElement is null
|
||||
} else {
|
||||
tEvent.target = this.keyman.domManager.sortedInputs[0]['kmw_ip'];
|
||||
|
|
@ -547,28 +557,33 @@ namespace com.keyman.dom {
|
|||
var osk = this.keyman.osk;
|
||||
|
||||
var touchX=tEvent.clientX,touchY=tEvent.clientY;
|
||||
var tTarg=tEvent.target as HTMLElement;
|
||||
var scroller: HTMLElement;
|
||||
|
||||
// Identify the scroller element
|
||||
if(tTarg && dom.Utils.instanceof(tTarg, "HTMLSpanElement")) {
|
||||
scroller=tTarg.parentNode as HTMLElement;
|
||||
} else if(tTarg && (tTarg.className != null && tTarg.className.indexOf('keymanweb-input') >= 0)) {
|
||||
scroller=tTarg.firstChild as HTMLElement;
|
||||
} else {
|
||||
scroller=tTarg;
|
||||
}
|
||||
// Some specifics rely upon which child of the TouchAliasElement received the actual event.
|
||||
let tTarg=tEvent.target as HTMLElement;
|
||||
|
||||
// And the actual target element
|
||||
var target=scroller.parentNode as TouchAliasElement;
|
||||
// Determines the actual TouchAliasElement - the part tied to an OutputTarget.
|
||||
// Ideally, we shouldn't need the second part as a fallback; it's there to preserve existing
|
||||
// behavior from 13.0, as this was refactored made LATE in the 14.0 beta process.
|
||||
let target = findTouchAliasTarget(tTarg) || (tTarg as TouchAliasElement);
|
||||
// Some parts rely upon the scroller element.
|
||||
let scroller = target.firstChild as HTMLElement;
|
||||
|
||||
// Move the caret and refocus if necessary
|
||||
if(DOMEventHandlers.states.activeElement != target) {
|
||||
// Hide the KMW caret
|
||||
let prevTarget = <TouchAliasElement> DOMEventHandlers.states.activeElement;
|
||||
if(prevTarget) {
|
||||
|
||||
// We're not 100% sure whether or not the next line can occur,
|
||||
// but it's a decent failsafe regardless.
|
||||
if(prevTarget && prevTarget['kmw_ip']) {
|
||||
prevTarget = prevTarget['kmw_ip'] as TouchAliasElement;
|
||||
}
|
||||
|
||||
// Make sure that we have the right type so that the expected method exists.
|
||||
if(prevTarget && dom.Utils.instanceof(prevTarget, "TouchAliasElement")) {
|
||||
prevTarget.hideCaret();
|
||||
}
|
||||
|
||||
DOMEventHandlers.states.activeElement=target;
|
||||
// The issue here is that touching a DIV does not actually set the focus for iOS, even when enabled to accept focus (by setting tabIndex=0)
|
||||
// We must explicitly set the focus in order to remove focus from any non-KMW input
|
||||
|
|
@ -587,8 +602,8 @@ namespace com.keyman.dom {
|
|||
osk._Show();
|
||||
}
|
||||
|
||||
// If clicked on DIV, set caret to end of text
|
||||
if(tTarg && dom.Utils.instanceof(tTarg, "TouchAliasElement")) {
|
||||
// If clicked on DIV on the main element or on the scroller element, set caret to end of text
|
||||
if(tTarg && tTarg == target || tTarg == scroller) {
|
||||
var x,cp;
|
||||
x=dom.Utils.getAbsoluteX(scroller.firstChild as HTMLElement);
|
||||
if(target.dir == 'rtl') {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,41 @@ namespace com.keyman.dom {
|
|||
return e;
|
||||
}
|
||||
|
||||
// If the specified HTMLElement is either a TouchAliasElement or one of its children elements,
|
||||
// this method will return the root TouchAliasElement.
|
||||
export function findTouchAliasTarget(target: HTMLElement): TouchAliasElement {
|
||||
let scroller: HTMLElement;
|
||||
|
||||
// Identify the scroller element
|
||||
if(target && dom.Utils.instanceof(target, "HTMLSpanElement")) {
|
||||
scroller=target.parentNode as HTMLElement;
|
||||
} else if(target && (target.className != null && target.className.indexOf('keymanweb-input') >= 0)) {
|
||||
scroller=target.firstChild as HTMLElement;
|
||||
} else if(target && dom.Utils.instanceof(target, "HTMLDivElement")) {
|
||||
// Two possibilities: the scroller & the blinking DIV of the caret.
|
||||
// A direct click CAN trigger events on the blinking element itself if well-timed.
|
||||
scroller=target;
|
||||
|
||||
// Ensures we land on the scroller, not the caret.
|
||||
if(scroller.parentElement && scroller.parentElement.className.indexOf('keymanweb-input') < 0) {
|
||||
scroller = scroller.parentElement;
|
||||
}
|
||||
} else if(target['kmw_ip']) { // In case it's called on a TouchAliasElement's base (aliased) element.
|
||||
return target['kmw_ip'] as TouchAliasElement;
|
||||
} else {
|
||||
// If it's not in any way related to a TouchAliasElement, simply return null.
|
||||
return null;
|
||||
}
|
||||
|
||||
// And the actual target element
|
||||
let root = scroller.parentNode;
|
||||
if(root['base'] !== undefined) {
|
||||
return root as TouchAliasElement;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function constructTouchAlias(base?: HTMLElement): TouchAliasElement {
|
||||
let div = document.createElement("div");
|
||||
let ele = link(div, new TouchAliasData());
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue