1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2026-01-26 12:53:42 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
jeremy@jermolene.com
995ab34ee0 First commit 2022-10-01 10:04:42 +01:00
340 changed files with 865 additions and 5077 deletions

2
.gitignore vendored
View File

@@ -1,7 +1,5 @@
.DS_Store .DS_Store
.c9/ .c9/
.vscode/
tmp/ tmp/
output/ output/
node_modules/ node_modules/

View File

@@ -5,7 +5,7 @@
# Default to the current version number for building the plugin library # Default to the current version number for building the plugin library
if [ -z "$TW5_BUILD_VERSION" ]; then if [ -z "$TW5_BUILD_VERSION" ]; then
TW5_BUILD_VERSION=v5.2.4 TW5_BUILD_VERSION=v5.2.3
fi fi
echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]" echo "Using TW5_BUILD_VERSION as [$TW5_BUILD_VERSION]"
@@ -233,15 +233,6 @@ node $TW5_BUILD_TIDDLYWIKI \
--build index \ --build index \
|| exit 1 || exit 1
# /editions/twitter-archivist/index.html Twitter Archivist edition
node $TW5_BUILD_TIDDLYWIKI \
./editions/twitter-archivist \
--verbose \
--load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/editions/twitter-archivist/ \
--build index \
|| exit 1
###################################################### ######################################################
# #
# Plugin demos # Plugin demos
@@ -459,7 +450,7 @@ node $TW5_BUILD_TIDDLYWIKI \
--verbose \ --verbose \
--load $TW5_BUILD_OUTPUT/build.tid \ --load $TW5_BUILD_OUTPUT/build.tid \
--output $TW5_BUILD_OUTPUT/library/$TW5_BUILD_VERSION \ --output $TW5_BUILD_OUTPUT/library/$TW5_BUILD_VERSION \
--build library\ --build \
|| exit 1 || exit 1
# Delete the temporary build tiddler # Delete the temporary build tiddler

View File

@@ -9,7 +9,6 @@ node ./tiddlywiki.js \
--verbose \ --verbose \
--version \ --version \
--rendertiddler $:/core/save/all test.html text/plain \ --rendertiddler $:/core/save/all test.html text/plain \
--test \
|| exit 1 || exit 1
echo To run the tests in a browser, open "editions/test/output/test.html" echo To run the tests in a browser, open "editions/test/output/test.html"

View File

@@ -2403,11 +2403,11 @@ $tw.boot.initStartup = function(options) {
$tw.utils.registerFileType("application/x-font-ttf","base64",".woff"); $tw.utils.registerFileType("application/x-font-ttf","base64",".woff");
$tw.utils.registerFileType("application/font-woff2","base64",".woff2"); $tw.utils.registerFileType("application/font-woff2","base64",".woff2");
$tw.utils.registerFileType("audio/ogg","base64",".ogg"); $tw.utils.registerFileType("audio/ogg","base64",".ogg");
$tw.utils.registerFileType("audio/mp4","base64",[".mp4",".m4a"]);
$tw.utils.registerFileType("video/ogg","base64",[".ogm",".ogv",".ogg"]); $tw.utils.registerFileType("video/ogg","base64",[".ogm",".ogv",".ogg"]);
$tw.utils.registerFileType("video/webm","base64",".webm"); $tw.utils.registerFileType("video/webm","base64",".webm");
$tw.utils.registerFileType("video/mp4","base64",".mp4"); $tw.utils.registerFileType("video/mp4","base64",".mp4");
$tw.utils.registerFileType("audio/mp3","base64",".mp3"); $tw.utils.registerFileType("audio/mp3","base64",".mp3");
$tw.utils.registerFileType("audio/mp4","base64",[".mp4",".m4a"]);
$tw.utils.registerFileType("text/markdown","utf8",[".md",".markdown"],{deserializerType:"text/x-markdown"}); $tw.utils.registerFileType("text/markdown","utf8",[".md",".markdown"],{deserializerType:"text/x-markdown"});
$tw.utils.registerFileType("text/x-markdown","utf8",[".md",".markdown"]); $tw.utils.registerFileType("text/x-markdown","utf8",[".md",".markdown"]);
$tw.utils.registerFileType("application/enex+xml","utf8",".enex"); $tw.utils.registerFileType("application/enex+xml","utf8",".enex");

View File

@@ -1,4 +0,0 @@
title: $:/core/images/layout-button
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-layout-button tc-image-button" viewBox="0 0 24 24" stroke-width="1" stroke="none"><path d="M0 0h24v24H0z" fill="none"/><rect x="2" y="2" width="7" height="7" rx="2"/><rect x="2" y="13" width="7" height="9" rx="2"/><rect x="12" y="2" width="10" height="20" rx="2"/></svg>

View File

@@ -1,6 +0,0 @@
title: $:/core/images/mastodon
tags: $:/tags/Image
<svg width="22pt" height="22pt" class="tc-image-mastodon tc-image-button" viewBox="0 0 128 128">
<path d="M112.716,76.735C111.231,85.764 99.411,95.646 85.836,97.561C78.757,98.559 71.787,99.476 64.355,99.073C52.201,98.415 42.61,95.646 42.61,95.646C42.61,97.044 42.683,98.374 42.829,99.619C44.409,113.79 54.723,114.639 64.493,115.035C74.354,115.434 83.134,112.163 83.134,112.163L83.539,122.695C83.539,122.695 76.642,127.071 64.355,127.875C57.58,128.315 49.167,127.674 39.369,124.61C18.118,117.965 14.463,91.202 13.904,64.048C13.733,55.985 13.839,48.383 13.839,42.024C13.839,14.257 29.238,6.118 29.238,6.118C37.002,1.905 50.326,0.134 64.177,-0L64.517,-0C78.369,0.134 91.701,1.905 99.465,6.118C99.465,6.118 114.864,14.257 114.864,42.024C114.864,42.024 115.057,62.511 112.716,76.735ZM96.7,44.179C96.7,37.307 95.219,31.847 92.245,27.807C89.177,23.767 85.16,21.696 80.174,21.696C74.403,21.696 70.034,24.316 67.146,29.556L64.337,35.118L61.529,29.556C58.64,24.316 54.271,21.696 48.501,21.696C43.514,21.696 39.497,23.767 36.43,27.807C33.455,31.847 31.974,37.307 31.974,44.179L31.974,77.8L43.249,77.8L43.249,45.167C43.249,38.288 45.699,34.796 50.599,34.796C56.017,34.796 58.733,38.938 58.733,47.128L58.733,64.99L69.941,64.99L69.941,47.128C69.941,38.938 72.657,34.796 78.075,34.796C82.975,34.796 85.425,38.288 85.425,45.167L85.425,77.8L96.7,77.8L96.7,44.179Z"/>
</svg>

View File

@@ -59,8 +59,6 @@ Home/Caption: home
Home/Hint: Open the default tiddlers Home/Hint: Open the default tiddlers
Language/Caption: language Language/Caption: language
Language/Hint: Choose the user interface language Language/Hint: Choose the user interface language
LayoutSwitcher/Hint: Open layout switcher
LayoutSwitcher/Caption: layout
Manager/Caption: tiddler manager Manager/Caption: tiddler manager
Manager/Hint: Open tiddler manager Manager/Hint: Open tiddler manager
More/Caption: more More/Caption: more

View File

@@ -7,7 +7,7 @@ Appearance/Hint: Ways to customise the appearance of your TiddlyWiki.
Basics/AnimDuration/Prompt: Animation duration Basics/AnimDuration/Prompt: Animation duration
Basics/AutoFocus/Prompt: Default focus field for new tiddlers Basics/AutoFocus/Prompt: Default focus field for new tiddlers
Basics/Caption: Basics Basics/Caption: Basics
Basics/DefaultTiddlers/BottomHint: Use &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to {{retain story ordering||$:/snippets/retain-story-ordering-button}} Basics/DefaultTiddlers/BottomHint: Use &#91;&#91;double square brackets&#93;&#93; for titles with spaces. Or you can choose to <$button set="$:/DefaultTiddlers" setTo="[list[$:/StoryList]]">retain story ordering</$button>
Basics/DefaultTiddlers/Prompt: Default tiddlers Basics/DefaultTiddlers/Prompt: Default tiddlers
Basics/DefaultTiddlers/TopHint: Choose which tiddlers are displayed at startup Basics/DefaultTiddlers/TopHint: Choose which tiddlers are displayed at startup
Basics/Language/Prompt: Hello! Current language: Basics/Language/Prompt: Hello! Current language:
@@ -90,8 +90,8 @@ Plugins/Languages/Caption: Languages
Plugins/Languages/Hint: Language pack plugins Plugins/Languages/Hint: Language pack plugins
Plugins/NoInfoFound/Hint: No ''"<$text text=<<currentTab>>/>"'' found Plugins/NoInfoFound/Hint: No ''"<$text text=<<currentTab>>/>"'' found
Plugins/NotInstalled/Hint: This plugin is not currently installed Plugins/NotInstalled/Hint: This plugin is not currently installed
Plugins/OpenPluginLibrary: Open plugin library Plugins/OpenPluginLibrary: open plugin library
Plugins/ClosePluginLibrary: Close plugin library Plugins/ClosePluginLibrary: close plugin library
Plugins/PluginWillRequireReload: (requires reload) Plugins/PluginWillRequireReload: (requires reload)
Plugins/Plugins/Caption: Plugins Plugins/Plugins/Caption: Plugins
Plugins/Plugins/Hint: Plugins Plugins/Plugins/Hint: Plugins

View File

@@ -13,7 +13,7 @@ dependents: For a plugin, lists the dependent plugin titles
description: The descriptive text for a plugin, or a modal dialogue description: The descriptive text for a plugin, or a modal dialogue
draft.of: For draft tiddlers, contains the title of the tiddler of which this is a draft draft.of: For draft tiddlers, contains the title of the tiddler of which this is a draft
draft.title: For draft tiddlers, contains the proposed new title of the tiddler draft.title: For draft tiddlers, contains the proposed new title of the tiddler
footer: The footer text for a modal footer: The footer text for a wizard
hide-body: The view template will hide bodies of tiddlers if set to ''yes'' hide-body: The view template will hide bodies of tiddlers if set to ''yes''
icon: The title of the tiddler containing the icon associated with a tiddler icon: The title of the tiddler containing the icon associated with a tiddler
library: Indicates that a tiddler should be saved as a JavaScript library if set to ''yes'' library: Indicates that a tiddler should be saved as a JavaScript library if set to ''yes''
@@ -28,7 +28,7 @@ plugin-type: The type of plugin in a plugin tiddler
revision: The revision of the tiddler held at the server revision: The revision of the tiddler held at the server
released: Date of a TiddlyWiki release released: Date of a TiddlyWiki release
source: The source URL associated with a tiddler source: The source URL associated with a tiddler
subtitle: The subtitle text for a modal subtitle: The subtitle text for a wizard
tags: A list of tags associated with a tiddler tags: A list of tags associated with a tiddler
text: The body text of a tiddler text: The body text of a tiddler
throttle.refresh: If present, throttles refreshes of this tiddler throttle.refresh: If present, throttles refreshes of this tiddler

View File

@@ -1,18 +0,0 @@
title: $:/language/Help/commands
description: Run commands returned from a filter
Sequentially run the command tokens returned from a filter
```
--commands <filter>
```
Examples
```
--commands "[enlist{$:/build-commands-as-text}]"
```
```
--commands "[{$:/build-commands-as-json}jsonindexes[]] :map[{$:/build-commands-as-json}jsonget<currentTiddler>]"
```

View File

@@ -1,42 +0,0 @@
/*\
title: $:/core/modules/commands/commands.js
type: application/javascript
module-type: command
Runs the commands returned from a filter
\*/
(function() {
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "commands",
synchronous: true
};
var Command = function(params, commander) {
this.params = params;
this.commander = commander;
};
Command.prototype.execute = function() {
// Parse the filter
var filter = this.params[0];
if(!filter) {
return "No filter specified";
}
var commands = this.commander.wiki.filterTiddlers(filter)
if(commands.length === 0) {
return "No tiddlers found for filter '" + filter + "'";
}
this.commander.addCommandTokens(commands);
return null;
};
exports.Command = Command;
})();

View File

@@ -87,7 +87,7 @@ function FramedEngine(options) {
$tw.utils.addEventListeners(this.domNode,[ $tw.utils.addEventListeners(this.domNode,[
{name: "click",handlerObject: this,handlerMethod: "handleClickEvent"}, {name: "click",handlerObject: this,handlerMethod: "handleClickEvent"},
{name: "input",handlerObject: this,handlerMethod: "handleInputEvent"}, {name: "input",handlerObject: this,handlerMethod: "handleInputEvent"},
{name: "keydown",handlerObject: this,handlerMethod: "handleKeydownEvent"}, {name: "keydown",handlerObject: this.widget,handlerMethod: "handleKeydownEvent"},
{name: "focus",handlerObject: this,handlerMethod: "handleFocusEvent"} {name: "focus",handlerObject: this,handlerMethod: "handleFocusEvent"}
]); ]);
// Add drag and drop event listeners if fileDrop is enabled // Add drag and drop event listeners if fileDrop is enabled
@@ -192,17 +192,6 @@ FramedEngine.prototype.handleFocusEvent = function(event) {
} }
}; };
/*
Handle a keydown event
*/
FramedEngine.prototype.handleKeydownEvent = function(event) {
if ($tw.keyboardManager.handleKeydownEvent(event, {onlyPriority: true})) {
return true;
}
return this.widget.handleKeydownEvent(event);
};
/* /*
Handle a click Handle a click
*/ */

View File

