1/* 2 * sidebar.js 3 * ~~~~~~~~~~ 4 * 5 * This script makes the Sphinx sidebar collapsible and implements 6 * intelligent scrolling. 7 * 8 * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds 9 * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton 10 * used to collapse and expand the sidebar. 11 * 12 * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden 13 * and the width of the sidebar and the margin-left of the document 14 * are decreased. When the sidebar is expanded the opposite happens. 15 * This script saves a per-browser/per-session cookie used to 16 * remember the position of the sidebar among the pages. 17 * Once the browser is closed the cookie is deleted and the position 18 * reset to the default (expanded). 19 * 20 * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. 21 * :license: BSD, see LICENSE for details. 22 * 23 */ 24 25$(function() { 26 // global elements used by the functions. 27 // the 'sidebarbutton' element is defined as global after its 28 // creation, in the add_sidebar_button function 29 var jwindow = $(window); 30 var jdocument = $(document); 31 var bodywrapper = $('.bodywrapper'); 32 var sidebar = $('.sphinxsidebar'); 33 var sidebarwrapper = $('.sphinxsidebarwrapper'); 34 35 // original margin-left of the bodywrapper and width of the sidebar 36 // with the sidebar expanded 37 var bw_margin_expanded = bodywrapper.css('margin-left'); 38 var ssb_width_expanded = sidebar.width(); 39 40 // margin-left of the bodywrapper and width of the sidebar 41 // with the sidebar collapsed 42 var bw_margin_collapsed = '.8em'; 43 var ssb_width_collapsed = '.8em'; 44 45 // colors used by the current theme 46 var dark_color = $('.related').css('background-color'); 47 var light_color = $('.document').css('background-color'); 48 49 function get_viewport_height() { 50 if (window.innerHeight) 51 return window.innerHeight; 52 else 53 return jwindow.height(); 54 } 55 56 function sidebar_is_collapsed() { 57 return sidebarwrapper.is(':not(:visible)'); 58 } 59 60 function toggle_sidebar() { 61 if (sidebar_is_collapsed()) 62 expand_sidebar(); 63 else 64 collapse_sidebar(); 65 // adjust the scrolling of the sidebar 66 scroll_sidebar(); 67 } 68 69 function collapse_sidebar() { 70 sidebarwrapper.hide(); 71 sidebar.css('width', ssb_width_collapsed); 72 bodywrapper.css('margin-left', bw_margin_collapsed); 73 sidebarbutton.css({ 74 'margin-left': '0', 75 'height': bodywrapper.height() 76 }); 77 sidebarbutton.find('span').text('»'); 78 sidebarbutton.attr('title', _('Expand sidebar')); 79 document.cookie = 'sidebar=collapsed'; 80 } 81 82 function expand_sidebar() { 83 bodywrapper.css('margin-left', bw_margin_expanded); 84 sidebar.css('width', ssb_width_expanded); 85 sidebarwrapper.show(); 86 sidebarbutton.css({ 87 'margin-left': ssb_width_expanded-12, 88 'height': bodywrapper.height() 89 }); 90 sidebarbutton.find('span').text('«'); 91 sidebarbutton.attr('title', _('Collapse sidebar')); 92 document.cookie = 'sidebar=expanded'; 93 } 94 95 function add_sidebar_button() { 96 sidebarwrapper.css({ 97 'float': 'left', 98 'margin-right': '0', 99 'width': ssb_width_expanded - 28 100 }); 101 // create the button 102 sidebar.append( 103 '<div id="sidebarbutton"><span>«</span></div>' 104 ); 105 var sidebarbutton = $('#sidebarbutton'); 106 light_color = sidebarbutton.css('background-color'); 107 // find the height of the viewport to center the '<<' in the page 108 var viewport_height = get_viewport_height(); 109 sidebarbutton.find('span').css({ 110 'display': 'block', 111 'margin-top': (viewport_height - sidebar.position().top - 20) / 2 112 }); 113 114 sidebarbutton.click(toggle_sidebar); 115 sidebarbutton.attr('title', _('Collapse sidebar')); 116 sidebarbutton.css({ 117 'color': '#FFFFFF', 118 'border-left': '1px solid ' + dark_color, 119 'font-size': '1.2em', 120 'cursor': 'pointer', 121 'height': bodywrapper.height(), 122 'padding-top': '1px', 123 'margin-left': ssb_width_expanded - 12 124 }); 125 126 sidebarbutton.hover( 127 function () { 128 $(this).css('background-color', dark_color); 129 }, 130 function () { 131 $(this).css('background-color', light_color); 132 } 133 ); 134 } 135 136 function set_position_from_cookie() { 137 if (!document.cookie) 138 return; 139 var items = document.cookie.split(';'); 140 for(var k=0; k<items.length; k++) { 141 var key_val = items[k].split('='); 142 var key = key_val[0]; 143 if (key == 'sidebar') { 144 var value = key_val[1]; 145 if ((value == 'collapsed') && (!sidebar_is_collapsed())) 146 collapse_sidebar(); 147 else if ((value == 'expanded') && (sidebar_is_collapsed())) 148 expand_sidebar(); 149 } 150 } 151 } 152 153 add_sidebar_button(); 154 var sidebarbutton = $('#sidebarbutton'); 155 set_position_from_cookie(); 156 157 158 /* intelligent scrolling */ 159 function scroll_sidebar() { 160 var sidebar_height = sidebarwrapper.height(); 161 var viewport_height = get_viewport_height(); 162 var offset = sidebar.position()['top']; 163 var wintop = jwindow.scrollTop(); 164 var winbot = wintop + viewport_height; 165 var curtop = sidebarwrapper.position()['top']; 166 var curbot = curtop + sidebar_height; 167 // does sidebar fit in window? 168 if (sidebar_height < viewport_height) { 169 // yes: easy case -- always keep at the top 170 sidebarwrapper.css('top', $u.min([$u.max([0, wintop - offset - 10]), 171 jdocument.height() - sidebar_height - 200])); 172 } 173 else { 174 // no: only scroll if top/bottom edge of sidebar is at 175 // top/bottom edge of window 176 if (curtop > wintop && curbot > winbot) { 177 sidebarwrapper.css('top', $u.max([wintop - offset - 10, 0])); 178 } 179 else if (curtop < wintop && curbot < winbot) { 180 sidebarwrapper.css('top', $u.min([winbot - sidebar_height - offset - 20, 181 jdocument.height() - sidebar_height - 200])); 182 } 183 } 184 } 185 jwindow.scroll(scroll_sidebar); 186}); 187