mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-19 16:24:51 +00:00
Refactored list macro
Now does selective refreshing, improving performance in several areas. (Classic TW always refreshed lists in their entirety). A bit more to do, but the plan is that this can replace the story macro, too
This commit is contained in:
parent
3a4288899d
commit
cb3741c8ee
@ -12,73 +12,153 @@ List macro
|
|||||||
/*global $tw: false */
|
/*global $tw: false */
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var handlers = {
|
|
||||||
all: function(wiki) {
|
|
||||||
return wiki.getTiddlers("title","excludeLists");
|
|
||||||
},
|
|
||||||
missing: function(wiki) {
|
|
||||||
return wiki.getMissingTitles();
|
|
||||||
},
|
|
||||||
orphans: function(wiki) {
|
|
||||||
return wiki.getOrphanTitles();
|
|
||||||
},
|
|
||||||
shadowed: function(wiki) {
|
|
||||||
return wiki.getShadowTitles();
|
|
||||||
},
|
|
||||||
touched: function(wiki) {
|
|
||||||
// Server syncing isn't implemented yet
|
|
||||||
return [];
|
|
||||||
},
|
|
||||||
filter: function(wiki) {
|
|
||||||
// Filters aren't implemented yet
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.info = {
|
exports.info = {
|
||||||
name: "list",
|
name: "list",
|
||||||
dependentAll: true, // Tiddlers containing <<list>> macro are dependent on every tiddler
|
dependentAll: true, // Tiddlers containing <<list>> macro are dependent on every tiddler
|
||||||
params: {
|
params: {
|
||||||
type: {byName: "default", type: "text"},
|
type: {byPos: 0, type: "text"},
|
||||||
|
filter: {byName: true, type: "filter"},
|
||||||
template: {byName: true, type: "tiddler"},
|
template: {byName: true, type: "tiddler"},
|
||||||
|
templateText: {byName: true, type: "text"},
|
||||||
|
editTemplate: {byName: true, type: "tiddler"},
|
||||||
|
editTemplateText: {byName: true, type: "text"},
|
||||||
emptyMessage: {byName: true, type: "text"}
|
emptyMessage: {byName: true, type: "text"}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.executeMacro = function() {
|
exports.executeMacro = function() {
|
||||||
var templateType = "text/x-tiddlywiki",
|
// Get the list of tiddlers object
|
||||||
templateText = "<<view title link>>",
|
this.getTiddlerList();
|
||||||
template = this.params.template ? this.wiki.getTiddler(this.params.template) : null,
|
// Create the list frame element
|
||||||
children = [],
|
var attributes = {"class": ["tw-list-frame"]};
|
||||||
t,
|
|
||||||
parents = this.parents,
|
|
||||||
attributes = {};
|
|
||||||
if(template) {
|
|
||||||
parents = parents.slice(0);
|
|
||||||
parents.push(template.title);
|
|
||||||
templateType = template.type;
|
|
||||||
templateText = template.text;
|
|
||||||
}
|
|
||||||
var handler = handlers[this.params.type];
|
|
||||||
handler = handler || handlers.all;
|
|
||||||
var tiddlers = handler(this.wiki,this.tiddlerTitle);
|
|
||||||
if(this.classes) {
|
if(this.classes) {
|
||||||
attributes["class"] = this.classes.slice(0);
|
$tw.utils.pushTop(attributes["class"],this.classes);
|
||||||
}
|
}
|
||||||
if(tiddlers.length === 0) {
|
this.listFrame = $tw.Tree.Element("div",attributes,[]);
|
||||||
return $tw.Tree.Text(this.params.emptyMessage || "");
|
// Create each list element
|
||||||
|
for(var t=0; t<this.list.length; t++) {
|
||||||
|
this.listFrame.children.push(this.createListElement(this.list[t]));
|
||||||
|
}
|
||||||
|
return this.listFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getTiddlerList = function() {
|
||||||
|
this.list = this.wiki.filterTiddlers(this.params.filter,this.tiddlerTitle);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create a list element representing a given tiddler
|
||||||
|
*/
|
||||||
|
exports.createListElement = function(title) {
|
||||||
|
var node = this.createListElementMacro(title),
|
||||||
|
eventHandler = {handleEvent: function(event) {
|
||||||
|
// Add context information to the event
|
||||||
|
event.navigateFromListElement = node;
|
||||||
|
event.navigateFromTitle = title;
|
||||||
|
return true;
|
||||||
|
}};
|
||||||
|
node.execute(this.parents,this.tiddlerTitle);
|
||||||
|
var listElement = $tw.Tree.Element("div",{"class": ["tw-list-element"]},[node],{
|
||||||
|
events: ["tw-navigate","tw-EditTiddler","tw-SaveTiddler","tw-CloseTiddler"],
|
||||||
|
eventHandler: eventHandler
|
||||||
|
});
|
||||||
|
// Save our data inside the list element node
|
||||||
|
listElement.listElementInfo = {title: title};
|
||||||
|
return listElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create the tiddler macro needed to represent a given tiddler
|
||||||
|
*/
|
||||||
|
exports.createListElementMacro = function(title) {
|
||||||
|
// Check if the tiddler is a draft
|
||||||
|
var tiddler = this.wiki.getTiddler(title),
|
||||||
|
draft = tiddler ? $tw.utils.hop(tiddler.fields,"draft-of") : false;
|
||||||
|
// Figure out the template to use
|
||||||
|
var template = this.params.template,
|
||||||
|
templateText = this.params.templateText;
|
||||||
|
if(draft && this.hasParameter("editTemplate")) {
|
||||||
|
template = this.params.editTemplate;
|
||||||
|
}
|
||||||
|
if(draft && this.hasParameter("editTemplateText")) {
|
||||||
|
template = this.params.editTemplateText;
|
||||||
|
}
|
||||||
|
// Create the tiddler macro
|
||||||
|
return $tw.Tree.Macro("tiddler",{
|
||||||
|
srcParams: {
|
||||||
|
target: title,
|
||||||
|
template: template,
|
||||||
|
templateText: templateText
|
||||||
|
},
|
||||||
|
wiki: this.wiki
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Remove a list element from the list, along with the attendant DOM nodes
|
||||||
|
*/
|
||||||
|
exports.removelistElement = function(index) {
|
||||||
|
// Get the list element
|
||||||
|
var listElement = this.listFrame.children[index];
|
||||||
|
// Remove the dom node
|
||||||
|
listElement.domNode.parentNode.removeChild(listElement.domNode);
|
||||||
|
// Then delete the actual renderer node
|
||||||
|
this.listFrame.children.splice(index,1);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Return the index of the list element that corresponds to a particular title
|
||||||
|
startIndex: index to start search (use zero to search from the top)
|
||||||
|
title: tiddler title to seach for
|
||||||
|
*/
|
||||||
|
exports.findListElementByTitle = function(startIndex,title) {
|
||||||
|
while(startIndex < this.listFrame.children.length) {
|
||||||
|
if(this.listFrame.children[startIndex].listElementInfo.title === title) {
|
||||||
|
return startIndex;
|
||||||
|
}
|
||||||
|
startIndex++;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Selectively update the list in response to changes in tiddlers
|
||||||
|
*/
|
||||||
|
exports.refreshInDom = function(changes) {
|
||||||
|
// If any of our parameters have changed we'll have to completely re-execute the macro
|
||||||
|
var paramNames = ["template","editTemplate"];
|
||||||
|
for(var t=0; t<paramNames.length; t++) {
|
||||||
|
if(this.hasParameter(paramNames[t]) && $tw.utils.hop(changes,this.params[paramNames[t]])) {
|
||||||
|
this.reexecuteInDom();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get the list of tiddlers
|
||||||
|
this.getTiddlerList();
|
||||||
|
// Step through the list and adjust our child list elements appropriately
|
||||||
|
for(t=0; t<this.list.length; t++) {
|
||||||
|
// Check to see if the list element is already there
|
||||||
|
var index = this.findListElementByTitle(t,this.list[t]);
|
||||||
|
if(index === undefined) {
|
||||||
|
// The list element isn't there, so we need to insert it
|
||||||
|
this.listFrame.children.splice(t,0,this.createListElement(this.list[t]));
|
||||||
|
this.listFrame.children[t].renderInDom(this.listFrame.domNode,this.listFrame.domNode.childNodes[t]);
|
||||||
} else {
|
} else {
|
||||||
var templateTree = this.wiki.parseText(templateType,templateText).tree;
|
// Delete any list elements preceding the one we want
|
||||||
for(t=0; t<tiddlers.length; t++) {
|
if(index > t) {
|
||||||
var cloneTemplate = [];
|
for(var n=index-1; n>=t; n--) {
|
||||||
for(var c=0; c<templateTree.length; c++) {
|
this.removelistElement(n);
|
||||||
cloneTemplate.push(templateTree[c].clone());
|
|
||||||
}
|
}
|
||||||
var listNode = $tw.Tree.Element("li",null,cloneTemplate);
|
|
||||||
listNode.execute(parents,tiddlers[t]);
|
|
||||||
children.push(listNode);
|
|
||||||
}
|
}
|
||||||
return $tw.Tree.Element("ul",attributes,children);
|
// Refresh the node we're reusing
|
||||||
|
this.listFrame.children[t].refreshInDom(changes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Remove any left over elements
|
||||||
|
if(this.listFrame.children.length > this.list.length) {
|
||||||
|
for(t=this.listFrame.children.length-1; t>=this.list.length; t--) {
|
||||||
|
this.removeStoryElement(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user