PageRenderTime 70ms CodeModel.GetById 55ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 0ms

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