Set multiple fields/variables/params using filters (#6130)

* Add action-setmultiplefields and setmultiplevariables, and extend action-sendmessage

* Add getfield operator

* Remove getfield operator

See discussion at https://github.com/Jermolene/TiddlyWiki5/pull/6130#issuecomment-949911439

* Add docs

* Adjust whitespace

* Add support for assigning multiple indexes to action-setmultiplefields
This commit is contained in:
Jeremy Ruston 2021-10-27 11:20:11 +01:00 committed by GitHub
parent 5f57bf81cd
commit d5f72cb282
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 252 additions and 9 deletions

View File

@ -39,6 +39,8 @@ SendMessageWidget.prototype.execute = function() {
this.actionParam = this.getAttribute("$param");
this.actionName = this.getAttribute("$name");
this.actionValue = this.getAttribute("$value","");
this.actionNames = this.getAttribute("$names");
this.actionValues = this.getAttribute("$values");
};
/*
@ -59,13 +61,20 @@ Invoke the action associated with this widget
SendMessageWidget.prototype.invokeAction = function(triggeringWidget,event) {
// Get the string parameter
var param = this.actionParam;
// Assemble the attributes as a hashmap
// Assemble the parameters as a hashmap
var paramObject = Object.create(null);
var count = 0;
// Add names/values pairs if present
if(this.actionNames && this.actionValues) {
var names = this.wiki.filterTiddlers(this.actionNames,this),
values = this.wiki.filterTiddlers(this.actionValues,this);
$tw.utils.each(names,function(name,index) {
paramObject[name] = values[index] || "";
});
}
// Add raw parameters
$tw.utils.each(this.attributes,function(attribute,name) {
if(name.charAt(0) !== "$") {
paramObject[name] = attribute;
count++;
}
});
// Add name/value pair if present
@ -73,14 +82,15 @@ SendMessageWidget.prototype.invokeAction = function(triggeringWidget,event) {
paramObject[this.actionName] = this.actionValue;
}
// Dispatch the message
this.dispatchEvent({
var params = {
type: this.actionMessage,
param: param,
paramObject: paramObject,
tiddlerTitle: this.getVariable("currentTiddler"),
navigateFromTitle: this.getVariable("storyTiddler"),
event: event
});
event: event,
currentTiddler: this.getVariable("currentTiddler"),
navigateFromTitle: this.getVariable("storyTiddler")
};
this.dispatchEvent(params);
return true; // Action was invoked
};

View File

@ -0,0 +1,86 @@
/*\
title: $:/core/modules/widgets/action-setmultiplefields.js
type: application/javascript
module-type: widget
Action widget to set multiple fields or indexes on a tiddler
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var SetMultipleFieldsWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
SetMultipleFieldsWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
SetMultipleFieldsWidget.prototype.render = function(parent,nextSibling) {
this.computeAttributes();
this.execute();
};
/*
Compute the internal state of the widget
*/
SetMultipleFieldsWidget.prototype.execute = function() {
this.actionTiddler = this.getAttribute("$tiddler",this.getVariable("currentTiddler"));
this.actionFields = this.getAttribute("$fields");
this.actionIndexes = this.getAttribute("$indexes");
this.actionValues = this.getAttribute("$values");
this.actionTimestamp = this.getAttribute("$timestamp","yes") === "yes";
};
/*
Refresh the widget by ensuring our attributes are up to date
*/
SetMultipleFieldsWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes();
if(changedAttributes["$tiddler"] || changedAttributes["$fields"] || changedAttributes["$indexes"] || changedAttributes["$values"] || changedAttributes["$timestamp"]) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
/*
Invoke the action associated with this widget
*/
SetMultipleFieldsWidget.prototype.invokeAction = function(triggeringWidget,event) {
var tiddler = this.wiki.getTiddler(this.actionTiddler),
names, values = this.wiki.filterTiddlers(this.actionValues,this);
if(this.actionFields) {
var additions = {};
names = this.wiki.filterTiddlers(this.actionFields,this);
$tw.utils.each(names,function(fieldname,index) {
additions[fieldname] = values[index] || "";
});
var creationFields = this.actionTimestamp ? this.wiki.getCreationFields() : undefined,
modificationFields = this.actionTimestamp ? this.wiki.getModificationFields() : undefined;
this.wiki.addTiddler(new $tw.Tiddler(creationFields,tiddler,{title: this.actionTiddler},modificationFields,additions));
} else if(this.actionIndexes) {
var data = this.wiki.getTiddlerData(this.actionTiddler,Object.create(null));
names = this.wiki.filterTiddlers(this.actionIndexes,this);
$tw.utils.each(names,function(name,index) {
data[name] = values[index] || "";
});
this.wiki.setTiddlerData(this.actionTiddler,data,{},{suppressTimestamp: !this.actionTimestamp});
}
return true; // Action was invoked
};
exports["action-setmultiplefields"] = SetMultipleFieldsWidget;
})();

View File

