guidancepanel.xml (7841B)
1 <?xml version="1.0"?> 2 <!-- 3 ***** BEGIN LICENSE BLOCK ***** 4 5 Copyright © 2011 Center for History and New Media 6 George Mason University, Fairfax, Virginia, USA 7 http://zotero.org 8 9 This file is part of Zotero. 10 11 Zotero is free software: you can redistribute it and/or modify 12 it under the terms of the GNU Affero General Public License as published by 13 the Free Software Foundation, either version 3 of the License, or 14 (at your option) any later version. 15 16 Zotero is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 GNU Affero General Public License for more details. 20 21 You should have received a copy of the GNU Affero General Public License 22 along with Zotero. If not, see <http://www.gnu.org/licenses/>. 23 24 ***** END LICENSE BLOCK ***** 25 --> 26 27 <bindings xmlns="http://www.mozilla.org/xbl" 28 xmlns:xbl="http://www.mozilla.org/xbl" 29 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> 30 31 <binding id="guidancepanel"> 32 <resources> 33 <stylesheet src="chrome://zotero/skin/bindings/guidancepanel.css"/> 34 </resources> 35 36 <implementation> 37 <property name="panel" onget="return document.getAnonymousNodes(this)[0]"/> 38 39 <!-- 40 @param {Object} [options] 41 @param {String} [options.text] - Text to use in place of firstRunGuidance.<about> 42 @param {DOMElement} [options.forEl] - Anchor node 43 @param {Boolean} [options.force] - Show even if already shown, and don't update 44 firstRunGuidanceShown.<about> pref 45 --> 46 <method name="show"> 47 <parameter name="options"/> 48 <body> 49 <![CDATA[ 50 Components.utils.import("resource://gre/modules/Services.jsm"); 51 if(!Zotero.Prefs.get("firstRunGuidance")) return; 52 53 options = options || {}; 54 let text = options.text; 55 let useLastText = options.useLastText || false; 56 let forEl = options.forEl || document.getElementById(this.getAttribute("for")); 57 let force = options.force || false; 58 59 if (!forEl) return; 60 // Don't show two panels at once 61 if (Zotero.guidanceBeingShown) { 62 return; 63 } 64 65 var about = this.getAttribute("about"); 66 var pref = false; 67 if (about) { 68 pref = "firstRunGuidanceShown." + about; 69 let shown = false; 70 try { 71 shown = Zotero.Prefs.get(pref); 72 } catch(e) {}; 73 if (shown && !force) { 74 return; 75 } 76 } 77 78 Zotero.guidanceBeingShown = true; 79 80 var x = this.getAttribute("x"), 81 y = this.getAttribute("y"), 82 position = this.getAttribute("position"); 83 84 if (!useLastText) { 85 if (!text) { 86 text = Zotero.getString("firstRunGuidance." + about); 87 } 88 text = text.split("\n"); 89 var descriptionNode = this.id('panel-description'); 90 91 while (descriptionNode.hasChildNodes()) { 92 descriptionNode.removeChild(descriptionNode.firstChild); 93 } 94 95 while(text.length) { 96 var textLine = text.shift(); 97 descriptionNode.appendChild(document.createTextNode(textLine)); 98 if(text.length) descriptionNode.appendChild(document.createElementNS( 99 "http://www.w3.org/1999/xhtml", "br")); 100 } 101 } 102 103 this.setAttribute( 104 "onpopuphidden", 105 "this.hidden = true; " 106 + "Zotero.guidanceBeingShown = false; " 107 + (this.getAttribute("onpopuphidden") || "") 108 ); 109 110 this._initNavButton('back', options.back); 111 this._initNavButton('forward', options.forward); 112 113 var self = this; 114 var f = function() { 115 if (self.hasAttribute("foregroundonly") && Services.ww.activeWindow != window) return; 116 117 // Hide panel if content page changes 118 if (self.getAttribute('hideonpagechange') == "true") { 119 let popupShownListener = function () { 120 self.removeEventListener("popupshown", popupShownListener); 121 122 let appcontent = document.getElementById('appcontent'); 123 let pageHideListener = function (event) { 124 var doc = event.originalTarget; 125 if(!(doc instanceof HTMLDocument)) return; 126 127 var rootDoc = doc.defaultView.top.document; 128 // Don't hide when frames and special URLs are unloaded 129 if (rootDoc != doc || !rootDoc.location.href.startsWith('http')) { 130 return; 131 } 132 appcontent.removeEventListener("pagehide", pageHideListener); 133 self.hide(); 134 }; 135 appcontent.addEventListener("pagehide", pageHideListener); 136 }; 137 self.addEventListener("popupshown", popupShownListener); 138 } 139 140 self.hidden = false; 141 self.panel.openPopup(forEl, position ? position : "after_start", 142 x ? parseInt(x, 10) : 0, y ? parseInt(y, 10) : 0, false, false, null); 143 if (pref) { 144 Zotero.Prefs.set(pref, true); 145 } 146 }; 147 148 if(this.hasAttribute("delay") && !force) { 149 window.setTimeout(f, this.getAttribute("delay")); 150 } else { 151 f(); 152 } 153 154 if (this.getAttribute("noautohide") == 'true' 155 && !this.hasAttribute('forward')) { 156 let listener = function () { 157 this.panel.removeEventListener("click", listener); 158 this.panel.hidePopup(); 159 }.bind(this); 160 this.panel.addEventListener("click", listener); 161 } 162 ]]> 163 </body> 164 </method> 165 166 <method name="hide"> 167 <body> 168 <![CDATA[ 169 document.getAnonymousNodes(this)[0].hidePopup(); 170 ]]> 171 </body> 172 </method> 173 174 <method name="_initNavButton"> 175 <parameter name="dir"/> 176 <parameter name="nextID"/> 177 <body><![CDATA[ 178 if (!nextID) { 179 nextID = this.getAttribute(dir); 180 } 181 if (!nextID) { 182 return; 183 } 184 var nextElem = document.getElementById(nextID); 185 button = this.id(dir + '-button'); 186 button.hidden = false; 187 var target; 188 // If there's a forward action and no back action, the whole panel triggers 189 // the forward in noautohide mode 190 if (dir == 'forward' && !this.hasAttribute('back') 191 && this.getAttribute('noautohide') == 'true') { 192 target = this.panel; 193 } 194 else { 195 target = button; 196 } 197 var listener = function (event) { 198 target.removeEventListener("click", listener); 199 this.hide(); 200 var data = { 201 force: true 202 }; 203 // Point the next panel back to this one 204 data[dir == 'back' ? 'forward' : 'back'] = this.getAttribute('id'); 205 // When going backwards, don't regenerate text 206 if (dir == 'back') { 207 data.useLastText = true; 208 } 209 nextElem.show(data); 210 event.stopPropagation(); 211 }.bind(this); 212 target.addEventListener("click", listener); 213 ]]></body> 214 </method> 215 216 <method name="id"> 217 <parameter name="id"/> 218 <body><![CDATA[ 219 return document.getAnonymousNodes(this)[0].getElementsByAttribute('anonid', id)[0]; 220 ]]></body> 221 </method> 222 </implementation> 223 224 <content> 225 <xul:panel type="arrow" align="top" xbl:inherits="noautohide"> 226 <xul:stack> 227 <xul:hbox align="center"> 228 <xul:image src="chrome://zotero/skin/zotero-new-z-48px.png" style="margin-right: 10px; width: 48px; height: 48px;"/> 229 <xul:description anonid="panel-description" flex="1"></xul:description> 230 </xul:hbox> 231 <xul:hbox anonid="close-button-box"> 232 <xul:toolbarbutton anonid="close-button" class="close-icon" hidden="true"/> 233 </xul:hbox> 234 <xul:hbox anonid="nav-buttons"> 235 <xul:toolbarbutton anonid="back-button" oncommand="hide()" hidden="true"/> 236 <xul:toolbarbutton anonid="forward-button" oncommand="hide()" hidden="true"/> 237 </xul:hbox> 238 </xul:stack> 239 </xul:panel> 240 </content> 241 </binding> 242 </bindings>