1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-12-13 11:40:27 +00:00
TiddlyWiki5/core/modules/startup/windows.js

181 lines
6.4 KiB
JavaScript
Raw Normal View History

/*\
title: $:/core/modules/startup/windows.js
type: application/javascript
module-type: startup
Setup root widget handlers for the messages concerned with opening external browser windows
\*/
(function(){
/*jslint node: true, browser: true */
/*global $tw: false */
"use strict";
// Export name and synchronous status
exports.name = "windows";
exports.platforms = ["browser"];
exports.after = ["startup"];
exports.synchronous = true;
// Global to keep track of open windows (hashmap by title)
$tw.windows = {};
// Default template to use for new windows
var DEFAULT_WINDOW_TEMPLATE = "$:/core/templates/single.tiddler.window";
exports.startup = function() {
// Handle open window message
$tw.rootWidget.addEventListener("tm-open-window",function(event) {
// Get the parameters
2024-10-14 04:53:34 +00:00
var mainRefreshHandler,
styleRefreshHandler,
title = event.param || event.tiddlerTitle,
paramObject = event.paramObject || {},
windowTitle = paramObject.windowTitle || title,
windowID = paramObject.windowID || title,
template = paramObject.template || DEFAULT_WINDOW_TEMPLATE,
width = paramObject.width || "700",
height = paramObject.height || "600",
top = paramObject.top,
left = paramObject.left,
variables = $tw.utils.extend({},paramObject,{currentTiddler: title, "tv-window-id": windowID});
// Open the window
var srcWindow,
srcDocument;
// In case that popup blockers deny opening a new window
try {
srcWindow = window.open("","external-" + windowID,"scrollbars,width=" + width + ",height=" + height + (top ? ",top=" + top : "" ) + (left ? ",left=" + left : "" )),
srcDocument = srcWindow.document;
}
catch(e) {
return;
}
$tw.windows[windowID] = srcWindow;
// Check for reopening the same window
if(srcWindow.haveInitialisedWindow) {
srcWindow.focus();
return;
}
// Initialise the document
srcDocument.write("<!DOCTYPE html><head></head><body class='tc-body tc-single-tiddler-window'></body></html>");
srcDocument.close();
srcDocument.title = windowTitle;
srcWindow.addEventListener("beforeunload",function(event) {
delete $tw.windows[windowID];
2024-10-14 04:53:34 +00:00
$tw.wiki.removeEventListener("change",styleRefreshHandler);
$tw.wiki.removeEventListener("change",mainRefreshHandler);
},false);
// Set up the styles
var styleWidgetNode = $tw.wiki.makeTranscludeWidget("$:/core/ui/PageStylesheet",{
document: $tw.fakeDocument,
variables: variables,
importPageMacros: true}),
styleContainer = $tw.fakeDocument.createElement("style");
styleWidgetNode.render(styleContainer,null);
var styleElement = srcDocument.createElement("style");
styleElement.innerHTML = styleContainer.textContent;
2024-10-14 04:53:34 +00:00
styleWidgetNode.assignedStyles = styleContainer.textContent;
srcDocument.head.insertBefore(styleElement,srcDocument.head.firstChild);
// Render the text of the tiddler
var parser = $tw.wiki.parseTiddler(template),
widgetNode = $tw.wiki.makeWidget(parser,{document: srcDocument, parentWidget: $tw.rootWidget, variables: variables});
widgetNode.render(srcDocument.body,srcDocument.body.firstChild);
2024-10-14 04:53:34 +00:00
// Prepare refresh mechanism
2024-10-15 03:09:28 +00:00
var mainDeferredChanges = Object.create(null),
styleDeferredChanges = Object.create(null),
mainTimerId,
styleTimerId,
2024-10-15 16:23:18 +00:00
throttledRefreshFn = function(changes,options) {
options = options || {};
2024-10-14 04:53:34 +00:00
// Check if only tiddlers that are throttled have changed
var onlyThrottledTiddlersHaveChanged = true;
for(var title in changes) {
var tiddler = $tw.wiki.getTiddler(title);
2024-10-15 16:23:18 +00:00
if(!$tw.wiki.isVolatileTiddler(title) && (!tiddler || !(tiddler.hasField("draft.of") || tiddler.hasField("throttle.refresh") ||
(options.mainCondition && tiddler.hasField("throttle.refresh.main")) || (options.styleCondition && tiddler.hasField("throttle.refresh.style"))))) {
2024-10-14 04:53:34 +00:00
onlyThrottledTiddlersHaveChanged = false;
}
}
// Defer the change if only drafts have changed
2024-10-15 16:23:18 +00:00
if(options.timerId) {
clearTimeout(options.timerId);
2024-10-14 04:53:34 +00:00
}
2024-10-15 16:23:18 +00:00
options.timerId = null;
2024-10-14 04:53:34 +00:00
if(onlyThrottledTiddlersHaveChanged) {
var timeout = parseInt($tw.wiki.getTiddlerText(DRAFT_TIDDLER_TIMEOUT_TITLE,""),10);
if(isNaN(timeout)) {
timeout = THROTTLE_REFRESH_TIMEOUT;
}
2024-10-15 16:23:18 +00:00
options.timerId = setTimeout(options.throttledRefresh,timeout);
$tw.utils.extend(options.deferredChanges,changes);
2024-10-14 04:53:34 +00:00
} else {
2024-10-15 16:23:18 +00:00
$tw.utils.extend(options.deferredChanges,changes);
options.callback();
2024-10-14 04:53:34 +00:00
}
};
2024-10-15 03:09:28 +00:00
var styleRefresh = function() {
if(styleWidgetNode.refresh(styleDeferredChanges,styleContainer,null)) {
2024-10-14 04:53:34 +00:00
var newStyles = styleContainer.textContent;
if(newStyles !== styleWidgetNode.assignedStyles) {
styleWidgetNode.assignedStyles = newStyles;
styleElement.innerHTML = styleWidgetNode.assignedStyles;
}
}
2024-10-15 03:09:28 +00:00
styleDeferredChanges = Object.create(null);
2024-10-14 04:53:34 +00:00
};
2024-10-15 03:09:28 +00:00
var mainRefresh = function() {
widgetNode.refresh(mainDeferredChanges);
mainDeferredChanges = Object.create(null);
2024-10-14 04:53:34 +00:00
};
var mainThrottledRefresh = $tw.perf.report("throttledMainRefresh",mainRefresh),
styleThrottledRefresh = $tw.perf.report("throttledStyleRefresh",styleRefresh);
2024-10-14 04:53:34 +00:00
styleRefreshHandler = function(changes) {
2024-10-15 16:23:18 +00:00
throttledRefreshFn(changes,{
deferredChanged: styleDeferredChanges,
timerId: styleTimerId,
throttledRefresh: styleThrottledRefresh,
callback: styleRefresh,
mainCondition: false,
styleCondition: true
});
2024-10-14 04:53:34 +00:00
};
mainRefreshHandler = function(changes) {
2024-10-15 16:23:18 +00:00
throttledRefreshFn(changes,{
deferredChanges: mainDeferredChanges,
timerId: mainTimerId,
throttledRefresh: mainThrottledRefresh,
callback: mainRefresh,
mainCondition: true,
styleCondition: false
});
};
2024-10-14 04:53:34 +00:00
$tw.wiki.addEventListener("change",styleRefreshHandler);
$tw.wiki.addEventListener("change",mainRefreshHandler);
// Listen for keyboard shortcuts
$tw.utils.addEventListeners(srcDocument,[{
name: "keydown",
handlerObject: $tw.keyboardManager,
handlerMethod: "handleKeydownEvent"
}]);
srcWindow.document.documentElement.addEventListener("click",$tw.popup,true);
srcWindow.haveInitialisedWindow = true;
});
$tw.rootWidget.addEventListener("tm-close-window",function(event) {
var windowID = event.param,
win = $tw.windows[windowID];
if(win) {
win.close();
}
});
var closeAllWindows = function() {
$tw.utils.each($tw.windows,function(win) {
win.close();
});
}
$tw.rootWidget.addEventListener("tm-close-all-windows",closeAllWindows);
// Close open windows when unloading main window
$tw.addUnloadTask(closeAllWindows);
};
})();