From 33ba69e852966d7c5449842a95636024857d7177 Mon Sep 17 00:00:00 2001 From: BurningTreeC Date: Sun, 18 Nov 2018 21:57:04 +0100 Subject: [PATCH] Modals: Display in source-window (#3539) * Make modals display in source Window this makes modals display within the window where they got opened, with the parameter `rootwindow` that, if `yes` or `true`, shows the modal always in the root TW window (`<$action-sendmessage $message="tm-modal" $param="mymodal" rootwindow="yes|true"/>`) * pass the full event to $tw.modal.display we need the event there to find `srcDocument` and `srcWindow` * pass event in options object * update modal.js to use options.event * add docs for rootwindow tm-modal attribute --- core/modules/startup/rootwidget.js | 2 +- core/modules/utils/dom/modal.js | 51 ++++++++++--------- .../messages/WidgetMessage_ tm-modal.tid | 5 +- 3 files changed, 32 insertions(+), 26 deletions(-) diff --git a/core/modules/startup/rootwidget.js b/core/modules/startup/rootwidget.js index 0fdcfd9a2..1d24f1db6 100644 --- a/core/modules/startup/rootwidget.js +++ b/core/modules/startup/rootwidget.js @@ -23,7 +23,7 @@ exports.startup = function() { // Install the modal message mechanism $tw.modal = new $tw.utils.Modal($tw.wiki); $tw.rootWidget.addEventListener("tm-modal",function(event) { - $tw.modal.display(event.param,{variables: event.paramObject}); + $tw.modal.display(event.param,{variables: event.paramObject, event: event}); }); // Install the notification mechanism $tw.notifier = new $tw.utils.Notifier($tw.wiki); diff --git a/core/modules/utils/dom/modal.js b/core/modules/utils/dom/modal.js index 74fceb1ba..0f65c8f63 100644 --- a/core/modules/utils/dom/modal.js +++ b/core/modules/utils/dom/modal.js @@ -28,6 +28,10 @@ Options include: */ Modal.prototype.display = function(title,options) { options = options || {}; + this.srcDocument = options.variables && (options.variables.rootwindow === "true" || + options.variables.rootwindow === "yes") ? document : + (options.event.event ? options.event.event.target.ownerDocument : document); + this.srcWindow = this.srcDocument.defaultView; var self = this, refreshHandler, duration = $tw.utils.getAnimationDuration(), @@ -39,16 +43,16 @@ Modal.prototype.display = function(title,options) { // Create the variables var variables = $tw.utils.extend({currentTiddler: title},options.variables); // Create the wrapper divs - var wrapper = document.createElement("div"), - modalBackdrop = document.createElement("div"), - modalWrapper = document.createElement("div"), - modalHeader = document.createElement("div"), - headerTitle = document.createElement("h3"), - modalBody = document.createElement("div"), - modalLink = document.createElement("a"), - modalFooter = document.createElement("div"), - modalFooterHelp = document.createElement("span"), - modalFooterButtons = document.createElement("span"); + var wrapper = this.srcDocument.createElement("div"), + modalBackdrop = this.srcDocument.createElement("div"), + modalWrapper = this.srcDocument.createElement("div"), + modalHeader = this.srcDocument.createElement("div"), + headerTitle = this.srcDocument.createElement("h3"), + modalBody = this.srcDocument.createElement("div"), + modalLink = this.srcDocument.createElement("a"), + modalFooter = this.srcDocument.createElement("div"), + modalFooterHelp = this.srcDocument.createElement("span"), + modalFooterButtons = this.srcDocument.createElement("span"); // Up the modal count and adjust the body class this.modalCount++; this.adjustPageClass(); @@ -80,7 +84,7 @@ Modal.prototype.display = function(title,options) { value: title }}}], parentWidget: $tw.rootWidget, - document: document, + document: this.srcDocument, variables: variables, importPageMacros: true }); @@ -88,7 +92,7 @@ Modal.prototype.display = function(title,options) { // Render the body of the message var bodyWidgetNode = this.wiki.makeTranscludeWidget(title,{ parentWidget: $tw.rootWidget, - document: document, + document: this.srcDocument, variables: variables, importPageMacros: true }); @@ -96,16 +100,16 @@ Modal.prototype.display = function(title,options) { // Setup the link if present if(options.downloadLink) { modalLink.href = options.downloadLink; - modalLink.appendChild(document.createTextNode("Right-click to save changes")); + modalLink.appendChild(this.srcDocument.createTextNode("Right-click to save changes")); modalBody.appendChild(modalLink); } // Render the footer of the message if(tiddler && tiddler.fields && tiddler.fields.help) { - var link = document.createElement("a"); + var link = this.srcDocument.createElement("a"); link.setAttribute("href",tiddler.fields.help); link.setAttribute("target","_blank"); link.setAttribute("rel","noopener noreferrer"); - link.appendChild(document.createTextNode("Help")); + link.appendChild(this.srcDocument.createTextNode("Help")); modalFooterHelp.appendChild(link); modalFooterHelp.style.float = "left"; } @@ -129,7 +133,7 @@ Modal.prototype.display = function(title,options) { }}} ]}], parentWidget: $tw.rootWidget, - document: document, + document: this.srcDocument, variables: variables, importPageMacros: true }); @@ -155,13 +159,13 @@ Modal.prototype.display = function(title,options) { {opacity: "0"} ]); $tw.utils.setStyle(modalWrapper,[ - {transform: "translateY(" + window.innerHeight + "px)"} + {transform: "translateY(" + self.srcWindow.innerHeight + "px)"} ]); // Set up an event for the transition end - window.setTimeout(function() { + self.srcWindow.setTimeout(function() { if(wrapper.parentNode) { // Remove the modal message from the DOM - document.body.removeChild(wrapper); + self.srcDocument.body.removeChild(wrapper); } },duration); // Don't let anyone else handle the tm-close-tiddler message @@ -176,10 +180,10 @@ Modal.prototype.display = function(title,options) { ]); $tw.utils.setStyle(modalWrapper,[ {transformOrigin: "0% 0%"}, - {transform: "translateY(" + (-window.innerHeight) + "px)"} + {transform: "translateY(" + (-this.srcWindow.innerHeight) + "px)"} ]); // Put the message into the document - document.body.appendChild(wrapper); + this.srcDocument.body.appendChild(wrapper); // Set up animation for the styles $tw.utils.setStyle(modalBackdrop,[ {transition: "opacity " + duration + "ms ease-out"} @@ -200,8 +204,9 @@ Modal.prototype.display = function(title,options) { }; Modal.prototype.adjustPageClass = function() { - if($tw.pageContainer) { - $tw.utils.toggleClass($tw.pageContainer,"tc-modal-displayed",this.modalCount > 0); + var windowContainer = $tw.pageContainer ? ($tw.pageContainer === this.srcDocument.body.firstChild ? $tw.pageContainer : this.srcDocument.body.firstChild) : null; + if(windowContainer) { + $tw.utils.toggleClass(windowContainer,"tc-modal-displayed",this.modalCount > 0); } }; diff --git a/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-modal.tid b/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-modal.tid index aa0b40067..a1b90b688 100644 --- a/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-modal.tid +++ b/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-modal.tid @@ -5,11 +5,10 @@ title: WidgetMessage: tm-modal type: text/vnd.tiddlywiki caption: tm-modal -The modal message displays a specified tiddler in a modal overlay that dims the main page. It requires the following properties on the `event` object: - |!Name |!Description | |param |Title of the tiddler to be displayed | |paramObject |Hashmap of variables to be provided to the modal | +|rootwindow |<<.from-version 5.1.18>> ''yes'' or ''true'' will always display a modal in the wiki-root-window | The "currentTiddler" variable is set to the title of the modal tiddler, but can be overridden by specifying a different value in `paramObject`. @@ -30,3 +29,5 @@ Your message: Click me! '/> +<<.tip """<$macrocall $name=".from-version" version="5.1.18"/> if triggered from within a ''new window'', the above examples will be displayed within that window. The <$macrocall $name=".attr" _="rootwindow"/> attribute can be set to ''yes'' or ''true'' to inherit this behavior and to display the Modal within the ''root'' window""">> +