icon.js (10124B)
1 /* 2 ***** BEGIN LICENSE BLOCK ***** 3 4 Copyright © 2015 Center for History and New Media 5 George Mason University, Fairfax, Virginia, USA 6 http://zotero.org 7 8 This file is part of Zotero. 9 10 Zotero is free software: you can redistribute it and/or modify 11 it under the terms of the GNU Affero General Public License as published by 12 the Free Software Foundation, either version 3 of the License, or 13 (at your option) any later version. 14 15 Zotero is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU Affero General Public License for more details. 19 20 You should have received a copy of the GNU Affero General Public License 21 along with Zotero. If not, see <http://www.gnu.org/licenses/>. 22 23 ***** END LICENSE BLOCK ***** 24 */ 25 26 "use strict"; 27 28 Components.utils.import("resource://zotero/config.js"); 29 Components.utils.import("resource:///modules/CustomizableUI.jsm"); 30 31 var Zotero = Components.classes["@zotero.org/Zotero;1"] 32 .getService(Components.interfaces.nsISupports) 33 .wrappedJSObject; 34 var comboButtonsID = 'zotero-toolbar-buttons'; 35 addIcon(); 36 37 function addIcon() { 38 // Don't try to add icons more than once, and avoid warnings in tests 39 if (Zotero.toolbarIconAdded || CustomizableUI.getPlacementOfWidget(comboButtonsID)) { 40 return; 41 } 42 43 CustomizableUI.addListener({ 44 onWidgetAdded: function (id, area, position) { 45 if (id == comboButtonsID) { 46 // When dropping combo button into panel, add two independent buttons instead 47 if (area == CustomizableUI.AREA_PANEL) { 48 let mainID = getSingleID('main'); 49 let saveID = getSingleID('save'); 50 CustomizableUI.removeWidgetFromArea(id); 51 // Remove independent main and save buttons first if they're already in panel 52 CustomizableUI.removeWidgetFromArea(mainID); 53 CustomizableUI.removeWidgetFromArea(saveID); 54 CustomizableUI.addWidgetToArea(mainID, area, position); 55 let placement = CustomizableUI.getPlacementOfWidget(mainID) 56 let mainPos = placement.position; 57 CustomizableUI.addWidgetToArea(saveID, area, mainPos + 1); 58 return; 59 } 60 61 var isUpgrade = false; 62 try { 63 isUpgrade = Zotero.Prefs.get("firstRunGuidanceShown.saveIcon"); 64 } catch(e) {} 65 var property = "firstRunGuidance.toolbarButton." + (isUpgrade ? "upgrade" : "new"); 66 var shortcut = Zotero.getString( 67 Zotero.isMac ? "general.keys.cmdShift" : "general.keys.ctrlShift" 68 ) + Zotero.Prefs.get("keys.openZotero"); 69 70 let widget = CustomizableUI.getWidget(id); 71 for (let instance of widget.instances) { 72 let doc = instance.node.ownerDocument; 73 74 updateItemForArea(instance.node, area); 75 76 doc.getElementById("zotero-main-button-guidance").show({ 77 text: Zotero.getString(property, shortcut) 78 }); 79 doc.getElementById("zotero-save-button-guidance").show(); 80 } 81 } 82 else if (id == getSingleID('save')) { 83 let widget = CustomizableUI.getWidget(id); 84 for (let instance of widget.instances) { 85 instance.node.ownerDocument.defaultView.Zotero_Browser.updateStatus(); 86 } 87 } 88 }, 89 90 onWidgetOverflow: function (node, container) { 91 if (node.id == comboButtonsID) { 92 node.classList.add("toolbarbutton-1"); 93 } 94 }, 95 96 onWidgetUnderflow: function (node, container) { 97 if (node.id == comboButtonsID) { 98 node.classList.remove("toolbarbutton-1"); 99 } 100 }, 101 102 // Save icon in panel isn't in DOM until menu is shown once and therefore isn't updated 103 // on page loads, so update the icon status when the panel is first shown so that it 104 // doesn't remain disabled 105 onAreaNodeRegistered: function (area, node) { 106 if (area == CustomizableUI.AREA_PANEL) { 107 var placement = CustomizableUI.getPlacementOfWidget(comboButtonsID) 108 var update = false; 109 let singleID = getSingleID('save'); 110 if (placement && placement.area == CustomizableUI.AREA_PANEL) { 111 update = true; 112 } 113 else { 114 placement = CustomizableUI.getPlacementOfWidget(singleID); 115 if (placement && placement.area == CustomizableUI.AREA_PANEL) { 116 update = true; 117 } 118 } 119 if (update) { 120 let widget = CustomizableUI.getWidget(singleID); 121 for (let instance of widget.instances) { 122 instance.node.ownerDocument.defaultView.Zotero_Browser.updateStatus(); 123 } 124 } 125 } 126 } 127 }) 128 129 // Create the combo buttons, which go in the toolbar by default 130 CustomizableUI.createWidget({ 131 id: comboButtonsID, 132 type: 'custom', 133 label: ZOTERO_CONFIG.CLIENT_NAME, 134 tooltiptext: ZOTERO_CONFIG.CLIENT_NAME, 135 defaultArea: CustomizableUI.AREA_NAVBAR, 136 onBuild: function (document) { 137 const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 138 139 var item = document.createElementNS(kNSXUL, "toolbaritem"); 140 item.setAttribute("id", comboButtonsID); 141 item.setAttribute("label", "Zotero (Combo)"); // TODO: localize 142 // Set this as an attribute in addition to the property to make sure we can style correctly. 143 item.setAttribute("removable", "true"); 144 item.classList.add("chromeclass-toolbar-additional"); 145 146 ['main', 'save'].map(button => { 147 return { 148 name: button, 149 id: getID(button), 150 tooltiptext: getTooltipText(button), 151 oncommand: getCommand(button) 152 }; 153 }).forEach(function(attribs, index) { 154 if (index != 0) { 155 item.appendChild(document.createElementNS(kNSXUL, "separator")); 156 } 157 let button = document.createElementNS(kNSXUL, "toolbarbutton"); 158 if (attribs.name == 'main') { 159 button.setAttribute('label', Zotero.clientName); 160 } 161 else if (attribs.name == 'save') { 162 button.setAttribute('label', Zotero.getString('ingester.saveToZotero')); 163 button.setAttribute('disabled', 'true'); 164 button.setAttribute('type', 'menu-button'); 165 let menupopup = document.createElementNS(kNSXUL, "menupopup"); 166 menupopup.setAttribute('onpopupshowing', "Zotero_Browser.onStatusPopupShowing(event)"); 167 button.appendChild(menupopup); 168 } 169 delete attribs.name; 170 setAttributes(button, attribs); 171 item.appendChild(button); 172 }); 173 174 updateItemForArea(item, this.currentArea) 175 176 return item; 177 } 178 }); 179 180 // Create the independent Z button, which isn't shown by default 181 CustomizableUI.createWidget({ 182 id: getSingleID('main'), 183 label: Zotero.clientName, 184 tooltiptext: getTooltipText('main'), 185 defaultArea: false, 186 onCommand: function (event) { 187 event.target.ownerDocument.defaultView.ZoteroOverlay.toggleDisplay(); 188 } 189 }); 190 191 // Create the independent save button, which isn't shown by default 192 CustomizableUI.createWidget({ 193 id: getSingleID('save'), 194 label: Zotero.getString('ingester.saveToZotero'), 195 tooltiptext: getTooltipText('save'), 196 defaultArea: false, 197 onCommand: function (event) { 198 event.target.ownerDocument.defaultView.Zotero_Browser.scrapeThisPage(null, event); 199 }, 200 onCreated: function (button) { 201 const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 202 button.setAttribute('disabled', 'true'); 203 button.setAttribute('type', 'menu-button'); 204 let menupopup = button.ownerDocument.createElementNS(kNSXUL, "menupopup"); 205 menupopup.setAttribute('onpopupshowing', "Zotero_Browser.onStatusPopupShowing(event)"); 206 button.appendChild(menupopup); 207 } 208 }); 209 210 Zotero.toolbarIconAdded = true; 211 } 212 213 function getID(button) { 214 switch (button) { 215 case 'main': 216 return "zotero-toolbar-main-button"; 217 218 case 'save': 219 return "zotero-toolbar-save-button"; 220 } 221 } 222 223 function getSingleID(button) { 224 return getID(button) + '-single'; 225 } 226 227 function getCommand(button) { 228 switch (button) { 229 case 'main': 230 return "ZoteroOverlay.toggleDisplay()"; 231 232 case 'save': 233 return "Zotero_Browser.scrapeThisPage(null, event)"; 234 } 235 } 236 237 function getTooltipText(button) { 238 var text; 239 switch (button) { 240 case 'main': 241 if (Zotero && Zotero.initialized) { 242 text = Zotero.clientName; 243 let key = Zotero.Keys.getKeyForCommand('openZotero'); 244 if (key) { 245 // Add RLE mark in RTL mode to make shortcut render the right way 246 text += (Zotero.rtl ? ' \u202B' : ' ') + '(' 247 + (Zotero.isMac ? '⇧⌘' : Zotero.getString('general.keys.ctrlShift')) 248 + key 249 + ')'; 250 } 251 252 } 253 else { 254 if (Zotero) { 255 text = Zotero.startupError; 256 } 257 258 // Use defaults if necessary 259 if (!text) { 260 let src = 'chrome://zotero/locale/zotero.properties'; 261 let stringBundleService = Components.classes["@mozilla.org/intl/stringbundle;1"] 262 .getService(Components.interfaces.nsIStringBundleService); 263 let stringBundle = stringBundleService.createBundle(src); 264 text = stringBundle.GetStringFromName('startupError'); 265 } 266 } 267 break; 268 269 case 'save': 270 text = Zotero.getString('ingester.saveToZotero'); 271 break; 272 } 273 return text; 274 } 275 276 /** 277 * Set various attributes that allow treeitem and subelements to be styled properly 278 * in the different areas 279 */ 280 function updateItemForArea(item, area) { 281 if (area) { 282 var areaType = CustomizableUI.getAreaType(area); 283 var inPanel = area == CustomizableUI.AREA_PANEL; 284 var classes = inPanel ? "panel-combined-button" : "toolbarbutton-1 toolbarbutton-combined"; 285 item.setAttribute("cui-areatype", areaType); 286 item.classList.add("toolbaritem-combined-buttons"); 287 if (inPanel) { 288 item.classList.add("panel-wide-item"); 289 } 290 var buttons = item.getElementsByTagName('toolbarbutton'); 291 for (let i = 0; i < buttons.length; i++) { 292 let button = buttons[i]; 293 button.setAttribute("class", classes); 294 button.setAttribute("cui-areatype", areaType); 295 } 296 } 297 // In customization palette pretend it's a single icon 298 else { 299 item.classList.remove("toolbaritem-combined-buttons"); 300 item.classList.remove("panel-wide-item"); 301 var buttons = item.getElementsByTagName('toolbarbutton'); 302 for (let i = 0; i < buttons.length; i++) { 303 let button = buttons[i]; 304 button.setAttribute("class", "toolbarbutton-1"); 305 button.removeAttribute("cui-areatype"); 306 } 307 } 308 } 309 310 function setAttributes(elem, attrs) { 311 for (let i in attrs) { 312 elem.setAttribute(i, attrs[i]); 313 } 314 }