2013-10-12 16:05:13 +00:00
|
|
|
/*\
|
2013-11-08 08:47:00 +00:00
|
|
|
title: $:/core/modules/widgets/navigator.js
|
2013-10-12 16:05:13 +00:00
|
|
|
type: application/javascript
|
2013-11-08 08:47:00 +00:00
|
|
|
module-type: widget
|
2013-10-12 16:05:13 +00:00
|
|
|
|
|
|
|
Navigator widget
|
|
|
|
|
|
|
|
\*/
|
|
|
|
(function(){
|
|
|
|
|
|
|
|
/*jslint node: true, browser: true */
|
|
|
|
/*global $tw: false */
|
|
|
|
"use strict";
|
|
|
|
|
2014-07-12 08:09:36 +00:00
|
|
|
var IMPORT_TITLE = "$:/Import";
|
|
|
|
|
2013-11-08 08:47:00 +00:00
|
|
|
var Widget = require("$:/core/modules/widgets/widget.js").widget;
|
2013-10-12 16:05:13 +00:00
|
|
|
|
|
|
|
var NavigatorWidget = function(parseTreeNode,options) {
|
|
|
|
this.initialise(parseTreeNode,options);
|
|
|
|
this.addEventListeners([
|
2014-08-28 20:43:44 +00:00
|
|
|
{type: "tm-navigate", handler: "handleNavigateEvent"},
|
|
|
|
{type: "tm-edit-tiddler", handler: "handleEditTiddlerEvent"},
|
|
|
|
{type: "tm-delete-tiddler", handler: "handleDeleteTiddlerEvent"},
|
|
|
|
{type: "tm-save-tiddler", handler: "handleSaveTiddlerEvent"},
|
|
|
|
{type: "tm-cancel-tiddler", handler: "handleCancelTiddlerEvent"},
|
|
|
|
{type: "tm-close-tiddler", handler: "handleCloseTiddlerEvent"},
|
|
|
|
{type: "tm-close-all-tiddlers", handler: "handleCloseAllTiddlersEvent"},
|
|
|
|
{type: "tm-close-other-tiddlers", handler: "handleCloseOtherTiddlersEvent"},
|
|
|
|
{type: "tm-new-tiddler", handler: "handleNewTiddlerEvent"},
|
|
|
|
{type: "tm-import-tiddlers", handler: "handleImportTiddlersEvent"},
|
2015-08-09 10:10:04 +00:00
|
|
|
{type: "tm-perform-import", handler: "handlePerformImportEvent"},
|
2015-08-09 11:56:48 +00:00
|
|
|
{type: "tm-fold-tiddler", handler: "handleFoldTiddlerEvent"},
|
2015-08-09 16:25:01 +00:00
|
|
|
{type: "tm-fold-other-tiddlers", handler: "handleFoldOtherTiddlersEvent"},
|
|
|
|
{type: "tm-fold-all-tiddlers", handler: "handleFoldAllTiddlersEvent"},
|
2015-08-30 18:11:14 +00:00
|
|
|
{type: "tm-unfold-all-tiddlers", handler: "handleUnfoldAllTiddlersEvent"},
|
|
|
|
{type: "tm-rename-tiddler", handler: "handleRenameTiddlerEvent"}
|
2013-10-12 16:05:13 +00:00
|
|
|
]);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Inherit from the base widget class
|
|
|
|
*/
|
|
|
|
NavigatorWidget.prototype = new Widget();
|
|
|
|
|
|
|
|
/*
|
|
|
|
Render this widget into the DOM
|
|
|
|
*/
|
|
|
|
NavigatorWidget.prototype.render = function(parent,nextSibling) {
|
|
|
|
this.parentDomNode = parent;
|
|
|
|
this.computeAttributes();
|
|
|
|
this.execute();
|
|
|
|
this.renderChildren(parent,nextSibling);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Compute the internal state of the widget
|
|
|
|
*/
|
|
|
|
NavigatorWidget.prototype.execute = function() {
|
|
|
|
// Get our parameters
|
|
|
|
this.storyTitle = this.getAttribute("story");
|
|
|
|
this.historyTitle = this.getAttribute("history");
|
2017-06-29 07:47:26 +00:00
|
|
|
this.setVariable("tv-story-list",this.storyTitle);
|
|
|
|
this.setVariable("tv-history-list",this.historyTitle);
|
2013-10-12 16:05:13 +00:00
|
|
|
// Construct the child widgets
|
|
|
|
this.makeChildWidgets();
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering
|
|
|
|
*/
|
|
|
|
NavigatorWidget.prototype.refresh = function(changedTiddlers) {
|
|
|
|
var changedAttributes = this.computeAttributes();
|
2014-02-07 10:12:45 +00:00
|
|
|
if(changedAttributes.story || changedAttributes.history) {
|
2013-10-12 16:05:13 +00:00
|
|
|
this.refreshSelf();
|
|
|
|
return true;
|
|
|
|
} else {
|
2016-10-08 11:17:27 +00:00
|
|
|
return this.refreshChildren(changedTiddlers);
|
2013-10-12 16:05:13 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
NavigatorWidget.prototype.getStoryList = function() {
|
2013-12-12 15:17:12 +00:00
|
|
|
return this.storyTitle ? this.wiki.getTiddlerList(this.storyTitle) : null;
|
2013-10-12 16:05:13 +00:00
|
|
|
};
|
|
|
|
|
2013-12-12 15:17:12 +00:00
|
|
|
NavigatorWidget.prototype.saveStoryList = function(storyList) {
|
2013-10-12 16:05:13 +00:00
|
|
|
var storyTiddler = this.wiki.getTiddler(this.storyTitle);
|
2013-12-12 15:17:12 +00:00
|
|
|
this.wiki.addTiddler(new $tw.Tiddler(
|
|
|
|
{title: this.storyTitle},
|
|
|
|
storyTiddler,
|
|
|
|
{list: storyList}
|
|
|
|
));
|
2013-10-12 16:05:13 +00:00
|
|
|
};
|
|
|
|
|
2013-12-12 15:17:12 +00:00
|
|
|
NavigatorWidget.prototype.removeTitleFromStory = function(storyList,title) {
|
|
|
|
var p = storyList.indexOf(title);
|
|
|
|
while(p !== -1) {
|
|
|
|
storyList.splice(p,1);
|
|
|
|
p = storyList.indexOf(title);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
NavigatorWidget.prototype.replaceFirstTitleInStory = function(storyList,oldTitle,newTitle) {
|
|
|
|
var pos = storyList.indexOf(oldTitle);
|
|
|
|
if(pos !== -1) {
|
|
|
|
storyList[pos] = newTitle;
|
|
|
|
do {
|
|
|
|
pos = storyList.indexOf(oldTitle,pos + 1);
|
|
|
|
if(pos !== -1) {
|
|
|
|
storyList.splice(pos,1);
|
|
|
|
}
|
|
|
|
} while(pos !== -1);
|
|
|
|
} else {
|
|
|
|
storyList.splice(0,0,newTitle);
|
|
|
|
}
|
|
|
|
};
|
2015-05-04 19:29:00 +00:00
|
|
|
|
2013-12-12 15:17:12 +00:00
|
|
|
NavigatorWidget.prototype.addToStory = function(title,fromTitle) {
|
|
|
|
var storyList = this.getStoryList();
|
2015-04-15 21:02:11 +00:00
|
|
|
// Quit if we cannot get hold of the story list
|
|
|
|
if(!storyList) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// See if the tiddler is already there
|
|
|
|
var slot = storyList.indexOf(title);
|
|
|
|
// Quit if it already exists in the story river
|
|
|
|
if(slot >= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// First we try to find the position of the story element we navigated from
|
|
|
|
var fromIndex = storyList.indexOf(fromTitle);
|
|
|
|
if(fromIndex >= 0) {
|
|
|
|
// The tiddler is added from inside the river
|
|
|
|
// Determine where to insert the tiddler; Fallback is "below"
|
2015-06-19 15:44:20 +00:00
|
|
|
switch(this.getAttribute("openLinkFromInsideRiver","below")) {
|
2015-04-15 21:02:11 +00:00
|
|
|
case "top":
|
|
|
|
slot = 0;
|
|
|
|
break;
|
|
|
|
case "bottom":
|
|
|
|
slot = storyList.length;
|
|
|
|
break;
|
|
|
|
case "above":
|
|
|
|
slot = fromIndex;
|
|
|
|
break;
|
2015-06-19 15:44:20 +00:00
|
|
|
case "below": // Intentional fall-through
|
2015-04-15 21:02:11 +00:00
|
|
|
default:
|
|
|
|
slot = fromIndex + 1;
|
2015-06-19 15:44:20 +00:00
|
|
|
break;
|
2015-04-15 21:02:11 +00:00
|
|
|
}
|
|
|
|
} else {
|
2015-06-19 15:44:20 +00:00
|
|
|
// The tiddler is opened from outside the river. Determine where to insert the tiddler; default is "top"
|
|
|
|
if(this.getAttribute("openLinkFromOutsideRiver","top") === "bottom") {
|
2015-04-15 21:02:11 +00:00
|
|
|
// Insert at bottom
|
2015-05-04 19:29:00 +00:00
|
|
|
slot = storyList.length;
|
2015-04-15 21:02:11 +00:00
|
|
|
} else {
|
|
|
|
// Insert at top
|
|
|
|
slot = 0;
|
2013-10-12 16:05:13 +00:00
|
|
|
}
|
2013-12-12 15:17:12 +00:00
|
|
|
}
|
2015-04-15 21:02:11 +00:00
|
|
|
// Add the tiddler
|
|
|
|
storyList.splice(slot,0,title);
|
|
|
|
// Save the story
|
|
|
|
this.saveStoryList(storyList);
|
2013-10-12 16:05:13 +00:00
|
|
|
};
|
|
|
|
|
2013-12-11 16:30:25 +00:00
|
|
|
/*
|
|
|
|
Add a new record to the top of the history stack
|
2013-12-12 15:17:12 +00:00
|
|
|
title: a title string or an array of title strings
|
|
|
|
fromPageRect: page coordinates of the origin of the navigation
|
2013-12-11 16:30:25 +00:00
|
|
|
*/
|
|
|
|
NavigatorWidget.prototype.addToHistory = function(title,fromPageRect) {
|
2014-05-03 10:32:55 +00:00
|
|
|
this.wiki.addToHistory(title,fromPageRect,this.historyTitle);
|
2013-12-11 16:30:25 +00:00
|
|
|
};
|
|
|
|
|
2013-10-12 16:05:13 +00:00
|
|
|
/*
|
2014-08-28 20:43:44 +00:00
|
|
|
Handle a tm-navigate event
|
2013-10-12 16:05:13 +00:00
|
|
|
*/
|
|
|
|
NavigatorWidget.prototype.handleNavigateEvent = function(event) {
|
2017-02-19 15:47:37 +00:00
|
|
|
event = $tw.hooks.invokeHook("th-navigating",event);
|
2015-02-20 16:19:53 +00:00
|
|
|
if(event.navigateTo) {
|
|
|
|
this.addToStory(event.navigateTo,event.navigateFromTitle);
|
|
|
|
if(!event.navigateSuppressNavigation) {
|
|
|
|
this.addToHistory(event.navigateTo,event.navigateFromClientRect);
|
|
|
|
}
|
2014-02-12 22:00:12 +00:00
|
|
|
}
|
2013-10-12 16:05:13 +00:00
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2013-10-13 20:31:00 +00:00
|
|
|
// Close a specified tiddler
|
|
|
|
NavigatorWidget.prototype.handleCloseTiddlerEvent = function(event) {
|
2013-12-12 15:17:12 +00:00
|
|
|
var title = event.param || event.tiddlerTitle,
|
|
|
|
storyList = this.getStoryList();
|
2013-10-13 20:31:00 +00:00
|
|
|
// Look for tiddlers with this title to close
|
2013-12-12 15:17:12 +00:00
|
|
|
this.removeTitleFromStory(storyList,title);
|
|
|
|
this.saveStoryList(storyList);
|
2013-10-13 20:31:00 +00:00
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2013-10-15 13:30:36 +00:00
|
|
|
// Close all tiddlers
|
|
|
|
NavigatorWidget.prototype.handleCloseAllTiddlersEvent = function(event) {
|
2013-12-12 15:17:12 +00:00
|
|
|
this.saveStoryList([]);
|
2013-10-15 13:30:36 +00:00
|
|
|
return false;
|
|
|
|
};
|
2013-12-12 15:17:12 +00:00
|
|
|
|
2013-11-11 13:48:54 +00:00
|
|
|
// Close other tiddlers
|
|
|
|
NavigatorWidget.prototype.handleCloseOtherTiddlersEvent = function(event) {
|
2013-12-12 15:17:12 +00:00
|
|
|
var title = event.param || event.tiddlerTitle;
|
|
|
|
this.saveStoryList([title]);
|
2013-11-11 04:09:52 +00:00
|
|
|
return false;
|
|
|
|
};
|
2013-10-15 13:30:36 +00:00
|
|
|
|
|
|
|
// Place a tiddler in edit mode
|
|
|
|
NavigatorWidget.prototype.handleEditTiddlerEvent = function(event) {
|
2017-06-29 07:55:43 +00:00
|
|
|
var editTiddler = $tw.hooks.invokeHook("th-editing-tiddler",event);
|
|
|
|
if(!editTiddler) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-05-07 13:49:14 +00:00
|
|
|
var self = this;
|
2014-04-25 13:40:24 +00:00
|
|
|
function isUnmodifiedShadow(title) {
|
2014-10-09 16:30:53 +00:00
|
|
|
return self.wiki.isShadowTiddler(title) && !self.wiki.tiddlerExists(title);
|
2014-04-25 13:40:24 +00:00
|
|
|
}
|
|
|
|
function confirmEditShadow(title) {
|
|
|
|
return confirm($tw.language.getString(
|
|
|
|
"ConfirmEditShadowTiddler",
|
|
|
|
{variables:
|
|
|
|
{title: title}
|
|
|
|
}
|
|
|
|
));
|
|
|
|
}
|
|
|
|
var title = event.param || event.tiddlerTitle;
|
|
|
|
if(isUnmodifiedShadow(title) && !confirmEditShadow(title)) {
|
|
|
|
return false;
|
|
|
|
}
|
2013-10-15 13:30:36 +00:00
|
|
|
// Replace the specified tiddler with a draft in edit mode
|
2015-08-05 14:07:19 +00:00
|
|
|
var draftTiddler = this.makeDraftTiddler(title);
|
|
|
|
// Update the story and history if required
|
|
|
|
if(!event.paramObject || event.paramObject.suppressNavigation !== "yes") {
|
|
|
|
var draftTitle = draftTiddler.fields.title,
|
|
|
|
storyList = this.getStoryList();
|
|
|
|
this.removeTitleFromStory(storyList,draftTitle);
|
|
|
|
this.replaceFirstTitleInStory(storyList,title,draftTitle);
|
|
|
|
this.addToHistory(draftTitle,event.navigateFromClientRect);
|
|
|
|
this.saveStoryList(storyList);
|
|
|
|
return false;
|
|
|
|
}
|
2013-10-15 13:30:36 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Delete a tiddler
|
|
|
|
NavigatorWidget.prototype.handleDeleteTiddlerEvent = function(event) {
|
|
|
|
// Get the tiddler we're deleting
|
2013-12-04 13:09:26 +00:00
|
|
|
var title = event.param || event.tiddlerTitle,
|
2013-12-12 15:17:12 +00:00
|
|
|
tiddler = this.wiki.getTiddler(title),
|
2014-04-09 10:32:08 +00:00
|
|
|
storyList = this.getStoryList(),
|
2015-02-09 21:46:54 +00:00
|
|
|
originalTitle = tiddler ? tiddler.fields["draft.of"] : "",
|
2017-02-09 15:42:55 +00:00
|
|
|
originalTiddler = originalTitle ? this.wiki.getTiddler(originalTitle) : undefined,
|
2014-11-11 11:54:46 +00:00
|
|
|
confirmationTitle;
|
2015-02-09 11:28:42 +00:00
|
|
|
if(!tiddler) {
|
|
|
|
return false;
|
|
|
|
}
|
2013-10-15 13:30:36 +00:00
|
|
|
// Check if the tiddler we're deleting is in draft mode
|
2014-11-11 11:54:46 +00:00
|
|
|
if(originalTitle) {
|
2014-04-09 10:32:08 +00:00
|
|
|
// If so, we'll prompt for confirmation referencing the original tiddler
|
|
|
|
confirmationTitle = originalTitle;
|
|
|
|
} else {
|
|
|
|
// If not a draft, then prompt for confirmation referencing the specified tiddler
|
|
|
|
confirmationTitle = title;
|
|
|
|
}
|
|
|
|
// Seek confirmation
|
2014-11-11 11:54:46 +00:00
|
|
|
if((this.wiki.getTiddler(originalTitle) || (tiddler.fields.text || "") !== "") && !confirm($tw.language.getString(
|
2014-04-09 10:32:08 +00:00
|
|
|
"ConfirmDeleteTiddler",
|
|
|
|
{variables:
|
|
|
|
{title: confirmationTitle}
|
|
|
|
}
|
|
|
|
))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Delete the original tiddler
|
|
|
|
if(originalTitle) {
|
2017-02-09 15:42:55 +00:00
|
|
|
if(originalTiddler) {
|
|
|
|
$tw.hooks.invokeHook("th-deleting-tiddler",originalTiddler);
|
|
|
|
}
|
2013-12-12 15:17:12 +00:00
|
|
|
this.wiki.deleteTiddler(originalTitle);
|
|
|
|
this.removeTitleFromStory(storyList,originalTitle);
|
2013-10-15 13:30:36 +00:00
|
|
|
}
|
2017-02-09 15:42:55 +00:00
|
|
|
// Invoke the hook function and delete this tiddler
|
|
|
|
$tw.hooks.invokeHook("th-deleting-tiddler",tiddler);
|
2013-12-04 13:09:26 +00:00
|
|
|
this.wiki.deleteTiddler(title);
|
2013-10-15 13:30:36 +00:00
|
|
|
// Remove the closed tiddler from the story
|
2013-12-12 15:17:12 +00:00
|
|
|
this.removeTitleFromStory(storyList,title);
|
|
|
|
this.saveStoryList(storyList);
|
2014-08-29 08:58:30 +00:00
|
|
|
// Trigger an autosave
|
2014-09-02 10:16:06 +00:00
|
|
|
$tw.rootWidget.dispatchEvent({type: "tm-auto-save-wiki"});
|
2013-10-15 13:30:36 +00:00
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2013-11-07 19:39:26 +00:00
|
|
|
/*
|
|
|
|
Create/reuse the draft tiddler for a given title
|
|
|
|
*/
|
2013-12-12 15:17:12 +00:00
|
|
|
NavigatorWidget.prototype.makeDraftTiddler = function(targetTitle) {
|
2013-11-07 19:39:26 +00:00
|
|
|
// See if there is already a draft tiddler for this tiddler
|
2014-10-09 16:30:53 +00:00
|
|
|
var draftTitle = this.wiki.findDraft(targetTitle);
|
|
|
|
if(draftTitle) {
|
2014-10-10 08:03:35 +00:00
|
|
|
return this.wiki.getTiddler(draftTitle);
|
2013-11-07 19:39:26 +00:00
|
|
|
}
|
|
|
|
// Get the current value of the tiddler we're editing
|
2014-10-09 16:30:53 +00:00
|
|
|
var tiddler = this.wiki.getTiddler(targetTitle);
|
2013-11-07 19:39:26 +00:00
|
|
|
// Save the initial value of the draft tiddler
|
2014-10-09 16:30:53 +00:00
|
|
|
draftTitle = this.generateDraftTitle(targetTitle);
|
2013-11-07 19:39:26 +00:00
|
|
|
var draftTiddler = new $tw.Tiddler(
|
|
|
|
tiddler,
|
|
|
|
{
|
|
|
|
title: draftTitle,
|
|
|
|
"draft.title": targetTitle,
|
|
|
|
"draft.of": targetTitle
|
|
|
|
},
|
|
|
|
this.wiki.getModificationFields()
|
|
|
|
);
|
|
|
|
this.wiki.addTiddler(draftTiddler);
|
|
|
|
return draftTiddler;
|
|
|
|
};
|
|
|
|
|
2013-10-15 13:30:36 +00:00
|
|
|
/*
|
|
|
|
Generate a title for the draft of a given tiddler
|
|
|
|
*/
|
|
|
|
NavigatorWidget.prototype.generateDraftTitle = function(title) {
|
2014-08-30 19:44:26 +00:00
|
|
|
var c = 0,
|
2018-08-23 16:43:06 +00:00
|
|
|
draftTitle,
|
|
|
|
username = this.wiki.getTiddlerText("$:/status/UserName"),
|
|
|
|
attribution = username ? " by " + username : "";
|
2013-10-15 13:30:36 +00:00
|
|
|
do {
|
2018-08-23 16:43:06 +00:00
|
|
|
draftTitle = "Draft " + (c ? (c + 1) + " " : "") + "of '" + title + "'" + attribution;
|
2013-10-15 13:30:36 +00:00
|
|
|
c++;
|
|
|
|
} while(this.wiki.tiddlerExists(draftTitle));
|
|
|
|
return draftTitle;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Take a tiddler out of edit mode, saving the changes
|
|
|
|
NavigatorWidget.prototype.handleSaveTiddlerEvent = function(event) {
|
2013-12-04 13:09:26 +00:00
|
|
|
var title = event.param || event.tiddlerTitle,
|
2013-12-12 15:17:12 +00:00
|
|
|
tiddler = this.wiki.getTiddler(title),
|
2014-04-25 02:16:32 +00:00
|
|
|
storyList = this.getStoryList();
|
2013-12-12 15:17:12 +00:00
|
|
|
// Replace the original tiddler with the draft
|
|
|
|
if(tiddler) {
|
|
|
|
var draftTitle = (tiddler.fields["draft.title"] || "").trim(),
|
|
|
|
draftOf = (tiddler.fields["draft.of"] || "").trim();
|
|
|
|
if(draftTitle) {
|
|
|
|
var isRename = draftOf !== draftTitle,
|
|
|
|
isConfirmed = true;
|
|
|
|
if(isRename && this.wiki.tiddlerExists(draftTitle)) {
|
2014-03-20 20:55:59 +00:00
|
|
|
isConfirmed = confirm($tw.language.getString(
|
|
|
|
"ConfirmOverwriteTiddler",
|
|
|
|
{variables:
|
|
|
|
{title: draftTitle}
|
|
|
|
}
|
|
|
|
));
|
2014-06-22 10:45:00 +00:00
|
|
|
}
|
2014-11-10 12:56:33 +00:00
|
|
|
if(isConfirmed) {
|
2015-09-08 15:16:50 +00:00
|
|
|
// Create the new tiddler and pass it through the th-saving-tiddler hook
|
|
|
|
var newTiddler = new $tw.Tiddler(this.wiki.getCreationFields(),tiddler,{
|
2013-12-12 15:17:12 +00:00
|
|
|
title: draftTitle,
|
2014-04-25 12:46:51 +00:00
|
|
|
"draft.title": undefined,
|
2013-12-12 15:17:12 +00:00
|
|
|
"draft.of": undefined
|
2015-09-08 15:16:50 +00:00
|
|
|
},this.wiki.getModificationFields());
|
|
|
|
newTiddler = $tw.hooks.invokeHook("th-saving-tiddler",newTiddler);
|
|
|
|
this.wiki.addTiddler(newTiddler);
|
2016-12-15 17:12:57 +00:00
|
|
|
// If enabled, relink references to renamed tiddler
|
|
|
|
var shouldRelink = this.getAttribute("relinkOnRename","no").toLowerCase().trim() === "yes";
|
|
|
|
if(isRename && shouldRelink && this.wiki.tiddlerExists(draftOf)) {
|
|
|
|
console.log("Relinking '" + draftOf + "' to '" + draftTitle + "'");
|
|
|
|
this.wiki.relinkTiddler(draftOf,draftTitle);
|
|
|
|
}
|
2013-12-12 15:17:12 +00:00
|
|
|
// Remove the draft tiddler
|
|
|
|
this.wiki.deleteTiddler(title);
|
|
|
|
// Remove the original tiddler if we're renaming it
|
|
|
|
if(isRename) {
|
|
|
|
this.wiki.deleteTiddler(draftOf);
|
|
|
|
}
|
2016-10-08 11:17:27 +00:00
|
|
|
// #2381 always remove new title & old
|
|
|
|
this.removeTitleFromStory(storyList,draftTitle);
|
|
|
|
this.removeTitleFromStory(storyList,draftOf);
|
2015-08-05 14:07:19 +00:00
|
|
|
if(!event.paramObject || event.paramObject.suppressNavigation !== "yes") {
|
|
|
|
// Replace the draft in the story with the original
|
|
|
|
this.replaceFirstTitleInStory(storyList,title,draftTitle);
|
|
|
|
this.addToHistory(draftTitle,event.navigateFromClientRect);
|
|
|
|
if(draftTitle !== this.storyTitle) {
|
|
|
|
this.saveStoryList(storyList);
|
|
|
|
}
|
2013-10-15 13:30:36 +00:00
|
|
|
}
|
2014-08-29 08:58:30 +00:00
|
|
|
// Trigger an autosave
|
2014-09-02 10:16:06 +00:00
|
|
|
$tw.rootWidget.dispatchEvent({type: "tm-auto-save-wiki"});
|
2013-10-15 13:30:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Take a tiddler out of edit mode without saving the changes
|
|
|
|
NavigatorWidget.prototype.handleCancelTiddlerEvent = function(event) {
|
2018-04-10 18:52:00 +00:00
|
|
|
event = $tw.hooks.invokeHook("th-cancelling-tiddler", event);
|
2013-12-06 08:45:24 +00:00
|
|
|
// Flip the specified tiddler from draft back to the original
|
|
|
|
var draftTitle = event.param || event.tiddlerTitle,
|
2013-12-12 15:17:12 +00:00
|
|
|
draftTiddler = this.wiki.getTiddler(draftTitle),
|
2014-12-22 08:40:11 +00:00
|
|
|
originalTitle = draftTiddler && draftTiddler.fields["draft.of"];
|
2013-12-12 15:17:12 +00:00
|
|
|
if(draftTiddler && originalTitle) {
|
2014-04-12 13:15:49 +00:00
|
|
|
// Ask for confirmation if the tiddler text has changed
|
2014-12-22 08:40:11 +00:00
|
|
|
var isConfirmed = true,
|
|
|
|
originalTiddler = this.wiki.getTiddler(originalTitle),
|
|
|
|
storyList = this.getStoryList();
|
2014-11-09 21:47:48 +00:00
|
|
|
if(this.wiki.isDraftModified(draftTitle)) {
|
2014-04-12 13:15:49 +00:00
|
|
|
isConfirmed = confirm($tw.language.getString(
|
|
|
|
"ConfirmCancelTiddler",
|
|
|
|
{variables:
|
|
|
|
{title: draftTitle}
|
|
|
|
}
|
|
|
|
));
|
|
|
|
}
|
2013-12-06 08:45:24 +00:00
|
|
|
// Remove the draft tiddler
|
2014-04-12 13:15:49 +00:00
|
|
|
if(isConfirmed) {
|
|
|
|
this.wiki.deleteTiddler(draftTitle);
|
2015-08-05 14:07:19 +00:00
|
|
|
if(!event.paramObject || event.paramObject.suppressNavigation !== "yes") {
|
|
|
|
if(originalTiddler) {
|
|
|
|
this.replaceFirstTitleInStory(storyList,draftTitle,originalTitle);
|
|
|
|
this.addToHistory(originalTitle,event.navigateFromClientRect);
|
|
|
|
} else {
|
|
|
|
this.removeTitleFromStory(storyList,draftTitle);
|
|
|
|
}
|
|
|
|
this.saveStoryList(storyList);
|
2014-11-09 21:47:48 +00:00
|
|
|
}
|
2014-04-12 13:15:49 +00:00
|
|
|
}
|
2013-10-15 13:30:36 +00:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Create a new draft tiddler
|
2014-10-09 16:30:53 +00:00
|
|
|
// event.param can either be the title of a template tiddler, or a hashmap of fields.
|
|
|
|
//
|
|
|
|
// The title of the newly created tiddler follows these rules:
|
|
|
|
// * If a hashmap was used and a title field was specified, use that title
|
|
|
|
// * If a hashmap was used without a title field, use a default title, if necessary making it unique with a numeric suffix
|
|
|
|
// * If a template tiddler was used, use the title of the template, if necessary making it unique with a numeric suffix
|
|
|
|
//
|
|
|
|
// If a draft of the target tiddler already exists then it is reused
|
2013-10-15 13:30:36 +00:00
|
|
|
NavigatorWidget.prototype.handleNewTiddlerEvent = function(event) {
|
2018-04-10 18:52:00 +00:00
|
|
|
event = $tw.hooks.invokeHook("th-new-tiddler", event);
|
2013-10-15 13:30:36 +00:00
|
|
|
// Get the story details
|
2014-10-08 16:45:26 +00:00
|
|
|
var storyList = this.getStoryList(),
|
2014-11-18 14:13:34 +00:00
|
|
|
templateTiddler, additionalFields, title, draftTitle, existingTiddler;
|
2014-11-07 14:53:37 +00:00
|
|
|
// Get the template tiddler (if any)
|
|
|
|
if(typeof event.param === "string") {
|
|
|
|
// Get the template tiddler
|
2014-10-10 08:52:19 +00:00
|
|
|
templateTiddler = this.wiki.getTiddler(event.param);
|
2014-11-07 14:53:37 +00:00
|
|
|
// Generate a new title
|
2014-10-10 08:52:19 +00:00
|
|
|
title = this.wiki.generateNewTitle(event.param || $tw.language.getString("DefaultNewTiddlerTitle"));
|
2014-10-09 16:30:53 +00:00
|
|
|
}
|
2014-11-07 14:53:37 +00:00
|
|
|
// Get the specified additional fields
|
|
|
|
if(typeof event.paramObject === "object") {
|
|
|
|
additionalFields = event.paramObject;
|
|
|
|
}
|
|
|
|
if(typeof event.param === "object") { // Backwards compatibility with 5.1.3
|
|
|
|
additionalFields = event.param;
|
|
|
|
}
|
2014-11-07 21:15:52 +00:00
|
|
|
if(additionalFields && additionalFields.title) {
|
2014-11-07 14:53:37 +00:00
|
|
|
title = additionalFields.title;
|
|
|
|
}
|
2017-11-08 08:41:00 +00:00
|
|
|
// Make a copy of the additional fields excluding any blank ones
|
|
|
|
var filteredAdditionalFields = $tw.utils.extend({},additionalFields);
|
|
|
|
Object.keys(filteredAdditionalFields).forEach(function(fieldName) {
|
|
|
|
if(filteredAdditionalFields[fieldName] === "") {
|
|
|
|
delete filteredAdditionalFields[fieldName];
|
|
|
|
}
|
|
|
|
});
|
2014-11-07 14:53:37 +00:00
|
|
|
// Generate a title if we don't have one
|
|
|
|
title = title || this.wiki.generateNewTitle($tw.language.getString("DefaultNewTiddlerTitle"));
|
2014-10-10 08:52:19 +00:00
|
|
|
// Find any existing draft for this tiddler
|
|
|
|
draftTitle = this.wiki.findDraft(title);
|
|
|
|
// Pull in any existing tiddler
|
|
|
|
if(draftTitle) {
|
|
|
|
existingTiddler = this.wiki.getTiddler(draftTitle);
|
|
|
|
} else {
|
2014-10-09 16:30:53 +00:00
|
|
|
draftTitle = this.generateDraftTitle(title);
|
2014-10-10 08:52:19 +00:00
|
|
|
existingTiddler = this.wiki.getTiddler(title);
|
|
|
|
}
|
|
|
|
// Merge the tags
|
2014-11-18 14:13:34 +00:00
|
|
|
var mergedTags = [];
|
|
|
|
if(existingTiddler && existingTiddler.fields.tags) {
|
2016-10-08 11:17:27 +00:00
|
|
|
$tw.utils.pushTop(mergedTags,existingTiddler.fields.tags);
|
2014-11-18 14:13:34 +00:00
|
|
|
}
|
|
|
|
if(additionalFields && additionalFields.tags) {
|
|
|
|
// Merge tags
|
|
|
|
mergedTags = $tw.utils.pushTop(mergedTags,$tw.utils.parseStringArray(additionalFields.tags));
|
|
|
|
}
|
|
|
|
if(templateTiddler && templateTiddler.fields.tags) {
|
2014-10-10 08:52:19 +00:00
|
|
|
// Merge tags
|
2014-11-18 14:13:34 +00:00
|
|
|
mergedTags = $tw.utils.pushTop(mergedTags,templateTiddler.fields.tags);
|
2014-10-09 16:30:53 +00:00
|
|
|
}
|
2014-10-10 08:52:19 +00:00
|
|
|
// Save the draft tiddler
|
|
|
|
var draftTiddler = new $tw.Tiddler({
|
2014-10-10 19:58:34 +00:00
|
|
|
text: "",
|
|
|
|
"draft.title": title
|
2014-10-10 08:52:19 +00:00
|
|
|
},
|
|
|
|
templateTiddler,
|
2014-11-07 14:53:37 +00:00
|
|
|
additionalFields,
|
2018-08-08 14:08:34 +00:00
|
|
|
this.wiki.getCreationFields(),
|
2017-11-08 08:41:00 +00:00
|
|
|
existingTiddler,
|
|
|
|
filteredAdditionalFields,
|
2014-10-10 08:52:19 +00:00
|
|
|
{
|
|
|
|
title: draftTitle,
|
|
|
|
"draft.of": title,
|
|
|
|
tags: mergedTags
|
|
|
|
},this.wiki.getModificationFields());
|
|
|
|
this.wiki.addTiddler(draftTiddler);
|
2014-10-09 16:30:53 +00:00
|
|
|
// Update the story to insert the new draft at the top and remove any existing tiddler
|
|
|
|
if(storyList.indexOf(draftTitle) === -1) {
|
|
|
|
var slot = storyList.indexOf(event.navigateFromTitle);
|
|
|
|
storyList.splice(slot + 1,0,draftTitle);
|
|
|
|
}
|
|
|
|
if(storyList.indexOf(title) !== -1) {
|
2017-06-29 07:36:20 +00:00
|
|
|
storyList.splice(storyList.indexOf(title),1);
|
2014-10-08 16:45:26 +00:00
|
|
|
}
|
2013-12-12 15:17:12 +00:00
|
|
|
this.saveStoryList(storyList);
|
2013-10-15 13:30:36 +00:00
|
|
|
// Add a new record to the top of the history stack
|
2013-12-11 16:30:25 +00:00
|
|
|
this.addToHistory(draftTitle);
|
2013-10-15 13:30:36 +00:00
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2014-07-12 08:09:36 +00:00
|
|
|
// Import JSON tiddlers into a pending import tiddler
|
2013-10-25 20:15:32 +00:00
|
|
|
NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) {
|
|
|
|
// Get the tiddlers
|
|
|
|
var tiddlers = [];
|
|
|
|
try {
|
2017-06-29 07:36:20 +00:00
|
|
|
tiddlers = JSON.parse(event.param);
|
2013-10-25 20:15:32 +00:00
|
|
|
} catch(e) {
|
|
|
|
}
|
2014-07-12 08:09:36 +00:00
|
|
|
// Get the current $:/Import tiddler
|
2014-07-17 14:02:42 +00:00
|
|
|
var importTiddler = this.wiki.getTiddler(IMPORT_TITLE),
|
2014-07-12 08:09:36 +00:00
|
|
|
importData = this.wiki.getTiddlerData(IMPORT_TITLE,{}),
|
|
|
|
newFields = new Object({
|
|
|
|
title: IMPORT_TITLE,
|
|
|
|
type: "application/json",
|
2014-07-14 13:53:21 +00:00
|
|
|
"plugin-type": "import",
|
|
|
|
"status": "pending"
|
2014-07-12 08:09:36 +00:00
|
|
|
}),
|
|
|
|
incomingTiddlers = [];
|
2013-10-25 20:15:32 +00:00
|
|
|
// Process each tiddler
|
2014-07-12 08:09:36 +00:00
|
|
|
importData.tiddlers = importData.tiddlers || {};
|
2013-10-25 20:15:32 +00:00
|
|
|
$tw.utils.each(tiddlers,function(tiddlerFields) {
|
2017-06-29 16:07:23 +00:00
|
|
|
tiddlerFields.title = $tw.utils.trim(tiddlerFields.title);
|
2013-12-02 09:59:38 +00:00
|
|
|
var title = tiddlerFields.title;
|
2014-07-12 08:09:36 +00:00
|
|
|
if(title) {
|
|
|
|
incomingTiddlers.push(title);
|
|
|
|
importData.tiddlers[title] = tiddlerFields;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// Give the active upgrader modules a chance to process the incoming tiddlers
|
|
|
|
var messages = this.wiki.invokeUpgraders(incomingTiddlers,importData.tiddlers);
|
|
|
|
$tw.utils.each(messages,function(message,title) {
|
|
|
|
newFields["message-" + title] = message;
|
|
|
|
});
|
|
|
|
// Deselect any suppressed tiddlers
|
|
|
|
$tw.utils.each(importData.tiddlers,function(tiddler,title) {
|
|
|
|
if($tw.utils.count(tiddler) === 0) {
|
|
|
|
newFields["selection-" + title] = "unchecked";
|
2013-10-25 20:15:32 +00:00
|
|
|
}
|
|
|
|
});
|
2014-07-12 08:09:36 +00:00
|
|
|
// Save the $:/Import tiddler
|
|
|
|
newFields.text = JSON.stringify(importData,null,$tw.config.preferences.jsonSpaces);
|
|
|
|
this.wiki.addTiddler(new $tw.Tiddler(importTiddler,newFields));
|
2014-07-14 13:53:21 +00:00
|
|
|
// Update the story and history details
|
2014-08-28 21:28:02 +00:00
|
|
|
if(this.getVariable("tv-auto-open-on-import") !== "no") {
|
2014-07-14 13:53:21 +00:00
|
|
|
var storyList = this.getStoryList(),
|
|
|
|
history = [];
|
|
|
|
// Add it to the story
|
|
|
|
if(storyList.indexOf(IMPORT_TITLE) === -1) {
|
|
|
|
storyList.unshift(IMPORT_TITLE);
|
|
|
|
}
|
|
|
|
// And to history
|
|
|
|
history.push(IMPORT_TITLE);
|
|
|
|
// Save the updated story and history
|
|
|
|
this.saveStoryList(storyList);
|
2016-10-08 11:17:27 +00:00
|
|
|
this.addToHistory(history);
|
2014-02-21 18:15:18 +00:00
|
|
|
}
|
2013-10-25 20:15:32 +00:00
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2017-06-29 07:36:20 +00:00
|
|
|
//
|
2014-07-12 08:09:36 +00:00
|
|
|
NavigatorWidget.prototype.handlePerformImportEvent = function(event) {
|
|
|
|
var self = this,
|
2014-07-17 14:02:42 +00:00
|
|
|
importTiddler = this.wiki.getTiddler(event.param),
|
2015-07-10 15:43:50 +00:00
|
|
|
importData = this.wiki.getTiddlerDataCached(event.param,{tiddlers: {}}),
|
2014-07-12 08:09:36 +00:00
|
|
|
importReport = [];
|
|
|
|
// Add the tiddlers to the store
|
2016-07-13 09:00:21 +00:00
|
|
|
importReport.push($tw.language.getString("Import/Imported/Hint") + "\n");
|
2014-07-12 08:09:36 +00:00
|
|
|
$tw.utils.each(importData.tiddlers,function(tiddlerFields) {
|
|
|
|
var title = tiddlerFields.title;
|
2014-07-17 14:02:42 +00:00
|
|
|
if(title && importTiddler && importTiddler.fields["selection-" + title] !== "unchecked") {
|
2017-02-09 15:42:55 +00:00
|
|
|
var tiddler = new $tw.Tiddler(tiddlerFields);
|
|
|
|
tiddler = $tw.hooks.invokeHook("th-importing-tiddler",tiddler);
|
|
|
|
self.wiki.addTiddler(tiddler);
|
2014-07-12 08:09:36 +00:00
|
|
|
importReport.push("# [[" + tiddlerFields.title + "]]");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
// Replace the $:/Import tiddler with an import report
|
2014-07-14 13:53:21 +00:00
|
|
|
this.wiki.addTiddler(new $tw.Tiddler({
|
2015-08-01 12:48:46 +00:00
|
|
|
title: event.param,
|
2014-07-14 13:53:21 +00:00
|
|
|
text: importReport.join("\n"),
|
|
|
|
"status": "complete"
|
|
|
|
}));
|
2014-07-12 08:09:36 +00:00
|
|
|
// Navigate to the $:/Import tiddler
|
2015-08-01 12:48:46 +00:00
|
|
|
this.addToHistory([event.param]);
|
2014-08-29 08:58:30 +00:00
|
|
|
// Trigger an autosave
|
2014-09-02 10:16:06 +00:00
|
|
|
$tw.rootWidget.dispatchEvent({type: "tm-auto-save-wiki"});
|
2014-07-12 08:09:36 +00:00
|
|
|
};
|
|
|
|
|
2015-08-09 10:10:04 +00:00
|
|
|
NavigatorWidget.prototype.handleFoldTiddlerEvent = function(event) {
|
2016-10-08 11:17:27 +00:00
|
|
|
var paramObject = event.paramObject || {};
|
2015-08-09 10:10:04 +00:00
|
|
|
if(paramObject.foldedState) {
|
|
|
|
var foldedState = this.wiki.getTiddlerText(paramObject.foldedState,"show") === "show" ? "hide" : "show";
|
|
|
|
this.wiki.setText(paramObject.foldedState,"text",null,foldedState);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2015-08-09 11:56:48 +00:00
|
|
|
NavigatorWidget.prototype.handleFoldOtherTiddlersEvent = function(event) {
|
|
|
|
var self = this,
|
|
|
|
paramObject = event.paramObject || {},
|
|
|
|
prefix = paramObject.foldedStatePrefix;
|
|
|
|
$tw.utils.each(this.getStoryList(),function(title) {
|
2015-08-09 15:11:34 +00:00
|
|
|
self.wiki.setText(prefix + title,"text",null,event.param === title ? "show" : "hide");
|
2015-08-09 11:56:48 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-08-09 16:25:01 +00:00
|
|
|
NavigatorWidget.prototype.handleFoldAllTiddlersEvent = function(event) {
|
|
|
|
var self = this,
|
|
|
|
paramObject = event.paramObject || {},
|
|
|
|
prefix = paramObject.foldedStatePrefix;
|
|
|
|
$tw.utils.each(this.getStoryList(),function(title) {
|
|
|
|
self.wiki.setText(prefix + title,"text",null,"hide");
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
NavigatorWidget.prototype.handleUnfoldAllTiddlersEvent = function(event) {
|
|
|
|
var self = this,
|
|
|
|
paramObject = event.paramObject || {},
|
|
|
|
prefix = paramObject.foldedStatePrefix;
|
|
|
|
$tw.utils.each(this.getStoryList(),function(title) {
|
|
|
|
self.wiki.setText(prefix + title,"text",null,"show");
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2015-08-30 18:11:14 +00:00
|
|
|
NavigatorWidget.prototype.handleRenameTiddlerEvent = function(event) {
|
2018-04-10 18:52:00 +00:00
|
|
|
event = $tw.hooks.invokeHook("th-renaming-tiddler", event);
|
2016-10-08 11:17:27 +00:00
|
|
|
var paramObject = event.paramObject || {},
|
2015-08-30 18:11:14 +00:00
|
|
|
from = paramObject.from || event.tiddlerTitle,
|
|
|
|
to = paramObject.to;
|
|
|
|
$tw.wiki.renameTiddler(from,to);
|
|
|
|
};
|
|
|
|
|
2013-10-12 16:05:13 +00:00
|
|
|
exports.navigator = NavigatorWidget;
|
|
|
|
|
|
|
|
})();
|