1- // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
1+ // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
22// file at the top-level directory of this distribution and at
33// http://rust-lang.org/COPYRIGHT.
44//
1111/*jslint browser: true, es5: true */
1212/*globals $: true, searchIndex: true, rootPath: true, allPaths: true */
1313
14- ( function ( ) {
14+ ( function ( ) {
1515 "use strict" ;
1616 var resizeTimeout , interval ;
1717
2121 if ( resizeTimeout ) {
2222 clearTimeout ( resizeTimeout ) ;
2323 }
24- resizeTimeout = setTimeout ( function ( ) {
24+ resizeTimeout = setTimeout ( function ( ) {
2525 var contentWidth = $ ( '.content' ) . width ( ) ;
26- $ ( '.docblock.short' ) . width ( function ( ) {
26+ $ ( '.docblock.short' ) . width ( function ( ) {
2727 return contentWidth - 40 - $ ( this ) . prev ( ) . width ( ) ;
2828 } ) . addClass ( 'nowrap' ) ;
2929 } , 150 ) ;
5050 highlightSourceLines ( ) ;
5151 $ ( window ) . on ( 'hashchange' , highlightSourceLines ) ;
5252
53- $ ( document ) . on ( 'keyup' , function ( e ) {
53+ $ ( document ) . on ( 'keyup' , function ( e ) {
5454 if ( document . activeElement . tagName === 'INPUT' ) {
5555 return ;
5656 }
7171 e . preventDefault ( ) ;
7272 $ ( '.search-input' ) . focus ( ) ;
7373 }
74- } ) . on ( 'click' , function ( e ) {
74+ } ) . on ( 'click' , function ( e ) {
7575 if ( ! $ ( e . target ) . closest ( '#help' ) . length ) {
7676 $ ( '#help' ) . addClass ( 'hidden' ) ;
7777 }
7878 } ) ;
7979
80- $ ( '.version-selector' ) . on ( 'change' , function ( ) {
80+ $ ( '.version-selector' ) . on ( 'change' , function ( ) {
8181 var i , match ,
8282 url = document . location . href ,
8383 stripped = '' ,
102102 // clear cached values from the search bar
103103 $ ( ".search-input" ) [ 0 ] . value = '' ;
104104
105+ /**
106+ * Executes the query and builds an index of results
107+ * @param {[Object] } query [The user query]
108+ * @param {[type] } max [The maximum results returned]
109+ * @param {[type] } searchWords [The list of search words to query against]
110+ * @return {[type] } [A search index of results]
111+ */
105112 function execQuery ( query , max , searchWords ) {
106113 var valLower = query . query . toLowerCase ( ) ,
107114 val = valLower ,
108115 typeFilter = query . type ,
109116 results = [ ] ,
110117 aa = 0 ,
111- bb = 0 ;
118+ bb = 0 ,
119+ split = valLower . split ( "::" ) ;
120+
121+ //remove empty keywords
122+ for ( var j = 0 ; j < split . length ; j ++ ) {
123+ split [ j ] . toLowerCase ( ) ;
124+ if ( split [ j ] === "" ) {
125+ split . splice ( j , 1 ) ;
126+ }
127+ }
112128
113129 // quoted values mean literal search
114130 bb = searchWords . length ;
128144 } else {
129145 // gather matching search results up to a certain maximum
130146 val = val . replace ( / \_ / g, "" ) ;
131- for ( aa = 0 ; aa < bb ; aa += 1 ) {
132- if ( searchWords [ aa ] . indexOf ( val ) > - 1 || searchWords [ aa ] . replace ( / _ / g, "" ) . indexOf ( val ) > - 1 ) {
133- // filter type: ... queries
134- if ( ! typeFilter || typeFilter === searchIndex [ aa ] . ty ) {
135- results . push ( [ aa , searchWords [ aa ] . replace ( / _ / g, "" ) . indexOf ( val ) ] ) ;
147+ for ( var i = 0 ; i < split . length ; i ++ ) {
148+ for ( aa = 0 ; aa < bb ; aa += 1 ) {
149+ if ( searchWords [ aa ] . indexOf ( split [ i ] ) > - 1 || searchWords [ aa ] . indexOf ( val ) > - 1 || searchWords [ aa ] . replace ( / _ / g, "" ) . indexOf ( val ) > - 1 ) {
150+ // filter type: ... queries
151+ if ( ! typeFilter || typeFilter === searchIndex [ aa ] . ty ) {
152+ results . push ( [ aa , searchWords [ aa ] . replace ( / _ / g, "" ) . indexOf ( val ) ] ) ;
153+ }
154+ }
155+ if ( results . length === max ) {
156+ break ;
136157 }
137- }
138- if ( results . length === max ) {
139- break ;
140158 }
141159 }
142160 }
161+
143162 bb = results . length ;
144163 for ( aa = 0 ; aa < bb ; aa += 1 ) {
145164 results [ aa ] . push ( searchIndex [ results [ aa ] [ 0 ] ] . ty ) ;
146- }
147- for ( aa = 0 ; aa < bb ; aa += 1 ) {
148165 results [ aa ] . push ( searchIndex [ results [ aa ] [ 0 ] ] . path ) ;
166+ results [ aa ] . push ( searchIndex [ results [ aa ] [ 0 ] ] . name ) ;
167+ results [ aa ] . push ( searchIndex [ results [ aa ] [ 0 ] ] . parent ) ;
149168 }
150-
151169 // if there are no results then return to default and fail
152170 if ( results . length === 0 ) {
153171 return [ ] ;
154172 }
155173
174+ results . forEach ( function ( item ) {
175+ for ( var i = 0 ; i < split . length ; i ++ ) {
176+ if ( item [ 3 ] . indexOf ( split [ i ] ) === - 1 ) {
177+ item = null ;
178+ break ;
179+ }
180+ }
181+ } ) ;
156182 // sort by exact match
157183 results . sort ( function search_complete_sort0 ( aaa , bbb ) {
158184 if ( searchWords [ aaa [ 0 ] ] === valLower && searchWords [ bbb [ 0 ] ] !== valLower ) {
203229 results [ aa ] [ 0 ] = - 1 ;
204230 }
205231 }
206-
232+ for ( var i = 0 ; i < results . length ; i ++ ) {
233+ var result = results [ i ] ,
234+ name = result [ 4 ] . toLowerCase ( ) ,
235+ path = result [ 3 ] . toLowerCase ( ) ,
236+ parent = allPaths [ result [ 5 ] ] ;
237+
238+ var valid = validateResult ( name , path , split , parent ) ;
239+ if ( ! valid ) {
240+ result [ 0 ] = - 1 ;
241+ }
242+ }
207243 return results ;
208244 }
209245
246+ /**
247+ * Validate performs the following boolean logic. For example: "File::open" will give
248+ * IF A PARENT EXISTS => ("file" && "open") exists in (name || path || parent)
249+ * OR => ("file" && "open") exists in (name || path )
250+ *
251+ * This could be written functionally, but I wanted to minimise functions on stack.
252+ * @param {[string] } name [The name of the result]
253+ * @param {[string] } path [The path of the result]
254+ * @param {[string] } keys [The keys to be used (["file", "open"])]
255+ * @param {[object] } parent [The parent of the result]
256+ * @return {[boolean] } [Whether the result is valid or not]
257+ */
258+ function validateResult ( name , path , keys , parent ) {
259+ //initially valid
260+ var validate = true ;
261+ //if there is a parent, then validate against parent
262+ if ( parent !== undefined ) {
263+ for ( var i = 0 ; i < keys . length ; i ++ ) {
264+ // if previous keys are valid and current key is in the path, name or parent
265+ if ( ( validate ) && ( name . toLowerCase ( ) . indexOf ( keys [ i ] ) > - 1 || path . toLowerCase ( ) . indexOf ( keys [ i ] ) > - 1 || parent . name . toLowerCase ( ) . indexOf ( keys [ i ] ) > - 1 ) ) {
266+ validate = true ;
267+ } else {
268+ validate = false ;
269+ }
270+ }
271+ } else {
272+ for ( var i = 0 ; i < keys . length ; i ++ ) {
273+ // if previous keys are valid and current key is in the path, name
274+ if ( ( validate ) && ( name . toLowerCase ( ) . indexOf ( keys [ i ] ) > - 1 || path . toLowerCase ( ) . indexOf ( keys [ i ] ) > - 1 ) ) {
275+ validate = true ;
276+ } else {
277+ validate = false ;
278+ }
279+ }
280+ }
281+ return validate ;
282+ }
283+
210284 function getQuery ( ) {
211285 var matches , type , query = $ ( '.search-input' ) . val ( ) ;
212286
226300 function initSearchNav ( ) {
227301 var hoverTimeout , $results = $ ( '.search-results .result' ) ;
228302
229- $results . on ( 'click' , function ( ) {
303+ $results . on ( 'click' , function ( ) {
230304 var dst = $ ( this ) . find ( 'a' ) [ 0 ] ;
231305 console . log ( window . location . pathname , dst . pathname ) ;
232306 if ( window . location . pathname == dst . pathname ) {
233307 $ ( '#search' ) . addClass ( 'hidden' ) ;
234308 $ ( '#main' ) . removeClass ( 'hidden' ) ;
235309 }
236310 document . location . href = dst . href ;
237- } ) . on ( 'mouseover' , function ( ) {
311+ } ) . on ( 'mouseover' , function ( ) {
238312 var $el = $ ( this ) ;
239313 clearTimeout ( hoverTimeout ) ;
240- hoverTimeout = setTimeout ( function ( ) {
314+ hoverTimeout = setTimeout ( function ( ) {
241315 $results . removeClass ( 'highlighted' ) ;
242316 $el . addClass ( 'highlighted' ) ;
243317 } , 20 ) ;
244318 } ) ;
245319
246320 $ ( document ) . off ( 'keypress.searchnav' ) ;
247- $ ( document ) . on ( 'keypress.searchnav' , function ( e ) {
321+ $ ( document ) . on ( 'keypress.searchnav' , function ( e ) {
248322 var $active = $results . filter ( '.highlighted' ) ;
249323
250324 if ( e . keyCode === 38 ) { // up
282356 if ( results . length > 0 ) {
283357 shown = [ ] ;
284358
285- results . forEach ( function ( item ) {
359+ results . forEach ( function ( item ) {
286360 var name , type ;
287361
288362 if ( shown . indexOf ( item ) !== - 1 ) {
298372 if ( type === 'mod' ) {
299373 output += item . path +
300374 '::<a href="' + rootPath +
301- item . path . replace ( / : : / g, '/' ) + '/' +
302- name + '/index.html" class="' +
303- type + '">' + name + '</a>' ;
375+ item . path . replace ( / : : / g, '/' ) + '/' +
376+ name + '/index.html" class="' +
377+ type + '">' + name + '</a>' ;
304378 } else if ( type === 'static' || type === 'reexport' ) {
305379 output += item . path +
306380 '::<a href="' + rootPath +
307- item . path . replace ( / : : / g, '/' ) +
308- '/index.html" class="' + type +
309- '">' + name + '</a>' ;
381+ item . path . replace ( / : : / g, '/' ) +
382+ '/index.html" class="' + type +
383+ '">' + name + '</a>' ;
310384 } else if ( item . parent !== undefined ) {
311385 var myparent = allPaths [ item . parent ] ;
312386 var anchor = '#' + type + '.' + name ;
313387 output += item . path + '::' + myparent . name +
314388 '::<a href="' + rootPath +
315- item . path . replace ( / : : / g, '/' ) +
316- '/' + myparent . type +
317- '.' + myparent . name +
318- '.html' + anchor +
319- '" class="' + type +
320- '">' + name + '</a>' ;
389+ item . path . replace ( / : : / g, '/' ) +
390+ '/' + myparent . type +
391+ '.' + myparent . name +
392+ '.html' + anchor +
393+ '" class="' + type +
394+ '">' + name + '</a>' ;
321395 } else {
322396 output += item . path +
323397 '::<a href="' + rootPath +
324- item . path . replace ( / : : / g, '/' ) +
325- '/' + type +
326- '.' + name +
327- '.html" class="' + type +
328- '">' + name + '</a>' ;
398+ item . path . replace ( / : : / g, '/' ) +
399+ '/' + type +
400+ '.' + name +
401+ '.html" class="' + type +
402+ '">' + name + '</a>' ;
329403 }
330404
331405 output += '</td><td><span class="desc">' + item . desc +
332- '</span></td></tr>' ;
406+ '</span></td></tr>' ;
333407 } ) ;
334408 } else {
335409 output += 'No results :( <a href="https://duckduckgo.com/?q=' +
336- encodeURIComponent ( 'rust ' + query . query ) +
337- '">Try on DuckDuckGo?</a>' ;
410+ encodeURIComponent ( 'rust ' + query . query ) +
411+ '">Try on DuckDuckGo?</a>' ;
338412 }
339413
340414 output += "</p>" ;
341415 $ ( '#main.content' ) . addClass ( 'hidden' ) ;
342416 $ ( '#search.content' ) . removeClass ( 'hidden' ) . html ( output ) ;
343417 $ ( '#search .desc' ) . width ( $ ( '#search' ) . width ( ) - 40 -
344- $ ( '#search td:first-child' ) . first ( ) . width ( ) ) ;
418+ $ ( '#search td:first-child' ) . first ( ) . width ( ) ) ;
345419 initSearchNav ( ) ;
346420 }
347421
348422 function search ( e ) {
349- var query , filterdata = [ ] , obj , i , len ,
423+ var query ,
424+ filterdata = [ ] ,
425+ obj , i , len ,
350426 results = [ ] ,
351427 maxResults = 200 ,
352428 resultIndex ;
464540 function startSearch ( ) {
465541 var keyUpTimeout ;
466542 $ ( '.do-search' ) . on ( 'click' , search ) ;
467- $ ( '.search-input' ) . on ( 'keyup' , function ( ) {
543+ $ ( '.search-input' ) . on ( 'keyup' , function ( ) {
468544 clearTimeout ( keyUpTimeout ) ;
469545 keyUpTimeout = setTimeout ( search , 100 ) ;
470546 } ) ;
475551 }
476552
477553 initSearch ( searchIndex ) ;
478- } ( ) ) ;
554+ } ( ) ) ;
0 commit comments