mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-27 03:57:21 +00:00
Added support for store events and basic refreshing
1s after loading you'll see the link to TiddlyWiki5 flip from italic to normal text as that tiddler is created on a timer
This commit is contained in:
parent
054977c912
commit
b7d0942625
10
js/App.js
10
js/App.js
@ -109,6 +109,16 @@ var App = function() {
|
||||
var div = document.createElement("div");
|
||||
div.innerHTML = this.store.renderTiddler("text/html","PageTemplate");
|
||||
document.body.appendChild(div);
|
||||
var me = this;
|
||||
window.setInterval(function() {
|
||||
me.store.addTiddler(new Tiddler({
|
||||
title: "TiddlyWiki5",
|
||||
text: "This is a newly created tiddler!"
|
||||
}));
|
||||
},3000);
|
||||
this.store.addEventListener("",function() {
|
||||
me.store.refreshDomNode(div,me.store.getTiddler("PageTemplate"));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
154
js/WikiStore.js
154
js/WikiStore.js
@ -22,6 +22,9 @@ var WikiStore = function WikiStore(options) {
|
||||
this.macros = {};
|
||||
this.tiddlerSerializers = {};
|
||||
this.tiddlerDeserializers = {};
|
||||
this.eventListeners = []; // Array of {filter:,listener:}
|
||||
this.eventsTriggered = false;
|
||||
this.changedTiddlers = {}; // Hashmap of {title: "created|modified|deleted"}
|
||||
this.sandbox = options.sandbox;
|
||||
this.shadows = options.shadowStore !== undefined ? options.shadowStore : new WikiStore({
|
||||
shadowStore: null
|
||||
@ -42,6 +45,73 @@ WikiStore.prototype.registerTiddlerDeserializer = function(extension,mimeType,de
|
||||
this.tiddlerDeserializers[mimeType] = deserializer;
|
||||
};
|
||||
|
||||
WikiStore.prototype.addEventListener = function(filter,listener) {
|
||||
this.eventListeners.push({
|
||||
filter: filter,
|
||||
listener: listener
|
||||
});
|
||||
};
|
||||
|
||||
WikiStore.prototype.removeEventListener = function(listener) {
|
||||
for(var c=this.eventListeners.length-1; c>=0; c--) {
|
||||
var l = this.eventListeners[c];
|
||||
if(l.listener === listener) {
|
||||
this.eventListeners.splice(c,1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Causes a tiddler to be marked as changed, so that event listeners are triggered for it
|
||||
type: Type of change to be registered for the tiddler "created", "modified" or "deleted"
|
||||
If the tiddler is already touched, the resultant touch type is as follows:
|
||||
|
||||
If the tiddler is already marked "created",
|
||||
... attempts to mark it "modified" leave it "created"
|
||||
... attempts to mark it "deleted" succeed
|
||||
|
||||
If the tiddler is already marked "modified",
|
||||
... attempts to mark it "deleted" succeed
|
||||
|
||||
If the tiddler is already marked "deleted",
|
||||
... attempts to mark it "created" succeed
|
||||
... attempts to mark it "modified" fail
|
||||
|
||||
*/
|
||||
WikiStore.prototype.touchTiddler = function(type,title) {
|
||||
var existingType = this.changedTiddlers[title];
|
||||
if(existingType === undefined && type === "modified") {
|
||||
type = "created";
|
||||
}
|
||||
if(existingType === "modified" && type === "created") {
|
||||
type = "modified";
|
||||
}
|
||||
if(existingType === "deleted" && type === "created") {
|
||||
type = "modified";
|
||||
}
|
||||
this.changedTiddlers[title] = type;
|
||||
this.triggerEvents();
|
||||
};
|
||||
|
||||
/*
|
||||
Trigger the execution of the event dispatcher at the next tick, if it is not already triggered
|
||||
*/
|
||||
WikiStore.prototype.triggerEvents = function() {
|
||||
if(!this.eventsTriggered) {
|
||||
var me = this;
|
||||
utils.nextTick(function() {
|
||||
var changes = me.changedTiddlers;
|
||||
me.changedTiddlers = {};
|
||||
me.eventsTriggered = false;
|
||||
for(var e=0; e<me.eventListeners.length; e++) {
|
||||
var listener = me.eventListeners[e];
|
||||
listener.listener(changes);
|
||||
}
|
||||
});
|
||||
this.eventsTriggered = true;
|
||||
}
|
||||
};
|
||||
|
||||
WikiStore.prototype.getTiddler = function(title) {
|
||||
var t = this.tiddlers[title];
|
||||
if(t instanceof Tiddler) {
|
||||
@ -74,6 +144,7 @@ WikiStore.prototype.tiddlerExists = function(title) {
|
||||
|
||||
WikiStore.prototype.addTiddler = function(tiddler) {
|
||||
this.tiddlers[tiddler.fields.title] = tiddler;
|
||||
this.touchTiddler("modified",tiddler.fields.title);
|
||||
};
|
||||
|
||||
WikiStore.prototype.forEachTiddler = function(/* [sortField,[excludeTag,]]callback */) {
|
||||
@ -163,17 +234,45 @@ WikiStore.prototype.deserializeTiddlers = function(type,text,srcFields) {
|
||||
}
|
||||
};
|
||||
|
||||
WikiStore.prototype.classesForLink = function(target) {
|
||||
var className = "",
|
||||
externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data):[^\s'"]+(?:\/|\b)/i;
|
||||
WikiStore.prototype.adjustClassesForLink = function(classes,target) {
|
||||
var externalRegExp = /(?:file|http|https|mailto|ftp|irc|news|data):[^\s'"]+(?:\/|\b)/i,
|
||||
setClass = function(className) {
|
||||
if(classes.indexOf(className) === -1) {
|
||||
classes.push(className);
|
||||
}
|
||||
},
|
||||
removeClass = function(className) {
|
||||
var p = classes.indexOf(className);
|
||||
if(p !== -1) {
|
||||
classes.splice(p,1);
|
||||
}
|
||||
};
|
||||
// Make sure we've got the main link class
|
||||
setClass("tw-tiddlylink");
|
||||
// Check if it's an internal link
|
||||
if (this.tiddlerExists(target)) {
|
||||
className = "linkInternalResolves";
|
||||
removeClass("tw-tiddlylink-external");
|
||||
setClass("tw-tiddlylink-internal");
|
||||
setClass("tw-tiddlylink-resolves");
|
||||
removeClass("tw-tiddlylink-missing");
|
||||
} else if(externalRegExp.test(target)) {
|
||||
className = "linkExternal";
|
||||
setClass("tw-tiddlylink-external");
|
||||
removeClass("tw-tiddlylink-internal");
|
||||
removeClass("tw-tiddlylink-resolves");
|
||||
removeClass("tw-tiddlylink-missing");
|
||||
} else {
|
||||
className = "linkInternalMissing";
|
||||
removeClass("tw-tiddlylink-external");
|
||||
setClass("tw-tiddlylink-internal");
|
||||
removeClass("tw-tiddlylink-resolves");
|
||||
setClass("tw-tiddlylink-missing");
|
||||
}
|
||||
return className !== "" ? " class=\"" + className + "\"" : "";
|
||||
return classes;
|
||||
};
|
||||
|
||||
WikiStore.prototype.classesForLink = function(target) {
|
||||
var classes = ["tw-tiddlylink"];
|
||||
this.adjustClassesForLink(classes,target);
|
||||
return " class=\"" + classes.join(" ") + "\"";
|
||||
};
|
||||
|
||||
WikiStore.prototype.parseText = function(type,text) {
|
||||
@ -258,6 +357,47 @@ WikiStore.prototype.renderTiddler = function(type,title,asTitle) {
|
||||
return null;
|
||||
};
|
||||
|
||||
/*
|
||||
Refresh a DOM node so that it reflects the current state of the store
|
||||
|
||||
The refresh processing is:
|
||||
|
||||
1. If the node is a link, check the link classes correctly reflect the status of the target tiddler. Recursively process any children. Exit
|
||||
2. If the node is a macro, and dependencies have changed, re-render the macro into the DOM node. Exit
|
||||
3. If the node is a macro and the dependencies haven't changed, recursively process each child node of the macro. Exit
|
||||
|
||||
Arguments
|
||||
node - the DOM node to be processed
|
||||
tiddler - the tiddler providing context for the rendering
|
||||
|
||||
*/
|
||||
WikiStore.prototype.refreshDomNode = function(node,tiddler) {
|
||||
// Process links
|
||||
if(node.className) {
|
||||
var classes = node.className.split(" ");
|
||||
if(classes.indexOf("tw-tiddlylink") !== -1) {
|
||||
var target = node.getAttribute("href");
|
||||
node.className = this.adjustClassesForLink(classes,target).join(" ");
|
||||
}
|
||||
}
|
||||
// Process macros
|
||||
var macro = node.getAttribute && node.getAttribute("data-tw-macro"),
|
||||
params = node.getAttribute && node.getAttribute("data-tw-params");
|
||||
if(macro && params) {
|
||||
}
|
||||
// Process children
|
||||
if(node.hasChildNodes()) {
|
||||
this.refreshDomChildren(node,tiddler);
|
||||
}
|
||||
};
|
||||
|
||||
WikiStore.prototype.refreshDomChildren = function(node,tiddler) {
|
||||
var nodes = node.childNodes;
|
||||
for(var c=0; c<nodes.length; c++) {
|
||||
this.refreshDomNode(nodes[c],tiddler);
|
||||
}
|
||||
};
|
||||
|
||||
WikiStore.prototype.installMacro = function(macro) {
|
||||
this.macros[macro.name] = macro;
|
||||
};
|
||||
|
@ -81,17 +81,17 @@ a:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
a.linkExternal {
|
||||
a.tw-tiddlylink {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
a.linkInternalResolves {
|
||||
a.tw-tiddlylink-resolves {
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
a.linkInternalMissing {
|
||||
a.tw-tiddlylink-missing {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user