r95409 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r95408‎ | r95409 | r95410 >
Date:18:22, 24 August 2011
Author:reedy
Status:ok
Tags:
Comment:
Revert r91728

Hence reverting r93382, t93383, r94236
Modified paths:
  • /trunk/phase3/includes/OutputPage.php (modified) (history)
  • /trunk/phase3/resources/Resources.php (modified) (history)
  • /trunk/phase3/resources/mediawiki.page/mediawiki.page.mwsuggest.js (deleted) (history)
  • /trunk/phase3/skins/common/mwsuggest.js (added) (history)
  • /trunk/phase3/skins/common/shared.css (modified) (history)
  • /trunk/phase3/skins/monobook/main.css (modified) (history)

Diff [purge]

Index: trunk/phase3/resources/mediawiki.page/mediawiki.page.mwsuggest.js
@@ -1,82 +0,0 @@
2 -jQuery( document ).ready( function( $ ) {
3 - var $container = $( '<div>', { 'class' : 'open-search-suggestions' } ),
4 - cache = {},
5 - $suggestionList,
6 - url = mw.util.wikiScript( 'api' ),
7 - maxRowWindow;
8 -
9 - //Append the container which will hold the menu to the body
10 - $( 'body' ).append( $container );
11 -
12 - /* Grabs namespaces from search form or
13 - * in case we're not on a search page, take it from wgSearchNamespaces.
14 - * @return Array: List of Namespaces that should be searched
15 - */
16 - var getNamespaces = function() {
17 - var namespaces = [];
18 - $( 'form#powersearch, form#search' ).find( '[name^="ns"]' ).each(function() {
19 - if ( this.checked || ( this.type == 'hidden' && this.value == '1' ) ) {
20 - namespaces.push( this.name.substring( 2 ) );
21 - }
22 - });
23 - if ( !namespaces.length ) {
24 - namespaces = mw.config.get( 'wgSearchNamespaces' );
25 - }
26 - return namespaces.join('|');
27 - };
28 -
29 - /* Helper function to make sure that the list doesn't expand below the visible part of the window */
30 - var deliverResult = function( obj, response ) {
31 - if ( obj && obj.length > 1 ) {
32 - response( obj[1] );
33 - // Get the lowest from multiple numbers using fn.apply
34 - var maxRow = Math.min.apply( Math, [7, obj[1].length, maxRowWindow] );
35 - $suggestionList.css( 'height', maxRow * $suggestionList.find( '.ui-menu-item' ).eq( 0 ).height() );
36 - } else {
37 - response( [] );
38 - }
39 - };
40 -
41 - /* The actual autocomplete setup */
42 - $( "#searchInput" ).autocomplete({
43 - minLength: 2,
44 - source: function ( request, response ) {
45 - var namespaces = getNamespaces();
46 - // We're caching queries for performance
47 - var term = request.term + namespaces;
48 - if ( term in cache ) {
49 - deliverResult( cache[term], response );
50 - return;
51 - }
52 - var params = {
53 - format : 'json',
54 - action : 'opensearch',
55 - search : request.term,
56 - namespace : namespaces
57 - };
58 - $.getJSON( url, params, function ( obj ) {
59 - // Save to cache
60 - cache[ term ] = obj;
61 - deliverResult( obj, response );
62 - });
63 - },
64 - select : function() {
65 - $( '#searchGoButton' ).click();
66 - },
67 - create : function() {
68 - $suggestionList = $container.find( 'ul' );
69 - },
70 - appendTo : '.open-search-suggestions',
71 - open : function() {
72 - maxRowWindow = Math.floor(
73 - ( $( window ).height() - $suggestionList.offset().top + $( window ).scrollTop() ) /
74 - $suggestionList.find( '.ui-menu-item' ).eq( 0 ).height()
75 - );
76 - }
77 - });
78 -
79 - /* Legacy teardown, called when things like SimpleSearch need to disable MWSuggest */
80 - window.os_MWSuggestDisable = function() {
81 - return $("#searchInput").autocomplete( "destroy" );
82 - };
83 -});
\ No newline at end of file
Index: trunk/phase3/resources/Resources.php
@@ -590,12 +590,6 @@
591591 'jquery.mwExtension',
592592 ),
593593 ),
594 - 'mediawiki.page.mwsuggest' => array(
595 - 'scripts' => 'resources/mediawiki.page/mediawiki.page.mwsuggest.js',
596 - 'dependencies' => array(
597 - 'jquery.ui.autocomplete',
598 - ),
599 - ),
600594 'mediawiki.page.ajaxCategories' => array(
601595 'scripts' => 'resources/mediawiki.page/mediawiki.page.ajaxCategories.js',
602596 'styles' => 'resources/mediawiki.page/mediawiki.page.ajaxCategories.css',
@@ -635,12 +629,6 @@
636630 'mediawiki.page.ajaxCategories',
637631 ),
638632 ),
639 - 'mediawiki.page.mwsuggest' => array(
640 - 'scripts' => 'resources/mediawiki.page/mediawiki.page.mwsuggest.js',
641 - 'dependencies' => array(
642 - 'jquery.ui.autocomplete',
643 - ),
644 - ),
645633 'mediawiki.page.ready' => array(
646634 'scripts' => 'resources/mediawiki.page/mediawiki.page.ready.js',
647635 'dependencies' => array(
@@ -732,6 +720,13 @@
733721 'localBasePath' => $GLOBALS['wgStyleDirectory'],
734722 'dependencies' => 'mediawiki.legacy.wikibits',
735723 ),
 724+ 'mediawiki.legacy.mwsuggest' => array(
 725+ 'scripts' => 'common/mwsuggest.js',
 726+ 'remoteBasePath' => $GLOBALS['wgStylePath'],
 727+ 'localBasePath' => $GLOBALS['wgStyleDirectory'],
 728+ 'dependencies' => array( 'mediawiki.legacy.wikibits', 'jquery.client' ),
 729+ 'messages' => array( 'search-mwsuggest-enabled', 'search-mwsuggest-disabled' ),
 730+ ),
736731 'mediawiki.legacy.preview' => array(
737732 'scripts' => 'common/preview.js',
738733 'remoteBasePath' => $GLOBALS['wgStylePath'],
Index: trunk/phase3/skins/monobook/main.css
@@ -1245,8 +1245,8 @@
12461246 }
12471247
12481248 /* God-damned hack for the crappy layout */
1249 -.ui-autocomplete {
1250 - font-size: 127%!important;
 1249+.os-suggest {
 1250+ font-size: 127%;
12511251 }
12521252
12531253 /* Sometimes people don't want personal tools to be lowercase! */
Index: trunk/phase3/skins/common/shared.css
@@ -222,26 +222,62 @@
223223 /*
224224 * OpenSearch ajax suggestions
225225 */
226 -.open-search-suggestions .ui-autocomplete {
227 - font-size: 95%;
228 - border: 1px solid #AAA!important;
 226+.os-suggest {
229227 overflow: auto;
230 - height: 100px;
231 - background: #FFF;
232 - background: Window;
 228+ overflow-x: hidden;
 229+ position: absolute;
 230+ top: 0px;
 231+ left: 0px;
 232+ width: 0px;
 233+ background-color: white;
 234+ background-color: Window;
 235+ border-style: solid;
 236+ border-color: #AAAAAA;
 237+ border-width: 1px;
 238+ z-index:99;
 239+ font-size:95%;
233240 }
234 -.open-search-suggestions .ui-autocomplete #ui-active-menuitem {
235 - background: #4C59A6;
236 - background: Highlight;
 241+
 242+table.os-suggest-results {
 243+ font-size: 95%;
 244+ cursor: pointer;
 245+ border: 0;
 246+ border-collapse: collapse;
 247+ width: 100%;
 248+}
 249+
 250+.os-suggest-result, .os-suggest-result-hl {
 251+ white-space: nowrap;
 252+ background-color: white;
 253+ background-color: Window;
 254+ color: black;
 255+ color: WindowText;
 256+ padding: 2px;
 257+}
 258+.os-suggest-result-hl,
 259+.os-suggest-result-hl-webkit {
 260+ background-color: #4C59A6;
237261 color: white;
 262+}
 263+.os-suggest-result-hl {
 264+ /* System colors are misimplemented in Safari 3.0 and earlier,
 265+ making highlighted text illegible... */
 266+ background-color: Highlight;
238267 color: HighlightText;
239 - border-color: #4C59A6;
240 - border-color: Highlight;
241268 }
242 -.open-search-suggestions .ui-autocomplete .ui-menu-item a{
243 - line-height: 1.1!important;
244 - font-size: 95%;
 269+
 270+.os-suggest-toggle {
 271+ position: relative;
 272+ left: 1ex;
 273+ font-size: 65%;
245274 }
 275+.os-suggest-toggle-def {
 276+ position: absolute;
 277+ top: 0px;
 278+ left: 0px;
 279+ font-size: 65%;
 280+ visibility: hidden;
 281+}
246282
247283 /* Page history styling */
248284 /* the auto-generated edit comments */
Index: trunk/phase3/skins/common/mwsuggest.js
@@ -0,0 +1,1066 @@
 2+/*
 3+ * OpenSearch ajax suggestion engine for MediaWiki
 4+ *
 5+ * uses core MediaWiki open search support to fetch suggestions
 6+ * and show them below search boxes and other inputs
 7+ *
 8+ * by Robert Stojnic (April 2008)
 9+ */
 10+
 11+// Make sure wgMWSuggestTemplate is defined
 12+if ( !mw.config.exists( 'wgMWSuggestTemplate' ) ) {
 13+ mw.config.set( 'wgMWSuggestTemplate', mw.config.get( 'wgServer' ) + mw.config.get( 'wgScriptPath' )
 14+ + "/api.php?action=opensearch\x26search={searchTerms}\x26namespace={namespaces}\x26suggest" );
 15+}
 16+
 17+// search_box_id -> Results object
 18+window.os_map = {};
 19+// cached data, url -> json_text
 20+window.os_cache = {};
 21+// global variables for suggest_keypress
 22+window.os_cur_keypressed = 0;
 23+window.os_keypressed_count = 0;
 24+// type: Timer
 25+window.os_timer = null;
 26+// tie mousedown/up events
 27+window.os_mouse_pressed = false;
 28+window.os_mouse_num = -1;
 29+// if true, the last change was made by mouse (and not keyboard)
 30+window.os_mouse_moved = false;
 31+// delay between keypress and suggestion (in ms)
 32+window.os_search_timeout = 250;
 33+// these pairs of inputs/forms will be autoloaded at startup
 34+window.os_autoload_inputs = new Array('searchInput', 'searchInput2', 'powerSearchText', 'searchText');
 35+window.os_autoload_forms = new Array('searchform', 'searchform2', 'powersearch', 'search' );
 36+// if we stopped the service
 37+window.os_is_stopped = false;
 38+// max lines to show in suggest table
 39+window.os_max_lines_per_suggest = 7;
 40+// number of steps to animate expansion/contraction of container width
 41+window.os_animation_steps = 6;
 42+// num of pixels of smallest step
 43+window.os_animation_min_step = 2;
 44+// delay between steps (in ms)
 45+window.os_animation_delay = 30;
 46+// max width of container in percent of normal size (1 == 100%)
 47+window.os_container_max_width = 2;
 48+// currently active animation timer
 49+window.os_animation_timer = null;
 50+// whether MWSuggest is enabled. Set to false when os_MWSuggestDisable() is called
 51+window.os_enabled = true;
 52+
 53+/**
 54+ * <datalist> is a new HTML5 element that allows you to manually supply
 55+ * suggestion lists and have them rendered according to the right platform
 56+ * conventions. Opera as of version 11 has a fatal problem: the suggestion
 57+ * lags behind what the user types by one keypress. (Reported as DSK-276870 to
 58+ * Opera's secret bug tracker.) However, Firefox 4 supports it without
 59+ * problems, so Opera is just blacklisted here. Ideally we wouldn't blacklist
 60+ * future versions, in case they fix it, but the fallback isn't bad at all and
 61+ * the failure if they don't fix it is very annoying, so in this case we'll
 62+ * blacklist future versions too.
 63+ */
 64+window.os_use_datalist = 'list' in document.createElement( 'input' )
 65+ && $.client.profile().name != 'opera';
 66+
 67+/** Timeout timer class that will fetch the results */
 68+window.os_Timer = function( id, r, query ) {
 69+ this.id = id;
 70+ this.r = r;
 71+ this.query = query;
 72+};
 73+
 74+/** Property class for single search box */
 75+window.os_Results = function( name, formname ) {
 76+ this.searchform = formname; // id of the searchform
 77+ this.searchbox = name; // id of the searchbox
 78+ this.container = name + 'Suggest'; // div that holds results
 79+ this.resultTable = name + 'Result'; // id base for the result table (+num = table row)
 80+ this.resultText = name + 'ResultText'; // id base for the spans within result tables (+num)
 81+ this.toggle = name + 'Toggle'; // div that has the toggle (enable/disable) link
 82+ this.query = null; // last processed query
 83+ this.results = null; // parsed titles
 84+ this.resultCount = 0; // number of results
 85+ this.original = null; // query that user entered
 86+ this.selected = -1; // which result is selected
 87+ this.containerCount = 0; // number of results visible in container
 88+ this.containerRow = 0; // height of result field in the container
 89+ this.containerTotal = 0; // total height of the container will all results
 90+ this.visible = false; // if container is visible
 91+ this.stayHidden = false; // don't try to show if lost focus
 92+};
 93+
 94+/** Timer user to animate expansion/contraction of container width */
 95+window.os_AnimationTimer = function( r, target ) {
 96+ this.r = r;
 97+ var current = document.getElementById(r.container).offsetWidth;
 98+ this.inc = Math.round( ( target - current ) / os_animation_steps );
 99+ if( this.inc < os_animation_min_step && this.inc >=0 ) {
 100+ this.inc = os_animation_min_step; // minimal animation step
 101+ }
 102+ if( this.inc > -os_animation_min_step && this.inc < 0 ) {
 103+ this.inc = -os_animation_min_step;
 104+ }
 105+ this.target = target;
 106+};
 107+
 108+/******************
 109+ * Initialization
 110+ ******************/
 111+
 112+/** Initialization, call upon page onload */
 113+window.os_MWSuggestInit = function() {
 114+ if ( !window.os_enabled ) {
 115+ return;
 116+ }
 117+
 118+ for( var i = 0; i < os_autoload_inputs.length; i++ ) {
 119+ var id = os_autoload_inputs[i];
 120+ var form = os_autoload_forms[i];
 121+ element = document.getElementById( id );
 122+ if( element != null ) {
 123+ os_initHandlers( id, form, element );
 124+ }
 125+ }
 126+};
 127+
 128+/* Teardown, called when things like SimpleSearch need to disable MWSuggest */
 129+window.os_MWSuggestTeardown = function() {
 130+ for( var i = 0; i < os_autoload_inputs.length; i++ ) {
 131+ var id = os_autoload_inputs[i];
 132+ var form = os_autoload_forms[i];
 133+ element = document.getElementById( id );
 134+ if( element != null ) {
 135+ os_teardownHandlers( id, form, element );
 136+ }
 137+ }
 138+};
 139+
 140+/* Call this to disable MWSuggest. Works regardless of whether MWSuggest has been initialized already. */
 141+window.os_MWSuggestDisable = function() {
 142+ window.os_MWSuggestTeardown();
 143+ window.os_enabled = false;
 144+}
 145+
 146+
 147+/** Init Result objects and event handlers */
 148+window.os_initHandlers = function( name, formname, element ) {
 149+ var r = new os_Results( name, formname );
 150+ var formElement = document.getElementById( formname );
 151+ if( !formElement ) {
 152+ // Older browsers (Opera 8) cannot get form elements
 153+ return;
 154+ }
 155+ // event handler
 156+ os_hookEvent( element, 'keyup', os_eventKeyup );
 157+ os_hookEvent( element, 'keydown', os_eventKeydown );
 158+ os_hookEvent( element, 'keypress', os_eventKeypress );
 159+ if ( !os_use_datalist ) {
 160+ // These are needed for the div hack to hide it if the user blurs.
 161+ os_hookEvent( element, 'blur', os_eventBlur );
 162+ os_hookEvent( element, 'focus', os_eventFocus );
 163+ // We don't want browser auto-suggestions interfering with our div, but
 164+ // autocomplete must be on for datalist to work (at least in Opera
 165+ // 10.10).
 166+ element.setAttribute( 'autocomplete', 'off' );
 167+ }
 168+ // stopping handler
 169+ os_hookEvent( formElement, 'submit', os_eventOnsubmit );
 170+ os_map[name] = r;
 171+ // toggle link
 172+ if( document.getElementById( r.toggle ) == null ) {
 173+ // TODO: disable this while we figure out a way for this to work in all browsers
 174+ /* if( name == 'searchInput' ) {
 175+ // special case: place above the main search box
 176+ var t = os_createToggle( r, 'os-suggest-toggle' );
 177+ var searchBody = document.getElementById( 'searchBody' );
 178+ var first = searchBody.parentNode.firstChild.nextSibling.appendChild(t);
 179+ } else {
 180+ // default: place below search box to the right
 181+ var t = os_createToggle( r, 'os-suggest-toggle-def' );
 182+ var top = element.offsetTop + element.offsetHeight;
 183+ var left = element.offsetLeft + element.offsetWidth;
 184+ t.style.position = 'absolute';
 185+ t.style.top = top + 'px';
 186+ t.style.left = left + 'px';
 187+ element.parentNode.appendChild( t );
 188+ // only now width gets calculated, shift right
 189+ left -= t.offsetWidth;
 190+ t.style.left = left + 'px';
 191+ t.style.visibility = 'visible';
 192+ } */
 193+ }
 194+
 195+};
 196+
 197+window.os_teardownHandlers = function( name, formname, element ) {
 198+ var formElement = document.getElementById( formname );
 199+ if( !formElement ) {
 200+ // Older browsers (Opera 8) cannot get form elements
 201+ return;
 202+ }
 203+
 204+ os_unhookEvent( element, 'keyup', os_eventKeyup );
 205+ os_unhookEvent( element, 'keydown', os_eventKeydown );
 206+ os_unhookEvent( element, 'keypress', os_eventKeypress );
 207+ if ( !os_use_datalist ) {
 208+ // These are needed for the div hack to hide it if the user blurs.
 209+ os_unhookEvent( element, 'blur', os_eventBlur );
 210+ os_unhookEvent( element, 'focus', os_eventFocus );
 211+ // We don't want browser auto-suggestions interfering with our div, but
 212+ // autocomplete must be on for datalist to work (at least in Opera
 213+ // 10.10).
 214+ element.removeAttribute( 'autocomplete' );
 215+ }
 216+ // stopping handler
 217+ os_unhookEvent( formElement, 'submit', os_eventOnsubmit );
 218+};
 219+
 220+
 221+window.os_hookEvent = function( element, hookName, hookFunct ) {
 222+ if ( element.addEventListener ) {
 223+ element.addEventListener( hookName, hookFunct, false );
 224+ } else if ( window.attachEvent ) {
 225+ element.attachEvent( 'on' + hookName, hookFunct );
 226+ }
 227+};
 228+
 229+window.os_unhookEvent = function( element, hookName, hookFunct ) {
 230+ if ( element.removeEventListener ) {
 231+ element.removeEventListener( hookName, hookFunct, false );
 232+ } else if ( element.detachEvent ) {
 233+ element.detachEvent( 'on' + hookName, hookFunct );
 234+ }
 235+}
 236+
 237+/********************
 238+ * Keyboard events
 239+ ********************/
 240+
 241+/** Event handler that will fetch results on keyup */
 242+window.os_eventKeyup = function( e ) {
 243+ var targ = os_getTarget( e );
 244+ var r = os_map[targ.id];
 245+ if( r == null ) {
 246+ return; // not our event
 247+ }
 248+
 249+ // some browsers won't generate keypressed for arrow keys, catch it
 250+ if( os_keypressed_count == 0 ) {
 251+ os_processKey( r, os_cur_keypressed, targ );
 252+ }
 253+ var query = targ.value;
 254+ os_fetchResults( r, query, os_search_timeout );
 255+};
 256+
 257+/** catch arrows up/down and escape to hide the suggestions */
 258+window.os_processKey = function( r, keypressed, targ ) {
 259+ if ( keypressed == 40 && !r.visible && os_timer == null ) {
 260+ // If the user hits the down arrow, fetch results immediately if none
 261+ // are already displayed.
 262+ r.query = '';
 263+ os_fetchResults( r, targ.value, 0 );
 264+ }
 265+ // Otherwise, if we're not using datalist, we need to handle scrolling and
 266+ // so on.
 267+ if ( os_use_datalist ) {
 268+ return;
 269+ }
 270+ if ( keypressed == 40 ) { // Arrow Down
 271+ if ( r.visible ) {
 272+ os_changeHighlight( r, r.selected, r.selected + 1, true );
 273+ }
 274+ } else if ( keypressed == 38 ) { // Arrow Up
 275+ if ( r.visible ) {
 276+ os_changeHighlight( r, r.selected, r.selected - 1, true );
 277+ }
 278+ } else if( keypressed == 27 ) { // Escape
 279+ document.getElementById( r.searchbox ).value = r.original;
 280+ r.query = r.original;
 281+ os_hideResults( r );
 282+ } else if( r.query != document.getElementById( r.searchbox ).value ) {
 283+ // os_hideResults( r ); // don't show old suggestions
 284+ }
 285+};
 286+
 287+/** When keys is held down use a timer to output regular events */
 288+window.os_eventKeypress = function( e ) {
 289+ var targ = os_getTarget( e );
 290+ var r = os_map[targ.id];
 291+ if( r == null ) {
 292+ return; // not our event
 293+ }
 294+
 295+ var keypressed = os_cur_keypressed;
 296+
 297+ os_keypressed_count++;
 298+ os_processKey( r, keypressed, targ );
 299+};
 300+
 301+/** Catch the key code (Firefox bug) */
 302+window.os_eventKeydown = function( e ) {
 303+ if ( !e ) {
 304+ e = window.event;
 305+ }
 306+ var targ = os_getTarget( e );
 307+ var r = os_map[targ.id];
 308+ if( r == null ) {
 309+ return; // not our event
 310+ }
 311+
 312+ os_mouse_moved = false;
 313+
 314+ os_cur_keypressed = ( e.keyCode == undefined ) ? e.which : e.keyCode;
 315+ os_keypressed_count = 0;
 316+};
 317+
 318+
 319+/** When the form is submitted hide everything, cancel updates... */
 320+window.os_eventOnsubmit = function( e ) {
 321+ var targ = os_getTarget( e );
 322+
 323+ os_is_stopped = true;
 324+ // kill timed requests
 325+ if( os_timer != null && os_timer.id != null ) {
 326+ clearTimeout( os_timer.id );
 327+ os_timer = null;
 328+ }
 329+ // Hide all suggestions
 330+ for( i = 0; i < os_autoload_inputs.length; i++ ) {
 331+ var r = os_map[os_autoload_inputs[i]];
 332+ if( r != null ) {
 333+ var b = document.getElementById( r.searchform );
 334+ if( b != null && b == targ ) {
 335+ // set query value so the handler won't try to fetch additional results
 336+ r.query = document.getElementById( r.searchbox ).value;
 337+ }
 338+ os_hideResults( r );
 339+ }
 340+ }
 341+ return true;
 342+};
 343+
 344+
 345+
 346+/** Hide results from the user, either making the div visibility=hidden or
 347+ * detaching the datalist from the input. */
 348+window.os_hideResults = function( r ) {
 349+ if ( os_use_datalist ) {
 350+ document.getElementById( r.searchbox ).setAttribute( 'list', '' );
 351+ } else {
 352+ var c = document.getElementById( r.container );
 353+ if ( c != null ) {
 354+ c.style.visibility = 'hidden';
 355+ }
 356+ }
 357+ r.visible = false;
 358+ r.selected = -1;
 359+};
 360+
 361+window.os_decodeValue = function( value ) {
 362+ if ( decodeURIComponent ) {
 363+ return decodeURIComponent( value );
 364+ }
 365+ if( unescape ) {
 366+ return unescape( value );
 367+ }
 368+ return null;
 369+};
 370+
 371+window.os_encodeQuery = function( value ) {
 372+ if ( encodeURIComponent ) {
 373+ return encodeURIComponent( value );
 374+ }
 375+ if( escape ) {
 376+ return escape( value );
 377+ }
 378+ return null;
 379+};
 380+
 381+/** Handles data from XMLHttpRequest, and updates the suggest results */
 382+window.os_updateResults = function( r, query, text, cacheKey ) {
 383+ os_cache[cacheKey] = text;
 384+ r.query = query;
 385+ r.original = query;
 386+ if( text == '' ) {
 387+ r.results = null;
 388+ r.resultCount = 0;
 389+ os_hideResults( r );
 390+ } else {
 391+ try {
 392+ var p = eval( '(' + text + ')' ); // simple json parse, could do a safer one
 393+ if( p.length < 2 || p[1].length == 0 ) {
 394+ r.results = null;
 395+ r.resultCount = 0;
 396+ os_hideResults( r );
 397+ return;
 398+ }
 399+ if ( os_use_datalist ) {
 400+ os_setupDatalist( r, p[1] );
 401+ } else {
 402+ os_setupDiv( r, p[1] );
 403+ }
 404+ } catch( e ) {
 405+ // bad response from server or such
 406+ os_hideResults( r );
 407+ os_cache[cacheKey] = null;
 408+ }
 409+ }
 410+};
 411+
 412+/**
 413+ * Create and populate a <datalist>.
 414+ *
 415+ * @param r os_Result object
 416+ * @param results Array of the new results to replace existing ones
 417+ */
 418+window.os_setupDatalist = function( r, results ) {
 419+ var s = document.getElementById( r.searchbox );
 420+ var c = document.getElementById( r.container );
 421+ if ( c == null ) {
 422+ c = document.createElement( 'datalist' );
 423+ c.setAttribute( 'id', r.container );
 424+ document.body.appendChild( c );
 425+ } else {
 426+ c.innerHTML = '';
 427+ }
 428+ s.setAttribute( 'list', r.container );
 429+
 430+ r.results = new Array();
 431+ r.resultCount = results.length;
 432+ r.visible = true;
 433+ for ( i = 0; i < results.length; i++ ) {
 434+ var title = os_decodeValue( results[i] );
 435+ var opt = document.createElement( 'option' );
 436+ opt.value = title;
 437+ r.results[i] = title;
 438+ c.appendChild( opt );
 439+ }
 440+};
 441+
 442+/** Fetch namespaces from checkboxes or hidden fields in the search form,
 443+ if none defined use wgSearchNamespaces global */
 444+window.os_getNamespaces = function( r ) {
 445+ var namespaces = '';
 446+ var elements = document.forms[r.searchform].elements;
 447+ for( i = 0; i < elements.length; i++ ) {
 448+ var name = elements[i].name;
 449+ if( typeof name != 'undefined' && name.length > 2 && name[0] == 'n' &&
 450+ name[1] == 's' && (
 451+ ( elements[i].type == 'checkbox' && elements[i].checked ) ||
 452+ ( elements[i].type == 'hidden' && elements[i].value == '1' )
 453+ )
 454+ ) {
 455+ if( namespaces != '' ) {
 456+ namespaces += '|';
 457+ }
 458+ namespaces += name.substring( 2 );
 459+ }
 460+ }
 461+ if( namespaces == '' ) {
 462+ namespaces = wgSearchNamespaces.join('|');
 463+ }
 464+ return namespaces;
 465+};
 466+
 467+/** Update results if user hasn't already typed something else */
 468+window.os_updateIfRelevant = function( r, query, text, cacheKey ) {
 469+ var t = document.getElementById( r.searchbox );
 470+ if( t != null && t.value == query ) { // check if response is still relevant
 471+ os_updateResults( r, query, text, cacheKey );
 472+ }
 473+ r.query = query;
 474+};
 475+
 476+/** Fetch results after some timeout */
 477+window.os_delayedFetch = function() {
 478+ if( os_timer == null ) {
 479+ return;
 480+ }
 481+ var r = os_timer.r;
 482+ var query = os_timer.query;
 483+ os_timer = null;
 484+ var path = mw.config.get( 'wgMWSuggestTemplate' ).replace( "{namespaces}", os_getNamespaces( r ) )
 485+ .replace( "{dbname}", wgDBname )
 486+ .replace( "{searchTerms}", os_encodeQuery( query ) );
 487+
 488+ // try to get from cache, if not fetch using ajax
 489+ var cached = os_cache[path];
 490+ if( cached != null && cached != undefined ) {
 491+ os_updateIfRelevant( r, query, cached, path );
 492+ } else {
 493+ var xmlhttp = sajax_init_object();
 494+ if( xmlhttp ) {
 495+ try {
 496+ xmlhttp.open( 'GET', path, true );
 497+ xmlhttp.onreadystatechange = function() {
 498+ if ( xmlhttp.readyState == 4 && typeof os_updateIfRelevant == 'function' ) {
 499+ os_updateIfRelevant( r, query, xmlhttp.responseText, path );
 500+ }
 501+ };
 502+ xmlhttp.send( null );
 503+ } catch ( e ) {
 504+ if ( window.location.hostname == 'localhost' ) {
 505+ alert( "Your browser blocks XMLHttpRequest to 'localhost', try using a real hostname for development/testing." );
 506+ }
 507+ throw e;
 508+ }
 509+ }
 510+ }
 511+};
 512+
 513+/** Init timed update via os_delayedUpdate() */
 514+window.os_fetchResults = function( r, query, timeout ) {
 515+ if( query == '' ) {
 516+ r.query = '';
 517+ os_hideResults( r );
 518+ return;
 519+ } else if( query == r.query ) {
 520+ return; // no change
 521+ }
 522+
 523+ os_is_stopped = false; // make sure we're running
 524+
 525+ // cancel any pending fetches
 526+ if( os_timer != null && os_timer.id != null ) {
 527+ clearTimeout( os_timer.id );
 528+ }
 529+ // schedule delayed fetching of results
 530+ if( timeout != 0 ) {
 531+ os_timer = new os_Timer( setTimeout( "os_delayedFetch()", timeout ), r, query );
 532+ } else {
 533+ os_timer = new os_Timer( null, r, query );
 534+ os_delayedFetch(); // do it now!
 535+ }
 536+};
 537+
 538+/** Find event target */
 539+window.os_getTarget = function( e ) {
 540+ if ( !e ) {
 541+ e = window.event;
 542+ }
 543+ if ( e.target ) {
 544+ return e.target;
 545+ } else if ( e.srcElement ) {
 546+ return e.srcElement;
 547+ } else {
 548+ return null;
 549+ }
 550+};
 551+
 552+/** Check if x is a valid integer */
 553+window.os_isNumber = function( x ) {
 554+ if( x == '' || isNaN( x ) ) {
 555+ return false;
 556+ }
 557+ for( var i = 0; i < x.length; i++ ) {
 558+ var c = x.charAt( i );
 559+ if( !( c >= '0' && c <= '9' ) ) {
 560+ return false;
 561+ }
 562+ }
 563+ return true;
 564+};
 565+
 566+/** Call this to enable suggestions on input (id=inputId), on a form (name=formName) */
 567+window.os_enableSuggestionsOn = function( inputId, formName ) {
 568+ os_initHandlers( inputId, formName, document.getElementById( inputId ) );
 569+};
 570+
 571+/** Call this to disable suggestios on input box (id=inputId) */
 572+window.os_disableSuggestionsOn = function( inputId ) {
 573+ r = os_map[inputId];
 574+ if( r != null ) {
 575+ // cancel/hide results
 576+ os_timer = null;
 577+ os_hideResults( r );
 578+ // turn autocomplete on !
 579+ document.getElementById( inputId ).setAttribute( 'autocomplete', 'on' );
 580+ // remove descriptor
 581+ os_map[inputId] = null;
 582+ }
 583+
 584+ // Remove the element from the os_autoload_* arrays
 585+ var index = os_autoload_inputs.indexOf( inputId );
 586+ if ( index >= 0 ) {
 587+ os_autoload_inputs[index] = os_autoload_forms[index] = '';
 588+ }
 589+};
 590+
 591+/************************************************
 592+ * Div-only functions (irrelevant for datalist)
 593+ ************************************************/
 594+
 595+/** Event: loss of focus of input box */
 596+window.os_eventBlur = function( e ) {
 597+ var targ = os_getTarget( e );
 598+ var r = os_map[targ.id];
 599+ if( r == null ) {
 600+ return; // not our event
 601+ }
 602+ if( !os_mouse_pressed ) {
 603+ os_hideResults( r );
 604+ // force canvas to stay hidden
 605+ r.stayHidden = true;
 606+ // cancel any pending fetches
 607+ if( os_timer != null && os_timer.id != null ) {
 608+ clearTimeout( os_timer.id );
 609+ }
 610+ os_timer = null;
 611+ }
 612+};
 613+
 614+/** Event: focus (catch only when stopped) */
 615+window.os_eventFocus = function( e ) {
 616+ var targ = os_getTarget( e );
 617+ var r = os_map[targ.id];
 618+ if( r == null ) {
 619+ return; // not our event
 620+ }
 621+ r.stayHidden = false;
 622+};
 623+
 624+/**
 625+ * Create and populate a <div>, for non-<datalist>-supporting browsers.
 626+ *
 627+ * @param r os_Result object
 628+ * @param results Array of the new results to replace existing ones
 629+ */
 630+window.os_setupDiv = function( r, results ) {
 631+ var c = document.getElementById( r.container );
 632+ if ( c == null ) {
 633+ c = os_createContainer( r );
 634+ }
 635+ c.innerHTML = os_createResultTable( r, results );
 636+ // init container table sizes
 637+ var t = document.getElementById( r.resultTable );
 638+ r.containerTotal = t.offsetHeight;
 639+ r.containerRow = t.offsetHeight / r.resultCount;
 640+ os_fitContainer( r );
 641+ os_trimResultText( r );
 642+ os_showResults( r );
 643+};
 644+
 645+/** Create the result table to be placed in the container div */
 646+window.os_createResultTable = function( r, results ) {
 647+ var c = document.getElementById( r.container );
 648+ var width = c.offsetWidth - os_operaWidthFix( c.offsetWidth );
 649+ var html = '<table class="os-suggest-results" id="' + r.resultTable + '" style="width: ' + width + 'px;">';
 650+ r.results = new Array();
 651+ r.resultCount = results.length;
 652+ for( i = 0; i < results.length; i++ ) {
 653+ var title = os_decodeValue( results[i] );
 654+ r.results[i] = title;
 655+ html += '<tr><td class="os-suggest-result" id="' + r.resultTable + i + '"><span id="' + r.resultText + i + '">' + title + '</span></td></tr>';
 656+ }
 657+ html += '</table>';
 658+ return html;
 659+};
 660+
 661+/** Show results div */
 662+window.os_showResults = function( r ) {
 663+ if( os_is_stopped ) {
 664+ return;
 665+ }
 666+ if( r.stayHidden ) {
 667+ return;
 668+ }
 669+ os_fitContainer( r );
 670+ var c = document.getElementById( r.container );
 671+ r.selected = -1;
 672+ if( c != null ) {
 673+ c.scrollTop = 0;
 674+ c.style.visibility = 'visible';
 675+ r.visible = true;
 676+ }
 677+};
 678+
 679+window.os_operaWidthFix = function( x ) {
 680+ // For browsers that don't understand overflow-x, estimate scrollbar width
 681+ if( typeof document.body.style.overflowX != 'string' ) {
 682+ return 30;
 683+ }
 684+ return 0;
 685+};
 686+
 687+/** Brower-dependent functions to find window inner size, and scroll status */
 688+window.f_clientWidth = function() {
 689+ return f_filterResults(
 690+ window.innerWidth ? window.innerWidth : 0,
 691+ document.documentElement ? document.documentElement.clientWidth : 0,
 692+ document.body ? document.body.clientWidth : 0
 693+ );
 694+};
 695+
 696+window.f_clientHeight = function() {
 697+ return f_filterResults(
 698+ window.innerHeight ? window.innerHeight : 0,
 699+ document.documentElement ? document.documentElement.clientHeight : 0,
 700+ document.body ? document.body.clientHeight : 0
 701+ );
 702+};
 703+
 704+window.f_scrollLeft = function() {
 705+ return f_filterResults(
 706+ window.pageXOffset ? window.pageXOffset : 0,
 707+ document.documentElement ? document.documentElement.scrollLeft : 0,
 708+ document.body ? document.body.scrollLeft : 0
 709+ );
 710+};
 711+
 712+window.f_scrollTop = function() {
 713+ return f_filterResults(
 714+ window.pageYOffset ? window.pageYOffset : 0,
 715+ document.documentElement ? document.documentElement.scrollTop : 0,
 716+ document.body ? document.body.scrollTop : 0
 717+ );
 718+};
 719+
 720+window.f_filterResults = function( n_win, n_docel, n_body ) {
 721+ var n_result = n_win ? n_win : 0;
 722+ if ( n_docel && ( !n_result || ( n_result > n_docel ) ) ) {
 723+ n_result = n_docel;
 724+ }
 725+ return n_body && ( !n_result || ( n_result > n_body ) ) ? n_body : n_result;
 726+};
 727+
 728+/** Get the height available for the results container */
 729+window.os_availableHeight = function( r ) {
 730+ var absTop = document.getElementById( r.container ).style.top;
 731+ var px = absTop.lastIndexOf( 'px' );
 732+ if( px > 0 ) {
 733+ absTop = absTop.substring( 0, px );
 734+ }
 735+ return f_clientHeight() - ( absTop - f_scrollTop() );
 736+};
 737+
 738+/** Get element absolute position {left,top} */
 739+window.os_getElementPosition = function( elemID ) {
 740+ var offsetTrail = document.getElementById( elemID );
 741+ var offsetLeft = 0;
 742+ var offsetTop = 0;
 743+ while ( offsetTrail ) {
 744+ offsetLeft += offsetTrail.offsetLeft;
 745+ offsetTop += offsetTrail.offsetTop;
 746+ offsetTrail = offsetTrail.offsetParent;
 747+ }
 748+ if ( navigator.userAgent.indexOf('Mac') != -1 && typeof document.body.leftMargin != 'undefined' ) {
 749+ offsetLeft += document.body.leftMargin;
 750+ offsetTop += document.body.topMargin;
 751+ }
 752+ return { left:offsetLeft, top:offsetTop };
 753+};
 754+
 755+/** Create the container div that will hold the suggested titles */
 756+window.os_createContainer = function( r ) {
 757+ var c = document.createElement( 'div' );
 758+ var s = document.getElementById( r.searchbox );
 759+ var pos = os_getElementPosition( r.searchbox );
 760+ var left = pos.left;
 761+ var top = pos.top + s.offsetHeight;
 762+ c.className = 'os-suggest';
 763+ c.setAttribute( 'id', r.container );
 764+ document.body.appendChild( c );
 765+
 766+ // dynamically generated style params
 767+ // IE workaround, cannot explicitely set "style" attribute
 768+ c = document.getElementById( r.container );
 769+ c.style.top = top + 'px';
 770+ c.style.left = left + 'px';
 771+ c.style.width = s.offsetWidth + 'px';
 772+
 773+ // mouse event handlers
 774+ c.onmouseover = function( event ) { os_eventMouseover( r.searchbox, event ); };
 775+ c.onmousemove = function( event ) { os_eventMousemove( r.searchbox, event ); };
 776+ c.onmousedown = function( event ) { return os_eventMousedown( r.searchbox, event ); };
 777+ c.onmouseup = function( event ) { os_eventMouseup( r.searchbox, event ); };
 778+ return c;
 779+};
 780+
 781+/** change container height to fit to screen */
 782+window.os_fitContainer = function( r ) {
 783+ var c = document.getElementById( r.container );
 784+ var h = os_availableHeight( r ) - 20;
 785+ var inc = r.containerRow;
 786+ h = parseInt( h / inc ) * inc;
 787+ if( h < ( 2 * inc ) && r.resultCount > 1 ) { // min: two results
 788+ h = 2 * inc;
 789+ }
 790+ if( ( h / inc ) > os_max_lines_per_suggest ) {
 791+ h = inc * os_max_lines_per_suggest;
 792+ }
 793+ if( h < r.containerTotal ) {
 794+ c.style.height = h + 'px';
 795+ r.containerCount = parseInt( Math.round( h / inc ) );
 796+ } else {
 797+ c.style.height = r.containerTotal + 'px';
 798+ r.containerCount = r.resultCount;
 799+ }
 800+};
 801+
 802+/** If some entries are longer than the box, replace text with "..." */
 803+window.os_trimResultText = function( r ) {
 804+ // find max width, first see if we could expand the container to fit it
 805+ var maxW = 0;
 806+ for( var i = 0; i < r.resultCount; i++ ) {
 807+ var e = document.getElementById( r.resultText + i );
 808+ if( e.offsetWidth > maxW ) {
 809+ maxW = e.offsetWidth;
 810+ }
 811+ }
 812+ var w = document.getElementById( r.container ).offsetWidth;
 813+ var fix = 0;
 814+ if( r.containerCount < r.resultCount ) {
 815+ fix = 20; // give 20px for scrollbar
 816+ } else {
 817+ fix = os_operaWidthFix( w );
 818+ }
 819+ if( fix < 4 ) {
 820+ fix = 4; // basic padding
 821+ }
 822+ maxW += fix;
 823+
 824+ // resize container to fit more data if permitted
 825+ var normW = document.getElementById( r.searchbox ).offsetWidth;
 826+ var prop = maxW / normW;
 827+ if( prop > os_container_max_width ) {
 828+ prop = os_container_max_width;
 829+ } else if( prop < 1 ) {
 830+ prop = 1;
 831+ }
 832+ var newW = Math.round( normW * prop );
 833+ if( w != newW ) {
 834+ w = newW;
 835+ if( os_animation_timer != null ) {
 836+ clearInterval( os_animation_timer.id );
 837+ }
 838+ os_animation_timer = new os_AnimationTimer( r, w );
 839+ os_animation_timer.id = setInterval( "os_animateChangeWidth()", os_animation_delay );
 840+ w -= fix; // this much is reserved
 841+ }
 842+
 843+ // trim results
 844+ if( w < 10 ) {
 845+ return;
 846+ }
 847+ for( var i = 0; i < r.resultCount; i++ ) {
 848+ var e = document.getElementById( r.resultText + i );
 849+ var replace = 1;
 850+ var lastW = e.offsetWidth + 1;
 851+ var iteration = 0;
 852+ var changedText = false;
 853+ while( e.offsetWidth > w && ( e.offsetWidth < lastW || iteration < 2 ) ) {
 854+ changedText = true;
 855+ lastW = e.offsetWidth;
 856+ var l = e.innerHTML;
 857+ e.innerHTML = l.substring( 0, l.length - replace ) + '...';
 858+ iteration++;
 859+ replace = 4; // how many chars to replace
 860+ }
 861+ if( changedText ) {
 862+ // show hint for trimmed titles
 863+ document.getElementById( r.resultTable + i ).setAttribute( 'title', r.results[i] );
 864+ }
 865+ }
 866+};
 867+
 868+/** Invoked on timer to animate change in container width */
 869+window.os_animateChangeWidth = function() {
 870+ var r = os_animation_timer.r;
 871+ var c = document.getElementById( r.container );
 872+ var w = c.offsetWidth;
 873+ var normW = document.getElementById( r.searchbox ).offsetWidth;
 874+ var normL = os_getElementPosition( r.searchbox ).left;
 875+ var inc = os_animation_timer.inc;
 876+ var target = os_animation_timer.target;
 877+ var nw = w + inc;
 878+ if( ( inc > 0 && nw >= target ) || ( inc <= 0 && nw <= target ) ) {
 879+ // finished !
 880+ c.style.width = target + 'px';
 881+ clearInterval( os_animation_timer.id );
 882+ os_animation_timer = null;
 883+ } else {
 884+ // in-progress
 885+ c.style.width = nw + 'px';
 886+ if( document.documentElement.dir == 'rtl' ) {
 887+ c.style.left = ( normL + normW + ( target - nw ) - os_animation_timer.target - 1 ) + 'px';
 888+ }
 889+ }
 890+};
 891+
 892+/** Change the highlighted row (i.e. suggestion), from position cur to next */
 893+window.os_changeHighlight = function( r, cur, next, updateSearchBox ) {
 894+ if ( next >= r.resultCount ) {
 895+ next = r.resultCount - 1;
 896+ }
 897+ if ( next < -1 ) {
 898+ next = -1;
 899+ }
 900+ r.selected = next;
 901+ if ( cur == next ) {
 902+ return; // nothing to do.
 903+ }
 904+
 905+ if( cur >= 0 ) {
 906+ var curRow = document.getElementById( r.resultTable + cur );
 907+ if( curRow != null ) {
 908+ curRow.className = 'os-suggest-result';
 909+ }
 910+ }
 911+ var newText;
 912+ if( next >= 0 ) {
 913+ var nextRow = document.getElementById( r.resultTable + next );
 914+ if( nextRow != null ) {
 915+ nextRow.className = os_HighlightClass();
 916+ }
 917+ newText = r.results[next];
 918+ } else {
 919+ newText = r.original;
 920+ }
 921+
 922+ // adjust the scrollbar if any
 923+ if( r.containerCount < r.resultCount ) {
 924+ var c = document.getElementById( r.container );
 925+ var vStart = c.scrollTop / r.containerRow;
 926+ var vEnd = vStart + r.containerCount;
 927+ if( next < vStart ) {
 928+ c.scrollTop = next * r.containerRow;
 929+ } else if( next >= vEnd ) {
 930+ c.scrollTop = ( next - r.containerCount + 1 ) * r.containerRow;
 931+ }
 932+ }
 933+
 934+ // update the contents of the search box
 935+ if( updateSearchBox ) {
 936+ os_updateSearchQuery( r, newText );
 937+ }
 938+};
 939+
 940+window.os_HighlightClass = function() {
 941+ var match = navigator.userAgent.match(/AppleWebKit\/(\d+)/);
 942+ if ( match ) {
 943+ var webKitVersion = parseInt( match[1] );
 944+ if ( webKitVersion < 523 ) {
 945+ // CSS system highlight colors broken on old Safari
 946+ // https://bugs.webkit.org/show_bug.cgi?id=6129
 947+ // Safari 3.0.4, 3.1 known ok
 948+ return 'os-suggest-result-hl-webkit';
 949+ }
 950+ }
 951+ return 'os-suggest-result-hl';
 952+};
 953+
 954+window.os_updateSearchQuery = function( r, newText ) {
 955+ document.getElementById( r.searchbox ).value = newText;
 956+ r.query = newText;
 957+};
 958+
 959+
 960+/********************
 961+ * Mouse events
 962+ ********************/
 963+
 964+/** Mouse over the container */
 965+window.os_eventMouseover = function( srcId, e ) {
 966+ var targ = os_getTarget( e );
 967+ var r = os_map[srcId];
 968+ if( r == null || !os_mouse_moved ) {
 969+ return; // not our event
 970+ }
 971+ var num = os_getNumberSuffix( targ.id );
 972+ if( num >= 0 ) {
 973+ os_changeHighlight( r, r.selected, num, false );
 974+ }
 975+};
 976+
 977+/* Get row where the event occured (from its id) */
 978+window.os_getNumberSuffix = function( id ) {
 979+ var num = id.substring( id.length - 2 );
 980+ if( !( num.charAt( 0 ) >= '0' && num.charAt( 0 ) <= '9' ) ) {
 981+ num = num.substring( 1 );
 982+ }
 983+ if( os_isNumber( num ) ) {
 984+ return parseInt( num );
 985+ } else {
 986+ return -1;
 987+ }
 988+};
 989+
 990+/** Save mouse move as last action */
 991+window.os_eventMousemove = function( srcId, e ) {
 992+ os_mouse_moved = true;
 993+};
 994+
 995+/** Mouse button held down, register possible click */
 996+window.os_eventMousedown = function( srcId, e ) {
 997+ var targ = os_getTarget( e );
 998+ var r = os_map[srcId];
 999+ if( r == null ) {
 1000+ return; // not our event
 1001+ }
 1002+ var num = os_getNumberSuffix( targ.id );
 1003+
 1004+ os_mouse_pressed = true;
 1005+ if( num >= 0 ) {
 1006+ os_mouse_num = num;
 1007+ // os_updateSearchQuery( r, r.results[num] );
 1008+ }
 1009+ // keep the focus on the search field
 1010+ document.getElementById( r.searchbox ).focus();
 1011+
 1012+ return false; // prevents selection
 1013+};
 1014+
 1015+/** Mouse button released, check for click on some row */
 1016+window.os_eventMouseup = function( srcId, e ) {
 1017+ var targ = os_getTarget( e );
 1018+ var r = os_map[srcId];
 1019+ if( r == null ) {
 1020+ return; // not our event
 1021+ }
 1022+ var num = os_getNumberSuffix( targ.id );
 1023+
 1024+ if( num >= 0 && os_mouse_num == num ) {
 1025+ os_updateSearchQuery( r, r.results[num] );
 1026+ os_hideResults( r );
 1027+ document.getElementById( r.searchform ).submit();
 1028+ }
 1029+ os_mouse_pressed = false;
 1030+ // keep the focus on the search field
 1031+ document.getElementById( r.searchbox ).focus();
 1032+};
 1033+
 1034+/** Toggle stuff seems to be dead code? */
 1035+
 1036+/** Return the span element that contains the toggle link */
 1037+window.os_createToggle = function( r, className ) {
 1038+ var t = document.createElement( 'span' );
 1039+ t.className = className;
 1040+ t.setAttribute( 'id', r.toggle );
 1041+ var link = document.createElement( 'a' );
 1042+ link.setAttribute( 'href', 'javascript:void(0);' );
 1043+ link.onclick = function() { os_toggle( r.searchbox, r.searchform ); };
 1044+ var msg = document.createTextNode( wgMWSuggestMessages[0] );
 1045+ link.appendChild( msg );
 1046+ t.appendChild( link );
 1047+ return t;
 1048+};
 1049+
 1050+/** Call when user clicks on some of the toggle links */
 1051+window.os_toggle = function( inputId, formName ) {
 1052+ r = os_map[inputId];
 1053+ var msg = '';
 1054+ if( r == null ) {
 1055+ os_enableSuggestionsOn( inputId, formName );
 1056+ r = os_map[inputId];
 1057+ msg = wgMWSuggestMessages[0];
 1058+ } else{
 1059+ os_disableSuggestionsOn( inputId, formName );
 1060+ msg = wgMWSuggestMessages[1];
 1061+ }
 1062+ // change message
 1063+ var link = document.getElementById( r.toggle ).firstChild;
 1064+ link.replaceChild( document.createTextNode( msg ), link.firstChild );
 1065+};
 1066+
 1067+hookEvent( 'load', os_MWSuggestInit );
Property changes on: trunk/phase3/skins/common/mwsuggest.js
___________________________________________________________________
Added: svn:eol-style
11068 + native
Index: trunk/phase3/includes/OutputPage.php
@@ -2311,7 +2311,7 @@
23122312 }
23132313
23142314 if ( $wgEnableMWSuggest && !$this->getUser()->getOption( 'disablesuggest', false ) ) {
2315 - $this->addModules( 'mediawiki.page.mwsuggest' );
 2315+ $this->addModules( 'mediawiki.legacy.mwsuggest' );
23162316 }
23172317 }
23182318

Follow-up revisions

RevisionCommit summaryAuthorDate
r964981.18: MFT r95171, r95409, r95436, r95458, r95467, r95470, r95475, r95493, r95...catrope21:04, 7 September 2011

Past revisions this follows-up on

RevisionCommit summaryAuthorDate
r91728Rewrite mwsuggest.js using j.ui.autocomplete. This gets rid of a lot of the l...diebuche14:59, 8 July 2011
r93382r91728 : Fix whitespace and two vars per CRdiebuche11:02, 28 July 2011
r94236Follow-up r93383: api param is 'namespace', not 'namespaces'.krinkle11:09, 11 August 2011

Status & tagging log