Project

General

Profile

Patch #21808 » collapsible-sidebar-with-expand-on-hover-for_Redmine_4_2_1.patch

Marian Liviriniu, 2022-03-22 08:22

View differences:

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="#">&raquo;</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("&laquo;");
1085
      setState('hidden');
1086
    } else {
1087
      button.html("&raquo;");
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 Mon Mar 21 22:01:41 2022
94
#main.nosidebar #sidebar {display: none;}
95
#sidebar{ flex-shrink: 0; padding-left: 20px; padding-right: 8px; background: #EEEEEE; border-left: 1px solid #ddd}
......
96
#sidebar{ flex-shrink: 0; padding-left: 20px; padding-right: 8px; background: #EEEEEE; border-left: 1px solid #ddd; z-index: 1;}
......
102
#sidebar h3{ font-size: 14px; margin-top:14px; color: #666;  }
......
103
#sidebar h3 { font-size: 14px; margin-top:14px; color: #666;  }
104
#sidebar h3:first-of-type { margin-top: 4px ; }
......
119
#main.nosidebar #sidebar{ display: none; }
......
121
#main.collapsedsidebar #sidebar { display: block; width: 0px !important; position: absolute; box-sizing: border-box; height: 100%; overflow: hidden; transition: 0.35s; }
122
#main.collapsedsidebar #sidebar:hover { width: 22% !important; }
123
#main:not(.collapsedsidebar) #content { margin-right: 0; }
......
125
#main.collapsedsidebar #sidebar > :not(#sidebar-switch-panel) {
126
    visibility: hidden;
127
}
128

  
129
#main.collapsedsidebar #sidebar:hover > :not(#sidebar-switch-panel) {
130
    visibility: visible;
131
}
132

  
133
body div#content {
134
    margin-right: 30px;
135
}
136

  
137
body #main {
138
    position: relative;
139
}
140

  
141
#sidebar-switch-panel {
142
  position: relative;
143
  left: 6px;
144
  font-size: 20px;
145
  width: 100% !important;
146
  color: #666;
147
  display: block;
148
  margin-left: -21px;
149
  padding-right: 21px;
150
  border-bottom: 1px solid #ddd;
151
  padding-left: 4px;
152
}
153

  
154
#sidebar-switch-panel:hover {
155
  background-color: #e6e6e6;
156
}
157

  
158
#sidebar-switch-button {
159
  color: #666;
160
  width: 100% !important;
161
  display: block;
162
}
163

  
164
#sidebar-switch-button:hover {
165
  text-decoration: none;
166
}
167

  
(18-18/18)