|
17 | 17 |
|
18 | 18 | $('.js-only').removeClass('js-only');
|
19 | 19 |
|
| 20 | + function getQueryStringParams() { |
| 21 | + var params = {}; |
| 22 | + window.location.search.substring(1).split("&"). |
| 23 | + map(function(s) { |
| 24 | + var pair = s.split("="); |
| 25 | + params[decodeURIComponent(pair[0])] = |
| 26 | + typeof pair[1] === "undefined" ? null : decodeURIComponent(pair[1]); |
| 27 | + }); |
| 28 | + return params; |
| 29 | + } |
| 30 | + |
| 31 | + function browserSupportsHistoryApi() { |
| 32 | + return window.history && typeof window.history.pushState === "function"; |
| 33 | + } |
| 34 | + |
20 | 35 | function resizeShortBlocks() {
|
21 | 36 | if (resizeTimeout) {
|
22 | 37 | clearTimeout(resizeTimeout);
|
|
97 | 112 | });
|
98 | 113 |
|
99 | 114 | function initSearch(searchIndex) {
|
100 |
| - var currentResults, index; |
| 115 | + var currentResults, index, params = getQueryStringParams(); |
101 | 116 |
|
102 |
| - // clear cached values from the search bar |
103 |
| - $(".search-input")[0].value = ''; |
| 117 | + // Populate search bar with query string search term when provided. |
| 118 | + $(".search-input")[0].value = params.search || ''; |
104 | 119 |
|
105 | 120 | /**
|
106 | 121 | * Executes the query and builds an index of results
|
|
418 | 433 | results = [],
|
419 | 434 | maxResults = 200,
|
420 | 435 | resultIndex;
|
| 436 | + var params = getQueryStringParams(); |
421 | 437 |
|
422 | 438 | query = getQuery();
|
423 | 439 | if (e) {
|
|
428 | 444 | return;
|
429 | 445 | }
|
430 | 446 |
|
| 447 | + // Because searching is incremental by character, only the most recent search query |
| 448 | + // is added to the browser history. |
| 449 | + if (browserSupportsHistoryApi()) { |
| 450 | + if (!history.state && !params.search) { |
| 451 | + history.pushState(query, "", "?search=" + encodeURIComponent(query.query)); |
| 452 | + } else { |
| 453 | + history.replaceState(query, "", "?search=" + encodeURIComponent(query.query)); |
| 454 | + } |
| 455 | + } |
| 456 | + |
431 | 457 | resultIndex = execQuery(query, 20000, index);
|
432 | 458 | len = resultIndex.length;
|
433 | 459 | for (i = 0; i < len; i += 1) {
|
|
536 | 562 | clearTimeout(keyUpTimeout);
|
537 | 563 | keyUpTimeout = setTimeout(search, 100);
|
538 | 564 | });
|
| 565 | + // Push and pop states are used to add search results to the browser history. |
| 566 | + if (browserSupportsHistoryApi()) { |
| 567 | + $(window).on('popstate', function(e) { |
| 568 | + var params = getQueryStringParams(); |
| 569 | + // When browsing back from search results the main page visibility must be reset. |
| 570 | + if (!params.search) { |
| 571 | + $('#main.content').removeClass('hidden'); |
| 572 | + $('#search.content').addClass('hidden'); |
| 573 | + } |
| 574 | + // When browsing forward to search results the previous search will be repeated, |
| 575 | + // so the currentResults are cleared to ensure the search is successful. |
| 576 | + currentResults = null; |
| 577 | + // Synchronize search bar with query string state and perform the search. |
| 578 | + $('.search-input').val(params.search); |
| 579 | + // Some browsers fire 'onpopstate' for every page load (Chrome), while others fire the |
| 580 | + // event only when actually popping a state (Firefox), which is why search() is called |
| 581 | + // both here and at the end of the startSearch() function. |
| 582 | + search(); |
| 583 | + }); |
| 584 | + } |
| 585 | + search(); |
539 | 586 | }
|
540 | 587 |
|
541 | 588 | index = buildIndex(searchIndex);
|
|
0 commit comments