Add support for assigning action widgets via the `actions` attribute

This is quite a big change: a new way to invoke action widgets.

The advantage is that it solves #2217 and #1564, a long running problem
that prevented us from adding action widgets to widgets that modify the
store.

This commit adds the new technique for the button and keyboard widgets,
but also extends the select widget to trigger action widgets for the
first time
This commit is contained in:
Jermolene 2016-04-29 18:53:23 +01:00
parent b53f4e9b20
commit 3c20f2396e
8 changed files with 69 additions and 11 deletions

View File

@ -86,6 +86,9 @@ ButtonWidget.prototype.render = function(parent,nextSibling) {
self.setTiddler();
handled = true;
}
if(self.actions) {
self.invokeActionString(self.actions,self,event);
}
if(handled) {
event.preventDefault();
event.stopPropagation();
@ -153,6 +156,7 @@ Compute the internal state of the widget
*/
ButtonWidget.prototype.execute = function() {
// Get attributes
this.actions = this.getAttribute("actions");
this.to = this.getAttribute("to");
this.message = this.getAttribute("message");
this.param = this.getAttribute("param");

View File

@ -42,7 +42,10 @@ KeyboardWidget.prototype.render = function(parent,nextSibling) {
// Add a keyboard event handler
domNode.addEventListener("keydown",function (event) {
if($tw.keyboardManager.checkKeyDescriptors(event,self.keyInfoArray)) {
self.invokeActions(this,event);
self.invokeActions(self,event);
if(self.actions) {
self.invokeActionString(self.actions,self,event);
}
self.dispatchMessage(event);
event.preventDefault();
event.stopPropagation();
@ -65,6 +68,7 @@ Compute the internal state of the widget
*/
KeyboardWidget.prototype.execute = function() {
// Get attributes
this.actions = this.getAttribute("actions");
this.message = this.getAttribute("message");
this.param = this.getAttribute("param");
this.key = this.getAttribute("key");

View File

@ -51,6 +51,7 @@ SelectWidget.prototype.render = function(parent,nextSibling) {
Handle a change event
*/
SelectWidget.prototype.handleChangeEvent = function(event) {
// Get the new value and assign it to the tiddler
if(this.selectMultiple == false) {
var value = this.getSelectDomNode().value;
} else {
@ -58,6 +59,10 @@ SelectWidget.prototype.handleChangeEvent = function(event) {
value = $tw.utils.stringifyList(value);
}
this.wiki.setText(this.selectTitle,this.selectField,this.selectIndex,value);
// Trigger actions
if(this.selectActions) {
this.invokeActionString(this.selectActions,this,event);
}
};
/*
@ -132,6 +137,7 @@ Compute the internal state of the widget
*/
SelectWidget.prototype.execute = function() {
// Get our parameters
this.selectActions = this.getAttribute("actions");
this.selectTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler"));
this.selectField = this.getAttribute("field","text");
this.selectIndex = this.getAttribute("index");

View File

@ -504,6 +504,23 @@ Widget.prototype.invokeActions = function(triggeringWidget,event) {
return handled;
};
/*
Invoke the action widgets defined in a string
*/
Widget.prototype.invokeActionString = function(actions,triggeringWidget,event) {
actions = actions || "";
var parser = this.wiki.parseText("text/vnd.tiddlywiki",actions,{
parentWidget: this,
document: this.document
}),
widgetNode = this.wiki.makeWidget(parser,{
parentWidget: this,
document: this.document
});
var container = this.document.createElement("div");
widgetNode.render(container,null);
return widgetNode.invokeActions(this,event);
};
Widget.prototype.allowActionPropagation = function() {
return true;

View File

@ -1,12 +1,38 @@
created: 20141008134425548
modified: 20150128163157192
modified: 20160429165240169
tags: Widgets
title: ActionWidgets
type: text/vnd.tiddlywiki
Action widgets are a special type of widget that perform an action such as sending a message, navigating to a tiddler, or changing the value of a tiddler. They are used in association with other widgets that trigger those actions (for example, the ButtonWidget).
Action widgets are a special type of widget that have no visual appearance but perform an action when triggered (such as sending a message, navigating to a tiddler, or changing the value of a tiddler). Action widgets are used in association with other widgets that trigger those actions (for example, the ButtonWidget).
Action widgets are invisible. They need not be immediate children of their triggering widget, but they must be descendents of it. The actions are performed in sequence. For example, here is a button that triggers two actions of sending different messages:
The following action widgets are provided:
<<list-links "[tag[ActionWidgets]]">>
There are two ways to use action widgets:
* Using the `actions` attribute of the triggering widget (this is the preferred way)
* Embedding the actions within the triggering widget (an older technique that is now deprecated)
!! Assigning action widgets with the `actions` attribute
The action widgets are passed as a string to the `actions` attribute of the triggering widget. Usually, it is more convenient to use a macro to assign the action widgets to a variable. For example, here is a button that triggers two actions of sending different messages:
```
\define my-actions()
<$action-sendmessage $message="tm-home"/>
<$action-sendmessage $message="tm-full-screen"/>
\end
<$button actions=<<my-actions>>>
Click me!
</$button>
```
!! Assigning action widgets by embedding
The action widgets need not be immediate children of their triggering widget, but they must be descendents of it. The actions are performed in sequence. Here is the above example rewritten to use embedding:
```
<$button>
@ -16,6 +42,3 @@ Click me!
</$button>
```
The following action widgets are provided:
<<list-links "[tag[ActionWidgets]]">>

View File

@ -1,6 +1,6 @@
caption: button
created: 20131024141900000
modified: 20150619111219516
modified: 20160429175044822
tags: Widgets
title: ButtonWidget
type: text/vnd.tiddlywiki
@ -9,6 +9,7 @@ type: text/vnd.tiddlywiki
The button widget displays an HTML `<button>` element that can perform a combination of optional actions when clicked:
* Executing any ActionWidgets passed in the `actions` attribute
* Executing any ActionWidgets that are immediate children of the button widget
* Execute any integrated actions:
** Navigate to a specified tiddler
@ -23,6 +24,7 @@ The integrated actions are provided as a shortcut for invoking common actions. T
The content of the `<$button>` widget is displayed within the button.
|!Attribute |!Description |
|actions |A string containing ActionWidgets to be triggered when the key combination is detected |
|to |The title of the tiddler to navigate to |
|message |The name of the [[widget message|Messages]] to send when the button is clicked |
|param |The optional parameter to the message |

View File

@ -1,6 +1,6 @@
caption: keyboard
created: 20140302192136805
modified: 20160418151713895
modified: 20160429175258940
tags: Widgets
title: KeyboardWidget
type: text/vnd.tiddlywiki
@ -14,6 +14,7 @@ The keyboard widget allows ActionWidgets to be triggered by specific key combina
The content of the `<$keyboard>` widget is rendered normally. The keyboard shortcuts only take effect when the focus is within the contained content.
|!Attribute |!Description |
|actions |A string containing ActionWidgets to be triggered when the key combination is detected |
|message |The title of the [[WidgetMessage|Messages]] to generate |
|param |The parameter to be passed with the [[WidgetMessage|Messages]] |
|key |Key string identifying the key(s) to be trapped (see below) |

View File

@ -1,6 +1,6 @@
caption: select
created: 20131024141900000
modified: 20141203155137508
modified: 20160429175220241
tags: Widgets
title: SelectWidget
type: text/vnd.tiddlywiki
@ -8,7 +8,7 @@ type: text/vnd.tiddlywiki
! Introduction
The select widget displays a popup menu based on a [[HTML select element|https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select]]. The popup (or dropdown) contains a list of items defined by `<option>` and `<optgroup>` elements.
Every time the user selects a new value in the menu, the selected value is written to the text of a specified tiddler field or index. If the tiddler value changes the menu is automatically updated to reflect the new value.
Every time the user selects a new value in the menu, the selected value is written to the text of a specified tiddler field or index and any ActionWidgets within the `actions` attribute are triggered. Conversely, if the tiddler value is changed independently the select widget is automatically updated to reflect the new value.
In multiple selection mode, the list of selected values is bound to the specified tiddler field or index. Browsers generally use the <kbd>ctrl</kbd> or <kbd>cmd</kbd> keys for multiple selection.
@ -38,6 +38,7 @@ The content of the `<$select>` widget should be one or more HTML `<option>` or `
|default |Default value to be used if the tiddler, field or index specifies a missing value |
|multiple |If present, switches to multiple selection mode |
|size |The number of rows to display in multiple selection mode |
|actions |A string containing ActionWidgets to be triggered when the key combination is detected |
! Examples