view.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. 'use strict';
  5. module.metadata = {
  6. 'stability': 'unstable',
  7. 'engines': {
  8. 'Firefox': '*'
  9. }
  10. };
  11. const { models, buttons, views, viewsFor, modelFor } = require('./namespace');
  12. const { isBrowser, getMostRecentBrowserWindow, windows, isWindowPrivate } = require('../../window/utils');
  13. const { setStateFor } = require('../state');
  14. const { defer } = require('../../core/promise');
  15. const { isPrivateBrowsingSupported } = require('../../self');
  16. const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  17. const WEB_PANEL_BROWSER_ID = 'web-panels-browser';
  18. function create(window, details) {
  19. let id = makeID(details.id);
  20. let { document } = window;
  21. if (document.getElementById(id))
  22. throw new Error('The ID "' + details.id + '" seems already used.');
  23. let menuitem = document.createElementNS(XUL_NS, 'menuitem');
  24. menuitem.setAttribute('id', id);
  25. menuitem.setAttribute('label', details.title);
  26. menuitem.setAttribute('sidebarurl', details.sidebarurl);
  27. menuitem.setAttribute('checked', 'false');
  28. menuitem.setAttribute('type', 'checkbox');
  29. menuitem.setAttribute('group', 'sidebar');
  30. menuitem.setAttribute('autoCheck', 'false');
  31. document.getElementById('viewSidebarMenu').appendChild(menuitem);
  32. return menuitem;
  33. }
  34. exports.create = create;
  35. function dispose(menuitem) {
  36. menuitem.parentNode.removeChild(menuitem);
  37. }
  38. exports.dispose = dispose;
  39. function updateTitle(sidebar, title) {
  40. let button = buttons.get(sidebar);
  41. for (let window of windows(null, { includePrivate: true })) {
  42. let { document } = window;
  43. // update the button
  44. if (button) {
  45. setStateFor(button, window, { label: title });
  46. }
  47. // update the menuitem
  48. let mi = document.getElementById(makeID(sidebar.id));
  49. if (mi) {
  50. mi.setAttribute('label', title)
  51. }
  52. // update sidebar, if showing
  53. if (isSidebarShowing(window, sidebar)) {
  54. document.getElementById('sidebar-title').setAttribute('value', title);
  55. }
  56. }
  57. }
  58. exports.updateTitle = updateTitle;
  59. function updateURL(sidebar, url) {
  60. let eleID = makeID(sidebar.id);
  61. for (let window of windows(null, { includePrivate: true })) {
  62. // update the menuitem
  63. let mi = window.document.getElementById(eleID);
  64. if (mi) {
  65. mi.setAttribute('sidebarurl', url)
  66. }
  67. // update sidebar, if showing
  68. if (isSidebarShowing(window, sidebar)) {
  69. showSidebar(window, sidebar, url);
  70. }
  71. }
  72. }
  73. exports.updateURL = updateURL;
  74. function isSidebarShowing(window, sidebar) {
  75. let win = window || getMostRecentBrowserWindow();
  76. // make sure there is a window
  77. if (!win) {
  78. return false;
  79. }
  80. // make sure there is a sidebar for the window
  81. let sb = win.document.getElementById('sidebar');
  82. let sidebarTitle = win.document.getElementById('sidebar-title');
  83. if (!(sb && sidebarTitle)) {
  84. return false;
  85. }
  86. // checks if the sidebar box is hidden
  87. let sbb = win.document.getElementById('sidebar-box');
  88. if (!sbb || sbb.hidden) {
  89. return false;
  90. }
  91. if (sidebarTitle.value == modelFor(sidebar).title) {
  92. // checks if the sidebar is loading
  93. if (win.gWebPanelURI == modelFor(sidebar).url) {
  94. return true;
  95. }
  96. // checks if the sidebar loaded already
  97. let ele = sb.contentDocument && sb.contentDocument.getElementById(WEB_PANEL_BROWSER_ID);
  98. if (!ele) {
  99. return false;
  100. }
  101. if (ele.getAttribute('cachedurl') == modelFor(sidebar).url) {
  102. return true;
  103. }
  104. if (ele && ele.contentWindow && ele.contentWindow.location == modelFor(sidebar).url) {
  105. return true;
  106. }
  107. }
  108. // default
  109. return false;
  110. }
  111. exports.isSidebarShowing = isSidebarShowing;
  112. function showSidebar(window, sidebar, newURL) {
  113. window = window || getMostRecentBrowserWindow();
  114. let { promise, resolve, reject } = defer();
  115. let model = modelFor(sidebar);
  116. if (!newURL && isSidebarShowing(window, sidebar)) {
  117. resolve({});
  118. }
  119. else if (!isPrivateBrowsingSupported && isWindowPrivate(window)) {
  120. reject(Error('You cannot show a sidebar on private windows'));
  121. }
  122. else {
  123. sidebar.once('show', resolve);
  124. let menuitem = window.document.getElementById(makeID(model.id));
  125. menuitem.setAttribute('checked', true);
  126. window.openWebPanel(model.title, newURL || model.url);
  127. }
  128. return promise;
  129. }
  130. exports.showSidebar = showSidebar;
  131. function hideSidebar(window, sidebar) {
  132. window = window || getMostRecentBrowserWindow();
  133. let { promise, resolve, reject } = defer();
  134. if (!isSidebarShowing(window, sidebar)) {
  135. reject(Error('The sidebar is already hidden'));
  136. }
  137. else {
  138. sidebar.once('hide', resolve);
  139. // Below was taken from http://mxr.mozilla.org/mozilla-central/source/browser/base/content/browser.js#4775
  140. // the code for window.todggleSideBar()..
  141. let { document } = window;
  142. let sidebarEle = document.getElementById('sidebar');
  143. let sidebarTitle = document.getElementById('sidebar-title');
  144. let sidebarBox = document.getElementById('sidebar-box');
  145. let sidebarSplitter = document.getElementById('sidebar-splitter');
  146. let commandID = sidebarBox.getAttribute('sidebarcommand');
  147. let sidebarBroadcaster = document.getElementById(commandID);
  148. sidebarBox.hidden = true;
  149. sidebarSplitter.hidden = true;
  150. sidebarEle.setAttribute('src', 'about:blank');
  151. //sidebarEle.docShell.createAboutBlankContentViewer(null);
  152. sidebarBroadcaster.removeAttribute('checked');
  153. sidebarBox.setAttribute('sidebarcommand', '');
  154. sidebarTitle.value = '';
  155. sidebarBox.hidden = true;
  156. sidebarSplitter.hidden = true;
  157. // TODO: perhaps this isn't necessary if the window is not most recent?
  158. window.gBrowser.selectedBrowser.focus();
  159. }
  160. return promise;
  161. }
  162. exports.hideSidebar = hideSidebar;
  163. function makeID(id) {
  164. return 'jetpack-sidebar-' + id;
  165. }