1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-10-05 02:10:45 +00:00
TiddlyWiki5/core/modules/macros/navigator.js
Jeremy Ruston 69a0c46447 Split the story macro out into two macros
Now the story macro manages the story element sequence, while the
navigator macro listens for the navigation events, and modifies the
story tiddler as required. Also introduces a history tiddler that
retains the history stack so that we can animate navigation properly
(as distinct from animating the addition and removal of story elements).

Note that the zoomin storyview isn't quite finished, but this is a
stable point to commit these changes.
2012-06-26 19:54:51 +01:00

209 lines
6.4 KiB
JavaScript

/*\
title: $:/core/modules/macros/navigator.js
type: application/javascript
module-type: macro
Traps navigation events to update a story tiddler and history tiddler. Can also optionally capture navigation target in a specified text reference.
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
exports.info = {
name: "navigator",
params: {
story: {byName: "default", type: "text"}, // Actually a tiddler, but we don't want it to be a dependency
history: {byName: "default", type: "text"}, // Actually a tiddler, but we don't want it to be a dependency
defaultViewTemplate: {byName: true, type: "tiddler"},
defaultEditTemplate: {byName: true, type: "tiddler"},
set: {byName: true, type: "tiddler"}
}
};
exports.getStory = function() {
var storyTiddler = this.wiki.getTiddler(this.params.story);
this.story = {tiddlers: []};
if(storyTiddler && $tw.utils.hop(storyTiddler.fields,"text")) {
this.story = JSON.parse(storyTiddler.fields.text);
}
};
exports.saveStory = function() {
if(this.hasParameter("story")) {
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getTiddler(this.params.story),{title: this.params.story, text: JSON.stringify(this.story)}));
}
};
exports.getHistory = function() {
var historyTiddler = this.wiki.getTiddler(this.params.history);
this.history = {stack: []};
if(historyTiddler && $tw.utils.hop(historyTiddler.fields,"text")) {
this.history = JSON.parse(historyTiddler.fields.text);
}
};
exports.saveHistory = function() {
if(this.hasParameter("history")) {
this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getTiddler(this.params.history),{title: this.params.history, text: JSON.stringify(this.history)}));
}
};
exports.handleEvent = function(event) {
if(this.eventMap[event.type]) {
this.eventMap[event.type].call(this,event);
}
};
exports.eventMap = {};
// Navigate to a specified tiddler
exports.eventMap["tw-navigate"] = function(event) {
// Update the story tiddler if specified
if(this.hasParameter("story")) {
this.getStory();
var template = this.params.defaultViewTemplate || "$:/templates/ViewTemplate",
t,tiddler,slot;
// See if the tiddler is already there
for(t=0; t<this.story.tiddlers.length; t++) {
if(this.story.tiddlers[t].title === event.navigateTo) {
tiddler = t;
}
}
// If not we need to add it
if(tiddler === undefined) {
// First we try to find the position of the story element we navigated from
var navigateFromTitle;
if(event.navigateFromStoryElement) {
navigateFromTitle = event.navigateFromStoryElement.params.target;
}
slot = 0;
if(navigateFromTitle !== undefined) {
for(t=0; t<this.story.tiddlers.length; t++) {
if(this.story.tiddlers[t].title === navigateFromTitle) {
slot = t + 1;
}
}
}
// Add the tiddler
this.story.tiddlers.splice(slot,0,{title: event.navigateTo});
// Save the story
this.saveStory();
}
}
// Set the tiddler if specified
if(this.hasParameter("set")) {
this.wiki.setTextReference(this.params.set,event.navigateTo);
}
// Add the tiddler to the top of the history stack
this.getHistory();
this.history.stack.push({title: event.navigateTo});
this.saveHistory();
event.stopPropagation();
return false;
};
// Place a tiddler in edit mode
exports.eventMap["tw-EditTiddler"] = function(event) {
if(this.hasParameter("story")) {
var storyTiddler, storyRecord, tiddler, t;
// Put the specified tiddler into edit mode
this.getStory();
for(t=0; t<this.story.tiddlers.length; t++) {
storyRecord = this.story.tiddlers[t];
if(storyRecord.title === event.tiddlerTitle && !storyRecord.draft) {
// Set the story record to the draft of the specified tiddler
storyRecord.draft = "Draft " + (new Date()) + " of " + event.tiddlerTitle;
// Get the current value of the tiddler we're editing
tiddler = this.wiki.getTiddler(event.tiddlerTitle);
// Save the initial value of the draft tiddler
this.wiki.addTiddler(new $tw.Tiddler(
{
text: "Type the text for the tiddler '" + event.tiddlerTitle + "'"
},
tiddler,
{
title: storyRecord.draft,
"draft.title": event.tiddlerTitle,
"draft.of": event.tiddlerTitle
}));
}
}
this.saveStory();
}
event.stopPropagation();
return false;
};
// Take a tiddler out of edit mode, saving the changes
exports.eventMap["tw-SaveTiddler"] = function(event) {
if(this.hasParameter("story")) {
var storyTiddler, storyRecord, tiddler, storyTiddlerModified, t;
this.getStory();
storyTiddlerModified = false;
for(t=0; t<this.story.tiddlers.length; t++) {
storyRecord = this.story.tiddlers[t];
if(storyRecord.draft === event.tiddlerTitle) {
tiddler = this.wiki.getTiddler(storyRecord.draft);
if(tiddler && $tw.utils.hop(tiddler.fields,"draft.title")) {
// Save the draft tiddler as the real tiddler
this.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: tiddler.fields["draft.title"],"draft.title": undefined, "draft.of": undefined}));
// Remove the draft tiddler
this.wiki.deleteTiddler(storyRecord.draft);
// Remove the original tiddler if we're renaming it
if(tiddler.fields["draft.of"] !== tiddler.fields["draft.title"]) {
this.wiki.deleteTiddler(tiddler.fields["draft.of"]);
}
// Make the story record point to the newly saved tiddler
storyRecord.title = tiddler.fields["draft.title"];
storyRecord.draft = undefined;
// Check if we're modifying the story tiddler itself
if(tiddler.fields["draft.title"] === this.params.story) {
storyTiddlerModified = true;
}
}
}
}
if(!storyTiddlerModified) {
this.saveStory();
}
}
event.stopPropagation();
return false;
};
// Close a specified tiddler
exports.eventMap["tw-CloseTiddler"] = function(event) {
if(this.hasParameter("story")) {
var t,storyElement;
this.getStory();
// Look for tiddlers with this title to close
for(t=this.story.tiddlers.length-1; t>=0; t--) {
if(this.story.tiddlers[t].title === event.tiddlerTitle) {
this.story.tiddlers.splice(t,1);
}
}
this.saveStory();
}
event.stopPropagation();
return false;
};
exports.executeMacro = function() {
var attributes = {};
if(this.classes) {
attributes["class"] = this.classes.slice(0);
}
for(var t=0; t<this.content.length; t++) {
this.content[t].execute(this.parents,this.tiddlerTitle);
}
return $tw.Tree.Element("div",attributes,this.content,{
events: ["tw-navigate","tw-EditTiddler","tw-SaveTiddler","tw-CloseTiddler"],
eventHandler: this
});
};
})();