mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-07 01:15:33 +00:00
Relates to #5853 and others. Selection management was not working properly with the various OutputTargets: 1. When there is a non-empty selection, rules have no context -- it's like new text. 2. Backspace over a selection deletes just the selection. 3. Typing a character replaces the selection, of course, and collapses the caret to the end of the new text. 4. `hasSelection` is a very strange name for `OutputTarget` descendants. It doesn't mean "has an active selection" but rather, kinda means "supports selection internally". 5. Added `isSelectionEmpty` which is used for some of the new selection rules above. Note that the `touchAlias` OutputTarget class does not currently support selection. I hope we can deprecate `touchAlias` with the use of `inputMode` (#3030) in the future, rather than adding support for selection.
93 lines
No EOL
2.6 KiB
TypeScript
93 lines
No EOL
2.6 KiB
TypeScript
// Defines the TouchAliasElement merged type.
|
|
/// <reference path="../touchAliasElement.ts" />
|
|
|
|
namespace com.keyman.dom.targets {
|
|
export class TouchAlias extends OutputTarget {
|
|
root: TouchAliasElement;
|
|
|
|
constructor(e: TouchAliasElement) {
|
|
super();
|
|
this.root = e;
|
|
}
|
|
|
|
getElement(): HTMLDivElement {
|
|
return this.root;
|
|
}
|
|
|
|
clearSelection(): void {
|
|
// Touch-alias elements do not currently support selections.
|
|
return;
|
|
}
|
|
|
|
invalidateSelection(): void {
|
|
// Touch-alias elements do not currently support selections.
|
|
return;
|
|
}
|
|
|
|
isSelectionEmpty(): boolean {
|
|
// Touch-alias elements do not currently support selections.
|
|
return true;
|
|
}
|
|
|
|
hasSelection(): boolean {
|
|
// Always has an internal caret position.
|
|
return true;
|
|
}
|
|
|
|
getDeadkeyCaret(): number {
|
|
return this.root.getTextCaret();
|
|
}
|
|
|
|
getTextBeforeCaret(): string {
|
|
return this.root.getTextBeforeCaret();
|
|
}
|
|
|
|
getTextAfterCaret(): string {
|
|
return this.root.getTextAfterCaret();
|
|
}
|
|
|
|
getText(): string {
|
|
return this.root.getText();
|
|
}
|
|
|
|
deleteCharsBeforeCaret(dn: number): void {
|
|
if(dn > 0) {
|
|
let curText = this.getTextBeforeCaret();
|
|
if(this.getDeadkeyCaret() < dn) {
|
|
dn = this.getDeadkeyCaret();
|
|
}
|
|
this.adjustDeadkeys(-dn);
|
|
this.root.setTextBeforeCaret(curText.kmwSubstring(0, this.root.getTextCaret() - dn));
|
|
}
|
|
}
|
|
|
|
insertTextBeforeCaret(s: string): void {
|
|
this.adjustDeadkeys(s._kmwLength());
|
|
this.root.setTextBeforeCaret(this.root.getTextBeforeCaret() + s);
|
|
}
|
|
|
|
handleNewlineAtCaret(): void {
|
|
// Insert new line in text area fields
|
|
if(this.root.base.nodeName == 'TEXTAREA') {
|
|
// As the TouchAliasElement was implemented long before OutputTargets, it already has
|
|
// built-in newline handling.
|
|
this.insertTextBeforeCaret('\n');
|
|
} else if(dom.Utils.instanceof(this.root.base, "HTMLInputElement")) {
|
|
// HTMLInputElements do not permit newlines; they instead have DOM-specific behaviors.
|
|
this.root.hideCaret();
|
|
Input.newlineHandler(this.root.base as HTMLInputElement);
|
|
} else {
|
|
console.warn("TouchAlias OutputTarget cannot output newlines for unexpected base element types!");
|
|
}
|
|
}
|
|
|
|
protected setTextAfterCaret(s: string) {
|
|
this.root.setText(this.getTextBeforeCaret() + s, this.getTextBeforeCaret()._kmwLength());
|
|
}
|
|
|
|
doInputEvent() {
|
|
// Dispatch the event on the aliased element, not the TouchAliasElement itself.
|
|
this.dispatchInputEventOn(this.root.base);
|
|
}
|
|
}
|
|
} |