require(["gitbook", "lodash", "jQuery"], function(gitbook, _, $) { var index = null; var $searchInput, $searchForm; var $highlighted, hi = 0, hiOpts = { className: 'search-highlight' }; var collapse = false; // Use a specific index function loadIndex(data) { // [Yihui] In bookdown, I use a character matrix to store the chapter // content, and the index is dynamically built on the client side. // Gitbook prebuilds the index data instead: https://github.com/GitbookIO/plugin-search // We can certainly do that via R packages V8 and jsonlite, but let's // see how slow it really is before improving it. On the other hand, // lunr cannot handle non-English text very well, e.g. the default // tokenizer cannot deal with Chinese text, so we may want to replace // lunr with a dumb simple text matching approach. index = lunr(function () { this.ref('url'); this.field('title', { boost: 10 }); this.field('body'); }); data.map(function(item) { index.add({ url: item[0], title: item[1], body: item[2] }); }); } // Fetch the search index function fetchIndex() { return $.getJSON(gitbook.state.basePath+"/search_index.json") .then(loadIndex); // [Yihui] we need to use this object later } // Search for a term and return results function search(q) { if (!index) return; var results = _.chain(index.search(q)) .map(function(result) { var parts = result.ref.split("#"); return { path: parts[0], hash: parts[1] }; }) .value(); // [Yihui] Highlight the search keyword on current page hi = 0; $highlighted = results.length === 0 ? undefined : $('.page-inner') .unhighlight(hiOpts).highlight(q, hiOpts).find('span.search-highlight'); scrollToHighlighted(); toggleTOC(results.length > 0); return results; } // [Yihui] Scroll the chapter body to the i-th highlighted string function scrollToHighlighted() { if (!$highlighted) return; var n = $highlighted.length; if (n === 0) return; var $p = $highlighted.eq(hi), p = $p[0], rect = p.getBoundingClientRect(); if (rect.top < 0 || rect.bottom > $(window).height()) { ($(window).width() >= 1240 ? $('.body-inner') : $('.book-body')) .scrollTop(p.offsetTop - 100); } $highlighted.css('background-color', ''); // an orange background color on the current item and removed later $p.css('background-color', 'orange'); setTimeout(function() { $p.css('background-color', ''); }, 2000); } // [Yihui] Expand/collapse TOC function toggleTOC(show) { if (!collapse) return; var toc_sub = $('ul.summary').children('li[data-level]').children('ul'); if (show) return toc_sub.show(); var href = window.location.pathname; href = href.substr(href.lastIndexOf('/') + 1); if (href === '') href = 'index.html'; var li = $('a[href^="' + href + location.hash + '"]').parent('li.chapter').first(); toc_sub.hide().parent().has(li).children('ul').show(); li.children('ul').show(); } // Create search form function createForm(value) { if ($searchForm) $searchForm.remove(); if ($searchInput) $searchInput.remove(); $searchForm = $('