new-style lozenge tree view
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/commit/2ef411f4 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/tree/2ef411f4 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-ui/diff/2ef411f4 Branch: refs/heads/0.6.0 Commit: 2ef411f4a28f8c79d50db50eda051c798c05ee66 Parents: a60c8eb Author: Alex Heneveld <[email protected]> Authored: Mon Sep 16 15:23:36 2013 +0100 Committer: Alex Heneveld <[email protected]> Committed: Wed Sep 18 09:30:06 2013 +0100 ---------------------------------------------------------------------- usage/jsgui/src/main/webapp/assets/css/base.css | 94 ++++++++++++- .../webapp/assets/js/view/application-tree.js | 131 +++++++++++++++---- .../main/webapp/assets/tpl/apps/tree-item.html | 40 +++++- 3 files changed, 241 insertions(+), 24 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/2ef411f4/usage/jsgui/src/main/webapp/assets/css/base.css ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/css/base.css b/usage/jsgui/src/main/webapp/assets/css/base.css index 5a55f55..9e33d3e 100644 --- a/usage/jsgui/src/main/webapp/assets/css/base.css +++ b/usage/jsgui/src/main/webapp/assets/css/base.css @@ -533,9 +533,12 @@ ol.tree { cursor: hand; cursor: pointer; } .entity_tree_node:hover { - text-decoration: underline; cursor: hand; cursor: pointer; } +.entity_tree_node a:hover { + color: #54932b !important; + text-decoration: none; +} .entity_tree_node.active { font-weight: bold; } @@ -550,6 +553,95 @@ line-height: 18px; width: auto; } +/* new lozenge-style tree-list */ +.navbar_main_wrapper .treeloz { + padding: 12px 0px 20px 0px; +} +.navbar_main .treeloz { + padding: 0px 0px 0px 0px; +} +.lozenge-app-tree-wrapper { + min-width: 100%; + min-height: 240px; + padding-bottom: 60px; /* for popup menu */ + margin-top: -2px; + position: relative; + float: left; +} + +.tree-box { + border: 1px solid #AAA; + border-right: 0px; + margin-top: 3px; + padding-top: 2px; + background-color: #EAECEA; +} +.tree-box.outer { + margin-left: 12px; + margin-right: 0px; + margin-bottom: 9px; + -webkit-border-radius: 4px 0 0 4px !important; + -moz-border-radius: 4px 0 0 4px !important; + border-radius: 4px 0 0 4px !important; + padding-left: 4px; + padding-bottom: 4px; +} +.tree-box.inner { + margin-bottom: 2px; + border: 1px solid #BBB; + border-right: 0px; + -webkit-border-radius: 3px 0 0 3px !important; + -moz-border-radius: 3px 0 0 3px !important; + border-radius: 3px 0 0 3px !important; + padding-left: 6px; + padding-bottom: 2px; +} +.tree-box.inner.depth-odd { + background-color: #D8DAD8; +} +.tree-box.inner.depth-even { + background-color: #EAECEA; +} +.tree-node { + position: relative; + padding-top: 2px; + padding-bottom: 1px; + padding-right: 8px; +} +.light-popup { + display: none; + position: relative; + float: left; + z-index: 1; +} +.toggler-icon .light-popup { + padding-top: 16px; +} +.light-popup-body { + padding: 3px 0px; + background-color: #606060; + color: #CDC; + font-weight: 300; + font-size: 85%; + border: 1px dotted #CDC; + -webkit-border-radius: 2px 2px 2px 2px !important; + -moz-border-radius: 2px 2px 2px 2px !important; + border-radius: 2px 2px 2px 2px !important; +} +.light-popup-menu-item { + color: #D0D4D0; +} +.light-popup-menu-item.tr-default { + color: #E0E4E0; +} +.light-popup-menu-item { + padding: 1px 6px; +} +.light-popup-menu-item:hover { + background-color: #58AA33; + color: #000; +} + .app-summary .inforow > div { display: inline-block; } .app-summary .inforow .info-name-value > div { display: inline-block; } .app-summary .inforow .info-name-value .name { font-weight: 700; width: 120px; padding-right: 12px;} http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/2ef411f4/usage/jsgui/src/main/webapp/assets/js/view/application-tree.js ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/js/view/application-tree.js b/usage/jsgui/src/main/webapp/assets/js/view/application-tree.js index 9c19997..61ea360 100644 --- a/usage/jsgui/src/main/webapp/assets/js/view/application-tree.js +++ b/usage/jsgui/src/main/webapp/assets/js/view/application-tree.js @@ -17,7 +17,8 @@ define([ template: treeViewTemplate, events:{ - 'click .name.entity':'displayEntity' + 'click span.entity_tree_node .tree-change':'treeChange', + 'click span.entity_tree_node':'displayEntity' }, initialize:function () { @@ -39,10 +40,10 @@ define([ that.$el.append(_.template(TreeEmptyHtml)) } else { that.$el.append( - '<div class="navbar_main_wrapper treelist cssninja">'+ - '<div id="tree-list" class="navbar_main treelist">'+ - '<ol class="tree applications"/>'); - var node = $('ol.tree.applications', that.$el); + '<div class="navbar_main_wrapper treeloz">'+ + '<div id="tree-list" class="navbar_main treeloz">'+ + '<div class="lozenge-app-tree-wrapper">'); + var node = $('div.lozenge-app-tree-wrapper', that.$el); this.collection.each(function (app) { node.append(that.buildTree(app)) @@ -76,59 +77,96 @@ define([ $template = $(this.template({ id:application.get("id"), type:"application", + hasChildren: application.hasChildren(), parentApp:application.get("id"), - displayName:application.get("name") + displayName:application.get("name"), + depth: 0 })), - treeFromEntity = function (entity) { + treeFromEntity = function (entity, depth) { var $entityTpl if (entity.hasChildren()) { $entityTpl = $(that.template({ id:entity.get("id"), type:"entity", + hasChildren: true, parentApp:application.get("id"), - displayName:entity.getDisplayName() + displayName:entity.getDisplayName(), + depth: depth })) - var $parentTpl = $entityTpl.find("ol.tree") + var $parentTpl = $entityTpl.find("#children") _.each(entity.get("children"), function (childEntity) { - $parentTpl.append(treeFromEntity(new AppTree.Model(childEntity))) + $parentTpl.append(treeFromEntity(new AppTree.Model(childEntity), depth+1)) }) } else { $entityTpl = $(that.template({ id:entity.get("id"), type:"leaf", + hasChildren: false, parentApp:application.get("id"), - displayName:entity.getDisplayName() + displayName:entity.getDisplayName(), + depth: depth })) } return $entityTpl } // start rendering from initial children of the application - var $tree = $template.find("ol.tree") + var $tree = $template.find("#children") _.each(application.get("children"), function (entity) { - $tree.append(treeFromEntity(new AppTree.Model(entity))) + $tree.append(treeFromEntity(new AppTree.Model(entity), 1)) }) $('a', $tree).click(function(e) { e.preventDefault(); }) + + // show the "light-popup" (expand / expand all / etc) menu + // if user hovers for 500ms. surprising there is no option for this. + var hoverTimer; + $('.light-popup', $template).parent().parent().hover( + function (parent) { + if (hoverTimer!=null) { + clearTimeout(hoverTimer); + hoverTimer = null; + } + hoverTimer = setTimeout(function() { + var menu = $(parent.currentTarget).find('.light-popup') + menu.show() + }, 500); + }, + function (parent) { + if (hoverTimer!=null) { + clearTimeout(hoverTimer); + hoverTimer = null; + } + var menu = $(parent.currentTarget).find('.light-popup') + menu.hide() + $('.light-popup').hide() + }) return $template }, displayEntity: function(event) { event.preventDefault(); - var entityId = $(event.currentTarget).attr("id"), + var nodeSpan = $(event.currentTarget) + var nodeA = $(event.currentTarget).children('a').first() + var entityId = nodeSpan.attr("id"), stateId = entityId, - href = event.target.getAttribute('href'), + href = nodeA.attr('href'), tab = (this.detailsView) ? this.detailsView.$el.find(".tab-pane.active").attr("id") : undefined; - if (tab) { - href = href+"/"+tab - stateId = entityId+"/"+tab - this.preselectTab(tab) + if (href) { + if (tab) { + href = href+"/"+tab + stateId = entityId+"/"+tab + this.preselectTab(tab) + } + window.history.pushState(stateId, "", href) + this.displayEntityId(entityId, $(event.currentTarget).data("parent-app")); + } else { + log("no a.href in clicked target") + log(nodeSpan) } - window.history.pushState(stateId, "", href) - this.displayEntityId(entityId, $(event.currentTarget).data("parent-app")); }, displayEntityId:function (id, appName) { @@ -171,6 +209,53 @@ define([ $("div#details").html(notFoundTemplate({"id": id})); }, + treeChange: function(event) { + log("changing") + log(event) + var $target = $(event.currentTarget); + var $treeBox = $target.closest('.tree-box'); + if ($target.hasClass('tr-expand')) { + this.showChildrenOf($treeBox, false) + } else if ($target.hasClass('tr-expand-all')) { + this.showChildrenOf($treeBox, true) + } else if ($target.hasClass('tr-collapse')) { + this.hideChildrenOf($treeBox, false) + } else if ($target.hasClass('tr-collapse-all')) { + this.hideChildrenOf($treeBox, true) + } else { + // default - toggle + if ($treeBox.children('#children').is(':visible')) { + this.hideChildrenOf($treeBox, false) + } else { + this.showChildrenOf($treeBox, false) + } + } + // hide the popup menu + $('.light-popup').hide() + // don't let other events interfere + return false + }, + hideChildrenOf: function($treeBox, recurse) { + var that = this; + $treeBox.children('#children').slideUp(300) + $treeBox.children('.tree-node').find('.tree-node-state').removeClass('icon-chevron-down').addClass('icon-chevron-right') + if (recurse) { + $treeBox.children('#children').children().each(function (index, childBox) { + that.hideChildrenOf($(childBox), recurse) + }) + } + }, + showChildrenOf: function($treeBox, recurse) { + var that = this; + $treeBox.children('#children').slideDown(300) + $treeBox.children('.tree-node').find('.tree-node-state').removeClass('icon-chevron-right').addClass('icon-chevron-down') + if (recurse) { + $treeBox.children('#children').children().each(function (index, childBox) { + that.showChildrenOf($(childBox), recurse) + }) + } + }, + /** * Causes the tab with the given name to be selected automatically when * the view is next rendered. @@ -205,7 +290,9 @@ define([ else id = this.selectedEntityId $("span.entity_tree_node").removeClass("active") if (id) { - $("span.entity_tree_node#"+id).addClass("active") + var $selectedNode = $("span.entity_tree_node#"+id); + this.showChildrenOf($selectedNode.parents('#app-tree .tree-box'), false) + $selectedNode.addClass("active") } } }) http://git-wip-us.apache.org/repos/asf/brooklyn-ui/blob/2ef411f4/usage/jsgui/src/main/webapp/assets/tpl/apps/tree-item.html ---------------------------------------------------------------------- diff --git a/usage/jsgui/src/main/webapp/assets/tpl/apps/tree-item.html b/usage/jsgui/src/main/webapp/assets/tpl/apps/tree-item.html index 64d6d17..f29c96b 100644 --- a/usage/jsgui/src/main/webapp/assets/tpl/apps/tree-item.html +++ b/usage/jsgui/src/main/webapp/assets/tpl/apps/tree-item.html @@ -1,3 +1,40 @@ +<div class="toggler-group tree-box <%= depth==0 ? "outer" : "inner "+(depth%2==1 ? "depth-odd" : "depth-even") %>"> + <div class="tree-node"> + <span class="entity_tree_node name entity" id="<%= id %>" data-entity-type="<%= type %>" data-parent-app="<%= parentApp %>"> + <a href="#/v1/applications/<%= parentApp %>/entities/<%= id %>"> + + <div style="min-width: 16px; max-width: 16px; max-height: 16px; display: inline-block; margin-right: 6px;"> + <% if (hasChildren) { %> + <div style="position: absolute; left: 3px; top: 3px;"> + <div class="toggler-icon icon-chevron-right tree-node-state tree-change"> + <div class="light-popup"> + <div class="light-popup-body"> + <div class="light-popup-menu-item tree-change tr-toggle tr-default">Toggle Children</div> + <div class="light-popup-menu-item tree-change tr-expand">Expand</div> + <div class="light-popup-menu-item tree-change tr-expand-all">Expand All</div> + <div class="light-popup-menu-item tree-change tr-collapse">Collapse</div> + <div class="light-popup-menu-item tree-change tr-collapse-all">Collapse All</div> + </div> + </div> + </div> + </div> + <% } else { %> + <div style="position: absolute; left: 39px; top: 24px;"> + + </div> + <% } %> + </div><%= + + displayName + + %></a> + </span> + </div> + <div id="children" class="toggler-target hide"> + </div> +</div> + +<!-- <li class="<%= type %>"> <% if (type != "leaf") { %> <label> <% } %> <span id="<%= id %>" class="name entity entity_tree_node<% @@ -5,7 +42,7 @@ if (type == "application") { %> application<% } %>" data-entity-type="<%= type %>" data-parent-app="<%= parentApp %>"> <a href="#/v1/applications/<%= parentApp %>/entities/<%= id %>"> - <%= displayName %> + </a> </span> <% if (type != "leaf") { %> </label> <% } %> @@ -14,3 +51,4 @@ <ol class="tree entities"/> <% } %> </li> + -->
