Feature #21808 » collapsible-sidebar-with-expand-on-hover-18474.patch
| app/views/layouts/base.html.erb (working copy) | ||
|---|---|---|
| 99 | 99 |
<% end %> |
| 100 | 100 |
</div> |
| 101 | 101 | |
| 102 |
<div id="main" class="<%= sidebar_content? ? '' : 'nosidebar' %>"> |
|
| 102 |
<div id="main" class="<%= sidebar_content? ? 'collapsiblesidebar' : 'nosidebar' %>"> |
|
| 103 |
<%= javascript_tag "$('#main.collapsiblesidebar').collapsibleSidebar();" if sidebar_content? %>
|
|
| 103 | 104 |
<div id="sidebar"> |
| 105 |
<% if sidebar_content? %> |
|
| 106 |
<div id="sidebar-switch-panel" style="visibility: hidden;"> |
|
| 107 |
<a id="sidebar-switch-button" href="#">»</a> |
|
| 108 |
</div> |
|
| 109 |
<%= javascript_tag "$('#sidebar-switch-panel').css('visibility', 'visible');" %>
|
|
| 110 |
<% end %> |
|
| 104 | 111 |
<%= yield :sidebar %> |
| 105 | 112 |
<%= view_layouts_base_sidebar_hook_response %> |
| 106 | 113 |
</div> |
| public/javascripts/application.js (working copy) | ||
|---|---|---|
| 1051 | 1051 |
tribute.attach(element); |
| 1052 | 1052 |
} |
| 1053 | 1053 | |
| 1054 |
// collapsible sidebar jQuery plugin |
|
| 1055 |
(function($) {
|
|
| 1056 |
// main container this is applied to |
|
| 1057 |
var main; |
|
| 1058 |
// triggers show/hide |
|
| 1059 |
var button; |
|
| 1060 |
// the key to use in local storage |
|
| 1061 |
// this will later be expanded using the current controller and action to |
|
| 1062 |
// allow for different sidebar states for different pages |
|
| 1063 |
var localStorageKey = 'redmine-sidebar-state'; |
|
| 1064 |
// true if local storage is available |
|
| 1065 |
var canUseLocalStorage = function(){
|
|
| 1066 |
try {
|
|
| 1067 |
if('localStorage' in window){
|
|
| 1068 |
localStorage.setItem('redmine.test.storage', 'ok');
|
|
| 1069 |
var item = localStorage.getItem('redmine.test.storage');
|
|
| 1070 |
localStorage.removeItem('redmine.test.storage');
|
|
| 1071 |
if(item === 'ok') return true; |
|
| 1072 |
} |
|
| 1073 |
} catch (err) {}
|
|
| 1074 |
return false; |
|
| 1075 |
}(); |
|
| 1076 |
// function to set current sidebar state |
|
| 1077 |
var setState = function(state){
|
|
| 1078 |
if(canUseLocalStorage){
|
|
| 1079 |
localStorage.setItem(localStorageKey, state); |
|
| 1080 |
} |
|
| 1081 |
}; |
|
| 1082 |
var applyState = function(){
|
|
| 1083 |
if(main.hasClass('collapsedsidebar')){
|
|
| 1084 |
button.html("«");
|
|
| 1085 |
setState('hidden');
|
|
| 1086 |
} else {
|
|
| 1087 |
button.html("»");
|
|
| 1088 |
setState('visible');
|
|
| 1089 |
} |
|
| 1090 |
}; |
|
| 1091 |
var setupToggleButton = function(){
|
|
| 1092 |
button = $('#sidebar-switch-button');
|
|
| 1093 |
button.click(function(e){
|
|
| 1094 |
main.addClass("animate");
|
|
| 1095 |
main.toggleClass('collapsedsidebar');
|
|
| 1096 |
applyState(); |
|
| 1097 |
e.preventDefault(); |
|
| 1098 |
return false; |
|
| 1099 |
}); |
|
| 1100 |
applyState(); |
|
| 1101 |
}; |
|
| 1102 |
$.fn.collapsibleSidebar = function() {
|
|
| 1103 |
main = this; |
|
| 1104 |
// determine previously stored sidebar state for this page |
|
| 1105 |
if(canUseLocalStorage) {
|
|
| 1106 |
// determine current controller/action pair and use them as storage key |
|
| 1107 |
var bodyClass = $('body').attr('class');
|
|
| 1108 |
if(bodyClass){
|
|
| 1109 |
try {
|
|
| 1110 |
localStorageKey += '-' + bodyClass.split(/\s+/).filter(function(s){
|
|
| 1111 |
return s.match(/(action|controller)-.*/); |
|
| 1112 |
}).sort().join('-');
|
|
| 1113 |
} catch(e) {
|
|
| 1114 |
// in case of error (probably IE8), continue with the unmodified key |
|
| 1115 |
} |
|
| 1116 |
} |
|
| 1117 |
var storedState = localStorage.getItem(localStorageKey); |
|
| 1118 |
main.toggleClass('collapsedsidebar', storedState === 'hidden');
|
|
| 1119 |
} |
|
| 1120 |
// draw the toggle button once the DOM is complete |
|
| 1121 |
$(document).ready(setupToggleButton); |
|
| 1122 |
}; |
|
| 1123 |
}(jQuery)); |
|
| 1054 | 1124 | |
| 1055 | 1125 |
$(document).ready(setupAjaxIndicator); |
| 1056 | 1126 |
$(document).ready(hideOnLoad); |
| public/stylesheets/application.css (working copy) | ||
|---|---|---|
| 84 | 84 |
#admin-menu li {margin: 0; padding: 0 0 6px 0; list-style-type:none;}
|
| 85 | 85 | |
| 86 | 86 |
#main {flex-grow: 2; display: flex; flex-direction: row-reverse;}
|
| 87 |
#main.nosidebar #sidebar {display: none;}
|
|
| 87 | 88 | |
| 88 |
#sidebar{ flex-shrink: 0; padding-left: 20px; background: #EEEEEE; border-left: 1px solid #ddd}
|
|
| 89 |
#sidebar{ flex-shrink: 0; padding-left: 20px; background: #EEEEEE; border-left: 1px solid #ddd; z-index: 1;}
|
|
| 89 | 90 |
@media screen and (min-width: 0px) and (max-width: 1089px) {#sidebar{width: 22%;}}
|
| 90 | 91 |
@media screen and (min-width: 1090px) and (max-width: 1279px) {#sidebar{width: 240px;}}
|
| 91 | 92 |
@media screen and (min-width: 1280px) and (max-width: 1599px) {#sidebar{width: 280px;}}
|
| 92 | 93 |
@media screen and (min-width: 1600px) and (max-width: 1919px) {#sidebar{width: 320px;}}
|
| 93 | 94 |
@media screen and (min-width: 1920px) and (max-width: 2559px) {#sidebar{width: 360px;}}
|
| 94 | 95 |
@media screen and (min-width: 2560px) {#sidebar{width: 380px;}}
|
| 95 |
#sidebar h3{ font-size: 14px; margin-top:14px; color: #666; }
|
|
| 96 |
#sidebar h3 { font-size: 14px; margin-top:14px; color: #666; }
|
|
| 97 |
#sidebar h3:first-of-type { margin-top: 4px ; }
|
|
| 96 | 98 |
#sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
|
| 97 | 99 |
* html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
|
| 98 | 100 |
#sidebar .contextual { margin-right: 1em; }
|
| ... | ... | |
| 107 | 109 |
html>body #content { min-height: 600px; }
|
| 108 | 110 |
* html body #content { height: 600px; } /* IE */
|
| 109 | 111 | |
| 110 |
#main.nosidebar #sidebar{ display: none; }
|
|
| 112 |
#main.collapsedsidebar #sidebar { display: block; width: 0px; }
|
|
| 113 |
#main.collapsedsidebar #sidebar:hover { width: 22%; position: absolute; height:100%; }
|
|
| 114 |
#main.collapsedsidebar #sidebar:hover ~ #content { padding-right: 30px; }
|
|
| 115 |
#sidebar-switch-panel {
|
|
| 116 |
font-size: 20px; |
|
| 117 |
width: 100%; |
|
| 118 |
color: #666; |
|
| 119 |
display: block; |
|
| 120 |
margin-left: -21px; |
|
| 121 |
padding-right: 21px; |
|
| 122 |
border-bottom: 1px solid #ddd; |
|
| 123 |
padding-left: 4px; |
|
| 124 |
} |
|
| 111 | 125 | |
| 126 |
#sidebar-switch-panel:hover {
|
|
| 127 |
background-color: #e6e6e6; |
|
| 128 |
} |
|
| 129 | ||
| 130 |
#sidebar-switch-button {
|
|
| 131 |
color: #666; |
|
| 132 |
width: 100%; |
|
| 133 |
display: block; |
|
| 134 |
} |
|
| 135 | ||
| 136 |
#sidebar-switch-button:hover {
|
|
| 137 |
text-decoration: none; |
|
| 138 |
} |
|
| 139 | ||
| 112 | 140 |
#footer {clear: both; border-top: 1px solid #bbb; font-size: 0.9em; color: #aaa; padding: 5px; text-align:center; background:#fff;}
|
| 113 | 141 | |
| 114 | 142 |
#login-form {margin:5em auto 2em auto; padding:20px; width:340px; border:1px solid #FDBF3B; background-color:#FFEBC1; border-radius:4px; box-sizing: border-box;}
|