2009-04-06 23:05:49 -04:00
|
|
|
/*
|
|
|
|
Tab Bar AutoScroll Library for Vertical and Horizontal Tab Bar
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
var scrolled = window['piro.sakura.ne.jp']
|
|
|
|
.autoScroll
|
|
|
|
.processAutoScroll(mouseMoveOrDragOverEvent);
|
|
|
|
|
2012-10-13 14:31:06 -04:00
|
|
|
license: The MIT License, Copyright (c) 2009-2012 YUKI "Piro" Hiroshi
|
2011-01-21 10:01:19 -05:00
|
|
|
http://github.com/piroor/fxaddonlibs/blob/master/license.txt
|
2009-04-06 23:05:49 -04:00
|
|
|
original:
|
2011-01-21 10:01:19 -05:00
|
|
|
http://github.com/piroor/fxaddonlibs/blob/master/autoScroll.js
|
2009-04-06 23:05:49 -04:00
|
|
|
*/
|
2010-06-22 19:46:51 -04:00
|
|
|
|
2010-08-26 11:40:13 -04:00
|
|
|
/* To work as a JS Code Module */
|
2010-08-27 05:58:57 -04:00
|
|
|
if (typeof window == 'undefined' ||
|
|
|
|
(window && typeof window.constructor == 'function')) {
|
2010-06-22 21:32:31 -04:00
|
|
|
this.EXPORTED_SYMBOLS = ['autoScroll'];
|
2010-06-22 19:46:51 -04:00
|
|
|
|
2010-06-26 11:13:11 -04:00
|
|
|
// If namespace.jsm is available, export symbols to the shared namespace.
|
2011-01-21 10:01:19 -05:00
|
|
|
// See: http://github.com/piroor/fxaddonlibs/blob/master/namespace.jsm
|
2010-06-26 11:13:11 -04:00
|
|
|
try {
|
|
|
|
let ns = {};
|
2010-12-06 07:04:52 -05:00
|
|
|
Components.utils.import('resource://treestyletab-modules/lib/namespace.jsm', ns);
|
2010-06-26 11:13:11 -04:00
|
|
|
/* var */ window = ns.getNamespaceFor('piro.sakura.ne.jp');
|
|
|
|
}
|
|
|
|
catch(e) {
|
|
|
|
window = {};
|
|
|
|
}
|
2010-06-22 19:46:51 -04:00
|
|
|
}
|
|
|
|
|
2009-04-06 23:05:49 -04:00
|
|
|
(function() {
|
2012-01-31 01:06:32 -05:00
|
|
|
const currentRevision = 6;
|
2009-04-06 23:05:49 -04:00
|
|
|
|
|
|
|
if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {};
|
|
|
|
|
|
|
|
var loadedRevision = 'autoScroll' in window['piro.sakura.ne.jp'] ?
|
|
|
|
window['piro.sakura.ne.jp'].autoScroll.revision :
|
|
|
|
0 ;
|
|
|
|
if (loadedRevision && loadedRevision > currentRevision) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-06-22 14:00:16 -04:00
|
|
|
const Cc = Components.classes;
|
|
|
|
const Ci = Components.interfaces;
|
2009-04-06 23:05:49 -04:00
|
|
|
|
|
|
|
window['piro.sakura.ne.jp'].autoScroll = {
|
|
|
|
revision : currentRevision,
|
|
|
|
|
|
|
|
processAutoScroll : function(aEvent)
|
|
|
|
{
|
|
|
|
var target = aEvent.originalTarget;
|
2010-06-23 08:00:33 -04:00
|
|
|
var b = this.getTabBrowserFromChild(target);
|
2009-04-06 23:05:49 -04:00
|
|
|
if (!b) return false;
|
|
|
|
|
|
|
|
var tabs = b.mTabContainer;
|
|
|
|
if (tabs.getAttribute('overflow') != 'true')
|
|
|
|
return false;
|
|
|
|
|
2010-06-22 14:00:16 -04:00
|
|
|
var view = target.ownerDocument.defaultView;
|
|
|
|
|
2009-04-06 23:05:49 -04:00
|
|
|
var box = this.getScrollBox(b);
|
|
|
|
var boxObject = this.getScrollBoxObject(b);
|
|
|
|
var innerBoxObject = (box.localName == 'arrowscrollbox' ? box._scrollbox : box ).boxObject;
|
|
|
|
|
|
|
|
var orientBox = box || tabs;
|
2010-01-13 14:03:24 -05:00
|
|
|
var isMultirow = tabs.getAttribute('flowing') == 'multibar'; // Tab Mix Plus
|
2009-07-16 06:28:27 -04:00
|
|
|
var isVertical = (
|
|
|
|
isMultirow ||
|
2010-06-22 14:00:16 -04:00
|
|
|
((orientBox.getAttribute('orient') || view.getComputedStyle(orientBox, '').getPropertyValue('-moz-box-orient')) == 'vertical')
|
2009-07-16 06:28:27 -04:00
|
|
|
);
|
2009-04-06 23:05:49 -04:00
|
|
|
|
|
|
|
var maxX = {}, maxY = {}, curX = {}, curY = {};
|
|
|
|
boxObject.getScrolledSize(maxX, maxY);
|
|
|
|
boxObject.getPosition(curX, curY);
|
|
|
|
|
2012-01-31 01:06:32 -05:00
|
|
|
var firstTab;
|
|
|
|
if (b.visibleTabs) {
|
|
|
|
let pinnedTabsCount = b.ownerDocument.evaluate(
|
|
|
|
'count(child::*[local-name()="tab" and @pinned="true"])',
|
|
|
|
tabs,
|
|
|
|
null,
|
|
|
|
Ci.nsIDOMXPathResult.NUMBER_TYPE,
|
|
|
|
null
|
|
|
|
).numberValue;
|
|
|
|
firstTab = b.visibleTabs[b.visibleTabs.length > pinnedTabsCount ? pinnedTabsCount : 0 ];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
firstTab = tabs.childNodes[0];
|
|
|
|
}
|
|
|
|
|
2009-04-06 23:05:49 -04:00
|
|
|
var pixels;
|
|
|
|
if (isVertical) {
|
2012-01-31 01:06:32 -05:00
|
|
|
pixels = firstTab.boxObject.height * 0.5;
|
2009-07-16 06:28:27 -04:00
|
|
|
if (isMultirow) pixels *= 0.5;
|
2009-04-06 23:05:49 -04:00
|
|
|
if (aEvent.screenY < boxObject.screenY + this.getUpButtonHeight(b)) {
|
|
|
|
if (curY.value == 0) return false;
|
|
|
|
pixels *= -1;
|
|
|
|
}
|
|
|
|
else if (aEvent.screenY > boxObject.screenY + boxObject.height - this.getDownButtonHeight(b)) {
|
|
|
|
if (innerBoxObject.height + curY.value == maxY.value) return false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pixels = box.scrollIncrement;
|
2010-06-22 14:00:16 -04:00
|
|
|
var ltr = view.getComputedStyle(tabs, null).direction == 'ltr';
|
2009-04-06 23:05:49 -04:00
|
|
|
if (aEvent.screenX < boxObject.screenX + this.getUpButtonWidth(b)) {
|
|
|
|
if (curX.value == 0) return false;
|
|
|
|
pixels *= -1;
|
|
|
|
}
|
|
|
|
else if (aEvent.screenX > boxObject.screenX + boxObject.width - this.getDownButtonWidth(b)) {
|
|
|
|
if (innerBoxObject.width + curX.value == maxX.value) return false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
pixels = (ltr ? 1 : -1) * pixels;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ('scrollByPixels' in box) {
|
|
|
|
box.scrollByPixels(pixels);
|
|
|
|
}
|
|
|
|
else { // Tab Mix Plus?
|
|
|
|
if (isVertical)
|
|
|
|
boxObject.scrollBy(0, pixels);
|
|
|
|
else
|
|
|
|
boxObject.scrollBy(pixels, 0);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
},
|
2010-06-23 08:00:33 -04:00
|
|
|
|
|
|
|
getTabBrowserFromChild : function(aTabBrowserChild)
|
|
|
|
{
|
|
|
|
if (aTabBrowserChild.localName == 'tabbrowser') // itself
|
|
|
|
return aTabBrowserChild;
|
|
|
|
|
2011-01-21 10:01:19 -05:00
|
|
|
if (aTabBrowserChild.tabbrowser) // tabs, Firefox 4.0 or later
|
2010-06-23 08:00:33 -04:00
|
|
|
return aTabBrowserChild.tabbrowser;
|
|
|
|
|
2011-01-21 10:01:19 -05:00
|
|
|
if (aTabBrowserChild.localName == 'toolbar') // tabs toolbar, Firefox 4.0 or later
|
2010-06-23 08:00:33 -04:00
|
|
|
return aTabBrowserChild.getElementsByTagName('tabs')[0].tabbrowser;
|
|
|
|
|
|
|
|
var b = aTabBrowserChild.ownerDocument.evaluate(
|
|
|
|
'ancestor::*[local-name()="tabbrowser"] | '+
|
|
|
|
'ancestor::*[local-name()="tabs" and @tabbrowser] |'+
|
2011-01-21 10:01:19 -05:00
|
|
|
'ancestor::*[local-name()="toolbar"]/descendant::*[local-name()="tabs"]',
|
2010-06-23 08:00:33 -04:00
|
|
|
aTabBrowserChild,
|
|
|
|
null,
|
|
|
|
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE,
|
|
|
|
null
|
|
|
|
).singleNodeValue;
|
|
|
|
return (b && b.tabbrowser) || b;
|
|
|
|
},
|
2009-04-06 23:05:49 -04:00
|
|
|
|
|
|
|
getScrollBox : function(aTabBrowser)
|
|
|
|
{
|
2010-06-22 14:00:16 -04:00
|
|
|
return aTabBrowser.ownerDocument.getAnonymousElementByAttribute(aTabBrowser.mTabContainer, 'class', 'tabs-frame') || // Tab Mix Plus
|
2010-01-13 14:03:24 -05:00
|
|
|
aTabBrowser.mTabContainer.mTabstrip;
|
2009-04-06 23:05:49 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
getScrollBoxObject : function(aTabBrowser)
|
|
|
|
{
|
|
|
|
var box = this.getScrollBox(aTabBrowser);
|
2014-10-21 21:23:17 -04:00
|
|
|
var boxObject = (box.scrollBoxObject || box.boxObject);
|
|
|
|
try {
|
|
|
|
boxObject = boxObject.QueryInterface(Ci.nsIScrollBoxObject); // for Tab Mix Plus (ensure scrollbox-ed)
|
|
|
|
} catch (ex) { /* May not implement this interface e.g. after bug 979835 */ }
|
|
|
|
return boxObject;
|
2009-04-06 23:05:49 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
getUpButton : function(aTabBrowser)
|
|
|
|
{
|
|
|
|
var box = this.getScrollBox(aTabBrowser);
|
|
|
|
return box._scrollButtonUp ||
|
2010-06-22 14:00:16 -04:00
|
|
|
aTabBrowser.ownerDocument.getAnonymousElementByAttribute(box, 'class', 'scrollbutton-up') ||
|
|
|
|
aTabBrowser.ownerDocument.getAnonymousElementByAttribute(box.previousSibling, 'class', 'scrollbutton-up'); // Tab Mix Plus
|
2009-04-06 23:05:49 -04:00
|
|
|
},
|
|
|
|
getDownButton : function(aTabBrowser)
|
|
|
|
{
|
|
|
|
var box = this.getScrollBox(aTabBrowser);
|
|
|
|
return box._scrollButtonDown ||
|
2010-06-22 14:00:16 -04:00
|
|
|
aTabBrowser.ownerDocument.getAnonymousElementByAttribute(box, 'class', 'scrollbutton-down') ||
|
|
|
|
aTabBrowser.ownerDocument.getAnonymousElementByAttribute(box.nextSibling, 'class', 'scrollbutton-up'); // Tab Mix Plus
|
2009-04-06 23:05:49 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
autoScrollArea : 20,
|
|
|
|
|
|
|
|
getUpButtonHeight : function(aTabBrowser)
|
|
|
|
{
|
|
|
|
var button = this.getUpButton(aTabBrowser);
|
|
|
|
return (button ? button.boxObject.height : 0 ) || this.autoScrollArea;
|
|
|
|
},
|
|
|
|
getUpButtonWidth : function(aTabBrowser)
|
|
|
|
{
|
|
|
|
var button = this.getUpButton(aTabBrowser);
|
|
|
|
return (button ? button.boxObject.width : 0 ) || this.autoScrollArea;
|
|
|
|
},
|
|
|
|
|
|
|
|
getDownButtonHeight : function(aTabBrowser)
|
|
|
|
{
|
|
|
|
var button = this.getDownButton(aTabBrowser);
|
|
|
|
return (button ? button.boxObject.height : 0 ) || this.autoScrollArea;
|
|
|
|
},
|
|
|
|
getDownButtonWidth : function(aTabBrowser)
|
|
|
|
{
|
|
|
|
var button = this.getDownButton(aTabBrowser);
|
|
|
|
return (button ? button.boxObject.width : 0 ) || this.autoScrollArea;
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
})();
|
2010-06-22 19:46:51 -04:00
|
|
|
|
|
|
|
if (window != this) { // work as a JS Code Module
|
2010-06-22 21:32:31 -04:00
|
|
|
this.autoScroll = window['piro.sakura.ne.jp'].autoScroll;
|
2010-06-22 19:46:51 -04:00
|
|
|
}
|