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