Adding shape tree plus synchronization

--HG--
branch : dev
This commit is contained in:
Sebastien Ros
2011-03-12 16:18:33 -08:00
parent 0d83b97cc3
commit 6dc7f927bd
4 changed files with 197 additions and 15 deletions

View File

@@ -6,7 +6,10 @@
'<div id="shape-tracing-toolbar">' +
'<div id="shape-tracing-toolbar-switch"></div>' +
'</div>' +
'<div id="shape-tracing-window"></div>' +
'<div id="shape-tracing-window">' +
'<div id="shape-tracing-window-tree"></div>' +
'<div id="shape-tracing-window-content">foo</div>' +
'</div>' +
'</div>' +
'<div id="shape-tracing-container-ghost"></div>'
).appendTo('body');
@@ -16,6 +19,8 @@
var shapeTracingToolbar = $('#shape-tracing-toolbar');
var shapeTracingToolbarSwitch = $('#shape-tracing-toolbar-switch');
var shapeTracingWindow = $('#shape-tracing-window');
var shapeTracingWindowTree = $('#shape-tracing-window-tree');
var shapeTracingWindowContent = $('#shape-tracing-window-content');
var shapeTracingGhost = $('#shape-tracing-container-ghost');
// store the size of the container when it is closed (default in css)
@@ -50,7 +55,7 @@
var _this = $(this);
_this.toggleClass('expanded');
if (_this.hasClass('expanded')) {
shapeTracingContainer.height(Math.max(previousSize, 100));
shapeTracingContainer.height(Math.max(previousSize, 100, shapeTracingContainer.height()));
}
else {
// save previous height
@@ -75,6 +80,7 @@
var shapeNode = {
id: _this.attr('shape-id'),
type: _this.attr('shape-type'),
hint: _this.attr('shape-hint'),
parent: null,
children: {}
};
@@ -83,6 +89,7 @@
shapeNodes[shapeNode.id] = shapeNode;
// assign the shape-id attribute to all elements, except wrappers themselves (it would erase their own shape-id)
var found = false;
_this
.nextUntil('[end-of="' + shapeNode.id + '"]') // all elements between the script beacons
.find(':not(.shape-tracing-wrapper)') // all children but not inner beacons
@@ -91,8 +98,13 @@
.each(function () {
// assign a shapeNode instance to the DOM element
this.shapeNode = shapeNode;
found = true;
});
// if the shape is empty, add a hint
if (!found) {
shapeNode.hint = 'empty';
}
this.shapeNode = shapeNode;
});
@@ -116,29 +128,109 @@
// removes all beacons as we don't need them anymore
$('.shape-tracing-wrapper').remove();
// add first level shapes tree nodes
var shapes = $('<ul></ul>');
for (var shapeId in shapeNodes) {
if (!shapeNodes[shapeId].parent) {
shapes.append(createTreeNode(shapeNodes[shapeId]));
}
}
shapeTracingWindow.append(shapes);
//create an overlay on shapes' descendants
$('[shape-id]').hover(
shapeTracingWindowTree.append(shapes);
// add the expand/collapse logic
var glyph = $('<span class="expando-glyph-container closed"><span class="expando-glyph"></span>&#8203;</span>');
shapeTracingWindowTree.find('div').parent(':has(li)').prepend(glyph);
// collapse all sub uls
shapeTracingWindowTree.find('ul ul').toggle(false);
// expands a list of shapes in the tree
var openExpando = function (expando) {
if (expando.hasClass("closed") || expando.hasClass("closing")) {
expando.siblings('ul').slideDown(100, function () { expando.removeClass("opening").removeClass("closed").addClass("open"); });
expando.addClass("opening");
}
}
// collapses a list of shapes in the tree
var closeExpando = function (expando) {
if (!expando.hasClass("closed") && !expando.hasClass("closing")) {
expando.siblings('ul').slideUp(100, function () { expando.removeClass("closing").removeClass("open").addClass("closed"); });
expando.addClass("closing");
}
}
// automatically expand or collapse shapes in the tree
shapeTracingWindowTree.find('.expando-glyph-container').click(function () {
var _this = $(this);
if (_this.hasClass("closed") || _this.hasClass("closing")) {
openExpando(_this);
}
else {
closeExpando(_this);
}
return false;
});
//create an overlay on shapes' descendants, and in shape tree
$('[shape-id]').add('[tree-shape-id] div').hover(
function () {
var _this = $(this);
$('.shape-tracing-overlay').removeClass('shape-tracing-overlay');
$(this).addClass('shape-tracing-overlay');
_this.addClass('shape-tracing-overlay');
},
function () {
$(this).removeClass('shape-tracing-overlay');
$('.shape-tracing-overlay').removeClass('shape-tracing-overlay');
}
);
// select shapes when clicked
$('[shape-id]').click(function (event) {
selectShape(this.shapeNode.id);
var lastExpanded = null;
// open the tree until the selected element
$('li[tree-shape-id="' + this.shapeNode.id + '"]').parents('li').andSelf().find('> .expando-glyph-container').each(function () {
openExpando($(lastExpanded = this));
});
if (lastExpanded) {
lastExpanded.scrollIntoView();
}
event.stopPropagation();
});
// select shape tree elements when clicked
$('[tree-shape-id] > div').click(function (event) {
var shapeId = $(this).parent().get(0).shapeNode.id;
selectShape(shapeId);
var element = $('[shape-id="' + shapeId + '"]').get(0);
// there might be no DOM element if the shape was empty, or is not displayed
if (element) {
element.scrollIntoView();
}
event.stopPropagation();
});
});
// recursively create a node for the shapes tree
function createTreeNode(shapeNode) {
var node = $('<li></li>');
node.text(shapeNode.type);
node.attr('tree-shape-id', shapeNode.id);
node.get(0).shapeNode = shapeNode;
var text = shapeNode.type;
// add the hint to the tree node if available
if (shapeNode.hint != '') {
text += ' [' + shapeNode.hint + ']';
}
node.append('<div>' + text + '</div>');
var list = $('<ul></ul>');
node.append(list);
if (shapeNode.children) {
@@ -150,4 +242,10 @@
return node;
}
// select a specific shape in the tree, highlight its elements, and display the information
function selectShape(shapeId) {
$('.shape-tracing-selected').removeClass('shape-tracing-selected');
$('li[tree-shape-id="' + shapeId + '"] > div').add('[shape-id="' + shapeId + '"]').addClass('shape-tracing-selected');
}
})(jQuery);

