1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-07-05 03:33:27 +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.refresh =
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
this.parents = parents || [];
// 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) {
@ -132,7 +132,7 @@ MacroNode.prototype.renderInDom = function(domNode,insertBefore) {
// Add event handlers to the node
var self = this,
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) {
macroContainer.addEventListener(e,dispatchMacroEvent,false);
@ -167,7 +167,7 @@ MacroNode.prototype.refreshInDom = function(changes) {
// Ask the macro to rerender itself if it can
var tiddler = this.store.getTiddler(this.tiddlerTitle);
if(this.macro.refresh) {
this.macro.refresh(changes,this,tiddler,this.store);
this.macro.refresh.call(this,changes);
} else {
// Manually reexecute and rerender this macro
while(this.domNode.hasChildNodes()) {

View File

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

View File

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

View File

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

View File

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

View File

@ -22,13 +22,13 @@ exports.macro = {
tooltip: {byPos: 3, type: "text"}
},
events: {
click: function(event,macroNode) {
click: function(event) {
if(event.target === event.currentTarget.firstChild.firstChild) {
var el = event.currentTarget.firstChild.firstChild.nextSibling,
stateTiddler = macroNode.params.state ? macroNode.store.getTiddler(macroNode.params.state) : null;
stateTiddler = stateTiddler || new Tiddler({title: macroNode.params.state, text: ""});
stateTiddler = this.params.state ? this.store.getTiddler(this.params.state) : null;
stateTiddler = stateTiddler || new Tiddler({title: this.params.state, text: ""});
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();
return false;
} else {
@ -36,30 +36,30 @@ exports.macro = {
}
}
},
execute: function(macroNode,tiddler,store) {
var isOpen = macroNode.params.state ? store.getTiddlerText(macroNode.params.state,"").trim() === "open" : true,
target = macroNode.params.targetTiddler;
var content = Renderer.SliderNode(macroNode.params.state,
macroNode.params.label ? macroNode.params.label : target,
macroNode.params.tooltip,
execute: function() {
var isOpen = this.params.state ? this.store.getTiddlerText(this.params.state,"").trim() === "open" : true,
target = this.params.targetTiddler;
var content = Renderer.SliderNode(this.params.state,
this.params.label ? this.params.label : target,
this.params.tooltip,
isOpen,
[
Renderer.MacroNode(
"tiddler",
{target: target},
null,
store)
this.store)
]);
content.execute(macroNode.parents,tiddler);
content.execute(this.parents,this.store.getTiddler(this.tiddlerText));
return [content];
},
refresh: function(changes,macroNode,tiddler,store) {
if(macroNode.params.target && changes.hasOwnProperty(macroNode.params.target) !== -1) {
refresh: function(changes) {
if(this.params.target && changes.hasOwnProperty(this.params.target) !== -1) {
// 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
var el = macroNode.domNode.firstChild.firstChild.nextSibling,
isOpen = macroNode.store.getTiddlerText(macroNode.params.state,"").trim() === "open";
var el = this.domNode.firstChild.firstChild.nextSibling,
isOpen = this.store.getTiddlerText(this.params.state,"").trim() === "open";
el.style.display = isOpen ? "block" : "none";
}
}

View File

@ -33,9 +33,9 @@ exports.macro = {
template: {byName: true, type: "tiddler"}
},
events: {
"tw-navigate": function(event,macroNode) {
var storyTiddler = macroNode.store.getTiddler(macroNode.params.story);
macroNode.store.addTiddler(new Tiddler(storyTiddler,{text: event.navigateTo + "\n" + storyTiddler.text}));
"tw-navigate": function(event) {
var storyTiddler = this.store.getTiddler(this.params.story);
this.store.addTiddler(new Tiddler(storyTiddler,{text: event.navigateTo + "\n" + storyTiddler.text}));
$("html,body").animate({
scrollTop: 0
}, 400);
@ -43,28 +43,29 @@ exports.macro = {
return false;
}
},
execute: function(macroNode,tiddler,store) {
var tiddlers = parseStory(store.getTiddlerText(macroNode.params.story)),
execute: function() {
var tiddlers = parseStory(this.store.getTiddlerText(this.params.story)),
content = [];
for(var t=0; t<tiddlers.length; t++) {
var m = Renderer.MacroNode("tiddler",
{target: tiddlers[t],template: macroNode.params.template},
{target: tiddlers[t],template: this.params.template},
null,
store);
m.execute(macroNode.parents,tiddler);
this.store);
m.execute(this.parents,this.store.getTiddler(this.tiddlerTitle));
content.push(m);
}
return content;
},
refresh: function(changes,macroNode,tiddler,store) {
refresh: function(changes) {
/*jslint browser: true */
// Get the tiddlers we're supposed to be displaying
var targetTiddlers = parseStory(store.getTiddlerText(macroNode.params.story)),
template = macroNode.params.template,
var self = this,
targetTiddlers = parseStory(this.store.getTiddlerText(this.params.story)),
template = this.params.template,
t,n,domNode,
findTiddler = function (childIndex,tiddlerTitle,templateTitle) {
while(childIndex < macroNode.content.length) {
var params = macroNode.content[childIndex].params;
while(childIndex < self.content.length) {
var params = self.content[childIndex].params;
if(params.target === tiddlerTitle) {
if(!templateTitle || params.template === templateTitle) {
return childIndex;
@ -82,32 +83,32 @@ exports.macro = {
var m = Renderer.MacroNode("tiddler",
{target: targetTiddlers[t],template: template},
null,
store);
m.execute(macroNode.parents,store.getTiddler(targetTiddlers[t]));
m.renderInDom(macroNode.domNode,macroNode.domNode.childNodes[t]);
macroNode.content.splice(t,0,m);
this.store);
m.execute(this.parents,this.store.getTiddler(targetTiddlers[t]));
m.renderInDom(this.domNode,this.domNode.childNodes[t]);
this.content.splice(t,0,m);
} else {
// Delete any nodes preceding the one we want
if(tiddlerNode > t) {
// First delete the DOM nodes
for(n=t; n<tiddlerNode; n++) {
domNode = macroNode.content[n].domNode;
domNode = this.content[n].domNode;
domNode.parentNode.removeChild(domNode);
}
// 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
macroNode.content[t].refreshInDom(changes);
this.content[t].refreshInDom(changes);
}
}
// Remove any left over nodes
if(macroNode.content.length > targetTiddlers.length) {
for(t=targetTiddlers.length; t<macroNode.content.length; t++) {
domNode = macroNode.content[t].domNode;
if(this.content.length > targetTiddlers.length) {
for(t=targetTiddlers.length; t<this.content.length; t++) {
domNode = this.content[t].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"},
"with": {byName: true, type: "text", dependentAll: true}
},
execute: function(macroNode,tiddler,store) {
var renderTitle = macroNode.params.target,
renderTemplate = macroNode.params.template,
execute: function() {
var tiddler = this.store.getTiddler(this.tiddlerTitle),
renderTitle = this.params.target,
renderTemplate = this.params.template,
content,
contentClone = [],
t,
parents = macroNode.parents.slice(0);
parents = this.parents.slice(0);
if(typeof renderTitle !== "string") {
renderTitle = tiddler.title;
}
@ -67,19 +68,19 @@ exports.macro = {
renderTemplate = renderTitle;
}
if(parents.indexOf(renderTemplate) === -1) {
if("with" in macroNode.params) {
if("with" in this.params) {
// Parameterised transclusion
var targetTiddler = store.getTiddler(renderTemplate),
var targetTiddler = this.store.getTiddler(renderTemplate),
text = targetTiddler.text;
var withTokens = [macroNode.params["with"]];
var withTokens = [this.params["with"]];
for(t=0; t<withTokens.length; t++) {
var placeholderRegExp = new RegExp("\\$"+(t+1),"mg");
text = text.replace(placeholderRegExp,withTokens[t]);
}
content = store.parseText(targetTiddler.type,text).tree;
content = this.store.parseText(targetTiddler.type,text).tree;
} else {
// 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 : [];
}
} else {
@ -90,7 +91,7 @@ exports.macro = {
contentClone.push(content[t].clone());
}
for(t=0; t<contentClone.length; t++) {
contentClone[t].execute(parents,store.getTiddler(renderTitle));
contentClone[t].execute(parents,this.store.getTiddler(renderTitle));
}
return contentClone;
}

View File

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

View File

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

View File

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