From 0d2df34c58f02dd9e52fb76a9757daacdab163f2 Mon Sep 17 00:00:00 2001 From: Simon Huber Date: Mon, 13 Jul 2020 18:42:55 +0200 Subject: [PATCH] Keyboard-driven dropdown inputs (#4725) * Add shortcut descriptions to Misc.multids * Update framed.js * Update simple.js * Add inputActions and refreshTitle to factory.js * Add inputActions and refreshTitle to edit.js * Update DefaultSearchResultList.tid * Update search.tid * Update ShortcutInfo.multids * Update shortcuts.multids * Create keyboard-driven-input.tid * Update tag-picker.tid * Create keyboard-driven-input_Macro.tid * Update EditTextWidget.tid * Update EditWidget.tid * Update engine.js * Update base.tid * Use primaryListFilter, secondaryListFilter, primaryList and secondaryList * Update tag-picker.tid * Update search.tid * Update DefaultSearchResultList.tid * Update keyboard-driven-input_Macro.tid * Fix typo udpate -> update * Update framed.js --- core/language/en-GB/Misc.multids | 5 ++ core/modules/editor/engines/framed.js | 14 +++- core/modules/editor/engines/simple.js | 12 +++- core/modules/editor/factory.js | 6 +- core/modules/widgets/edit.js | 4 +- core/ui/DefaultSearchResultList.tid | 12 +++- core/ui/SideBarSegments/search.tid | 72 ++++++++++++------- core/wiki/config/ShortcutInfo.multids | 5 ++ core/wiki/config/shortcuts/shortcuts.multids | 5 ++ core/wiki/macros/keyboard-driven-input.tid | 51 +++++++++++++ core/wiki/macros/tag-picker.tid | 57 ++++++++++----- .../macros/keyboard-driven-input_Macro.tid | 20 ++++++ .../tiddlers/widgets/EditTextWidget.tid | 2 + .../tw5.com/tiddlers/widgets/EditWidget.tid | 3 + plugins/tiddlywiki/codemirror/engine.js | 12 +++- themes/tiddlywiki/vanilla/base.tid | 13 ++++ 16 files changed, 244 insertions(+), 49 deletions(-) create mode 100644 core/wiki/macros/keyboard-driven-input.tid create mode 100644 editions/tw5.com/tiddlers/macros/keyboard-driven-input_Macro.tid diff --git a/core/language/en-GB/Misc.multids b/core/language/en-GB/Misc.multids index 861bb6899..62d41adfa 100644 --- a/core/language/en-GB/Misc.multids +++ b/core/language/en-GB/Misc.multids @@ -62,6 +62,11 @@ OfficialPluginLibrary: Official ~TiddlyWiki Plugin Library OfficialPluginLibrary/Hint: The official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team. PluginReloadWarning: Please save {{$:/core/ui/Buttons/save-wiki}} and reload {{$:/core/ui/Buttons/refresh}} to allow changes to ~JavaScript plugins to take effect RecentChanges/DateFormat: DDth MMM YYYY +Shortcuts/Input/Accept/Hint: Accept the selected item +Shortcuts/Input/AcceptVariant/Hint: Accept the selected item (variant) +Shortcuts/Input/Cancel/Hint: Clear the input field +Shortcuts/Input/Down/Hint: Select the next item +Shortcuts/Input/Up/Hint: Select the previous item SystemTiddler/Tooltip: This is a system tiddler SystemTiddlers/Include/Prompt: Include system tiddlers TagManager/Colour/Heading: Colour diff --git a/core/modules/editor/engines/framed.js b/core/modules/editor/engines/framed.js index bdb83fe8a..8413d11df 100644 --- a/core/modules/editor/engines/framed.js +++ b/core/modules/editor/engines/framed.js @@ -81,7 +81,7 @@ function FramedEngine(options) { {name: "click",handlerObject: this,handlerMethod: "handleClickEvent"}, {name: "input",handlerObject: this,handlerMethod: "handleInputEvent"}, {name: "keydown",handlerObject: this.widget,handlerMethod: "handleKeydownEvent"}, - {name: "focus",handlerObject: this,handlerMethod: "handleFocusEvent"}, + {name: "focus",handlerObject: this,handlerMethod: "handleFocusEvent"} ]); // Insert the element into the DOM this.iframeDoc.body.appendChild(this.domNode); @@ -108,13 +108,20 @@ Set the text of the engine if it doesn't currently have focus FramedEngine.prototype.setText = function(text,type) { if(!this.domNode.isTiddlyWikiFakeDom) { if(this.domNode.ownerDocument.activeElement !== this.domNode) { - this.domNode.value = text; + this.updateDomNodeText(text); } // Fix the height if needed this.fixHeight(); } }; +/* +Update the DomNode with the new text +*/ +FramedEngine.prototype.updateDomNodeText = function(text) { + this.domNode.value = text; +}; + /* Get the text of the engine */ @@ -177,6 +184,9 @@ Handle a dom "input" event which occurs when the text has changed FramedEngine.prototype.handleInputEvent = function(event) { this.widget.saveChanges(this.getText()); this.fixHeight(); + if(this.widget.editInputActions) { + this.widget.invokeActionString(this.widget.editInputActions); + } return true; }; diff --git a/core/modules/editor/engines/simple.js b/core/modules/editor/engines/simple.js index 39f1163f6..1c50d28b1 100644 --- a/core/modules/editor/engines/simple.js +++ b/core/modules/editor/engines/simple.js @@ -68,13 +68,20 @@ Set the text of the engine if it doesn't currently have focus SimpleEngine.prototype.setText = function(text,type) { if(!this.domNode.isTiddlyWikiFakeDom) { if(this.domNode.ownerDocument.activeElement !== this.domNode || text === "") { - this.domNode.value = text; + this.updateDomNodeText(text); } // Fix the height if needed this.fixHeight(); } }; +/* +Update the DomNode with the new text +*/ +SimpleEngine.prototype.updateDomNodeText = function(text) { + this.domNode.value = text; +}; + /* Get the text of the engine */ @@ -115,6 +122,9 @@ Handle a dom "input" event which occurs when the text has changed SimpleEngine.prototype.handleInputEvent = function(event) { this.widget.saveChanges(this.getText()); this.fixHeight(); + if(this.widget.editInputActions) { + this.widget.invokeActionString(this.widget.editInputActions); + } return true; }; diff --git a/core/modules/editor/factory.js b/core/modules/editor/factory.js index 98fa599bb..e7c4ec3d8 100644 --- a/core/modules/editor/factory.js +++ b/core/modules/editor/factory.js @@ -178,6 +178,8 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) { this.editFocus = this.getAttribute("focus"); this.editTabIndex = this.getAttribute("tabindex"); this.editCancelPopups = this.getAttribute("cancelPopups","") === "yes"; + this.editInputActions = this.getAttribute("inputActions"); + this.editRefreshTitle = this.getAttribute("refreshTitle"); // Get the default editor element tag and type var tag,type; if(this.editField === "text") { @@ -209,9 +211,11 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) { EditTextWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); // Completely rerender if any of our attributes have changed - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE]) { + if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE]) { this.refreshSelf(); return true; + } else if (changedTiddlers[this.editRefreshTitle]) { + this.engine.updateDomNodeText(this.getEditInfo().value); } else if(changedTiddlers[this.editTitle]) { var editInfo = this.getEditInfo(); this.updateEditor(editInfo.value,editInfo.type); diff --git a/core/modules/widgets/edit.js b/core/modules/widgets/edit.js index 472fc534b..6ee918170 100644 --- a/core/modules/widgets/edit.js +++ b/core/modules/widgets/edit.js @@ -49,6 +49,8 @@ EditWidget.prototype.execute = function() { this.editTabIndex = this.getAttribute("tabindex"); this.editFocus = this.getAttribute("focus",""); this.editCancelPopups = this.getAttribute("cancelPopups",""); + this.editInputActions = this.getAttribute("inputActions"); + this.editRefreshTitle = this.getAttribute("refreshTitle"); // Choose the appropriate edit widget this.editorType = this.getEditorType(); // Make the child widgets @@ -87,7 +89,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of EditWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); // Refresh if an attribute has changed, or the type associated with the target tiddler has changed - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.cancelPopups || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) { + if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) { this.refreshSelf(); return true; } else { diff --git a/core/ui/DefaultSearchResultList.tid b/core/ui/DefaultSearchResultList.tid index 331ef8718..1e0b1e403 100644 --- a/core/ui/DefaultSearchResultList.tid +++ b/core/ui/DefaultSearchResultList.tid @@ -5,11 +5,19 @@ caption: {{$:/language/Search/DefaultResults/Caption}} \define searchResultList() //{{$:/language/Search/Matches/Title}}// -<$list filter="[!is[system]search:title{$(searchTiddler)$}sort[title]limit[250]]" template="$:/core/ui/ListItemTemplate"/> +<$list filter="[!is[system]search:title{$(searchTiddler)$}sort[title]limit[250]]"> +addsuffix[-primaryList]] -[get[text]] +[then[]else[tc-list-item-selected]] }}}> +<$transclude tiddler="$:/core/ui/ListItemTemplate"/> + + //{{$:/language/Search/Matches/All}}// -<$list filter="[!is[system]search{$(searchTiddler)$}sort[title]limit[250]]" template="$:/core/ui/ListItemTemplate"/> +<$list filter="[!is[system]search{$(searchTiddler)$}sort[title]limit[250]]"> +addsuffix[-secondaryList]] -[get[text]] +[then[]else[tc-list-item-selected]] }}}> +<$transclude tiddler="$:/core/ui/ListItemTemplate"/> + + \end <> diff --git a/core/ui/SideBarSegments/search.tid b/core/ui/SideBarSegments/search.tid index 9121d5ace..08cbd45f7 100644 --- a/core/ui/SideBarSegments/search.tid +++ b/core/ui/SideBarSegments/search.tid @@ -2,25 +2,12 @@ title: $:/core/ui/SideBarSegments/search tags: $:/tags/SideBarSegment \whitespace trim -