Project

General

Profile

Feature #21808 » 0001-Collapsible-sidebar-with-expand-on-hover.patch

Marius BĂLTEANU, 2019-09-09 22:25

View differences:

app/views/layouts/base.html.erb
23 23

  
24 24
<div class="flyout-menu js-flyout-menu">
25 25

  
26

  
27 26
    <% if User.current.logged? || !Setting.login_required? %>
28 27
        <div class="flyout-menu__search">
29 28
            <%= form_tag({:controller => 'search', :action => 'index', :id => @project}, :method => :get ) do %>
......
99 98
    <% end %>
100 99
</div>
101 100

  
102
<div id="main" class="<%= sidebar_content? ? '' : 'nosidebar' %>">
101
<div id="main" class="<%= sidebar_content? ? 'collapsiblesidebar' : 'nosidebar' %>">
102
<%= javascript_tag "$('#main.collapsiblesidebar').collapsibleSidebar();" if sidebar_content? %>
103 103
    <div id="sidebar">
104
        <% if sidebar_content? %>
105
          <div id="sidebar-switch-panel" style="visibility: hidden;">
106
            <a id="sidebar-switch-button" href="#">&raquo;</a>
107
          </div>
108
          <%= javascript_tag "$('#sidebar-switch-panel').css('visibility', 'visible');" %>
109
        <% end %>
104 110
        <%= yield :sidebar %>
105 111
        <%= view_layouts_base_sidebar_hook_response %>
106 112
    </div>
public/javascripts/application.js
1006 1006
        }
1007 1007
    });
1008 1008
});
1009
// collapsible sidebar jQuery plugin
1010
(function($) {
1011
  // main container this is applied to
1012
  var main;
1013
  // triggers show/hide
1014
  var button;
1015
  // the key to use in local storage
1016
  // this will later be expanded using the current controller and action to
1017
  // allow for different sidebar states for different pages
1018
  var localStorageKey = 'redmine-sidebar-state';
1019
  // true if local storage is available
1020
  var canUseLocalStorage = function(){
1021
    try {
1022
      if('localStorage' in window){
1023
        localStorage.setItem('redmine.test.storage', 'ok');
1024
        var item = localStorage.getItem('redmine.test.storage');
1025
        localStorage.removeItem('redmine.test.storage');
1026
        if(item === 'ok') return true;
1027
      }
1028
    } catch (err) {}
1029
    return false;
1030
  }();
1031
  // function to set current sidebar state
1032
  var setState = function(state){
1033
    if(canUseLocalStorage){
1034
      localStorage.setItem(localStorageKey, state);
1035
    }
1036
  };
1037
  var applyState = function(){
1038
    if(main.hasClass('collapsedsidebar')){
1039
      button.html("&laquo;");
1040
      setState('hidden');
1041
    } else {
1042
      button.html("&raquo;");
1043
      setState('visible');
1044
    }
1045
  };
1046
  var setupToggleButton = function(){
1047
    button = $('#sidebar-switch-button');
1048
    button.click(function(e){
1049
      main.addClass("animate");
1050
      main.toggleClass('collapsedsidebar');
1051
      applyState();
1052
      e.preventDefault();
1053
      return false;
1054
    });
1055
    applyState();
1056
  };
1057
  $.fn.collapsibleSidebar = function() {
1058
    main = this;
1059
    // determine previously stored sidebar state for this page
1060
    if(canUseLocalStorage) {
1061
      // determine current controller/action pair and use them as storage key
1062
      var bodyClass = $('body').attr('class');
1063
      if(bodyClass){
1064
        try {
1065
          localStorageKey += '-' + bodyClass.split(/\s+/).filter(function(s){
1066
            return s.match(/(action|controller)-.*/);
1067
          }).sort().join('-');
1068
        } catch(e) {
1069
          // in case of error (probably IE8), continue with the unmodified key
1070
        }
1071
      }
1072
      var storedState = localStorage.getItem(localStorageKey);
1073
      main.toggleClass('collapsedsidebar', storedState === 'hidden');
1074
    }
1075
    // draw the toggle button once the DOM is complete
1076
    $(document).ready(setupToggleButton);
1077
  };
1078
}(jQuery));
1079

  
1009 1080
$(document).ready(setupAjaxIndicator);
1010 1081
$(document).ready(hideOnLoad);
1011 1082
$(document).ready(addFormObserversForDoubleSubmit);
public/stylesheets/application.css
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; width: 22%; padding-left: 20px; background: #EEEEEE; border-left: 1px solid #ddd}
89
#sidebar h3{ font-size: 14px; margin-top:14px; color: #666;  }
89
#sidebar{ flex-shrink: 0; width: 22%; padding-left: 20px; background: #EEEEEE; border-left: 1px solid #ddd; z-index: 1;}
90
#sidebar h3 { font-size: 14px; margin-top:14px; color: #666;  }
91
#sidebar h3:first-of-type { margin-top: 4px ; }
90 92
#sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
91 93
* html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
92 94
#sidebar .contextual { margin-right: 1em; }
......
99 101
html>body #content { min-height: 600px; }
100 102
* html body #content { height: 600px; } /* IE */
101 103

  
102
#main.nosidebar #sidebar{ display: none; }
104
#main.collapsedsidebar #sidebar { display: block; width: 0px; }
105
#main.collapsedsidebar #sidebar:hover { width: 22%; position: absolute; height:100%; }
106
#main.collapsedsidebar #sidebar:hover ~ #content { padding-right: 30px; }
107

  
108

  
109
#sidebar-switch-panel {
110
  font-size: 20px;
111
  width: 100%;
112
  color: #666;
113
  display: block;
114
  margin-left: -21px;
115
  padding-right: 21px;
116
  border-bottom: 1px solid #ddd;
117
  padding-left: 4px;
118
}
119
#sidebar-switch-panel:hover {
120
  background-color: #e6e6e6;
121
}
122
#sidebar-switch-button {
123
  color: #666;
124
  width: 100%;
125
  display: block;
126
}
127
#sidebar-switch-button:hover {
128
  text-decoration: none;
129
}
103 130

  
104 131
#footer {clear: both; border-top: 1px solid #bbb; font-size: 0.9em; color: #aaa; padding: 5px; text-align:center; background:#fff;}
105 132

  
(10-10/22)