Caret/js/sessions/binding.js
2014-05-04 21:53:50 -07:00

147 lines
No EOL
4.5 KiB
JavaScript

define([
"command",
"sessions/state",
"sessions/addRemove",
"ui/contextMenus",
"util/manos",
"util/dom2"
], function(command, state, addRemove, contextMenus, M) {
/*
This module returns a function that will bind for event delegation to the
tab container. Most of it is support for drag/drop.
*/
var enableTabDragDrop = function() {
var tabContainer = document.find(".tabs");
var draggedTab = null;
tabContainer.on("dragstart", function(e) {
if (!e.target.matches(".tab")) return;
e.target.style.opacity = 0;
setTimeout(function() {
e.target.addClass("dragging");
}, 50);
e.dataTransfer.setDragImage(e.target, 0, 0);
e.dataTransfer.effectAllowed = "move";
e.dataTransfer.clearData("text/plain");
e.dataTransfer.clearData("text/uri-list");
e.dataTransfer.setData("application/x-tab-id", e.target.getAttribute("tab-id"));
draggedTab = e.target;
draggedTab.ondragend = function() {
draggedTab = null;
e.target.style.opacity = null;
e.target.removeClass("dragging");
};
});
tabContainer.on("dragover", function(e) {
e.preventDefault();
e.stopPropagation();
e.dropEffect = "move";
var tab = e.target.findUp(".tab:not(.hovering)");
if (tab || e.target == tabContainer) {
var old = tabContainer.find(".hovering");
if (old) old.removeClass("hovering");
if (tab) tab.addClass("hovering");
}
});
//cancel hover appearance when leaving the tab bar
tabContainer.on("drag", function(e) {
var tabCoords = tabContainer.getBoundingClientRect();
if (
e.clientX > tabCoords.left &&
e.clientX < tabCoords.left + tabCoords.width &&
e.clientY > tabCoords.top &&
e.clientY < tabCoords.top + tabCoords.top
) return;
var hovered = tabContainer.find(".hovering");
if (hovered) hovered.removeClass("hovering");
});
tabContainer.on("drop", function(e) {
if (!draggedTab) return;
e.stopPropagation();
var location = "before"; //how to position the new tab
var target; //closest tab to drop event
if (e.target == tabContainer) {
//if dropped on the bar, find the nearest tab to go after
var elements = tabContainer.findAll(".tab");
location = "after";
elements.forEach(function(el) {
if (el.offsetLeft < e.offsetX) {
target = el;
}
});
} else {
//otherwise, find the actual tab element
target = e.target.findUp(".tab");
}
var fromIndex = e.dataTransfer.getData("application/x-tab-id") * 1;
var toIndex = target.getAttribute("tab-id") * 1;
var from = state.tabs[fromIndex];
var to = state.tabs[toIndex];
if (from != to) {
var reordered = [];
state.tabs.forEach(function(t) {
if (t == from) return;
if (t == to && location == "before") {
reordered.push(from);
}
reordered.push(t);
if (t == to && location == "after") {
reordered.push(from);
}
});
state.tabs = reordered;
}
command.fire("session:render");
});
};
var enableTabMiddleClick = function() {
var tabContainer = document.find(".tabs");
tabContainer.on("click", function(e) {
if (!e.target.matches(".label")) return;
if (e.button != 1) return;
e.preventDefault();
command.fire("session:close-tab", e.target.getAttribute("argument"));
});
};
var closeTabsRight = function(tabID) {
tabID = tabID || state.tabs.indexOf(editor.getSession());
var toClose = [];
for (var i = state.tabs.length - 1; i > tabID; i--) {
toClose.push(i);
}
M.serial(toClose, addRemove.remove);
};
var enableDblClickNewTab = function() {
var tabContainer = document.find(".tabs");
tabContainer.on("dblclick", function(e) {
e.preventDefault();
if (e.button == 0)
command.fire("session:new-file");
});
};
command.on("session:close-to-right", closeTabsRight);
contextMenus.register("Close", "closeTab", "tabs/:id", function(args) {
command.fire("session:close-tab", args.id);
});
contextMenus.register("Close tabs to the right", "closeTabsRight", "tabs/:id", function(args) {
closeTabsRight(args.id);
});
return function() {
enableTabDragDrop();
enableTabMiddleClick();
enableDblClickNewTab();
};
});