Changed trials-in-common page to use a single database query to get analyses. Changed...
[sgn.git] / docs / libs / gitbook-2.6.7 / js / plugin-search.js
blob747fccebd0fb50e37c99948862e555af48bd9be9
1 gitbook.require(["gitbook", "lodash", "jQuery"], function(gitbook, _, $) {
2     var index = null;
3     var fuse = null;
4     var _search = {engine: 'lunr', opts: {}};
5     var $searchInput, $searchLabel, $searchForm;
6     var $highlighted = [], hi, hiOpts = { className: 'search-highlight' };
7     var collapse = false, toc_visible = [];
9     function init(config) {
10         // Instantiate search settings
11         _search = gitbook.storage.get("search", {
12             engine: config.search.engine || 'lunr',
13             opts: config.search.options || {},
14         });
15     };
17     // Save current search settings
18     function saveSearchSettings() {
19         gitbook.storage.set("search", _search);
20     }
22     // Use a specific index
23     function loadIndex(data) {
24         // [Yihui] In bookdown, I use a character matrix to store the chapter
25         // content, and the index is dynamically built on the client side.
26         // Gitbook prebuilds the index data instead: https://github.com/GitbookIO/plugin-search
27         // We can certainly do that via R packages V8 and jsonlite, but let's
28         // see how slow it really is before improving it. On the other hand,
29         // lunr cannot handle non-English text very well, e.g. the default
30         // tokenizer cannot deal with Chinese text, so we may want to replace
31         // lunr with a dumb simple text matching approach.
32         if (_search.engine === 'lunr') {
33           index = lunr(function () {
34             this.ref('url');
35             this.field('title', { boost: 10 });
36             this.field('body');
37           });
38           data.map(function(item) {
39             index.add({
40               url: item[0],
41               title: item[1],
42               body: item[2]
43             });
44           });
45           return;
46         }
47         fuse = new Fuse(data.map((_data => {
48             return {
49                 url: _data[0],
50                 title: _data[1],
51                 body: _data[2]
52             };
53         })), Object.assign(
54             {
55                 includeScore: true,
56                 threshold: 0.1,
57                 ignoreLocation: true,
58                 keys: ["title", "body"]
59             },
60             _search.opts
61         ));
62     }
64     // Fetch the search index
65     function fetchIndex() {
66         return $.getJSON(gitbook.state.basePath+"/search_index.json")
67                 .then(loadIndex);  // [Yihui] we need to use this object later
68     }
70     // Search for a term and return results
71     function search(q) {
72         let results = [];
73         switch (_search.engine) {
74             case 'fuse':
75                 if (!fuse) return;
76                 results = fuse.search(q).map(function(result) {
77                     var parts = result.item.url.split('#');
78                     return {
79                         path: parts[0],
80                         hash: parts[1]
81                     };
82                 });
83                 break;
84             case 'lunr':
85             default:
86                 if (!index) return;
87                 results = _.chain(index.search(q)).map(function(result) {
88                     var parts = result.ref.split("#");
89                     return {
90                         path: parts[0],
91                         hash: parts[1]
92                     };
93                 })
94                 .value();
95         }
97         // [Yihui] Highlight the search keyword on current page
98         $highlighted = $('.page-inner')
99           .unhighlight(hiOpts).highlight(q, hiOpts).find('span.search-highlight');
100         scrollToHighlighted(0);
102         return results;
103     }
105     // [Yihui] Scroll the chapter body to the i-th highlighted string
106     function scrollToHighlighted(d) {
107       var n = $highlighted.length;
108       hi = hi === undefined ? 0 : hi + d;
109       // navignate to the previous/next page in the search results if reached the top/bottom
110       var b = hi < 0;
111       if (d !== 0 && (b || hi >= n)) {
112         var path = currentPath(), n2 = toc_visible.length;
113         if (n2 === 0) return;
114         for (var i = b ? 0 : n2; (b && i < n2) || (!b && i >= 0); i += b ? 1 : -1) {
115           if (toc_visible.eq(i).data('path') === path) break;
116         }
117         i += b ? -1 : 1;
118         if (i < 0) i = n2 - 1;
119         if (i >= n2) i = 0;
120         var lnk = toc_visible.eq(i).find('a[href$=".html"]');
121         if (lnk.length) lnk[0].click();
122         return;
123       }
124       if (n === 0) return;
125       var $p = $highlighted.eq(hi);
126       $p[0].scrollIntoView();
127       $highlighted.css('background-color', '');
128       // an orange background color on the current item and removed later
129       $p.css('background-color', 'orange');
130       setTimeout(function() {
131         $p.css('background-color', '');
132       }, 2000);
133     }
135     function currentPath() {
136       var href = window.location.pathname;
137       href = href.substr(href.lastIndexOf('/') + 1);
138       return href === '' ? 'index.html' : href;
139     }
141     // Create search form
142     function createForm(value) {
143         if ($searchForm) $searchForm.remove();
144         if ($searchLabel) $searchLabel.remove();
145         if ($searchInput) $searchInput.remove();
147         $searchForm = $('<div>', {
148             'class': 'book-search',
149             'role': 'search'
150         });
152         $searchLabel = $('<label>', {
153             'for': 'search-box',
154             'aria-hidden': 'false',
155             'hidden': ''
156         });
158         $searchInput = $('<input>', {
159             'id': 'search-box',
160             'type': 'search',
161             'class': 'form-control',
162             'val': value,
163             'placeholder': 'Type to search (Enter for navigation)',
164             'title': 'Use Enter or the <Down> key to navigate to the next match, or the <Up> key to the previous match'
165         });
167         $searchLabel.append("Type to search");
168         $searchLabel.appendTo($searchForm);
169         $searchInput.appendTo($searchForm);
170         $searchForm.prependTo(gitbook.state.$book.find('.book-summary'));
171     }
173     // Return true if search is open
174     function isSearchOpen() {
175         return gitbook.state.$book.hasClass("with-search");
176     }
178     // Toggle the search
179     function toggleSearch(_state) {
180         if (isSearchOpen() === _state) return;
181         if (!$searchInput) return;
183         gitbook.state.$book.toggleClass("with-search", _state);
185         // If search bar is open: focus input
186         if (isSearchOpen()) {
187             gitbook.sidebar.toggle(true);
188             $searchInput.focus();
189         } else {
190             $searchInput.blur();
191             $searchInput.val("");
192             gitbook.storage.remove("keyword");
193             gitbook.sidebar.filter(null);
194             $('.page-inner').unhighlight(hiOpts);
195         }
196     }
198     function sidebarFilter(results) {
199         gitbook.sidebar.filter(_.pluck(results, "path"));
200         toc_visible = $('ul.summary').find('li:visible');
201     }
203     // Recover current search when page changed
204     function recoverSearch() {
205         var keyword = gitbook.storage.get("keyword", "");
207         createForm(keyword);
209         if (keyword.length > 0) {
210             if(!isSearchOpen()) {
211                 toggleSearch(true); // [Yihui] open the search box
212             }
213             sidebarFilter(search(keyword));
214         }
215     }
218     gitbook.events.bind("start", function(e, config) {
219         // [Yihui] disable search
220         if (config.search === false) return;
221         init(config);
222         collapse = !config.toc || config.toc.collapse === 'section' ||
223           config.toc.collapse === 'subsection';
225         // Pre-fetch search index and create the form
226         fetchIndex()
227         // [Yihui] recover search after the page is loaded
228         .then(recoverSearch);
231         // Type in search bar
232         $(document).on("keyup", ".book-search input", function(e) {
233             var key = (e.keyCode ? e.keyCode : e.which);
234             // [Yihui] Escape -> close search box; Up/Down/Enter: previous/next highlighted
235             if (key == 27) {
236                 e.preventDefault();
237                 toggleSearch(false);
238             } else if (key == 38) {
239               scrollToHighlighted(-1);
240             } else if (key == 40 || key == 13) {
241               scrollToHighlighted(1);
242             }
243         }).on("input", ".book-search input", function(e) {
244             var q = $(this).val().trim();
245             if (q.length === 0) {
246                 gitbook.sidebar.filter(null);
247                 gitbook.storage.remove("keyword");
248                 $('.page-inner').unhighlight(hiOpts);
249             } else {
250                 var results = search(q);
251                 sidebarFilter(results);
252                 gitbook.storage.set("keyword", q);
253             }
254         });
256         // Create the toggle search button
257         gitbook.toolbar.createButton({
258             icon: 'fa fa-search',
259             label: 'Search',
260             position: 'left',
261             onClick: toggleSearch
262         });
264         // Bind keyboard to toggle search
265         gitbook.keyboard.bind(['f'], toggleSearch);
266     });
268     // [Yihui] do not try to recover search; always start fresh
269     // gitbook.events.bind("page.change", recoverSearch);