1
- // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
1
+ // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2
2
// file at the top-level directory of this distribution and at
3
3
// http://rust-lang.org/COPYRIGHT.
4
4
//
11
11
/*jslint browser: true, es5: true */
12
12
/*globals $: true, searchIndex: true, rootPath: true, allPaths: true */
13
13
14
- ( function ( ) {
14
+ ( function ( ) {
15
15
"use strict" ;
16
16
var resizeTimeout , interval ;
17
17
21
21
if ( resizeTimeout ) {
22
22
clearTimeout ( resizeTimeout ) ;
23
23
}
24
- resizeTimeout = setTimeout ( function ( ) {
24
+ resizeTimeout = setTimeout ( function ( ) {
25
25
var contentWidth = $ ( '.content' ) . width ( ) ;
26
- $ ( '.docblock.short' ) . width ( function ( ) {
26
+ $ ( '.docblock.short' ) . width ( function ( ) {
27
27
return contentWidth - 40 - $ ( this ) . prev ( ) . width ( ) ;
28
28
} ) . addClass ( 'nowrap' ) ;
29
29
} , 150 ) ;
50
50
highlightSourceLines ( ) ;
51
51
$ ( window ) . on ( 'hashchange' , highlightSourceLines ) ;
52
52
53
- $ ( document ) . on ( 'keyup' , function ( e ) {
53
+ $ ( document ) . on ( 'keyup' , function ( e ) {
54
54
if ( document . activeElement . tagName === 'INPUT' ) {
55
55
return ;
56
56
}
71
71
e . preventDefault ( ) ;
72
72
$ ( '.search-input' ) . focus ( ) ;
73
73
}
74
- } ) . on ( 'click' , function ( e ) {
74
+ } ) . on ( 'click' , function ( e ) {
75
75
if ( ! $ ( e . target ) . closest ( '#help' ) . length ) {
76
76
$ ( '#help' ) . addClass ( 'hidden' ) ;
77
77
}
78
78
} ) ;
79
79
80
- $ ( '.version-selector' ) . on ( 'change' , function ( ) {
80
+ $ ( '.version-selector' ) . on ( 'change' , function ( ) {
81
81
var i , match ,
82
82
url = document . location . href ,
83
83
stripped = '' ,
102
102
// clear cached values from the search bar
103
103
$ ( ".search-input" ) [ 0 ] . value = '' ;
104
104
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
+ */
105
112
function execQuery ( query , max , searchWords ) {
106
113
var valLower = query . query . toLowerCase ( ) ,
107
114
val = valLower ,
108
115
typeFilter = query . type ,
109
116
results = [ ] ,
110
117
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
+ }
112
128
113
129
// quoted values mean literal search
114
130
bb = searchWords . length ;
128
144
} else {
129
145
// gather matching search results up to a certain maximum
130
146
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 ;
136
157
}
137
- }
138
- if ( results . length === max ) {
139
- break ;
140
158
}
141
159
}
142
160
}
161
+
143
162
bb = results . length ;
144
163
for ( aa = 0 ; aa < bb ; aa += 1 ) {
145
164
results [ aa ] . push ( searchIndex [ results [ aa ] [ 0 ] ] . ty ) ;
146
- }
147
- for ( aa = 0 ; aa < bb ; aa += 1 ) {
148
165
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 ) ;
149
168
}
150
-
151
169
// if there are no results then return to default and fail
152
170
if ( results . length === 0 ) {
153
171
return [ ] ;
154
172
}
155
173
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
+ } ) ;
156
182
// sort by exact match
157
183
results . sort ( function search_complete_sort0 ( aaa , bbb ) {
158
184
if ( searchWords [ aaa [ 0 ] ] === valLower && searchWords [ bbb [ 0 ] ] !== valLower ) {
203
229
results [ aa ] [ 0 ] = - 1 ;
204
230
}
205
231
}
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
+ }
207
243
return results ;
208
244
}
209
245
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
+
210
284
function getQuery ( ) {
211
285
var matches , type , query = $ ( '.search-input' ) . val ( ) ;
212
286
226
300
function initSearchNav ( ) {
227
301
var hoverTimeout , $results = $ ( '.search-results .result' ) ;
228
302
229
- $results . on ( 'click' , function ( ) {
303
+ $results . on ( 'click' , function ( ) {
230
304
var dst = $ ( this ) . find ( 'a' ) [ 0 ] ;
231
305
console . log ( window . location . pathname , dst . pathname ) ;
232
306
if ( window . location . pathname == dst . pathname ) {
233
307
$ ( '#search' ) . addClass ( 'hidden' ) ;
234
308
$ ( '#main' ) . removeClass ( 'hidden' ) ;
235
309
}
236
310
document . location . href = dst . href ;
237
- } ) . on ( 'mouseover' , function ( ) {
311
+ } ) . on ( 'mouseover' , function ( ) {
238
312
var $el = $ ( this ) ;
239
313
clearTimeout ( hoverTimeout ) ;
240
- hoverTimeout = setTimeout ( function ( ) {
314
+ hoverTimeout = setTimeout ( function ( ) {
241
315
$results . removeClass ( 'highlighted' ) ;
242
316
$el . addClass ( 'highlighted' ) ;
243
317
} , 20 ) ;
244
318
} ) ;
245
319
246
320
$ ( document ) . off ( 'keypress.searchnav' ) ;
247
- $ ( document ) . on ( 'keypress.searchnav' , function ( e ) {
321
+ $ ( document ) . on ( 'keypress.searchnav' , function ( e ) {
248
322
var $active = $results . filter ( '.highlighted' ) ;
249
323
250
324
if ( e . keyCode === 38 ) { // up
282
356
if ( results . length > 0 ) {
283
357
shown = [ ] ;
284
358
285
- results . forEach ( function ( item ) {
359
+ results . forEach ( function ( item ) {
286
360
var name , type ;
287
361
288
362
if ( shown . indexOf ( item ) !== - 1 ) {
298
372
if ( type === 'mod' ) {
299
373
output += item . path +
300
374
'::<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>' ;
304
378
} else if ( type === 'static' || type === 'reexport' ) {
305
379
output += item . path +
306
380
'::<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>' ;
310
384
} else if ( item . parent !== undefined ) {
311
385
var myparent = allPaths [ item . parent ] ;
312
386
var anchor = '#' + type + '.' + name ;
313
387
output += item . path + '::' + myparent . name +
314
388
'::<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>' ;
321
395
} else {
322
396
output += item . path +
323
397
'::<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>' ;
329
403
}
330
404
331
405
output += '</td><td><span class="desc">' + item . desc +
332
- '</span></td></tr>' ;
406
+ '</span></td></tr>' ;
333
407
} ) ;
334
408
} else {
335
409
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>' ;
338
412
}
339
413
340
414
output += "</p>" ;
341
415
$ ( '#main.content' ) . addClass ( 'hidden' ) ;
342
416
$ ( '#search.content' ) . removeClass ( 'hidden' ) . html ( output ) ;
343
417
$ ( '#search .desc' ) . width ( $ ( '#search' ) . width ( ) - 40 -
344
- $ ( '#search td:first-child' ) . first ( ) . width ( ) ) ;
418
+ $ ( '#search td:first-child' ) . first ( ) . width ( ) ) ;
345
419
initSearchNav ( ) ;
346
420
}
347
421
348
422
function search ( e ) {
349
- var query , filterdata = [ ] , obj , i , len ,
423
+ var query ,
424
+ filterdata = [ ] ,
425
+ obj , i , len ,
350
426
results = [ ] ,
351
427
maxResults = 200 ,
352
428
resultIndex ;
464
540
function startSearch ( ) {
465
541
var keyUpTimeout ;
466
542
$ ( '.do-search' ) . on ( 'click' , search ) ;
467
- $ ( '.search-input' ) . on ( 'keyup' , function ( ) {
543
+ $ ( '.search-input' ) . on ( 'keyup' , function ( ) {
468
544
clearTimeout ( keyUpTimeout ) ;
469
545
keyUpTimeout = setTimeout ( search , 100 ) ;
470
546
} ) ;
475
551
}
476
552
477
553
initSearch ( searchIndex ) ;
478
- } ( ) ) ;
554
+ } ( ) ) ;
0 commit comments