From 6dc7f927bd9437c89ca0ffb976a0a8e4ecee674e Mon Sep 17 00:00:00 2001 From: Sebastien Ros Date: Sat, 12 Mar 2011 16:18:33 -0800 Subject: [PATCH] Adding shape tree plus synchronization --HG-- branch : dev --- .../orchard-designertools-shapetracing.js | 114 ++++++++++++++++-- .../Services/ShapeTracingFactory.cs | 6 + .../orchard-designertools-shapetracing.css | 90 +++++++++++++- .../Views/ShapeTracingWrapper.cshtml | 2 +- 4 files changed, 197 insertions(+), 15 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Scripts/orchard-designertools-shapetracing.js b/src/Orchard.Web/Modules/Orchard.DesignerTools/Scripts/orchard-designertools-shapetracing.js index 11c11dec1..a1e0b1080 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Scripts/orchard-designertools-shapetracing.js +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Scripts/orchard-designertools-shapetracing.js @@ -6,7 +6,10 @@ '
' + '
' + '
' + - '
' + + '
' + + '
' + + '
foo
' + + '
' + '' + '
' ).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 = $(''); 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 = $(''); + 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 = $('
  • '); - 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('
    ' + text + '
    '); var list = $(''); 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); diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ShapeTracingFactory.cs b/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ShapeTracingFactory.cs index 28074bc10..90c9b3650 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ShapeTracingFactory.cs +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Services/ShapeTracingFactory.cs @@ -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; + } } diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Styles/orchard-designertools-shapetracing.css b/src/Orchard.Web/Modules/Orchard.DesignerTools/Styles/orchard-designertools-shapetracing.css index ae2ecbbf7..48ccbdf3a 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Styles/orchard-designertools-shapetracing.css +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Styles/orchard-designertools-shapetracing.css @@ -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); } diff --git a/src/Orchard.Web/Modules/Orchard.DesignerTools/Views/ShapeTracingWrapper.cshtml b/src/Orchard.Web/Modules/Orchard.DesignerTools/Views/ShapeTracingWrapper.cshtml index 8aa2de442..09f2f63b6 100644 --- a/src/Orchard.Web/Modules/Orchard.DesignerTools/Views/ShapeTracingWrapper.cshtml +++ b/src/Orchard.Web/Modules/Orchard.DesignerTools/Views/ShapeTracingWrapper.cshtml @@ -21,7 +21,7 @@ Script.Include("CodeMirror/htmlmixed.js"); } -@Display(Model.Metadata.ChildContent) +@Display(Model.Metadata.ChildContent) @{ Layout.Zones["Tail"].Add( New.ShapeTracingMeta(