Index: trunk/phase3/skins/common/mwsuggest.js |
— | — | @@ -40,6 +40,17 @@ |
41 | 41 | var os_container_max_width = 2; |
42 | 42 | // currently active animation timer |
43 | 43 | var os_animation_timer = null; |
| 44 | +/** |
| 45 | + * <datalist> is a new HTML5 element that allows you to manually supply |
| 46 | + * suggestion lists and have them rendered according to the right platform |
| 47 | + * conventions. However, the only shipping browser as of early 2010 is Opera, |
| 48 | + * and that has a fatal problem: the suggestion lags behind what the user types |
| 49 | + * by one keypress. (Reported as DSK-276870 to Opera's secret bug tracker.) |
| 50 | + * The code here otherwise seems to work, though, so this can be flipped on |
| 51 | + * (maybe with a UA check) when some browser has a better implementation. |
| 52 | + */ |
| 53 | +// var os_use_datalist = 'list' in document.createElement( 'input' ); |
| 54 | +var os_use_datalist = false; |
44 | 55 | |
45 | 56 | /** Timeout timer class that will fetch the results */ |
46 | 57 | function os_Timer( id, r, query ) { |
— | — | @@ -105,9 +116,15 @@ |
106 | 117 | os_hookEvent( element, 'keyup', function( event ) { os_eventKeyup( event ); } ); |
107 | 118 | os_hookEvent( element, 'keydown', function( event ) { os_eventKeydown( event ); } ); |
108 | 119 | os_hookEvent( element, 'keypress', function( event ) { os_eventKeypress( event ); } ); |
109 | | - os_hookEvent( element, 'blur', function( event ) { os_eventBlur( event ); } ); |
110 | | - os_hookEvent( element, 'focus', function( event ) { os_eventFocus( event ); } ); |
111 | | - element.setAttribute( 'autocomplete', 'off' ); |
| 120 | + if ( !os_use_datalist ) { |
| 121 | + // These are needed for the div hack to hide it if the user blurs. |
| 122 | + os_hookEvent( element, 'blur', function( event ) { os_eventBlur( event ); } ); |
| 123 | + os_hookEvent( element, 'focus', function( event ) { os_eventFocus( event ); } ); |
| 124 | + // We don't want browser auto-suggestions interfering with our div, but |
| 125 | + // autocomplete must be on for datalist to work (at least in Opera |
| 126 | + // 10.10). |
| 127 | + element.setAttribute( 'autocomplete', 'off' ); |
| 128 | + } |
112 | 129 | // stopping handler |
113 | 130 | os_hookEvent( document.getElementById( formname ), 'submit', function( event ) { return os_eventOnsubmit( event ); } ); |
114 | 131 | os_map[name] = r; |
— | — | @@ -167,13 +184,20 @@ |
168 | 185 | |
169 | 186 | /** catch arrows up/down and escape to hide the suggestions */ |
170 | 187 | function os_processKey( r, keypressed, targ ) { |
| 188 | + if ( keypressed == 40 && !r.visible && os_timer == null ) { |
| 189 | + // If the user hits the down arrow, fetch results immediately if none |
| 190 | + // are already displayed. |
| 191 | + r.query = ''; |
| 192 | + os_fetchResults( r, targ.value, 0 ); |
| 193 | + } |
| 194 | + // Otherwise, if we're not using datalist, we need to handle scrolling and |
| 195 | + // so on. |
| 196 | + if ( os_use_datalist ) { |
| 197 | + return; |
| 198 | + } |
171 | 199 | if ( keypressed == 40 ) { // Arrow Down |
172 | 200 | if ( r.visible ) { |
173 | 201 | os_changeHighlight( r, r.selected, r.selected + 1, true ); |
174 | | - } else if( os_timer == null ) { |
175 | | - // user wants to get suggestions now |
176 | | - r.query = ''; |
177 | | - os_fetchResults( r, targ.value, 0 ); |
178 | 202 | } |
179 | 203 | } else if ( keypressed == 38 ) { // Arrow Up |
180 | 204 | if ( r.visible ) { |
— | — | @@ -219,6 +243,283 @@ |
220 | 244 | os_keypressed_count = 0; |
221 | 245 | } |
222 | 246 | |
| 247 | + |
| 248 | +/** When the form is submitted hide everything, cancel updates... */ |
| 249 | +function os_eventOnsubmit( e ) { |
| 250 | + var targ = os_getTarget( e ); |
| 251 | + |
| 252 | + os_is_stopped = true; |
| 253 | + // kill timed requests |
| 254 | + if( os_timer != null && os_timer.id != null ) { |
| 255 | + clearTimeout( os_timer.id ); |
| 256 | + os_timer = null; |
| 257 | + } |
| 258 | + // Hide all suggestions |
| 259 | + for( i = 0; i < os_autoload_inputs.length; i++ ) { |
| 260 | + var r = os_map[os_autoload_inputs[i]]; |
| 261 | + if( r != null ) { |
| 262 | + var b = document.getElementById( r.searchform ); |
| 263 | + if( b != null && b == targ ) { |
| 264 | + // set query value so the handler won't try to fetch additional results |
| 265 | + r.query = document.getElementById( r.searchbox ).value; |
| 266 | + } |
| 267 | + os_hideResults( r ); |
| 268 | + } |
| 269 | + } |
| 270 | + return true; |
| 271 | +} |
| 272 | + |
| 273 | + |
| 274 | + |
| 275 | +/** Hide results from the user, either making the div visibility=hidden or |
| 276 | + * detaching the datalist from the input. */ |
| 277 | +function os_hideResults( r ) { |
| 278 | + if ( os_use_datalist ) { |
| 279 | + document.getElementById( r.searchbox ).setAttribute( 'list', '' ); |
| 280 | + } else { |
| 281 | + var c = document.getElementById( r.container ); |
| 282 | + if ( c != null ) { |
| 283 | + c.style.visibility = 'hidden'; |
| 284 | + } |
| 285 | + } |
| 286 | + r.visible = false; |
| 287 | + r.selected = -1; |
| 288 | +} |
| 289 | + |
| 290 | +function os_decodeValue( value ) { |
| 291 | + if ( decodeURIComponent ) { |
| 292 | + return decodeURIComponent( value ); |
| 293 | + } |
| 294 | + if( unescape ) { |
| 295 | + return unescape( value ); |
| 296 | + } |
| 297 | + return null; |
| 298 | +} |
| 299 | + |
| 300 | +function os_encodeQuery( value ) { |
| 301 | + if ( encodeURIComponent ) { |
| 302 | + return encodeURIComponent( value ); |
| 303 | + } |
| 304 | + if( escape ) { |
| 305 | + return escape( value ); |
| 306 | + } |
| 307 | + return null; |
| 308 | +} |
| 309 | + |
| 310 | +/** Handles data from XMLHttpRequest, and updates the suggest results */ |
| 311 | +function os_updateResults( r, query, text, cacheKey ) { |
| 312 | + os_cache[cacheKey] = text; |
| 313 | + r.query = query; |
| 314 | + r.original = query; |
| 315 | + if( text == '' ) { |
| 316 | + r.results = null; |
| 317 | + r.resultCount = 0; |
| 318 | + os_hideResults( r ); |
| 319 | + } else { |
| 320 | + try { |
| 321 | + var p = eval( '(' + text + ')' ); // simple json parse, could do a safer one |
| 322 | + if( p.length < 2 || p[1].length == 0 ) { |
| 323 | + r.results = null; |
| 324 | + r.resultCount = 0; |
| 325 | + os_hideResults( r ); |
| 326 | + return; |
| 327 | + } |
| 328 | + if ( os_use_datalist ) { |
| 329 | + os_setupDatalist( r, p[1] ); |
| 330 | + } else { |
| 331 | + os_setupDiv( r, p[1] ); |
| 332 | + } |
| 333 | + } catch( e ) { |
| 334 | + // bad response from server or such |
| 335 | + os_hideResults( r ); |
| 336 | + os_cache[cacheKey] = null; |
| 337 | + } |
| 338 | + } |
| 339 | +} |
| 340 | + |
| 341 | +/** |
| 342 | + * Create and populate a <datalist>. |
| 343 | + * |
| 344 | + * @param r os_Result object |
| 345 | + * @param results Array of the new results to replace existing ones |
| 346 | + */ |
| 347 | +function os_setupDatalist( r, results ) { |
| 348 | + var s = document.getElementById( r.searchbox ); |
| 349 | + var c = document.getElementById( r.container ); |
| 350 | + if ( c == null ) { |
| 351 | + c = document.createElement( 'datalist' ); |
| 352 | + c.setAttribute( 'id', r.container ); |
| 353 | + document.body.appendChild( c ); |
| 354 | + } else { |
| 355 | + c.innerHTML = ''; |
| 356 | + } |
| 357 | + s.setAttribute( 'list', r.container ); |
| 358 | + |
| 359 | + r.results = new Array(); |
| 360 | + r.resultCount = results.length; |
| 361 | + r.visible = true; |
| 362 | + for ( i = 0; i < results.length; i++ ) { |
| 363 | + var title = os_decodeValue( results[i] ); |
| 364 | + var opt = document.createElement( 'option' ); |
| 365 | + opt.value = title; |
| 366 | + r.results[i] = title; |
| 367 | + c.appendChild( opt ); |
| 368 | + } |
| 369 | +} |
| 370 | + |
| 371 | +/** Fetch namespaces from checkboxes or hidden fields in the search form, |
| 372 | + if none defined use wgSearchNamespaces global */ |
| 373 | +function os_getNamespaces( r ) { |
| 374 | + var namespaces = ''; |
| 375 | + var elements = document.forms[r.searchform].elements; |
| 376 | + for( i = 0; i < elements.length; i++ ) { |
| 377 | + var name = elements[i].name; |
| 378 | + if( typeof name != 'undefined' && name.length > 2 && name[0] == 'n' && |
| 379 | + name[1] == 's' && ( |
| 380 | + ( elements[i].type == 'checkbox' && elements[i].checked ) || |
| 381 | + ( elements[i].type == 'hidden' && elements[i].value == '1' ) |
| 382 | + ) |
| 383 | + ) { |
| 384 | + if( namespaces != '' ) { |
| 385 | + namespaces += '|'; |
| 386 | + } |
| 387 | + namespaces += name.substring( 2 ); |
| 388 | + } |
| 389 | + } |
| 390 | + if( namespaces == '' ) { |
| 391 | + namespaces = wgSearchNamespaces.join('|'); |
| 392 | + } |
| 393 | + return namespaces; |
| 394 | +} |
| 395 | + |
| 396 | +/** Update results if user hasn't already typed something else */ |
| 397 | +function os_updateIfRelevant( r, query, text, cacheKey ) { |
| 398 | + var t = document.getElementById( r.searchbox ); |
| 399 | + if( t != null && t.value == query ) { // check if response is still relevant |
| 400 | + os_updateResults( r, query, text, cacheKey ); |
| 401 | + } |
| 402 | + r.query = query; |
| 403 | +} |
| 404 | + |
| 405 | +/** Fetch results after some timeout */ |
| 406 | +function os_delayedFetch() { |
| 407 | + if( os_timer == null ) { |
| 408 | + return; |
| 409 | + } |
| 410 | + var r = os_timer.r; |
| 411 | + var query = os_timer.query; |
| 412 | + os_timer = null; |
| 413 | + var path = wgMWSuggestTemplate.replace( "{namespaces}", os_getNamespaces( r ) ) |
| 414 | + .replace( "{dbname}", wgDBname ) |
| 415 | + .replace( "{searchTerms}", os_encodeQuery( query ) ); |
| 416 | + |
| 417 | + // try to get from cache, if not fetch using ajax |
| 418 | + var cached = os_cache[path]; |
| 419 | + if( cached != null && cached != undefined ) { |
| 420 | + os_updateIfRelevant( r, query, cached, path ); |
| 421 | + } else { |
| 422 | + var xmlhttp = sajax_init_object(); |
| 423 | + if( xmlhttp ) { |
| 424 | + try { |
| 425 | + xmlhttp.open( 'GET', path, true ); |
| 426 | + xmlhttp.onreadystatechange = function() { |
| 427 | + if ( xmlhttp.readyState == 4 && typeof os_updateIfRelevant == 'function' ) { |
| 428 | + os_updateIfRelevant( r, query, xmlhttp.responseText, path ); |
| 429 | + } |
| 430 | + }; |
| 431 | + xmlhttp.send( null ); |
| 432 | + } catch ( e ) { |
| 433 | + if ( window.location.hostname == 'localhost' ) { |
| 434 | + alert( "Your browser blocks XMLHttpRequest to 'localhost', try using a real hostname for development/testing." ); |
| 435 | + } |
| 436 | + throw e; |
| 437 | + } |
| 438 | + } |
| 439 | + } |
| 440 | +} |
| 441 | + |
| 442 | +/** Init timed update via os_delayedUpdate() */ |
| 443 | +function os_fetchResults( r, query, timeout ) { |
| 444 | + if( query == '' ) { |
| 445 | + r.query = ''; |
| 446 | + os_hideResults( r ); |
| 447 | + return; |
| 448 | + } else if( query == r.query ) { |
| 449 | + return; // no change |
| 450 | + } |
| 451 | + |
| 452 | + os_is_stopped = false; // make sure we're running |
| 453 | + |
| 454 | + // cancel any pending fetches |
| 455 | + if( os_timer != null && os_timer.id != null ) { |
| 456 | + clearTimeout( os_timer.id ); |
| 457 | + } |
| 458 | + // schedule delayed fetching of results |
| 459 | + if( timeout != 0 ) { |
| 460 | + os_timer = new os_Timer( setTimeout( "os_delayedFetch()", timeout ), r, query ); |
| 461 | + } else { |
| 462 | + os_timer = new os_Timer( null, r, query ); |
| 463 | + os_delayedFetch(); // do it now! |
| 464 | + } |
| 465 | +} |
| 466 | + |
| 467 | +/** Find event target */ |
| 468 | +function os_getTarget( e ) { |
| 469 | + if ( !e ) { |
| 470 | + e = window.event; |
| 471 | + } |
| 472 | + if ( e.target ) { |
| 473 | + return e.target; |
| 474 | + } else if ( e.srcElement ) { |
| 475 | + return e.srcElement; |
| 476 | + } else { |
| 477 | + return null; |
| 478 | + } |
| 479 | +} |
| 480 | + |
| 481 | +/** Check if x is a valid integer */ |
| 482 | +function os_isNumber( x ) { |
| 483 | + if( x == '' || isNaN( x ) ) { |
| 484 | + return false; |
| 485 | + } |
| 486 | + for( var i = 0; i < x.length; i++ ) { |
| 487 | + var c = x.charAt( i ); |
| 488 | + if( !( c >= '0' && c <= '9' ) ) { |
| 489 | + return false; |
| 490 | + } |
| 491 | + } |
| 492 | + return true; |
| 493 | +} |
| 494 | + |
| 495 | +/** Call this to enable suggestions on input (id=inputId), on a form (name=formName) */ |
| 496 | +function os_enableSuggestionsOn( inputId, formName ) { |
| 497 | + os_initHandlers( inputId, formName, document.getElementById( inputId ) ); |
| 498 | +} |
| 499 | + |
| 500 | +/** Call this to disable suggestios on input box (id=inputId) */ |
| 501 | +function os_disableSuggestionsOn( inputId ) { |
| 502 | + r = os_map[inputId]; |
| 503 | + if( r != null ) { |
| 504 | + // cancel/hide results |
| 505 | + os_timer = null; |
| 506 | + os_hideResults( r ); |
| 507 | + // turn autocomplete on ! |
| 508 | + document.getElementById( inputId ).setAttribute( 'autocomplete', 'on' ); |
| 509 | + // remove descriptor |
| 510 | + os_map[inputId] = null; |
| 511 | + } |
| 512 | + |
| 513 | + // Remove the element from the os_autoload_* arrays |
| 514 | + var index = os_autoload_inputs.indexOf( inputId ); |
| 515 | + if ( index >= 0 ) { |
| 516 | + os_autoload_inputs[index] = os_autoload_forms[index] = ''; |
| 517 | + } |
| 518 | +} |
| 519 | + |
| 520 | +/************************************************ |
| 521 | + * Div-only functions (irrelevant for datalist) |
| 522 | + ************************************************/ |
| 523 | + |
223 | 524 | /** Event: loss of focus of input box */ |
224 | 525 | function os_eventBlur( e ) { |
225 | 526 | var targ = os_getTarget( e ); |
— | — | @@ -248,42 +549,41 @@ |
249 | 550 | r.stayHidden = false; |
250 | 551 | } |
251 | 552 | |
252 | | - |
253 | | -/** When the form is submitted hide everything, cancel updates... */ |
254 | | -function os_eventOnsubmit( e ) { |
255 | | - var targ = os_getTarget( e ); |
256 | | - |
257 | | - os_is_stopped = true; |
258 | | - // kill timed requests |
259 | | - if( os_timer != null && os_timer.id != null ) { |
260 | | - clearTimeout( os_timer.id ); |
261 | | - os_timer = null; |
| 553 | +/** |
| 554 | + * Create and populate a <div>, for non-<datalist>-supporting browsers. |
| 555 | + * |
| 556 | + * @param r os_Result object |
| 557 | + * @param results Array of the new results to replace existing ones |
| 558 | + */ |
| 559 | +function os_setupDiv( r, results ) { |
| 560 | + var c = document.getElementById( r.container ); |
| 561 | + if ( c == null ) { |
| 562 | + c = os_createContainer( r ); |
262 | 563 | } |
263 | | - // Hide all suggestions |
264 | | - for( i = 0; i < os_autoload_inputs.length; i++ ) { |
265 | | - var r = os_map[os_autoload_inputs[i]]; |
266 | | - if( r != null ) { |
267 | | - var b = document.getElementById( r.searchform ); |
268 | | - if( b != null && b == targ ) { |
269 | | - // set query value so the handler won't try to fetch additional results |
270 | | - r.query = document.getElementById( r.searchbox ).value; |
271 | | - } |
272 | | - os_hideResults( r ); |
273 | | - } |
274 | | - } |
275 | | - return true; |
| 564 | + c.innerHTML = os_createResultTable( r, results ); |
| 565 | + // init container table sizes |
| 566 | + var t = document.getElementById( r.resultTable ); |
| 567 | + r.containerTotal = t.offsetHeight; |
| 568 | + r.containerRow = t.offsetHeight / r.resultCount; |
| 569 | + os_fitContainer( r ); |
| 570 | + os_trimResultText( r ); |
| 571 | + os_showResults( r ); |
276 | 572 | } |
277 | 573 | |
278 | | - |
279 | | - |
280 | | -/** Hide results div */ |
281 | | -function os_hideResults( r ) { |
| 574 | +/** Create the result table to be placed in the container div */ |
| 575 | +function os_createResultTable( r, results ) { |
282 | 576 | var c = document.getElementById( r.container ); |
283 | | - if( c != null ) { |
284 | | - c.style.visibility = 'hidden'; |
| 577 | + var width = c.offsetWidth - os_operaWidthFix( c.offsetWidth ); |
| 578 | + var html = '<table class="os-suggest-results" id="' + r.resultTable + '" style="width: ' + width + 'px;">'; |
| 579 | + r.results = new Array(); |
| 580 | + r.resultCount = results.length; |
| 581 | + for( i = 0; i < results.length; i++ ) { |
| 582 | + var title = os_decodeValue( results[i] ); |
| 583 | + r.results[i] = title; |
| 584 | + html += '<tr><td class="os-suggest-result" id="' + r.resultTable + i + '"><span id="' + r.resultText + i + '">' + title + '</span></td></tr>'; |
285 | 585 | } |
286 | | - r.visible = false; |
287 | | - r.selected = -1; |
| 586 | + html += '</table>'; |
| 587 | + return html; |
288 | 588 | } |
289 | 589 | |
290 | 590 | /** Show results div */ |
— | — | @@ -312,26 +612,6 @@ |
313 | 613 | return 0; |
314 | 614 | } |
315 | 615 | |
316 | | -function os_encodeQuery( value ) { |
317 | | - if ( encodeURIComponent ) { |
318 | | - return encodeURIComponent( value ); |
319 | | - } |
320 | | - if( escape ) { |
321 | | - return escape( value ); |
322 | | - } |
323 | | - return null; |
324 | | -} |
325 | | - |
326 | | -function os_decodeValue( value ) { |
327 | | - if ( decodeURIComponent ) { |
328 | | - return decodeURIComponent( value ); |
329 | | - } |
330 | | - if( unescape ) { |
331 | | - return unescape( value ); |
332 | | - } |
333 | | - return null; |
334 | | -} |
335 | | - |
336 | 616 | /** Brower-dependent functions to find window inner size, and scroll status */ |
337 | 617 | function f_clientWidth() { |
338 | 618 | return f_filterResults( |
— | — | @@ -537,164 +817,6 @@ |
538 | 818 | } |
539 | 819 | } |
540 | 820 | |
541 | | -/** Handles data from XMLHttpRequest, and updates the suggest results */ |
542 | | -function os_updateResults( r, query, text, cacheKey ) { |
543 | | - os_cache[cacheKey] = text; |
544 | | - r.query = query; |
545 | | - r.original = query; |
546 | | - if( text == '' ) { |
547 | | - r.results = null; |
548 | | - r.resultCount = 0; |
549 | | - os_hideResults( r ); |
550 | | - } else { |
551 | | - try { |
552 | | - var p = eval( '(' + text + ')' ); // simple json parse, could do a safer one |
553 | | - if( p.length < 2 || p[1].length == 0 ) { |
554 | | - r.results = null; |
555 | | - r.resultCount = 0; |
556 | | - os_hideResults( r ); |
557 | | - return; |
558 | | - } |
559 | | - var c = document.getElementById( r.container ); |
560 | | - if( c == null ) { |
561 | | - c = os_createContainer( r ); |
562 | | - } |
563 | | - c.innerHTML = os_createResultTable( r, p[1] ); |
564 | | - // init container table sizes |
565 | | - var t = document.getElementById( r.resultTable ); |
566 | | - r.containerTotal = t.offsetHeight; |
567 | | - r.containerRow = t.offsetHeight / r.resultCount; |
568 | | - os_fitContainer( r ); |
569 | | - os_trimResultText( r ); |
570 | | - os_showResults( r ); |
571 | | - } catch( e ) { |
572 | | - // bad response from server or such |
573 | | - os_hideResults( r ); |
574 | | - os_cache[cacheKey] = null; |
575 | | - } |
576 | | - } |
577 | | -} |
578 | | - |
579 | | -/** Create the result table to be placed in the container div */ |
580 | | -function os_createResultTable( r, results ) { |
581 | | - var c = document.getElementById( r.container ); |
582 | | - var width = c.offsetWidth - os_operaWidthFix( c.offsetWidth ); |
583 | | - var html = '<table class="os-suggest-results" id="' + r.resultTable + '" style="width: ' + width + 'px;">'; |
584 | | - r.results = new Array(); |
585 | | - r.resultCount = results.length; |
586 | | - for( i = 0; i < results.length; i++ ) { |
587 | | - var title = os_decodeValue( results[i] ); |
588 | | - r.results[i] = title; |
589 | | - html += '<tr><td class="os-suggest-result" id="' + r.resultTable + i + '"><span id="' + r.resultText + i + '">' + title + '</span></td></tr>'; |
590 | | - } |
591 | | - html += '</table>'; |
592 | | - return html; |
593 | | -} |
594 | | - |
595 | | -/** Fetch namespaces from checkboxes or hidden fields in the search form, |
596 | | - if none defined use wgSearchNamespaces global */ |
597 | | -function os_getNamespaces( r ) { |
598 | | - var namespaces = ''; |
599 | | - var elements = document.forms[r.searchform].elements; |
600 | | - for( i = 0; i < elements.length; i++ ) { |
601 | | - var name = elements[i].name; |
602 | | - if( typeof name != 'undefined' && name.length > 2 && name[0] == 'n' && |
603 | | - name[1] == 's' && ( |
604 | | - ( elements[i].type == 'checkbox' && elements[i].checked ) || |
605 | | - ( elements[i].type == 'hidden' && elements[i].value == '1' ) |
606 | | - ) |
607 | | - ) { |
608 | | - if( namespaces != '' ) { |
609 | | - namespaces += '|'; |
610 | | - } |
611 | | - namespaces += name.substring( 2 ); |
612 | | - } |
613 | | - } |
614 | | - if( namespaces == '' ) { |
615 | | - namespaces = wgSearchNamespaces.join('|'); |
616 | | - } |
617 | | - return namespaces; |
618 | | -} |
619 | | - |
620 | | -/** Update results if user hasn't already typed something else */ |
621 | | -function os_updateIfRelevant( r, query, text, cacheKey ) { |
622 | | - var t = document.getElementById( r.searchbox ); |
623 | | - if( t != null && t.value == query ) { // check if response is still relevant |
624 | | - os_updateResults( r, query, text, cacheKey ); |
625 | | - } |
626 | | - r.query = query; |
627 | | -} |
628 | | - |
629 | | -/** Fetch results after some timeout */ |
630 | | -function os_delayedFetch() { |
631 | | - if( os_timer == null ) { |
632 | | - return; |
633 | | - } |
634 | | - var r = os_timer.r; |
635 | | - var query = os_timer.query; |
636 | | - os_timer = null; |
637 | | - var path = wgMWSuggestTemplate.replace( "{namespaces}", os_getNamespaces( r ) ) |
638 | | - .replace( "{dbname}", wgDBname ) |
639 | | - .replace( "{searchTerms}", os_encodeQuery( query ) ); |
640 | | - |
641 | | - // try to get from cache, if not fetch using ajax |
642 | | - var cached = os_cache[path]; |
643 | | - if( cached != null ) { |
644 | | - os_updateIfRelevant( r, query, cached, path ); |
645 | | - } else { |
646 | | - var xmlhttp = sajax_init_object(); |
647 | | - if( xmlhttp ) { |
648 | | - try { |
649 | | - xmlhttp.open( 'GET', path, true ); |
650 | | - xmlhttp.onreadystatechange = function() { |
651 | | - if ( xmlhttp.readyState == 4 && typeof os_updateIfRelevant == 'function' ) { |
652 | | - os_updateIfRelevant( r, query, xmlhttp.responseText, path ); |
653 | | - } |
654 | | - }; |
655 | | - xmlhttp.send( null ); |
656 | | - } catch ( e ) { |
657 | | - if ( window.location.hostname == 'localhost' ) { |
658 | | - alert( "Your browser blocks XMLHttpRequest to 'localhost', try using a real hostname for development/testing." ); |
659 | | - } |
660 | | - throw e; |
661 | | - } |
662 | | - } |
663 | | - } |
664 | | -} |
665 | | - |
666 | | -/** Init timed update via os_delayedUpdate() */ |
667 | | -function os_fetchResults( r, query, timeout ) { |
668 | | - if( query == '' ) { |
669 | | - r.query = ''; |
670 | | - os_hideResults( r ); |
671 | | - return; |
672 | | - } else if( query == r.query ) { |
673 | | - return; // no change |
674 | | - } |
675 | | - |
676 | | - os_is_stopped = false; // make sure we're running |
677 | | - |
678 | | - /* var cacheKey = wgDBname + ':' + query; |
679 | | - var cached = os_cache[cacheKey]; |
680 | | - if( cached != null ) { |
681 | | - os_updateResults( r, wgDBname, query, cached ); |
682 | | - return; |
683 | | - } */ |
684 | | - |
685 | | - // cancel any pending fetches |
686 | | - if( os_timer != null && os_timer.id != null ) { |
687 | | - clearTimeout( os_timer.id ); |
688 | | - } |
689 | | - // schedule delayed fetching of results |
690 | | - if( timeout != 0 ) { |
691 | | - os_timer = new os_Timer( setTimeout( "os_delayedFetch()", timeout ), r, query ); |
692 | | - } else { |
693 | | - os_timer = new os_Timer( null, r, query ); |
694 | | - os_delayedFetch(); // do it now! |
695 | | - } |
696 | | - |
697 | | -} |
698 | | - |
699 | 821 | /** Change the highlighted row (i.e. suggestion), from position cur to next */ |
700 | 822 | function os_changeHighlight( r, cur, next, updateSearchBox ) { |
701 | 823 | if ( next >= r.resultCount ) { |
— | — | @@ -762,21 +884,7 @@ |
763 | 885 | r.query = newText; |
764 | 886 | } |
765 | 887 | |
766 | | -/** Find event target */ |
767 | | -function os_getTarget( e ) { |
768 | | - if ( !e ) { |
769 | | - e = window.event; |
770 | | - } |
771 | | - if ( e.target ) { |
772 | | - return e.target; |
773 | | - } else if ( e.srcElement ) { |
774 | | - return e.srcElement; |
775 | | - } else { |
776 | | - return null; |
777 | | - } |
778 | | -} |
779 | 888 | |
780 | | - |
781 | 889 | /******************** |
782 | 890 | * Mouse events |
783 | 891 | ********************/ |
— | — | @@ -851,19 +959,7 @@ |
852 | 960 | document.getElementById( r.searchbox ).focus(); |
853 | 961 | } |
854 | 962 | |
855 | | -/** Check if x is a valid integer */ |
856 | | -function os_isNumber( x ) { |
857 | | - if( x == '' || isNaN( x ) ) { |
858 | | - return false; |
859 | | - } |
860 | | - for( var i = 0; i < x.length; i++ ) { |
861 | | - var c = x.charAt( i ); |
862 | | - if( !( c >= '0' && c <= '9' ) ) { |
863 | | - return false; |
864 | | - } |
865 | | - } |
866 | | - return true; |
867 | | -} |
| 963 | +/** Toggle stuff seems to be dead code? */ |
868 | 964 | |
869 | 965 | /** Return the span element that contains the toggle link */ |
870 | 966 | function os_createToggle( r, className ) { |
— | — | @@ -896,29 +992,4 @@ |
897 | 993 | link.replaceChild( document.createTextNode( msg ), link.firstChild ); |
898 | 994 | } |
899 | 995 | |
900 | | -/** Call this to enable suggestions on input (id=inputId), on a form (name=formName) */ |
901 | | -function os_enableSuggestionsOn( inputId, formName ) { |
902 | | - os_initHandlers( inputId, formName, document.getElementById( inputId ) ); |
903 | | -} |
904 | | - |
905 | | -/** Call this to disable suggestios on input box (id=inputId) */ |
906 | | -function os_disableSuggestionsOn( inputId ) { |
907 | | - r = os_map[inputId]; |
908 | | - if( r != null ) { |
909 | | - // cancel/hide results |
910 | | - os_timer = null; |
911 | | - os_hideResults( r ); |
912 | | - // turn autocomplete on ! |
913 | | - document.getElementById( inputId ).setAttribute( 'autocomplete', 'on' ); |
914 | | - // remove descriptor |
915 | | - os_map[inputId] = null; |
916 | | - } |
917 | | - |
918 | | - // Remove the element from the os_autoload_* arrays |
919 | | - var index = os_autoload_inputs.indexOf( inputId ); |
920 | | - if ( index >= 0 ) { |
921 | | - os_autoload_inputs[index] = os_autoload_forms[index] = ''; |
922 | | - } |
923 | | -} |
924 | | - |
925 | 996 | hookEvent( 'load', os_MWSuggestInit ); |