Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | "use strict"; |
michael@0 | 6 | const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components; |
michael@0 | 7 | |
michael@0 | 8 | this.EXPORTED_SYMBOLS = ["CustomizableWidgets"]; |
michael@0 | 9 | |
michael@0 | 10 | Cu.import("resource:///modules/CustomizableUI.jsm"); |
michael@0 | 11 | Cu.import("resource://gre/modules/Services.jsm"); |
michael@0 | 12 | Cu.import("resource://gre/modules/XPCOMUtils.jsm"); |
michael@0 | 13 | XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", |
michael@0 | 14 | "resource://gre/modules/PlacesUtils.jsm"); |
michael@0 | 15 | XPCOMUtils.defineLazyModuleGetter(this, "PlacesUIUtils", |
michael@0 | 16 | "resource:///modules/PlacesUIUtils.jsm"); |
michael@0 | 17 | XPCOMUtils.defineLazyModuleGetter(this, "RecentlyClosedTabsAndWindowsMenuUtils", |
michael@0 | 18 | "resource:///modules/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.jsm"); |
michael@0 | 19 | XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils", |
michael@0 | 20 | "resource://gre/modules/ShortcutUtils.jsm"); |
michael@0 | 21 | XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu", |
michael@0 | 22 | "resource://gre/modules/CharsetMenu.jsm"); |
michael@0 | 23 | XPCOMUtils.defineLazyServiceGetter(this, "CharsetManager", |
michael@0 | 24 | "@mozilla.org/charset-converter-manager;1", |
michael@0 | 25 | "nsICharsetConverterManager"); |
michael@0 | 26 | |
michael@0 | 27 | XPCOMUtils.defineLazyGetter(this, "CharsetBundle", function() { |
michael@0 | 28 | const kCharsetBundle = "chrome://global/locale/charsetMenu.properties"; |
michael@0 | 29 | return Services.strings.createBundle(kCharsetBundle); |
michael@0 | 30 | }); |
michael@0 | 31 | XPCOMUtils.defineLazyGetter(this, "BrandBundle", function() { |
michael@0 | 32 | const kBrandBundle = "chrome://branding/locale/brand.properties"; |
michael@0 | 33 | return Services.strings.createBundle(kBrandBundle); |
michael@0 | 34 | }); |
michael@0 | 35 | |
michael@0 | 36 | const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; |
michael@0 | 37 | const kPrefCustomizationDebug = "browser.uiCustomization.debug"; |
michael@0 | 38 | const kWidePanelItemClass = "panel-wide-item"; |
michael@0 | 39 | |
michael@0 | 40 | let gModuleName = "[CustomizableWidgets]"; |
michael@0 | 41 | #include logging.js |
michael@0 | 42 | |
michael@0 | 43 | function setAttributes(aNode, aAttrs) { |
michael@0 | 44 | let doc = aNode.ownerDocument; |
michael@0 | 45 | for (let [name, value] of Iterator(aAttrs)) { |
michael@0 | 46 | if (!value) { |
michael@0 | 47 | if (aNode.hasAttribute(name)) |
michael@0 | 48 | aNode.removeAttribute(name); |
michael@0 | 49 | } else { |
michael@0 | 50 | if (name == "shortcutId") { |
michael@0 | 51 | continue; |
michael@0 | 52 | } |
michael@0 | 53 | if (name == "label" || name == "tooltiptext") { |
michael@0 | 54 | let stringId = (typeof value == "string") ? value : name; |
michael@0 | 55 | let additionalArgs = []; |
michael@0 | 56 | if (aAttrs.shortcutId) { |
michael@0 | 57 | let shortcut = doc.getElementById(aAttrs.shortcutId); |
michael@0 | 58 | if (doc) { |
michael@0 | 59 | additionalArgs.push(ShortcutUtils.prettifyShortcut(shortcut)); |
michael@0 | 60 | } |
michael@0 | 61 | } |
michael@0 | 62 | value = CustomizableUI.getLocalizedProperty({id: aAttrs.id}, stringId, additionalArgs); |
michael@0 | 63 | } |
michael@0 | 64 | aNode.setAttribute(name, value); |
michael@0 | 65 | } |
michael@0 | 66 | } |
michael@0 | 67 | } |
michael@0 | 68 | |
michael@0 | 69 | function updateCombinedWidgetStyle(aNode, aArea, aModifyCloseMenu) { |
michael@0 | 70 | let inPanel = (aArea == CustomizableUI.AREA_PANEL); |
michael@0 | 71 | let cls = inPanel ? "panel-combined-button" : "toolbarbutton-1 toolbarbutton-combined"; |
michael@0 | 72 | let attrs = {class: cls}; |
michael@0 | 73 | if (aModifyCloseMenu) { |
michael@0 | 74 | attrs.closemenu = inPanel ? "none" : null; |
michael@0 | 75 | } |
michael@0 | 76 | attrs["cui-areatype"] = aArea ? CustomizableUI.getAreaType(aArea) : null; |
michael@0 | 77 | for (let i = 0, l = aNode.childNodes.length; i < l; ++i) { |
michael@0 | 78 | if (aNode.childNodes[i].localName == "separator") |
michael@0 | 79 | continue; |
michael@0 | 80 | setAttributes(aNode.childNodes[i], attrs); |
michael@0 | 81 | } |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | function addShortcut(aNode, aDocument, aItem) { |
michael@0 | 85 | let shortcutId = aNode.getAttribute("key"); |
michael@0 | 86 | if (!shortcutId) { |
michael@0 | 87 | return; |
michael@0 | 88 | } |
michael@0 | 89 | let shortcut = aDocument.getElementById(shortcutId); |
michael@0 | 90 | if (!shortcut) { |
michael@0 | 91 | return; |
michael@0 | 92 | } |
michael@0 | 93 | aItem.setAttribute("shortcut", ShortcutUtils.prettifyShortcut(shortcut)); |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | function fillSubviewFromMenuItems(aMenuItems, aSubview) { |
michael@0 | 97 | let attrs = ["oncommand", "onclick", "label", "key", "disabled", |
michael@0 | 98 | "command", "observes", "hidden", "class", "origin", |
michael@0 | 99 | "image", "checked"]; |
michael@0 | 100 | |
michael@0 | 101 | let doc = aSubview.ownerDocument; |
michael@0 | 102 | let fragment = doc.createDocumentFragment(); |
michael@0 | 103 | for (let menuChild of aMenuItems) { |
michael@0 | 104 | if (menuChild.hidden) |
michael@0 | 105 | continue; |
michael@0 | 106 | |
michael@0 | 107 | let subviewItem; |
michael@0 | 108 | if (menuChild.localName == "menuseparator") { |
michael@0 | 109 | // Don't insert duplicate or leading separators. This can happen if there are |
michael@0 | 110 | // menus (which we don't copy) above the separator. |
michael@0 | 111 | if (!fragment.lastChild || fragment.lastChild.localName == "menuseparator") { |
michael@0 | 112 | continue; |
michael@0 | 113 | } |
michael@0 | 114 | subviewItem = doc.createElementNS(kNSXUL, "menuseparator"); |
michael@0 | 115 | } else if (menuChild.localName == "menuitem") { |
michael@0 | 116 | subviewItem = doc.createElementNS(kNSXUL, "toolbarbutton"); |
michael@0 | 117 | addShortcut(menuChild, doc, subviewItem); |
michael@0 | 118 | |
michael@0 | 119 | let item = menuChild; |
michael@0 | 120 | if (!item.hasAttribute("onclick")) { |
michael@0 | 121 | subviewItem.addEventListener("click", event => { |
michael@0 | 122 | let newEvent = new doc.defaultView.MouseEvent(event.type, event); |
michael@0 | 123 | item.dispatchEvent(newEvent); |
michael@0 | 124 | }); |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | if (!item.hasAttribute("oncommand")) { |
michael@0 | 128 | subviewItem.addEventListener("command", event => { |
michael@0 | 129 | let newEvent = doc.createEvent("XULCommandEvent"); |
michael@0 | 130 | newEvent.initCommandEvent( |
michael@0 | 131 | event.type, event.bubbles, event.cancelable, event.view, |
michael@0 | 132 | event.detail, event.ctrlKey, event.altKey, event.shiftKey, |
michael@0 | 133 | event.metaKey, event.sourceEvent); |
michael@0 | 134 | item.dispatchEvent(newEvent); |
michael@0 | 135 | }); |
michael@0 | 136 | } |
michael@0 | 137 | } else { |
michael@0 | 138 | continue; |
michael@0 | 139 | } |
michael@0 | 140 | for (let attr of attrs) { |
michael@0 | 141 | let attrVal = menuChild.getAttribute(attr); |
michael@0 | 142 | if (attrVal) |
michael@0 | 143 | subviewItem.setAttribute(attr, attrVal); |
michael@0 | 144 | } |
michael@0 | 145 | // We do this after so the .subviewbutton class doesn't get overriden. |
michael@0 | 146 | if (menuChild.localName == "menuitem") { |
michael@0 | 147 | subviewItem.classList.add("subviewbutton"); |
michael@0 | 148 | } |
michael@0 | 149 | fragment.appendChild(subviewItem); |
michael@0 | 150 | } |
michael@0 | 151 | aSubview.appendChild(fragment); |
michael@0 | 152 | } |
michael@0 | 153 | |
michael@0 | 154 | function clearSubview(aSubview) { |
michael@0 | 155 | let parent = aSubview.parentNode; |
michael@0 | 156 | // We'll take the container out of the document before cleaning it out |
michael@0 | 157 | // to avoid reflowing each time we remove something. |
michael@0 | 158 | parent.removeChild(aSubview); |
michael@0 | 159 | |
michael@0 | 160 | while (aSubview.firstChild) { |
michael@0 | 161 | aSubview.firstChild.remove(); |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | parent.appendChild(aSubview); |
michael@0 | 165 | } |
michael@0 | 166 | |
michael@0 | 167 | const CustomizableWidgets = [{ |
michael@0 | 168 | id: "history-panelmenu", |
michael@0 | 169 | type: "view", |
michael@0 | 170 | viewId: "PanelUI-history", |
michael@0 | 171 | shortcutId: "key_gotoHistory", |
michael@0 | 172 | tooltiptext: "history-panelmenu.tooltiptext2", |
michael@0 | 173 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 174 | onViewShowing: function(aEvent) { |
michael@0 | 175 | // Populate our list of history |
michael@0 | 176 | const kMaxResults = 15; |
michael@0 | 177 | let doc = aEvent.detail.ownerDocument; |
michael@0 | 178 | |
michael@0 | 179 | let options = PlacesUtils.history.getNewQueryOptions(); |
michael@0 | 180 | options.excludeQueries = true; |
michael@0 | 181 | options.includeHidden = false; |
michael@0 | 182 | options.resultType = options.RESULTS_AS_URI; |
michael@0 | 183 | options.queryType = options.QUERY_TYPE_HISTORY; |
michael@0 | 184 | options.sortingMode = options.SORT_BY_DATE_DESCENDING; |
michael@0 | 185 | options.maxResults = kMaxResults; |
michael@0 | 186 | let query = PlacesUtils.history.getNewQuery(); |
michael@0 | 187 | |
michael@0 | 188 | let items = doc.getElementById("PanelUI-historyItems"); |
michael@0 | 189 | // Clear previous history items. |
michael@0 | 190 | while (items.firstChild) { |
michael@0 | 191 | items.removeChild(items.firstChild); |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase) |
michael@0 | 195 | .asyncExecuteLegacyQueries([query], 1, options, { |
michael@0 | 196 | handleResult: function (aResultSet) { |
michael@0 | 197 | let onHistoryVisit = function (aUri, aEvent, aItem) { |
michael@0 | 198 | doc.defaultView.openUILink(aUri, aEvent); |
michael@0 | 199 | CustomizableUI.hidePanelForNode(aItem); |
michael@0 | 200 | }; |
michael@0 | 201 | let fragment = doc.createDocumentFragment(); |
michael@0 | 202 | for (let row, i = 0; (row = aResultSet.getNextRow()); i++) { |
michael@0 | 203 | try { |
michael@0 | 204 | let uri = row.getResultByIndex(1); |
michael@0 | 205 | let title = row.getResultByIndex(2); |
michael@0 | 206 | let icon = row.getResultByIndex(6); |
michael@0 | 207 | |
michael@0 | 208 | let item = doc.createElementNS(kNSXUL, "toolbarbutton"); |
michael@0 | 209 | item.setAttribute("label", title || uri); |
michael@0 | 210 | item.setAttribute("targetURI", uri); |
michael@0 | 211 | item.setAttribute("class", "subviewbutton"); |
michael@0 | 212 | item.addEventListener("click", function (aEvent) { |
michael@0 | 213 | onHistoryVisit(uri, aEvent, item); |
michael@0 | 214 | }); |
michael@0 | 215 | if (icon) |
michael@0 | 216 | item.setAttribute("image", "moz-anno:favicon:" + icon); |
michael@0 | 217 | fragment.appendChild(item); |
michael@0 | 218 | } catch (e) { |
michael@0 | 219 | ERROR("Error while showing history subview: " + e); |
michael@0 | 220 | } |
michael@0 | 221 | } |
michael@0 | 222 | items.appendChild(fragment); |
michael@0 | 223 | }, |
michael@0 | 224 | handleError: function (aError) { |
michael@0 | 225 | LOG("History view tried to show but had an error: " + aError); |
michael@0 | 226 | }, |
michael@0 | 227 | handleCompletion: function (aReason) { |
michael@0 | 228 | LOG("History view is being shown!"); |
michael@0 | 229 | }, |
michael@0 | 230 | }); |
michael@0 | 231 | |
michael@0 | 232 | let recentlyClosedTabs = doc.getElementById("PanelUI-recentlyClosedTabs"); |
michael@0 | 233 | while (recentlyClosedTabs.firstChild) { |
michael@0 | 234 | recentlyClosedTabs.removeChild(recentlyClosedTabs.firstChild); |
michael@0 | 235 | } |
michael@0 | 236 | |
michael@0 | 237 | let recentlyClosedWindows = doc.getElementById("PanelUI-recentlyClosedWindows"); |
michael@0 | 238 | while (recentlyClosedWindows.firstChild) { |
michael@0 | 239 | recentlyClosedWindows.removeChild(recentlyClosedWindows.firstChild); |
michael@0 | 240 | } |
michael@0 | 241 | |
michael@0 | 242 | #ifdef MOZ_SERVICES_SYNC |
michael@0 | 243 | let tabsFromOtherComputers = doc.getElementById("sync-tabs-menuitem2"); |
michael@0 | 244 | if (PlacesUIUtils.shouldShowTabsFromOtherComputersMenuitem()) { |
michael@0 | 245 | tabsFromOtherComputers.removeAttribute("hidden"); |
michael@0 | 246 | } else { |
michael@0 | 247 | tabsFromOtherComputers.setAttribute("hidden", true); |
michael@0 | 248 | } |
michael@0 | 249 | |
michael@0 | 250 | if (PlacesUIUtils.shouldEnableTabsFromOtherComputersMenuitem()) { |
michael@0 | 251 | tabsFromOtherComputers.removeAttribute("disabled"); |
michael@0 | 252 | } else { |
michael@0 | 253 | tabsFromOtherComputers.setAttribute("disabled", true); |
michael@0 | 254 | } |
michael@0 | 255 | #endif |
michael@0 | 256 | |
michael@0 | 257 | let utils = RecentlyClosedTabsAndWindowsMenuUtils; |
michael@0 | 258 | let tabsFragment = utils.getTabsFragment(doc.defaultView, "toolbarbutton", true, |
michael@0 | 259 | "menuRestoreAllTabsSubview.label"); |
michael@0 | 260 | let separator = doc.getElementById("PanelUI-recentlyClosedTabs-separator"); |
michael@0 | 261 | let elementCount = tabsFragment.childElementCount; |
michael@0 | 262 | separator.hidden = !elementCount; |
michael@0 | 263 | while (--elementCount >= 0) { |
michael@0 | 264 | tabsFragment.children[elementCount].classList.add("subviewbutton"); |
michael@0 | 265 | } |
michael@0 | 266 | recentlyClosedTabs.appendChild(tabsFragment); |
michael@0 | 267 | |
michael@0 | 268 | let windowsFragment = utils.getWindowsFragment(doc.defaultView, "toolbarbutton", true, |
michael@0 | 269 | "menuRestoreAllWindowsSubview.label"); |
michael@0 | 270 | separator = doc.getElementById("PanelUI-recentlyClosedWindows-separator"); |
michael@0 | 271 | elementCount = windowsFragment.childElementCount; |
michael@0 | 272 | separator.hidden = !elementCount; |
michael@0 | 273 | while (--elementCount >= 0) { |
michael@0 | 274 | windowsFragment.children[elementCount].classList.add("subviewbutton"); |
michael@0 | 275 | } |
michael@0 | 276 | recentlyClosedWindows.appendChild(windowsFragment); |
michael@0 | 277 | }, |
michael@0 | 278 | onCreated: function(aNode) { |
michael@0 | 279 | // Middle clicking recently closed items won't close the panel - cope: |
michael@0 | 280 | let onRecentlyClosedClick = function(aEvent) { |
michael@0 | 281 | if (aEvent.button == 1) { |
michael@0 | 282 | CustomizableUI.hidePanelForNode(this); |
michael@0 | 283 | } |
michael@0 | 284 | }; |
michael@0 | 285 | let doc = aNode.ownerDocument; |
michael@0 | 286 | let recentlyClosedTabs = doc.getElementById("PanelUI-recentlyClosedTabs"); |
michael@0 | 287 | let recentlyClosedWindows = doc.getElementById("PanelUI-recentlyClosedWindows"); |
michael@0 | 288 | recentlyClosedTabs.addEventListener("click", onRecentlyClosedClick); |
michael@0 | 289 | recentlyClosedWindows.addEventListener("click", onRecentlyClosedClick); |
michael@0 | 290 | }, |
michael@0 | 291 | onViewHiding: function(aEvent) { |
michael@0 | 292 | LOG("History view is being hidden!"); |
michael@0 | 293 | } |
michael@0 | 294 | }, { |
michael@0 | 295 | id: "privatebrowsing-button", |
michael@0 | 296 | shortcutId: "key_privatebrowsing", |
michael@0 | 297 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 298 | onCommand: function(e) { |
michael@0 | 299 | if (e.target && e.target.ownerDocument && e.target.ownerDocument.defaultView) { |
michael@0 | 300 | let win = e.target.ownerDocument.defaultView; |
michael@0 | 301 | if (typeof win.OpenBrowserWindow == "function") { |
michael@0 | 302 | win.OpenBrowserWindow({private: true}); |
michael@0 | 303 | } |
michael@0 | 304 | } |
michael@0 | 305 | } |
michael@0 | 306 | }, { |
michael@0 | 307 | id: "save-page-button", |
michael@0 | 308 | shortcutId: "key_savePage", |
michael@0 | 309 | tooltiptext: "save-page-button.tooltiptext3", |
michael@0 | 310 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 311 | onCommand: function(aEvent) { |
michael@0 | 312 | let win = aEvent.target && |
michael@0 | 313 | aEvent.target.ownerDocument && |
michael@0 | 314 | aEvent.target.ownerDocument.defaultView; |
michael@0 | 315 | if (win && typeof win.saveDocument == "function") { |
michael@0 | 316 | win.saveDocument(win.content.document); |
michael@0 | 317 | } |
michael@0 | 318 | } |
michael@0 | 319 | }, { |
michael@0 | 320 | id: "find-button", |
michael@0 | 321 | shortcutId: "key_find", |
michael@0 | 322 | tooltiptext: "find-button.tooltiptext3", |
michael@0 | 323 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 324 | onCommand: function(aEvent) { |
michael@0 | 325 | let win = aEvent.target && |
michael@0 | 326 | aEvent.target.ownerDocument && |
michael@0 | 327 | aEvent.target.ownerDocument.defaultView; |
michael@0 | 328 | if (win && win.gFindBar) { |
michael@0 | 329 | win.gFindBar.onFindCommand(); |
michael@0 | 330 | } |
michael@0 | 331 | } |
michael@0 | 332 | }, { |
michael@0 | 333 | id: "open-file-button", |
michael@0 | 334 | shortcutId: "openFileKb", |
michael@0 | 335 | tooltiptext: "open-file-button.tooltiptext3", |
michael@0 | 336 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 337 | onCommand: function(aEvent) { |
michael@0 | 338 | let win = aEvent.target |
michael@0 | 339 | && aEvent.target.ownerDocument |
michael@0 | 340 | && aEvent.target.ownerDocument.defaultView; |
michael@0 | 341 | if (win && typeof win.BrowserOpenFileWindow == "function") { |
michael@0 | 342 | win.BrowserOpenFileWindow(); |
michael@0 | 343 | } |
michael@0 | 344 | } |
michael@0 | 345 | }, { |
michael@0 | 346 | id: "developer-button", |
michael@0 | 347 | type: "view", |
michael@0 | 348 | viewId: "PanelUI-developer", |
michael@0 | 349 | shortcutId: "key_devToolboxMenuItem", |
michael@0 | 350 | tooltiptext: "developer-button.tooltiptext2", |
michael@0 | 351 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 352 | onViewShowing: function(aEvent) { |
michael@0 | 353 | // Populate the subview with whatever menuitems are in the developer |
michael@0 | 354 | // menu. We skip menu elements, because the menu panel has no way |
michael@0 | 355 | // of dealing with those right now. |
michael@0 | 356 | let doc = aEvent.target.ownerDocument; |
michael@0 | 357 | let win = doc.defaultView; |
michael@0 | 358 | |
michael@0 | 359 | let menu = doc.getElementById("menuWebDeveloperPopup"); |
michael@0 | 360 | |
michael@0 | 361 | let itemsToDisplay = [...menu.children]; |
michael@0 | 362 | // Hardcode the addition of the "work offline" menuitem at the bottom: |
michael@0 | 363 | itemsToDisplay.push({localName: "menuseparator", getAttribute: () => {}}); |
michael@0 | 364 | itemsToDisplay.push(doc.getElementById("goOfflineMenuitem")); |
michael@0 | 365 | fillSubviewFromMenuItems(itemsToDisplay, doc.getElementById("PanelUI-developerItems")); |
michael@0 | 366 | |
michael@0 | 367 | }, |
michael@0 | 368 | onViewHiding: function(aEvent) { |
michael@0 | 369 | let doc = aEvent.target.ownerDocument; |
michael@0 | 370 | clearSubview(doc.getElementById("PanelUI-developerItems")); |
michael@0 | 371 | } |
michael@0 | 372 | }, { |
michael@0 | 373 | id: "sidebar-button", |
michael@0 | 374 | type: "view", |
michael@0 | 375 | viewId: "PanelUI-sidebar", |
michael@0 | 376 | tooltiptext: "sidebar-button.tooltiptext2", |
michael@0 | 377 | onViewShowing: function(aEvent) { |
michael@0 | 378 | // Largely duplicated from the developer-button above with a couple minor |
michael@0 | 379 | // alterations. |
michael@0 | 380 | // Populate the subview with whatever menuitems are in the |
michael@0 | 381 | // sidebar menu. We skip menu elements, because the menu panel has no way |
michael@0 | 382 | // of dealing with those right now. |
michael@0 | 383 | let doc = aEvent.target.ownerDocument; |
michael@0 | 384 | let win = doc.defaultView; |
michael@0 | 385 | let menu = doc.getElementById("viewSidebarMenu"); |
michael@0 | 386 | |
michael@0 | 387 | // First clear any existing menuitems then populate. Social sidebar |
michael@0 | 388 | // options may not have been added yet, so we do that here. Add it to the |
michael@0 | 389 | // standard menu first, then copy all sidebar options to the panel. |
michael@0 | 390 | win.SocialSidebar.clearProviderMenus(); |
michael@0 | 391 | let providerMenuSeps = menu.getElementsByClassName("social-provider-menu"); |
michael@0 | 392 | if (providerMenuSeps.length > 0) |
michael@0 | 393 | win.SocialSidebar.populateProviderMenu(providerMenuSeps[0]); |
michael@0 | 394 | |
michael@0 | 395 | fillSubviewFromMenuItems([...menu.children], doc.getElementById("PanelUI-sidebarItems")); |
michael@0 | 396 | }, |
michael@0 | 397 | onViewHiding: function(aEvent) { |
michael@0 | 398 | let doc = aEvent.target.ownerDocument; |
michael@0 | 399 | clearSubview(doc.getElementById("PanelUI-sidebarItems")); |
michael@0 | 400 | } |
michael@0 | 401 | }, { |
michael@0 | 402 | id: "add-ons-button", |
michael@0 | 403 | shortcutId: "key_openAddons", |
michael@0 | 404 | tooltiptext: "add-ons-button.tooltiptext3", |
michael@0 | 405 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 406 | onCommand: function(aEvent) { |
michael@0 | 407 | let win = aEvent.target && |
michael@0 | 408 | aEvent.target.ownerDocument && |
michael@0 | 409 | aEvent.target.ownerDocument.defaultView; |
michael@0 | 410 | if (win && typeof win.BrowserOpenAddonsMgr == "function") { |
michael@0 | 411 | win.BrowserOpenAddonsMgr(); |
michael@0 | 412 | } |
michael@0 | 413 | } |
michael@0 | 414 | }, { |
michael@0 | 415 | id: "preferences-button", |
michael@0 | 416 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 417 | #ifdef XP_WIN |
michael@0 | 418 | label: "preferences-button.labelWin", |
michael@0 | 419 | tooltiptext: "preferences-button.tooltipWin2", |
michael@0 | 420 | #else |
michael@0 | 421 | #ifdef XP_MACOSX |
michael@0 | 422 | tooltiptext: "preferences-button.tooltiptext.withshortcut", |
michael@0 | 423 | shortcutId: "key_preferencesCmdMac", |
michael@0 | 424 | #else |
michael@0 | 425 | tooltiptext: "preferences-button.tooltiptext2", |
michael@0 | 426 | #endif |
michael@0 | 427 | #endif |
michael@0 | 428 | onCommand: function(aEvent) { |
michael@0 | 429 | let win = aEvent.target && |
michael@0 | 430 | aEvent.target.ownerDocument && |
michael@0 | 431 | aEvent.target.ownerDocument.defaultView; |
michael@0 | 432 | if (win && typeof win.openPreferences == "function") { |
michael@0 | 433 | win.openPreferences(); |
michael@0 | 434 | } |
michael@0 | 435 | } |
michael@0 | 436 | }, { |
michael@0 | 437 | id: "zoom-controls", |
michael@0 | 438 | type: "custom", |
michael@0 | 439 | tooltiptext: "zoom-controls.tooltiptext2", |
michael@0 | 440 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 441 | onBuild: function(aDocument) { |
michael@0 | 442 | const kPanelId = "PanelUI-popup"; |
michael@0 | 443 | let areaType = CustomizableUI.getAreaType(this.currentArea); |
michael@0 | 444 | let inPanel = areaType == CustomizableUI.TYPE_MENU_PANEL; |
michael@0 | 445 | let inToolbar = areaType == CustomizableUI.TYPE_TOOLBAR; |
michael@0 | 446 | |
michael@0 | 447 | let buttons = [{ |
michael@0 | 448 | id: "zoom-out-button", |
michael@0 | 449 | command: "cmd_fullZoomReduce", |
michael@0 | 450 | label: true, |
michael@0 | 451 | tooltiptext: "tooltiptext2", |
michael@0 | 452 | shortcutId: "key_fullZoomReduce", |
michael@0 | 453 | }, { |
michael@0 | 454 | id: "zoom-reset-button", |
michael@0 | 455 | command: "cmd_fullZoomReset", |
michael@0 | 456 | tooltiptext: "tooltiptext2", |
michael@0 | 457 | shortcutId: "key_fullZoomReset", |
michael@0 | 458 | }, { |
michael@0 | 459 | id: "zoom-in-button", |
michael@0 | 460 | command: "cmd_fullZoomEnlarge", |
michael@0 | 461 | label: true, |
michael@0 | 462 | tooltiptext: "tooltiptext2", |
michael@0 | 463 | shortcutId: "key_fullZoomEnlarge", |
michael@0 | 464 | }]; |
michael@0 | 465 | |
michael@0 | 466 | let node = aDocument.createElementNS(kNSXUL, "toolbaritem"); |
michael@0 | 467 | node.setAttribute("id", "zoom-controls"); |
michael@0 | 468 | node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label")); |
michael@0 | 469 | node.setAttribute("title", CustomizableUI.getLocalizedProperty(this, "tooltiptext")); |
michael@0 | 470 | // Set this as an attribute in addition to the property to make sure we can style correctly. |
michael@0 | 471 | node.setAttribute("removable", "true"); |
michael@0 | 472 | node.classList.add("chromeclass-toolbar-additional"); |
michael@0 | 473 | node.classList.add("toolbaritem-combined-buttons"); |
michael@0 | 474 | node.classList.add(kWidePanelItemClass); |
michael@0 | 475 | |
michael@0 | 476 | buttons.forEach(function(aButton, aIndex) { |
michael@0 | 477 | if (aIndex != 0) |
michael@0 | 478 | node.appendChild(aDocument.createElementNS(kNSXUL, "separator")); |
michael@0 | 479 | let btnNode = aDocument.createElementNS(kNSXUL, "toolbarbutton"); |
michael@0 | 480 | setAttributes(btnNode, aButton); |
michael@0 | 481 | node.appendChild(btnNode); |
michael@0 | 482 | }); |
michael@0 | 483 | |
michael@0 | 484 | // The middle node is the 'Reset Zoom' button. |
michael@0 | 485 | let zoomResetButton = node.childNodes[2]; |
michael@0 | 486 | let window = aDocument.defaultView; |
michael@0 | 487 | function updateZoomResetButton() { |
michael@0 | 488 | let updateDisplay = true; |
michael@0 | 489 | // Label should always show 100% in customize mode, so don't update: |
michael@0 | 490 | if (aDocument.documentElement.hasAttribute("customizing")) { |
michael@0 | 491 | updateDisplay = false; |
michael@0 | 492 | } |
michael@0 | 493 | //XXXgijs in some tests we get called very early, and there's no docShell on the |
michael@0 | 494 | // tabbrowser. This breaks the zoom toolkit code (see bug 897410). Don't let that happen: |
michael@0 | 495 | let zoomFactor = 100; |
michael@0 | 496 | try { |
michael@0 | 497 | zoomFactor = Math.round(window.ZoomManager.zoom * 100); |
michael@0 | 498 | } catch (e) {} |
michael@0 | 499 | zoomResetButton.setAttribute("label", CustomizableUI.getLocalizedProperty( |
michael@0 | 500 | buttons[1], "label", [updateDisplay ? zoomFactor : 100] |
michael@0 | 501 | )); |
michael@0 | 502 | }; |
michael@0 | 503 | |
michael@0 | 504 | // Register ourselves with the service so we know when the zoom prefs change. |
michael@0 | 505 | Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:zoomChange", false); |
michael@0 | 506 | Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:zoomReset", false); |
michael@0 | 507 | Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:location-change", false); |
michael@0 | 508 | |
michael@0 | 509 | if (inPanel) { |
michael@0 | 510 | let panel = aDocument.getElementById(kPanelId); |
michael@0 | 511 | panel.addEventListener("popupshowing", updateZoomResetButton); |
michael@0 | 512 | } else { |
michael@0 | 513 | if (inToolbar) { |
michael@0 | 514 | let container = window.gBrowser.tabContainer; |
michael@0 | 515 | container.addEventListener("TabSelect", updateZoomResetButton); |
michael@0 | 516 | } |
michael@0 | 517 | updateZoomResetButton(); |
michael@0 | 518 | } |
michael@0 | 519 | updateCombinedWidgetStyle(node, this.currentArea, true); |
michael@0 | 520 | |
michael@0 | 521 | let listener = { |
michael@0 | 522 | onWidgetAdded: function(aWidgetId, aArea, aPosition) { |
michael@0 | 523 | if (aWidgetId != this.id) |
michael@0 | 524 | return; |
michael@0 | 525 | |
michael@0 | 526 | updateCombinedWidgetStyle(node, aArea, true); |
michael@0 | 527 | updateZoomResetButton(); |
michael@0 | 528 | |
michael@0 | 529 | let areaType = CustomizableUI.getAreaType(aArea); |
michael@0 | 530 | if (areaType == CustomizableUI.TYPE_MENU_PANEL) { |
michael@0 | 531 | let panel = aDocument.getElementById(kPanelId); |
michael@0 | 532 | panel.addEventListener("popupshowing", updateZoomResetButton); |
michael@0 | 533 | } else if (areaType == CustomizableUI.TYPE_TOOLBAR) { |
michael@0 | 534 | let container = window.gBrowser.tabContainer; |
michael@0 | 535 | container.addEventListener("TabSelect", updateZoomResetButton); |
michael@0 | 536 | } |
michael@0 | 537 | }.bind(this), |
michael@0 | 538 | |
michael@0 | 539 | onWidgetRemoved: function(aWidgetId, aPrevArea) { |
michael@0 | 540 | if (aWidgetId != this.id) |
michael@0 | 541 | return; |
michael@0 | 542 | |
michael@0 | 543 | let areaType = CustomizableUI.getAreaType(aPrevArea); |
michael@0 | 544 | if (areaType == CustomizableUI.TYPE_MENU_PANEL) { |
michael@0 | 545 | let panel = aDocument.getElementById(kPanelId); |
michael@0 | 546 | panel.removeEventListener("popupshowing", updateZoomResetButton); |
michael@0 | 547 | } else if (areaType == CustomizableUI.TYPE_TOOLBAR) { |
michael@0 | 548 | let container = window.gBrowser.tabContainer; |
michael@0 | 549 | container.removeEventListener("TabSelect", updateZoomResetButton); |
michael@0 | 550 | } |
michael@0 | 551 | |
michael@0 | 552 | // When a widget is demoted to the palette ('removed'), it's visual |
michael@0 | 553 | // style should change. |
michael@0 | 554 | updateCombinedWidgetStyle(node, null, true); |
michael@0 | 555 | updateZoomResetButton(); |
michael@0 | 556 | }.bind(this), |
michael@0 | 557 | |
michael@0 | 558 | onWidgetReset: function(aWidgetNode) { |
michael@0 | 559 | if (aWidgetNode != node) |
michael@0 | 560 | return; |
michael@0 | 561 | updateCombinedWidgetStyle(node, this.currentArea, true); |
michael@0 | 562 | updateZoomResetButton(); |
michael@0 | 563 | }.bind(this), |
michael@0 | 564 | |
michael@0 | 565 | onWidgetMoved: function(aWidgetId, aArea) { |
michael@0 | 566 | if (aWidgetId != this.id) |
michael@0 | 567 | return; |
michael@0 | 568 | updateCombinedWidgetStyle(node, aArea, true); |
michael@0 | 569 | updateZoomResetButton(); |
michael@0 | 570 | }.bind(this), |
michael@0 | 571 | |
michael@0 | 572 | onWidgetInstanceRemoved: function(aWidgetId, aDoc) { |
michael@0 | 573 | if (aWidgetId != this.id || aDoc != aDocument) |
michael@0 | 574 | return; |
michael@0 | 575 | |
michael@0 | 576 | CustomizableUI.removeListener(listener); |
michael@0 | 577 | Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:zoomChange"); |
michael@0 | 578 | Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:zoomReset"); |
michael@0 | 579 | Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:location-change"); |
michael@0 | 580 | let panel = aDoc.getElementById(kPanelId); |
michael@0 | 581 | panel.removeEventListener("popupshowing", updateZoomResetButton); |
michael@0 | 582 | let container = aDoc.defaultView.gBrowser.tabContainer; |
michael@0 | 583 | container.removeEventListener("TabSelect", updateZoomResetButton); |
michael@0 | 584 | }.bind(this), |
michael@0 | 585 | |
michael@0 | 586 | onCustomizeStart: function(aWindow) { |
michael@0 | 587 | if (aWindow.document == aDocument) { |
michael@0 | 588 | updateZoomResetButton(); |
michael@0 | 589 | } |
michael@0 | 590 | }, |
michael@0 | 591 | |
michael@0 | 592 | onCustomizeEnd: function(aWindow) { |
michael@0 | 593 | if (aWindow.document == aDocument) { |
michael@0 | 594 | updateZoomResetButton(); |
michael@0 | 595 | } |
michael@0 | 596 | }, |
michael@0 | 597 | |
michael@0 | 598 | onWidgetDrag: function(aWidgetId, aArea) { |
michael@0 | 599 | if (aWidgetId != this.id) |
michael@0 | 600 | return; |
michael@0 | 601 | aArea = aArea || this.currentArea; |
michael@0 | 602 | updateCombinedWidgetStyle(node, aArea, true); |
michael@0 | 603 | }.bind(this) |
michael@0 | 604 | }; |
michael@0 | 605 | CustomizableUI.addListener(listener); |
michael@0 | 606 | |
michael@0 | 607 | return node; |
michael@0 | 608 | } |
michael@0 | 609 | }, { |
michael@0 | 610 | id: "edit-controls", |
michael@0 | 611 | type: "custom", |
michael@0 | 612 | tooltiptext: "edit-controls.tooltiptext2", |
michael@0 | 613 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 614 | onBuild: function(aDocument) { |
michael@0 | 615 | let buttons = [{ |
michael@0 | 616 | id: "cut-button", |
michael@0 | 617 | command: "cmd_cut", |
michael@0 | 618 | label: true, |
michael@0 | 619 | tooltiptext: "tooltiptext2", |
michael@0 | 620 | shortcutId: "key_cut", |
michael@0 | 621 | }, { |
michael@0 | 622 | id: "copy-button", |
michael@0 | 623 | command: "cmd_copy", |
michael@0 | 624 | label: true, |
michael@0 | 625 | tooltiptext: "tooltiptext2", |
michael@0 | 626 | shortcutId: "key_copy", |
michael@0 | 627 | }, { |
michael@0 | 628 | id: "paste-button", |
michael@0 | 629 | command: "cmd_paste", |
michael@0 | 630 | label: true, |
michael@0 | 631 | tooltiptext: "tooltiptext2", |
michael@0 | 632 | shortcutId: "key_paste", |
michael@0 | 633 | }]; |
michael@0 | 634 | |
michael@0 | 635 | let node = aDocument.createElementNS(kNSXUL, "toolbaritem"); |
michael@0 | 636 | node.setAttribute("id", "edit-controls"); |
michael@0 | 637 | node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label")); |
michael@0 | 638 | node.setAttribute("title", CustomizableUI.getLocalizedProperty(this, "tooltiptext")); |
michael@0 | 639 | // Set this as an attribute in addition to the property to make sure we can style correctly. |
michael@0 | 640 | node.setAttribute("removable", "true"); |
michael@0 | 641 | node.classList.add("chromeclass-toolbar-additional"); |
michael@0 | 642 | node.classList.add("toolbaritem-combined-buttons"); |
michael@0 | 643 | node.classList.add(kWidePanelItemClass); |
michael@0 | 644 | |
michael@0 | 645 | buttons.forEach(function(aButton, aIndex) { |
michael@0 | 646 | if (aIndex != 0) |
michael@0 | 647 | node.appendChild(aDocument.createElementNS(kNSXUL, "separator")); |
michael@0 | 648 | let btnNode = aDocument.createElementNS(kNSXUL, "toolbarbutton"); |
michael@0 | 649 | setAttributes(btnNode, aButton); |
michael@0 | 650 | node.appendChild(btnNode); |
michael@0 | 651 | }); |
michael@0 | 652 | |
michael@0 | 653 | updateCombinedWidgetStyle(node, this.currentArea); |
michael@0 | 654 | |
michael@0 | 655 | let listener = { |
michael@0 | 656 | onWidgetAdded: function(aWidgetId, aArea, aPosition) { |
michael@0 | 657 | if (aWidgetId != this.id) |
michael@0 | 658 | return; |
michael@0 | 659 | updateCombinedWidgetStyle(node, aArea); |
michael@0 | 660 | }.bind(this), |
michael@0 | 661 | |
michael@0 | 662 | onWidgetRemoved: function(aWidgetId, aPrevArea) { |
michael@0 | 663 | if (aWidgetId != this.id) |
michael@0 | 664 | return; |
michael@0 | 665 | // When a widget is demoted to the palette ('removed'), it's visual |
michael@0 | 666 | // style should change. |
michael@0 | 667 | updateCombinedWidgetStyle(node); |
michael@0 | 668 | }.bind(this), |
michael@0 | 669 | |
michael@0 | 670 | onWidgetReset: function(aWidgetNode) { |
michael@0 | 671 | if (aWidgetNode != node) |
michael@0 | 672 | return; |
michael@0 | 673 | updateCombinedWidgetStyle(node, this.currentArea); |
michael@0 | 674 | }.bind(this), |
michael@0 | 675 | |
michael@0 | 676 | onWidgetMoved: function(aWidgetId, aArea) { |
michael@0 | 677 | if (aWidgetId != this.id) |
michael@0 | 678 | return; |
michael@0 | 679 | updateCombinedWidgetStyle(node, aArea); |
michael@0 | 680 | }.bind(this), |
michael@0 | 681 | |
michael@0 | 682 | onWidgetInstanceRemoved: function(aWidgetId, aDoc) { |
michael@0 | 683 | if (aWidgetId != this.id || aDoc != aDocument) |
michael@0 | 684 | return; |
michael@0 | 685 | CustomizableUI.removeListener(listener); |
michael@0 | 686 | }.bind(this), |
michael@0 | 687 | |
michael@0 | 688 | onWidgetDrag: function(aWidgetId, aArea) { |
michael@0 | 689 | if (aWidgetId != this.id) |
michael@0 | 690 | return; |
michael@0 | 691 | aArea = aArea || this.currentArea; |
michael@0 | 692 | updateCombinedWidgetStyle(node, aArea); |
michael@0 | 693 | }.bind(this) |
michael@0 | 694 | }; |
michael@0 | 695 | CustomizableUI.addListener(listener); |
michael@0 | 696 | |
michael@0 | 697 | return node; |
michael@0 | 698 | } |
michael@0 | 699 | }, |
michael@0 | 700 | { |
michael@0 | 701 | id: "feed-button", |
michael@0 | 702 | type: "view", |
michael@0 | 703 | viewId: "PanelUI-feeds", |
michael@0 | 704 | tooltiptext: "feed-button.tooltiptext2", |
michael@0 | 705 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 706 | onClick: function(aEvent) { |
michael@0 | 707 | let win = aEvent.target.ownerDocument.defaultView; |
michael@0 | 708 | let feeds = win.gBrowser.selectedBrowser.feeds; |
michael@0 | 709 | |
michael@0 | 710 | // Here, we only care about the case where we have exactly 1 feed and the |
michael@0 | 711 | // user clicked... |
michael@0 | 712 | let isClick = (aEvent.button == 0 || aEvent.button == 1); |
michael@0 | 713 | if (feeds && feeds.length == 1 && isClick) { |
michael@0 | 714 | aEvent.preventDefault(); |
michael@0 | 715 | aEvent.stopPropagation(); |
michael@0 | 716 | win.FeedHandler.subscribeToFeed(feeds[0].href, aEvent); |
michael@0 | 717 | CustomizableUI.hidePanelForNode(aEvent.target); |
michael@0 | 718 | } |
michael@0 | 719 | }, |
michael@0 | 720 | onViewShowing: function(aEvent) { |
michael@0 | 721 | let doc = aEvent.detail.ownerDocument; |
michael@0 | 722 | let container = doc.getElementById("PanelUI-feeds"); |
michael@0 | 723 | let gotView = doc.defaultView.FeedHandler.buildFeedList(container, true); |
michael@0 | 724 | |
michael@0 | 725 | // For no feeds or only a single one, don't show the panel. |
michael@0 | 726 | if (!gotView) { |
michael@0 | 727 | aEvent.preventDefault(); |
michael@0 | 728 | aEvent.stopPropagation(); |
michael@0 | 729 | return; |
michael@0 | 730 | } |
michael@0 | 731 | }, |
michael@0 | 732 | onCreated: function(node) { |
michael@0 | 733 | let win = node.ownerDocument.defaultView; |
michael@0 | 734 | let selectedBrowser = win.gBrowser.selectedBrowser; |
michael@0 | 735 | let feeds = selectedBrowser && selectedBrowser.feeds; |
michael@0 | 736 | if (!feeds || !feeds.length) { |
michael@0 | 737 | node.setAttribute("disabled", "true"); |
michael@0 | 738 | } |
michael@0 | 739 | } |
michael@0 | 740 | }, { |
michael@0 | 741 | id: "characterencoding-button", |
michael@0 | 742 | type: "view", |
michael@0 | 743 | viewId: "PanelUI-characterEncodingView", |
michael@0 | 744 | tooltiptext: "characterencoding-button.tooltiptext2", |
michael@0 | 745 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 746 | maybeDisableMenu: function(aDocument) { |
michael@0 | 747 | let window = aDocument.defaultView; |
michael@0 | 748 | return !(window.gBrowser && |
michael@0 | 749 | window.gBrowser.docShell && |
michael@0 | 750 | window.gBrowser.docShell.mayEnableCharacterEncodingMenu); |
michael@0 | 751 | }, |
michael@0 | 752 | populateList: function(aDocument, aContainerId, aSection) { |
michael@0 | 753 | let containerElem = aDocument.getElementById(aContainerId); |
michael@0 | 754 | |
michael@0 | 755 | containerElem.addEventListener("command", this.onCommand, false); |
michael@0 | 756 | |
michael@0 | 757 | let list = this.charsetInfo[aSection]; |
michael@0 | 758 | |
michael@0 | 759 | for (let item of list) { |
michael@0 | 760 | let elem = aDocument.createElementNS(kNSXUL, "toolbarbutton"); |
michael@0 | 761 | elem.setAttribute("label", item.label); |
michael@0 | 762 | elem.setAttribute("type", "checkbox"); |
michael@0 | 763 | elem.section = aSection; |
michael@0 | 764 | elem.value = item.value; |
michael@0 | 765 | elem.setAttribute("class", "subviewbutton"); |
michael@0 | 766 | containerElem.appendChild(elem); |
michael@0 | 767 | } |
michael@0 | 768 | }, |
michael@0 | 769 | updateCurrentCharset: function(aDocument) { |
michael@0 | 770 | let content = aDocument.defaultView.content; |
michael@0 | 771 | let currentCharset = content && content.document && content.document.characterSet; |
michael@0 | 772 | currentCharset = CharsetMenu.foldCharset(currentCharset); |
michael@0 | 773 | |
michael@0 | 774 | let pinnedContainer = aDocument.getElementById("PanelUI-characterEncodingView-pinned"); |
michael@0 | 775 | let charsetContainer = aDocument.getElementById("PanelUI-characterEncodingView-charsets"); |
michael@0 | 776 | let elements = [...(pinnedContainer.childNodes), ...(charsetContainer.childNodes)]; |
michael@0 | 777 | |
michael@0 | 778 | this._updateElements(elements, currentCharset); |
michael@0 | 779 | }, |
michael@0 | 780 | updateCurrentDetector: function(aDocument) { |
michael@0 | 781 | let detectorContainer = aDocument.getElementById("PanelUI-characterEncodingView-autodetect"); |
michael@0 | 782 | let currentDetector; |
michael@0 | 783 | try { |
michael@0 | 784 | currentDetector = Services.prefs.getComplexValue( |
michael@0 | 785 | "intl.charset.detector", Ci.nsIPrefLocalizedString).data; |
michael@0 | 786 | } catch (e) {} |
michael@0 | 787 | |
michael@0 | 788 | this._updateElements(detectorContainer.childNodes, currentDetector); |
michael@0 | 789 | }, |
michael@0 | 790 | _updateElements: function(aElements, aCurrentItem) { |
michael@0 | 791 | if (!aElements.length) { |
michael@0 | 792 | return; |
michael@0 | 793 | } |
michael@0 | 794 | let disabled = this.maybeDisableMenu(aElements[0].ownerDocument); |
michael@0 | 795 | for (let elem of aElements) { |
michael@0 | 796 | if (disabled) { |
michael@0 | 797 | elem.setAttribute("disabled", "true"); |
michael@0 | 798 | } else { |
michael@0 | 799 | elem.removeAttribute("disabled"); |
michael@0 | 800 | } |
michael@0 | 801 | if (elem.value.toLowerCase() == aCurrentItem.toLowerCase()) { |
michael@0 | 802 | elem.setAttribute("checked", "true"); |
michael@0 | 803 | } else { |
michael@0 | 804 | elem.removeAttribute("checked"); |
michael@0 | 805 | } |
michael@0 | 806 | } |
michael@0 | 807 | }, |
michael@0 | 808 | onViewShowing: function(aEvent) { |
michael@0 | 809 | let document = aEvent.target.ownerDocument; |
michael@0 | 810 | |
michael@0 | 811 | let autoDetectLabelId = "PanelUI-characterEncodingView-autodetect-label"; |
michael@0 | 812 | let autoDetectLabel = document.getElementById(autoDetectLabelId); |
michael@0 | 813 | if (!autoDetectLabel.hasAttribute("value")) { |
michael@0 | 814 | let label = CharsetBundle.GetStringFromName("charsetMenuAutodet"); |
michael@0 | 815 | autoDetectLabel.setAttribute("value", label); |
michael@0 | 816 | this.populateList(document, |
michael@0 | 817 | "PanelUI-characterEncodingView-pinned", |
michael@0 | 818 | "pinnedCharsets"); |
michael@0 | 819 | this.populateList(document, |
michael@0 | 820 | "PanelUI-characterEncodingView-charsets", |
michael@0 | 821 | "otherCharsets"); |
michael@0 | 822 | this.populateList(document, |
michael@0 | 823 | "PanelUI-characterEncodingView-autodetect", |
michael@0 | 824 | "detectors"); |
michael@0 | 825 | } |
michael@0 | 826 | this.updateCurrentDetector(document); |
michael@0 | 827 | this.updateCurrentCharset(document); |
michael@0 | 828 | }, |
michael@0 | 829 | onCommand: function(aEvent) { |
michael@0 | 830 | let node = aEvent.target; |
michael@0 | 831 | if (!node.hasAttribute || !node.section) { |
michael@0 | 832 | return; |
michael@0 | 833 | } |
michael@0 | 834 | |
michael@0 | 835 | let window = node.ownerDocument.defaultView; |
michael@0 | 836 | let section = node.section; |
michael@0 | 837 | let value = node.value; |
michael@0 | 838 | |
michael@0 | 839 | // The behavior as implemented here is directly based off of the |
michael@0 | 840 | // `MultiplexHandler()` method in browser.js. |
michael@0 | 841 | if (section != "detectors") { |
michael@0 | 842 | window.BrowserSetForcedCharacterSet(value); |
michael@0 | 843 | } else { |
michael@0 | 844 | // Set the detector pref. |
michael@0 | 845 | try { |
michael@0 | 846 | let str = Cc["@mozilla.org/supports-string;1"] |
michael@0 | 847 | .createInstance(Ci.nsISupportsString); |
michael@0 | 848 | str.data = value; |
michael@0 | 849 | Services.prefs.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str); |
michael@0 | 850 | } catch (e) { |
michael@0 | 851 | Cu.reportError("Failed to set the intl.charset.detector preference."); |
michael@0 | 852 | } |
michael@0 | 853 | // Prepare a browser page reload with a changed charset. |
michael@0 | 854 | window.BrowserCharsetReload(); |
michael@0 | 855 | } |
michael@0 | 856 | }, |
michael@0 | 857 | onCreated: function(aNode) { |
michael@0 | 858 | const kPanelId = "PanelUI-popup"; |
michael@0 | 859 | let document = aNode.ownerDocument; |
michael@0 | 860 | |
michael@0 | 861 | let updateButton = () => { |
michael@0 | 862 | if (this.maybeDisableMenu(document)) |
michael@0 | 863 | aNode.setAttribute("disabled", "true"); |
michael@0 | 864 | else |
michael@0 | 865 | aNode.removeAttribute("disabled"); |
michael@0 | 866 | }; |
michael@0 | 867 | |
michael@0 | 868 | if (this.currentArea == CustomizableUI.AREA_PANEL) { |
michael@0 | 869 | let panel = document.getElementById(kPanelId); |
michael@0 | 870 | panel.addEventListener("popupshowing", updateButton); |
michael@0 | 871 | } |
michael@0 | 872 | |
michael@0 | 873 | let listener = { |
michael@0 | 874 | onWidgetAdded: (aWidgetId, aArea) => { |
michael@0 | 875 | if (aWidgetId != this.id) |
michael@0 | 876 | return; |
michael@0 | 877 | if (aArea == CustomizableUI.AREA_PANEL) { |
michael@0 | 878 | let panel = document.getElementById(kPanelId); |
michael@0 | 879 | panel.addEventListener("popupshowing", updateButton); |
michael@0 | 880 | } |
michael@0 | 881 | }, |
michael@0 | 882 | onWidgetRemoved: (aWidgetId, aPrevArea) => { |
michael@0 | 883 | if (aWidgetId != this.id) |
michael@0 | 884 | return; |
michael@0 | 885 | aNode.removeAttribute("disabled"); |
michael@0 | 886 | if (aPrevArea == CustomizableUI.AREA_PANEL) { |
michael@0 | 887 | let panel = document.getElementById(kPanelId); |
michael@0 | 888 | panel.removeEventListener("popupshowing", updateButton); |
michael@0 | 889 | } |
michael@0 | 890 | }, |
michael@0 | 891 | onWidgetInstanceRemoved: (aWidgetId, aDoc) => { |
michael@0 | 892 | if (aWidgetId != this.id || aDoc != document) |
michael@0 | 893 | return; |
michael@0 | 894 | |
michael@0 | 895 | CustomizableUI.removeListener(listener); |
michael@0 | 896 | let panel = aDoc.getElementById(kPanelId); |
michael@0 | 897 | panel.removeEventListener("popupshowing", updateButton); |
michael@0 | 898 | } |
michael@0 | 899 | }; |
michael@0 | 900 | CustomizableUI.addListener(listener); |
michael@0 | 901 | if (!this.charsetInfo) { |
michael@0 | 902 | this.charsetInfo = CharsetMenu.getData(); |
michael@0 | 903 | } |
michael@0 | 904 | } |
michael@0 | 905 | }, { |
michael@0 | 906 | id: "email-link-button", |
michael@0 | 907 | tooltiptext: "email-link-button.tooltiptext3", |
michael@0 | 908 | onCommand: function(aEvent) { |
michael@0 | 909 | let win = aEvent.view; |
michael@0 | 910 | win.MailIntegration.sendLinkForWindow(win.content); |
michael@0 | 911 | } |
michael@0 | 912 | }]; |
michael@0 | 913 | |
michael@0 | 914 | #ifdef XP_WIN |
michael@0 | 915 | #ifdef MOZ_METRO |
michael@0 | 916 | if (Services.metro && Services.metro.supported) { |
michael@0 | 917 | let widgetArgs = {tooltiptext: "switch-to-metro-button2.tooltiptext"}; |
michael@0 | 918 | let brandShortName = BrandBundle.GetStringFromName("brandShortName"); |
michael@0 | 919 | let metroTooltip = CustomizableUI.getLocalizedProperty(widgetArgs, "tooltiptext", |
michael@0 | 920 | [brandShortName]); |
michael@0 | 921 | CustomizableWidgets.push({ |
michael@0 | 922 | id: "switch-to-metro-button", |
michael@0 | 923 | label: "switch-to-metro-button2.label", |
michael@0 | 924 | tooltiptext: metroTooltip, |
michael@0 | 925 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 926 | showInPrivateBrowsing: false, /* See bug 928068 */ |
michael@0 | 927 | onCommand: function(aEvent) { |
michael@0 | 928 | let win = aEvent.view; |
michael@0 | 929 | if (win && typeof win.SwitchToMetro == "function") { |
michael@0 | 930 | win.SwitchToMetro(); |
michael@0 | 931 | } |
michael@0 | 932 | } |
michael@0 | 933 | }); |
michael@0 | 934 | } |
michael@0 | 935 | #endif |
michael@0 | 936 | #endif |
michael@0 | 937 | |
michael@0 | 938 | #ifdef NIGHTLY_BUILD |
michael@0 | 939 | /** |
michael@0 | 940 | * The e10s button's purpose is to lower the barrier of entry |
michael@0 | 941 | * for our Nightly testers to use e10s windows. We'll be removing it |
michael@0 | 942 | * once remote tabs are enabled. This button should never ever make it |
michael@0 | 943 | * to production. If it does, that'd be bad, and we should all feel bad. |
michael@0 | 944 | */ |
michael@0 | 945 | if (Services.prefs.getBoolPref("browser.tabs.remote")) { |
michael@0 | 946 | let getCommandFunction = function(aOpenRemote) { |
michael@0 | 947 | return function(aEvent) { |
michael@0 | 948 | let win = aEvent.view; |
michael@0 | 949 | if (win && typeof win.OpenBrowserWindow == "function") { |
michael@0 | 950 | win.OpenBrowserWindow({remote: aOpenRemote}); |
michael@0 | 951 | } |
michael@0 | 952 | }; |
michael@0 | 953 | } |
michael@0 | 954 | |
michael@0 | 955 | let openRemote = !Services.prefs.getBoolPref("browser.tabs.remote.autostart"); |
michael@0 | 956 | // Like the XUL menuitem counterparts, we hard-code these strings in because |
michael@0 | 957 | // this button should never roll into production. |
michael@0 | 958 | let buttonLabel = openRemote ? "New e10s Window" |
michael@0 | 959 | : "New Non-e10s Window"; |
michael@0 | 960 | |
michael@0 | 961 | CustomizableWidgets.push({ |
michael@0 | 962 | id: "e10s-button", |
michael@0 | 963 | label: buttonLabel, |
michael@0 | 964 | tooltiptext: buttonLabel, |
michael@0 | 965 | defaultArea: CustomizableUI.AREA_PANEL, |
michael@0 | 966 | onCommand: getCommandFunction(openRemote), |
michael@0 | 967 | }); |
michael@0 | 968 | } |
michael@0 | 969 | #endif |