@ -0,0 +1,81 @@
/*\
title: $:/core/modules/widgets/setmultiplevariables.js
type: application/javascript
module-type: widget
Widget to set multiple variables at once from a list of names and a list of values
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
var Widget = require("$:/core/modules/widgets/widget.js").widget;
var SetMultipleVariablesWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options);
};
/*
Inherit from the base widget class
*/
SetMultipleVariablesWidget.prototype = new Widget();
/*
Render this widget into the DOM
*/
SetMultipleVariablesWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
this.computeAttributes();
this.execute();
this.renderChildren(parent,nextSibling);
};
/*
Compute the internal state of the widget
*/
SetMultipleVariablesWidget.prototype.execute = function() {
// Setup our variables
this.setVariables();
// Construct the child widgets
this.makeChildWidgets();
};
SetMultipleVariablesWidget.prototype.setVariables = function() {
// Set the variables
var self = this,
filterNames = this.getAttribute("$names",""),
filterValues = this.getAttribute("$values","");
this.variableNames = [];
this.variableValues = [];
if(filterNames && filterValues) {
this.variableNames = this.wiki.filterTiddlers(filterNames,this);
this.variableValues = this.wiki.filterTiddlers(filterValues,this);
$tw.utils.each(this.variableNames,function(varname,index) {
self.setVariable(varname,self.variableValues[index]);
});
}
};
/*
Refresh the widget by ensuring our attributes are up to date
*/
SetMultipleVariablesWidget.prototype.refresh = function(changedTiddlers) {
var filterNames = this.getAttribute("$names",""),
filterValues = this.getAttribute("$values",""),
variableNames = this.wiki.filterTiddlers(filterNames,this),
variableValues = this.wiki.filterTiddlers(filterValues,this);
if(!$tw.utils.isArrayEqual(this.variableNames,variableNames) || !$tw.utils.isArrayEqual(this.variableValues,variableValues)) {
this.refreshSelf();
return true;
}
return this.refreshChildren(changedTiddlers);
};
exports["setmultiplevariables"] = SetMultipleVariablesWidget;
})();

View File

@ -1,6 +1,6 @@
caption: action-sendmessage
created: 20141008134309742
modified: 20150518210909583
modified: 20211023160110220
tags: Widgets ActionWidgets
title: ActionSendMessageWidget
type: text/vnd.tiddlywiki
@ -18,6 +18,8 @@ The ''action-sendmessage'' widget is invisible. Any content within it is ignored
|$param |Optional parameter string whose meaning is dependent on the message being sent |
|$name |Optional name of additional parameter |
|$value |Value for optional parameter whose name is specified in `$name` |
|$names |<<.from-version "5.2.1">> Optional filter evaluating to a list of additional parameter names |
|$values |<<.from-version "5.2.1">> Optional filter evaluating to a list of parameter values corresponding to the parameters names specified in `$names` |
|//{any attributes not starting with $}// |Multiple additional, optional named parameters that are attached to the message |
! Examples

View File

@ -0,0 +1,31 @@
caption: action-setmultiplefields
created: 20211023160110220
modified: 20211023160110220
tags: Widgets ActionWidgets
title: ActionSetMultipleFieldsWidget
type: text/vnd.tiddlywiki
! Introduction
The ''action-setmultiplefields'' widget is an [[action widget|ActionWidgets]] that assigns multiple fields to a tiddler where the names and values of the fields are specified as separate filters. ActionWidgets are used within triggering widgets such as the ButtonWidget.
! Content and Attributes
The ''action-setmultiplefields'' widget is invisible. Any content within it is ignored.
|!Attribute |!Description |
|$tiddler |Optional title of the tiddler to modify (defaults to the current tiddler) |
|$fields |Optional filter evaluating to the names of a list of fields to assign. Either `$fields` or `$indexes` must be specified |
|$indexes |Optional filter evaluating to the names of a list of indexes to assign. Either `$fields` or `$indexes` must be specified |
|$values |Filter evaluating to the values to be assigned to the fields or indexes |
|$timestamp |Specifies whether the timestamp(s) of the target tiddler will be updated (''modified'' and ''modifier'', plus ''created'' and ''creator'' for newly created tiddlers). Can be "yes" (the default) or "no" |
! Examples
Here is an example of button that uses the data in [[Days of the Week]] to assign fields `day-Monday`, `day-Tuesday` etc. to the tiddler "HelloThere":
<$macrocall $name='wikitext-example-without-html'
src='<$button>
<$action-setmultiplefields $tiddler="HelloThere" $fields="[list[Days of the Week]addprefix[day-]]" $values="[list[Days of the Week]]">>/>
Click me!
</$button>'/>

View File

@ -0,0 +1,33 @@
caption: setmultiplevariables
created: 20211023162409163
modified: 20211023162409163
tags: Widgets
title: SetMultipleVariablesWidget
type: text/vnd.tiddlywiki
! Introduction
The setmultiplevariables widget assigns values to multiple [[variables|Variables]] where the names and values of the variables are specified as separate filter.
! Content and Attributes
The content of the `<$setmultiplevariables>` widget is the scope for the value assigned to the variable.
|!Attribute |!Description |
|$names |Filter evaluating to the names of a list of variables to assign |
|$values |Filter evaluating to the values corresponding to the list of names specified in `$names` |
! Examples
Here is an example of a convoluted way to display the values of the fields of the tiddler "HelloThere":
<$macrocall $name='wikitext-example-without-html'
src="""<$setmultiplevariables $names="[[HelloThere]fields[]addprefix[demo-]]" $values="[[HelloThere]fields[]] :map[[HelloThere]get<currentTiddler>]">
<ol>
<$list filter="[variables[]prefix[demo-]sort[]]">
<li>
''<$text text={{{ [<currentTiddler>removeprefix[demo-]] }}}/>'': <$text text={{{ [<currentTiddler>getvariable[]] }}}/>
</li>
</$list>
</ol>
</$setmultiplevariables>"""/>