1gitbook.require(["gitbook", "lodash", "jQuery"], function(gitbook, _, $) { 2 3 var gs = gitbook.storage; 4 5 gitbook.events.bind("start", function(e, config) { 6 7 // add the Edit button (edit on Github) 8 var edit = config.edit; 9 if (edit && edit.link) gitbook.toolbar.createButton({ 10 icon: 'fa fa-edit', 11 label: edit.text || 'Edit', 12 position: 'left', 13 onClick: function(e) { 14 e.preventDefault(); 15 window.open(edit.link); 16 } 17 }); 18 19 // add the History button (file history on Github) 20 var history = config.history; 21 if (history && history.link) gitbook.toolbar.createButton({ 22 icon: 'fa fa-history', 23 label: history.text || 'History', 24 position: 'left', 25 onClick: function(e) { 26 e.preventDefault(); 27 window.open(history.link); 28 } 29 }); 30 31 // add the View button (file view on Github) 32 var view = config.view; 33 if (view && view.link) gitbook.toolbar.createButton({ 34 icon: 'fa fa-eye', 35 label: view.text || 'View Source', 36 position: 'left', 37 onClick: function(e) { 38 e.preventDefault(); 39 window.open(view.link); 40 } 41 }); 42 43 // add the Download button 44 var down = config.download; 45 var normalizeDownload = function() { 46 if (!down || !(down instanceof Array) || down.length === 0) return; 47 if (down[0] instanceof Array) return down; 48 return $.map(down, function(file, i) { 49 return [[file, file.replace(/.*[.]/g, '').toUpperCase()]]; 50 }); 51 }; 52 down = normalizeDownload(down); 53 if (down) if (down.length === 1 && /[.]pdf$/.test(down[0][0])) { 54 gitbook.toolbar.createButton({ 55 icon: 'fa fa-file-pdf-o', 56 label: down[0][1], 57 position: 'left', 58 onClick: function(e) { 59 e.preventDefault(); 60 window.open(down[0][0]); 61 } 62 }); 63 } else { 64 gitbook.toolbar.createButton({ 65 icon: 'fa fa-download', 66 label: 'Download', 67 position: 'left', 68 dropdown: $.map(down, function(item, i) { 69 return { 70 text: item[1], 71 onClick: function(e) { 72 e.preventDefault(); 73 window.open(item[0]); 74 } 75 }; 76 }) 77 }); 78 } 79 80 // add the Information button 81 var info = ['Keyboard shortcuts (<> indicates arrow keys):', 82 '<left>/<right>: navigate to previous/next page', 83 's: Toggle sidebar']; 84 if (config.search !== false) info.push('f: Toggle search input ' + 85 '(use <up>/<down>/Enter in the search input to navigate through search matches; ' + 86 'press Esc to cancel search)'); 87 if (config.info !== false) gitbook.toolbar.createButton({ 88 icon: 'fa fa-info', 89 label: 'Information about the toolbar', 90 position: 'left', 91 onClick: function(e) { 92 e.preventDefault(); 93 window.alert(info.join('\n\n')); 94 } 95 }); 96 97 // highlight the current section in TOC 98 var href = window.location.pathname; 99 href = href.substr(href.lastIndexOf('/') + 1); 100 // accentuated characters need to be decoded (#819) 101 href = decodeURIComponent(href); 102 if (href === '') href = 'index.html'; 103 var li = $('a[href^="' + href + location.hash + '"]').parent('li.chapter').first(); 104 var summary = $('ul.summary'), chaps = summary.find('li.chapter'); 105 if (li.length === 0) li = chaps.first(); 106 li.addClass('active'); 107 chaps.on('click', function(e) { 108 chaps.removeClass('active'); 109 $(this).addClass('active'); 110 gs.set('tocScrollTop', summary.scrollTop()); 111 }); 112 113 var toc = config.toc; 114 // collapse TOC items that are not for the current chapter 115 if (toc && toc.collapse) (function() { 116 var type = toc.collapse; 117 if (type === 'none') return; 118 if (type !== 'section' && type !== 'subsection') return; 119 // sections under chapters 120 var toc_sub = summary.children('li[data-level]').children('ul'); 121 if (type === 'section') { 122 toc_sub.hide() 123 .parent().has(li).children('ul').show(); 124 } else { 125 toc_sub.children('li').children('ul').hide() 126 .parent().has(li).children('ul').show(); 127 } 128 li.children('ul').show(); 129 var toc_sub2 = toc_sub.children('li'); 130 if (type === 'section') toc_sub2.children('ul').hide(); 131 summary.children('li[data-level]').find('a') 132 .on('click.bookdown', function(e) { 133 if (href === $(this).attr('href').replace(/#.*/, '')) 134 $(this).parent('li').children('ul').toggle(); 135 }); 136 })(); 137 138 // add tooltips to the <a>'s that are truncated 139 $('a').each(function(i, el) { 140 if (el.offsetWidth >= el.scrollWidth) return;
141 if (typeof el.title === 'undefined') return; 142 el.title = el.text; 143 }); 144 145 // restore TOC scroll position 146 var pos = gs.get('tocScrollTop'); 147 if (typeof pos !== 'undefined') summary.scrollTop(pos); 148 149 // highlight the TOC item that has same text as the heading in view as scrolling 150 if (toc && toc.scroll_highlight !== false && li.length > 0) (function() { 151 // scroll the current TOC item into viewport 152 var ht = $(window).height(), rect = li[0].getBoundingClientRect(); 153 if (rect.top >= ht || rect.top <= 0 || rect.bottom <= 0) { 154 summary.scrollTop(li[0].offsetTop); 155 } 156 // current chapter TOC items 157 var items = $('a[href^="' + href + '"]').parent('li.chapter'), 158 m = items.length; 159 if (m === 0) { 160 items = summary.find('li.chapter'); 161 m = items.length; 162 } 163 if (m === 0) return; 164 // all section titles on current page 165 var hs = bookInner.find('.page-inner').find('h1,h2,h3'), n = hs.length, 166 ts = hs.map(function(i, el) { return $(el).text(); }); 167 if (n === 0) return; 168 var scrollHandler = function(e) { 169 var ht = $(window).height(); 170 clearTimeout($.data(this, 'scrollTimer')); 171 $.data(this, 'scrollTimer', setTimeout(function() { 172 // find the first visible title in the viewport 173 for (var i = 0; i < n; i++) { 174 var rect = hs[i].getBoundingClientRect(); 175 if (rect.top >= 0 && rect.bottom <= ht) break; 176 } 177 if (i === n) return; 178 items.removeClass('active'); 179 for (var j = 0; j < m; j++) { 180 if (items.eq(j).children('a').first().text() === ts[i]) break; 181 } 182 if (j === m) j = 0; // highlight the chapter title 183 // search bottom-up for a visible TOC item to highlight; if an item is 184 // hidden, we check if its parent is visible, and so on 185 while (j > 0 && items.eq(j).is(':hidden')) j--; 186 items.eq(j).addClass('active'); 187 }, 250)); 188 }; 189 bookInner.on('scroll.bookdown', scrollHandler); 190 bookBody.on('scroll.bookdown', scrollHandler); 191 })(); 192 193 // do not refresh the page if the TOC item points to the current page 194 $('a[href="' + href + '"]').parent('li.chapter').children('a') 195 .on('click', function(e) { 196 bookInner.scrollTop(0); 197 bookBody.scrollTop(0); 198 return false; 199 }); 200 201 var toolbar = config.toolbar; 202 if (!toolbar || toolbar.position !== 'static') { 203 var bookHeader = $('.book-header'); 204 bookBody.addClass('fixed'); 205 bookHeader.addClass('fixed') 206 .css('background-color', bookBody.css('background-color')) 207 .on('click.bookdown', function(e) { 208 // the theme may have changed after user clicks the theme button 209 bookHeader.css('background-color', bookBody.css('background-color')); 210 }); 211 } 212 213 }); 214 215 gitbook.events.bind("page.change", function(e) { 216 // store TOC scroll position 217 var summary = $('ul.summary'); 218 gs.set('tocScrollTop', summary.scrollTop()); 219 }); 220 221 var bookBody = $('.book-body'), bookInner = bookBody.find('.body-inner'); 222 var chapterTitle = function() { 223 return bookInner.find('.page-inner').find('h1,h2').first().text(); 224 }; 225 var saveScrollPos = function(e) { 226 // save scroll position before page is reloaded 227 gs.set('bodyScrollTop', { 228 body: bookBody.scrollTop(), 229 inner: bookInner.scrollTop(), 230 focused: document.hasFocus(), 231 title: chapterTitle() 232 }); 233 }; 234 $(document).on('servr:reload', saveScrollPos); 235 236 // check if the page is loaded in an iframe (e.g. the RStudio preview window) 237 var inIFrame = function() { 238 var inIframe = true; 239 try { inIframe = window.self !== window.top; } catch (e) {} 240 return inIframe; 241 }; 242 if (inIFrame()) { 243 $(window).on('blur unload', saveScrollPos); 244 } 245 246 $(function(e) { 247 var pos = gs.get('bodyScrollTop'); 248 if (pos) { 249 if (pos.title === chapterTitle()) { 250 if (pos.body !== 0) bookBody.scrollTop(pos.body); 251 if (pos.inner !== 0) bookInner.scrollTop(pos.inner); 252 } 253 } 254 if ((pos && pos.focused) || !inIFrame()) bookInner.find('.page-wrapper').focus(); 255 // clear book body scroll position 256 gs.remove('bodyScrollTop'); 257 }); 258 259});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.