View File

@@ -6,6 +6,7 @@ using Orchard.DisplayManagement.Shapes;
using Orchard.Environment.Extensions;
using Orchard.FileSystems.WebSite;
using Orchard.Themes;
using Orchard.UI;
namespace Orchard.DesignerTools.Services {
[OrchardFeature("Orchard.DesignerTools")]
@@ -78,6 +79,11 @@ namespace Orchard.DesignerTools.Services {
if (shapeMetadata.PlacementSource != null && _webSiteFolder.FileExists(shapeMetadata.PlacementSource)) {
context.Shape.PlacementContent = _webSiteFolder.ReadFile(shapeMetadata.PlacementSource);
}
// Inject the Zone name
if(shapeMetadata.Type == "Zone") {
shape.Hint = ((Zone) shape).ZoneName;
}
}

View File

@@ -5,7 +5,6 @@
#shape-tracing-container ul,
#shape-tracing-container li {
background-color: #fff;
margin:0;
padding:0;
color:#000;
@@ -71,18 +70,97 @@
cursor: pointer;
}
.shape-tracing-tree-overlay {
background-color:#eee;
cursor: pointer;
}
#shape-tracing-window {
background-color: #fff;
height:100%;
}
#shape-tracing-window li
{
list-style-type:inherit;
#shape-tracing-window-tree {
display:block;
float:left;
overflow:auto;
width:33%;
height:100%;
padding:10px;
}
#shape-tracing-window ul
{
#shape-tracing-window-tree li {
clear:both;
line-height:16px;
}
.shape-tracing-selected {
background-color:#FFA20D;
}
#shape-tracing-window-tree ul {
margin-left:10px;
padding-left:10px;
list-style-type:none;
}
#shape-tracing-window-tree li > div {
}
#shape-tracing-window-content {
display:block;
float:left;
width:66%;
background:yellow;
height:100%;
}
#shape-tracing-window-tree .expando-glyph {
background:transparent no-repeat 0 -19px;
background-image:url(images/menu-glyph.png);
padding-left:15px;
}
#shape-tracing-window-tree .expando-glyph:hover {
background-image:url(images/menu-glyph.png);
}
#shape-tracing-window-tree .expando-glyph-container {
float:left;
display:block;
width:15px;
margin-left:-15px;
cursor:default;
}
#shape-tracing-window-tree .expando-glyph-container.closed .expando-glyph {
background-repeat:no-repeat;
background-image:url(images/menu-glyph.png);
background-position:0 3px;
}
#shape-tracing-window-tree .expando-glyph-container.closed .expando-glyph:hover {
background-image:url(images/menu-glyph.png);
}
#shape-tracing-window-tree .expando-glyph-container.closing .expando-glyph
{
background-repeat:no-repeat;
-webkit-transition:all .2s ease-in-out;
-moz-transition:all .2s ease-in-out;
transition:all .2s ease-in-out;
-webkit-transform:rotate(-90deg) translate(3px, -3px);
-moz-transform:rotate(-90deg) translate(3px, -3px);
transform:rotate(-90deg) translate(3px, -3px);
}
#shape-tracing-window-tree .expando-glyph-container.opening .expando-glyph
{
background-repeat:no-repeat;
-webkit-transition:all .2s ease-in-out;
-moz-transition:all .2s ease-in-out;
transition:all .2s ease-in-out;
-webkit-transform:rotate(90deg) translate(3px, 3px);
-moz-transform:rotate(90deg) translate(3px, 3px);
transform:rotate(90deg) translate(3px, 3px);
}

View File

@@ -21,7 +21,7 @@
Script.Include("CodeMirror/htmlmixed.js");
}
<script class="shape-tracing-wrapper" shape-id="@Model.GetHashCode()" shape-type="@Model.Metadata.Type"></script>@Display(Model.Metadata.ChildContent)<script class="shape-tracing-wrapper" end-of="@Model.GetHashCode()"></script>
<script class="shape-tracing-wrapper" shape-id="@Model.GetHashCode()" shape-type="@Model.Metadata.Type" shape-hint="@Model.Hint"></script>@Display(Model.Metadata.ChildContent)<script class="shape-tracing-wrapper" end-of="@Model.GetHashCode()"></script>
@{
Layout.Zones["Tail"].Add(
New.ShapeTracingMeta(