1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-07-08 04:54:23 +00:00

Refactored macro interface

Now 'this' points to the Renderer.MacroNode
This commit is contained in:
Jeremy Ruston 2012-02-21 21:57:30 +00:00
parent 1d007ce6d5
commit bf6f5e0254
11 changed files with 101 additions and 98 deletions

View File

@ -30,7 +30,7 @@ Node.prototype.render =
Node.prototype.renderInDom = Node.prototype.renderInDom =
Node.prototype.refresh = Node.prototype.refresh =
Node.prototype.refreshInDom = function() { Node.prototype.refreshInDom = function() {
// All these methods are noops by default // All these methods are no-ops by default
}; };
/* /*
@ -107,7 +107,7 @@ MacroNode.prototype.execute = function(parents,tiddler) {
// Save a reference to the array of parents // Save a reference to the array of parents
this.parents = parents || []; this.parents = parents || [];
// Render the macro to get its content // Render the macro to get its content
this.content = this.macro.execute(this,tiddler,this.store); this.content = this.macro.execute.call(this);
}; };
MacroNode.prototype.render = function(type) { MacroNode.prototype.render = function(type) {
@ -132,7 +132,7 @@ MacroNode.prototype.renderInDom = function(domNode,insertBefore) {
// Add event handlers to the node // Add event handlers to the node
var self = this, var self = this,
dispatchMacroEvent = function(event) { dispatchMacroEvent = function(event) {
self.macro.events[event.type](event,self); self.macro.events[event.type].call(self,event);
}; };
for(var e in this.macro.events) { for(var e in this.macro.events) {
macroContainer.addEventListener(e,dispatchMacroEvent,false); macroContainer.addEventListener(e,dispatchMacroEvent,false);
@ -167,7 +167,7 @@ MacroNode.prototype.refreshInDom = function(changes) {
// Ask the macro to rerender itself if it can // Ask the macro to rerender itself if it can
var tiddler = this.store.getTiddler(this.tiddlerTitle); var tiddler = this.store.getTiddler(this.tiddlerTitle);
if(this.macro.refresh) { if(this.macro.refresh) {
this.macro.refresh(changes,this,tiddler,this.store); this.macro.refresh.call(this,changes);
} else { } else {
// Manually reexecute and rerender this macro // Manually reexecute and rerender this macro
while(this.domNode.hasChildNodes()) { while(this.domNode.hasChildNodes()) {

View File

@ -15,8 +15,8 @@ exports.macro = {
params: { params: {
text: {byPos: 0, type: "text"} text: {byPos: 0, type: "text"}
}, },
execute: function(macroNode,tiddler,store) { execute: function() {
return [Renderer.TextNode(macroNode.params.text)]; return [Renderer.TextNode(this.params.text)];
} }
}; };

View File

@ -17,26 +17,26 @@ exports.macro = {
text: {byName: true, type: "text"}, text: {byName: true, type: "text"},
alignment: {byName: true, type: "text"} alignment: {byName: true, type: "text"}
}, },
execute: function(macroNode,tiddler,store) { execute: function() {
if(store.tiddlerExists(macroNode.params.src)) { if(this.store.tiddlerExists(this.params.src)) {
var imageTree = store.parseTiddler(macroNode.params.src).tree, var imageTree = this.store.parseTiddler(this.params.src).tree,
cloneImage = []; cloneImage = [];
for(var t=0; t<imageTree.length; t++) { for(var t=0; t<imageTree.length; t++) {
cloneImage.push(imageTree[t].clone()); cloneImage.push(imageTree[t].clone());
} }
if(macroNode.params.text) { if(this.params.text) {
return [Renderer.ElementNode("div",{ return [Renderer.ElementNode("div",{
alt: macroNode.params.text, alt: this.params.text,
title: macroNode.params.text title: this.params.text
},cloneImage)]; },cloneImage)];
} else { } else {
return cloneImage; return cloneImage;
} }
} else { } else {
return [Renderer.ElementNode("img",{ return [Renderer.ElementNode("img",{
href: macroNode.params.src, href: this.params.src,
alt: macroNode.params.text, alt: this.params.text,
title: macroNode.params.text title: this.params.text
})]; })];
} }
} }

View File

@ -21,28 +21,28 @@ exports.macro = {
target: {byName: "default", type: "tiddler", skinny: true} target: {byName: "default", type: "tiddler", skinny: true}
}, },
events: { events: {
click: function(event,macroNode) { click: function(event) {
if(isLinkExternal(macroNode.params.target)) { if(isLinkExternal(this.params.target)) {
event.target.setAttribute("target","_blank"); event.target.setAttribute("target","_blank");
return true; return true;
} else { } else {
var navEvent = document.createEvent("Event"); var navEvent = document.createEvent("Event");
navEvent.initEvent("tw-navigate",true,true); navEvent.initEvent("tw-navigate",true,true);
navEvent.navigateTo = macroNode.params.target; navEvent.navigateTo = this.params.target;
event.target.dispatchEvent(navEvent); event.target.dispatchEvent(navEvent);
event.preventDefault(); event.preventDefault();
return false; return false;
} }
} }
}, },
execute: function(macroNode,tiddler,store) { execute: function() {
var classes = ["tw-tiddlylink"], var classes = ["tw-tiddlylink"],
target = macroNode.params.target; target = this.params.target;
if(isLinkExternal(target)) { if(isLinkExternal(target)) {
classes.push("tw-tiddlylink-external"); classes.push("tw-tiddlylink-external");
} else { } else {
classes.push("tw-tiddlylink-internal"); classes.push("tw-tiddlylink-internal");
if(store.tiddlerExists(target)) { if(this.store.tiddlerExists(target)) {
classes.push("tw-tiddlylink-resolves"); classes.push("tw-tiddlylink-resolves");
} else { } else {
classes.push("tw-tiddlylink-missing"); classes.push("tw-tiddlylink-missing");
@ -53,9 +53,9 @@ exports.macro = {
"a",{ "a",{
href: target, href: target,
"class": classes "class": classes
},macroNode.cloneChildren())]; },this.cloneChildren())];
for(var t=0; t<content.length; t++) { for(var t=0; t<content.length; t++) {
content[t].execute(macroNode.parents,tiddler); content[t].execute(this.parents,this.store.getTiddler(this.tiddlerTitle));
} }
return content; return content;
} }

View File

@ -41,33 +41,33 @@ exports.macro = {
template: {byName: true, type: "tiddler"}, template: {byName: true, type: "tiddler"},
emptyMessage: {byName: true, type: "text"} emptyMessage: {byName: true, type: "text"}
}, },
execute: function(macroNode,tiddler,store) { execute: function() {
var templateType = "text/x-tiddlywiki", var templateType = "text/x-tiddlywiki",
templateText = "<<view title link>>", templateText = "<<view title link>>",
template = macroNode.params.template ? store.getTiddler(macroNode.params.template) : null, template = this.params.template ? this.store.getTiddler(this.params.template) : null,
content = [], content = [],
t, t,
parents = macroNode.parents; parents = this.parents;
if(template) { if(template) {
parents = parents.slice(0); parents = parents.slice(0);
parents.push(template.title); parents.push(template.title);
templateType = template.type; templateType = template.type;
templateText = template.text; templateText = template.text;
} }
var handler = handlers[macroNode.params.type]; var handler = handlers[this.params.type];
handler = handler || handlers.all; handler = handler || handlers.all;
var tiddlers = handler(store); var tiddlers = handler(this.store);
if(tiddlers.length === 0) { if(tiddlers.length === 0) {
return [Renderer.TextNode(macroNode.params.emptyMessage || "")]; return [Renderer.TextNode(this.params.emptyMessage || "")];
} else { } else {
var templateTree = store.parseText(templateType,templateText).tree; var templateTree = this.store.parseText(templateType,templateText).tree;
for(t=0; t<tiddlers.length; t++) { for(t=0; t<tiddlers.length; t++) {
var cloneTemplate = []; var cloneTemplate = [];
for(var c=0; c<templateTree.length; c++) { for(var c=0; c<templateTree.length; c++) {
cloneTemplate.push(templateTree[c].clone()); cloneTemplate.push(templateTree[c].clone());
} }
var listNode = Renderer.ElementNode("li",null,cloneTemplate); var listNode = Renderer.ElementNode("li",null,cloneTemplate);
listNode.execute(parents,store.getTiddler(tiddlers[t])); listNode.execute(parents,this.store.getTiddler(tiddlers[t]));
content.push(listNode); content.push(listNode);
} }
return [Renderer.ElementNode("ul",null,content)]; return [Renderer.ElementNode("ul",null,content)];

View File

@ -22,13 +22,13 @@ exports.macro = {
tooltip: {byPos: 3, type: "text"} tooltip: {byPos: 3, type: "text"}
}, },
events: { events: {
click: function(event,macroNode) { click: function(event) {
if(event.target === event.currentTarget.firstChild.firstChild) { if(event.target === event.currentTarget.firstChild.firstChild) {
var el = event.currentTarget.firstChild.firstChild.nextSibling, var el = event.currentTarget.firstChild.firstChild.nextSibling,
stateTiddler = macroNode.params.state ? macroNode.store.getTiddler(macroNode.params.state) : null; stateTiddler = this.params.state ? this.store.getTiddler(this.params.state) : null;
stateTiddler = stateTiddler || new Tiddler({title: macroNode.params.state, text: ""}); stateTiddler = stateTiddler || new Tiddler({title: this.params.state, text: ""});
var isOpen = stateTiddler.text.trim() === "open"; var isOpen = stateTiddler.text.trim() === "open";
macroNode.store.addTiddler(new Tiddler(stateTiddler,{text: isOpen ? "closed" : "open"})); this.store.addTiddler(new Tiddler(stateTiddler,{text: isOpen ? "closed" : "open"}));
event.preventDefault(); event.preventDefault();
return false; return false;
} else { } else {
@ -36,30 +36,30 @@ exports.macro = {
} }
} }
}, },
execute: function(macroNode,tiddler,store) { execute: function() {
var isOpen = macroNode.params.state ? store.getTiddlerText(macroNode.params.state,"").trim() === "open" : true, var isOpen = this.params.state ? this.store.getTiddlerText(this.params.state,"").trim() === "open" : true,
target = macroNode.params.targetTiddler; target = this.params.targetTiddler;
var content = Renderer.SliderNode(macroNode.params.state, var content = Renderer.SliderNode(this.params.state,
macroNode.params.label ? macroNode.params.label : target, this.params.label ? this.params.label : target,
macroNode.params.tooltip, this.params.tooltip,
isOpen, isOpen,
[ [
Renderer.MacroNode( Renderer.MacroNode(
"tiddler", "tiddler",
{target: target}, {target: target},
null, null,
store) this.store)
]); ]);
content.execute(macroNode.parents,tiddler); content.execute(this.parents,this.store.getTiddler(this.tiddlerText));
return [content]; return [content];
}, },
refresh: function(changes,macroNode,tiddler,store) { refresh: function(changes) {
if(macroNode.params.target && changes.hasOwnProperty(macroNode.params.target) !== -1) { if(this.params.target && changes.hasOwnProperty(this.params.target) !== -1) {
// If the target has changed, re-render the macro // If the target has changed, re-render the macro
} else if (macroNode.params.state && changes.hasOwnProperty(macroNode.params.state) !== -1) { } else if (this.params.state && changes.hasOwnProperty(this.params.state) !== -1) {
// If it was just the state tiddler that's changed, set the display appropriately // If it was just the state tiddler that's changed, set the display appropriately
var el = macroNode.domNode.firstChild.firstChild.nextSibling, var el = this.domNode.firstChild.firstChild.nextSibling,
isOpen = macroNode.store.getTiddlerText(macroNode.params.state,"").trim() === "open"; isOpen = this.store.getTiddlerText(this.params.state,"").trim() === "open";
el.style.display = isOpen ? "block" : "none"; el.style.display = isOpen ? "block" : "none";
} }
} }

View File

@ -33,9 +33,9 @@ exports.macro = {
template: {byName: true, type: "tiddler"} template: {byName: true, type: "tiddler"}
}, },
events: { events: {
"tw-navigate": function(event,macroNode) { "tw-navigate": function(event) {
var storyTiddler = macroNode.store.getTiddler(macroNode.params.story); var storyTiddler = this.store.getTiddler(this.params.story);
macroNode.store.addTiddler(new Tiddler(storyTiddler,{text: event.navigateTo + "\n" + storyTiddler.text})); this.store.addTiddler(new Tiddler(storyTiddler,{text: event.navigateTo + "\n" + storyTiddler.text}));
$("html,body").animate({ $("html,body").animate({
scrollTop: 0 scrollTop: 0
}, 400); }, 400);
@ -43,28 +43,29 @@ exports.macro = {
return false; return false;
} }
}, },
execute: function(macroNode,tiddler,store) { execute: function() {
var tiddlers = parseStory(store.getTiddlerText(macroNode.params.story)), var tiddlers = parseStory(this.store.getTiddlerText(this.params.story)),
content = []; content = [];
for(var t=0; t<tiddlers.length; t++) { for(var t=0; t<tiddlers.length; t++) {
var m = Renderer.MacroNode("tiddler", var m = Renderer.MacroNode("tiddler",
{target: tiddlers[t],template: macroNode.params.template}, {target: tiddlers[t],template: this.params.template},
null, null,
store); this.store);
m.execute(macroNode.parents,tiddler); m.execute(this.parents,this.store.getTiddler(this.tiddlerTitle));
content.push(m); content.push(m);
} }
return content; return content;
}, },
refresh: function(changes,macroNode,tiddler,store) { refresh: function(changes) {
/*jslint browser: true */ /*jslint browser: true */
// Get the tiddlers we're supposed to be displaying // Get the tiddlers we're supposed to be displaying
var targetTiddlers = parseStory(store.getTiddlerText(macroNode.params.story)), var self = this,
template = macroNode.params.template, targetTiddlers = parseStory(this.store.getTiddlerText(this.params.story)),
template = this.params.template,
t,n,domNode, t,n,domNode,
findTiddler = function (childIndex,tiddlerTitle,templateTitle) { findTiddler = function (childIndex,tiddlerTitle,templateTitle) {
while(childIndex < macroNode.content.length) { while(childIndex < self.content.length) {
var params = macroNode.content[childIndex].params; var params = self.content[childIndex].params;
if(params.target === tiddlerTitle) { if(params.target === tiddlerTitle) {
if(!templateTitle || params.template === templateTitle) { if(!templateTitle || params.template === templateTitle) {
return childIndex; return childIndex;
@ -82,32 +83,32 @@ exports.macro = {
var m = Renderer.MacroNode("tiddler", var m = Renderer.MacroNode("tiddler",
{target: targetTiddlers[t],template: template}, {target: targetTiddlers[t],template: template},
null, null,
store); this.store);
m.execute(macroNode.parents,store.getTiddler(targetTiddlers[t])); m.execute(this.parents,this.store.getTiddler(targetTiddlers[t]));
m.renderInDom(macroNode.domNode,macroNode.domNode.childNodes[t]); m.renderInDom(this.domNode,this.domNode.childNodes[t]);
macroNode.content.splice(t,0,m); this.content.splice(t,0,m);
} else { } else {
// Delete any nodes preceding the one we want // Delete any nodes preceding the one we want
if(tiddlerNode > t) { if(tiddlerNode > t) {
// First delete the DOM nodes // First delete the DOM nodes
for(n=t; n<tiddlerNode; n++) { for(n=t; n<tiddlerNode; n++) {
domNode = macroNode.content[n].domNode; domNode = this.content[n].domNode;
domNode.parentNode.removeChild(domNode); domNode.parentNode.removeChild(domNode);
} }
// Then delete the actual renderer nodes // Then delete the actual renderer nodes
macroNode.content.splice(t,tiddlerNode-t); this.content.splice(t,tiddlerNode-t);
} }
// Refresh the DOM node we're reusing // Refresh the DOM node we're reusing
macroNode.content[t].refreshInDom(changes); this.content[t].refreshInDom(changes);
} }
} }
// Remove any left over nodes // Remove any left over nodes
if(macroNode.content.length > targetTiddlers.length) { if(this.content.length > targetTiddlers.length) {
for(t=targetTiddlers.length; t<macroNode.content.length; t++) { for(t=targetTiddlers.length; t<this.content.length; t++) {
domNode = macroNode.content[t].domNode; domNode = this.content[t].domNode;
domNode.parentNode.removeChild(domNode); domNode.parentNode.removeChild(domNode);
} }
macroNode.content.splice(targetTiddlers.length,macroNode.content.length-targetTiddlers.length); this.content.splice(targetTiddlers.length,this.content.length-targetTiddlers.length);
} }
} }
}; };

View File

@ -53,13 +53,14 @@ exports.macro = {
template: {byName: true, type: "tiddler"}, template: {byName: true, type: "tiddler"},
"with": {byName: true, type: "text", dependentAll: true} "with": {byName: true, type: "text", dependentAll: true}
}, },
execute: function(macroNode,tiddler,store) { execute: function() {
var renderTitle = macroNode.params.target, var tiddler = this.store.getTiddler(this.tiddlerTitle),
renderTemplate = macroNode.params.template, renderTitle = this.params.target,
renderTemplate = this.params.template,
content, content,
contentClone = [], contentClone = [],
t, t,
parents = macroNode.parents.slice(0); parents = this.parents.slice(0);
if(typeof renderTitle !== "string") { if(typeof renderTitle !== "string") {
renderTitle = tiddler.title; renderTitle = tiddler.title;
} }
@ -67,19 +68,19 @@ exports.macro = {
renderTemplate = renderTitle; renderTemplate = renderTitle;
} }
if(parents.indexOf(renderTemplate) === -1) { if(parents.indexOf(renderTemplate) === -1) {
if("with" in macroNode.params) { if("with" in this.params) {
// Parameterised transclusion // Parameterised transclusion
var targetTiddler = store.getTiddler(renderTemplate), var targetTiddler = this.store.getTiddler(renderTemplate),
text = targetTiddler.text; text = targetTiddler.text;
var withTokens = [macroNode.params["with"]]; var withTokens = [this.params["with"]];
for(t=0; t<withTokens.length; t++) { for(t=0; t<withTokens.length; t++) {
var placeholderRegExp = new RegExp("\\$"+(t+1),"mg"); var placeholderRegExp = new RegExp("\\$"+(t+1),"mg");
text = text.replace(placeholderRegExp,withTokens[t]); text = text.replace(placeholderRegExp,withTokens[t]);
} }
content = store.parseText(targetTiddler.type,text).tree; content = this.store.parseText(targetTiddler.type,text).tree;
} else { } else {
// There's no parameterisation, so we can just render the target tiddler directly // There's no parameterisation, so we can just render the target tiddler directly
var parseTree = store.parseTiddler(renderTemplate); var parseTree = this.store.parseTiddler(renderTemplate);
content = parseTree ? parseTree.tree : []; content = parseTree ? parseTree.tree : [];
} }
} else { } else {
@ -90,7 +91,7 @@ exports.macro = {
contentClone.push(content[t].clone()); contentClone.push(content[t].clone());
} }
for(t=0; t<contentClone.length; t++) { for(t=0; t<contentClone.length; t++) {
contentClone[t].execute(parents,store.getTiddler(renderTitle)); contentClone[t].execute(parents,this.store.getTiddler(renderTitle));
} }
return contentClone; return contentClone;
} }

