script.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. function initSideNav() {
  2. var leftNavToggle = document.getElementById('sidenav-left-toggle');
  3. var leftDrawer = document.querySelector('.sidebar-offcanvas-left');
  4. var overlay = document.getElementById('overlay-under-drawer');
  5. function toggleBoth() {
  6. if (leftDrawer) {
  7. leftDrawer.classList.toggle('active');
  8. }
  9. if (overlay) {
  10. overlay.classList.toggle('active');
  11. }
  12. }
  13. if (overlay) {
  14. overlay.addEventListener('click', function(e) {
  15. toggleBoth();
  16. });
  17. }
  18. if (leftNavToggle) {
  19. leftNavToggle.addEventListener('click', function(e) {
  20. toggleBoth();
  21. });
  22. }
  23. }
  24. function saveLeftScroll() {
  25. var leftSidebar = document.getElementById('dartdoc-sidebar-left');
  26. sessionStorage.setItem('dartdoc-sidebar-left-scrollt' + window.location.pathname, leftSidebar.scrollTop);
  27. sessionStorage.setItem('dartdoc-sidebar-left-scrolll' + window.location.pathname, leftSidebar.scrollLeft);
  28. }
  29. function saveMainContentScroll() {
  30. var mainContent = document.getElementById('dartdoc-main-content');
  31. sessionStorage.setItem('dartdoc-main-content-scrollt' + window.location.pathname, mainContent.scrollTop);
  32. sessionStorage.setItem('dartdoc-main-content-scrolll' + window.location.pathname, mainContent.scrollLeft);
  33. }
  34. function saveRightScroll() {
  35. var rightSidebar = document.getElementById('dartdoc-sidebar-right');
  36. sessionStorage.setItem('dartdoc-sidebar-right-scrollt' + window.location.pathname, rightSidebar.scrollTop);
  37. sessionStorage.setItem('dartdoc-sidebar-right-scrolll' + window.location.pathname, rightSidebar.scrollLeft);
  38. }
  39. function restoreScrolls() {
  40. var leftSidebar = document.getElementById('dartdoc-sidebar-left');
  41. var mainContent = document.getElementById('dartdoc-main-content');
  42. var rightSidebar = document.getElementById('dartdoc-sidebar-right');
  43. try {
  44. var leftSidebarX = sessionStorage.getItem('dartdoc-sidebar-left-scrolll' + window.location.pathname);
  45. var leftSidebarY = sessionStorage.getItem('dartdoc-sidebar-left-scrollt' + window.location.pathname);
  46. var mainContentX = sessionStorage.getItem('dartdoc-main-content-scrolll' + window.location.pathname);
  47. var mainContentY = sessionStorage.getItem('dartdoc-main-content-scrollt' + window.location.pathname);
  48. var rightSidebarX = sessionStorage.getItem('dartdoc-sidebar-right-scrolll' + window.location.pathname);
  49. var rightSidebarY = sessionStorage.getItem('dartdoc-sidebar-right-scrollt' + window.location.pathname);
  50. leftSidebar.scrollTo(leftSidebarX, leftSidebarY);
  51. mainContent.scrollTo(mainContentX, mainContentY);
  52. rightSidebar.scrollTo(rightSidebarX, rightSidebarY);
  53. } finally {
  54. // Set visibility to visible after scroll to prevent the brief appearance of the
  55. // panel in the wrong position.
  56. leftSidebar.style.visibility = 'visible';
  57. mainContent.style.visibility = 'visible';
  58. rightSidebar.style.visibility = 'visible';
  59. }
  60. }
  61. function initScrollSave() {
  62. var leftSidebar = document.getElementById('dartdoc-sidebar-left');
  63. var mainContent = document.getElementById('dartdoc-main-content');
  64. var rightSidebar = document.getElementById('dartdoc-sidebar-right');
  65. // For portability, use two different ways of attaching saveLeftScroll to events.
  66. leftSidebar.onscroll = saveLeftScroll;
  67. leftSidebar.addEventListener("scroll", saveLeftScroll, true);
  68. mainContent.onscroll = saveMainContentScroll;
  69. mainContent.addEventListener("scroll", saveMainContentScroll, true);
  70. rightSidebar.onscroll = saveRightScroll;
  71. rightSidebar.addEventListener("scroll", saveRightScroll, true);
  72. }
  73. function initSearch(name) {
  74. var searchIndex; // the JSON data
  75. var weights = {
  76. 'library' : 2,
  77. 'class' : 2,
  78. 'typedef' : 3,
  79. 'method' : 4,
  80. 'accessor' : 4,
  81. 'operator' : 4,
  82. 'property' : 4,
  83. 'constructor' : 4
  84. };
  85. var baseHref = '';
  86. if (!$('body').data('using-base-href')) {
  87. // If dartdoc did not add a base-href tag, we will need to add the relative
  88. // path ourselves.
  89. baseHref = $('body').data('base-href');
  90. }
  91. function findMatches(q) {
  92. var allMatches = []; // list of matches
  93. function score(element, num) {
  94. num -= element.overriddenDepth * 10;
  95. var weightFactor = weights[element.type] || 4;
  96. return {e: element, score: (num / weightFactor) >> 0};
  97. }
  98. $.each(searchIndex, function(i, element) {
  99. // TODO: prefer matches in the current library
  100. // TODO: help prefer a named constructor
  101. var lowerName = element.name.toLowerCase();
  102. var lowerQualifiedName = element.qualifiedName.toLowerCase();
  103. var lowerQ = q.toLowerCase();
  104. var previousMatchCount = allMatches.length;
  105. if (element.name === q || element.qualifiedName === q) {
  106. // exact match, maximum score
  107. allMatches.push(score(element, 2000));
  108. } else if (element.name === 'dart:'+q) {
  109. // exact match for a dart: library
  110. allMatches.push(score(element, 2000));
  111. } else if (lowerName === 'dart:'+lowerQ) {
  112. // case-insensitive match for a dart: library
  113. allMatches.push(score(element, 1800));
  114. } else if (lowerName === lowerQ || lowerQualifiedName === lowerQ) {
  115. // case-insensitive exact match
  116. allMatches.push(score(element, 1700));
  117. }
  118. // only care about exact matches if length is 2 or less
  119. // and only continue if we didn't find a match above
  120. if (q.length <= 2 || previousMatchCount < allMatches.length) return;
  121. if (element.name.indexOf(q) === 0 || element.qualifiedName.indexOf(q) === 0) {
  122. // starts with
  123. allMatches.push(score(element, 750));
  124. } else if (lowerName.indexOf(lowerQ) === 0 || lowerQualifiedName.indexOf(lowerQ) === 0) {
  125. // case-insensitive starts with
  126. allMatches.push(score(element, 650));
  127. } else if (element.name.indexOf(q) >= 0 || element.qualifiedName.indexOf(q) >= 0) {
  128. // contains
  129. allMatches.push(score(element, 500));
  130. } else if (lowerName.indexOf(lowerQ) >= 0 || lowerQualifiedName.indexOf(lowerQ) >= 0) {
  131. // case insensitive contains
  132. allMatches.push(score(element, 400));
  133. }
  134. });
  135. allMatches.sort(function(a, b) {
  136. var x = b.score - a.score;
  137. if (x === 0) {
  138. // tie-breaker: shorter name wins
  139. return a.e.name.length - b.e.name.length;
  140. } else {
  141. return x;
  142. }
  143. });
  144. var sortedMatches = [];
  145. for (var i = 0; i < allMatches.length; i++) {
  146. sortedMatches.push(allMatches[i].e);
  147. }
  148. return sortedMatches;
  149. };
  150. function initTypeahead() {
  151. if ('URLSearchParams' in window) {
  152. var search = new URLSearchParams(window.location.search).get('search');
  153. if (search) {
  154. var matches = findMatches(search);
  155. if (matches.length !== 0) {
  156. window.location = baseHref + matches[0].href;
  157. return;
  158. }
  159. }
  160. }
  161. $('#' + name).prop('disabled', false);
  162. $('#' + name).prop('placeholder', 'Search API Docs');
  163. $(document).keypress(function(event) {
  164. if (event.which == 47 /* / */) {
  165. event.preventDefault();
  166. $('#' + name).focus();
  167. }
  168. });
  169. $('#' + name + '.typeahead').typeahead({
  170. hint: true,
  171. highlight: true,
  172. minLength: 1
  173. },
  174. {
  175. name: 'elements',
  176. limit: 10,
  177. source: function(q, cb) { cb(findMatches(q)); },
  178. display: function(element) { return element.name; },
  179. templates: {
  180. suggestion: function(match) {
  181. return [
  182. '<div data-href="' + match.href + '">',
  183. match.name,
  184. ' ',
  185. match.type.toLowerCase(),
  186. (match.enclosedBy ? [
  187. '<div class="search-from-lib">from ',
  188. match.enclosedBy.name,
  189. '</div>'].join('') : ''),
  190. '</div>'
  191. ].join('');
  192. }
  193. }
  194. });
  195. var typeaheadElement = $('#' + name + '.typeahead');
  196. var typeaheadElementParent = typeaheadElement.parent();
  197. var selectedSuggestion;
  198. typeaheadElement.on("keydown", function (e) {
  199. if (e.keyCode === 13) { // Enter
  200. if (selectedSuggestion == null) {
  201. var suggestion = typeaheadElementParent.find(".tt-suggestion.tt-selectable:eq(0)");
  202. if (suggestion.length > 0) {
  203. var href = suggestion.data("href");
  204. if (href != null) {
  205. window.location = baseHref + href;
  206. }
  207. }
  208. }
  209. }
  210. });
  211. typeaheadElement.bind('typeahead:select', function(ev, suggestion) {
  212. selectedSuggestion = suggestion;
  213. window.location = baseHref + suggestion.href;
  214. });
  215. }
  216. var jsonReq = new XMLHttpRequest();
  217. jsonReq.open('GET', baseHref + 'index.json', true);
  218. jsonReq.addEventListener('load', function() {
  219. searchIndex = JSON.parse(jsonReq.responseText);
  220. initTypeahead();
  221. });
  222. jsonReq.addEventListener('error', function() {
  223. $('#' + name).prop('placeholder', 'Error loading search index');
  224. });
  225. jsonReq.send();
  226. }
  227. document.addEventListener("DOMContentLoaded", function() {
  228. // Place this first so that unexpected exceptions in other JavaScript do not block page visibility.
  229. restoreScrolls();
  230. hljs.initHighlightingOnLoad();
  231. initSideNav();
  232. initScrollSave();
  233. initSearch("search-box");
  234. initSearch("search-body");
  235. initSearch("search-sidebar");
  236. });