diff --git a/core/modules/macros/button.js b/core/modules/macros/button.js index 2d8b7cfad..bc70601fc 100644 --- a/core/modules/macros/button.js +++ b/core/modules/macros/button.js @@ -30,47 +30,42 @@ exports.dispatchMessage = function(event) { }; exports.triggerPopup = function(event,cancel) { - // Get the title of the popup state tiddler - var title = this.params.popup; + // Get the textref of the popup state tiddler + var textRef = this.params.popup; if(this.hasParameter("qualifyTiddlerTitles") && this.params.qualifyTiddlerTitles === "yes") { - title = "(" + this.parents.join(",") + "," + this.tiddlerTitle + ")" + title; + textRef = "(" + this.parents.join(",") + "," + this.tiddlerTitle + ")" + textRef; } - // Get the popup state tiddler and the the text value - var tiddler = this.wiki.getTiddler(title), - value = tiddler ? tiddler.fields.text : ""; // Check for cancelling if(cancel) { - value = ""; + this.wiki.deleteTextReference(textRef,this.tiddlerTitle); } else { + // Get the current popup state tiddler + var value = this.wiki.getTextReference(textRef,"",this.tiddlerTitle); // Check if the popup is open by checking whether it matches "(,)" var popupLocationRegExp = /^\((-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+),(-?[0-9\.E]+)\)$/; if(popupLocationRegExp.test(value)) { - value = ""; + this.wiki.deleteTextReference(textRef,this.tiddlerTitle); } else { // Set the position if we're opening it - value = "(" + this.child.domNode.offsetLeft + "," + this.child.domNode.offsetTop + "," + this.child.domNode.offsetWidth + "," + this.child.domNode.offsetHeight + ")"; + this.wiki.setTextReference(textRef, + "(" + this.child.domNode.offsetLeft + "," + this.child.domNode.offsetTop + "," + + this.child.domNode.offsetWidth + "," + this.child.domNode.offsetHeight + ")", + this.tiddlerTitle,true); + $tw.popupper.popup(textRef); } } - // Update the state tiddler - this.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: title, text: value}),true); }; exports.handleEvent = function(event) { - switch(event.type) { - case "click": - if(this.hasParameter("message")) { - this.dispatchMessage(event); - } - if(this.hasParameter("popup")) { - this.triggerPopup(event); - } - event.preventDefault(); - return false; - case "tw-cancel-popup": - if(this.hasParameter("popup") && this.child.domNode !== event.targetOfCancel && !$tw.utils.domContains(this.child.domNode,event.targetOfCancel)) { - this.triggerPopup(event,true); - } - break; + if(event.type === "click") { + if(this.hasParameter("message")) { + this.dispatchMessage(event); + } + if(this.hasParameter("popup")) { + this.triggerPopup(event); + } + event.preventDefault(); + return false; } return true; }; @@ -87,7 +82,7 @@ exports.executeMacro = function() { this.content[t].execute(this.parents,this.tiddlerTitle); } return $tw.Tree.Element("button",attributes,this.content,{ - events: ["click","tw-cancel-popup"], + events: ["click"], eventHandler: this }); }; diff --git a/core/modules/macros/reveal.js b/core/modules/macros/reveal.js index 0bffa2270..d32a3ffa3 100644 --- a/core/modules/macros/reveal.js +++ b/core/modules/macros/reveal.js @@ -30,15 +30,12 @@ exports.readState = function() { this.isOpen = this.params["default"] === "open"; } // Read the information from the state tiddler - if(this.stateTitle) { - var stateTiddler = this.wiki.getTiddler(this.stateTitle); - if(stateTiddler) { - var state = stateTiddler ? stateTiddler.fields.text : ""; - switch(this.params.type) { - case "popup": - this.readPopupState(state); - break; - } + if(this.stateTextRef) { + var state = this.wiki.getTextReference(this.stateTextRef,"",this.tiddlerTitle); + switch(this.params.type) { + case "popup": + this.readPopupState(state); + break; } } }; @@ -66,15 +63,16 @@ exports.readPopupState = function(state) { exports.handleEvent = function(event) { if(event.type === "click") { // Cancel the popup if we get a click on it - var tiddler = this.wiki.getTiddler(this.stateTitle); - this.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: this.stateTitle, text: ""}),true); + if(this.stateTextRef) { + this.wiki.deleteTextReference(this.stateTextRef); + } } }; exports.executeMacro = function() { - this.stateTitle = this.params.state; + this.stateTextRef = this.params.state; if(this.hasParameter("qualifyTiddlerTitles")) { - this.stateTitle = "(" + this.parents.join(",") + "," + this.tiddlerTitle + ")" + this.stateTitle; + this.stateTextRef = "(" + this.parents.join(",") + "," + this.tiddlerTitle + ")" + this.stateTextRef; } this.readState(); var attributes = { @@ -105,10 +103,8 @@ exports.executeMacro = function() { exports.refreshInDom = function(changes) { var needChildrenRefresh = true, // Avoid refreshing the children nodes if we don't need to t; - // If the state tiddler has changed then reset the open state - if($tw.utils.hop(changes,this.stateTitle)) { - this.readState(); - } + // Re-read the open state + this.readState(); // Render the children if we're open and we don't have any children yet if(this.isOpen && this.child.children.length === 0) { // Install the children and execute them diff --git a/core/modules/popupper.js b/core/modules/popupper.js new file mode 100644 index 000000000..0bbeb6587 --- /dev/null +++ b/core/modules/popupper.js @@ -0,0 +1,49 @@ +/*\ +title: $:/core/modules/popupper.js +type: application/javascript +module-type: utils + +Plugin that creates a $tw.utils.Popupper object prototype that manages popups in the browser + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Creates a Popupper object with these options: + wiki: the wiki to use for resolving tiddler titles + rootElement: the DOM element to which the popup zapper should be attached +*/ +var Popupper = function(options) { + options = options || {}; + this.wiki = options.wiki; + this.rootElement = options.rootElement || document.body; + this.popupTextRef = null; +}; + +Popupper.prototype.popup = function(stateTextRef) { + var popupState; + this.cancel(); + this.popupTextRef = stateTextRef; + this.rootElement.addEventListener("click",this,true); +}; + +Popupper.prototype.handleEvent = function(event) { + if(event.type === "click") { + this.cancel(); + } +} + +Popupper.prototype.cancel = function() { + if(this.popupTextRef) { + this.wiki.deleteTextReference(this.popupTextRef); + this.popupTextRef = null; + } +}; + +exports.Popupper = Popupper; + +})(); diff --git a/core/modules/startup.js b/core/modules/startup.js index 9c5b9e1d0..2f470dd84 100644 --- a/core/modules/startup.js +++ b/core/modules/startup.js @@ -48,35 +48,18 @@ exports.startup = function() { $tw.Commander.initCommands(); // Host-specific startup if($tw.browser) { - // Install the popup zapper - // document.body.addEventListener("click",function(event) { - // // Is the click within a popup? - // var inPopup = false, - // e = event.target; - // while(e !== document) { - // if($tw.utils.hasClass(e,"tw-popup")) { - // inPopup = true; - // } - // e = e.parentNode; - // } - // // If we're not in a popup, then send out an event to cancel all popups - // if(!inPopup) { - // var cancelPopupEvent = document.createEvent("Event"); - // cancelPopupEvent.initEvent("tw-cancel-popup",true,true); - // cancelPopupEvent.targetOfCancel = event.target; - // var controllers = document.querySelectorAll(".tw-popup-controller"); - // for(var t=0; t