diff --git a/ui/css/editor.css b/ui/css/editor.css index 3b48f33c..8646bc4d 100755 --- a/ui/css/editor.css +++ b/ui/css/editor.css @@ -22,11 +22,13 @@ -o-user-select: none; user-select: none; } -.panel summary { +.panel summary, +.sub-panel summary { padding-left: 3px; background: silver } -.panel summary::-webkit-details-marker { +.panel summary::-webkit-details-marker, +.sub-panel summary::-webkit-details-marker { color: gray; } .panel .close-button { @@ -218,7 +220,8 @@ .dark .panel summary { background: #333; } -.dark .panel summary::-webkit-details-marker { +.dark .panel summary::-webkit-details-marker, +.dark .sub-panel summary::-webkit-details-marker { color: #555; } .dark .sub-panel button, @@ -295,7 +298,8 @@ .gray .panel summary { background: #444; } -.gray .panel summary::-webkit-details-marker { +.gray .panel summary::-webkit-details-marker, +.gray .sub-panel summary::-webkit-details-marker { color: #555; } .gray .sub-panel button, diff --git a/ui/lib/panels.js b/ui/lib/panels.js index 2223a4b7..e5f98a93 100755 --- a/ui/lib/panels.js +++ b/ui/lib/panels.js @@ -6,35 +6,111 @@ //var DEBUG = DEBUG != null ? DEBUG : true +// this is an element/selector to be used as the temporary parent for +// helpers while dragging/sorting sub-panels... +// if set to null, the parent of a nearest panel will be used (slower) +var PANEL_ROOT = 'body' + +var PANEL_HELPER_HIDE_DELAY = 50 +var PANEL_HELPER_HIDE_DELAY_NO_ROOT = 100 + + +/********************************************************************** +* Helpers... +*/ + +// - start monitoring where we are dragged to... +// - open hidden side panels... +function _startSortHandler(e, ui){ + // make the sorted element on top of everything... + // NOTE: showing and hiding the helper for 100ms here prevents it + // from blinking in the upper-left corner of the screen which + // is more distracting... + // XXX find a better way to do this... + (PANEL_ROOT == null + ? ui.item.parents('.panel, .side-panel').first().parent() + : $(PANEL_ROOT)) + .append(ui.helper.css('display', 'none')) + setTimeout(function(){ + ui.helper.css('display', '') + }, PANEL_ROOT == null + ? PANEL_HELPER_HIDE_DELAY_NO_ROOT + : PANEL_HELPER_HIDE_DELAY) + + ui.item.data('isoutside', false) + ui.placeholder + .height(ui.helper.outerHeight()) + .width(ui.helper.outerWidth()) + // show all hidden panels... + $('.side-panel').each(function(){ + var p = $(this) + if(p.attr('autohide') == 'on'){ + p.attr('autohide', 'off') + p.data('autohide', true) + } else { + p.data('autohide', false) + } + }) +} + + +// wrap a sub-panel with a new panel... +// +function wrapWithPanel(panel, parent, offset){ + var new_panel = makePanel() + .css(offset) + .appendTo(parent) + new_panel.find('.panel-content') + .append(panel) + return new_panel +} + + +// close the panel and fire close events on it and all sub-panels... +// +function closePanel(panel, skip_sub_panel_events){ + skip_sub_panel_events = skip_sub_panel_events == null ? false : true + if(!skip_sub_panel_events){ + panel.find('.sub-panel') + .trigger('panelClosing') + } + panel + .trigger('panelClosing') + .remove() +} + + /*********************************************************************/ -function makePanel(title, open, editable_title, keep_empty){ +// XXX dragging out, into another panel and back out behaves oddly: +// should: +// either revert or create a new panel +// does: +// drops to last placeholder +function makePanel(title, open, keep_empty, close_button){ title = title == null || title.trim() == '' ? ' ' : title + close_button = close_button == null ? true : false - // tool panel... + // the outer panel... var panel = $('
') .prop('open', open == null ? true : open) .addClass('panel noScroll') - .append($(''+title+'') - .attr({ - contenteditable: editable_title == null ? 'false' : 'true', - }) - .append($('') - .addClass('close-button') - .click(function(){ - panel - .trigger('panelClosing') - .remove() - return false - }) - .html('×'))) + .append(close_button + ? $(''+title+'') + .append($('') + .addClass('close-button') + .click(function(){ + closePanel(panel) + return false + }) + .html('×')) + : $(''+title+'')) .draggable({ containment: 'parent', scroll: false, - // XXX this makes things quite a bit slower... - //stack: '.panel, .sub-panel', stack: '.panel', + // sanp to panels... //snap: ".panel", //snapMode: "outer", }) @@ -44,41 +120,23 @@ function makePanel(title, open, editable_title, keep_empty){ position: 'absolute', }) - // wrapper for sub-panels... - // XXX dragging out, into another panel and back out behaves oddly: - // should: - // either revert or create a new panel - // does: - // drops to last placeholder - // XXX the helper should be above all other panels... + // content -- wrapper for sub-panels... var content = $('') .sortable({ + // general settings... forcePlaceholderSize: true, opacity: 0.7, connectWith: '.panel-content', - zIndex: 9999, - start: function(e, ui){ - ui.item.data('isoutside', false) - ui.placeholder - .height(ui.helper.outerHeight()) - .width(ui.helper.outerWidth()) - // show all hidden panels... - $('.side-panel').each(function(){ - var p = $(this) - if(p.attr('autohide') == 'on'){ - p.attr('autohide', 'off') - p.data('autohide', true) - } else { - p.data('autohide', false) - } - }) - }, - // create a new panel when dropping outside of curent panel... + start: _startSortHandler, + + // - create a new panel when dropping outside of curent panel... + // - remove empty panels... beforeStop: function(e, ui){ var c = 0 // do this only when dropping outside the panel... + //if(ui.placeholder.css('display') == 'none' if(ui.item.data('isoutside') // prevent draggingout the last panel... // NOTE: 2 because we are taking into account @@ -89,19 +147,13 @@ function makePanel(title, open, editable_title, keep_empty){ // ...this is likely to the fact that we jquery-ui did // not cleanup yet c = 1 - var new_panel = makePanel() - .css(ui.offset) - .appendTo(panel.parent()) - new_panel.find('.panel-content') - .append(ui.item) - panel.trigger('newPanel', [new_panel]) + wrapWithPanel(ui.item, panel.parent(), ui.offset) } // remove the panel when it runs out of sub-panels... if(!keep_empty && panel.find('.sub-panel').length-c <= 0){ - panel - .trigger('panelClosing') - .remove() + // XXX need to trigger sub-panel's 'closing' event... + closePanel(panel, true) } // reset the auto-hide of the side panels... @@ -114,14 +166,18 @@ function makePanel(title, open, editable_title, keep_empty){ ui.item.data('isoutside', false) }, + over: function(e, ui){ ui.item.data('isoutside', false) + ui.placeholder.show() }, out: function(e, ui){ ui.item.data('isoutside', true) + ui.placeholder.hide() }, }) .appendTo(panel) + return panel } @@ -139,38 +195,30 @@ function makeSidePanel(side, autohide){ } panel = $('
') .addClass('side-panel panel-content ' + side) + .attr('autohide', autohide) + // toggle auto-hide... + .dblclick(function(e){ + var elem = $(this) + if(elem.attr('autohide') == 'off'){ + elem.attr('autohide', 'on') + } else { + elem.attr('autohide', 'off') + } + return false + }) .sortable({ forcePlaceholderSize: true, opacity: 0.7, connectWith: '.panel-content', - zIndex: 9999, - start: function(e, ui){ - ui.item.data('isoutside', false) - ui.placeholder - .height(ui.helper.outerHeight()) - .width(ui.helper.outerWidth()) - // show all hidden panels... - $('.side-panel').each(function(){ - var p = $(this) - if(p.attr('autohide') == 'on'){ - p.attr('autohide', 'off') - p.data('autohide', true) - } else { - p.data('autohide', false) - } - }) - }, - // create a new panel when dropping outside of curent panel... + start: _startSortHandler, + + // - create a new panel when dropping outside of curent panel... + // - remove empty panels... beforeStop: function(e, ui){ // do this only when dropping outside the panel... if(ui.item.data('isoutside')){ - var new_panel = makePanel() - .css(ui.offset) - .appendTo(panel.parent()) - new_panel.find('.panel-content') - .append(ui.item) - panel.trigger('newPanel', [new_panel]) + wrapWithPanel(ui.item, panel.parent(), ui.offset) } // reset the auto-hide of the side panels... @@ -183,23 +231,17 @@ function makeSidePanel(side, autohide){ ui.item.data('isoutside', false) }, + over: function(e, ui){ ui.item.data('isoutside', false) + ui.placeholder.show() }, out: function(e, ui){ ui.item.data('isoutside', true) + ui.placeholder.hide() }, }) - .dblclick(function(e){ - var elem = $(this) - if(elem.attr('autohide') == 'off'){ - elem.attr('autohide', 'on') - } else { - elem.attr('autohide', 'off') - } - return false - }) - .attr('autohide', autohide) + return panel }