mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-06-27 07:32:58 +00:00
Introduce genesis widget for dynamically creating widgets
See the "RedefineLet" test for a contrived example of usage
This commit is contained in:
parent
e1df50d981
commit
56c2242e4e
100
core/modules/widgets/genesis.js
Normal file
100
core/modules/widgets/genesis.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*\
|
||||||
|
title: $:/core/modules/widgets/genesis.js
|
||||||
|
type: application/javascript
|
||||||
|
module-type: widget
|
||||||
|
|
||||||
|
Genesis widget for dynamically creating widgets
|
||||||
|
|
||||||
|
\*/
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
/*jslint node: true, browser: true */
|
||||||
|
/*global $tw: false */
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
||||||
|
|
||||||
|
var GenesisWidget = function(parseTreeNode,options) {
|
||||||
|
this.initialise(parseTreeNode,options);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inherit from the base widget class
|
||||||
|
*/
|
||||||
|
GenesisWidget.prototype = new Widget();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Render this widget into the DOM
|
||||||
|
*/
|
||||||
|
GenesisWidget.prototype.render = function(parent,nextSibling) {
|
||||||
|
this.parentDomNode = parent;
|
||||||
|
this.computeAttributes();
|
||||||
|
this.execute();
|
||||||
|
this.renderChildren(parent,nextSibling);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Compute the internal state of the widget
|
||||||
|
*/
|
||||||
|
GenesisWidget.prototype.execute = function() {
|
||||||
|
var self = this;
|
||||||
|
// Collect attributes
|
||||||
|
this.genesisType = this.getAttribute("$type","element");
|
||||||
|
this.genesisTag = this.getAttribute("$tag","div");
|
||||||
|
this.genesisNames = this.getAttribute("$names","");
|
||||||
|
this.genesisValues = this.getAttribute("$values","");
|
||||||
|
// Construct parse tree
|
||||||
|
var parseTreeNodes = [{
|
||||||
|
type: this.genesisType,
|
||||||
|
tag: this.genesisTag,
|
||||||
|
attributes: {},
|
||||||
|
orderedAttributes: [],
|
||||||
|
children: this.parseTreeNode.children || []
|
||||||
|
}];
|
||||||
|
// Apply attributes in $names/$values
|
||||||
|
this.attributeNames = [];
|
||||||
|
this.attributeValues = [];
|
||||||
|
if(this.genesisNames && this.genesisValues) {
|
||||||
|
this.attributeNames = this.wiki.filterTiddlers(self.genesisNames,this);
|
||||||
|
this.attributeValues = this.wiki.filterTiddlers(self.genesisValues,this);
|
||||||
|
$tw.utils.each(this.attributeNames,function(varname,index) {
|
||||||
|
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],varname,self.attributeValues[index] || "");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Apply explicit attributes
|
||||||
|
$tw.utils.each(this.attributes,function(value,name) {
|
||||||
|
if(name.charAt(0) === "$") {
|
||||||
|
if(name.charAt(1) === "$") {
|
||||||
|
// Double $$ is changed to a single $
|
||||||
|
name = name.substr(1);
|
||||||
|
} else {
|
||||||
|
// Single dollar is ignored
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tw.utils.addAttributeToParseTreeNode(parseTreeNodes[0],name,value);
|
||||||
|
});
|
||||||
|
// Construct the child widgets
|
||||||
|
this.makeChildWidgets(parseTreeNodes);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
||||||
|
*/
|
||||||
|
GenesisWidget.prototype.refresh = function(changedTiddlers) {
|
||||||
|
var changedAttributes = this.computeAttributes(),
|
||||||
|
filterNames = this.getAttribute("$names",""),
|
||||||
|
filterValues = this.getAttribute("$values",""),
|
||||||
|
attributeNames = this.wiki.filterTiddlers(filterNames,this),
|
||||||
|
attributeValues = this.wiki.filterTiddlers(filterValues,this);
|
||||||
|
if($tw.utils.count(changedAttributes) > 0 || !$tw.utils.isArrayEqual(this.attributeNames,attributeNames) || !$tw.utils.isArrayEqual(this.attributeValues,attributeValues)) {
|
||||||
|
this.refreshSelf();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return this.refreshChildren(changedTiddlers);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.genesis = GenesisWidget;
|
||||||
|
|
||||||
|
})();
|
@ -0,0 +1,14 @@
|
|||||||
|
title: Genesis/DollarSigns
|
||||||
|
description: Usage of genesis widget with attributes starting with dollar signs
|
||||||
|
type: text/vnd.tiddlywiki-multiple
|
||||||
|
tags: [[$:/tags/wiki-test-spec]]
|
||||||
|
|
||||||
|
title: Output
|
||||||
|
|
||||||
|
\whitespace trim
|
||||||
|
<$genesis $type="let" myvar="Kitten">(<$text text=<<myvar>>/>)</$genesis>
|
||||||
|
<$genesis $type="let" $$myvar="Kitten">(<$text text=<<$myvar>>/>)</$genesis>
|
||||||
|
_
|
||||||
|
title: ExpectedResult
|
||||||
|
|
||||||
|
<p>(Kitten)(Kitten)</p>
|
@ -0,0 +1,14 @@
|
|||||||
|
title: Genesis/MultipleAttributes
|
||||||
|
description: Usage of genesis widget with multiple attributes
|
||||||
|
type: text/vnd.tiddlywiki-multiple
|
||||||
|
tags: [[$:/tags/wiki-test-spec]]
|
||||||
|
|
||||||
|
title: Output
|
||||||
|
|
||||||
|
\whitespace trim
|
||||||
|
<$genesis $type="let" $names="myvar other" $values="Kitten Donkey" myvar="Shark">(<$text text=<<myvar>>/>|<$text text=<<other>>/>)</$genesis>
|
||||||
|
<$genesis $type="let" $names="$myvar $other" $values="Kitten Donkey" $$myvar="Shark">(<$text text=<<$myvar>>/>|<$text text=<<$other>>/>)</$genesis>
|
||||||
|
_
|
||||||
|
title: ExpectedResult
|
||||||
|
|
||||||
|
<p>(Shark|Donkey)(Shark|Donkey)</p>
|
@ -0,0 +1,33 @@
|
|||||||
|
title: Genesis/RedefineLet
|
||||||
|
description: Using the genesis widget to override the let widget
|
||||||
|
type: text/vnd.tiddlywiki-multiple
|
||||||
|
tags: [[$:/tags/wiki-test-spec]]
|
||||||
|
|
||||||
|
title: Output
|
||||||
|
|
||||||
|
\whitespace trim
|
||||||
|
\function <$let>
|
||||||
|
\whitespace trim
|
||||||
|
<$setmultiplevariables $names="[enlist<paramNames>]" $values="[enlist<paramValues>addprefix[--]addsuffix[--]]">
|
||||||
|
<$slot $name="ts-body"/>
|
||||||
|
</$setmultiplevariables>
|
||||||
|
\end
|
||||||
|
<$let
|
||||||
|
one="Elephant"
|
||||||
|
$two="Kangaroo"
|
||||||
|
$$three="Giraffe"
|
||||||
|
>
|
||||||
|
(<$text text=<<one>>/>)
|
||||||
|
(<$text text=<<$two>>/>)
|
||||||
|
(<$text text=<<$$three>>/>)
|
||||||
|
</$let>
|
||||||
|
_
|
||||||
|
title: Definition
|
||||||
|
|
||||||
|
\whitespace trim
|
||||||
|
_
|
||||||
|
title: ExpectedResult
|
||||||
|
|
||||||
|
<p>(--Elephant--)
|
||||||
|
(--Kangaroo--)
|
||||||
|
(--Giraffe--)</p>
|
14
editions/test/tiddlers/tests/data/genesis-widget/Simple.tid
Normal file
14
editions/test/tiddlers/tests/data/genesis-widget/Simple.tid
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
title: Genesis/Simple
|
||||||
|
description: Simple usage of genesis widget
|
||||||
|
type: text/vnd.tiddlywiki-multiple
|
||||||
|
tags: [[$:/tags/wiki-test-spec]]
|
||||||
|
|
||||||
|
title: Output
|
||||||
|
|
||||||
|
\whitespace trim
|
||||||
|
<$genesis $tag="div">Mouse</$genesis>
|
||||||
|
<$genesis $tag="div" class="tc-thing" label="Squeak">Mouse</$genesis>
|
||||||
|
_
|
||||||
|
title: ExpectedResult
|
||||||
|
|
||||||
|
<p><div>Mouse</div><div class="tc-thing" label="Squeak">Mouse</div></p>
|
34
editions/tw5.com/tiddlers/widgets/GenesisWidget.tid
Normal file
34
editions/tw5.com/tiddlers/widgets/GenesisWidget.tid
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
caption: genesis
|
||||||
|
created: 20220502144738010
|
||||||
|
modified: 20220502144738010
|
||||||
|
tags: Widgets
|
||||||
|
title: GenesisWidget
|
||||||
|
type: text/vnd.tiddlywiki
|
||||||
|
|
||||||
|
! Introduction
|
||||||
|
|
||||||
|
<<.from-version "5.2.3">> The genesis widget allows the dynamic construction of widgets, where the name and attributes of the widget can be dynamically determined, and do not need to be known in advance.
|
||||||
|
|
||||||
|
! Content and Attributes
|
||||||
|
|
||||||
|
The content of the `<$genesis>` widget is used as the content of the dynamically created widget.
|
||||||
|
|
||||||
|
|!Attribute |!Description |
|
||||||
|
|$type |The type of widget to create |
|
||||||
|
|$tag |The HTML tag to be used for "element" widgets |
|
||||||
|
|$names |An optional filter evaluating to the names of a list of variables to be applied to the widget |
|
||||||
|
|$values |An optional filter evaluating to the values corresponding to the list of names specified in `$names` |
|
||||||
|
|//{other attributes starting with $}// |Other attributes starting with a single dollar sign are reserved for future use |
|
||||||
|
|//{attributes starting with $$}// |Attributes starting with two dollar signs are appplied as attributes to the output widget, but with the attribute name changed to use a single dollar sign |
|
||||||
|
|//{attributes not starting with $}// |Any other attributes that do not start with a dollar are applied as attributes to the output widget |
|
||||||
|
|
||||||
|
Note that attributes explicitly specified take precedence over attributes with the same name specified in the `$names` filter.
|
||||||
|
|
||||||
|
! Examples
|
||||||
|
|
||||||
|
<$macrocall $name='wikitext-example-without-html'
|
||||||
|
src='<$set name="myTiddler" value="HelloThere">
|
||||||
|
<$set name="myVariable" tiddler=<<myTiddler>> field={{$:/docs/anyField!!field}}>
|
||||||
|
<$text text=<<myVariable>>/>
|
||||||
|
</$set>
|
||||||
|
</$set>'/>
|
Loading…
x
Reference in New Issue
Block a user