Support ESC key to dismiss menus and dialogs (which required jquery eventstack plugin).

Updated binding names in project.vt so that the bound HTML elements are distinguished from the JS objects that manage them (e.g., summarBarDiv vs summaryBar).

git-svn-id: http://google-refine.googlecode.com/svn/trunk@1591 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
David Huynh 2010-10-18 01:07:35 +00:00
parent 5c54984c96
commit a5c6a3af34
7 changed files with 157 additions and 24 deletions

View File

@ -164,6 +164,7 @@ function init() {
[ [
"externals/jquery-1.4.2.min.js", "externals/jquery-1.4.2.min.js",
"externals/jquery.cookie.js", "externals/jquery.cookie.js",
"externals/jquery.eventstack-0.3.js",
"externals/suggest/suggest-1.2.1.min.js", "externals/suggest/suggest-1.2.1.min.js",
"externals/jquery-ui/jquery-ui-1.8.custom.min.js", "externals/jquery-ui/jquery-ui-1.8.custom.min.js",
"externals/imgareaselect/jquery.imgareaselect.js", "externals/imgareaselect/jquery.imgareaselect.js",

View File

@ -126,6 +126,9 @@ licenses/jquery.LICENSE.txt
licenses/jquery_ui.LICENSE.txt licenses/jquery_ui.LICENSE.txt
jquery_ui jquery_ui
licenses/jquery.eventstack.LICENSE.txt
jquery eventstack
licenses/datejs.LICENSE.txt licenses/datejs.LICENSE.txt
datejs datejs

View File

@ -0,0 +1,94 @@
/**
* Copyright (c) 2008, Ben XO <me@ben-xo.com>
*
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
*
* This is a jQuery plugin that allows events to be handled in reverse order of
* binding - add events to the head of the queue rather than the end.
*
* Particularly useful if you apply your "do"s in a modular order and wish to
* apply your "undo"s in reverse order.
*
* It adds the following two methods:
*
* reverse(event): reverses the order that functions attached to <event> are
* applied to this element.
*
* stack( event, data, fn ): just like bind(), except adds to the front of the
* event queue instead of the end.
*
* Also, every event method (.click(), .focus(), .resize(), .submit(), etc -
* 21 methods in all) can take an extra parameter "reverse" that controls if
* the event is added to the front or end of the event queue. For example:
*
* $("body").click(function() { alert("1"); });
* $("body").click(function() { alert("2"); });
* $("body").click(function() { alert("3"); }, true);
*
* ... will show "3", "1" then "2" when the document is clicked.
*
* @version 0.3
*/
jQuery.fn.extend({
// reverse the order of events bound to an element
reverse: function( event ) {
var events = this.data("events");
if ( events != undefined && events[event] != undefined) {
// can't reverse what's not there
var reverseEvent = new Array;
for (var e in events[event]) {
reverseEvent.unshift(events[event][e]);
}
events[event] = reverseEvent;
}
return this;
},
// add an event to the front of an event queue rather than the back
// we do this by reversing the queue, adding, then reversing again
stack: function( event, data, fn ) {
return this
.reverse( event )
.bind( event, data, fn )
.reverse( event )
;
},
hover: function( fnOver, fnOut, reverse ) {
if(reverse) {
return this
.stack('mouseenter', fnOver)
.stack('mouseleave', fnOut)
;
} else {
return this
.bind('mouseenter', fnOver)
.bind('mouseleave', fnOut)
;
}
}
});
// every event handler - blur(), focus(), click() etc now has a 2nd param which
// if true will add the passed function to the beginning of the event list
// instead of the end
jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," +
"submit,keydown,keypress,keyup,error").split(","), function(i, name){
// Handle event binding
jQuery.fn[name] = function(fn, reverse){
if(fn) {
return reverse ?
this.stack(name, fn) :
this.bind(name, fn)
;
} else {
return this.trigger(name);
}
};
});

View File

@ -22,28 +22,28 @@
<div id="loading-message"><img src="images/large-spinner.gif" /> Starting up...</div> <div id="loading-message"><img src="images/large-spinner.gif" /> Starting up...</div>
<div id="body"> <div id="body">
<div bind="leftPanel" id="left-panel"> <div bind="leftPanelDiv" id="left-panel">
<div bind="leftPanelTabs" class="refine-tabs"> <div bind="leftPanelTabs" class="refine-tabs">
<ul> <ul>
<li><a href="#refine-tabs-facets">Facet / Filter</a></li> <li><a href="#refine-tabs-facets">Facet / Filter</a></li>
<li><a href="#refine-tabs-history" bind="historyTabHeader">Undo / Redo</a></li> <li><a href="#refine-tabs-history" bind="historyTabHeader">Undo / Redo</a></li>
</ul> </ul>
<div id="refine-tabs-facets" bind="facetPanel" id="facet-panel"></div> <div id="refine-tabs-facets" bind="facetPanelDiv" id="facet-panel"></div>
<div id="refine-tabs-history" bind="historyPanel" id="history-panel"></div> <div id="refine-tabs-history" bind="historyPanelDiv" id="history-panel"></div>
</div> </div>
</div> </div>
<div bind="rightPanel" id="right-panel"> <div bind="rightPanelDiv" id="right-panel">
<div bind="toolPanel" id="tool-panel"> <div bind="toolPanelDiv" id="tool-panel">
<div bind="summaryBar" id="summary-bar"> <div bind="summaryBarDiv" id="summary-bar">
<!-- row/record counts --> <!-- row/record counts -->
</div> </div>
<div bind="extensionBar" id="extension-bar"> <div bind="extensionBarDiv" id="extension-bar">
Extensions: <span bind="menuContainer" id="extension-bar-menu-container"></span> Extensions: <span bind="menuContainer" id="extension-bar-menu-container"></span>
</div> </div>
</div> </div>
<div bind="viewPanel" id="view-panel"></div> <div bind="viewPanelDiv" id="view-panel"></div>
</div> </div>
<div bind="processPanel" id="process-panel"></div> <div bind="processPanelDiv" id="process-panel"></div>
</div> </div>
</body> </body>
</html> </html>

View File

@ -19,34 +19,34 @@ function resize() {
var top = $("#header").outerHeight(); var top = $("#header").outerHeight();
var height = $(window).height() - top; var height = $(window).height() - top;
var leftPanelPaddings = ui.leftPanel.outerHeight(true) - ui.leftPanel.height(); var leftPanelPaddings = ui.leftPanelDiv.outerHeight(true) - ui.leftPanelDiv.height();
ui.leftPanel ui.leftPanelDiv
.css("top", top + "px") .css("top", top + "px")
.css("left", "0px") .css("left", "0px")
.css("height", (height - leftPanelPaddings) + "px") .css("height", (height - leftPanelPaddings) + "px")
.css("width", leftPanelWidth + "px"); .css("width", leftPanelWidth + "px");
var leftPanelTabsPaddings = ui.leftPanelTabs.outerHeight(true) - ui.leftPanelTabs.height(); var leftPanelTabsPaddings = ui.leftPanelTabs.outerHeight(true) - ui.leftPanelTabs.height();
ui.leftPanelTabs.height(ui.leftPanel.height() - leftPanelTabsPaddings); ui.leftPanelTabs.height(ui.leftPanelDiv.height() - leftPanelTabsPaddings);
var rightPanelVPaddings = ui.rightPanel.outerHeight(true) - ui.rightPanel.height(); var rightPanelVPaddings = ui.rightPanelDiv.outerHeight(true) - ui.rightPanelDiv.height();
var rightPanelHPaddings = ui.rightPanel.outerWidth(true) - ui.rightPanel.width(); var rightPanelHPaddings = ui.rightPanelDiv.outerWidth(true) - ui.rightPanelDiv.width();
ui.rightPanel ui.rightPanelDiv
.css("top", top + "px") .css("top", top + "px")
.css("left", leftPanelWidth + "px") .css("left", leftPanelWidth + "px")
.css("height", (height - rightPanelVPaddings) + "px") .css("height", (height - rightPanelVPaddings) + "px")
.css("width", (width - leftPanelWidth - rightPanelHPaddings) + "px"); .css("width", (width - leftPanelWidth - rightPanelHPaddings) + "px");
ui.viewPanel.height((height - ui.toolPanel.outerHeight() - rightPanelVPaddings) + "px"); ui.viewPanelDiv.height((height - ui.toolPanelDiv.outerHeight() - rightPanelVPaddings) + "px");
var processPanelWidth = 400; var processPanelWidth = 400;
ui.processPanel ui.processPanelDiv
.css("width", processPanelWidth + "px") .css("width", processPanelWidth + "px")
.css("left", Math.floor((width - processPanelWidth) / 2) + "px"); .css("left", Math.floor((width - processPanelWidth) / 2) + "px");
} }
function resizeTabs() { function resizeTabs() {
var totalHeight = ui.leftPanel.height(); var totalHeight = ui.leftPanelDiv.height();
var headerHeight = ui.leftPanelTabs.find(".ui-tabs-nav").outerHeight(true); var headerHeight = ui.leftPanelTabs.find(".ui-tabs-nav").outerHeight(true);
var visibleTabPanels = ui.leftPanelTabs.find(".ui-tabs-panel:not(.ui-tabs-hide)"); var visibleTabPanels = ui.leftPanelTabs.find(".ui-tabs-panel:not(.ui-tabs-hide)");
@ -81,18 +81,18 @@ function initializeUI(uiState) {
ui = DOM.bind($("#body")); ui = DOM.bind($("#body"));
ui.extensionBar = new ExtensionBar(ui.extensionBar); // construct the menu first so we can resize everything else ui.extensionBar = new ExtensionBar(ui.extensionBarDiv); // construct the menu first so we can resize everything else
ui.exporterManager = new ExporterManager($("#export-button")); ui.exporterManager = new ExporterManager($("#export-button"));
ui.leftPanelTabs.tabs({ selected: 0 }); ui.leftPanelTabs.tabs({ selected: 0 });
resize(); resize();
resizeTabs(); resizeTabs();
ui.summaryBar = new SummaryBar(ui.summaryBar); ui.summaryBar = new SummaryBar(ui.summaryBarDiv);
ui.browsingEngine = new BrowsingEngine(ui.facetPanel, uiState.facets || []); ui.browsingEngine = new BrowsingEngine(ui.facetPanelDiv, uiState.facets || []);
ui.processPanel = new ProcessPanel(ui.processPanel); ui.processPanel = new ProcessPanel(ui.processPanelDiv);
ui.historyPanel = new HistoryPanel(ui.historyPanel, ui.historyTabHeader); ui.historyPanel = new HistoryPanel(ui.historyPanelDiv, ui.historyTabHeader);
ui.dataTableView = new DataTableView(ui.viewPanel); ui.dataTableView = new DataTableView(ui.viewPanelDiv);
ui.leftPanelTabs.bind('tabsshow', function(event, tabs) { ui.leftPanelTabs.bind('tabsshow', function(event, tabs) {
if (tabs.index === 0) { if (tabs.index === 0) {

View File

@ -27,6 +27,21 @@ DialogSystem.showDialog = function(elmt, onCancel) {
DialogSystem._layers.push(layer); DialogSystem._layers.push(layer);
var level = DialogSystem._layers.length; var level = DialogSystem._layers.length;
layer.keyHandler = function(evt) {
if (evt.keyCode == 27 && !evt.shiftKey && !evt.metaKey && !evt.altKey && !evt.ctrlKey &&
evt.target.tagName.toLowerCase() != "input" &&
evt.target.tagName.toLowerCase() != "textarea") {
DialogSystem.dismissUntil(level - 1);
evt.stopImmediatePropagation();
evt.stopPropagation();
evt.preventDefault();
return false;
}
};
$(document).stack("keydown", layer.keyHandler);
return level; return level;
}; };
@ -37,6 +52,9 @@ DialogSystem.dismissAll = function() {
DialogSystem.dismissUntil = function(level) { DialogSystem.dismissUntil = function(level) {
for (var i = DialogSystem._layers.length - 1; i >= level; i--) { for (var i = DialogSystem._layers.length - 1; i >= level; i--) {
var layer = DialogSystem._layers[i]; var layer = DialogSystem._layers[i];
$(document).unbind("keydown", layer.keyHandler);
layer.overlay.remove(); layer.overlay.remove();
layer.container.remove(); layer.container.remove();
layer.container.unbind(); layer.container.unbind();

View File

@ -17,10 +17,24 @@ MenuSystem.showMenu = function(elmt, onDismiss) {
elmt: elmt, elmt: elmt,
onDismiss: onDismiss onDismiss: onDismiss
}; };
MenuSystem._layers.push(layer); MenuSystem._layers.push(layer);
var level = MenuSystem._layers.length; var level = MenuSystem._layers.length;
layer.keyHandler = function(evt) {
if (evt.keyCode == 27 && !evt.shiftKey && !evt.metaKey && !evt.altKey && !evt.ctrlKey &&
evt.target.tagName.toLowerCase() != "input" &&
evt.target.tagName.toLowerCase() != "textarea") {
MenuSystem.dismissUntil(level - 1);
evt.stopImmediatePropagation();
evt.stopPropagation();
evt.preventDefault();
return false;
}
};
$(document).stack("keydown", layer.keyHandler);
return level; return level;
}; };
@ -35,6 +49,9 @@ MenuSystem.dismissAll = function() {
MenuSystem.dismissUntil = function(level) { MenuSystem.dismissUntil = function(level) {
for (var i = MenuSystem._layers.length - 1; i >= level; i--) { for (var i = MenuSystem._layers.length - 1; i >= level; i--) {
var layer = MenuSystem._layers[i]; var layer = MenuSystem._layers[i];
$(document).unbind("keydown", layer.keyHandler);
layer.elmt.remove(); layer.elmt.remove();
layer.elmt.unbind(); layer.elmt.unbind();
layer.onDismiss(); layer.onDismiss();