refactor drag and drop implementations
This commit is contained in:
parent
fad08b3d1f
commit
19926994d7
@ -13,7 +13,7 @@
|
||||
http://github.com/piroor/fxaddonlibs/blob/master/tabsDragUtils.js
|
||||
*/
|
||||
(function() {
|
||||
const currentRevision = 1;
|
||||
const currentRevision = 2;
|
||||
|
||||
if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {};
|
||||
|
||||
@ -160,7 +160,7 @@
|
||||
return false;
|
||||
for (let i = 0, maxi = dt.mozItemCount; i < maxi; i++)
|
||||
{
|
||||
if (Array.slice(dt.mozTypesAt(i)).indexOf(TAB_DROP_TYPE) < 0)
|
||||
if (!dt.mozTypesAt(i).contains(TAB_DROP_TYPE))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -171,7 +171,7 @@
|
||||
var dt = aEvent.dataTransfer;
|
||||
var tabs = [];
|
||||
if (dt.mozItemCount < 1 ||
|
||||
Array.slice(dt.mozTypesAt(0)).indexOf(TAB_DROP_TYPE) < 0)
|
||||
!dt.mozTypesAt(0).contains(TAB_DROP_TYPE))
|
||||
return tabs;
|
||||
|
||||
for (let i = 0, maxi = dt.mozItemCount; i < maxi; i++)
|
||||
|
@ -386,14 +386,8 @@ var TreeStyleTabService = {
|
||||
if (aObserver.tabContainer &&
|
||||
aObserver.tabContainer.tabbrowser == aObserver) { // Firefox 4.0 or later
|
||||
aObserver = aObserver.tabContainer;
|
||||
strip.addEventListener('drop', this, true);
|
||||
strip.addEventListener('dragend', this, true);
|
||||
}
|
||||
|
||||
strip.addEventListener('dragstart', this, true);
|
||||
strip.addEventListener('dragover', this, true);
|
||||
strip.addEventListener('dragleave', this, true);
|
||||
|
||||
if ('_setEffectAllowedForDataTransfer' in aObserver) {
|
||||
eval('aObserver._setEffectAllowedForDataTransfer = '+
|
||||
aObserver._setEffectAllowedForDataTransfer.toSource().replace(
|
||||
@ -406,7 +400,7 @@ var TreeStyleTabService = {
|
||||
).replace(
|
||||
/(return (?:true|dt.effectAllowed = "copyMove");)/,
|
||||
<![CDATA[
|
||||
if (!this.treeStyleTab.checkCanTabDrop(arguments[0], this)) {
|
||||
if (!this.treeStyleTab.tabbarDNDObserver.canDropTab(arguments[0])) {
|
||||
return dt.effectAllowed = "none";
|
||||
}
|
||||
$1
|
||||
@ -417,475 +411,8 @@ var TreeStyleTabService = {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ('_onDrop' in aObserver) { // Firefox 3.5 - 3.6
|
||||
eval('aObserver._onDrop = '+
|
||||
aObserver._onDrop.toSource().replace(
|
||||
'{',
|
||||
<![CDATA[
|
||||
{
|
||||
var TSTTabBrowser = this;
|
||||
TSTTabBrowser.treeStyleTab.clearDropPosition();
|
||||
var dropActionInfo = TSTTabBrowser.treeStyleTab.getDropAction(aEvent, TSTTabBrowser.treeStyleTab.getCurrentDragSession());
|
||||
]]>
|
||||
).replace(
|
||||
/(if \((accelKeyPressed|isCopy|dropEffect == "copy")\) {)/,
|
||||
<![CDATA[
|
||||
if (TSTTabBrowser.treeStyleTab.performDrop(dropActionInfo, draggedTab))
|
||||
return;
|
||||
$1]]>
|
||||
).replace( // duplication of tab
|
||||
/(this.selectedTab = newTab;)(\s*\})?/g,
|
||||
<![CDATA[$1;
|
||||
if (dropActionInfo.position == TreeStyleTabService.kDROP_ON)
|
||||
TSTTabBrowser.treeStyleTab.attachTabTo(newTab, dropActionInfo.target);
|
||||
$2]]>
|
||||
).replace( // dragging tab from another window
|
||||
'else if (draggedTab) {',
|
||||
<![CDATA[$&
|
||||
if (TSTTabBrowser.treeStyleTab.performDrop(dropActionInfo, draggedTab))
|
||||
return;
|
||||
]]>
|
||||
).replace(
|
||||
/(this.loadOneTab\([^;]+\));/,
|
||||
<![CDATA[
|
||||
TSTTabBrowser.treeStyleTab.performDrop(dropActionInfo, $1);
|
||||
return;
|
||||
]]>
|
||||
).replace(
|
||||
'document.getBindingParent(aEvent.originalTarget).localName != "tab"',
|
||||
'!TreeStyleTabService.getTabFromEvent(aEvent)'
|
||||
|
||||
|
||||
).replace(
|
||||
'var tab = aEvent.target;',
|
||||
<![CDATA[$&
|
||||
let locked = (
|
||||
tab.getAttribute('locked') == 'true' || // Tab Mix Plus and others
|
||||
tab.getAttribute('isPageLocked') == 'true' // Super Tab Mode
|
||||
);
|
||||
var loadDroppedLinkToNewChildTab = (
|
||||
dropActionInfo.position != TreeStyleTabService.kDROP_ON ||
|
||||
locked
|
||||
);
|
||||
if (!loadDroppedLinkToNewChildTab &&
|
||||
dropActionInfo.position == TreeStyleTabService.kDROP_ON) {
|
||||
loadDroppedLinkToNewChildTab = TreeStyleTabService.dropLinksOnTabBehavior() == TreeStyleTabService.kDROPLINK_NEWTAB;
|
||||
}
|
||||
if (loadDroppedLinkToNewChildTab || locked) {
|
||||
TSTTabBrowser.treeStyleTab.performDrop(dropActionInfo, TSTTabBrowser.loadOneTab(getShortcutOrURI(url), null, null, null, bgLoad, false));
|
||||
return;
|
||||
}
|
||||
]]>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ('_onDragEnd' in aObserver) { // Firefox 3.5 - 3.6
|
||||
eval('aObserver._onDragEnd = '+aObserver._onDragEnd.toSource().replace(
|
||||
/([^\{\}\(\);]*this\.replaceTabWithWindow\()/,
|
||||
'if (this.treeStyleTab.isDraggingAllCurrentTabs(draggedTab) || this.treeStyleTab.tabbarDNDObserver.canDragTabbar(arguments[0])) return; $1'
|
||||
).replace(
|
||||
'{',
|
||||
'{ var treeStyleTab = this.treeStyleTab;'
|
||||
).replace(
|
||||
/window\.screenX/g, 'gBrowser.boxObject.screenX'
|
||||
).replace(
|
||||
/window\.outerWidth/g, 'gBrowser.boxObject.width'
|
||||
).replace(
|
||||
/\.screenX/g, '[treeStyleTab.positionProp]'
|
||||
).replace(
|
||||
/\.width/g, '[treeStyleTab.sizeProp]'
|
||||
).replace(
|
||||
/\.screenY/g, '[treeStyleTab.invertedPositionProp]'
|
||||
).replace(
|
||||
/\.height/g, '[treeStyleTab.invertedSizeProp]'
|
||||
));
|
||||
}
|
||||
},
|
||||
destroyTabDNDObserver : function TSTService_destroyTabDNDObserver(aObserver)
|
||||
{
|
||||
var strip = this.getTabStrip(aObserver) ||
|
||||
gBrowser.mStrip // fallback to the default strip, for Tab Mix Plus;
|
||||
|
||||
if (aObserver.tabContainer &&
|
||||
aObserver.tabContainer.tabbrowser == aObserver) { // Firefox 4.0 or later
|
||||
strip.removeEventListener('dragstart', this, true);
|
||||
strip.removeEventListener('dragover', this, true);
|
||||
strip.removeEventListener('dragleave', this, true);
|
||||
}
|
||||
|
||||
strip.removeEventListener('dragover', this, true);
|
||||
strip.removeEventListener('dragleave', this, true);
|
||||
},
|
||||
|
||||
checkCanTabDrop : function TSTService_checkCanTabDrop(aEvent, aTabBrowser)
|
||||
{
|
||||
try{
|
||||
var session = this.getCurrentDragSession();
|
||||
var node = session.sourceNode;
|
||||
var tab = this.getTabFromChild(node);
|
||||
if (!node ||
|
||||
!tab ||
|
||||
tab.parentNode != aTabBrowser.mTabContainer)
|
||||
return true;
|
||||
|
||||
tab = this.getTabFromEvent(aEvent);
|
||||
if (this.isCollapsed(tab))
|
||||
return false;
|
||||
|
||||
var info = this.getDropAction(aEvent, session);
|
||||
return info.canDrop;
|
||||
}
|
||||
catch(e) {
|
||||
dump('TreeStyleTabService::canDrop\n'+e+'\n');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
onTabDragStart : function TSTService_onTabDragStart(aEvent)
|
||||
{
|
||||
var b = this.getTabBrowserFromChild(aEvent.currentTarget);
|
||||
if (b.treeStyleTab.tabbarDNDObserver.canDragTabbar(aEvent))
|
||||
return b.treeStyleTab.onTabbarDragStart(aEvent, b);
|
||||
|
||||
var tab = this.getTabFromEvent(aEvent);
|
||||
if (!tab)
|
||||
return;
|
||||
|
||||
var actionInfo = {
|
||||
action : this.kACTIONS_FOR_DESTINATION | this.kACTION_MOVE,
|
||||
event : aEvent
|
||||
};
|
||||
var tabsInfo = b.treeStyleTab.getDraggedTabsInfoFromOneTab(actionInfo, tab);
|
||||
if (tabsInfo.draggedTabs.length <= 1)
|
||||
return;
|
||||
|
||||
window['piro.sakura.ne.jp'].tabsDragUtils.startTabsDrag(aEvent, tabsInfo.draggedTabs);
|
||||
},
|
||||
|
||||
onTabbarDragStart : function TSTService_onTabbarDragStart(aEvent, aTabBrowser)
|
||||
{
|
||||
var dt = aEvent.dataTransfer;
|
||||
dt.mozSetDataAt(
|
||||
this.kDRAG_TYPE_TABBAR,
|
||||
aEvent.shiftKey ?
|
||||
this.kTABBAR_MOVE_FORCE :
|
||||
this.kTABBAR_MOVE_NORMAL,
|
||||
0
|
||||
);
|
||||
dt.mozCursor = 'move';
|
||||
// var tabbar = aTabBrowser.mTabContainer;
|
||||
// var box = tabbar.boxObject;
|
||||
// dt.setDragImage(
|
||||
// tabbar,
|
||||
// aEvent.screenX - box.screenX,
|
||||
// aEvent.screenY - box.screenY
|
||||
// );
|
||||
// no feedback image, because it's annoying...
|
||||
dt.setDragImage(new Image(), 0, 0);
|
||||
aEvent.stopPropagation();
|
||||
aTabBrowser.treeStyleTab.tabbarDNDObserver.readyToStartDrag();
|
||||
},
|
||||
|
||||
onTabDragOver : function TSTService_onTabDragOver(aEvent)
|
||||
{
|
||||
var b = this.getTabBrowserFromChild(aEvent.currentTarget);
|
||||
if (b.treeStyleTab.processTabDragOverEvent(aEvent, b)) {
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault(); // this is required to override default dragover actions!
|
||||
}
|
||||
},
|
||||
|
||||
processTabDragOverEvent : function TSTService_processTabDragOverEvent(aEvent, aTabBrowser)
|
||||
{
|
||||
try{
|
||||
var session = this.getCurrentDragSession();
|
||||
// don't touch to drag & drop of customizable toolbar items
|
||||
if (this.isToolbarCustomizing && !this.getTabFromChild(session.sourceNode))
|
||||
return false;
|
||||
|
||||
this.autoScroll.processAutoScroll(aEvent);
|
||||
|
||||
var info = this.getDropAction(aEvent, session);
|
||||
|
||||
var setEffectAllowedFunc;
|
||||
var observer = aTabBrowser;
|
||||
if (aTabBrowser._setEffectAllowedForDataTransfer) {
|
||||
setEffectAllowedFunc = function(aEvent) {
|
||||
return aTabBrowser._setEffectAllowedForDataTransfer(aEvent);
|
||||
};
|
||||
}
|
||||
else if (aTabBrowser.tabContainer &&
|
||||
aTabBrowser.tabContainer._setEffectAllowedForDataTransfer) {
|
||||
observer = aTabBrowser.tabContainer;
|
||||
setEffectAllowedFunc = function(aEvent) {
|
||||
return aTabBrowser.tabContainer._setEffectAllowedForDataTransfer(aEvent);
|
||||
};
|
||||
}
|
||||
|
||||
// auto-switch for staying on tabs (Firefox 3.5 or later)
|
||||
if (
|
||||
setEffectAllowedFunc &&
|
||||
info.position == this.kDROP_ON &&
|
||||
info.target &&
|
||||
!info.target.selected &&
|
||||
(
|
||||
('mDragTime' in observer && 'mDragOverDelay' in observer) || // Firefox 3.6
|
||||
('_dragTime' in observer && '_dragOverDelay' in observer) // Firefox 4.0 or later
|
||||
)
|
||||
) {
|
||||
let time = observer.mDragTime || observer._dragTime || 0;
|
||||
let delay = observer.mDragOverDelay || observer._dragOverDelay || 0;
|
||||
let effects = setEffectAllowedFunc(aEvent);
|
||||
if (effects == 'link') {
|
||||
let now = Date.now();
|
||||
if (!time) {
|
||||
time = now;
|
||||
if ('mDragTime' in observer)
|
||||
observer.mDragTime = time;
|
||||
else
|
||||
observer._dragTime = time;
|
||||
}
|
||||
if (now >= time + delay)
|
||||
aTabBrowser.selectedTab = info.target;
|
||||
}
|
||||
}
|
||||
|
||||
if (!info.target || info.target != this.evaluateXPath(
|
||||
'child::xul:tab[@'+this.kDROP_POSITION+']',
|
||||
aTabBrowser.mTabContainer,
|
||||
XPathResult.FIRST_ORDERED_NODE_TYPE
|
||||
).singleNodeValue)
|
||||
this.clearDropPosition();
|
||||
|
||||
if (
|
||||
!info.canDrop ||
|
||||
(setEffectAllowedFunc ?
|
||||
(setEffectAllowedFunc(aEvent) == 'none') :
|
||||
!aTabBrowser.canDrop(aEvent, session)
|
||||
)
|
||||
) {
|
||||
aEvent.dataTransfer.effectAllowed = "none";
|
||||
return true;
|
||||
}
|
||||
|
||||
info.target.setAttribute(
|
||||
this.kDROP_POSITION,
|
||||
info.position == this.kDROP_BEFORE ? 'before' :
|
||||
info.position == this.kDROP_AFTER ? 'after' :
|
||||
'self'
|
||||
);
|
||||
var indicator = aTabBrowser.mTabDropIndicatorBar || aTabBrowser.tabContainer._tabDropIndicator;
|
||||
indicator.setAttribute('dragging', (info.position == this.kDROP_ON) ? 'false' : 'true' );
|
||||
return (info.position == this.kDROP_ON || aTabBrowser.treeStyleTab.currentTabbarPosition != 'top')
|
||||
}
|
||||
catch(e) {
|
||||
dump('TreeStyleTabService::onDragOver\n'+e+'\n');
|
||||
}
|
||||
},
|
||||
|
||||
onTabDragLeave : function TSTService_onTabDragLeave(aEvent)
|
||||
{
|
||||
var b = this.getTabBrowserFromChild(aEvent.currentTarget);
|
||||
var tabbarFromEvent = this.getTabbarFromChild(aEvent.relatedTarget);
|
||||
if (!tabbarFromEvent)
|
||||
b.treeStyleTab.clearDropPosition();
|
||||
},
|
||||
|
||||
onTabDrop : function TSTService_onTabDrop(aEvent)
|
||||
{
|
||||
var b = this.getTabBrowserFromChild(aEvent.currentTarget);
|
||||
var tabbar = b.mTabContainer;
|
||||
var sv = b.treeStyleTab;
|
||||
var dt = aEvent.dataTransfer;
|
||||
|
||||
sv.clearDropPosition();
|
||||
|
||||
if (tabbar._tabDropIndicator) // for Firefox 4 or later
|
||||
tabbar._tabDropIndicator.collapsed = true;
|
||||
|
||||
var session = sv.getCurrentDragSession();
|
||||
var dropActionInfo = sv.getDropAction(aEvent, session);
|
||||
|
||||
var draggedTab;
|
||||
if (dt.dropEffect != 'link') {
|
||||
draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||
if (!draggedTab) {
|
||||
aEvent.stopPropagation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (draggedTab && sv.performDrop(dropActionInfo, draggedTab)) {
|
||||
aEvent.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
// duplicating of tabs
|
||||
if (
|
||||
draggedTab &&
|
||||
(
|
||||
dt.dropEffect == 'copy' ||
|
||||
this.getTabBrowserFromChild(draggedTab) != b
|
||||
) &&
|
||||
dropActionInfo.position == sv.kDROP_ON
|
||||
) {
|
||||
var beforeTabs = Array.slice(b.mTabContainer.childNodes);
|
||||
window.setTimeout(function() {
|
||||
var newTabs = Array.slice(b.mTabContainer.childNodes).filter(function(aTab) {
|
||||
return beforeTabs.indexOf(aTab) < 0;
|
||||
});
|
||||
if (newTabs.length)
|
||||
sv.attachTabTo(newTabs[0], dropActionInfo.target);
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// dropping of urls
|
||||
if (!draggedTab) {
|
||||
aEvent.stopPropagation();
|
||||
|
||||
let url = this.retrieveURLFromDataTransfer(dt);
|
||||
|
||||
if (!url || !url.length || url.indexOf(' ', 0) != -1 || /^\s*(javascript|data):/.test(url))
|
||||
return;
|
||||
|
||||
let (sourceDoc = session ? session.sourceDocument : null) {
|
||||
if (sourceDoc &&
|
||||
sourceDoc.documentURI.indexOf('chrome://') < 0) {
|
||||
let sourceURI = sourceDoc.documentURI;
|
||||
let nsIScriptSecurityManager = Components.interfaces.nsIScriptSecurityManager;
|
||||
let secMan = Components.classes['@mozilla.org/scriptsecuritymanager;1']
|
||||
.getService(nsIScriptSecurityManager);
|
||||
try {
|
||||
secMan.checkLoadURIStr(sourceDoc.documentURI, url, nsIScriptSecurityManager.STANDARD);
|
||||
}
|
||||
catch(e) {
|
||||
aEvent.stopPropagation();
|
||||
throw 'Drop of ' + url + ' denied.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let bgLoad = this.getPref('browser.tabs.loadInBackground');
|
||||
if (aEvent.shiftKey) bgLoad = !bgLoad;
|
||||
|
||||
let tab = sv.getTabFromEvent(aEvent);
|
||||
if (!tab || dt.dropEffect == 'copy') {
|
||||
sv.performDrop(dropActionInfo, b.loadOneTab(getShortcutOrURI(url), { inBackground: bgLoad }));
|
||||
}
|
||||
else {
|
||||
let locked = (
|
||||
tab.getAttribute('locked') == 'true' || // Tab Mix Plus and others
|
||||
tab.getAttribute('isPageLocked') == 'true' // Super Tab Mode
|
||||
);
|
||||
let loadDroppedLinkToNewChildTab = dropActionInfo.position != sv.kDROP_ON || locked;
|
||||
if (!loadDroppedLinkToNewChildTab &&
|
||||
dropActionInfo.position == sv.kDROP_ON)
|
||||
loadDroppedLinkToNewChildTab = sv.dropLinksOnTabBehavior() == sv.kDROPLINK_NEWTAB;
|
||||
|
||||
try {
|
||||
if (loadDroppedLinkToNewChildTab || locked) {
|
||||
sv.performDrop(dropActionInfo, b.loadOneTab(getShortcutOrURI(url), { inBackground: bgLoad }));
|
||||
}
|
||||
else {
|
||||
tab.linkedBrowser.loadURI(getShortcutOrURI(url));
|
||||
if (!bgLoad)
|
||||
b.selectedTab = tab;
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
retrieveURLFromDataTransfer : function TSTService_retrieveURLFromDataTransfer(aDataTransfer)
|
||||
{
|
||||
let url;
|
||||
let types = ['text/x-moz-url', 'text/uri-list', 'text/plain', 'application/x-moz-file'];
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
let dataType = types[i];
|
||||
let isURLList = dataType == 'text/uri-list';
|
||||
let urlData = aDataTransfer.mozGetDataAt(isURLList ? 'URL' : dataType , 0);
|
||||
if (urlData) {
|
||||
url = this.retrieveURLFromData(urlData, isURLList ? 'text/plain' : dataType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return url;
|
||||
},
|
||||
retrieveURLFromData : function TSTService_retrieveURLFromData(aData, aType)
|
||||
{
|
||||
switch (aType)
|
||||
{
|
||||
case 'text/unicode':
|
||||
case 'text/plain':
|
||||
case 'text/x-moz-text-internal':
|
||||
return aData.replace(/^\s+|\s+$/g, '');
|
||||
|
||||
case 'text/x-moz-url':
|
||||
return ((aData instanceof Components.interfaces.nsISupportsString) ? aData.toString() : aData)
|
||||
.split('\n')[0];
|
||||
|
||||
case 'application/x-moz-file':
|
||||
let fileHandler = this.IOService.getProtocolHandler('file')
|
||||
.QueryInterface(Components.interfaces.nsIFileProtocolHandler);
|
||||
return fileHandler.getURLSpecFromFile(aData);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
onTabDragEnd : function TSTService_onTabDragEnd(aEvent)
|
||||
{
|
||||
var b = this.getTabBrowserFromChild(aEvent.currentTarget);
|
||||
var tabbar = b.mTabContainer;
|
||||
var strip = b.treeStyleTab.tabStrip;
|
||||
var sv = b.treeStyleTab;
|
||||
var dt = aEvent.dataTransfer;
|
||||
|
||||
sv.clearDropPosition();
|
||||
|
||||
if (
|
||||
dt.mozUserCancelled ||
|
||||
dt.dropEffect != 'none' ||
|
||||
tabbar.hasAttribute(this.kDROP_POSITION) // ignore dragging of the tabbar itself
|
||||
)
|
||||
return;
|
||||
|
||||
// prevent handling of this event by the default handler
|
||||
aEvent.stopPropagation();
|
||||
|
||||
var eX = aEvent.screenX;
|
||||
var eY = aEvent.screenY;
|
||||
var x, y, w, h;
|
||||
|
||||
// ignore drop on the toolbox
|
||||
x = window.screenX;
|
||||
y = window.screenY;
|
||||
w = window.outerWidth;
|
||||
h = document.getElementById('navigator-toolbox').boxObject.height;
|
||||
if (eX > x && eX < x + w && eY > y && eY < y + h)
|
||||
return;
|
||||
|
||||
// ignore drop near the tab bar
|
||||
var box = strip.boxObject;
|
||||
var ignoreArea = Math.max(16, parseInt(this.getFirstNormalTab(b).boxObject.height / 2));
|
||||
x = box.screenX - (sv.isVertical ? ignoreArea : 0 );
|
||||
y = box.screenY - ignoreArea;
|
||||
w = box.width + (sv.isVertical ? ignoreArea + ignoreArea : 0 );
|
||||
h = box.height + ignoreArea + ignoreArea;
|
||||
if (eX > x && eX < x + w && eY > y && eY < y + h)
|
||||
return;
|
||||
|
||||
var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||
if (sv.isDraggingAllCurrentTabs(draggedTab) ||
|
||||
sv.tabbarDNDObserver.canDragTabbar(aEvent))
|
||||
return;
|
||||
|
||||
b.replaceTabWithWindow(draggedTab);
|
||||
},
|
||||
|
||||
overrideGlobalFunctions : function TSTService_overrideGlobalFunctions()
|
||||
{
|
||||
window.__treestyletab__BrowserCustomizeToolbar = window.BrowserCustomizeToolbar;
|
||||
@ -1323,14 +850,6 @@ catch(e) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
// Firefox 3.5 or later
|
||||
case 'dragstart': return this.onTabDragStart(aEvent);
|
||||
case 'dragover': return this.onTabDragOver(aEvent);
|
||||
case 'dragleave': return this.onTabDragLeave(aEvent);
|
||||
// Firefox 4.0 or later
|
||||
case 'drop': return this.onTabDrop(aEvent);
|
||||
case 'dragend': return this.onTabDragEnd(aEvent);
|
||||
}
|
||||
},
|
||||
|
||||
@ -1555,7 +1074,7 @@ catch(e) {
|
||||
}
|
||||
},
|
||||
|
||||
onFocusNextTab : function TSTService_onFocusNextTab(aEvent)
|
||||
onFocusNextTab : function TSTService_onFocusNextTab(aEvent)
|
||||
{
|
||||
var tab = aEvent.target.selectedTab;
|
||||
if (
|
||||
|
@ -324,23 +324,23 @@ TreeStyleTabBrowser.prototype = {
|
||||
tabContainer.addEventListener('dblclick', this, true);
|
||||
tabContainer.addEventListener('select', this, true);
|
||||
tabContainer.addEventListener('scroll', this, true);
|
||||
tabContainer.addEventListener('dragleave', this, false);
|
||||
tabContainer.addEventListener('dragover', this, false);
|
||||
tabContainer.addEventListener('drop', this, true);
|
||||
tabContainer.addEventListener('dragdrop', this, false); // for Firefox 3.5 or older
|
||||
tabContainer.addEventListener('MultipleTabHandler:TabsDragStart', this, true);
|
||||
|
||||
var strip = this.tabStrip;
|
||||
strip.addEventListener('dragstart', this, false);
|
||||
strip.addEventListener('dragstart', this, true);
|
||||
strip.addEventListener('dragover', this, true);
|
||||
strip.addEventListener('dragenter', this, false);
|
||||
strip.addEventListener('dragleave', this, false);
|
||||
strip.addEventListener('dragend', this, false);
|
||||
strip.addEventListener('dragover', this, false);
|
||||
strip.addEventListener('drop', this, false);
|
||||
strip.addEventListener('drop', this, true);
|
||||
strip.addEventListener('MozMouseHittest', this, true); // to block default behaviors of the tab bar
|
||||
strip.addEventListener('mousedown', this, true);
|
||||
strip.addEventListener('click', this, true);
|
||||
|
||||
b.mPanelContainer.addEventListener('dragover', this, true);
|
||||
b.mPanelContainer.addEventListener('dragleave', this, true);
|
||||
b.mPanelContainer.addEventListener('drop', this, true);
|
||||
|
||||
if (this.isFloating)
|
||||
window.addEventListener('resize', this, true);
|
||||
|
||||
@ -1625,23 +1625,23 @@ TreeStyleTabBrowser.prototype = {
|
||||
tabContainer.removeEventListener('dblclick', this, true);
|
||||
tabContainer.removeEventListener('select', this, true);
|
||||
tabContainer.removeEventListener('scroll', this, true);
|
||||
tabContainer.removeEventListener('dragleave', this, false);
|
||||
tabContainer.removeEventListener('dragover', this, false);
|
||||
tabContainer.removeEventListener('drop', this, true);
|
||||
tabContainer.removeEventListener('dragdrop', this, false); // for Firefox 3.5 or older
|
||||
tabContainer.removeEventListener('MultipleTabHandler:TabsDragStart', this, true);
|
||||
|
||||
var strip = this.tabStrip;
|
||||
strip.removeEventListener('dragstart', this, false);
|
||||
strip.removeEventListener('dragstart', this, true);
|
||||
strip.removeEventListener('dragover', this, true);
|
||||
strip.removeEventListener('dragenter', this, false);
|
||||
strip.removeEventListener('dragleave', this, false);
|
||||
strip.removeEventListener('dragend', this, false);
|
||||
strip.removeEventListener('dragover', this, false);
|
||||
strip.removeEventListener('drop', this, false);
|
||||
strip.removeEventListener('drop', this, true);
|
||||
strip.removeEventListener('MozMouseHittest', this, true);
|
||||
strip.removeEventListener('mousedown', this, true);
|
||||
strip.removeEventListener('click', this, true);
|
||||
|
||||
b.mPanelContainer.removeEventListener('dragover', this, true);
|
||||
b.mPanelContainer.removeEventListener('dragleave', this, true);
|
||||
b.mPanelContainer.removeEventListener('drop', this, true);
|
||||
|
||||
if (this.isFloating)
|
||||
window.removeEventListener('resize', this, true);
|
||||
|
||||
@ -1652,8 +1652,6 @@ TreeStyleTabBrowser.prototype = {
|
||||
|
||||
window['piro.sakura.ne.jp'].tabsDragUtils.destroyTabBrowser(b);
|
||||
|
||||
TreeStyleTabService.destroyTabDNDObserver(b);
|
||||
|
||||
this.tabbarDNDObserver.destroy();
|
||||
delete this._tabbarDNDObserver;
|
||||
this.panelDNDObserver.destroy();
|
||||
@ -2030,25 +2028,14 @@ TreeStyleTabBrowser.prototype = {
|
||||
return this.tabbarDNDObserver.onDragEnd(aEvent);
|
||||
|
||||
case 'dragover':
|
||||
case 'dragdrop':
|
||||
return (aEvent.currentTarget == this.tabStrip ?
|
||||
this.tabbarDNDObserver :
|
||||
this.panelDNDObserver).onDragOver(aEvent);
|
||||
|
||||
case 'drop':
|
||||
let (observer) {
|
||||
if (aEvent.currentTarget == this.tabStrip) {
|
||||
observer = this.tabbarDNDObserver;
|
||||
}
|
||||
else {
|
||||
observer = this.panelDNDObserver;
|
||||
if ('nsDragAndDrop' in window) {// for Firefox 3.5 or older
|
||||
// don't use nsDragAndDrop if it can't be dropped!!
|
||||
// http://piro.sakura.ne.jp/latest/blosxom/mozilla/xul/2007-02-02_splitbrowser-dragdrop.htm
|
||||
if (observer.canDrop(aEvent))
|
||||
nsDragAndDrop[aEvent.type == 'dragover' ? 'dragOver' : 'drop' ](aEvent, observer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
observer[aEvent.type == 'dragover' ? 'onDragOver' : 'onDrop' ](aEvent);
|
||||
}
|
||||
return;
|
||||
return (aEvent.currentTarget == this.tabStrip ?
|
||||
this.tabbarDNDObserver :
|
||||
this.panelDNDObserver).onDrop(aEvent);
|
||||
|
||||
|
||||
case 'mouseover':
|
||||
|
@ -7,29 +7,30 @@ function TreeStyleTabBrowserTabbarDNDObserver(aOwner)
|
||||
|
||||
TreeStyleTabBrowserTabbarDNDObserver.prototype = {
|
||||
|
||||
onDragStart : function TSTTabbarDND_onDragStart(aEvent)
|
||||
get SSS()
|
||||
{
|
||||
if (!this.canDragTabbar(aEvent))
|
||||
return false;
|
||||
|
||||
var sv = this.mOwner;
|
||||
var dt = aEvent.dataTransfer;
|
||||
dt.setData(
|
||||
sv.kDRAG_TYPE_TABBAR,
|
||||
aEvent.shiftKey ?
|
||||
sv.kTABBAR_MOVE_FORCE :
|
||||
sv.kTABBAR_MOVE_NORMAL
|
||||
);
|
||||
dt.setData(
|
||||
sv.kDRAG_TYPE_TABBAR+'-node',
|
||||
sv.getTabbarFromEvent(aEvent)
|
||||
);
|
||||
dt.effectAllowed = 'move';
|
||||
|
||||
this.readyToStartDrag();
|
||||
|
||||
aEvent.stopPropagation();
|
||||
return true;
|
||||
if (this._SSS === void(0)) {
|
||||
if ('@mozilla.org/content/style-sheet-service;1' in Components.classes) {
|
||||
this._SSS = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService);
|
||||
}
|
||||
if (!this._SSS)
|
||||
this._SSS = null;
|
||||
}
|
||||
return this._SSS;
|
||||
},
|
||||
|
||||
readyToStartTabbarDrag : function TSTTabbarDND_readyToStartTabbarDrag()
|
||||
{
|
||||
var sheet = this.mOwner.makeURIFromSpec('chrome://treestyletab/content/hide-embed.css');
|
||||
if (!this.SSS.sheetRegistered(sheet, this.SSS.AGENT_SHEET))
|
||||
this.SSS.loadAndRegisterSheet(sheet, this.SSS.AGENT_SHEET);
|
||||
},
|
||||
|
||||
readyToEndTabbarDrag : function TSTTabbarDND_readyToEndTabbarDrag()
|
||||
{
|
||||
var sheet = this.mOwner.makeURIFromSpec('chrome://treestyletab/content/hide-embed.css');
|
||||
if (this.SSS.sheetRegistered(sheet, this.SSS.AGENT_SHEET))
|
||||
this.SSS.unregisterSheet(sheet, this.SSS.AGENT_SHEET);
|
||||
},
|
||||
|
||||
canDragTabbar : function TSTTabbarDND_canDragTabbar(aEvent)
|
||||
@ -87,38 +88,113 @@ TreeStyleTabBrowserTabbarDNDObserver.prototype = {
|
||||
return canDrag;
|
||||
},
|
||||
|
||||
get SSS()
|
||||
canDrop : function TSTTabbarDND_canDrop(aEvent)
|
||||
{
|
||||
if (this._SSS === void(0)) {
|
||||
if ('@mozilla.org/content/style-sheet-service;1' in Components.classes) {
|
||||
this._SSS = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService);
|
||||
var sv = this.mOwner;
|
||||
var tooltip = sv.tabStrip.firstChild;
|
||||
if (tooltip &&
|
||||
tooltip.localName == 'tooltip' &&
|
||||
tooltip.popupBoxObject.popupState != 'closed')
|
||||
tooltip.hidePopup();
|
||||
|
||||
var dropAction = sv.getDropAction(aEvent);
|
||||
if ('dataTransfer' in aEvent) {
|
||||
var dt = aEvent.dataTransfer;
|
||||
if (dropAction.action & this.kACTION_NEWTAB) {
|
||||
dt.effectAllowed = dt.dropEffect = (
|
||||
!dropAction.source ? 'link' :
|
||||
sv.isCopyAction(aEvent) ? 'copy' :
|
||||
'move'
|
||||
);
|
||||
}
|
||||
if (!this._SSS)
|
||||
this._SSS = null;
|
||||
}
|
||||
return this._SSS;
|
||||
return dropAction.canDrop;
|
||||
},
|
||||
|
||||
readyToStartDrag : function TSTTabbarDND_readyToStartDrag()
|
||||
|
||||
canDropTab : function TSTTabbarDND_canDropTab(aEvent)
|
||||
{
|
||||
var sheet = this.mOwner.makeURIFromSpec('chrome://treestyletab/content/hide-embed.css');
|
||||
if (!this.SSS.sheetRegistered(sheet, this.SSS.AGENT_SHEET))
|
||||
this.SSS.loadAndRegisterSheet(sheet, this.SSS.AGENT_SHEET);
|
||||
try{
|
||||
var sv = this.mOwner;
|
||||
var b = sv.mTabBrowser;
|
||||
|
||||
var session = sv.getCurrentDragSession();
|
||||
var node = session.sourceNode;
|
||||
var tab = sv.getTabFromChild(node);
|
||||
if (!node ||
|
||||
!tab ||
|
||||
tab.parentNode != b.mTabContainer)
|
||||
return true;
|
||||
|
||||
tab = sv.getTabFromEvent(aEvent);
|
||||
if (sv.isCollapsed(tab))
|
||||
return false;
|
||||
|
||||
var info = sv.getDropAction(aEvent, session);
|
||||
return info.canDrop;
|
||||
}
|
||||
catch(e) {
|
||||
dump('TreeStyleTabService::canDrop\n'+e+'\n');
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
readyToEndDrag : function TSTTabbarDND_readyToEndDrag()
|
||||
|
||||
onDragStart : function TSTTabbarDND_onDragStart(aEvent)
|
||||
{
|
||||
var sheet = this.mOwner.makeURIFromSpec('chrome://treestyletab/content/hide-embed.css');
|
||||
if (this.SSS.sheetRegistered(sheet, this.SSS.AGENT_SHEET))
|
||||
this.SSS.unregisterSheet(sheet, this.SSS.AGENT_SHEET);
|
||||
if (this.canDragTabbar(aEvent))
|
||||
return this.onTabbarDragStart(aEvent);
|
||||
|
||||
var tab = this.mOwner.getTabFromEvent(aEvent);
|
||||
if (tab)
|
||||
return this.onTabDragStart(aEvent, tab);
|
||||
},
|
||||
|
||||
onTabDragStart : function TSTTabbarDND_onTabDragStart(aEvent, aTab)
|
||||
{
|
||||
var sv = this.mOwner;
|
||||
var actionInfo = {
|
||||
action : sv.kACTIONS_FOR_DESTINATION | sv.kACTION_MOVE,
|
||||
event : aEvent
|
||||
};
|
||||
var tabsInfo = sv.getDraggedTabsInfoFromOneTab(actionInfo, aTab);
|
||||
if (tabsInfo.draggedTabs.length)
|
||||
window['piro.sakura.ne.jp'].tabsDragUtils.startTabsDrag(aEvent, tabsInfo.draggedTabs);
|
||||
},
|
||||
|
||||
onTabbarDragStart : function TSTTabbarDND_onTabbarDragStart(aEvent)
|
||||
{
|
||||
var sv = this.mOwner;
|
||||
var dt = aEvent.dataTransfer;
|
||||
dt.mozSetDataAt(
|
||||
sv.kDRAG_TYPE_TABBAR,
|
||||
aEvent.shiftKey ?
|
||||
sv.kTABBAR_MOVE_FORCE :
|
||||
sv.kTABBAR_MOVE_NORMAL,
|
||||
0
|
||||
);
|
||||
dt.mozCursor = 'move';
|
||||
// var tabbar = sv.mTabBrowser.mTabContainer;
|
||||
// var box = tabbar.boxObject;
|
||||
// dt.setDragImage(
|
||||
// tabbar,
|
||||
// aEvent.screenX - box.screenX,
|
||||
// aEvent.screenY - box.screenY
|
||||
// );
|
||||
// no feedback image, because it's annoying...
|
||||
dt.setDragImage(new Image(), 0, 0);
|
||||
aEvent.stopPropagation();
|
||||
this.readyToStartTabbarDrag();
|
||||
},
|
||||
|
||||
onDragEnter : function TSTTabbarDND_onDragEnter(aEvent)
|
||||
{
|
||||
var dt = aEvent.dataTransfer;
|
||||
if (!this.canDrop(aEvent)) return;
|
||||
|
||||
var sv = this.mOwner;
|
||||
|
||||
var dt = aEvent.dataTransfer;
|
||||
if (!this.canDrop(aEvent)) {
|
||||
dt.effectAllowed = dt.dropEffect = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
var tab = aEvent.target;
|
||||
if (tab.localName != 'tab' ||
|
||||
!sv.getTreePref('autoExpand.enabled'))
|
||||
@ -127,7 +203,8 @@ TreeStyleTabBrowserTabbarDNDObserver.prototype = {
|
||||
window.clearTimeout(this.mAutoExpandTimer);
|
||||
|
||||
var sourceNode = dt.getData(sv.kDRAG_TYPE_TABBAR+'-node');
|
||||
if (aEvent.target == sourceNode) return;
|
||||
if (aEvent.target == sourceNode)
|
||||
return;
|
||||
|
||||
this.mAutoExpandTimer = window.setTimeout(
|
||||
function(aTarget) {
|
||||
@ -154,8 +231,11 @@ TreeStyleTabBrowserTabbarDNDObserver.prototype = {
|
||||
onDragLeave : function TSTTabbarDND_onDragLeave(aEvent)
|
||||
{
|
||||
var sv = this.mOwner;
|
||||
var dt = aEvent.dataTransfer;
|
||||
if (!dt.getData(sv.kDRAG_TYPE_TABBAR)) return;
|
||||
var b = sv.mTabBrowser;
|
||||
|
||||
var tabbarFromEvent = sv.getTabbarFromChild(aEvent.relatedTarget);
|
||||
if (!tabbarFromEvent)
|
||||
sv.clearDropPosition();
|
||||
|
||||
window.clearTimeout(this.mAutoExpandTimer);
|
||||
this.mAutoExpandTimer = null;
|
||||
@ -165,65 +245,314 @@ TreeStyleTabBrowserTabbarDNDObserver.prototype = {
|
||||
{
|
||||
var sv = this.mOwner;
|
||||
var dt = aEvent.dataTransfer;
|
||||
if (!dt.getData(sv.kDRAG_TYPE_TABBAR)) return;
|
||||
if (dt.getData(sv.kDRAG_TYPE_TABBAR))
|
||||
this.onTabbarDragEnd(aEvent);
|
||||
else
|
||||
this.onTabDragEnd(aEvent);
|
||||
},
|
||||
|
||||
onTabDragEnd : function TSTTabbarDND_onTabDragEnd(aEvent)
|
||||
{
|
||||
var sv = this.mOwner;
|
||||
var b = sv.mTabBrowser;
|
||||
|
||||
var tabbar = b.mTabContainer;
|
||||
var strip = sv.tabStrip;
|
||||
var dt = aEvent.dataTransfer;
|
||||
|
||||
sv.clearDropPosition();
|
||||
|
||||
if (dt.mozUserCancelled || dt.dropEffect != 'none')
|
||||
return;
|
||||
|
||||
// prevent handling of this event by the default handler
|
||||
aEvent.stopPropagation();
|
||||
|
||||
var eX = aEvent.screenX;
|
||||
var eY = aEvent.screenY;
|
||||
var x, y, w, h;
|
||||
|
||||
// ignore drop on the toolbox
|
||||
x = window.screenX;
|
||||
y = window.screenY;
|
||||
w = window.outerWidth;
|
||||
h = document.getElementById('navigator-toolbox').boxObject.height;
|
||||
if (eX > x && eX < x + w && eY > y && eY < y + h)
|
||||
return;
|
||||
|
||||
// ignore drop near the tab bar
|
||||
var box = strip.boxObject;
|
||||
var ignoreArea = Math.max(16, parseInt(sv.getFirstNormalTab(b).boxObject.height / 2));
|
||||
x = box.screenX - (sv.isVertical ? ignoreArea : 0 );
|
||||
y = box.screenY - ignoreArea;
|
||||
w = box.width + (sv.isVertical ? ignoreArea + ignoreArea : 0 );
|
||||
h = box.height + ignoreArea + ignoreArea;
|
||||
if (eX > x && eX < x + w && eY > y && eY < y + h)
|
||||
return;
|
||||
|
||||
var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||
if (sv.isDraggingAllCurrentTabs(draggedTab))
|
||||
return;
|
||||
|
||||
b.replaceTabWithWindow(draggedTab);
|
||||
},
|
||||
|
||||
onTabbarDragEnd : function TSTTabbarDND_onTabbarDragEnd(aEvent)
|
||||
{
|
||||
window.setTimeout(function(aSelf) {
|
||||
aSelf.readyToEndDrag();
|
||||
aSelf.readyToEndTabbarDrag();
|
||||
aSelf.mOwner.removeTabbrowserAttribute(aSelf.mOwner.kDROP_POSITION);
|
||||
}, 10, this);
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault();
|
||||
},
|
||||
|
||||
|
||||
onDragOver : function TSTTabbarDND_onDragOver(aEvent)
|
||||
{
|
||||
var sv = this.mOwner;
|
||||
var dt = aEvent.dataTransfer;
|
||||
if (!dt.getData(sv.kDRAG_TYPE_TABBAR) || !this.canDrop(aEvent))
|
||||
return;
|
||||
|
||||
dt.dropEffect = 'move';
|
||||
aEvent.preventDefault();
|
||||
},
|
||||
|
||||
onDrop : function TSTTabbarDND_onDrop(aEvent)
|
||||
{
|
||||
if (!this.canDrop(aEvent)) return;
|
||||
var sv = this.mOwner;
|
||||
if (!this.mAutoExpandedTabs.length) return;
|
||||
if (sv.getTreePref('autoExpand.collapseFinally')) {
|
||||
this.mAutoExpandedTabs.forEach(function(aTarget) {
|
||||
this.collapseExpandSubtree(this.getTabById(aTarget), true, true);
|
||||
}, sv);
|
||||
if (this.onTabDragOver(aEvent)) {
|
||||
aEvent.stopPropagation();
|
||||
aEvent.preventDefault(); // this is required to override default dragover actions!
|
||||
}
|
||||
this.mAutoExpandedTabs = [];
|
||||
aEvent.preventDefault();
|
||||
aEvent.stopPropagation();
|
||||
},
|
||||
|
||||
canDrop : function TSTTabbarDND_canDrop(aEvent)
|
||||
|
||||
onTabDragOver : function TSTTabbarDND_onTabDragOver(aEvent)
|
||||
{
|
||||
try{
|
||||
var sv = this.mOwner;
|
||||
var tooltip = sv.tabStrip.firstChild;
|
||||
if (tooltip &&
|
||||
tooltip.localName == 'tooltip' &&
|
||||
tooltip.popupBoxObject.popupState != 'closed')
|
||||
tooltip.hidePopup();
|
||||
var b = sv.mTabBrowser;
|
||||
|
||||
var dropAction = sv.getDropAction(aEvent);
|
||||
if ('dataTransfer' in aEvent) {
|
||||
var dt = aEvent.dataTransfer;
|
||||
if (dropAction.action & this.kACTION_NEWTAB) {
|
||||
dt.effectAllowed = dt.dropEffect = (
|
||||
!dropAction.source ? 'link' :
|
||||
sv.isCopyAction(aEvent) ? 'copy' :
|
||||
'move'
|
||||
);
|
||||
var session = sv.getCurrentDragSession();
|
||||
if (
|
||||
sv.isToolbarCustomizing ||
|
||||
!sv.getTabFromChild(session.sourceNode)
|
||||
)
|
||||
return false;
|
||||
|
||||
sv.autoScroll.processAutoScroll(aEvent);
|
||||
|
||||
var info = sv.getDropAction(aEvent, session);
|
||||
|
||||
var observer = b;
|
||||
if (b.tabContainer && b.tabContainer._setEffectAllowedForDataTransfer) // for Firefox 4.0
|
||||
observer = b.tabContainer;
|
||||
|
||||
// auto-switch for staying on tabs (Firefox 3.5 or later)
|
||||
if (
|
||||
info.position == sv.kDROP_ON &&
|
||||
info.target &&
|
||||
!info.target.selected &&
|
||||
(
|
||||
('mDragTime' in observer && 'mDragOverDelay' in observer) || // Firefox 3.6
|
||||
('_dragTime' in observer && '_dragOverDelay' in observer) // Firefox 4.0 or later
|
||||
)
|
||||
) {
|
||||
let time = observer.mDragTime || observer._dragTime || 0;
|
||||
let delay = observer.mDragOverDelay || observer._dragOverDelay || 0;
|
||||
let effects = observer._setEffectAllowedForDataTransfer(aEvent);
|
||||
if (effects == 'link') {
|
||||
let now = Date.now();
|
||||
if (!time) {
|
||||
time = now;
|
||||
if ('mDragTime' in observer)
|
||||
observer.mDragTime = time;
|
||||
else
|
||||
observer._dragTime = time;
|
||||
}
|
||||
if (now >= time + delay)
|
||||
aTabBrowser.selectedTab = info.target;
|
||||
}
|
||||
}
|
||||
return dropAction.canDrop;
|
||||
|
||||
if (!info.target || info.target != sv.evaluateXPath(
|
||||
'child::xul:tab[@'+sv.kDROP_POSITION+']',
|
||||
b.mTabContainer,
|
||||
XPathResult.FIRST_ORDERED_NODE_TYPE
|
||||
).singleNodeValue)
|
||||
sv.clearDropPosition();
|
||||
|
||||
if (
|
||||
!info.canDrop ||
|
||||
observer._setEffectAllowedForDataTransfer(aEvent) == 'none'
|
||||
) {
|
||||
aEvent.dataTransfer.effectAllowed = "none";
|
||||
return true;
|
||||
}
|
||||
|
||||
info.target.setAttribute(
|
||||
sv.kDROP_POSITION,
|
||||
info.position == sv.kDROP_BEFORE ? 'before' :
|
||||
info.position == sv.kDROP_AFTER ? 'after' :
|
||||
'self'
|
||||
);
|
||||
var indicator = b.mTabDropIndicatorBar || b.tabContainer._tabDropIndicator;
|
||||
indicator.setAttribute('dragging', (info.position == sv.kDROP_ON) ? 'false' : 'true' );
|
||||
return (info.position == sv.kDROP_ON || sv.currentTabbarPosition != 'top')
|
||||
}
|
||||
catch(e) {
|
||||
dump('TreeStyleTabService::onDragOver\n'+e+'\n');
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onDrop : function TSTTabbarDND_onDrop(aEvent)
|
||||
{
|
||||
this.onTabDrop(aEvent);
|
||||
|
||||
var sv = this.mOwner;
|
||||
if (this.mAutoExpandedTabs.length) {
|
||||
if (sv.getTreePref('autoExpand.collapseFinally')) {
|
||||
this.mAutoExpandedTabs.forEach(function(aTarget) {
|
||||
this.collapseExpandSubtree(this.getTabById(aTarget), true, true);
|
||||
}, sv);
|
||||
}
|
||||
this.mAutoExpandedTabs = [];
|
||||
}
|
||||
},
|
||||
|
||||
onTabDrop : function TSTService_onTabDrop(aEvent)
|
||||
{
|
||||
var sv = this.mOwner;
|
||||
var b = sv.mTabBrowser;
|
||||
|
||||
var tabbar = b.mTabContainer;
|
||||
var dt = aEvent.dataTransfer;
|
||||
|
||||
sv.clearDropPosition();
|
||||
|
||||
if (tabbar._tabDropIndicator) // for Firefox 4 or later
|
||||
tabbar._tabDropIndicator.collapsed = true;
|
||||
|
||||
var session = sv.getCurrentDragSession();
|
||||
var dropActionInfo = sv.getDropAction(aEvent, session);
|
||||
|
||||
var draggedTab;
|
||||
if (dt.dropEffect != 'link') {
|
||||
draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||
if (!draggedTab) {
|
||||
aEvent.stopPropagation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (draggedTab && sv.performDrop(dropActionInfo, draggedTab)) {
|
||||
aEvent.stopPropagation();
|
||||
return;
|
||||
}
|
||||
|
||||
// duplicating of tabs
|
||||
if (
|
||||
draggedTab &&
|
||||
(
|
||||
dt.dropEffect == 'copy' ||
|
||||
sv.getTabBrowserFromChild(draggedTab) != b
|
||||
) &&
|
||||
dropActionInfo.position == sv.kDROP_ON
|
||||
) {
|
||||
var beforeTabs = Array.slice(b.mTabContainer.childNodes);
|
||||
window.setTimeout(function() {
|
||||
var newTabs = Array.slice(b.mTabContainer.childNodes).filter(function(aTab) {
|
||||
return beforeTabs.indexOf(aTab) < 0;
|
||||
});
|
||||
if (newTabs.length)
|
||||
sv.attachTabTo(newTabs[0], dropActionInfo.target);
|
||||
}, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// dropping of urls
|
||||
if (!draggedTab) {
|
||||
aEvent.stopPropagation();
|
||||
|
||||
let url = this.retrieveURLFromDataTransfer(dt);
|
||||
|
||||
if (!url || !url.length || url.indexOf(' ', 0) != -1 || /^\s*(javascript|data):/.test(url))
|
||||
return;
|
||||
|
||||
let (sourceDoc = session ? session.sourceDocument : null) {
|
||||
if (sourceDoc &&
|
||||
sourceDoc.documentURI.indexOf('chrome://') < 0) {
|
||||
let sourceURI = sourceDoc.documentURI;
|
||||
let nsIScriptSecurityManager = Components.interfaces.nsIScriptSecurityManager;
|
||||
let secMan = Components.classes['@mozilla.org/scriptsecuritymanager;1']
|
||||
.getService(nsIScriptSecurityManager);
|
||||
try {
|
||||
secMan.checkLoadURIStr(sourceDoc.documentURI, url, nsIScriptSecurityManager.STANDARD);
|
||||
}
|
||||
catch(e) {
|
||||
aEvent.stopPropagation();
|
||||
throw 'Drop of ' + url + ' denied.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let bgLoad = sv.getPref('browser.tabs.loadInBackground');
|
||||
if (aEvent.shiftKey) bgLoad = !bgLoad;
|
||||
|
||||
let tab = sv.getTabFromEvent(aEvent);
|
||||
if (!tab || dt.dropEffect == 'copy') {
|
||||
sv.performDrop(dropActionInfo, b.loadOneTab(getShortcutOrURI(url), { inBackground: bgLoad }));
|
||||
}
|
||||
else {
|
||||
let locked = (
|
||||
tab.getAttribute('locked') == 'true' || // Tab Mix Plus and others
|
||||
tab.getAttribute('isPageLocked') == 'true' // Super Tab Mode
|
||||
);
|
||||
let loadDroppedLinkToNewChildTab = dropActionInfo.position != sv.kDROP_ON || locked;
|
||||
if (!loadDroppedLinkToNewChildTab &&
|
||||
dropActionInfo.position == sv.kDROP_ON)
|
||||
loadDroppedLinkToNewChildTab = sv.dropLinksOnTabBehavior() == sv.kDROPLINK_NEWTAB;
|
||||
|
||||
try {
|
||||
if (loadDroppedLinkToNewChildTab || locked) {
|
||||
sv.performDrop(dropActionInfo, b.loadOneTab(getShortcutOrURI(url), { inBackground: bgLoad }));
|
||||
}
|
||||
else {
|
||||
tab.linkedBrowser.loadURI(getShortcutOrURI(url));
|
||||
if (!bgLoad)
|
||||
b.selectedTab = tab;
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
retrieveURLFromDataTransfer : function TSTService_retrieveURLFromDataTransfer(aDataTransfer)
|
||||
{
|
||||
let url;
|
||||
let types = ['text/x-moz-url', 'text/uri-list', 'text/plain', 'application/x-moz-file'];
|
||||
for (let i = 0; i < types.length; i++) {
|
||||
let dataType = types[i];
|
||||
let isURLList = dataType == 'text/uri-list';
|
||||
let urlData = aDataTransfer.mozGetDataAt(isURLList ? 'URL' : dataType , 0);
|
||||
if (urlData) {
|
||||
url = this.retrieveURLFromData(urlData, isURLList ? 'text/plain' : dataType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return url;
|
||||
},
|
||||
retrieveURLFromData : function TSTService_retrieveURLFromData(aData, aType)
|
||||
{
|
||||
switch (aType)
|
||||
{
|
||||
case 'text/unicode':
|
||||
case 'text/plain':
|
||||
case 'text/x-moz-text-internal':
|
||||
return aData.replace(/^\s+|\s+$/g, '');
|
||||
|
||||
case 'text/x-moz-url':
|
||||
return ((aData instanceof Components.interfaces.nsISupportsString) ? aData.toString() : aData)
|
||||
.split('\n')[0];
|
||||
|
||||
case 'application/x-moz-file':
|
||||
let fileHandler = this.IOService.getProtocolHandler('file')
|
||||
.QueryInterface(Components.interfaces.nsIFileProtocolHandler);
|
||||
return fileHandler.getURLSpecFromFile(aData);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
destroy : function TSTTabbarDND_destroy()
|
||||
{
|
||||
delete this.mOwner;
|
||||
|
@ -75,13 +75,6 @@ TreeStyleTabBrowserTabpanelDNDObserver.prototype = {
|
||||
) ? true : false ;
|
||||
},
|
||||
|
||||
getSupportedFlavours : function TSTTabpanelDND_getSupportedFlavours()
|
||||
{
|
||||
var flavourSet = new FlavourSet();
|
||||
flavourSet.appendFlavour(this.mOwner.kDRAG_TYPE_TABBAR);
|
||||
return flavourSet;
|
||||
},
|
||||
|
||||
destroy : function TSTTabpanelDND_destroy()
|
||||
{
|
||||
delete this.mOwner;
|
||||
|
Loading…
Reference in New Issue
Block a user