From 686f1019256822f434aa7cd55a4425758d44016f Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Fri, 13 May 2011 13:30:49 +1200 Subject: [PATCH] ENHANCEMENT Toggleable panels in CMS --- admin/code/LeftAndMain.php | 4 + admin/css/layout.css | 7 +- admin/css/screen.css | 49 +++++--- admin/javascript/LeftAndMain.Panel.js | 108 ++++++++++++++++++ admin/javascript/LeftAndMain.js | 27 +++-- admin/scss/_menu.scss | 39 +++++++ admin/scss/_style.scss | 59 +++++++++- admin/templates/Includes/LeftAndMain_Menu.ss | 96 ++++++++-------- .../templates/Includes/ModelAdmin_Content.ss | 53 +++++---- 9 files changed, 342 insertions(+), 100 deletions(-) create mode 100644 admin/javascript/LeftAndMain.Panel.js diff --git a/admin/code/LeftAndMain.php b/admin/code/LeftAndMain.php index 20cb96b4c58..df50f0fd569 100755 --- a/admin/code/LeftAndMain.php +++ b/admin/code/LeftAndMain.php @@ -254,8 +254,10 @@ function init() { Requirements::css(THIRDPARTY_DIR . '/jstree/themes/apple/style.css'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.js'); + Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Panel.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Tree.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.EditForm.js'); + Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Menu.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.AddForm.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Preview.js'); Requirements::javascript(SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.BatchActions.js'); @@ -310,8 +312,10 @@ function init() { 'leftandmain.js', array( SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.js', + SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Panel.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Tree.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.EditForm.js', + SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Menu.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.AddForm.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.Preview.js', SAPPHIRE_ADMIN_DIR . '/javascript/LeftAndMain.BatchActions.js', diff --git a/admin/css/layout.css b/admin/css/layout.css index 4a41361477b..bae19c12014 100755 --- a/admin/css/layout.css +++ b/admin/css/layout.css @@ -24,11 +24,14 @@ html, body { width: 100%; height: 100%; padding: 0; margin: 0; overflow: hidden; .cms-container { height: 100%; } .cms-menu { width: 250px; overflow: auto; } +.cms-menu .cms-panel-content { width: 250px; } +.cms-menu.collapsed { width: 40px; } .cms-preview, .cms-menu, .cms-content, .cms-content-header, .cms-content-tools, .cms-content-form { display: -moz-inline-box; -moz-box-orient: vertical; display: inline-block; vertical-align: middle; *vertical-align: auto; } .cms-preview, .cms-menu, .cms-content, .cms-content-header, .cms-content-tools, .cms-content-form { *display: inline; } -.cms-content-tools { width: 230px; padding: 10px; overflow: auto; } +.cms-content-tools { width: 230px; overflow: auto; } +.cms-content-tools .cms-panel-header, .cms-content-tools .cms-panel-content { padding: 10px; } .cms-content-form { overflow: auto; } @@ -38,6 +41,8 @@ html, body { width: 100%; height: 100%; padding: 0; margin: 0; overflow: hidden; .cms-content-actions { padding: 10px; } +.cms-header { padding: 7px 0 7px 7px; } + .cms-logo { height: 30px; overflow: hidden; vertical-align: middle; } .cms-login-status { height: 30px; overflow: hidden; vertical-align: middle; } diff --git a/admin/css/screen.css b/admin/css/screen.css index 11922985789..3d19ab669b0 100755 --- a/admin/css/screen.css +++ b/admin/css/screen.css @@ -137,20 +137,27 @@ li.jstree-closed > ul { display: none; } @charset "UTF-8"; .cms-menu { z-index: 10; background: #c6d7df; border-right: 1px solid #8c99a1; width: 250px; overflow: auto; -moz-box-shadow: rgba(107, 120, 123, 0.5) 2px 0 6px 0; -webkit-box-shadow: rgba(107, 120, 123, 0.5) 2px 0 6px 0; -o-box-shadow: rgba(107, 120, 123, 0.5) 2px 0 6px 0; box-shadow: rgba(107, 120, 123, 0.5) 2px 0 6px 0; } .cms-menu a { text-decoration: none; } - -.cms-menu-list li a { display: block; height: 30px; line-height: 30px; vertical-align: middle; font-size: 13px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-shadow: #ced7dc 1px 1px 0; color: #1f1f1f; padding: 5px; background-color: #b0bec7; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #b0bec7), color-stop(100%, #98aab6)); background-image: -moz-linear-gradient(top, #b0bec7 0%, #98aab6 100%); background-image: linear-gradient(top, #b0bec7 0%, #98aab6 100%); border-top: 1px solid #ced7dc; border-bottom: 1px solid #748d9d; } -.cms-menu-list li a:hover { text-decoration: none; background-color: #b6c3cb; border-bottom: 1px solid #8399a7; color: #2c2c2c; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #bfcad2), color-stop(100%, #b0bec7)); background-image: -moz-linear-gradient(top, #bfcad2 0%, #b0bec7 100%); background-image: linear-gradient(top, #bfcad2 0%, #b0bec7 100%); } -.cms-menu-list li a:focus { border-top: 1px solid #a1b2bc; text-decoration: none; background-color: #a1b2bc; color: #393939; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #92a5b2), color-stop(100%, #a1b2bc)); background-image: -moz-linear-gradient(top, #92a5b2 0%, #a1b2bc 100%); background-image: linear-gradient(top, #92a5b2 0%, #a1b2bc 100%); } -.cms-menu-list li a .icon { display: block; float: left; margin-right: 4px; background: url('../images/icons-32.png') no-repeat; width: 32px; height: 32px; overflow: hidden; background-position: 0px 0px; } -.cms-menu-list li a .text { display: block; } -.cms-menu-list li.current a { color: white; text-shadow: #1e5270 0 -1px 0; border-top: 1px solid #55a4d2; border-bottom: 1px solid #1e5270; background-color: #338dc1; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #338dc1), color-stop(100%, #287099)); background-image: -moz-linear-gradient(top, #338dc1 0%, #287099 100%); background-image: linear-gradient(top, #338dc1 0%, #287099 100%); } -.cms-menu-list li.current ul { border-top: 1px solid #1e5270; } -.cms-menu-list li.current li { background-color: #287099; } -.cms-menu-list li.current li a { font-size: 11px; padding: 0 10px 0 36px; height: 32px; line-height: 32px; color: #e2f0f7; background: none; border-top: 1px solid #338dc1; border-bottom: 1px solid #1e5270; } -.cms-menu-list li.current li a.current, .cms-menu-list li.current li a:hover { background: #2e7ead; border-top: 1px solid #2e7ead; color: white; } -.cms-menu-list li.current li a:focus { background: #236184; border-top: 1px solid #1e5270; color: white; } -.cms-menu-list li.current li.current a { font-weight: bold; color: white; } -.cms-menu-list li.current li.first a { border-top: none; } +.cms-menu.collapsed { cursor: auto; } +.cms-menu.collapsed .cms-menu-list li span.text { display: none; } +.cms-menu.collapsed .cms-menu-list li ul { display: none; } +.cms-menu.collapsed.cms-panel .cms-panel-content { display: block; } + +.cms-menu-list li { background-color: #b0bfc6; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #b0bfc6), color-stop(100%, #758f9b)); background-image: -moz-linear-gradient(top, #b0bfc6 0%, #758f9b 100%); background-image: linear-gradient(top, #b0bfc6 0%, #758f9b 100%); border-bottom: 1px solid #aaaaaa; } +.cms-menu-list li a { display: block; height: 32px; vertical-align: middle; font-size: 14px; text-shadow: #aaaaaa 1px 1px 1px; color: #333333; padding: 5px; } +.cms-menu-list li a .icon { display: block; float: left; margin-right: 5px; background: url('../images/icons-32.png?1305180670') no-repeat; width: 32px; height: 32px; overflow: hidden; background-position: 0px 0px; } +.cms-menu-list li a .text { display: block; padding-top: 10px; } +.cms-menu-list li.current { background-color: #338dc1; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #338dc1), color-stop(100%, #1e5270)); background-image: -moz-linear-gradient(top, #338dc1 0%, #1e5270 100%); background-image: linear-gradient(top, #338dc1 0%, #1e5270 100%); } +.cms-menu-list li.current li { background-color: #2e7ead; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #2e7ead), color-stop(100%, #287099)); background-image: -moz-linear-gradient(top, #2e7ead 0%, #287099 100%); background-image: linear-gradient(top, #2e7ead 0%, #287099 100%); } +.cms-menu-list li.current a { color: white; text-shadow: #333333 1px 1px 1px; } +.cms-menu-list li li:first { -moz-box-shadow: #333333 0 4px 4px 0; -webkit-box-shadow: #333333 0 4px 4px 0; -o-box-shadow: #333333 0 4px 4px 0; box-shadow: #333333 0 4px 4px 0; } +.cms-menu-list li li a { font-size: 12px; text-shadow: #333333 1px 1px 1px; margin: 0; padding-left: 30px; color: white; } +.cms-menu-list li li.current a { font-weight: bold; } +.cms-menu-list li#Menu-CMSMain a .icon { background-position: 0px 0px; } +.cms-menu-list li#Menu-CMSMain.current a .icon, .cms-menu-list li#Menu-CMSMain a:hover .icon { background-position: -32px 0px; } +.cms-menu-list li#Menu-AssetAdmin a .icon { background-position: 0px -32px; } +.cms-menu-list li#Menu-AssetAdmin.current a .icon, .cms-menu-list li#Menu-AssetAdmin a:hover .icon { background-position: -32px -32px; } +.cms-menu-list.collapsed li .text { display: none; } +.cms-menu-list.collapsed li > li { display: none; } /** This file defines common styles for form elements used throughout the CMS interface. It is an addition to the base styles defined in sapphire/css/Form.css. */ .field { display: block; padding: 10px 0; border-bottom: 1px solid rgba(201, 205, 206, 0.8); } @@ -225,7 +232,7 @@ strong { font-weight: bold; } .ui-tabs .cms-content-header .ui-state-default, .ui-tabs .cms-content-header .ui-widget-content .ui-state-default, .ui-tabs .cms-content-header .ui-widget-header .ui-state-default { background-color: #feffff; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #feffff), color-stop(100%, #d6d9da)); background-image: -moz-linear-gradient(top, #feffff 0%, #d6d9da 100%); background-image: linear-gradient(top, #feffff 0%, #d6d9da 100%); } .ui-tabs .cms-content-header .ui-state-active, .ui-tabs .cms-content-header .ui-widget-content .ui-state-active, .ui-tabs .cms-content-header .ui-widget-header .ui-state-active { background: #eceff1; } -.cms-content-tools { background-color: #dde3e6; padding: 10px; width: 230px; overflow: auto; } +.cms-content-tools { background-color: #dce3e6; } /** ------------------------------------------------------- Top Left Header and logo area -------------------------------------------------------- */ .cms-header { background-color: #00111d; position: relative; padding: 16px 8px 8px; line-height: 24px; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #00111d), color-stop(50%, #003050), color-stop(100%, #00111d)); background-image: -moz-linear-gradient(top, #00111d 0%, #003050 50%, #00111d 100%); background-image: linear-gradient(top, #00111d 0%, #003050 50%, #00111d 100%); } @@ -283,9 +290,17 @@ form.member-profile-form .formattingHelpText { margin: 5px auto; color: #333; pa form.member-profile-form .formattingHelpText ul { padding: 0; } form.member-profile-form .formattingHelpText li { font-size: 11px; color: #333; margin-bottom: 2px; } -.cms-content-form { overflow: auto; } +.cms-panel { overflow: hidden; } +.cms-panel .toggle-expand, .cms-panel .toggle-collapse { display: block; position: absolute; bottom: 0; text-align: right; background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(0%, #afbfc7), color-stop(100%, #91a7b2)); background-image: -moz-linear-gradient(top, #afbfc7 0%, #91a7b2 100%); background-image: linear-gradient(top, #afbfc7 0%, #91a7b2 100%); } +.cms-panel .toggle-expand span, .cms-panel .toggle-collapse span { display: inline-block; margin: 5px; color: #333333; font-size: 16px; } +.cms-panel .toggle-collapse { width: 100%; } +.cms-panel .toggle-expand { width: 40px; } +.cms-panel.collapsed .cms-panel-content { display: none; } +.cms-panel.collapsed .cms-panel-header { -moz-transform: rotate(-90deg); -webkit-transform: rotate(-90deg); -o-transform: rotate(-90deg); transform: rotate(-90deg); position: relative; top: 100px; } + +.cms-content .cms-panel.collapsed { cursor: pointer; } -.cms-preview { background-color: #b0bec7; } +.cms-preview { background-color: #b0bfc6; } .cms-preview .cms-preview-toggle { cursor: pointer; } .cms-preview .cms-preview-toggle a { color: white; font-weight: bold; text-decoration: none; } diff --git a/admin/javascript/LeftAndMain.Panel.js b/admin/javascript/LeftAndMain.Panel.js new file mode 100644 index 00000000000..b4d12f878a7 --- /dev/null +++ b/admin/javascript/LeftAndMain.Panel.js @@ -0,0 +1,108 @@ +(function($) { + + $.entwine('ss', function($){ + + // setup jquery.entwine + $.entwine.warningLevel = $.entwine.WARN_LEVEL_BESTPRACTISE; + + /** + * Vertically collapsible panel. Generic enough to work with CMS menu as well as various "filter" panels. + * + * A panel consists of the following parts: + * - Container div: The outer element, with class ".cms-panel" + * - Header (optional) + * - Content + * - Expand and collapse toggle anchors (optional) + * + * Sample HTML: + *
+ *
your header
+ *
your content here
+ * your toggle text + * your toggle text + *
+ */ + $('.cms-panel').entwine({ + + WidthExpanded: null, + + WidthCollapsed: null, + + onmatch: function() { + if(!this.find('.cms-panel-content').length) throw new Exception('Content panel for ".cms-panel" not found'); + + // Create default controls unless they already exist + if(!this.find('.toggle-expand').length) this.append('»'); + if(!this.find('.toggle-collapse').length) this.append('«'); + + // Set panel width same as the content panel it contains. Assumes the panel has overflow: hidden. + this.setWidthExpanded(this.find('.cms-panel-content').width()); + + // Assumes the collasped width is indicated by the toggle, or by an optional collapsed view + var collapsedContent = this.find('.cms-panel-content-collapsed'); + this.setWidthCollapsed(collapsedContent.length ? collapsedContent.widht() : this.find('.toggle-expand').width()); + + this.togglePanel(!jQuery(this).hasClass('collapsed')); + + this._super(); + }, + + onclick: function(e) { + // By default, the whole collapsed area serves as a trigger + if(this.data('expandOnClick') && jQuery(this).hasClass('collapsed')) { + e.preventDefault(); + this.expandPanel(); + } + }, + + togglePanel: function(bool) { + // if((!bool && this.hasClass('collapsed')) || (bool && !this.hasClass('collapsed'))) return; + + this.toggleClass('collapsed', !bool); + var newWidth = bool ? this.getWidthExpanded() : this.getWidthCollapsed(); + + this.trigger('beforetoggle'); + this.width(newWidth); // the content panel width always stays in "expanded state" to avoid floating elements + this.find('.toggle-collapse')[bool ? 'show' : 'hide'](); + this.find('.toggle-expand')[bool ? 'hide' : 'show'](); + + // If an alternative collapsed view exists, toggle it as well + var collapsedContent = this.find('.cms-panel-content-collapsed'); + if(collapsedContent.length) { + this.find('.cms-panel-content')[bool ? 'show' : 'hide'](); + this.find('.cms-panel-content-collapsed')[bool ? 'hide' : 'show'](); + } + + this.trigger('toggle'); + }, + + expandPanel: function() { + this.togglePanel(true); + }, + + collapsePanel: function() { + this.togglePanel(false); + } + }); + + $('.cms-panel *').entwine({ + getPanel: function() { + return this.parents('.cms-panel:first'); + } + }); + + $('.cms-panel .toggle-expand').entwine({ + onclick: function(e) { + e.preventDefault(); + this.getPanel().expandPanel(); + } + }); + + $('.cms-panel .toggle-collapse').entwine({ + onclick: function(e) { + this.getPanel().collapsePanel(); + return false; + } + }); + }); +}(jQuery)); \ No newline at end of file diff --git a/admin/javascript/LeftAndMain.js b/admin/javascript/LeftAndMain.js index 16345f30938..ef57b1c2864 100755 --- a/admin/javascript/LeftAndMain.js +++ b/admin/javascript/LeftAndMain.js @@ -65,12 +65,8 @@ } // Initialize layouts, inner to outer - var doInnerLayout = function() {$('.cms-content').layout();} - var outer = $('.cms-container'); - var doOuterLayout = function() {outer.layout({resize: false});} - doInnerLayout(); - doOuterLayout(); - $(window).resize(doOuterLayout); + this.updateLayout(); + $(window).resize(function() {self.updateLayout()}); // Remove loading screen $('.ss-loading-screen').hide(); @@ -79,13 +75,15 @@ this._setupPinging(); - $('.cms-edit-form').live('loadnewpage', function() { - doInnerLayout(); - doOuterLayout(); - }); + $('.cms-edit-form').live('loadnewpage', function() {self.updateLayout()}); this._super(); }, + + updateLayout: function() { + $('.cms-content').layout(); + $('.cms-container').layout({resize: false}) + }, /** * Function: _setupPinging @@ -116,6 +114,15 @@ }, this.getPingIntervalSeconds() * 1000); } }); + + /** + * Monitor all panels for layout changes + */ + $('.LeftAndMain .cms-panel').entwine({ + ontoggle: function(e) { + this.parents('.LeftAndMain').updateLayout(); + } + }); /** * Class: .LeftAndMain :submit, .LeftAndMain button, .LeftAndMain :reset diff --git a/admin/scss/_menu.scss b/admin/scss/_menu.scss index 9d3b887923d..101b5c76c07 100755 --- a/admin/scss/_menu.scss +++ b/admin/scss/_menu.scss @@ -21,6 +21,30 @@ a { text-decoration: none; } + + .cms-panel-content { + width: 250px; // avoids floating of elements when collapsed + } + + // toggled via JS + &.collapsed { + + width: 40px; + cursor: auto; + + .cms-menu-list { + li span.text { + display: none; + } + li ul { + display: none; + } + } + + &.cms-panel .cms-panel-content { + display: block; // override panel defaults + } + } } .cms-menu-list { @@ -140,4 +164,19 @@ } } } + + li#Menu-CMSMain a .icon {@include sprite-position(1, 1);} + li#Menu-CMSMain.current a .icon, li#Menu-CMSMain a:hover .icon {@include sprite-position(2, 1);} + li#Menu-AssetAdmin a .icon {@include sprite-position(1, 2);} + li#Menu-AssetAdmin.current a .icon, li#Menu-AssetAdmin a:hover .icon {@include sprite-position(2, 2);} + + &.collapsed { + li .text { + display: none; + } + + li > li { + display: none; + } + } } \ No newline at end of file diff --git a/admin/scss/_style.scss b/admin/scss/_style.scss index 1e0fd04c03f..656e262ec1a 100755 --- a/admin/scss/_style.scss +++ b/admin/scss/_style.scss @@ -121,9 +121,13 @@ strong { .cms-content-tools { background-color: darken($color-widget-bg, 5%); - padding: 10px; width: 230px; overflow: auto; + + .cms-panel-header, + .cms-panel-content { + padding: 10px; + } } @@ -405,6 +409,59 @@ form.member-profile-form { overflow: auto; } +// ######################### Panels ######################### +.cms-panel { + + overflow: hidden; + + .toggle-expand, + .toggle-collapse { + display: block; + position: absolute; + bottom: 0; + text-align: right; + @include linear-gradient(color-stops( + darken($color-widget-bg, 20%), + darken($color-widget-bg, 30%) + )); + + span { + display: inline-block; + margin: 5px; + color: $color-text-dark; + font-size: 16px; + } + } + + .toggle-collapse { + width: 100%; + } + + .toggle-expand { + width: 40px; // will set the collapsed width + } + + &.collapsed { + + .cms-panel-content { + display: none; + } + + .cms-panel-header { + @include rotate(-90deg); + // TODO How to reflow container to correct height? + position: relative; + top: 100px; + } + } + +} + +.cms-content .cms-panel.collapsed { + cursor: pointer; +} + +// ######################### Other ######################### .cms-preview { background-color: $color-base; diff --git a/admin/templates/Includes/LeftAndMain_Menu.ss b/admin/templates/Includes/LeftAndMain_Menu.ss index da5537edd15..383488c8fb6 100755 --- a/admin/templates/Includes/LeftAndMain_Menu.ss +++ b/admin/templates/Includes/LeftAndMain_Menu.ss @@ -1,50 +1,54 @@ -
+
+ +
-
- - - + + +
+
\ No newline at end of file diff --git a/admin/templates/Includes/ModelAdmin_Content.ss b/admin/templates/Includes/ModelAdmin_Content.ss index c8643d76193..1f79725be3f 100755 --- a/admin/templates/Includes/ModelAdmin_Content.ss +++ b/admin/templates/Includes/ModelAdmin_Content.ss @@ -6,34 +6,37 @@
- -
- -
- <% if SearchClassSelector = tabs %> -
    - <% control ModelForms %> -
  • $Title
  • - <% end_control %> -
- <% end_if %> - - <% if SearchClassSelector = dropdown %> -
- Search for: - -
- <% end_if %> + + <% end_if %> + + <% if SearchClassSelector = dropdown %> +
+ Search for: + +
+ <% end_if %> - <% control ModelForms %> -
- $Content -
- <% end_control %> + <% control ModelForms %> +
+ $Content +
+ <% end_control %> +