• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>&laquo;</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