@@ -298,7 +298,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) {
Propogate keydown events to our container for the keyboard widgets benefit Propogate keydown events to our container for the keyboard widgets benefit
*/ */
EditTextWidget.prototype.propogateKeydownEvent = function(event) { EditTextWidget.prototype.propogateKeydownEvent = function(event) {
var newEvent = this.cloneEvent(event,["keyCode","code","which","key","metaKey","ctrlKey","altKey","shiftKey"]); var newEvent = this.cloneEvent(event,["keyCode","which","metaKey","ctrlKey","altKey","shiftKey"]);
return !this.parentDomNode.dispatchEvent(newEvent); return !this.parentDomNode.dispatchEvent(newEvent);
}; };

View File

@@ -19,13 +19,13 @@ exports.variable = function(source,prefix,options) {
var results = []; var results = [];
if(prefix === "!") { if(prefix === "!") {
source(function(tiddler,title) { source(function(tiddler,title) {
if(options.widget.getVariable(title) === undefined) { if(!(title in options.widget.variables)) {
results.push(title); results.push(title);
} }
}); });
} else { } else {
source(function(tiddler,title) { source(function(tiddler,title) {
if(options.widget.getVariable(title) !== undefined) { if(title in options.widget.variables) {
results.push(title); results.push(title);
} }
}); });

View File

@@ -17,23 +17,9 @@ exports["jsonget"] = function(source,operator,options) {
source(function(tiddler,title) { source(function(tiddler,title) {
var data = $tw.utils.parseJSONSafe(title,title); var data = $tw.utils.parseJSONSafe(title,title);
if(data) { if(data) {
var items = getDataItemValueAsStrings(data,operator.operands); var item = getDataItemValueAsString(data,operator.operands);
if(items !== undefined) {
results.push.apply(results,items);
}
}
});
return results;
};
exports["jsonextract"] = function(source,operator,options) {
var results = [];
source(function(tiddler,title) {
var data = $tw.utils.parseJSONSafe(title,title);
if(data) {
var item = getDataItem(data,operator.operands);
if(item !== undefined) { if(item !== undefined) {
results.push(JSON.stringify(item)); results.push(item);
} }
} }
}); });
@@ -45,9 +31,9 @@ exports["jsonindexes"] = function(source,operator,options) {
source(function(tiddler,title) { source(function(tiddler,title) {
var data = $tw.utils.parseJSONSafe(title,title); var data = $tw.utils.parseJSONSafe(title,title);
if(data) { if(data) {
var items = getDataItemKeysAsStrings(data,operator.operands); var item = getDataItemKeysAsStrings(data,operator.operands);
if(items !== undefined) { if(item !== undefined) {
results.push.apply(results,items); results.push.apply(results,item);
} }
} }
}); });
@@ -71,11 +57,11 @@ exports["jsontype"] = function(source,operator,options) {
/* /*
Given a JSON data structure and an array of index strings, return an array of the string representation of the values at the end of the index chain, or "undefined" if any of the index strings are invalid Given a JSON data structure and an array of index strings, return an array of the string representation of the values at the end of the index chain, or "undefined" if any of the index strings are invalid
*/ */
function getDataItemValueAsStrings(data,indexes) { function getDataItemValueAsString(data,indexes) {
// Get the item // Get the item
var item = getDataItem(data,indexes); var item = getDataItem(data,indexes);
// Return the item as a string list // Return the item as a string
return convertDataItemValueToStrings(item); return convertDataItemValueToString(item);
} }
/* /*
@@ -91,34 +77,15 @@ function getDataItemKeysAsStrings(data,indexes) {
/* /*
Return an array of the string representation of the values of a data item, or "undefined" if the item is undefined Return an array of the string representation of the values of a data item, or "undefined" if the item is undefined
*/ */
function convertDataItemValueToStrings(item) { function convertDataItemValueToString(item) {
// Return the item as a string // Return the item as a string
if(item === undefined) { if(item === undefined) {
return undefined; return item;
} else if(item === null) {
return ["null"]
} else if(typeof item === "object") {
var results = [],i,t;
if($tw.utils.isArray(item)) {
// Return all the items in arrays recursively
for(i=0; i<item.length; i++) {
t = convertDataItemValueToStrings(item[i])
if(t !== undefined) {
results.push.apply(results,t);
}
}
} else {
// Return all the values in objects recursively
$tw.utils.each(Object.keys(item).sort(),function(key) {
t = convertDataItemValueToStrings(item[key]);
if(t !== undefined) {
results.push.apply(results,t);
}
});
}
return results;
} }
return [item.toString()]; if(typeof item === "object") {
return JSON.stringify(item);
}
return item.toString();
} }
/* /*

View File

@@ -16,15 +16,9 @@ Filter operator for returning the names of the active variables
Export our filter function Export our filter function
*/ */
exports.variables = function(source,operator,options) { exports.variables = function(source,operator,options) {
var names = [], var names = [];
widget = options.widget; for(var variable in options.widget.variables) {
while(widget && !widget.hasOwnProperty("variables")) { names.push(variable);
widget = widget.parentWidget;
}
if(widget && widget.variables) {
for(var variable in widget.variables) {
names.push(variable);
}
} }
return names.sort(); return names.sort();
}; };

View File

@@ -141,7 +141,6 @@ function KeyboardManager(options) {
this.shortcutKeysList = [], // Stores the shortcut-key descriptors this.shortcutKeysList = [], // Stores the shortcut-key descriptors
this.shortcutActionList = [], // Stores the corresponding action strings this.shortcutActionList = [], // Stores the corresponding action strings
this.shortcutParsedList = []; // Stores the parsed key descriptors this.shortcutParsedList = []; // Stores the parsed key descriptors
this.shortcutPriorityList = []; // Stores the parsed shortcut priority
this.lookupNames = ["shortcuts"]; this.lookupNames = ["shortcuts"];
this.lookupNames.push($tw.platform.isMac ? "shortcuts-mac" : "shortcuts-not-mac") this.lookupNames.push($tw.platform.isMac ? "shortcuts-mac" : "shortcuts-not-mac")
this.lookupNames.push($tw.platform.isWindows ? "shortcuts-windows" : "shortcuts-not-windows"); this.lookupNames.push($tw.platform.isWindows ? "shortcuts-windows" : "shortcuts-not-windows");
@@ -319,23 +318,12 @@ KeyboardManager.prototype.updateShortcutLists = function(tiddlerList) {
this.shortcutKeysList[i] = tiddlerFields.key !== undefined ? tiddlerFields.key : undefined; this.shortcutKeysList[i] = tiddlerFields.key !== undefined ? tiddlerFields.key : undefined;
this.shortcutActionList[i] = tiddlerFields.text; this.shortcutActionList[i] = tiddlerFields.text;
this.shortcutParsedList[i] = this.shortcutKeysList[i] !== undefined ? this.parseKeyDescriptors(this.shortcutKeysList[i]) : undefined; this.shortcutParsedList[i] = this.shortcutKeysList[i] !== undefined ? this.parseKeyDescriptors(this.shortcutKeysList[i]) : undefined;
this.shortcutPriorityList[i] = tiddlerFields.priority === "yes" ? true : false;
} }
}; };
/* KeyboardManager.prototype.handleKeydownEvent = function(event) {
event: the keyboard event object
options:
onlyPriority: true if only priority global shortcuts should be invoked
*/
KeyboardManager.prototype.handleKeydownEvent = function(event, options) {
options = options || {};
var key, action; var key, action;
for(var i=0; i<this.shortcutTiddlers.length; i++) { for(var i=0; i<this.shortcutTiddlers.length; i++) {
if(options.onlyPriority && this.shortcutPriorityList[i] !== true) {
continue;
}
if(this.shortcutParsedList[i] !== undefined && this.checkKeyDescriptors(event,this.shortcutParsedList[i])) { if(this.shortcutParsedList[i] !== undefined && this.checkKeyDescriptors(event,this.shortcutParsedList[i])) {
key = this.shortcutParsedList[i]; key = this.shortcutParsedList[i];
action = this.shortcutActionList[i]; action = this.shortcutActionList[i];

View File

@@ -13,11 +13,6 @@ The CSV text parser processes CSV files into a table wrapped in a scrollable wid
"use strict"; "use strict";
var CsvParser = function(type,text,options) { var CsvParser = function(type,text,options) {
// Special handler for tab-delimited files
if (type === 'text/tab-delimited-values' && !options.separator) {
options.separator = "\t";
}
// Table framework // Table framework
this.tree = [{ this.tree = [{
"type": "scrollable", "children": [{ "type": "scrollable", "children": [{
@@ -29,33 +24,30 @@ var CsvParser = function(type,text,options) {
}] }]
}]; }];
// Split the text into lines // Split the text into lines
var lines = $tw.utils.parseCsvString(text, options), var lines = text.split(/\r?\n/mg),
tag = "th"; tag = "th";
var maxColumns = 0;
$tw.utils.each(lines, function(columns) {
maxColumns = Math.max(columns.length, maxColumns);
});
for(var line=0; line<lines.length; line++) { for(var line=0; line<lines.length; line++) {
var columns = lines[line]; var lineText = lines[line];
var row = { if(lineText) {
"type": "element", "tag": "tr", "children": [] var row = {
}; "type": "element", "tag": "tr", "children": []
for(var column=0; column<maxColumns; column++) { };
row.children.push({ var columns = lineText.split(",");
"type": "element", "tag": tag, "children": [{ for(var column=0; column<columns.length; column++) {
"type": "text", row.children.push({
"text": columns[column] || '' "type": "element", "tag": tag, "children": [{
}] "type": "text",
}); "text": columns[column]
}]
});
}
tag = "td";
this.tree[0].children[0].children[0].children.push(row);
} }
tag = "td";
this.tree[0].children[0].children[0].children.push(row);
} }
}; };
exports["text/csv"] = CsvParser; exports["text/csv"] = CsvParser;
exports["text/tab-delimited-values"] = CsvParser;
})(); })();

View File

@@ -58,7 +58,7 @@ exports.parse = function() {
var reEnd; var reEnd;
if(this.match[3]) { if(this.match[3]) {
// If so, the end of the body is marked with \end // If so, the end of the body is marked with \end
reEnd = new RegExp("(\\r?\\n\\\\end[^\\S\\n\\r]*(?:" + $tw.utils.escapeRegExp(this.match[1]) + ")?(?:$|\\r?\\n))","mg"); reEnd = /(\r?\n\\end[^\S\n\r]*(?:$|\r?\n))/mg;
} else { } else {
// Otherwise, the end of the definition is marked by the end of the line // Otherwise, the end of the definition is marked by the end of the line
reEnd = /($|\r?\n)/mg; reEnd = /($|\r?\n)/mg;

View File

@@ -1,68 +0,0 @@
/*\
title: $:/core/modules/parsers/wikiparser/rules/parsermode.js
type: application/javascript
module-type: wikirule
Wiki pragma rule for parser mode specifications
```
\parsermode block
\parsermode inline
```
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.name = "parsermode";
exports.types = {pragma: true};
/*
Instantiate parse rule
*/
exports.init = function(parser) {
this.parser = parser;
// Regexp to match
this.matchRegExp = /^\\parsermode[^\S\n]/mg;
};
/*
Parse the most recent match
*/
exports.parse = function() {
// Move past the pragma invocation
this.parser.pos = this.matchRegExp.lastIndex;
// Parse whitespace delimited tokens terminated by a line break
var reMatch = /[^\S\n]*(\S+)|(\r?\n)/mg,
parserMode = undefined;
reMatch.lastIndex = this.parser.pos;
var match = reMatch.exec(this.parser.source);
while(match && match.index === this.parser.pos) {
this.parser.pos = reMatch.lastIndex;
// Exit if we've got the line break
if(match[2]) {
break;
}
// Process the token
if(match[1]) {
parserMode = match[1];
}
// Match the next token
match = reMatch.exec(this.parser.source);
}
// Process the tokens
if(parserMode !== undefined) {
if(parserMode === "block") {
this.parser.parseAsInline = false;
} else if(parserMode === "inline") {
this.parser.parseAsInline = true;
}
}
// No parse tree nodes to return
return [];
};
})();

View File

@@ -41,6 +41,9 @@ exports.parse = function() {
var node = { var node = {
type: "element", type: "element",
tag: "span", tag: "span",
attributes: {
"class": {type: "string", value: "tc-inline-style"}
},
children: tree children: tree
}; };
if(classString) { if(classString) {
@@ -49,9 +52,6 @@ exports.parse = function() {
if(stylesString) { if(stylesString) {
$tw.utils.addAttributeToParseTreeNode(node,"style",stylesString); $tw.utils.addAttributeToParseTreeNode(node,"style",stylesString);
} }
if(!classString && !stylesString) {
$tw.utils.addClassToParseTreeNode(node,"tc-inline-style");
}
return [node]; return [node];
}; };

View File

@@ -47,8 +47,6 @@ var WikiParser = function(type,text,options) {
this.sourceLength = this.source.length; this.sourceLength = this.source.length;
// Flag for ignoring whitespace // Flag for ignoring whitespace
this.configTrimWhiteSpace = false; this.configTrimWhiteSpace = false;
// Parser mode
this.parseAsInline = options.parseAsInline;
// Set current parse position // Set current parse position
this.pos = 0; this.pos = 0;
// Start with empty output // Start with empty output
@@ -85,7 +83,7 @@ var WikiParser = function(type,text,options) {
// Parse any pragmas // Parse any pragmas
var topBranch = this.parsePragmas(); var topBranch = this.parsePragmas();
// Parse the text into inline runs or blocks // Parse the text into inline runs or blocks
if(this.parseAsInline) { if(options.parseAsInline) {
topBranch.push.apply(topBranch,this.parseInlineRun()); topBranch.push.apply(topBranch,this.parseInlineRun());
} else { } else {
topBranch.push.apply(topBranch,this.parseBlocks()); topBranch.push.apply(topBranch,this.parseBlocks());

View File

@@ -30,16 +30,6 @@ exports.handler = function(request,response,state) {
if(fields.revision) { if(fields.revision) {
delete fields.revision; delete fields.revision;
} }
// If this is a skinny tiddler, it means the client never got the full
// version of the tiddler to edit. So we must preserve whatever text
// already exists on the server, or else we'll inadvertently delete it.
if(fields._is_skinny !== undefined) {
var tiddler = state.wiki.getTiddler(title);
if(tiddler) {
fields.text = tiddler.fields.text;
}
delete fields._is_skinny;
}
state.wiki.addTiddler(new $tw.Tiddler(fields,{title: title})); state.wiki.addTiddler(new $tw.Tiddler(fields,{title: title}));
var changeCount = state.wiki.getChangeCount(title).toString(); var changeCount = state.wiki.getChangeCount(title).toString();
response.writeHead(204, "OK",{ response.writeHead(204, "OK",{

View File

@@ -121,11 +121,7 @@ exports.startup = function() {
}); });
// Set up the syncer object if we've got a syncadaptor // Set up the syncer object if we've got a syncadaptor
if($tw.syncadaptor) { if($tw.syncadaptor) {
$tw.syncer = new $tw.Syncer({ $tw.syncer = new $tw.Syncer({wiki: $tw.wiki, syncadaptor: $tw.syncadaptor});
wiki: $tw.wiki,
syncadaptor: $tw.syncadaptor,
logging: $tw.wiki.getTiddlerText('$:/config/SyncLogging', "yes") === "yes"
});
} }
// Setup the saver handler // Setup the saver handler
$tw.saverHandler = new $tw.SaverHandler({ $tw.saverHandler = new $tw.SaverHandler({

View File

@@ -12,113 +12,35 @@ A barebones CSV parser
/*global $tw: false */ /*global $tw: false */
"use strict"; "use strict";
var QUOTE = '"';
var getCellInfo = function(text, start, length, SEPARATOR) {
var isCellQuoted = text.charAt(start) === QUOTE;
var cellStart = isCellQuoted ? start + 1 : start;
if (text.charAt(i) === SEPARATOR) {
return [cellStart, cellStart, false];
}
for (var i = cellStart; i < length; i++) {
var cellCharacter = text.charAt(i);
var isEOL = cellCharacter === "\n" || cellCharacter === "\r";
if (isEOL && !isCellQuoted) {
return [cellStart, i, false];
} else if (cellCharacter === SEPARATOR && !isCellQuoted) {
return [cellStart, i, false];
} else if (cellCharacter === QUOTE && isCellQuoted) {
var nextCharacter = i + 1 < length ? text.charAt(i + 1) : '';
if (nextCharacter !== QUOTE) {
return [cellStart, i, true];
} else {
i++;
}
}
}
return [cellStart, i, isCellQuoted];
}
exports.parseCsvString = function(text, options) {
if (!text) {
return [];
}
options = options || {};
var SEPARATOR = options.separator || ",",
length = text.length,
rows = [],
nextRow = [];
for (var i = 0; i < length; i++) {
var cellInfo = getCellInfo(text, i, length, SEPARATOR);
var cellText = text.substring(cellInfo[0], cellInfo[1]);
if (cellInfo[2]) {
cellText = cellText.replace(/""/g, '"');
cellInfo[1]++;
}
nextRow.push(cellText);
i = cellInfo[1];
var character = text.charAt(i);
var nextCharacter = i + 1 < length ? text.charAt(i + 1) : '';
if (character === "\r" || character === "\n") {
// Edge case for empty rows
if (nextRow.length === 1 && nextRow[0] === '') {
nextRow.length = 0;
}
rows.push(nextRow);
nextRow = [];
if (character === "\r") {
var nextCharacter = i + 1 < length ? text.charAt(i + 1) : '';
if (nextCharacter === "\n") {
i++;
}
}
}
}
// Special case if last cell in last row is an empty cell
if (text.charAt(length - 1) === SEPARATOR) {
nextRow.push("");
}
rows.push(nextRow);
return rows;
}
/* /*
Parse a CSV string with a header row and return an array of hashmaps. Parse a CSV string with a header row and return an array of hashmaps.
*/ */
exports.parseCsvStringWithHeader = function(text,options) { exports.parseCsvStringWithHeader = function(text,options) {
var csv = $tw.utils.parseCsvString(text, options); options = options || {};
var headers = csv[0]; var separator = options.separator || ",",
rows = text.split(/\r?\n/mg).map(function(row) {
csv = csv.slice(1); return $tw.utils.trim(row);
for (var i = 0; i < csv.length; i++) { }).filter(function(row) {
var row = csv[i]; return row !== "";
var rowObject = Object.create(null); });
if(rows.length < 1) {
for(var columnIndex=0; columnIndex<headers.length; columnIndex++) { return "Missing header row";
var columnName = headers[columnIndex];
if (columnName) {
rowObject[columnName] = $tw.utils.trim(row[columnIndex] || "");
}
}
csv[i] = rowObject;
} }
return csv; var headings = rows[0].split(separator),
results = [];
for(var row=1; row<rows.length; row++) {
var columns = rows[row].split(separator),
columnResult = Object.create(null);
if(columns.length !== headings.length) {
return "Malformed CSV row '" + rows[row] + "'";
}
for(var column=0; column<columns.length; column++) {
var columnName = headings[column];
columnResult[columnName] = $tw.utils.trim(columns[column] || "");
}
results.push(columnResult);
}
return results;
} }
})(); })();

View File

@@ -12,8 +12,6 @@ Various static DOM-related utility functions.
/*global $tw: false */ /*global $tw: false */
"use strict"; "use strict";
var Popup = require("$:/core/modules/utils/dom/popup.js");
/* /*
Determines whether element 'a' contains element 'b' Determines whether element 'a' contains element 'b'
Code thanks to John Resig, http://ejohn.org/blog/comparing-document-position/ Code thanks to John Resig, http://ejohn.org/blog/comparing-document-position/
@@ -296,21 +294,8 @@ exports.collectDOMVariables = function(selectedNode,domNode,event) {
}); });
if(selectedNode.offsetLeft) { if(selectedNode.offsetLeft) {
// Add variables with a (relative and absolute) popup coordinate string for the selected node // Add a variable with a popup coordinate string for the selected node
var nodeRect = { variables["tv-popup-coords"] = "(" + selectedNode.offsetLeft + "," + selectedNode.offsetTop +"," + selectedNode.offsetWidth + "," + selectedNode.offsetHeight + ")";
left: selectedNode.offsetLeft,
top: selectedNode.offsetTop,
width: selectedNode.offsetWidth,
height: selectedNode.offsetHeight
};
variables["tv-popup-coords"] = Popup.buildCoordinates(Popup.coordinatePrefix.csOffsetParent,nodeRect);
var absRect = $tw.utils.extend({}, nodeRect);
for (var currentNode = selectedNode.offsetParent; currentNode; currentNode = currentNode.offsetParent) {
absRect.left += currentNode.offsetLeft;
absRect.top += currentNode.offsetTop;
}
variables["tv-popup-abs-coords"] = Popup.buildCoordinates(Popup.coordinatePrefix.csAbsolute,absRect);
// Add variables for offset of selected node // Add variables for offset of selected node
variables["tv-selectednode-posx"] = selectedNode.offsetLeft.toString(); variables["tv-selectednode-posx"] = selectedNode.offsetLeft.toString();

View File

@@ -26,8 +26,6 @@ Display a modal dialogue
options: see below options: see below
Options include: Options include:
downloadLink: Text of a big download link to include downloadLink: Text of a big download link to include
event: widget event
variables: from event.paramObject
*/ */
Modal.prototype.display = function(title,options) { Modal.prototype.display = function(title,options) {
options = options || {}; options = options || {};
@@ -211,10 +209,6 @@ Modal.prototype.display = function(title,options) {
headerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false); headerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
bodyWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false); bodyWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
footerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false); footerWidgetNode.addEventListener("tm-close-tiddler",closeHandler,false);
// Whether to close the modal dialog when the mask (area outside the modal) is clicked
if(tiddler.fields && (tiddler.fields["mask-closable"] === "yes" || tiddler.fields["mask-closable"] === "true")) {
modalBackdrop.addEventListener("click",closeHandler,false);
}
// Set the initial styles for the message // Set the initial styles for the message
$tw.utils.setStyle(modalBackdrop,[ $tw.utils.setStyle(modalBackdrop,[
{opacity: "0"} {opacity: "0"}

View File

@@ -22,19 +22,6 @@ var Popup = function(options) {
this.popups = []; // Array of {title:,wiki:,domNode:} objects this.popups = []; // Array of {title:,wiki:,domNode:} objects
}; };
/*
Global regular expression for parsing the location of a popup.
This is also used by the Reveal widget.
*/
exports.popupLocationRegExp = /^(@?)\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/
/*
Objekt containing the available prefixes for coordinates build with the `buildCoordinates` function:
- csOffsetParent: Uses a coordinate system based on the offset parent (no prefix).
- csAbsolute: Use an absolute coordinate system (prefix "@").
*/
exports.coordinatePrefix = { csOffsetParent: "", csAbsolute: "@" }
/* /*
Trigger a popup open or closed. Parameters are in a hashmap: Trigger a popup open or closed. Parameters are in a hashmap:
title: title of the tiddler where the popup details are stored title: title of the tiddler where the popup details are stored
@@ -149,17 +136,8 @@ Popup.prototype.show = function(options) {
height: options.domNode.offsetHeight height: options.domNode.offsetHeight
}; };
} }
if(options.absolute && options.domNode) { var popupRect = "(" + rect.left + "," + rect.top + "," +
// Walk the offsetParent chain and add the position of the offsetParents to make rect.width + "," + rect.height + ")";
// the position absolute to the root node of the page.
var currentNode = options.domNode.offsetParent;
while(currentNode) {
rect.left += currentNode.offsetLeft;
rect.top += currentNode.offsetTop;
currentNode = currentNode.offsetParent;
}
}
var popupRect = exports.buildCoordinates(options.absolute?exports.coordinatePrefix.csAbsolute:exports.coordinatePrefix.csOffsetParent,rect);
if(options.noStateReference) { if(options.noStateReference) {
options.wiki.setText(options.title,"text",undefined,popupRect); options.wiki.setText(options.title,"text",undefined,popupRect);
} else { } else {
@@ -194,54 +172,13 @@ Popup.prototype.cancel = function(level) {
}; };
/* /*
Returns true if the specified title and text identifies an active popup. Returns true if the specified title and text identifies an active popup
This function is safe to call, even if the popup class was not initialized.
*/ */
exports.readPopupState = function(text) { Popup.prototype.readPopupState = function(text) {
return exports.popupLocationRegExp.test(text); var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/;
return popupLocationRegExp.test(text);
}; };
/*
Parses a coordinate string in the format `(x,y,w,h)` or `@(x,y,z,h)` and returns
an object containing the position, width and height. The absolute-Mark is boolean
value that indicates the coordinate system of the coordinates. If they start with
an `@`, `absolute` is set to true and the coordinates are relative to the root
element. If the initial `@` is missing, they are relative to the offset parent
element and `absoute` is false.
This function is safe to call, even if the popup class was not initialized.
*/
exports.parseCoordinates = function(coordinates) {
var match = exports.popupLocationRegExp.exec(coordinates);
if(match) {
return {
absolute: (match[1] === "@"),
left: parseFloat(match[2]),
top: parseFloat(match[3]),
width: parseFloat(match[4]),
height: parseFloat(match[5])
};
} else {
return false;
}
}
/*
Builds a coordinate string from a coordinate system identifier and an object
containing the left, top, width and height values.
Use constants defined in coordinatePrefix to specify a coordinate system.
If one of the parameters is invalid for building a coordinate string `(0,0,0,0)`
will be returned.
This function is safe to call, even if the popup class was not initialized.
*/
exports.buildCoordinates = function(prefix,position) {
var coord = prefix + "(" + position.left + "," + position.top + "," + position.width + "," + position.height + ")";
if (exports.popupLocationRegExp.test(coord)) {
return coord;
} else {
return "(0,0,0,0)";
}
}
exports.Popup = Popup; exports.Popup = Popup;
})(); })();

View File

@@ -15,11 +15,10 @@ function LinkedList() {
LinkedList.prototype.clear = function() { LinkedList.prototype.clear = function() {
// LinkedList performs the duty of both the head and tail node // LinkedList performs the duty of both the head and tail node
this.next = new LLMap(); this.next = Object.create(null);
this.prev = new LLMap(); this.prev = Object.create(null);
// Linked list head initially points to itself this.first = undefined;
this.next.set(null, null); this.last = undefined;
this.prev.set(null, null);
this.length = 0; this.length = 0;
}; };
@@ -42,29 +41,28 @@ Push behaves like array.push and accepts multiple string arguments. But it also
accepts a single array argument too, to be consistent with its other methods. accepts a single array argument too, to be consistent with its other methods.
*/ */
LinkedList.prototype.push = function(/* values */) { LinkedList.prototype.push = function(/* values */) {
var i, values = arguments; var values = arguments;
if($tw.utils.isArray(values[0])) { if($tw.utils.isArray(values[0])) {
values = values[0]; values = values[0];
} }
for(i = 0; i < values.length; i++) { for(var i = 0; i < values.length; i++) {
_assertString(values[i]); _assertString(values[i]);
} }
for(i = 0; i < values.length; i++) { for(var i = 0; i < values.length; i++) {
_linkToEnd(this,values[i]); _linkToEnd(this,values[i]);
} }
return this.length; return this.length;
}; };
LinkedList.prototype.pushTop = function(value) { LinkedList.prototype.pushTop = function(value) {
var t;
if($tw.utils.isArray(value)) { if($tw.utils.isArray(value)) {
for (t=0; t<value.length; t++) { for (var t=0; t<value.length; t++) {
_assertString(value[t]); _assertString(value[t]);
} }
for(t=0; t<value.length; t++) { for(var t=0; t<value.length; t++) {
_removeOne(this,value[t]); _removeOne(this,value[t]);
} }
for(t=0; t<value.length; t++) { for(var t=0; t<value.length; t++) {
_linkToEnd(this,value[t]); _linkToEnd(this,value[t]);
} }
} else { } else {
@@ -76,11 +74,11 @@ LinkedList.prototype.pushTop = function(value) {
LinkedList.prototype.each = function(callback) { LinkedList.prototype.each = function(callback) {
var visits = Object.create(null), var visits = Object.create(null),
value = this.next.get(null); value = this.first;
while(value !== null) { while(value !== undefined) {
callback(value); callback(value);
var next = this.next.get(value); var next = this.next[value];
if(Array.isArray(next)) { if(typeof next === "object") {
var i = visits[value] || 0; var i = visits[value] || 0;
visits[value] = i+1; visits[value] = i+1;
value = next[i]; value = next[i];
@@ -107,79 +105,91 @@ LinkedList.prototype.makeTiddlerIterator = function(wiki) {
}; };
function _removeOne(list,value) { function _removeOne(list,value) {
var nextEntry = list.next.get(value); var prevEntry = list.prev[value],
if(nextEntry === undefined) { nextEntry = list.next[value],
return;
}
var prevEntry = list.prev.get(value),
prev = prevEntry, prev = prevEntry,
next = nextEntry, next = nextEntry;
ref; if(typeof nextEntry === "object") {
if(Array.isArray(nextEntry)) {
next = nextEntry[0]; next = nextEntry[0];
prev = prevEntry[0]; prev = prevEntry[0];
} }
// Relink preceding element. // Relink preceding element.
ref = list.next.get(prev); if(list.first === value) {
if(Array.isArray(ref)) { list.first = next
var i = ref.indexOf(value); } else if(prev !== undefined) {
ref[i] = next; if(typeof list.next[prev] === "object") {
if(next === undefined) {
// Must have been last, and 'i' would be last element.
list.next[prev].pop();
} else {
var i = list.next[prev].indexOf(value);
list.next[prev][i] = next;
}
} else {
list.next[prev] = next;
}
} else { } else {
list.next.set(prev,next); return;
} }
// Now relink following element // Now relink following element
ref = list.prev.get(next); // Check "next !== undefined" rather than "list.last === value" because
if(Array.isArray(ref)) { // we need to know if the FIRST value is the last in the list, not the last.
var i = ref.indexOf(value); if(next !== undefined) {
ref[i] = prev; if(typeof list.prev[next] === "object") {
if(prev === undefined) {
// Must have been first, and 'i' would be 0.
list.prev[next].shift();
} else {
var i = list.prev[next].indexOf(value);
list.prev[next][i] = prev;
}
} else {
list.prev[next] = prev;
}
} else { } else {
list.prev.set(next,prev); list.last = prev;
} }
// Delink actual value. If it uses arrays, just remove first entries. // Delink actual value. If it uses arrays, just remove first entries.
if(Array.isArray(nextEntry) && nextEntry.length > 1) { if(typeof nextEntry === "object") {
nextEntry.shift(); nextEntry.shift();
prevEntry.shift(); prevEntry.shift();
} else { } else {
list.next.set(value,undefined); list.next[value] = undefined;
list.prev.set(value,undefined); list.prev[value] = undefined;
} }
list.length -= 1; list.length -= 1;
}; };
// Sticks the given node onto the end of the list. // Sticks the given node onto the end of the list.
function _linkToEnd(list,value) { function _linkToEnd(list,value) {
var old = list.next.get(value); if(list.first === undefined) {
var last = list.prev.get(null); list.first = value;
// Does it already exists?
if(old !== undefined) {
if(!Array.isArray(old)) {
old = [old];
list.next.set(value,old);
list.prev.set(value,[list.prev.get(value)]);
}
old.push(null);
list.prev.get(value).push(last);
} else { } else {
list.next.set(value,null); // Does it already exists?
list.prev.set(value,last); if(list.first === value || list.prev[value] !== undefined) {
} if(typeof list.next[value] === "string") {
// Make the old last point to this new one. list.next[value] = [list.next[value]];
if(value !== last) { list.prev[value] = [list.prev[value]];
var array = list.next.get(last); } else if(typeof list.next[value] === "undefined") {
if(Array.isArray(array)) { // list.next[value] must be undefined.
array[array.length-1] = value; // Special case. List already has 1 value. It's at the end.
list.next[value] = [];
list.prev[value] = [list.prev[value]];
}
list.prev[value].push(list.last);
// We do NOT append a new value onto "next" list. Iteration will
// figure out it must point to End-of-List on its own.
} else { } else {
list.next.set(last,value); list.prev[value] = list.last;
}
// Make the old last point to this new one.
if(typeof list.next[list.last] === "object") {
list.next[list.last].push(value);
} else {
list.next[list.last] = value;
} }
list.prev.set(null,value);
} else {
// Edge case, the pushed value was already the last value.
// The second-to-last nextPtr for that value must point to itself now.
var array = list.next.get(last);
array[array.length-2] = value;
} }
list.last = value;
list.length += 1; list.length += 1;
}; };
@@ -189,20 +199,6 @@ function _assertString(value) {
} }
}; };
var LLMap = function() {
this.map = Object.create(null);
};
// Just a wrapper so our object map can also accept null.
LLMap.prototype = {
set: function(key,val) {
(key === null) ? (this.null = val) : (this.map[key] = val);
},
get: function(key) {
return (key === null) ? this.null : this.map[key];
}
};
exports.LinkedList = LinkedList; exports.LinkedList = LinkedList;
})(); })();

View File

@@ -65,8 +65,10 @@ exports.addClassToParseTreeNode = function(node,classString) {
// If the class attribute does not exist, we must create it first. // If the class attribute does not exist, we must create it first.
attribute = {name: "class", type: "string", value: ""}; attribute = {name: "class", type: "string", value: ""};
node.attributes["class"] = attribute; node.attributes["class"] = attribute;
node.orderedAttributes = node.orderedAttributes || []; if(node.orderedAttributes) {
node.orderedAttributes.push(attribute); // If there are orderedAttributes, we've got to add them there too.
node.orderedAttributes.push(attribute);
}
} }
if(attribute.type === "string") { if(attribute.type === "string") {
if(attribute.value !== "") { if(attribute.value !== "") {
@@ -86,8 +88,10 @@ exports.addStyleToParseTreeNode = function(node,name,value) {
if(!attribute) { if(!attribute) {
attribute = {name: "style", type: "string", value: ""}; attribute = {name: "style", type: "string", value: ""};
node.attributes.style = attribute; node.attributes.style = attribute;
node.orderedAttributes = node.orderedAttributes || []; if(node.orderedAttributes) {
node.orderedAttributes.push(attribute); // If there are orderedAttributes, we've got to add them there too.
node.orderedAttributes.push(attribute);
}
} }
if(attribute.type === "string") { if(attribute.type === "string") {
attribute.value += name + ":" + value + ";"; attribute.value += name + ":" + value + ";";

View File

@@ -354,9 +354,6 @@ exports.formatDateString = function(date,template) {
var result = "", var result = "",
t = template, t = template,
matches = [ matches = [
[/^TIMESTAMP/, function() {
return date.getTime();
}],
[/^0hh12/, function() { [/^0hh12/, function() {
return $tw.utils.pad($tw.utils.getHours12(date)); return $tw.utils.pad($tw.utils.getHours12(date));
}], }],

View File

@@ -14,8 +14,6 @@ Action widget to trigger a popup.
var Widget = require("$:/core/modules/widgets/widget.js").widget; var Widget = require("$:/core/modules/widgets/widget.js").widget;
var Popup = require("$:/core/modules/utils/dom/popup.js");
var ActionPopupWidget = function(parseTreeNode,options) { var ActionPopupWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options); this.initialise(parseTreeNode,options);
}; };
@@ -59,20 +57,20 @@ Invoke the action associated with this widget
*/ */
ActionPopupWidget.prototype.invokeAction = function(triggeringWidget,event) { ActionPopupWidget.prototype.invokeAction = function(triggeringWidget,event) {
// Trigger the popup // Trigger the popup
var coordinates = Popup.parseCoordinates(this.actionCoords || ""); var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
if(coordinates) { match = popupLocationRegExp.exec(this.actionCoords || "");
if(match) {
$tw.popup.triggerPopup({ $tw.popup.triggerPopup({
domNode: null, domNode: null,
domNodeRect: { domNodeRect: {
left: coordinates.left, left: parseFloat(match[1]),
top: coordinates.top, top: parseFloat(match[2]),
width: coordinates.width, width: parseFloat(match[3]),
height: coordinates.height height: parseFloat(match[4])
}, },
title: this.actionState, title: this.actionState,
wiki: this.wiki, wiki: this.wiki,
floating: this.floating, floating: this.floating
absolute: coordinates.absolute
}); });
} else { } else {
$tw.popup.cancel(0); $tw.popup.cancel(0);

View File

@@ -14,8 +14,6 @@ Button widget
var Widget = require("$:/core/modules/widgets/widget.js").widget; var Widget = require("$:/core/modules/widgets/widget.js").widget;
var Popup = require("$:/core/modules/utils/dom/popup.js");
var ButtonWidget = function(parseTreeNode,options) { var ButtonWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options); this.initialise(parseTreeNode,options);
}; };
@@ -149,7 +147,7 @@ ButtonWidget.prototype.isSelected = function() {
ButtonWidget.prototype.isPoppedUp = function() { ButtonWidget.prototype.isPoppedUp = function() {
var tiddler = this.popupTitle ? this.wiki.getTiddler(this.popupTitle) : this.wiki.getTiddler(this.popup); var tiddler = this.popupTitle ? this.wiki.getTiddler(this.popupTitle) : this.wiki.getTiddler(this.popup);
var result = tiddler && tiddler.fields.text ? Popup.readPopupState(tiddler.fields.text) : false; var result = tiddler && tiddler.fields.text ? $tw.popup.readPopupState(tiddler.fields.text) : false;
return result; return result;
}; };
@@ -175,7 +173,6 @@ ButtonWidget.prototype.triggerPopup = function(event) {
if(this.popupTitle) { if(this.popupTitle) {
$tw.popup.triggerPopup({ $tw.popup.triggerPopup({
domNode: this.domNodes[0], domNode: this.domNodes[0],
absolute: (this.popupAbsCoords === "yes"),
title: this.popupTitle, title: this.popupTitle,
wiki: this.wiki, wiki: this.wiki,
noStateReference: true noStateReference: true
@@ -183,7 +180,6 @@ ButtonWidget.prototype.triggerPopup = function(event) {
} else { } else {
$tw.popup.triggerPopup({ $tw.popup.triggerPopup({
domNode: this.domNodes[0], domNode: this.domNodes[0],
absolute: (this.popupAbsCoords === "yes"),
title: this.popup, title: this.popup,
wiki: this.wiki wiki: this.wiki
}); });
@@ -227,7 +223,6 @@ ButtonWidget.prototype.execute = function() {
this.setField = this.getAttribute("setField"); this.setField = this.getAttribute("setField");
this.setIndex = this.getAttribute("setIndex"); this.setIndex = this.getAttribute("setIndex");
this.popupTitle = this.getAttribute("popupTitle"); this.popupTitle = this.getAttribute("popupTitle");
this.popupAbsCoords = this.getAttribute("popupAbsCoords", "no");
this.tabIndex = this.getAttribute("tabindex"); this.tabIndex = this.getAttribute("tabindex");
this.isDisabled = this.getAttribute("disabled","no"); this.isDisabled = this.getAttribute("disabled","no");
// Make child widgets // Make child widgets
@@ -257,7 +252,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of
*/ */
ButtonWidget.prototype.refresh = function(changedTiddlers) { ButtonWidget.prototype.refresh = function(changedTiddlers) {
var changedAttributes = this.computeAttributes(); var changedAttributes = this.computeAttributes();
if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.popupAbsCoords || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) { if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled || changedAttributes["default"]) {
this.refreshSelf(); this.refreshSelf();
return true; return true;
} else if(changedAttributes["class"]) { } else if(changedAttributes["class"]) {

View File

@@ -53,10 +53,6 @@ KeyboardWidget.prototype.render = function(parent,nextSibling) {
}; };
KeyboardWidget.prototype.handleChangeEvent = function(event) { KeyboardWidget.prototype.handleChangeEvent = function(event) {
if ($tw.keyboardManager.handleKeydownEvent(event, {onlyPriority: true})) {
return true;
}
var keyInfo = $tw.keyboardManager.getMatchingKeyDescriptor(event,this.keyInfoArray); var keyInfo = $tw.keyboardManager.getMatchingKeyDescriptor(event,this.keyInfoArray);
if(keyInfo) { if(keyInfo) {
var handled = this.invokeActions(this,event); var handled = this.invokeActions(this,event);

View File

@@ -14,8 +14,6 @@ Reveal widget
var Widget = require("$:/core/modules/widgets/widget.js").widget; var Widget = require("$:/core/modules/widgets/widget.js").widget;
var Popup = require("$:/core/modules/utils/dom/popup.js");
var RevealWidget = function(parseTreeNode,options) { var RevealWidget = function(parseTreeNode,options) {
this.initialise(parseTreeNode,options); this.initialise(parseTreeNode,options);
}; };
@@ -96,13 +94,6 @@ RevealWidget.prototype.positionPopup = function(domNode) {
left = Math.max(0,left); left = Math.max(0,left);
top = Math.max(0,top); top = Math.max(0,top);
} }
if (this.popup.absolute) {
// Traverse the offsetParent chain and correct the offset to make it relative to the parent node.
for (var offsetParentDomNode = domNode.offsetParent; offsetParentDomNode; offsetParentDomNode = offsetParentDomNode.offsetParent) {
left -= offsetParentDomNode.offsetLeft;
top -= offsetParentDomNode.offsetTop;
}
}
domNode.style.left = left + "px"; domNode.style.left = left + "px";
domNode.style.top = top + "px"; domNode.style.top = top + "px";
}; };
@@ -192,11 +183,19 @@ RevealWidget.prototype.compareStateText = function(state) {
}; };
RevealWidget.prototype.readPopupState = function(state) { RevealWidget.prototype.readPopupState = function(state) {
this.popup = Popup.parseCoordinates(state); var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/,
match = popupLocationRegExp.exec(state);
// Check if the state matches the location regexp // Check if the state matches the location regexp
if(this.popup) { if(match) {
// If so, we're open // If so, we're open
this.isOpen = true; this.isOpen = true;
// Get the location
this.popup = {
left: parseFloat(match[1]),
top: parseFloat(match[2]),
width: parseFloat(match[3]),
height: parseFloat(match[4])
};
} else { } else {
// If not, we're closed // If not, we're closed
this.isOpen = false; this.isOpen = false;

View File

@@ -42,9 +42,6 @@ SelectWidget.prototype.render = function(parent,nextSibling) {
this.execute(); this.execute();
this.renderChildren(parent,nextSibling); this.renderChildren(parent,nextSibling);
this.setSelectValue(); this.setSelectValue();
if(this.selectFocus == "yes") {
this.getSelectDomNode().focus();
}
$tw.utils.addEventListeners(this.getSelectDomNode(),[ $tw.utils.addEventListeners(this.getSelectDomNode(),[
{name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"} {name: "change", handlerObject: this, handlerMethod: "handleChangeEvent"}
]); ]);
@@ -146,7 +143,6 @@ SelectWidget.prototype.execute = function() {
this.selectMultiple = this.getAttribute("multiple", false); this.selectMultiple = this.getAttribute("multiple", false);
this.selectSize = this.getAttribute("size"); this.selectSize = this.getAttribute("size");
this.selectTooltip = this.getAttribute("tooltip"); this.selectTooltip = this.getAttribute("tooltip");
this.selectFocus = this.getAttribute("focus");
// Make the child widgets // Make the child widgets
var selectNode = { var selectNode = {
type: "element", type: "element",
@@ -179,11 +175,6 @@ SelectWidget.prototype.refresh = function(changedTiddlers) {
return true; return true;
// If the target tiddler value has changed, just update setting and refresh the children // If the target tiddler value has changed, just update setting and refresh the children
} else { } else {
if(changedAttributes.class) {
this.selectClass = this.getAttribute("class");
this.getSelectDomNode().setAttribute("class",this.selectClass);
}
var childrenRefreshed = this.refreshChildren(changedTiddlers); var childrenRefreshed = this.refreshChildren(changedTiddlers);
if(changedTiddlers[this.selectTitle] || childrenRefreshed) { if(changedTiddlers[this.selectTitle] || childrenRefreshed) {
this.setSelectValue(); this.setSelectValue();

View File

@@ -70,9 +70,11 @@ TranscludeWidget.prototype.execute = function() {
// Check for recursion // Check for recursion
if(parser) { if(parser) {
if(this.parentWidget && this.parentWidget.hasVariable("transclusion",recursionMarker)) { if(this.parentWidget && this.parentWidget.hasVariable("transclusion",recursionMarker)) {
parseTreeNodes = [{type: "error", attributes: { parseTreeNodes = [{type: "element", tag: "span", attributes: {
"$message": {type: "string", value: $tw.language.getString("Error/RecursiveTransclusion")} "class": {type: "string", value: "tc-error"}
}}]; }, children: [
{type: "text", text: $tw.language.getString("Error/RecursiveTransclusion")}
]}];
} }
} }
// Construct the child widgets // Construct the child widgets

View File

@@ -34,8 +34,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #0000aa external-link-foreground-visited: #0000aa
external-link-foreground: #0000ee external-link-foreground: #0000ee
foreground: #333333 foreground: #333333
highlight-background: #ffff00
highlight-foreground: #000000
message-background: #ecf2ff message-background: #ecf2ff
message-border: #cfd6e6 message-border: #cfd6e6
message-foreground: #547599 message-foreground: #547599

View File

@@ -34,8 +34,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #0000aa external-link-foreground-visited: #0000aa
external-link-foreground: #0000ee external-link-foreground: #0000ee
foreground: #333353 foreground: #333353
highlight-background: #ffff00
highlight-foreground: #000000
message-background: #ecf2ff message-background: #ecf2ff
message-border: #cfd6e6 message-border: #cfd6e6
message-foreground: #547599 message-foreground: #547599

View File

@@ -34,8 +34,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #0000aa external-link-foreground-visited: #0000aa
external-link-foreground: #0000ee external-link-foreground: #0000ee
foreground: #333333 foreground: #333333
highlight-background: #ffff00
highlight-foreground: #000000
message-background: #ecf2ff message-background: #ecf2ff
message-border: #cfd6e6 message-border: #cfd6e6
message-foreground: #547599 message-foreground: #547599

View File

@@ -34,8 +34,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #00a external-link-foreground-visited: #00a
external-link-foreground: #00e external-link-foreground: #00e
foreground: #000 foreground: #000
highlight-background: #ffff00
highlight-foreground: #000000
message-background: <<colour foreground>> message-background: <<colour foreground>>
message-border: <<colour background>> message-border: <<colour background>>
message-foreground: <<colour background>> message-foreground: <<colour background>>

View File

@@ -34,8 +34,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #00a external-link-foreground-visited: #00a
external-link-foreground: #00e external-link-foreground: #00e
foreground: #fff foreground: #fff
highlight-background: #ffff00
highlight-foreground: #000000
message-background: <<colour foreground>> message-background: <<colour foreground>>
message-border: <<colour background>> message-border: <<colour background>>
message-foreground: <<colour background>> message-foreground: <<colour background>>

View File

@@ -32,8 +32,6 @@ external-link-foreground-hover:
external-link-foreground-visited: #BF5AF2 external-link-foreground-visited: #BF5AF2
external-link-foreground: #32D74B external-link-foreground: #32D74B
foreground: #FFFFFF foreground: #FFFFFF
highlight-background: #ffff78
highlight-foreground: #000000
menubar-background: #464646 menubar-background: #464646
menubar-foreground: #ffffff menubar-foreground: #ffffff
message-background: <<colour background>> message-background: <<colour background>>

View File

@@ -36,8 +36,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #0000aa external-link-foreground-visited: #0000aa
external-link-foreground: #0000ee external-link-foreground: #0000ee
foreground: #333333 foreground: #333333
highlight-background: #ffff00
highlight-foreground: #000000
message-background: #ecf2ff message-background: #ecf2ff
message-border: #cfd6e6 message-border: #cfd6e6
message-foreground: #547599 message-foreground: #547599

View File

@@ -40,8 +40,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #313163 external-link-foreground-visited: #313163
external-link-foreground: #555592 external-link-foreground: #555592
foreground: #2D2A23 foreground: #2D2A23
highlight-background: #ffff00
highlight-foreground: #000000
menubar-background: #CDC2A6 menubar-background: #CDC2A6
menubar-foreground: #5A5446 menubar-foreground: #5A5446
message-background: #ECE5CF message-background: #ECE5CF

View File

@@ -41,8 +41,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #d3869b external-link-foreground-visited: #d3869b
external-link-foreground: #8ec07c external-link-foreground: #8ec07c
foreground: #fbf1c7 foreground: #fbf1c7
highlight-background: #ffff79
highlight-foreground: #000000
menubar-background: #504945 menubar-background: #504945
menubar-foreground: <<colour foreground>> menubar-foreground: <<colour foreground>>
message-background: #83a598 message-background: #83a598

View File

@@ -41,8 +41,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #5E81AC external-link-foreground-visited: #5E81AC
external-link-foreground: #8FBCBB external-link-foreground: #8FBCBB
foreground: #d8dee9 foreground: #d8dee9
highlight-background: #ffff78
highlight-foreground: #000000
menubar-background: #2E3440 menubar-background: #2E3440
menubar-foreground: #d8dee9 menubar-foreground: #d8dee9
message-background: #2E3440 message-background: #2E3440

View File

@@ -34,8 +34,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #0000aa external-link-foreground-visited: #0000aa
external-link-foreground: #0000ee external-link-foreground: #0000ee
foreground: #333333 foreground: #333333
highlight-background: #ffff00
highlight-foreground: #000000
message-background: #ecf2ff message-background: #ecf2ff
message-border: #cfd6e6 message-border: #cfd6e6
message-foreground: #547599 message-foreground: #547599

View File

@@ -131,8 +131,6 @@ external-link-background-hover: inherit
external-link-background-visited: inherit external-link-background-visited: inherit
external-link-background: inherit external-link-background: inherit
external-link-foreground-hover: inherit external-link-foreground-hover: inherit
highlight-background: #ffff00
highlight-foreground: #000000
message-border: #cfd6e6 message-border: #cfd6e6
modal-border: #999999 modal-border: #999999
select-tag-background: select-tag-background:

View File

@@ -35,8 +35,6 @@ external-link-foreground: #268bd2
external-link-foreground-hover: external-link-foreground-hover:
external-link-foreground-visited: #268bd2 external-link-foreground-visited: #268bd2
foreground: #839496 foreground: #839496
highlight-background: #ffff78
highlight-foreground: #000000
message-background: #002b36 message-background: #002b36
message-border: #586e75 message-border: #586e75
message-foreground: #839496 message-foreground: #839496

View File

@@ -35,8 +35,6 @@ external-link-foreground: #268bd2
external-link-foreground-hover: inherit external-link-foreground-hover: inherit
external-link-foreground-visited: #268bd2 external-link-foreground-visited: #268bd2
foreground: #657b83 foreground: #657b83
highlight-background: #ffff00
highlight-foreground: #000000
message-background: #fdf6e3 message-background: #fdf6e3
message-border: #93a1a1 message-border: #93a1a1
message-foreground: #657b83 message-foreground: #657b83

View File

@@ -34,8 +34,6 @@ external-link-foreground-hover:
external-link-foreground-visited: external-link-foreground-visited:
external-link-foreground: external-link-foreground:
foreground: rgba(0, 0, 0, 0.87) foreground: rgba(0, 0, 0, 0.87)
highlight-background: #ffff00
highlight-foreground: #000000
message-background: <<colour background>> message-background: <<colour background>>
message-border: <<colour very-muted-foreground>> message-border: <<colour very-muted-foreground>>
message-foreground: rgba(0, 0, 0, 0.54) message-foreground: rgba(0, 0, 0, 0.54)

View File

@@ -34,8 +34,6 @@ external-link-foreground-hover:
external-link-foreground-visited: #7c318c external-link-foreground-visited: #7c318c
external-link-foreground: #9e3eb3 external-link-foreground: #9e3eb3
foreground: rgba(255, 255, 255, 0.7) foreground: rgba(255, 255, 255, 0.7)
highlight-background: #ffff78
highlight-foreground: #000000
message-background: <<colour background>> message-background: <<colour background>>
message-border: <<colour very-muted-foreground>> message-border: <<colour very-muted-foreground>>
message-foreground: rgba(255, 255, 255, 0.54) message-foreground: rgba(255, 255, 255, 0.54)

View File

@@ -43,8 +43,6 @@ external-link-foreground: rgb(179, 179, 255)
external-link-foreground-hover: inherit external-link-foreground-hover: inherit
external-link-foreground-visited: rgb(153, 153, 255) external-link-foreground-visited: rgb(153, 153, 255)
foreground: rgb(179, 179, 179) foreground: rgb(179, 179, 179)
highlight-background: #ffff78
highlight-foreground: #000000
message-background: <<colour tag-foreground>> message-background: <<colour tag-foreground>>
message-border: #96ccff message-border: #96ccff
message-foreground: <<colour tag-background>> message-foreground: <<colour tag-background>>

View File

@@ -42,8 +42,6 @@ external-link-foreground-hover: inherit
external-link-foreground-visited: #0000aa external-link-foreground-visited: #0000aa
external-link-foreground: #0000ee external-link-foreground: #0000ee
foreground: #333333 foreground: #333333
highlight-background: #ffff00
highlight-foreground: #000000
message-background: #ecf2ff message-background: #ecf2ff
message-border: #cfd6e6 message-border: #cfd6e6
message-foreground: #547599 message-foreground: #547599

View File

@@ -4,7 +4,5 @@ title: $:/core/save/all-external-js
\define saveTiddlerFilter() \define saveTiddlerFilter()
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$ [is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
\end \end
\define defaultCoreURL() %24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js \define coreURL() %24%3A%2Fcore%2Ftemplates%2Ftiddlywiki5.js
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}> {{$:/core/templates/tiddlywiki5-external-js.html}}
{{$:/core/templates/tiddlywiki5-external-js.html}}
</$let>

View File

@@ -4,7 +4,5 @@ title: $:/core/save/offline-external-js
\define saveTiddlerFilter() \define saveTiddlerFilter()
[is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$ [is[tiddler]] -[prefix[$:/state/popup/]] -[prefix[$:/temp/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/core]] -[[$:/plugins/tiddlywiki/filesystem]] -[[$:/plugins/tiddlywiki/tiddlyweb]] -[[$:/boot/boot.css]] -[type[application/javascript]library[yes]] -[[$:/boot/boot.js]] -[[$:/boot/bootprefix.js]] +[sort[title]] $(publishFilter)$
\end \end
\define defaultCoreURL() tiddlywikicore-$(version)$.js \define coreURL() tiddlywikicore-$(version)$.js
<$let coreURL={{{ [[coreURL]is[variable]then<coreURL>else<defaultCoreURL>] }}}> {{$:/core/templates/tiddlywiki5-external-js.html}}
{{$:/core/templates/tiddlywiki5-external-js.html}}
</$let>

View File

@@ -18,7 +18,7 @@ tc-page-container tc-page-view-$(storyviewTitle)$ tc-language-$(languageTitle)$
<$navigator story="$:/StoryList" history="$:/HistoryList"> <$navigator story="$:/StoryList" history="$:/HistoryList">
<$transclude tiddler="$:/core/ui/ViewTemplate/body" mode="block"/> <$transclude mode="block"/>
</$navigator> </$navigator>

View File

@@ -2,5 +2,11 @@ title: $:/core/ui/Actions/new-image
tags: $:/tags/Actions tags: $:/tags/Actions
description: create a new image tiddler description: create a new image tiddler
\define get-type()
image/$(imageType)$
\end
\define get-tags() $(textFieldTags)$ $(tagsFieldTags)$
\whitespace trim \whitespace trim
<$action-sendmessage $message="tm-new-tiddler" type={{{ [{$:/config/NewImageType}addprefix[image/]] }}}/> <$vars imageType={{$:/config/NewImageType}} textFieldTags={{$:/config/NewJournal/Tags}} tagsFieldTags={{$:/config/NewJournal/Tags!!tags}}>
<$action-sendmessage $message="tm-new-tiddler" type=<<get-type>> tags=<<get-tags>>/>
</$vars>

View File

@@ -14,8 +14,8 @@ tags: $:/tags/AdvancedSearch/FilterButton
<$linkcatcher actions="<$action-setfield $tiddler='$:/temp/advancedsearch' text=<<navigateTo>>/><$action-setfield $tiddler='$:/temp/advancedsearch/input' text=<<navigateTo>>/><$action-setfield $tiddler='$:/temp/advancedsearch/refresh' text='yes'/><$action-sendmessage $message='tm-focus-selector' $param='.tc-advanced-search input' />"> <$linkcatcher actions="<$action-setfield $tiddler='$:/temp/advancedsearch' text=<<navigateTo>>/><$action-setfield $tiddler='$:/temp/advancedsearch/input' text=<<navigateTo>>/><$action-setfield $tiddler='$:/temp/advancedsearch/refresh' text='yes'/><$action-sendmessage $message='tm-focus-selector' $param='.tc-advanced-search input' />">
<div class="tc-block-dropdown-wrapper"> <div class="tc-block-dropdown-wrapper">
<div class="tc-block-dropdown tc-edit-type-dropdown"> <div class="tc-block-dropdown tc-edit-type-dropdown">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/Filter]!is[draft]]"> <$list filter="[all[shadows+tiddlers]tag[$:/tags/Filter]]">
<$link to={{!!filter}}><$let tv-wikilinks="no"><$transclude field="description"/></$let></$link> <$link to={{!!filter}}><$transclude field="description"/></$link>
</$list> </$list>
</div> </div>
</div> </div>

View File

@@ -20,16 +20,15 @@ caption: {{$:/language/ControlPanel/Basics/Caption}}
\end \end
\whitespace trim \whitespace trim
|tc-max-width tc-edit-max-width|k
|<<lingo Version/Prompt>> |''<<version>>'' | |<<lingo Version/Prompt>> |''<<version>>'' |
|<$link to="$:/SiteTitle"><<lingo Title/Prompt>></$link> |<$edit-text tiddler="$:/SiteTitle" default="" tag="input"/> | |<$link to="$:/SiteTitle"><<lingo Title/Prompt>></$link> |<$edit-text tiddler="$:/SiteTitle" default="" tag="input"/> |
|<$link to="$:/SiteSubtitle"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler="$:/SiteSubtitle" default="" tag="input"/> | |<$link to="$:/SiteSubtitle"><<lingo Subtitle/Prompt>></$link> |<$edit-text tiddler="$:/SiteSubtitle" default="" tag="input"/> |
|<$link to="$:/status/UserName"><<lingo Username/Prompt>></$link> |<$edit-text tiddler="$:/status/UserName" default="" tag="input"/> | |<$link to="$:/status/UserName"><<lingo Username/Prompt>></$link> |<$edit-text tiddler="$:/status/UserName" default="" tag="input"/> |
|<$link to="$:/config/AnimationDuration"><<lingo AnimDuration/Prompt>></$link> |<$edit-text tiddler="$:/config/AnimationDuration" default="" tag="input"/> | |<$link to="$:/config/AnimationDuration"><<lingo AnimDuration/Prompt>></$link> |<$edit-text tiddler="$:/config/AnimationDuration" default="" tag="input"/> |
|<$link to="$:/DefaultTiddlers"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit class="tc-edit-texteditor" tiddler="$:/DefaultTiddlers"/><br>//<<lingo DefaultTiddlers/BottomHint>>// | |<$link to="$:/DefaultTiddlers"><<lingo DefaultTiddlers/Prompt>></$link> |<<lingo DefaultTiddlers/TopHint>><br> <$edit tag="textarea" tiddler="$:/DefaultTiddlers" class="tc-edit-texteditor"/><br>//<<lingo DefaultTiddlers/BottomHint>>// |
|<$link to="$:/language/DefaultNewTiddlerTitle"><<lingo NewTiddler/Title/Prompt>></$link> |<$edit-text tiddler="$:/language/DefaultNewTiddlerTitle" default="" tag="input"/> | |<$link to="$:/language/DefaultNewTiddlerTitle"><<lingo NewTiddler/Title/Prompt>></$link> |<$edit-text tiddler="$:/language/DefaultNewTiddlerTitle" default="" tag="input"/> |
|<$link to="$:/config/NewJournal/Title"><<lingo NewJournal/Title/Prompt>></$link> |<$edit-text tiddler="$:/config/NewJournal/Title" default="" tag="input"/> | |<$link to="$:/config/NewJournal/Title"><<lingo NewJournal/Title/Prompt>></$link> |<$edit-text tiddler="$:/config/NewJournal/Title" default="" tag="input"/> |
|<$link to="$:/config/NewJournal/Text"><<lingo NewJournal/Text/Prompt>></$link> |<$edit tiddler="$:/config/NewJournal/Text" class="tc-edit-texteditor" default=""/> | |<$link to="$:/config/NewJournal/Text"><<lingo NewJournal/Text/Prompt>></$link> |<$edit tiddler="$:/config/NewJournal/Text" tag="textarea" class="tc-edit-texteditor" default=""/> |
|<$link to="$:/config/NewTiddler/Tags"><<lingo NewTiddler/Tags/Prompt>></$link> |<$vars currentTiddler="$:/config/NewTiddler/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}<$list filter="[<currentTiddler>tags[]] +[limit[1]]" variable="ignore"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><<lingo RemoveTags>><$action-listops $tiddler=<<currentTiddler>> $field="text" $subfilter={{{ [<currentTiddler>get[tags]] }}}/><$action-setfield $tiddler=<<currentTiddler>> tags=""/></$button></$list></$vars> | |<$link to="$:/config/NewTiddler/Tags"><<lingo NewTiddler/Tags/Prompt>></$link> |<$vars currentTiddler="$:/config/NewTiddler/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}<$list filter="[<currentTiddler>tags[]] +[limit[1]]" variable="ignore"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><<lingo RemoveTags>><$action-listops $tiddler=<<currentTiddler>> $field="text" $subfilter={{{ [<currentTiddler>get[tags]] }}}/><$action-setfield $tiddler=<<currentTiddler>> tags=""/></$button></$list></$vars> |
|<$link to="$:/config/NewJournal/Tags"><<lingo NewJournal/Tags/Prompt>></$link> |<$vars currentTiddler="$:/config/NewJournal/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}<$list filter="[<currentTiddler>tags[]] +[limit[1]]" variable="ignore"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><<lingo RemoveTags>><$action-listops $tiddler=<<currentTiddler>> $field="text" $subfilter={{{ [<currentTiddler>get[tags]] }}}/><$action-setfield $tiddler=<<currentTiddler>> tags=""/></$button></$list></$vars> | |<$link to="$:/config/NewJournal/Tags"><<lingo NewJournal/Tags/Prompt>></$link> |<$vars currentTiddler="$:/config/NewJournal/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}<$list filter="[<currentTiddler>tags[]] +[limit[1]]" variable="ignore"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><<lingo RemoveTags>><$action-listops $tiddler=<<currentTiddler>> $field="text" $subfilter={{{ [<currentTiddler>get[tags]] }}}/><$action-setfield $tiddler=<<currentTiddler>> tags=""/></$button></$list></$vars> |
|<$link to="$:/config/AutoFocus"><<lingo AutoFocus/Prompt>></$link> |{{$:/snippets/minifocusswitcher}} | |<$link to="$:/config/AutoFocus"><<lingo AutoFocus/Prompt>></$link> |{{$:/snippets/minifocusswitcher}} |

View File

@@ -1,3 +0,0 @@
title: $:/snippets/retain-story-ordering-button
<$button set="$:/DefaultTiddlers" setTo={{$:/config/ControlPanel/Basics/DefaultTiddlers/RetainStory}} ><<currentTiddler>></$button>

View File

@@ -1,12 +1,7 @@
title: $:/core/ui/EditTemplate title: $:/core/ui/EditTemplate
\define delete-edittemplate-state-tiddlers() \define delete-edittemplate-state-tiddlers() <$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix<newFieldValueTiddlerPrefix>] [<newFieldNameInputTiddler>] [<newFieldNameSelectionTiddler>] [<newTagNameTiddler>] [<newTagNameInputTiddler>] [<newTagNameSelectionTiddler>] [<typeInputTiddler>] [<typeSelectionTiddler>]"/>
<$set name="safeNewFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> >
<$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix[$:/temp/NewFieldValue]prefix<safeNewFieldValueTiddlerPrefix>] [<newFieldNameInputTiddler>] [<newFieldNameSelectionTiddler>] [<newTagNameTiddler>] [<newTagNameInputTiddler>] [<newTagNameSelectionTiddler>] [<typeInputTiddler>] [<typeSelectionTiddler>]"/>
</$set>
\end
<!-- Beware this is duplicated from fields.tid. For details see bug #7054 -->
\define get-field-value-tiddler-filter() [subfilter<get-field-editor-filter>sha256[16]addprefix[/]addprefix<newFieldValueTiddlerPrefix>] \define get-field-value-tiddler-filter() [subfilter<get-field-editor-filter>sha256[16]addprefix[/]addprefix<newFieldValueTiddlerPrefix>]
\define get-field-editor-filter() [<newFieldNameTiddler>get[text]else[]] :cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]] :and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}] \define get-field-editor-filter() [<newFieldNameTiddler>get[text]else[]] :cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]] :and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}]
@@ -28,7 +23,7 @@ title: $:/core/ui/EditTemplate
<div <div
data-tiddler-title=<<currentTiddler>> data-tiddler-title=<<currentTiddler>>
data-tags={{!!tags}} data-tags={{!!tags}}
class={{{ [all[shadows+tiddlers]tag[$:/tags/ClassFilters/TiddlerTemplate]!is[draft]] :map:flat[subfilter{!!text}] tc-tiddler-frame tc-tiddler-edit-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}} class={{{ tc-tiddler-frame tc-tiddler-edit-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}}
role="region" role="region"
aria-label={{$:/language/EditTemplate/Caption}}> aria-label={{$:/language/EditTemplate/Caption}}>
<$fieldmangler> <$fieldmangler>

View File

@@ -19,7 +19,7 @@ $:/config/EditorToolbarButtons/Visibility/$(currentTiddler)$
<$transclude tiddler="$:/core/ui/EditTemplate/body/editor" mode="inline"/> <$transclude tiddler="$:/core/ui/EditTemplate/body/editor" mode="inline"/>
<div class="tc-tiddler-preview-preview" data-tiddler-title={{!!draft.title}} data-tags={{!!tags}}> <div class="tc-tiddler-preview-preview">
<$transclude tiddler={{$:/state/editpreviewtype}} mode="inline"> <$transclude tiddler={{$:/state/editpreviewtype}} mode="inline">

View File

@@ -10,10 +10,6 @@ $:/config/EditTemplateFields/Visibility/$(currentField)$
[[hide]] -[title{$(config-title)$}] [[hide]] -[title{$(config-title)$}]
\end \end
<!-- Beware this is duplicated from EditTemplate.tid. For details see bug #7054 -->
\define get-field-value-tiddler-filter() [subfilter<get-field-editor-filter>sha256[16]addprefix[/]addprefix<newFieldValueTiddlerPrefix>]
\define get-field-editor-filter() [<newFieldNameTiddler>get[text]else[]] :cascade[all[shadows+tiddlers]tag[$:/tags/FieldEditorFilter]!is[draft]get[text]] :and[!is[blank]else{$:/core/ui/EditTemplate/fieldEditor/default}]
\define current-tiddler-new-field-selector() \define current-tiddler-new-field-selector()
[data-tiddler-title="$(currentTiddlerCSSescaped)$"] .tc-edit-field-add-name-wrapper input [data-tiddler-title="$(currentTiddlerCSSescaped)$"] .tc-edit-field-add-name-wrapper input
\end \end
@@ -21,9 +17,7 @@ $:/config/EditTemplateFields/Visibility/$(currentField)$
\define new-field-actions() \define new-field-actions()
\whitespace trim \whitespace trim
<$action-sendmessage $message="tm-add-field" $name={{{ [<newFieldNameTiddler>get[text]] }}} $value={{{ [<newFieldNameTiddler>get[text]] :map[subfilter<get-field-value-tiddler-filter>get[text]] }}}/> <$action-sendmessage $message="tm-add-field" $name={{{ [<newFieldNameTiddler>get[text]] }}} $value={{{ [<newFieldNameTiddler>get[text]] :map[subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
<$set name="safeNewFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> > <$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix<newFieldValueTiddlerPrefix>] [<storeTitle>] [<searchListState>]"/>
<$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix[$:/temp/NewFieldValue]prefix<safeNewFieldValueTiddlerPrefix>] [<storeTitle>] [<searchListState>]"/>
</$set>
<$action-sendmessage $message="tm-focus-selector" $param=<<current-tiddler-new-field-selector>>/> <$action-sendmessage $message="tm-focus-selector" $param=<<current-tiddler-new-field-selector>>/>
\end \end
@@ -58,9 +52,7 @@ $:/config/EditTemplateFields/Visibility/$(currentField)$
<$action-sendmessage $message="tm-add-field" <$action-sendmessage $message="tm-add-field"
$name=<<name>> $name=<<name>>
$value={{{ [subfilter<get-field-value-tiddler-filter>get[text]] }}}/> $value={{{ [subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
<$set name="safeNewFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> > <$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix<newFieldValueTiddlerPrefix>] [<storeTitle>] [<searchListState>]"/>
<$action-deletetiddler $filter="[<newFieldNameTiddler>] [prefix[$:/temp/NewFieldValue]prefix<safeNewFieldValueTiddlerPrefix>] [<storeTitle>] [<searchListState>]"/>
</$set>
<<lingo Fields/Add/Button>> <<lingo Fields/Add/Button>>
</$button> </$button>
</$reveal> </$reveal>
@@ -73,7 +65,6 @@ $value={{{ [subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
\end \end
\whitespace trim \whitespace trim
<$set name="newFieldValueTiddlerPrefix" value=<<newFieldValueTiddlerPrefix>> emptyValue=<<qualify "$:/temp/NewFieldValue">> >
<div class="tc-edit-fields"> <div class="tc-edit-fields">
<table class={{{ [all[current]fields[]] :filter[lookup[$:/config/EditTemplateFields/Visibility/]!match[hide]] +[count[]!match[0]] +[then[tc-edit-fields]] ~[[tc-edit-fields tc-edit-fields-small]] }}}> <table class={{{ [all[current]fields[]] :filter[lookup[$:/config/EditTemplateFields/Visibility/]!match[hide]] +[count[]!match[0]] +[then[tc-edit-fields]] ~[[tc-edit-fields tc-edit-fields-small]] }}}>
<tbody> <tbody>
@@ -157,4 +148,3 @@ $value={{{ [subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
</$vars> </$vars>
</div> </div>
</$fieldmangler> </$fieldmangler>
</$set>

View File

@@ -117,15 +117,15 @@ title: $:/core/ui/ImportListing
</div> </div>
</td> </td>
</$reveal> </$reveal>
<$reveal type="match" text="yes" state=<<previewPopupState>> tag="tr"> <tr>
<td colspan="3"> <td colspan="3">
<$reveal type="match" text="yes" state=<<previewPopupState>> tag="div">
<$list filter="[{$:/state/importpreviewtype}has[text]]" variable="listItem" emptyMessage={{$:/core/ui/ImportPreviews/Text}}> <$list filter="[{$:/state/importpreviewtype}has[text]]" variable="listItem" emptyMessage={{$:/core/ui/ImportPreviews/Text}}>
<div> <$transclude tiddler={{$:/state/importpreviewtype}}/>
<$transclude tiddler={{$:/state/importpreviewtype}}/>
</div>
</$list> </$list>
</td>
</$reveal> </$reveal>
</td>
</tr>
</$list> </$list>
</tbody> </tbody>
</table> </table>

View File

@@ -4,6 +4,6 @@ key: ((advanced-search))
\whitespace trim \whitespace trim
<$navigator story="$:/StoryList" history="$:/HistoryList"> <$navigator story="$:/StoryList" history="$:/HistoryList">
<$action-navigate $to="$:/AdvancedSearch" $scroll="yes"/> <$action-navigate $to="$:/AdvancedSearch"/>
<$action-sendmessage $message="tm-focus-selector" $param="""[data-tiddler-title="$:/AdvancedSearch"] .tc-search input""" preventScroll="true"/> <$action-sendmessage $message="tm-focus-selector" $param="""[data-tiddler-title="$:/AdvancedSearch"] .tc-search input""" preventScroll="true"/>
</$navigator> </$navigator>

View File

@@ -1,15 +0,0 @@
title: $:/core/ui/Buttons/layout
tags: $:/tags/PageControls
caption: {{$:/core/images/layout-button}} {{$:/language/Buttons/LayoutSwitcher/Caption}}
description: {{$:/language/LayoutSwitcher/Description}}
\whitespace trim
<$button tooltip={{$:/language/Buttons/LayoutSwitcher/Hint}} aria-label={{$:/language/Buttons/LayoutSwitcher/Caption}} class=<<tv-config-toolbar-class>>>
<$action-sendmessage $message="tm-show-switcher" switch="layout"/>
<$list filter="[<tv-config-toolbar-icons>match[yes]]">
{{$:/core/images/layout-button}}
</$list>
<$list filter="[<tv-config-toolbar-text>match[yes]]">
<span class="tc-btn-text"><$text text={{$:/language/Buttons/LayoutSwitcher/Caption}}/></span>
</$list>
</$button>

View File

@@ -3,6 +3,9 @@ name: {{$:/language/PageTemplate/Name}}
description: {{$:/language/PageTemplate/Description}} description: {{$:/language/PageTemplate/Description}}
\whitespace trim \whitespace trim
\define containerClasses()
tc-page-container tc-page-view-$(storyviewTitle)$ tc-language-$(languageTitle)$
\end
\import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] \import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]]
<$vars <$vars
@@ -14,7 +17,7 @@ description: {{$:/language/PageTemplate/Description}}
storyviewTitle={{$:/view}} storyviewTitle={{$:/view}}
languageTitle={{{ [{$:/language}get[name]] }}}> languageTitle={{{ [{$:/language}get[name]] }}}>
<div class={{{ [all[shadows+tiddlers]tag[$:/tags/ClassFilters/PageTemplate]!is[draft]] :map:flat[subfilter{!!text}] tc-page-container [[tc-page-view-]addsuffix<storyviewTitle>] [[tc-language-]addsuffix<languageTitle>] :and[unique[]join[ ]] }}} > <div class=<<containerClasses>>>
<$navigator story="$:/StoryList" history="$:/HistoryList" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}> <$navigator story="$:/StoryList" history="$:/HistoryList" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}>

View File

@@ -3,6 +3,6 @@ tags: $:/tags/SideBar
caption: {{$:/language/SideBar/More/Caption}} caption: {{$:/language/SideBar/More/Caption}}
\whitespace trim \whitespace trim
<div class={{{ [{$:/config/ui/SideBar/More/horizontal}match[yes]then[tc-sidebar-tabs]else[tc-more-sidebar]] }}}> <div class="tc-more-sidebar">
<$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]" default={{$:/config/DefaultMoreSidebarTab}} state="$:/state/tab/moresidebar" class={{{ [{$:/config/ui/SideBar/More/horizontal}match[yes]then[tc-sidebar-tabs-more]else[tc-vertical tc-sidebar-tabs-more]] }}} explicitState="$:/state/tab/moresidebar-1850697562"/> <$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/MoreSideBar]!has[draft.of]]" default={{$:/config/DefaultMoreSidebarTab}} state="$:/state/tab/moresidebar" class="tc-vertical tc-sidebar-tabs-more" explicitState="$:/state/tab/moresidebar-1850697562"/>
</div> </div>

View File

@@ -1,7 +1,6 @@
title: $:/core/ui/SwitcherModal title: $:/core/ui/SwitcherModal
subtitle: <$text text={{{[<switch>lookup[$:/language/Switcher/Subtitle/]]}}}/> subtitle: <$text text={{{[<switch>lookup[$:/language/Switcher/Subtitle/]]}}}/>
class: tc-modal-centered class: tc-modal-centered
mask-closable: yes
<$tiddler tiddler={{{[<switch>lookup[$:/config/SwitcherTargets/]]}}}> <$tiddler tiddler={{{[<switch>lookup[$:/config/SwitcherTargets/]]}}}>

View File

@@ -3,101 +3,89 @@ icon: $:/core/images/tag-button
color: #bbb color: #bbb
\define lingo-base() $:/language/TagManager/ \define lingo-base() $:/language/TagManager/
\define iconEditorTab(type) \define iconEditorTab(type)
\whitespace trim \whitespace trim
<$link to=""><<lingo Icons/None>></$link> <$link to=""><<lingo Icons/None>></$link>
<$list filter="[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[sort[title]] +[$type$is[system]]"> <$list filter="[all[shadows+tiddlers]is[image]] [all[shadows+tiddlers]tag[$:/tags/Image]] -[type[application/pdf]] +[sort[title]] +[$type$is[system]]">
<$link to={{!!title}}> <$link to={{!!title}}>
<$transclude/> <$view field="title"/> <$transclude/> <$view field="title"/>
</$link> </$link>
</$list> </$list>
\end \end
\define iconEditor(title) \define iconEditor(title)
\whitespace trim \whitespace trim
<div class="tc-drop-down-wrapper"> <div class="tc-drop-down-wrapper">
<$button popupTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} class="tc-btn-invisible tc-btn-dropdown"> <$button popupTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} class="tc-btn-invisible tc-btn-dropdown">{{$:/core/images/down-arrow}}</$button>
{{$:/core/images/down-arrow}} <$reveal stateTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} type="popup" position="belowleft" text="" default="">
</$button> <div class="tc-drop-down">
<$reveal stateTitle={{{ [[$:/state/popup/icon/]addsuffix<__title__>] }}} type="popup" position="belowleft" text="" default=""> <$linkcatcher actions="""<$action-setfield $tiddler=<<__title__>> icon=<<navigateTo>>/>""">
<div class="tc-drop-down"> <<iconEditorTab type:"!">>
<$linkcatcher actions="""<$action-setfield $tiddler=<<__title__>> icon=<<navigateTo>>/>"""> <hr/>
<<iconEditorTab type:"!">> <<iconEditorTab type:"">>
<hr/> </$linkcatcher>
<<iconEditorTab type:"">> </div>
</$linkcatcher> </$reveal>
</div>
</$reveal>
</div> </div>
\end \end
\define toggleButton(state) \define toggleButton(state)
\whitespace trim \whitespace trim
<$reveal stateTitle=<<__state__>> type="match" text="closed" default="closed"> <$reveal stateTitle=<<__state__>> type="match" text="closed" default="closed">
<$button setTitle=<<__state__>> setTo="open" class="tc-btn-invisible tc-btn-dropdown" selectedClass="tc-selected"> <$button setTitle=<<__state__>> setTo="open" class="tc-btn-invisible tc-btn-dropdown" selectedClass="tc-selected">
{{$:/core/images/info-button}} {{$:/core/images/info-button}}
</$button> </$button>
</$reveal> </$reveal>
<$reveal stateTitle=<<__state__>> type="match" text="open" default="closed"> <$reveal stateTitle=<<__state__>> type="match" text="open" default="closed">
<$button setTitle=<<__state__>> setTo="closed" class="tc-btn-invisible tc-btn-dropdown" selectedClass="tc-selected"> <$button setTitle=<<__state__>> setTo="closed" class="tc-btn-invisible tc-btn-dropdown" selectedClass="tc-selected">
{{$:/core/images/info-button}} {{$:/core/images/info-button}}
</$button> </$button>
</$reveal> </$reveal>
\end \end
\whitespace trim \whitespace trim
<table class="tc-tag-manager-table"> <table class="tc-tag-manager-table">
<tbody> <tbody>
<tr> <tr>
<th><<lingo Colour/Heading>></th> <th><<lingo Colour/Heading>></th>
<th class="tc-tag-manager-tag"><<lingo Tag/Heading>></th> <th class="tc-tag-manager-tag"><<lingo Tag/Heading>></th>
<th><<lingo Count/Heading>></th> <th><<lingo Count/Heading>></th>
<th><<lingo Icon/Heading>></th> <th><<lingo Icon/Heading>></th>
<th><<lingo Info/Heading>></th> <th><<lingo Info/Heading>></th>
</tr> </tr>
<$list filter="[tags[]!is[system]sort[title]]"> <$list filter="[tags[]!is[system]sort[title]]">
<tr> <tr>
<td><$edit-text field="color" tag="input" type="color"/></td> <td><$edit-text field="color" tag="input" type="color"/></td>
<td>{{||$:/core/ui/TagTemplate}}</td> <td>{{||$:/core/ui/TagTemplate}}</td>
<td><$count filter="[all[current]tagging[]]"/></td> <td><$count filter="[all[current]tagging[]]"/></td>
<td> <td>
<$macrocall $name="iconEditor" title={{!!title}}/> <$macrocall $name="iconEditor" title={{!!title}}/>
</td> </td>
<td> <td>
<$macrocall $name="toggleButton" state={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} /> <$macrocall $name="toggleButton" state={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} />
</td> </td>
</tr> </tr>
<tr> <tr>
<td></td> <td></td>
<td colspan="4"> <td colspan="4">
<$reveal stateTitle={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} type="match" text="open" default=""> <$reveal stateTitle={{{ [[$:/state/tag-manager/]addsuffix<currentTiddler>] }}} type="match" text="open" default="">
<table> <table>
<tbody> <tbody>
<tr> <tr><td><<lingo Colour/Heading>></td><td><$edit-text field="color" tag="input" type="text" size="9"/></td></tr>
<td><<lingo Colour/Heading>></td> <tr><td><<lingo Icon/Heading>></td><td><$edit-text field="icon" tag="input" size="45"/></td></tr>
<td><$edit-text field="color" tag="input" type="text" size="9"/></td> </tbody>
</tr> </table>
<tr> </$reveal>
<td><<lingo Icon/Heading>></td> </td>
<td><$edit-text field="icon" tag="input" size="45"/></td> </tr>
</tr> </$list>
</tbody> <tr>
</table> <td></td>
</$reveal> <td style="position:relative;">
</td> {{$:/core/ui/UntaggedTemplate}}
</tr> </td>
</$list> <td>
<tr> <small class="tc-menu-list-count"><$count filter="[untagged[]!is[system]] -[tags[]]"/></small>
<td></td> </td>
<td style="position:relative;"> <td></td>
{{$:/core/ui/UntaggedTemplate}} <td></td>
</td> </tr>
<td>
<small class="tc-menu-list-count"><$count filter="[untagged[]!is[system]] -[tags[]]"/></small>
</td>
<td></td>
<td></td>
</tr>
</tbody> </tbody>
</table> </table>

View File

@@ -7,7 +7,7 @@ $:/state/folded/$(currentTiddler)$
\define cancel-delete-tiddler-actions(message) <$action-sendmessage $message="tm-$message$-tiddler"/> \define cancel-delete-tiddler-actions(message) <$action-sendmessage $message="tm-$message$-tiddler"/>
\import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]] \import [all[shadows+tiddlers]tag[$:/tags/Macro/View]!has[draft.of]]
<$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify "$:/state/popup/tiddler-info">>> <$vars storyTiddler=<<currentTiddler>> tiddlerInfoState=<<qualify "$:/state/popup/tiddler-info">>>
<div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ [all[shadows+tiddlers]tag[$:/tags/ClassFilters/TiddlerTemplate]!is[draft]] :map:flat[subfilter{!!text}] tc-tiddler-frame tc-tiddler-view-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[shadow]is[tiddler]then[tc-tiddler-overridden-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}} role="article"> <div data-tiddler-title=<<currentTiddler>> data-tags={{!!tags}} class={{{ tc-tiddler-frame tc-tiddler-view-frame [<currentTiddler>is[tiddler]then[tc-tiddler-exists]] [<currentTiddler>is[missing]!is[shadow]then[tc-tiddler-missing]] [<currentTiddler>is[shadow]then[tc-tiddler-exists tc-tiddler-shadow]] [<currentTiddler>is[shadow]is[tiddler]then[tc-tiddler-overridden-shadow]] [<currentTiddler>is[system]then[tc-tiddler-system]] [{!!class}] [<currentTiddler>tags[]encodeuricomponent[]addprefix[tc-tagged-]] +[join[ ]] }}} role="article">
<$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]" variable="listItem"> <$list filter="[all[shadows+tiddlers]tag[$:/tags/ViewTemplate]!has[draft.of]]" variable="listItem">
<$transclude tiddler=<<listItem>>/> <$transclude tiddler=<<listItem>>/>
</$list> </$list>

View File

@@ -2,21 +2,17 @@ title: $:/core/ui/ViewTemplate/unfold
tags: $:/tags/ViewTemplate tags: $:/tags/ViewTemplate
\whitespace trim \whitespace trim
<div class="tc-reveal"> <$reveal tag="div" type="nomatch" state="$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar" text="hide">
<$list filter="[{$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar}match[show]]" variable="ignore">
<$reveal tag="div" type="nomatch" stateTitle=<<folded-state>> text="hide" default="show" retain="yes" animate="yes"> <$reveal tag="div" type="nomatch" stateTitle=<<folded-state>> text="hide" default="show" retain="yes" animate="yes">
<$button tooltip={{$:/language/Buttons/Fold/Hint}} aria-label={{$:/language/Buttons/Fold/Caption}} class="tc-fold-banner"> <$button tooltip={{$:/language/Buttons/Fold/Hint}} aria-label={{$:/language/Buttons/Fold/Caption}} class="tc-fold-banner">
<$action-sendmessage $message="tm-fold-tiddler" $param=<<currentTiddler>> foldedState=<<folded-state>>/> <$action-sendmessage $message="tm-fold-tiddler" $param=<<currentTiddler>> foldedState=<<folded-state>>/>
{{$:/core/images/chevron-up}} {{$:/core/images/chevron-up}}
</$button> </$button>
</$reveal> </$reveal>
</$list>
<$list filter="[{$:/config/ViewToolbarButtons/Visibility/$:/core/ui/Buttons/fold-bar}match[show]] :else[<folded-state>get[text]match[hide]]" variable="ignore">
<$reveal tag="div" type="nomatch" stateTitle=<<folded-state>> text="show" default="show" retain="yes" animate="yes"> <$reveal tag="div" type="nomatch" stateTitle=<<folded-state>> text="show" default="show" retain="yes" animate="yes">
<$button tooltip={{$:/language/Buttons/Unfold/Hint}} aria-label={{$:/language/Buttons/Unfold/Caption}} class="tc-unfold-banner"> <$button tooltip={{$:/language/Buttons/Unfold/Hint}} aria-label={{$:/language/Buttons/Unfold/Caption}} class="tc-unfold-banner">
<$action-sendmessage $message="tm-fold-tiddler" $param=<<currentTiddler>> foldedState=<<folded-state>>/> <$action-sendmessage $message="tm-fold-tiddler" $param=<<currentTiddler>> foldedState=<<folded-state>>/>
{{$:/core/images/chevron-down}} {{$:/core/images/chevron-down}}
</$button> </$button>
</$reveal> </$reveal>
</$list> </$reveal>
</div>

View File

@@ -1,3 +0,0 @@
title: $:/config/ControlPanel/Basics/DefaultTiddlers/RetainStory
[list[$:/StoryList]]

View File

@@ -21,5 +21,4 @@ core/ui/Buttons/print: hide
core/ui/Buttons/storyview: hide core/ui/Buttons/storyview: hide
core/ui/Buttons/timestamp: hide core/ui/Buttons/timestamp: hide
core/ui/Buttons/theme: hide core/ui/Buttons/theme: hide
core/ui/Buttons/layout: hide
core/ui/Buttons/unfold-all: hide core/ui/Buttons/unfold-all: hide

View File

@@ -1,21 +1,21 @@
title: $:/core/macros/list title: $:/core/macros/list
tags: $:/tags/Macro tags: $:/tags/Macro
\define list-links(filter,type:"ul",subtype:"li",class:"",emptyMessage,field:"caption") \define list-links(filter,type:"ul",subtype:"li",class:"",emptyMessage)
\whitespace trim \whitespace trim
<$genesis $type=<<__type__>> class=<<__class__>>> <$type$ class="$class$">
<$list filter=<<__filter__>> emptyMessage=<<__emptyMessage__>>> <$list filter="$filter$" emptyMessage=<<__emptyMessage__>>>
<$genesis $type=<<__subtype__>>> <$subtype$>
<$link to={{!!title}}> <$link to={{!!title}}>
<$let tv-wikilinks="no"> <$let tv-wikilinks="no">
<$transclude field=<<__field__>>> <$transclude field="caption">
<$view field="title"/> <$view field="title"/>
</$transclude> </$transclude>
</$let> </$let>
</$link> </$link>
</$genesis> </$subtype$>
</$list> </$list>
</$genesis> </$type$>
\end \end
\define list-links-draggable-drop-actions() \define list-links-draggable-drop-actions()

View File

@@ -3,11 +3,14 @@ modified: 20141212110330815
tags: $:/tags/Macro tags: $:/tags/Macro
title: $:/core/macros/timeline title: $:/core/macros/timeline
<!-- Override one or both of the following two macros with a global or local macro of the same name \define timeline-title()
if you need to change how titles are displayed on a timeline --> \whitespace trim
<!-- Override this macro with a global macro
\define timeline-title() <$view field="title"/> of the same name if you need to change
\define timeline-link() <$link to={{!!title}}><<timeline-title>></$link> how titles are displayed on the timeline
-->
<$view field="title"/>
\end
\define timeline(limit:"100",format:"DDth MMM YYYY",subfilter:"",dateField:"modified") \define timeline(limit:"100",format:"DDth MMM YYYY",subfilter:"",dateField:"modified")
\whitespace trim \whitespace trim
<div class="tc-timeline"> <div class="tc-timeline">
@@ -16,7 +19,7 @@ if you need to change how titles are displayed on a timeline -->
<$view field="$dateField$" format="date" template="$format$"/> <$view field="$dateField$" format="date" template="$format$"/>
<$list filter="[sameday:$dateField${!!$dateField$}!is[system]$subfilter$!sort[$dateField$]]"> <$list filter="[sameday:$dateField${!!$dateField$}!is[system]$subfilter$!sort[$dateField$]]">
<div class="tc-menu-list-subitem"> <div class="tc-menu-list-subitem">
<<timeline-link>> <$link to={{!!title}}><<timeline-title>></$link>
</div> </div>
</$list> </$list>
</div> </div>

View File

@@ -1,10 +1,6 @@
title: $:/core/macros/toc title: $:/core/macros/toc
tags: $:/tags/Macro tags: $:/tags/Macro
\define toc-open-icon() $:/core/images/down-arrow
\define toc-closed-icon() $:/core/images/right-arrow
\define toc-caption() \define toc-caption()
\whitespace trim \whitespace trim
<span class="tc-toc-caption tc-tiny-gap-left"> <span class="tc-toc-caption tc-tiny-gap-left">
@@ -49,12 +45,12 @@ tags: $:/tags/Macro
<$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}> <$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}>
<$reveal type="nomatch" stateTitle=<<toc-state>> text="open"> <$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
<$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep"> <$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
<$transclude tiddler=<<toc-closed-icon>> /> {{$:/core/images/right-arrow}}
</$button> </$button>
</$reveal> </$reveal>
<$reveal type="match" stateTitle=<<toc-state>> text="open"> <$reveal type="match" stateTitle=<<toc-state>> text="open">
<$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep"> <$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
<$transclude tiddler=<<toc-open-icon>> /> {{$:/core/images/down-arrow}}
</$button> </$button>
</$reveal> </$reveal>
<<toc-caption>> <<toc-caption>>
@@ -75,13 +71,13 @@ tags: $:/tags/Macro
<li class=<<toc-item-class>>> <li class=<<toc-item-class>>>
<$reveal type="nomatch" stateTitle=<<toc-state>> text="open"> <$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
<$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep"> <$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
<$transclude tiddler=<<toc-closed-icon>> /> {{$:/core/images/right-arrow}}
<<toc-caption>> <<toc-caption>>
</$button> </$button>
</$reveal> </$reveal>
<$reveal type="match" stateTitle=<<toc-state>> text="open"> <$reveal type="match" stateTitle=<<toc-state>> text="open">
<$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep"> <$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
<$transclude tiddler=<<toc-open-icon>> /> {{$:/core/images/down-arrow}}
<<toc-caption>> <<toc-caption>>
</$button> </$button>
</$reveal> </$reveal>
@@ -121,12 +117,12 @@ tags: $:/tags/Macro
<$list filter="[all[current]tagging[]$sort$limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button>"> <$list filter="[all[current]tagging[]$sort$limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button>">
<$reveal type="nomatch" stateTitle=<<toc-state>> text="open"> <$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
<$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep"> <$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
<$transclude tiddler=<<toc-closed-icon>> /> {{$:/core/images/right-arrow}}
</$button> </$button>
</$reveal> </$reveal>
<$reveal type="match" stateTitle=<<toc-state>> text="open"> <$reveal type="match" stateTitle=<<toc-state>> text="open">
<$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep"> <$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
<$transclude tiddler=<<toc-open-icon>> /> {{$:/core/images/down-arrow}}
</$button> </$button>
</$reveal> </$reveal>
</$list> </$list>
@@ -148,13 +144,13 @@ tags: $:/tags/Macro
<$list filter="[all[current]tagging[]$sort$limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button> <$view field='caption'><$view field='title'/></$view>"> <$list filter="[all[current]tagging[]$sort$limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button> <$view field='caption'><$view field='title'/></$view>">
<$reveal type="nomatch" stateTitle=<<toc-state>> text="open"> <$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
<$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep"> <$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
<$transclude tiddler=<<toc-closed-icon>> /> {{$:/core/images/right-arrow}}
<<toc-caption>> <<toc-caption>>
</$button> </$button>
</$reveal> </$reveal>
<$reveal type="match" stateTitle=<<toc-state>> text="open"> <$reveal type="match" stateTitle=<<toc-state>> text="open">
<$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep"> <$button setTitle=<<toc-state>> setTo="close" class="tc-btn-invisible tc-popup-keep">
<$transclude tiddler=<<toc-open-icon>> /> {{$:/core/images/down-arrow}}
<<toc-caption>> <<toc-caption>>
</$button> </$button>
</$reveal> </$reveal>

View File

@@ -1,2 +1,2 @@
title: $:/tags/PageControls title: $:/tags/PageControls
list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/layout]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]] list: [[$:/core/ui/Buttons/home]] [[$:/core/ui/Buttons/close-all]] [[$:/core/ui/Buttons/fold-all]] [[$:/core/ui/Buttons/unfold-all]] [[$:/core/ui/Buttons/permaview]] [[$:/core/ui/Buttons/new-tiddler]] [[$:/core/ui/Buttons/new-journal]] [[$:/core/ui/Buttons/new-image]] [[$:/core/ui/Buttons/import]] [[$:/core/ui/Buttons/export-page]] [[$:/core/ui/Buttons/control-panel]] [[$:/core/ui/Buttons/advanced-search]] [[$:/core/ui/Buttons/manager]] [[$:/core/ui/Buttons/tag-manager]] [[$:/core/ui/Buttons/language]] [[$:/core/ui/Buttons/palette]] [[$:/core/ui/Buttons/theme]] [[$:/core/ui/Buttons/storyview]] [[$:/core/ui/Buttons/encryption]] [[$:/core/ui/Buttons/timestamp]] [[$:/core/ui/Buttons/full-screen]] [[$:/core/ui/Buttons/print]] [[$:/core/ui/Buttons/save-wiki]] [[$:/core/ui/Buttons/refresh]] [[$:/core/ui/Buttons/more-page-actions]]

View File

@@ -1,5 +1,5 @@
created: 20190115173333457 created: 20190115173333457
modified: 20221029175754753 modified: 20190115173723915
tags: TableOfContents tags: TableOfContents
title: HelloThere title: HelloThere
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
@@ -15,7 +15,6 @@ Welcome to the developer documentation for TiddlyWiki (https://tiddlywiki.com/).
** [[Using ES2016 for Writing Plugins]] ** [[Using ES2016 for Writing Plugins]]
** [[Adding Babel Polyfill to TiddlyWiki]] ** [[Adding Babel Polyfill to TiddlyWiki]]
** [[TiddlyWiki Drag and Drop Interoperability]] ** [[TiddlyWiki Drag and Drop Interoperability]]
** [[Javascript Widget Tutorial]]
* The original developer documentation from https://tiddlywiki.com: * The original developer documentation from https://tiddlywiki.com:
** [[TiddlyWiki for Developers]] ** [[TiddlyWiki for Developers]]
** [[TiddlyWiki Coding Style Guidelines]] ** [[TiddlyWiki Coding Style Guidelines]]

View File

@@ -1,42 +0,0 @@
created: 20221114225038703
modified: 20221114230502925
tags: howto
title: How to run a local plugin library for testing
type: text/vnd.tiddlywiki
!! Start the Library Server
The "pluginlibrary" edition contains the components needed to set up a local server for ~TiddlyWiki plugin library testing or development.
The following commands will create the library files and start a test server at http://localhost:8888
```
cd /your/path/to/TiddlyWiki5/editions/pluginlibrary
tiddlywiki --build test-server
```
!! Important
''This server is read-only. Nothing is saved back to the filesystem''
!! Test the Library with a Single File Wiki
* Open a single file wiki and import the configuration tiddler form http://localhost:8888/#%24%3A%2Fconfig%2FLocalPluginLibrary
* Open the ''$:/ControlPanel : Plugins : "Get More Plugins"'' modal
!! Test the Library with a Node.js Wiki
* Create a new wiki with eg:
<<<
```
cd /temp/
tiddlywiki my-wiki --init server
tiddlywiki my-wiki --listen
```
<<<
* Open "my-wiki" from http://localhost:8080
* Import the http://localhost:8888/#%24%3A%2Fconfig%2FLocalPluginLibrary tiddler into "my-wiki"
* Open the ''$:/ControlPanel : Plugins : "Get More Plugins"'' modal

View File

@@ -1,140 +0,0 @@
created: 20190202160512541
modified: 20190222231130254
title: Child widgets tutorial
type: text/vnd.tiddlywiki
\define showTrees(wikitext)
<table>
<thead>
<tr><th>wiki text</th><th>html</th><th>renders as</th></tr>
</thead>
<tbody>
<tr>
<td>`$wikitext$`</td>
<td>
<$wikify name=html text="""$wikitext$""" output=html mode=inline>
<$text text=<<html>>/>
</$wikify>
</td>
<td>$wikitext$</td>
</tr>
</tbody>
</table>
<table>
<thead>
<tr><th>parse tree</th><th>widget tree</th></tr>
</thead>
<tbody>
<tr>
<td style="vertical-align: text-top">
<pre><code>
<$wikify name=parsetree text="""$wikitext$""" output=parsetree mode=inline>
<<parsetree>>
</$wikify>
</code></pre>
</td>
<td style="vertical-align: text-top">
<pre><code>
<$wikify name=widgettree text="""$wikitext$""" output=widgettree mode=inline>
<<widgettree>>
</$wikify>
</code></pre>
</td>
</tr>
</tbody>
</table>
\end
! Introduction
Until now the examples have covered only simple, leaf widgets, but widgets can be arranged into a hierarchy. Compared to a leaf-only widget, widget classes which support having children must contain code to instantiate the children.
Not all widgets need to support having children. Widgets whose only purpose is to integrate third party javascript libraries, for example may not need it.
! wiki text ⇨ parse tree ⇨ widget tree ⇨ DOM tree
# [[wiki text|https://tiddlywiki.com/#WikiText]] - Users write content in tiddlers using wiki text.
# [[parse tree|https://tiddlywiki.com/dev/#ParsingMechanism]] - A parse tree is a JSON data structure describing the wiki text. Wiki text can be converted into a parse tree using `this.wiki.parseText`.
# ''widget tree'' - Most items in the parse tree correspond to one or more items in the widget tree. The `this.makeChildWidgets` method is used to convert the parse tree into a widget tree.
# [[DOM tree|https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction]] - A DOM tree is a standard javascript datastructure used by browsers to display a web page. The `this.renderChildren` method is used to instantiate the widget class and then render each widget in the widget tree. If a given widget will be visible in the browser, then one or more DOM nodes will be created.
!Examples
!! Simple trees without nesting
[[Widgets in wiki text|https://tiddlywiki.com/#Widgets%20in%20WikiText]] have a syntax similar to html (i.e. `<$list/>`). But all [[wiki markup|https://tiddlywiki.com/#WikiText]] is seen by the tiddlywiki code as widgets.
Even a simple string with no special syntax will be treated as a widget. In this case a widget of type `text`:
<<showTrees """hello""">>
The above bare string of text is mostly just a synonym for this widget syntax:
<<showTrees """<$text text=hello/>""">>
Some of the details of the parseTree and widgetTree are different in the two examples, but the general structure is the same and the rendered output is the same.
In these two simple examples, there is no nesting and so no child widgets are created.
!! Trees with one level of nesting
This next example shows the structure for bold wiki syntax. It is still simple, but does introduce one level of nesting: `element`→`text`
The wiki syntax for bold converts to the standard html element `strong`. Any standard html element is represented in tiddlywiki as a widget of type `element`:
<<showTrees """''bold''""">>
Another example showing one level of nesting (`link`→`text`):
<<showTrees """<$link to=atiddler>link</$link>""">>
!!Widgets with no DOM contribution
Not all widgets contribute items to the DOM. The purpose of some widgets is to affect the display of descendant widgets by changing some state. The `$set` widget for example sets a variable which will be accessible to the descendant widgets:
<<showTrees """<$set name=myvar value=hi/>""">>
Nothing is rendered and there is no html, but the parse tree and widget tree contain information about the variable.
!! Dynamic widget children using this.wiki.parseText
In all the examples so far, there has been a close mapping between the nesting structure of the parse tree and the widget tree. If the item is in the parse tree, then it is in the widget tree. If the parse tree item has children, then the widget tree has the same number of children.
However, there are several examples of widgets in which more levels of nesting are created dynamically during the widget rendering process
The `$macrocall` widget is one example:
<<showTrees """<$macrocall $name=now/>""" >>
The parse tree has just a single type=$macrocall element with no children. The widget tree has that same type=$macrocall element, but it also has a child widget which wasn't in the parse tree.
In all cases, the `$macrocall` widget calls the given macro and then calls `this.wiki.parseText` on the output. This results in a new parse tree which is used to make the child widgets.
In this particular case, the `now` macro is called. It returns a simple string of text, so when it is parsed the result causes the creation of a single child text widget containing the current date and time.
!! Widgets which do not support nesting
Just as some widgets can cause widget trees to have more nesting than the parse tree, some widgets can cause widget trees to have less nesting.
This happens when there is no use for the widget to have any children. The `$text` widget, for example, has no use for displaying any descendants.
This behavior is accomplished by not calling the `makeChildWidgets` method. Without that method call, the child widgets are not created from the child parse tree items. For example:
<$macrocall $name=showTrees wikitext="""<$text text="hi">ignored child text</$text>"""/>
Since the `$text` widget does not have a call to `makeChildWidgets`, 'ignored child text' above is present in the parse tree, but not in the widget tree.
!Reference
|!method|!when to call|!what it does|
|`makeChildWidgets`|directly or indirectly from `render` method|converts child parse tree items into widget tree items|
|`renderChildren`|directly or indirectly from `render` method, after the `makeChildWidgets` call|calls the `render` method of the child widget|
|`refreshChildren`|directly or indirectly from `refresh` method, only needed if `refreshSelf` is not called|calls the `refresh` method of of the child widgets so they can check if refresh is needed|
|`this.wiki.parseText`|pass the output parse tree to `makeChildWidgets`|converts the given text to a parse tree...only needed for dynamically constructed parsetree|
|!example call|!purpose|!widgets using this approach|
|`this.makeChildWidgets()`|construct child widgets from the static parse tree|[[$link|$:/core/modules/widgets/link.js]], [[$button|$:/core/modules/widgets/button.js]], etc.|
|`this.makeChildWidgets(parseTreeNodes)`|construct child widgets from a dynamic parse tree|[[$list|$:/core/modules/widgets/list.js]], [[$transclude|$:/core/modules/widgets/transclude.js]], [[$macrocall|$:/core/modules/widgets/macrocall.js]], etc|
|`this.renderChildren(parent, nextSibling)`|when the widget adds nothing to the dom, just pass the `render` arguments through to the children|[[$set|$:/core/modules/widgets/set.js]], [[$importvariables|$:/core/modules/widgets/importvariables.js]], [[$tiddler|$:/core/modules/widgets/tiddler.js]], [[$wikify|$:/core/modules/widgets/wikify.js]], etc.|
|`this.renderChildren(domNode, null)`|passes the dom node generated by this widget into the children|[[$link|$:/core/modules/widgets/link.js]], [[$button|$:/core/modules/widgets/button.js]], etc|

View File

@@ -1,22 +0,0 @@
created: 20190201120100249
modified: 20190201222600576
tags:
title: Do nothing widget demo
type: text/vnd.tiddlywiki
<!-- The innerwiki doesn't refresh on its own when tiddlers on the outside change, so use the list widget to force a dependency -->
<$list name=refresh filter=[[donothing.js]get[text]]>
<$innerwiki width="600" height="400" style="width:100%;">
<$data title="$:/DefaultTiddlers" text="[[do nothing widget]]"/>
<$data $tiddler=donothing.js/>
<$data title="do nothing widget" text="""
```
<$donothing/>
```
Renders as:
<$donothing/>
"""/>
</$innerwiki>
</$list>

View File

@@ -1,25 +0,0 @@
created: 20190201232102417
modified: 20190202145547621
tags:
title: Do nothing widget tutorial
type: text/vnd.tiddlywiki
In order to define a widget in a tiddler, the tiddler must satisfy these requirements:
* type field is application/javascript
* module-type field is widget
* the text field contains the javascript code
The [[donothing.js]] tiddler fulfills the requirements and its code looks like this:
{{donothing.js}}
That code does 2 key things:
* Imports the core Widget class ([[$:/core/modules/widgets/widget.js]])
* exports the class in an attribute with the name we want our widget to have (`donothing`)
Here's what it looks like:
{{Do nothing widget demo}}
And it worked. No error message this time.
''Exercise'': Modify [[donothing.js]] and [[Do nothing widget demo]] so the widget is named `noop` instead of `donothing`

View File

@@ -1,23 +0,0 @@
created: 20190201114718313
modified: 20190201231556294
tags:
title: Hello World demo
type: text/vnd.tiddlywiki
<!-- The innerwiki doesn't refresh on its own when tiddlers on the outside change, so use the list widget to force a dependency -->
<$list name=refresh filter=[[hello.js]get[text]]>
<$innerwiki width="600" height="400" style="width:100%;">
<$data title="$:/DefaultTiddlers" text="[[hello world widget]]"/>
<$data $tiddler=hello.js/>
<$data title="hello world widget" text="""
```
<$hello/>
```
Renders as:
<$hello/>
"""/>
</$innerwiki>
</$list>

View File

@@ -1,18 +0,0 @@
created: 20190201232200698
modified: 20190216175629825
tags:
title: Hello World widget tutorial
type: text/vnd.tiddlywiki
Now let's create a widget which actually has output.
When tiddlywiki encounters a widget definition like `<$hello>` it will create an object which is an instance of the class which is exported by the widget code.
In addition to creating an instance of the class, tiddlywiki will call the render method of the resulting object. The render method is expected to create a dom node which will be display in place of the widget.
In the `donothing` example the core widget was exported. The core widget class doesn't have a render method which creates a dom node and that's why there is no output. Getting output requires writing a widget class which inherits from the core `Widget` class. Code in the render method of this class will display the hello world message.
The [[hello.js]] tiddler has code which accomplishes that:
{{hello.js}}
The code for importing the core widget class remains, but now we also have code to create our own class which inherits from it. In addition an implementation of the `render` method is included. Here is the result:
{{Hello World demo}}

View File

@@ -1,37 +0,0 @@
created: 20190202035524804
modified: 20221029161501848
tags:
title: Javascript Widget Tutorial
type: text/vnd.tiddlywiki
! Introduction
This tutorial provides step-by-step, interactive examples of how to write code for tiddlywiki widgets. The demo javascript code can be modified without having to reload the entire wiki.
Intended audience:
# Those who know tiddlywiki well and know programming and javascript and want to write their own widget. I don't make any effort to explain javascript here. For that you will need other resources.
# Those who know tiddlywiki well and don't know javascript, but want to understand more about how tiddlywiki works. You should be able to skim through and interact with the demos and learn something.
!The tutorial
*[[Undefined widget tutorial]]
*[[Do nothing widget tutorial]]
*[[Hello World widget tutorial]]
*[[Widget refresh tutorial part I]]
*[[Widget refresh tutorial part II]]
*[[Widget refresh tutorial part III]]
*[[Widget attributes tutorial part I]]
*[[Widget attributes tutorial part II]]
*[[Child widgets tutorial]]
! Notes
tiddlywiki doesn't support dynamically reloading javascript. If you change a javascript tiddler, then you need to save and reload the wiki before the changes will take affect.
To avoid the need for such reloads, the excellent [[innerwiki plugin|https://tiddlywiki.com/prerelease/plugins/tiddlywiki/innerwiki/]] is used. This allows an inner wiki to be created from a subset of tiddlers in the outer wiki. Each time the inner wiki is refreshed, its entire wiki is reloaded and the javascript changes in the inner wiki will take affect.
Without the need for reloads, a tiddlywiki instance with the [[innerwiki plugin|https://tiddlywiki.com/prerelease/plugins/tiddlywiki/innerwiki/]] installed works great as a playground for interacting with tiddlywiki javascript.
! Other documentation on writing TW widgets
*WidgetModules
*[[Widgets]]

View File

@@ -1,18 +0,0 @@
created: 20190201212238781
modified: 20190201213112748
tags:
title: Undefined widget demo
type: text/vnd.tiddlywiki
<$innerwiki width="600" height="400" style="width:100%;">
<$data title="$:/DefaultTiddlers" text="[[Undefined widget]]"/>
<$data title="Undefined widget" text="""
```
<$donothing/>
```
Renders as:
<$donothing/>
"""/>
</$innerwiki>

View File

@@ -1,11 +0,0 @@
created: 20190201232001970
modified: 20190202145655413
tags:
title: Undefined widget tutorial
type: text/vnd.tiddlywiki
Let's start be defining a minimal widget which does nothing. It doesn't support any attributes, no child elements, and it doesn't output anything. The name of the widget will be `donothing`. If it does nothing, then how can we verify after writing the code that we accomplished anything? Well, let's see what happens when an undefined widget is referenced.
{{Undefined widget demo}}
Since we haven't written the code, the attempt to render the widget gives an undefined widget error. So we will know the donothing code accomplishes something if we don't get the undefined widget error when rendering.

View File

@@ -1,48 +0,0 @@
created: 20190204020507195
modified: 20190204031520013
tags:
title: Widget attributes demo I
type: text/vnd.tiddlywiki
<!-- The innerwiki doesn't refresh on its own when tiddlers on the outside change, so use the list widget to force a dependency -->
<$list name=refresh filter=[[hello-attribute.js]get[text]]>
<$innerwiki width="600" height="400" style="width:100%;">
<$data title="$:/DefaultTiddlers" text="[[hello world widget]]"/>
<$data $tiddler=hello-attribute.js/>
<$data title="hello world widget" text="""
```
<$hello/>
```
Renders as:
<$hello/>
---
```
<$hello message="pale blue dot"/>
```
Renders as:
<$hello message="pale blue dot"/>
---
<$edit-text focus=yes tiddler=test tag=input/>
```
<$hello message={{test!!text}}/>
```
Renders as:
<$hello message={{test!!text}}/>
"""/>
<$data title="test" text="Alice"/>
</$innerwiki>
</$list>

View File

@@ -1,48 +0,0 @@
created: 20190205024953535
modified: 20190205025028737
tags:
title: Widget attributes demo II
type: text/vnd.tiddlywiki
<!-- The innerwiki doesn't refresh on its own when tiddlers on the outside change, so use the list widget to force a dependency -->
<$list name=refresh filter=[[hello-attribute-optimized.js]get[text]]>
<$innerwiki width="600" height="400" style="width:100%;">
<$data title="$:/DefaultTiddlers" text="[[hello world widget]]"/>
<$data $tiddler=hello-attribute-optimized.js/>
<$data title="hello world widget" text="""
```
<$hello/>
```
Renders as:
<$hello/>
---
```
<$hello message="pale blue dot"/>
```
Renders as:
<$hello message="pale blue dot"/>
---
<$edit-text focus=yes tiddler=test tag=input/>
```
<$hello message={{test!!text}}/>
```
Renders as:
<$hello message={{test!!text}}/>
"""/>
<$data title="test" text="Alice"/>
</$innerwiki>
</$list>

View File

@@ -1,50 +0,0 @@
created: 20190202035425715
modified: 20190205023518575
tags:
title: Widget attributes tutorial part I
type: text/vnd.tiddlywiki
So far none of the widgets we've implemented have had any code for handling widget attributes A vast majority of useful widgets will need to support attributes in order to make them useful.
As an example, let's change the Hello World widget so it can greet not just the world, but whoever/whatever the user wants. To do that we can add support for an attribute named `what` and call it like `<$hello what="pale blue dot"/>`.
The tiddlywiki widget class provides methods `computeAttributes` and `getAttribute` which can together be used by the widget code to discover what values are passed into the widget.
The `computeAttributes` and `getAttribute` methods can be called like this (the second parameter to `getAttribute` will be used as the default value if the user doesn't provide that attribute in the widget call):
```javascript
this.computeAttributes();
var message = this.getAttribute("message", "World");
```
Then the `message` variable can be used to construct the Hello XXX string:
```javascript
var textNode = this.document.createTextNode("Hello, " + message + "!");
```
The original [[hello.js]] code only implements a `render` method. The `refresh` method is not needed because the output from the widget can never be different...it will always be "Hello, World!".
Even with a `message` attribute, you might think the `render` by itself is enough. After all, the value of the input parameter `message` can only be changed by modifying the wiki text which means the tiddler will be redisplayed from scratch.
However, tiddlywiki has a syntax which allows parameter values to vary without modifying the wiki text. See https://tiddlywiki.com/#Widgets%20in%20WikiText for details. As one example, if the widget were called like `<$hello message={{MyTiddler!!field}}/>`, then every time the `field` field of `MyTiddler` were modified, only the `refresh` method would be called. Therefore, in order to get the widget display to update, the refresh method needs to be implemented.
If the `computeAttributes` and `getAttribute` calls are placed in the `render` method then we can implement a performance unoptimized version of refresh as was done in [[Widget refresh tutorial part II]]:
```javascript
/*
A widget with optimized performance will selectively refresh, but here we refresh always
*/
MyWidget.prototype.refresh = function(changedTiddlers) {
// Regenerate and rerender the widget and
// replace the existing DOM node
this.refreshSelf();
return true;
};
```
The full code can be seen at [[hello-attribute.js]] and here is the result ([[Widget attributes demo I]]):
{{Widget attributes demo I}}
The third example above is the only one which requires the refresh method in order to behave properly.

View File

@@ -1,33 +0,0 @@
created: 20190205023543910
modified: 20190217012121130
tags:
title: Widget attributes tutorial part II
type: text/vnd.tiddlywiki
This example will build on the previous one. The only modification will be to add a check to the `refresh` method. The `refreshSelf` will only be called if a change to the attributes is detected.
The `computeAttributes` method returns a Javascript object containing properties for each attribute which has changed. So a check like `if (changedAttributes.attr1 || changedAttributes.attr2 || changedAttributes.attr3)` etc. can be used to detect the change. See the refresh method in [[$:/core/modules/widgets/view.js]] for an example showing the check for multiple attributes.
For this example, `message` is the only attribute implemented.
```javascript
/*
Refresh if the attribute value changed since render
*/
MyWidget.prototype.refresh = function(changedTiddlers) {
// Find which attributes have changed
var changedAttributes = this.computeAttributes();
if (changedAttributes.message) {
this.refreshSelf();
return true;
} else {
return false;
}
};
```
The full code can be seen at [[hello-attribute-optimized.js]] and here is the result ([[Widget attributes demo II]]):
{{Widget attributes demo II}}
The visible behavior here should be identical to the unoptimized behavior of the previous tutorial.

View File

@@ -1,44 +0,0 @@
created: 20190201233806976
modified: 20221029194854112
tags:
title: Widget refresh demo I
type: text/vnd.tiddlywiki
<!-- The innerwiki doesn't refresh on its own when tiddlers on the outside change, so use the list widget to force a dependency -->
<$list name=refresh filter=[[tiddlerfield-norefresh.js]get[text]]>
<$innerwiki width="600" height="400" style="width:100%;">
<$data title="$:/DefaultTiddlers" text="[[tiddler field widget]]"/>
<$data title="test" text="type new text here"/>
<$data $tiddler=tiddlerfield-norefresh.js/>
<$data title="tiddler field widget" text="""
<$edit-text focus=yes tiddler=test tag=input/>
<$button set="!!refresh" setTo={{test}}>Force refresh</$button>
<$list filter="[{!!refresh}]">
<div>
<div style="display:inline-block;width: 49%;vertical-align: text-top;word-wrap: break-word;}">
```
<$tiddlerfield/>
```
Renders as:
<$tiddlerfield/>
</div>
<div style="display:inline-block;width: 49%;vertical-align: text-top;word-wrap: break-word;}">
```
<$view tiddler="test"/>
```
Renders as:
<$view tiddler="test"/>
</div>
</div>
</$list>
"""/>
</$innerwiki>
</$list>

View File

@@ -1,40 +0,0 @@
created: 20190202032354223
modified: 20190217005540498
tags:
title: Widget refresh demo II
type: text/vnd.tiddlywiki
<!-- The innerwiki doesn't refresh on its own when tiddlers on the outside change, so use the list widget to force a dependency -->
<$list name=refresh filter=[[tiddlerfield.js]get[text]]>
<$innerwiki width="600" height="400" style="width:100%;">
<$data title="$:/DefaultTiddlers" text="[[tiddler field widget]]"/>
<$data title="test" text="type new text here"/>
<$data $tiddler=tiddlerfield.js/>
<$data title="tiddler field widget" text="""
<$edit-text focus=yes tiddler=test tag=input/>
<div>
<div style="display:inline-block;width: 49%;vertical-align: text-top;word-wrap: break-word;}">
```
<$tiddlerfield/>
```
Renders as:
<$tiddlerfield/>
</div>
<div style="display:inline-block;width: 49%;vertical-align: text-top;word-wrap: break-word;}">
```
<$view tiddler="test"/>
```
Renders as:
<$view tiddler="test"/>
</div>
"""/>
</$innerwiki>
</$list>

View File

@@ -1,50 +0,0 @@
created: 20190202122928187
modified: 20190216191939585
tags:
title: Widget refresh demo III
type: text/vnd.tiddlywiki
<!-- The innerwiki doesn't refresh on its own when tiddlers on the outside change, so use the list widget to force a dependency -->
<$list name=refresh filter=[[refreshcount.js]get[text]]>
<$innerwiki width="600" height="400" style="width:100%;">
<$data title="$:/DefaultTiddlers" text="[[refresh count widget]]"/>
<$data title="test" text="Text field of tiddler='test'"/>
<$data $tiddler=refreshcount.js/>
<$data title="refresh count widget" text="""
*<$button set="test!!test" setTo="hello">Modify a different tiddler</$button>
*<$button set="!!test" setTo="hello">Modify this tiddler</$button>
*<$edit-text focus=yes tiddler=test tag=input/>
<div>
<div style="display:inline-block;width: 49%;vertical-align: text-top;word-wrap: break-word;}">
```
<$refreshcount/>
```
Renders as:
<$refreshcount/>
</div>
<div style="display:inline-block;width: 49%;vertical-align: text-top;word-wrap: break-word;}">
```
<$list filter="[[test]get[text]]">
<<currentTiddler>><br>
<$refreshcount/>
</$list>
```
Renders as:
<$list filter="[[test]get[text]]">
<<currentTiddler>><br>
<$refreshcount/>
</$list>
"""/>
</div>
</div>
</$innerwiki>
</$list>

View File

@@ -1,47 +0,0 @@
created: 20190201232847949
modified: 20221029203553291
tags:
title: Widget refresh tutorial part I
type: text/vnd.tiddlywiki
But what if we want to display dynamic content? How can we display information and keep it up to date as it changes? Let's display the content of a tiddler field.
The [[tiddlerfield-norefresh.js]] which defines the `tiddlerfield` widget is almost the same as [[hello.js]] except for this part:
```javascript
MyWidget.prototype.render = function(parent,nextSibling) {
this.parentDomNode = parent;
var text = this.wiki.getTiddlerText("test", "<empty>")
var textNode = this.document.createTextNode(text);
parent.insertBefore(textNode,nextSibling);
this.domNodes.push(textNode);
};
```
Instead of creating the text dom node from a static string, the text field of the `test` tiddler is used. This is similar to using the view widget like this: `<$view tiddler="test"/>`
Here's how it looks (see [[Widget refresh demo I]] to look at the code):
{{Widget refresh demo I}}
Notice if you change the text in the input box, the output from the `tiddlerfield` widget doesn't change, but the output of the `view` widget does. Only after the ''Force refresh'' button is clicked does the output of `tiddlerfield` update to match the input box contents.
What's going on here? The render method of the widget code is only called by tiddlywiki core when the widget is first created. After that, it isn't called again unless the widget is completely destroyed and then created again.
The tiddlywiki ~ViewWidget has a properly written `refresh` method so typing in the input box will cause its content to update. However, the `tiddlerfield` widget does not have a `refresh` method at all. It has no way of being notified that the `test` tiddler content has changed. Its output will not change until the ''Force refresh'' button is clicked.
See the next example for an implementation of the `refresh` method for the `tiddlerfield` widget.
The code for the refresh button looks like this:
```
<$button set="!!refresh" setTo={{test}}>Force refresh</$button>
```
and the widgets are enclosed in a list widget like this:
```
<$list filter="[{!!refresh}]">...</$list>
```
When the button is clicked the field `refresh` in the containing tiddler is modified and it causes the children of the list widget to be created from scratch. The render method is called and the output of the `tiddlerfield` widget updates.

View File

@@ -1,37 +0,0 @@
created: 20190201232910076
modified: 20190217014335419
tags:
title: Widget refresh tutorial part II
type: text/vnd.tiddlywiki
This example is like [[Widget refresh tutorial part I]] except the widget output will be automatically refreshed when the tiddler field changes.
[[tiddlerfield.js]] is the same as [[tiddlerfield-norefresh.js]], except this `refresh` method is added:
```javascript
/*
A widget with optimized performance will selectively refresh, but here we refresh always
*/
MyWidget.prototype.refresh = function(changedTiddlers) {
// Regenerate and rerender the widget and
// replace the existing DOM node
this.refreshSelf();
return true;
};
```
The `refreshSelf` method called above is implemented by the core widget class and it takes care of cleaning the old dom node and calling the render function.
Here is the result ([[Widget refresh demo II]]):
{{Widget refresh demo II}}
And now any typing into the input box will cause both the `tiddlerfield` and the `view` widget output to refresh immediately.
Note this is a naive version of `refresh`. It unconditionally refreshes itself. This is far from optimal since the `refresh` method for all visible widgets is called every time the tiddler store changes. But the way we've defined our widget, the output ONLY depends on the tiddler titled `text`.
In tiddlywiki the tiddler store is used for everything and almost any interaction will result in an update to the store. This means almost any interaction will cause the refresh method to be called. If you type into the search box, for example, the `tiddlerfield` widget will be refreshed with every keystroke.
Adding and removing dom elements is a relatively expensive operation, so if someone has used the list widget to create a few hundred instances of this widget, then such tiddlywiki interactions might gain a noticable lag. Therefore, it usually makes sense to avoid modifying the dom when possible by writing a smarter `refresh` method.
''Exercise'' - change the refresh method above to only call `refreshSelf` when the `changedTiddlers` input array contains `test` as one of its entries (Hint: see the refresh method in $:/core/modules/widgets/view.js for an example).

View File

@@ -1,26 +0,0 @@
created: 20190202034841184
modified: 20221029201023638
tags:
title: Widget refresh tutorial part III
type: text/vnd.tiddlywiki
This tutorial is intended to demonstrate a few examples of when calls to the `refresh` method happen vs. when a widget is recreated from scratch.
This is accomplished with a [[refreshcount.js]] widget which sets a counter to zero when the widget is created and increments the counter every time the `refresh` method is called. Here is the full code:
{{refreshcount.js}}
These are the key parts of the code from above:
```javascript
this.refreshCount = 0;
this.document.createTextNode(this.refreshCount + " refreshes");
this.refreshCount++;
```
In the following example (see [[Widget refresh demo III]] for the code), two instances of the `refreshcount` widget are created. One at the top level and the other inside a list widget whose filter results depend on the value in the `text` field of the `test` widget. The tiddler store can be modified in a few ways via two buttons and an input box:
{{Widget refresh demo III}}
* ''Modify a different tiddler'' - every time this button is clicked, both counters increment, indicating the `refresh` method is being called
* ''Modify this tiddler'' - clicking this button modifies the tiddler itself. In earlier ~TiddlyWiki versions that caused both widgets to be recreated from scratch and the counters are thereby reset to zero. Since [[version 5.2.0|https://tiddlywiki.com/#Release%205.2.0]] modifying another field in this tiddler does not cause the widgets to be recreated and the counters are not reset.
* ''Text field of tiddler='test''' - typing text into the input box causes the counter in the standalone `refreshcount` widget to be incremented. But the other instance of the widget is embedded inside a list widget whose filter output depends on the value of the tiddler field which is being modified. This causes it to recreate its children from scratch and the counter is reset every time. So with every keystroke, the counter on the left is incremented, but the counter on the right goes to/stays at zero.

Some files were not shown because too many files have changed in this diff Show More