/chrome/content/instantbird.js

https://code.google.com/p/vertical-tabs/ · JavaScript · 218 lines · 157 code · 29 blank · 32 comment · 39 complexity · 3ef283799f7130547d08d251d503db96 MD5 · raw file

  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. function dump(aMessage) {
  5. var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
  6. .getService(Components.interfaces.nsIConsoleService);
  7. consoleService.logStringMessage("Vertical Tabs: " + aMessage);
  8. }
  9. let verticalTabs = {
  10. startup: function() {
  11. let tabbrowser = getTabBrowser();
  12. tabbrowser._onDragStart = (function(aEvent) {
  13. var target = aEvent.target;
  14. if (target.localName == "tab" &&
  15. aEvent.originalTarget.localName != "toolbarbutton") {
  16. var dt = aEvent.dataTransfer;
  17. dt.mozSetDataAt(TAB_DROP_TYPE, target, 0);
  18. aEvent.stopPropagation();
  19. target._dragOffsetY =
  20. aEvent.screenY - window.screenY - target.getBoundingClientRect().top;
  21. target._dragOffsetX = aEvent.screenX - window.screenX;
  22. }
  23. this._dragLeftWindow = false;
  24. });
  25. tabbrowser._setEffectAllowedForDataTransfer = (function(aEvent) {
  26. var dt = aEvent.dataTransfer;
  27. // Disallow dropping multiple items
  28. if (dt.mozItemCount > 1)
  29. return dt.effectAllowed = "none";
  30. var types = dt.mozTypesAt(0);
  31. var sourceNode = null;
  32. // tabs are always added as the first type
  33. if (types[0] == TAB_DROP_TYPE) {
  34. var sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
  35. if (sourceNode instanceof XULElement &&
  36. sourceNode.localName == "tab" &&
  37. (sourceNode.parentNode == this.mTabContainer ||
  38. (sourceNode.ownerDocument.defaultView instanceof ChromeWindow &&
  39. sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "Messenger:convs"))) {
  40. if (sourceNode.parentNode == this.mTabContainer &&
  41. (aEvent.screenY >= sourceNode.boxObject.screenY &&
  42. aEvent.screenY <= (sourceNode.boxObject.screenY +
  43. sourceNode.boxObject.height))) {
  44. return dt.effectAllowed = "none";
  45. }
  46. return dt.effectAllowed = "copyMove";
  47. }
  48. }
  49. return dt.effectAllowed = "none";
  50. });
  51. tabbrowser._onDragOver = (function(aEvent) {
  52. var effects = this._setEffectAllowedForDataTransfer(aEvent);
  53. var ib = this.mTabDropIndicatorBar;
  54. if (effects == "" || effects == "none") {
  55. ib.collapsed = "true";
  56. return;
  57. }
  58. aEvent.preventDefault();
  59. aEvent.stopPropagation();
  60. var tabStrip = this.mTabContainer.mTabstrip;
  61. // autoscroll the tab strip if we drag over the scroll
  62. // buttons, even if we aren't dragging a tab, but then
  63. // return to avoid drawing the drop indicator
  64. var pixelsToScroll = 0;
  65. if (this.mTabContainer.getAttribute("overflow") == "true") {
  66. var targetAnonid = aEvent.originalTarget.getAttribute("anonid");
  67. switch (targetAnonid) {
  68. case "scrollbutton-up":
  69. pixelsToScroll = tabStrip.scrollIncrement * -1;
  70. break;
  71. case "scrollbutton-down":
  72. case "alltabs-button":
  73. case "newtab-button":
  74. pixelsToScroll = tabStrip.scrollIncrement;
  75. break;
  76. }
  77. if (pixelsToScroll)
  78. tabStrip.scrollByPixels(pixelsToScroll);
  79. }
  80. var newIndex = this.getNewIndex(aEvent);
  81. var ib = this.mTabDropIndicatorBar;
  82. var ind = ib.firstChild;
  83. var tabStripBoxObject = tabStrip.scrollBoxObject;
  84. var minMargin = tabStripBoxObject.y - this.boxObject.y;
  85. // make sure we don't place the tab drop indicator past the
  86. // edge, or the containing box will flex and stretch
  87. // the tab drop indicator bar, which will flex the url bar.
  88. // XXX todo
  89. // just use first value if you can figure out how to get
  90. // the tab drop indicator to crop instead of flex and stretch
  91. // the tab drop indicator bar.
  92. var maxMargin = Math.max(minMargin + tabStripBoxObject.height,
  93. ib.boxObject.y + ib.boxObject.height -
  94. ind.boxObject.height);
  95. var newMargin, tabBoxObject;
  96. if (pixelsToScroll) {
  97. // if we are scrolling, put the drop indicator at the edge
  98. // so that it doesn't jump while scrolling
  99. newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin;
  100. }
  101. else {
  102. if (newIndex == this.mTabs.length) {
  103. tabBoxObject = this.mTabs[newIndex-1].boxObject;
  104. newMargin = tabBoxObject.screenY - this.boxObject.screenY
  105. + tabBoxObject.height;
  106. }
  107. else {
  108. tabBoxObject = this.mTabs[newIndex].boxObject;
  109. newMargin = tabBoxObject.screenY - this.boxObject.screenY;
  110. }
  111. // ensure we never place the drop indicator beyond our limits
  112. if (newMargin < minMargin)
  113. newMargin = minMargin;
  114. else if (newMargin > maxMargin)
  115. newMargin = maxMargin;
  116. }
  117. ind.style.marginTop = newMargin + 'px';
  118. ib.collapsed = false;
  119. });
  120. tabbrowser._onDragEnd = (function(aEvent) {
  121. // Note: while this case is correctly handled here, this event
  122. // isn't dispatched when the tab is moved within the tabstrip,
  123. // see bug 460801.
  124. // Collapse the drop indicator, just to be sure...
  125. this.mTabDropIndicatorBar.collapsed = true;
  126. // * mozUserCancelled = the user pressed ESC to cancel the drag
  127. var dt = aEvent.dataTransfer;
  128. if (dt.mozUserCancelled || dt.dropEffect != "none")
  129. return;
  130. // Disable detach within the browser toolbox
  131. var eX = aEvent.screenX;
  132. var wY = window.screenY;
  133. var eY = aEvent.screenY;
  134. // check if the drop point is horizontally within the window
  135. if (eY > wY && eY < (wY + window.outerHeight)) {
  136. var bo = this.mTabContainer.mTabstrip.boxObject;
  137. // also avoid detaching if the the tab was dropped too close to
  138. // the tabbar (half a tab)
  139. var endScreenX = bo.screenX + 1.5 * bo.width;
  140. if (eX < endScreenX && eX > window.screenX)
  141. return;
  142. }
  143. var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
  144. let win = this.replaceTabsWithWindow([draggedTab]);
  145. if (win) {
  146. win.moveTo(eX - draggedTab._dragOffsetX,
  147. eY - draggedTab._dragOffsetY);
  148. }
  149. aEvent.stopPropagation();
  150. });
  151. tabbrowser.getNewIndex = (function(aEvent) {
  152. var i;
  153. for (i = aEvent.target.localName == "tab" ? aEvent.target._tPos : 0; i < this.mTabs.length; i++)
  154. if (aEvent.screenY < this.mTabs[i].boxObject.screenY + this.mTabs[i].boxObject.height / 2)
  155. return i;
  156. return this.mTabs.length;
  157. });
  158. let document = tabbrowser.ownerDocument;
  159. let tabbox = tabbrowser.mTabBox;
  160. //tabbox.orient = "horizontal"; // Set in CSS
  161. let tabstrip = tabbrowser.mStrip;
  162. tabstrip.orient = "vertical";
  163. // Swap the tab container and the tab drop indicator bar
  164. tabbox.insertBefore(tabstrip, tabbrowser.mTabDropIndicatorBar);
  165. let tabcontainer = tabbrowser.mTabContainer;
  166. tabcontainer.orient = "vertical";
  167. //tabcontainer.align = "stretch"; // Set in CSS
  168. let tabscontainer = document.getAnonymousNodes(tabcontainer)[0];
  169. tabscontainer.orient = "horizontal";
  170. let arrowscrollbox = tabcontainer.mTabstrip;
  171. arrowscrollbox.orient = "vertical";
  172. let scrollbox = document.getAnonymousElementByAttribute(arrowscrollbox,
  173. "anonid",
  174. "scrollbox");
  175. scrollbox.orient = "vertical";
  176. // Add a buffer to collapse the tab heights
  177. let tabspacer = document.createElement("spacer");
  178. tabspacer.setAttribute("flex", "100000");
  179. scrollbox.appendChild(tabspacer);
  180. // Add a splitter
  181. let tabssplitter = document.createElement("splitter");
  182. tabssplitter.className = "tabs-splitter";
  183. tabssplitter.setAttribute("collapse", "before");
  184. tabssplitter.setAttribute("resizebefore", "closest");
  185. tabssplitter.appendChild(document.createElement("grippy"));
  186. tabbox.insertBefore(tabssplitter, tabbrowser.mTabDropIndicatorBar);
  187. }
  188. }
  189. window.addEventListener("load", function(e) {verticalTabs.startup();}, false);