r61348 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r61347‎ | r61348 | r61349 >
Date:00:51, 22 January 2010
Author:simetrical
Status:deferred
Tags:
Comment:
Add disabled <datalist> support to mwsuggest

<datalist> is an HTML5 element that allows us to provide suggestions to
the browser to display with the proper format with no extra work on our
part. I got a working implementation, so I'm committing it for the
future, but the only supporting browser (Opera) has a small but fatal
flaw, so it's disabled unconditionally.

I moved around some code to separate out the <div>-specific parts from
the general code, which unfortunately makes this somewhat messy to
review. (I should probably have done it in two parts.) There aren't
supposed to be any functional changes in any browser, though, so if you
find any, either fix or revert.

Before enabling this feature, we'd also want to look at UI in shipping
browsers. WebKit looks like it will implement it more as a combobox, in
which case we wouldn't want to use it for WebKit. But the code will
still be useful if/when this or any other search-suggest feature becomes
standard.
Modified paths:
  • /trunk/phase3/skins/common/mwsuggest.js (modified) (history)

Diff [purge]

Index: trunk/phase3/skins/common/mwsuggest.js
@@ -40,6 +40,17 @@
4141 var os_container_max_width = 2;
4242 // currently active animation timer
4343 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;
4455
4556 /** Timeout timer class that will fetch the results */
4657 function os_Timer( id, r, query ) {
@@ -105,9 +116,15 @@
106117 os_hookEvent( element, 'keyup', function( event ) { os_eventKeyup( event ); } );
107118 os_hookEvent( element, 'keydown', function( event ) { os_eventKeydown( event ); } );
108119 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+ }
112129 // stopping handler
113130 os_hookEvent( document.getElementById( formname ), 'submit', function( event ) { return os_eventOnsubmit( event ); } );
114131 os_map[name] = r;
@@ -167,13 +184,20 @@
168185
169186 /** catch arrows up/down and escape to hide the suggestions */
170187 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+ }
171199 if ( keypressed == 40 ) { // Arrow Down
172200 if ( r.visible ) {
173201 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 );
178202 }
179203 } else if ( keypressed == 38 ) { // Arrow Up
180204 if ( r.visible ) {
@@ -219,6 +243,283 @@
220244 os_keypressed_count = 0;
221245 }
222246
 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+
223524 /** Event: loss of focus of input box */
224525 function os_eventBlur( e ) {
225526 var targ = os_getTarget( e );
@@ -248,42 +549,41 @@
249550 r.stayHidden = false;
250551 }
251552
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 );
262563 }
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 );
276572 }
277573
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 ) {
282576 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>';
285585 }
286 - r.visible = false;
287 - r.selected = -1;
 586+ html += '</table>';
 587+ return html;
288588 }
289589
290590 /** Show results div */
@@ -312,26 +612,6 @@
313613 return 0;
314614 }
315615
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 -
336616 /** Brower-dependent functions to find window inner size, and scroll status */
337617 function f_clientWidth() {
338618 return f_filterResults(
@@ -537,164 +817,6 @@
538818 }
539819 }
540820
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 -
699821 /** Change the highlighted row (i.e. suggestion), from position cur to next */
700822 function os_changeHighlight( r, cur, next, updateSearchBox ) {
701823 if ( next >= r.resultCount ) {
@@ -762,21 +884,7 @@
763885 r.query = newText;
764886 }
765887
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 -}
779888
780 -
781889 /********************
782890 * Mouse events
783891 ********************/
@@ -851,19 +959,7 @@
852960 document.getElementById( r.searchbox ).focus();
853961 }
854962
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? */
868964
869965 /** Return the span element that contains the toggle link */
870966 function os_createToggle( r, className ) {
@@ -896,29 +992,4 @@
897993 link.replaceChild( document.createTextNode( msg ), link.firstChild );
898994 }
899995
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 -
925996 hookEvent( 'load', os_MWSuggestInit );

Follow-up revisions

RevisionCommit summaryAuthorDate
r79363Enable mwsuggest datalist implementation...simetrical19:30, 31 December 2010

Status & tagging log