| Hao Zhu | c145088 | 2018-10-03 17:56:26 -0400 | [diff] [blame] | 1 | gitbook.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 |     var down = config.download; | 
 | 20 |     var normalizeDownload = function() { | 
 | 21 |       if (!down || !(down instanceof Array) || down.length === 0) return; | 
 | 22 |       if (down[0] instanceof Array) return down; | 
 | 23 |       return $.map(down, function(file, i) { | 
 | 24 |         return [[file, file.replace(/.*[.]/g, '').toUpperCase()]]; | 
 | 25 |       }); | 
 | 26 |     }; | 
 | 27 |     down = normalizeDownload(down); | 
 | 28 |     if (down) if (down.length === 1 && /[.]pdf$/.test(down[0][0])) { | 
 | 29 |       gitbook.toolbar.createButton({ | 
 | 30 |         icon: 'fa fa-file-pdf-o', | 
 | 31 |         label: down[0][1], | 
 | 32 |         position: 'left', | 
 | 33 |         onClick: function(e) { | 
 | 34 |           e.preventDefault(); | 
 | 35 |           window.open(down[0][0]); | 
 | 36 |         } | 
 | 37 |       }); | 
 | 38 |     } else { | 
 | 39 |       gitbook.toolbar.createButton({ | 
 | 40 |         icon: 'fa fa-download', | 
 | 41 |         label: 'Download', | 
 | 42 |         position: 'left', | 
 | 43 |         dropdown: $.map(down, function(item, i) { | 
 | 44 |           return { | 
 | 45 |             text: item[1], | 
 | 46 |             onClick: function(e) { | 
 | 47 |               e.preventDefault(); | 
 | 48 |               window.open(item[0]); | 
 | 49 |             } | 
 | 50 |           }; | 
 | 51 |         }) | 
 | 52 |       }); | 
 | 53 |     } | 
 | 54 |  | 
 | 55 |     // highlight the current section in TOC | 
 | 56 |     var href = window.location.pathname; | 
 | 57 |     href = href.substr(href.lastIndexOf('/') + 1); | 
 | 58 |     if (href === '') href = 'index.html'; | 
 | 59 |     var li = $('a[href^="' + href + location.hash + '"]').parent('li.chapter').first(); | 
 | 60 |     var summary = $('ul.summary'), chaps = summary.find('li.chapter'); | 
 | 61 |     if (li.length === 0) li = chaps.first(); | 
 | 62 |     li.addClass('active'); | 
 | 63 |     chaps.on('click', function(e) { | 
 | 64 |       chaps.removeClass('active'); | 
 | 65 |       $(this).addClass('active'); | 
 | 66 |       gs.set('tocScrollTop', summary.scrollTop()); | 
 | 67 |     }); | 
 | 68 |  | 
 | 69 |     var toc = config.toc; | 
 | 70 |     // collapse TOC items that are not for the current chapter | 
 | 71 |     if (toc && toc.collapse) (function() { | 
 | 72 |       var type = toc.collapse; | 
 | 73 |       if (type === 'none') return; | 
 | 74 |       if (type !== 'section' && type !== 'subsection') return; | 
 | 75 |       // sections under chapters | 
 | 76 |       var toc_sub = summary.children('li[data-level]').children('ul'); | 
 | 77 |       if (type === 'section') { | 
 | 78 |         toc_sub.hide() | 
 | 79 |           .parent().has(li).children('ul').show(); | 
 | 80 |       } else { | 
 | 81 |         toc_sub.children('li').children('ul').hide() | 
 | 82 |           .parent().has(li).children('ul').show(); | 
 | 83 |       } | 
 | 84 |       li.children('ul').show(); | 
 | 85 |       var toc_sub2 = toc_sub.children('li'); | 
 | 86 |       if (type === 'section') toc_sub2.children('ul').hide(); | 
 | 87 |       summary.children('li[data-level]').find('a') | 
 | 88 |         .on('click.bookdown', function(e) { | 
 | 89 |           if (href === $(this).attr('href').replace(/#.*/, '')) | 
 | 90 |             $(this).parent('li').children('ul').toggle(); | 
 | 91 |         }); | 
 | 92 |     })(); | 
 | 93 |  | 
 | 94 |     // add tooltips to the <a>'s that are truncated | 
 | 95 |     $('a').each(function(i, el) { | 
 | 96 |       if (el.offsetWidth >= el.scrollWidth) return; | 
 | 97 |       if (typeof el.title === 'undefined') return; | 
 | 98 |       el.title = el.text; | 
 | 99 |     }); | 
 | 100 |  | 
 | 101 |     // restore TOC scroll position | 
 | 102 |     var pos = gs.get('tocScrollTop'); | 
 | 103 |     if (typeof pos !== 'undefined') summary.scrollTop(pos); | 
 | 104 |  | 
 | 105 |     // highlight the TOC item that has same text as the heading in view as scrolling | 
 | 106 |     if (toc && toc.scroll_highlight !== false) (function() { | 
 | 107 |       // scroll the current TOC item into viewport | 
 | 108 |       var ht = $(window).height(), rect = li[0].getBoundingClientRect(); | 
 | 109 |       if (rect.top >= ht || rect.top <= 0 || rect.bottom <= 0) { | 
 | 110 |         summary.scrollTop(li[0].offsetTop); | 
 | 111 |       } | 
 | 112 |       // current chapter TOC items | 
 | 113 |       var items = $('a[href^="' + href + '"]').parent('li.chapter'), | 
 | 114 |           m = items.length; | 
 | 115 |       if (m === 0) { | 
 | 116 |         items = summary.find('li.chapter'); | 
 | 117 |         m = items.length; | 
 | 118 |       } | 
 | 119 |       if (m === 0) return; | 
 | 120 |       // all section titles on current page | 
 | 121 |       var hs = bookInner.find('.page-inner').find('h1,h2,h3'), n = hs.length, | 
 | 122 |           ts = hs.map(function(i, el) { return $(el).text(); }); | 
 | 123 |       if (n === 0) return; | 
 | 124 |       var scrollHandler = function(e) { | 
 | 125 |         var ht = $(window).height(); | 
 | 126 |         clearTimeout($.data(this, 'scrollTimer')); | 
 | 127 |         $.data(this, 'scrollTimer', setTimeout(function() { | 
 | 128 |           // find the first visible title in the viewport | 
 | 129 |           for (var i = 0; i < n; i++) { | 
 | 130 |             var rect = hs[i].getBoundingClientRect(); | 
 | 131 |             if (rect.top >= 0 && rect.bottom <= ht) break; | 
 | 132 |           } | 
 | 133 |           if (i === n) return; | 
 | 134 |           items.removeClass('active'); | 
 | 135 |           for (var j = 0; j < m; j++) { | 
 | 136 |             if (items.eq(j).children('a').first().text() === ts[i]) break; | 
 | 137 |           } | 
 | 138 |           if (j === m) j = 0;  // highlight the chapter title | 
 | 139 |           // search bottom-up for a visible TOC item to highlight; if an item is | 
 | 140 |           // hidden, we check if its parent is visible, and so on | 
 | 141 |           while (j > 0 && items.eq(j).is(':hidden')) j--; | 
 | 142 |           items.eq(j).addClass('active'); | 
 | 143 |         }, 250)); | 
 | 144 |       }; | 
 | 145 |       bookInner.on('scroll.bookdown', scrollHandler); | 
 | 146 |       bookBody.on('scroll.bookdown', scrollHandler); | 
 | 147 |     })(); | 
 | 148 |  | 
 | 149 |     // do not refresh the page if the TOC item points to the current page | 
 | 150 |     $('a[href="' + href + '"]').parent('li.chapter').children('a') | 
 | 151 |       .on('click', function(e) { | 
 | 152 |         bookInner.scrollTop(0); | 
 | 153 |         bookBody.scrollTop(0); | 
 | 154 |         return false; | 
 | 155 |       }); | 
 | 156 |  | 
 | 157 |     var toolbar = config.toolbar; | 
 | 158 |     if (!toolbar || toolbar.position !== 'static') { | 
 | 159 |       var bookHeader = $('.book-header'); | 
 | 160 |       bookBody.addClass('fixed'); | 
 | 161 |       bookHeader.addClass('fixed') | 
 | 162 |       .css('background-color', bookBody.css('background-color')) | 
 | 163 |       .on('click.bookdown', function(e) { | 
 | 164 |         // the theme may have changed after user clicks the theme button | 
 | 165 |         bookHeader.css('background-color', bookBody.css('background-color')); | 
 | 166 |       }); | 
 | 167 |     } | 
 | 168 |  | 
 | 169 |   }); | 
 | 170 |  | 
 | 171 |   gitbook.events.bind("page.change", function(e) { | 
 | 172 |     // store TOC scroll position | 
 | 173 |     var summary = $('ul.summary'); | 
 | 174 |     gs.set('tocScrollTop', summary.scrollTop()); | 
 | 175 |   }); | 
 | 176 |  | 
 | 177 |   var bookBody = $('.book-body'), bookInner = bookBody.find('.body-inner'); | 
 | 178 |   var chapterTitle = function() { | 
 | 179 |     return bookInner.find('.page-inner').find('h1,h2').first().text(); | 
 | 180 |   }; | 
 | 181 |   var bookTitle = function() { | 
 | 182 |     return bookInner.find('.book-header > h1').first().text(); | 
 | 183 |   }; | 
 | 184 |   var saveScrollPos = function(e) { | 
 | 185 |     // save scroll position before page is reloaded | 
 | 186 |     gs.set('bodyScrollTop', { | 
 | 187 |       body: bookBody.scrollTop(), | 
 | 188 |       inner: bookInner.scrollTop(), | 
 | 189 |       focused: document.hasFocus(), | 
 | 190 |       title: chapterTitle() | 
 | 191 |     }); | 
 | 192 |   }; | 
 | 193 |   $(document).on('servr:reload', saveScrollPos); | 
 | 194 |  | 
 | 195 |   // check if the page is loaded in an iframe (e.g. the RStudio preview window) | 
 | 196 |   var inIFrame = function() { | 
 | 197 |     var inIframe = true; | 
 | 198 |     try { inIframe = window.self !== window.top; } catch (e) {} | 
 | 199 |     return inIframe; | 
 | 200 |   }; | 
 | 201 |   $(window).on('blur unload', function(e) { | 
 | 202 |     if (inIFrame()) saveScrollPos(e); | 
 | 203 |     gs.set('bookTitle', bookTitle()); | 
 | 204 |   }); | 
 | 205 |  | 
 | 206 |   $(function(e) { | 
 | 207 |     if (gs.get('bookTitle', '') !== bookTitle()) localStorage.clear(); | 
 | 208 |     var pos = gs.get('bodyScrollTop'); | 
 | 209 |     if (pos) { | 
 | 210 |       if (pos.title === chapterTitle()) { | 
 | 211 |         if (pos.body !== 0) bookBody.scrollTop(pos.body); | 
 | 212 |         if (pos.inner !== 0) bookInner.scrollTop(pos.inner); | 
 | 213 |       } | 
 | 214 |       if (pos.focused) bookInner.find('.page-wrapper').focus(); | 
 | 215 |     } | 
 | 216 |     // clear book body scroll position | 
 | 217 |     gs.remove('bodyScrollTop'); | 
 | 218 |   }); | 
 | 219 |  | 
 | 220 | }); |