2012-06-26 18:54:51 +00:00
|
|
|
/*\
|
|
|
|
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
|
|
|
|
set: {byName: true, type: "tiddler"}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getStory = function() {
|
2012-07-22 21:03:06 +00:00
|
|
|
this.story = this.wiki.getTiddlerData(this.params.story,{tiddlers: []});
|
2012-06-26 18:54:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.saveStory = function() {
|
|
|
|
if(this.hasParameter("story")) {
|
2012-07-22 21:03:06 +00:00
|
|
|
this.wiki.setTiddlerData(this.params.story,this.story);
|
2012-06-26 18:54:51 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getHistory = function() {
|
2012-07-22 21:03:06 +00:00
|
|
|
this.history = this.wiki.getTiddlerData(this.params.history,{stack: []});
|
2012-06-26 18:54:51 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
exports.saveHistory = function() {
|
|
|
|
if(this.hasParameter("history")) {
|
2012-07-22 21:03:06 +00:00
|
|
|
this.wiki.setTiddlerData(this.params.history,this.history);
|
2012-06-26 18:54:51 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
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();
|
2012-07-07 16:14:50 +00:00
|
|
|
var t,tiddler,slot;
|
2012-06-26 18:54:51 +00:00
|
|
|
// 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);
|
|
|
|
}
|
2012-06-26 19:50:29 +00:00
|
|
|
// Add a new record to the top of the history stack
|
2012-06-26 18:54:51 +00:00
|
|
|
this.getHistory();
|
2012-06-26 19:50:29 +00:00
|
|
|
this.history.stack.push({
|
|
|
|
title: event.navigateTo,
|
|
|
|
fromTitle: event.navigateFromTitle,
|
2012-07-07 16:14:50 +00:00
|
|
|
fromPosition: event.navigateFrom.getNodeBounds(),
|
|
|
|
scrollPosition: $tw.utils.getScrollPosition()
|
2012-06-26 19:50:29 +00:00
|
|
|
});
|
2012-06-26 18:54:51 +00:00
|
|
|
this.saveHistory();
|
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2012-07-07 16:14:50 +00:00
|
|
|
// Navigate to a specified tiddler
|
|
|
|
exports.eventMap["tw-NavigateBack"] = function(event) {
|
|
|
|
// Pop a record record off the top of the history stack
|
|
|
|
this.getHistory();
|
|
|
|
if(this.history.stack.length < 2) {
|
|
|
|
return false; // Bail if there is not enough entries on the history stack
|
|
|
|
}
|
|
|
|
var fromHistoryInfo = this.history.stack.pop(),
|
|
|
|
toHistoryInfo = this.history.stack[this.history.stack.length-1];
|
|
|
|
this.saveHistory();
|
|
|
|
// Make sure that the tiddler we're navigating back to is open in the story
|
|
|
|
if(this.hasParameter("story") && toHistoryInfo) {
|
|
|
|
this.getStory();
|
|
|
|
var 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 === toHistoryInfo.title) {
|
|
|
|
tiddler = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If not we need to add it
|
|
|
|
if(tiddler === undefined) {
|
|
|
|
// Add the tiddler
|
|
|
|
this.story.tiddlers.splice(slot,0,{title: toHistoryInfo.title});
|
|
|
|
// Save the story
|
|
|
|
this.saveStory();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2012-06-26 18:54:51 +00:00
|
|
|
// 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;
|
|
|
|
};
|
|
|
|
|
2012-10-21 15:44:53 +00:00
|
|
|
// Create a new draft tiddler
|
|
|
|
exports.eventMap["tw-NewTiddler"] = function(event) {
|
|
|
|
var t;
|
|
|
|
if(this.hasParameter("story")) {
|
|
|
|
// Get the story details
|
|
|
|
this.getStory();
|
|
|
|
// Create the new tiddler
|
|
|
|
for(var t=0; true; t++) {
|
|
|
|
var title = "New Tiddler" + (t ? " " + t : "");
|
|
|
|
if(!this.wiki.tiddlerExists(title)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var tiddler = new $tw.Tiddler({
|
|
|
|
title: title,
|
|
|
|
text: "Newly created tiddler"
|
|
|
|
});
|
|
|
|
this.wiki.addTiddler(tiddler);
|
|
|
|
// Create the draft tiddler
|
|
|
|
var draftTitle = "New Tiddler at " + (new Date()),
|
|
|
|
draftTiddler = new $tw.Tiddler({
|
|
|
|
text: "Type the text for the new tiddler",
|
|
|
|
title: draftTitle,
|
|
|
|
"draft.title": title,
|
|
|
|
"draft.of": title
|
|
|
|
});
|
|
|
|
this.wiki.addTiddler(draftTiddler);
|
|
|
|
// Update the story to put the new draft at the top
|
|
|
|
this.story.tiddlers.splice(0,0,{
|
|
|
|
title: title,
|
|
|
|
draft: draftTitle
|
|
|
|
});
|
|
|
|
// Save the updated story
|
|
|
|
this.saveStory();
|
|
|
|
// Add a new record to the top of the history stack
|
|
|
|
this.getHistory();
|
|
|
|
this.history.stack.push({
|
|
|
|
title: title,
|
|
|
|
fromTitle: "HelloThere",
|
|
|
|
fromPosition: {
|
|
|
|
top: 0,
|
|
|
|
left: 0,
|
|
|
|
right: 100,
|
|
|
|
bottom: 100,
|
|
|
|
width: 100,
|
|
|
|
height: 100
|
|
|
|
},
|
|
|
|
scrollPosition: $tw.utils.getScrollPosition()
|
|
|
|
});
|
|
|
|
this.saveHistory();
|
|
|
|
}
|
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2012-06-26 18:54:51 +00:00
|
|
|
// 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
|
2012-07-15 16:36:02 +00:00
|
|
|
exports.eventMap["tw-close"] = function(event) {
|
2012-06-26 18:54:51 +00:00
|
|
|
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,{
|
2012-10-21 15:44:53 +00:00
|
|
|
events: ["tw-navigate","tw-EditTiddler","tw-SaveTiddler","tw-close","tw-NavigateBack","tw-NewTiddler"],
|
2012-06-26 18:54:51 +00:00
|
|
|
eventHandler: this
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
})();
|