2012-12-13 21:34:31 +00:00
|
|
|
/*\
|
2013-05-31 12:23:25 +00:00
|
|
|
title: $:/core/modules/widgets/navigator.js
|
2012-12-13 21:34:31 +00:00
|
|
|
type: application/javascript
|
|
|
|
module-type: widget
|
|
|
|
|
|
|
|
Implements the navigator widget.
|
|
|
|
|
|
|
|
\*/
|
|
|
|
(function(){
|
|
|
|
|
|
|
|
/*jslint node: true, browser: true */
|
|
|
|
/*global $tw: false */
|
|
|
|
"use strict";
|
|
|
|
|
2013-01-01 17:51:02 +00:00
|
|
|
var NavigatorWidget = function(renderer) {
|
2012-12-13 21:34:31 +00:00
|
|
|
// Save state
|
|
|
|
this.renderer = renderer;
|
|
|
|
// Generate child nodes
|
2013-01-03 16:27:55 +00:00
|
|
|
this.generate();
|
2012-12-13 21:34:31 +00:00
|
|
|
};
|
|
|
|
|
2013-01-03 16:27:55 +00:00
|
|
|
NavigatorWidget.prototype.generate = function() {
|
2012-12-13 21:34:31 +00:00
|
|
|
// Get our parameters
|
|
|
|
this.storyTitle = this.renderer.getAttribute("story");
|
|
|
|
this.historyTitle = this.renderer.getAttribute("history");
|
2013-01-03 16:27:55 +00:00
|
|
|
// Set the element
|
|
|
|
this.tag = "div";
|
|
|
|
this.attributes = {
|
|
|
|
"class": "tw-navigator"
|
|
|
|
};
|
2013-05-15 16:32:17 +00:00
|
|
|
this.children = this.renderer.renderTree.createRenderers(this.renderer,this.renderer.parseTreeNode.children);
|
2013-01-03 16:27:55 +00:00
|
|
|
this.events = [
|
2012-12-13 21:34:31 +00:00
|
|
|
{name: "tw-navigate", handlerObject: this, handlerMethod: "handleNavigateEvent"},
|
2013-02-04 15:29:25 +00:00
|
|
|
{name: "tw-edit-tiddler", handlerObject: this, handlerMethod: "handleEditTiddlerEvent"},
|
2013-03-10 19:24:49 +00:00
|
|
|
{name: "tw-delete-tiddler", handlerObject: this, handlerMethod: "handleDeleteTiddlerEvent"},
|
2013-02-04 15:29:25 +00:00
|
|
|
{name: "tw-save-tiddler", handlerObject: this, handlerMethod: "handleSaveTiddlerEvent"},
|
2013-03-20 17:20:46 +00:00
|
|
|
{name: "tw-cancel-tiddler", handlerObject: this, handlerMethod: "handleCancelTiddlerEvent"},
|
2013-02-04 15:29:25 +00:00
|
|
|
{name: "tw-close-tiddler", handlerObject: this, handlerMethod: "handleCloseTiddlerEvent"},
|
2013-04-27 15:35:59 +00:00
|
|
|
{name: "tw-close-all-tiddlers", handlerObject: this, handlerMethod: "handleCloseAllTiddlersEvent"},
|
2013-02-04 15:29:25 +00:00
|
|
|
{name: "tw-new-tiddler", handlerObject: this, handlerMethod: "handleNewTiddlerEvent"}
|
2012-12-14 17:57:53 +00:00
|
|
|
];
|
2012-12-13 21:34:31 +00:00
|
|
|
};
|
|
|
|
|
2013-01-01 17:51:02 +00:00
|
|
|
NavigatorWidget.prototype.refreshInDom = function(changedAttributes,changedTiddlers) {
|
2012-12-13 21:34:31 +00:00
|
|
|
// We don't need to refresh ourselves, so just refresh any child nodes
|
|
|
|
$tw.utils.each(this.children,function(node) {
|
|
|
|
if(node.refreshInDom) {
|
|
|
|
node.refreshInDom(changedTiddlers);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2013-01-01 17:51:02 +00:00
|
|
|
NavigatorWidget.prototype.getStoryList = function() {
|
2012-12-13 21:34:31 +00:00
|
|
|
var text = this.renderer.renderTree.wiki.getTextReference(this.storyTitle,"");
|
|
|
|
if(text && text.length > 0) {
|
|
|
|
this.storyList = text.split("\n");
|
|
|
|
} else {
|
|
|
|
this.storyList = [];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-01-01 17:51:02 +00:00
|
|
|
NavigatorWidget.prototype.saveStoryList = function() {
|
2012-12-13 21:34:31 +00:00
|
|
|
var storyTiddler = this.renderer.renderTree.wiki.getTiddler(this.storyTitle);
|
|
|
|
this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler({
|
|
|
|
title: this.storyTitle
|
|
|
|
},storyTiddler,{text: this.storyList.join("\n")}));
|
|
|
|
};
|
|
|
|
|
2013-01-01 17:51:02 +00:00
|
|
|
NavigatorWidget.prototype.findTitleInStory = function(title,defaultIndex) {
|
2012-12-13 21:34:31 +00:00
|
|
|
for(var t=0; t<this.storyList.length; t++) {
|
|
|
|
if(this.storyList[t] === title) {
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return defaultIndex;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Navigate to a specified tiddler
|
2013-01-01 17:51:02 +00:00
|
|
|
NavigatorWidget.prototype.handleNavigateEvent = function(event) {
|
2012-12-13 21:34:31 +00:00
|
|
|
if(this.storyTitle) {
|
|
|
|
// Update the story tiddler if specified
|
|
|
|
this.getStoryList();
|
|
|
|
// See if the tiddler is already there
|
|
|
|
var slot = this.findTitleInStory(event.navigateTo,-1);
|
|
|
|
// If not we need to add it
|
|
|
|
if(slot === -1) {
|
|
|
|
// First we try to find the position of the story element we navigated from
|
|
|
|
slot = this.findTitleInStory(event.navigateFromTitle,-1) + 1;
|
|
|
|
// Add the tiddler
|
|
|
|
this.storyList.splice(slot,0,event.navigateTo);
|
|
|
|
// Save the story
|
|
|
|
this.saveStoryList();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Add a new record to the top of the history stack
|
|
|
|
if(this.historyTitle) {
|
|
|
|
var historyList = this.renderer.renderTree.wiki.getTiddlerData(this.historyTitle,[]);
|
|
|
|
historyList.push({title: event.navigateTo, fromPageRect: event.navigateFromClientRect});
|
|
|
|
this.renderer.renderTree.wiki.setTiddlerData(this.historyTitle,historyList);
|
|
|
|
}
|
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Close a specified tiddler
|
2013-01-01 17:51:02 +00:00
|
|
|
NavigatorWidget.prototype.handleCloseTiddlerEvent = function(event) {
|
2012-12-13 21:34:31 +00:00
|
|
|
this.getStoryList();
|
|
|
|
// Look for tiddlers with this title to close
|
|
|
|
var slot = this.findTitleInStory(event.tiddlerTitle,-1);
|
|
|
|
if(slot !== -1) {
|
|
|
|
this.storyList.splice(slot,1);
|
|
|
|
this.saveStoryList();
|
|
|
|
}
|
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2013-04-27 15:35:59 +00:00
|
|
|
// Close all tiddlers
|
|
|
|
NavigatorWidget.prototype.handleCloseAllTiddlersEvent = function(event) {
|
|
|
|
this.storyList = [];
|
|
|
|
this.saveStoryList();
|
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2012-12-13 21:34:31 +00:00
|
|
|
// Place a tiddler in edit mode
|
2013-01-01 17:51:02 +00:00
|
|
|
NavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {
|
2012-12-13 21:34:31 +00:00
|
|
|
this.getStoryList();
|
|
|
|
// Replace the specified tiddler with a draft in edit mode
|
|
|
|
for(var t=0; t<this.storyList.length; t++) {
|
|
|
|
if(this.storyList[t] === event.tiddlerTitle) {
|
|
|
|
// Compute the title for the draft
|
2013-02-04 11:56:11 +00:00
|
|
|
var draftTitle = this.generateDraftTitle(event.tiddlerTitle);
|
2012-12-13 21:34:31 +00:00
|
|
|
this.storyList[t] = draftTitle;
|
|
|
|
// Get the current value of the tiddler we're editing
|
|
|
|
var tiddler = this.renderer.renderTree.wiki.getTiddler(event.tiddlerTitle);
|
|
|
|
// Save the initial value of the draft tiddler
|
|
|
|
this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(
|
|
|
|
{
|
|
|
|
text: "Type the text for the tiddler '" + event.tiddlerTitle + "'"
|
|
|
|
},
|
|
|
|
tiddler,
|
|
|
|
{
|
|
|
|
title: draftTitle,
|
|
|
|
"draft.title": event.tiddlerTitle,
|
|
|
|
"draft.of": event.tiddlerTitle
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.saveStoryList();
|
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2013-03-10 19:24:49 +00:00
|
|
|
// Delete a tiddler
|
|
|
|
NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
|
|
|
|
// Get the tiddler title we're deleting
|
|
|
|
var tiddler = this.renderer.renderTree.wiki.getTiddler(event.tiddlerTitle);
|
|
|
|
// Check if the tiddler we're deleting is in draft mode
|
|
|
|
if(tiddler.hasField("draft.title")) {
|
|
|
|
// Delete the original tiddler
|
|
|
|
this.renderer.renderTree.wiki.deleteTiddler(tiddler.fields["draft.of"]);
|
|
|
|
}
|
|
|
|
// Delete this tiddler
|
|
|
|
this.renderer.renderTree.wiki.deleteTiddler(event.tiddlerTitle);
|
|
|
|
// Remove the closed tiddler from the story
|
|
|
|
this.getStoryList();
|
|
|
|
// Look for tiddler with this title to close
|
|
|
|
var slot = this.findTitleInStory(event.tiddlerTitle,-1);
|
|
|
|
if(slot !== -1) {
|
|
|
|
this.storyList.splice(slot,1);
|
|
|
|
this.saveStoryList();
|
|
|
|
}
|
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2013-02-04 11:56:11 +00:00
|
|
|
/*
|
|
|
|
Generate a title for the draft of a given tiddler
|
|
|
|
*/
|
|
|
|
NavigatorWidget.prototype.generateDraftTitle = function(title) {
|
|
|
|
var c = 0;
|
|
|
|
do {
|
|
|
|
var draftTitle = "Draft " + (c ? (c + 1) + " " : "") + "of '" + title + "'";
|
|
|
|
c++;
|
|
|
|
} while(this.renderer.renderTree.wiki.tiddlerExists(draftTitle));
|
|
|
|
return draftTitle;
|
|
|
|
};
|
|
|
|
|
2012-12-13 21:34:31 +00:00
|
|
|
// Take a tiddler out of edit mode, saving the changes
|
2013-01-01 17:51:02 +00:00
|
|
|
NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
|
2012-12-13 21:34:31 +00:00
|
|
|
this.getStoryList();
|
|
|
|
var storyTiddlerModified = false;
|
|
|
|
for(var t=0; t<this.storyList.length; t++) {
|
|
|
|
if(this.storyList[t] === event.tiddlerTitle) {
|
|
|
|
var tiddler = this.renderer.renderTree.wiki.getTiddler(event.tiddlerTitle);
|
2013-03-10 19:24:49 +00:00
|
|
|
if(tiddler.hasField("draft.title")) {
|
2012-12-13 21:34:31 +00:00
|
|
|
// Save the draft tiddler as the real tiddler
|
|
|
|
this.renderer.renderTree.wiki.addTiddler(new $tw.Tiddler(tiddler,{
|
|
|
|
title: tiddler.fields["draft.title"],
|
|
|
|
modified: new Date(),
|
|
|
|
"draft.title": undefined,
|
|
|
|
"draft.of": undefined
|
|
|
|
}));
|
|
|
|
// Remove the draft tiddler
|
|
|
|
this.renderer.renderTree.wiki.deleteTiddler(event.tiddlerTitle);
|
|
|
|
// Remove the original tiddler if we're renaming it
|
|
|
|
if(tiddler.fields["draft.of"] !== tiddler.fields["draft.title"]) {
|
|
|
|
this.renderer.renderTree.wiki.deleteTiddler(tiddler.fields["draft.of"]);
|
|
|
|
}
|
|
|
|
// Make the story record point to the newly saved tiddler
|
|
|
|
this.storyList[t] = tiddler.fields["draft.title"];
|
|
|
|
// Check if we're modifying the story tiddler itself
|
|
|
|
if(tiddler.fields["draft.title"] === this.storyTitle) {
|
|
|
|
storyTiddlerModified = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!storyTiddlerModified) {
|
|
|
|
this.saveStoryList();
|
|
|
|
}
|
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2013-03-20 17:20:46 +00:00
|
|
|
// Take a tiddler out of edit mode without saving the changes
|
|
|
|
NavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {
|
|
|
|
this.getStoryList();
|
|
|
|
var storyTiddlerModified = false;
|
|
|
|
for(var t=0; t<this.storyList.length; t++) {
|
|
|
|
if(this.storyList[t] === event.tiddlerTitle) {
|
|
|
|
var tiddler = this.renderer.renderTree.wiki.getTiddler(event.tiddlerTitle);
|
|
|
|
if(tiddler.hasField("draft.title")) {
|
|
|
|
// Remove the draft tiddler
|
|
|
|
this.renderer.renderTree.wiki.deleteTiddler(event.tiddlerTitle);
|
|
|
|
// Make the story record point to the original tiddler
|
|
|
|
this.storyList[t] = tiddler.fields["draft.title"];
|
|
|
|
// Check if we're modifying the story tiddler itself
|
|
|
|
if(tiddler.fields["draft.title"] === this.storyTitle) {
|
|
|
|
storyTiddlerModified = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!storyTiddlerModified) {
|
|
|
|
this.saveStoryList();
|
|
|
|
}
|
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2012-12-13 21:34:31 +00:00
|
|
|
// Create a new draft tiddler
|
2013-01-01 17:51:02 +00:00
|
|
|
NavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {
|
2012-12-13 21:34:31 +00:00
|
|
|
// Get the story details
|
|
|
|
this.getStoryList();
|
|
|
|
// Create the new tiddler
|
|
|
|
var title;
|
|
|
|
for(var t=0; true; t++) {
|
|
|
|
title = "New Tiddler" + (t ? " " + t : "");
|
|
|
|
if(!this.renderer.renderTree.wiki.tiddlerExists(title)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var tiddler = new $tw.Tiddler({
|
|
|
|
title: title,
|
|
|
|
text: "Newly created tiddler"
|
|
|
|
});
|
|
|
|
this.renderer.renderTree.wiki.addTiddler(tiddler);
|
|
|
|
// Create the draft tiddler
|
2013-03-18 10:59:47 +00:00
|
|
|
var draftTitle = this.generateDraftTitle(title),
|
2012-12-13 21:34:31 +00:00
|
|
|
draftTiddler = new $tw.Tiddler({
|
|
|
|
text: "Type the text for the new tiddler",
|
|
|
|
title: draftTitle,
|
|
|
|
"draft.title": title,
|
|
|
|
"draft.of": title
|
|
|
|
});
|
|
|
|
this.renderer.renderTree.wiki.addTiddler(draftTiddler);
|
|
|
|
// Update the story to insert the new draft at the top
|
|
|
|
var slot = this.findTitleInStory(event.navigateFromTitle,-1) + 1;
|
|
|
|
this.storyList.splice(slot,0,draftTitle);
|
|
|
|
// Save the updated story
|
|
|
|
this.saveStoryList();
|
|
|
|
// Add a new record to the top of the history stack
|
|
|
|
var history = this.renderer.renderTree.wiki.getTiddlerData(this.historyTitle,[]);
|
|
|
|
history.push({title: draftTitle});
|
2013-01-17 11:38:02 +00:00
|
|
|
this.renderer.renderTree.wiki.setTiddlerData(this.historyTitle,history);
|
2012-12-13 21:34:31 +00:00
|
|
|
event.stopPropagation();
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2013-01-01 17:51:02 +00:00
|
|
|
exports.navigator = NavigatorWidget;
|
|
|
|
|
2012-12-13 21:34:31 +00:00
|
|
|
})();
|