From 161ddcb4735d1f78ee204207df471d8ca49b5ac1 Mon Sep 17 00:00:00 2001 From: Jeremy Ruston Date: Wed, 13 Jun 2012 15:37:07 +0100 Subject: [PATCH] Made it so clicking outside a popup cancels the popup Clicking inside still doesn't cancel it, though --- core/modules/macros/button.js | 47 +++++++++++++++++++++-------------- core/modules/macros/reveal.js | 10 ++++++-- core/modules/startup.js | 22 ++++++++++++++++ 3 files changed, 59 insertions(+), 20 deletions(-) diff --git a/core/modules/macros/button.js b/core/modules/macros/button.js index dd3c05011..77acb3ca1 100644 --- a/core/modules/macros/button.js +++ b/core/modules/macros/button.js @@ -20,7 +20,7 @@ exports.info = { qualifyTiddlerTitles: {byName: true, type: "text"}, "class": {byName: true, type: "text"} }, - events: ["click"] + events: ["click", "tw-cancel-popup"] }; exports.dispatchMessage = function(event) { @@ -30,7 +30,7 @@ exports.dispatchMessage = function(event) { event.target.dispatchEvent(buttonEvent); }; -exports.triggerPopup = function(event) { +exports.triggerPopup = function(event,cancel) { // Get the title of the popup state tiddler var title = this.params.popup; if(this.hasParameter("qualifyTiddlerTitles") && this.params.qualifyTiddlerTitles === "yes") { @@ -39,36 +39,47 @@ exports.triggerPopup = function(event) { // Get the popup state tiddler and the the text value var tiddler = this.wiki.getTiddler(title), value = tiddler ? tiddler.fields.text : ""; - // 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)) { + // Check for cancelling + if(cancel) { value = ""; } else { - // Set the position if we're opening it - value = "(" + this.domNode.offsetLeft + "," + this.domNode.offsetTop + "," + this.domNode.offsetWidth + "," + this.domNode.offsetHeight + ")"; + // 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 = ""; + } else { + // Set the position if we're opening it + value = "(" + this.domNode.offsetLeft + "," + this.domNode.offsetTop + "," + this.domNode.offsetWidth + "," + this.domNode.offsetHeight + ")"; + } } // Update the state tiddler this.wiki.addTiddler(new $tw.Tiddler(tiddler,{title: title, text: value}),true); }; exports.handleEvent = function(event) { - if(event.type === "click") { - if(this.hasParameter("message")) { - this.dispatchMessage(event); - } - if(this.hasParameter("popup")) { - this.triggerPopup(); - } - event.preventDefault(); - return false; + 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") && event.targetOfCancel !== this.domNode) { + this.triggerPopup(event,true); + } + break; } return true; }; exports.executeMacro = function() { - var attributes = {}; + var attributes = {"class": ["tw-popup-controller"]}; if(this.hasParameter("class")) { - attributes["class"] = this.params["class"].split(" "); + $tw.utils.pushTop(attributes["class"],this.params["class"].split(" ")); } if(this.classes) { $tw.utils.pushTop(attributes["class"],this.classes); diff --git a/core/modules/macros/reveal.js b/core/modules/macros/reveal.js index 5f43426da..6d53cab41 100644 --- a/core/modules/macros/reveal.js +++ b/core/modules/macros/reveal.js @@ -71,7 +71,7 @@ exports.executeMacro = function() { this.readState(); var attributes = { "class": ["tw-reveal"], - style: {position: "absolute"} + style: {} }; if(this.hasParameter("class")) { attributes["class"].push(this.params["class"]); @@ -79,6 +79,12 @@ exports.executeMacro = function() { if(this.classes) { $tw.utils.pushTop(attributes["class"],this.classes); } + switch(this.params.type) { + case "popup": + attributes.style.position = "absolute"; + attributes["class"].push("tw-popup"); + break; + } attributes.style = {display: this.isOpen ? "block" : "none"}; var child = $tw.Tree.Element("div",attributes,this.isOpen ? this.content : []); child.execute(this.parents,this.tiddlerTitle); @@ -115,7 +121,7 @@ exports.refreshInDom = function(changes) { case "popup": if(this.isOpen) { this.child.domNode.style.position = "absolute"; - this.child.domNode.style.zIndex = "3000"; + this.child.domNode.style.zIndex = "1000"; switch(this.params.position) { case "left": this.child.domNode.style.left = (this.popup.left - this.child.domNode.offsetWidth) + "px"; diff --git a/core/modules/startup.js b/core/modules/startup.js index 9a0a217b9..a283a4588 100644 --- a/core/modules/startup.js +++ b/core/modules/startup.js @@ -48,6 +48,28 @@ 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