treestyletab/modules/lib/autoScroll.js
2010-12-06 21:04:52 +09:00

202 lines
6.5 KiB
JavaScript

/*
Tab Bar AutoScroll Library for Vertical and Horizontal Tab Bar
Usage:
var scrolled = window['piro.sakura.ne.jp']
.autoScroll
.processAutoScroll(mouseMoveOrDragOverEvent);
license: The MIT License, Copyright (c) 2009-2010 SHIMODA "Piro" Hiroshi
http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/license.txt
original:
http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/autoScroll.js
*/
/* To work as a JS Code Module */
if (typeof window == 'undefined' ||
(window && typeof window.constructor == 'function')) {
this.EXPORTED_SYMBOLS = ['autoScroll'];
// If namespace.jsm is available, export symbols to the shared namespace.
// See: http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/namespace.jsm
try {
let ns = {};
Components.utils.import('resource://treestyletab-modules/lib/namespace.jsm', ns);
/* var */ window = ns.getNamespaceFor('piro.sakura.ne.jp');
}
catch(e) {
window = {};
}
}
(function() {
const currentRevision = 4;
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;
}
const Cc = Components.classes;
const Ci = Components.interfaces;
window['piro.sakura.ne.jp'].autoScroll = {
revision : currentRevision,
processAutoScroll : function(aEvent)
{
var target = aEvent.originalTarget;
var b = this.getTabBrowserFromChild(target);
if (!b) return false;
var tabs = b.mTabContainer;
if (tabs.getAttribute('overflow') != 'true')
return false;
var view = target.ownerDocument.defaultView;
var box = this.getScrollBox(b);
var boxObject = this.getScrollBoxObject(b);
var innerBoxObject = (box.localName == 'arrowscrollbox' ? box._scrollbox : box ).boxObject;
var orientBox = box || tabs;
var isMultirow = tabs.getAttribute('flowing') == 'multibar'; // Tab Mix Plus
var isVertical = (
isMultirow ||
((orientBox.getAttribute('orient') || view.getComputedStyle(orientBox, '').getPropertyValue('-moz-box-orient')) == 'vertical')
);
var maxX = {}, maxY = {}, curX = {}, curY = {};
boxObject.getScrolledSize(maxX, maxY);
boxObject.getPosition(curX, curY);
var pixels;
if (isVertical) {
pixels = tabs.childNodes[0].boxObject.height * 0.5;
if (isMultirow) pixels *= 0.5;
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;
var ltr = view.getComputedStyle(tabs, null).direction == 'ltr';
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;
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;
},
getTabBrowserFromChild : function(aTabBrowserChild)
{
if (aTabBrowserChild.localName == 'tabbrowser') // itself
return aTabBrowserChild;
if (aTabBrowserChild.tabbrowser) // tabs, Firefox 3.7 or later
return aTabBrowserChild.tabbrowser;
if (aTabBrowserChild.id == 'TabsToolbar') // tabs toolbar, Firefox 3.7 or later
return aTabBrowserChild.getElementsByTagName('tabs')[0].tabbrowser;
var b = aTabBrowserChild.ownerDocument.evaluate(
'ancestor::*[local-name()="tabbrowser"] | '+
'ancestor::*[local-name()="tabs" and @tabbrowser] |'+
'ancestor::*[local-name()="toolbar" and @id="TabsToolbar"]/descendant::*[local-name()="tabs"]',
aTabBrowserChild,
null,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE,
null
).singleNodeValue;
return (b && b.tabbrowser) || b;
},
getScrollBox : function(aTabBrowser)
{
return aTabBrowser.ownerDocument.getAnonymousElementByAttribute(aTabBrowser.mTabContainer, 'class', 'tabs-frame') || // Tab Mix Plus
aTabBrowser.mTabContainer.mTabstrip;
},
getScrollBoxObject : function(aTabBrowser)
{
var box = this.getScrollBox(aTabBrowser);
return (box.scrollBoxObject || box.boxObject)
.QueryInterface(Ci.nsIScrollBoxObject); // Tab Mix Plus
},
getUpButton : function(aTabBrowser)
{
var box = this.getScrollBox(aTabBrowser);
return box._scrollButtonUp ||
aTabBrowser.ownerDocument.getAnonymousElementByAttribute(box, 'class', 'scrollbutton-up') ||
aTabBrowser.ownerDocument.getAnonymousElementByAttribute(box.previousSibling, 'class', 'scrollbutton-up'); // Tab Mix Plus
},
getDownButton : function(aTabBrowser)
{
var box = this.getScrollBox(aTabBrowser);
return box._scrollButtonDown ||
aTabBrowser.ownerDocument.getAnonymousElementByAttribute(box, 'class', 'scrollbutton-down') ||
aTabBrowser.ownerDocument.getAnonymousElementByAttribute(box.nextSibling, 'class', 'scrollbutton-up'); // Tab Mix Plus
},
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;
}
};
})();
if (window != this) { // work as a JS Code Module
this.autoScroll = window['piro.sakura.ne.jp'].autoScroll;
}