View File

@ -14,7 +14,7 @@ exports.macro = {
types: ["text/html","text/plain"], types: ["text/html","text/plain"],
params: { params: {
}, },
execute: function(macroNode,tiddler,store) { execute: function() {
return [Renderer.TextNode("5.0.0")]; return [Renderer.TextNode("5.0.0")];
} }
}; };

View File

@ -18,11 +18,11 @@ exports.macro = {
width: {byName: true, type: "text"}, width: {byName: true, type: "text"},
height: {byName: true, type: "text"} height: {byName: true, type: "text"}
}, },
execute: function(macroNode,tiddler,store) { execute: function() {
var src = macroNode.params.src, var src = this.params.src,
videoType = macroNode.params.type || "vimeo", videoType = this.params.type || "vimeo",
videoWidth = macroNode.params.width || 640, videoWidth = this.params.width || 640,
videoHeight = macroNode.params.height || 360; videoHeight = this.params.height || 360;
switch(videoType) { switch(videoType) {
case "vimeo": case "vimeo":
return [Renderer.ElementNode("iframe",{ return [Renderer.ElementNode("iframe",{

View File

@ -19,35 +19,36 @@ exports.macro = {
format: {byPos: 1, type: "text"}, format: {byPos: 1, type: "text"},
template: {byPos: 2, type: "text"} template: {byPos: 2, type: "text"}
}, },
execute: function(macroNode,tiddler,store) { execute: function() {
if(!tiddler) { if(!this.tiddlerTitle) {
return Renderer.TextNode("{{** Missing tiddler **}}"); return Renderer.TextNode("{{** Missing tiddler **}}");
} else { } else {
var v = tiddler[macroNode.params.field], var tiddler = this.store.getTiddler(this.tiddlerTitle),
v = tiddler[this.params.field],
content, content,
t, t,
contentClone = [], contentClone = [],
parents = macroNode.parents; parents = this.parents;
if(v !== undefined) { if(v !== undefined) {
switch(macroNode.params.format) { switch(this.params.format) {
case "link": case "link":
var link = Renderer.MacroNode("link", var link = Renderer.MacroNode("link",
{target: v}, {target: v},
[Renderer.TextNode(v)], [Renderer.TextNode(v)],
store); this.store);
link.execute(parents,tiddler); link.execute(parents,tiddler);
return [link]; return [link];
case "wikified": case "wikified":
if(macroNode.params.field === "text") { if(this.params.field === "text") {
if(parents.indexOf(tiddler.title) === -1) { if(parents.indexOf(tiddler.title) === -1) {
content = store.parseTiddler(tiddler.title).tree; content = this.store.parseTiddler(tiddler.title).tree;
} else { } else {
content = [Renderer.TextNode("{{** Tiddler recursion error in <<view>> macro **}}")]; content = [Renderer.TextNode("{{** Tiddler recursion error in <<view>> macro **}}")];
} }
parents = parents.slice(0); parents = parents.slice(0);
parents.push(tiddler.title); parents.push(tiddler.title);
} else { } else {
content = store.parseText("text/x-tiddlywiki",v).tree; content = this.store.parseText("text/x-tiddlywiki",v).tree;
} }
for(t=0; t<content.length; t++) { for(t=0; t<content.length; t++) {
contentClone.push(content[t].clone()); contentClone.push(content[t].clone());
@ -57,7 +58,7 @@ exports.macro = {
} }
return contentClone; return contentClone;
case "date": case "date":
var template = macroNode.params.template || "DD MMM YYYY"; var template = this.params.template || "DD MMM YYYY";
return [Renderer.TextNode(utils.formatDateString(v,template))]; return [Renderer.TextNode(utils.formatDateString(v,template))];
default: // "text" default: // "text"
return [Renderer.TextNode(v)]; return [Renderer.TextNode(v)];