1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-09-29 23:40:45 +00:00
TiddlyWiki5/core/modules/startup.js
Jermolene 28db76ddb3 Refactor page rendering into a separate function
Refactoring page rendering so that we can fix the performance issues
with editing drafts. The plan is to defer the refresh cycle if all the
changes are to draft tiddlers.

We need to do a bit more of this to get startup.js into better shape
(and more extensible).
2014-04-14 09:53:13 +01:00

262 lines
8.6 KiB
JavaScript
Executable File

/*\
title: $:/core/modules/startup.js
type: application/javascript
module-type: startup
This is the main application logic for both the client and server
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Set to `true` to enable performance instrumentation
var PERFORMANCE_INSTRUMENTATION = false;
var widget = require("$:/core/modules/widgets/widget.js");
exports.startup = function() {
var modules,n,m,f,commander;
// Load modules
$tw.modules.applyMethods("utils",$tw.utils);
if($tw.node) {
$tw.modules.applyMethods("utils-node",$tw.utils);
}
$tw.modules.applyMethods("global",$tw);
$tw.modules.applyMethods("config",$tw.config);
if($tw.browser) {
$tw.utils.getBrowserInfo($tw.browser);
}
$tw.version = $tw.utils.extractVersionInfo();
$tw.Tiddler.fieldModules = $tw.modules.getModulesByTypeAsHashmap("tiddlerfield");
$tw.modules.applyMethods("tiddlermethod",$tw.Tiddler.prototype);
$tw.modules.applyMethods("wikimethod",$tw.Wiki.prototype);
$tw.modules.applyMethods("tiddlerdeserializer",$tw.Wiki.tiddlerDeserializerModules);
$tw.macros = $tw.modules.getModulesByTypeAsHashmap("macro");
// Set up the performance framework
$tw.perf = new $tw.Performance(PERFORMANCE_INSTRUMENTATION);
// Set up the parsers
$tw.wiki.initParsers();
// Set up the command modules
$tw.Commander.initCommands();
// Kick off the language manager and switcher
$tw.language = new $tw.Language();
$tw.languageSwitcher = new $tw.PluginSwitcher({
wiki: $tw.wiki,
pluginType: "language",
controllerTitle: "$:/language",
defaultPlugins: [
"$:/languages/en-US"
]
});
// Kick off the theme manager
$tw.themeManager = new $tw.PluginSwitcher({
wiki: $tw.wiki,
pluginType: "theme",
controllerTitle: "$:/theme",
defaultPlugins: [
"$:/themes/tiddlywiki/snowwhite",
"$:/themes/tiddlywiki/vanilla"
]
});
// Display the default tiddlers
var displayDefaultTiddlers = function() {
// Get the default tiddlers
var defaultTiddlersTitle = "$:/DefaultTiddlers",
defaultTiddlersTiddler = $tw.wiki.getTiddler(defaultTiddlersTitle),
defaultTiddlers = [];
if(defaultTiddlersTiddler) {
defaultTiddlers = $tw.wiki.filterTiddlers(defaultTiddlersTiddler.fields.text);
}
// Initialise the story
var storyTitle = "$:/StoryList",
story = [];
for(var t=0; t<defaultTiddlers.length; t++) {
story[t] = defaultTiddlers[t];
}
$tw.wiki.addTiddler({title: storyTitle, text: "", list: story},$tw.wiki.getModificationFields());
};
displayDefaultTiddlers();
// Set up the syncer object
$tw.syncer = new $tw.Syncer({wiki: $tw.wiki});
// Host-specific startup
if($tw.browser) {
// Set up our beforeunload handler
window.addEventListener("beforeunload",function(event) {
var confirmationMessage = undefined;
if($tw.syncer.isDirty()) {
confirmationMessage = "You have unsaved changes in TiddlyWiki";
event.returnValue = confirmationMessage; // Gecko
}
return confirmationMessage;
});
// Install the popup manager
$tw.popup = new $tw.utils.Popup({
rootElement: document.body
});
// Install the animator
$tw.anim = new $tw.utils.Animator();
// Create a root widget for attaching event handlers. By using it as the parentWidget for another widget tree, one can reuse the event handlers
$tw.rootWidget = new widget.widget({
type: "widget",
children: []
},{
wiki: $tw.wiki,
document: document
});
// Install the modal message mechanism
$tw.modal = new $tw.utils.Modal($tw.wiki);
$tw.rootWidget.addEventListener("tw-modal",function(event) {
$tw.modal.display(event.param);
});
// Install the notification mechanism
$tw.notifier = new $tw.utils.Notifier($tw.wiki);
$tw.rootWidget.addEventListener("tw-notify",function(event) {
$tw.notifier.display(event.param);
});
// Install the scroller
$tw.pageScroller = new $tw.utils.PageScroller();
$tw.rootWidget.addEventListener("tw-scroll",function(event) {
$tw.pageScroller.handleEvent(event);
});
// Listen for the tw-home message
$tw.rootWidget.addEventListener("tw-home",function(event) {
displayDefaultTiddlers();
});
// Install the save action handlers
$tw.rootWidget.addEventListener("tw-save-wiki",function(event) {
$tw.syncer.saveWiki({
template: event.param,
downloadType: "text/plain"
});
});
$tw.rootWidget.addEventListener("tw-auto-save-wiki",function(event) {
$tw.syncer.saveWiki({
method: "autosave",
template: event.param,
downloadType: "text/plain"
});
});
$tw.rootWidget.addEventListener("tw-download-file",function(event) {
$tw.syncer.saveWiki({
method: "download",
template: event.param,
downloadType: "text/plain"
});
});
// Listen out for login/logout/refresh events in the browser
$tw.rootWidget.addEventListener("tw-login",function() {
$tw.syncer.handleLoginEvent();
});
$tw.rootWidget.addEventListener("tw-logout",function() {
$tw.syncer.handleLogoutEvent();
});
$tw.rootWidget.addEventListener("tw-server-refresh",function() {
$tw.syncer.handleRefreshEvent();
});
// Install the crypto event handlers
$tw.rootWidget.addEventListener("tw-set-password",function(event) {
$tw.passwordPrompt.createPrompt({
serviceName: "Set a new password for this TiddlyWiki",
noUserName: true,
submitText: "Set password",
canCancel: true,
callback: function(data) {
if(data) {
$tw.crypto.setPassword(data.password);
}
return true; // Get rid of the password prompt
}
});
});
$tw.rootWidget.addEventListener("tw-clear-password",function(event) {
$tw.crypto.setPassword(null);
});
// Ensure that $:/isEncrypted is maintained properly
$tw.wiki.addEventListener("change",function(changes) {
if($tw.utils.hop(changes,"$:/isEncrypted")) {
$tw.crypto.updateCryptoStateTiddler();
}
});
// Set up the favicon
var faviconTitle = "$:/favicon.ico",
faviconLink = document.getElementById("faviconLink"),
setFavicon = function() {
var tiddler = $tw.wiki.getTiddler(faviconTitle);
if(tiddler) {
faviconLink.setAttribute("href","data:" + tiddler.fields.type + ";base64," + tiddler.fields.text);
}
};
setFavicon();
$tw.wiki.addEventListener("change",function(changes) {
if($tw.utils.hop(changes,faviconTitle)) {
setFavicon();
}
});
// Set up the styles
var styleTemplateTitle = "$:/core/ui/PageStylesheet",
styleParser = $tw.wiki.parseTiddler(styleTemplateTitle);
$tw.styleWidgetNode = $tw.wiki.makeWidget(styleParser,{document: $tw.fakeDocument});
$tw.styleContainer = $tw.fakeDocument.createElement("style");
$tw.styleWidgetNode.render($tw.styleContainer,null);
$tw.styleElement = document.createElement("style");
$tw.styleElement.innerHTML = $tw.styleContainer.textContent;
document.head.insertBefore($tw.styleElement,document.head.firstChild);
$tw.wiki.addEventListener("change",$tw.perf.report("styleRefresh",function(changes) {
if($tw.styleWidgetNode.refresh(changes,$tw.styleContainer,null)) {
$tw.styleElement.innerHTML = $tw.styleContainer.textContent;
}
}));
// Display the $:/PageMacros tiddler to kick off the display
renderPage();
// Fix up the link between the root widget and the page container
$tw.rootWidget.domNodes = [$tw.pageContainer];
$tw.rootWidget.children = [$tw.pageWidgetNode];
// If we're being viewed on a data: URI then give instructions for how to save
if(document.location.protocol === "data:") {
$tw.utils.dispatchCustomEvent(document,"tw-modal",{
param: "$:/language/Modals/SaveInstructions"
});
}
// Call browser startup modules
$tw.modules.forEachModuleOfType("browser-startup",function(title,module) {
if(module.startup) {
module.startup();
}
});
} else {
// On the server, start a commander with the command line arguments
commander = new $tw.Commander(
$tw.boot.argv,
function(err) {
if(err) {
console.log("Error: " + err);
}
},
$tw.wiki,
{output: process.stdout, error: process.stderr}
);
commander.execute();
}
};
function renderPage() {
// Display the PageMacros, which includes the PageTemplate
var templateTitle = "$:/core/ui/PageMacros",
parser = $tw.wiki.parseTiddler(templateTitle);
$tw.perf.report("mainRender",function() {
$tw.pageWidgetNode = $tw.wiki.makeWidget(parser,{document: document, parentWidget: $tw.rootWidget});
$tw.pageContainer = document.createElement("div");
$tw.utils.addClass($tw.pageContainer,"tw-page-container-wrapper");
document.body.insertBefore($tw.pageContainer,document.body.firstChild);
$tw.pageWidgetNode.render($tw.pageContainer,null);
})();
$tw.wiki.addEventListener("change",$tw.perf.report("mainRefresh",function(changes) {
$tw.pageWidgetNode.refresh(changes,$tw.pageContainer,null);
}));
}
})();