summaryrefslogtreecommitdiff
path: root/resources/src/mediawiki/mediawiki.searchSuggest.js
diff options
context:
space:
mode:
Diffstat (limited to 'resources/src/mediawiki/mediawiki.searchSuggest.js')
-rw-r--r--resources/src/mediawiki/mediawiki.searchSuggest.js199
1 files changed, 199 insertions, 0 deletions
diff --git a/resources/src/mediawiki/mediawiki.searchSuggest.js b/resources/src/mediawiki/mediawiki.searchSuggest.js
new file mode 100644
index 00000000..a214cb3f
--- /dev/null
+++ b/resources/src/mediawiki/mediawiki.searchSuggest.js
@@ -0,0 +1,199 @@
+/*!
+ * Add search suggestions to the search form.
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var api, map, resultRenderCache, searchboxesSelectors,
+ // Region where the suggestions box will appear directly below
+ // (using the same width). Can be a container element or the input
+ // itself, depending on what suits best in the environment.
+ // For Vector the suggestion box should align with the simpleSearch
+ // container's borders, in other skins it should align with the input
+ // element (not the search form, as that would leave the buttons
+ // vertically between the input and the suggestions).
+ $searchRegion = $( '#simpleSearch, #searchInput' ).first(),
+ $searchInput = $( '#searchInput' );
+
+ // Compatibility map
+ map = {
+ // SimpleSearch is broken in Opera < 9.6
+ opera: [['>=', 9.6]],
+ // Older Konquerors are unable to position the suggestions correctly (bug 50805)
+ konqueror: [['>=', '4.11']],
+ docomo: false,
+ blackberry: false,
+ // Support for iOS 6 or higher. It has not been tested on iOS 5 or lower
+ ipod: [['>=', 6]],
+ iphone: [['>=', 6]]
+ };
+
+ if ( !$.client.test( map ) ) {
+ return;
+ }
+
+ // Compute form data for search suggestions functionality.
+ function computeResultRenderCache( context ) {
+ var $form, baseHref, linkParams;
+
+ // Compute common parameters for links' hrefs
+ $form = context.config.$region.closest( 'form' );
+
+ baseHref = $form.attr( 'action' );
+ baseHref += baseHref.indexOf( '?' ) > -1 ? '&' : '?';
+
+ linkParams = {};
+ $.each( $form.serializeArray(), function ( idx, obj ) {
+ linkParams[ obj.name ] = obj.value;
+ } );
+
+ return {
+ textParam: context.data.$textbox.attr( 'name' ),
+ linkParams: linkParams,
+ baseHref: baseHref
+ };
+ }
+
+ // The function used to render the suggestions.
+ function renderFunction( text, context ) {
+ if ( !resultRenderCache ) {
+ resultRenderCache = computeResultRenderCache( context );
+ }
+
+ // linkParams object is modified and reused
+ resultRenderCache.linkParams[ resultRenderCache.textParam ] = text;
+
+ // this is the container <div>, jQueryfied
+ this.text( text )
+ .wrap(
+ $( '<a>' )
+ .attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) )
+ .attr( 'title', text )
+ .addClass( 'mw-searchSuggest-link' )
+ );
+ }
+
+ function specialRenderFunction( query, context ) {
+ var $el = this;
+
+ if ( !resultRenderCache ) {
+ resultRenderCache = computeResultRenderCache( context );
+ }
+
+ // linkParams object is modified and reused
+ resultRenderCache.linkParams[ resultRenderCache.textParam ] = query;
+
+ if ( $el.children().length === 0 ) {
+ $el
+ .append(
+ $( '<div>' )
+ .addClass( 'special-label' )
+ .text( mw.msg( 'searchsuggest-containing' ) ),
+ $( '<div>' )
+ .addClass( 'special-query' )
+ .text( query )
+ )
+ .show();
+ } else {
+ $el.find( '.special-query' )
+ .text( query );
+ }
+
+ if ( $el.parent().hasClass( 'mw-searchSuggest-link' ) ) {
+ $el.parent().attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) + '&fulltext=1' );
+ } else {
+ $el.wrap(
+ $( '<a>' )
+ .attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) + '&fulltext=1' )
+ .addClass( 'mw-searchSuggest-link' )
+ );
+ }
+ }
+
+ // Generic suggestions functionality for all search boxes
+ searchboxesSelectors = [
+ // Primary searchbox on every page in standard skins
+ '#searchInput',
+ // Special:Search
+ '#powerSearchText',
+ '#searchText',
+ // Generic selector for skins with multiple searchboxes (used by CologneBlue)
+ // and for MediaWiki itself (special pages with page title inputs)
+ '.mw-searchInput'
+ ];
+ $( searchboxesSelectors.join( ', ' ) )
+ .suggestions( {
+ fetch: function ( query, response ) {
+ var node = this[0];
+
+ api = api || new mw.Api();
+
+ $.data( node, 'request', api.get( {
+ action: 'opensearch',
+ search: query,
+ namespace: 0,
+ suggest: ''
+ } ).done( function ( data ) {
+ response( data[ 1 ] );
+ } ) );
+ },
+ cancel: function () {
+ var node = this[0],
+ request = $.data( node, 'request' );
+
+ if ( request ) {
+ request.abort();
+ $.removeData( node, 'request' );
+ }
+ },
+ result: {
+ render: renderFunction,
+ select: function () {
+ // allow the form to be submitted
+ return true;
+ }
+ },
+ cache: true,
+ highlightInput: true
+ } )
+ .bind( 'paste cut drop', function () {
+ // make sure paste and cut events from the mouse and drag&drop events
+ // trigger the keypress handler and cause the suggestions to update
+ $( this ).trigger( 'keypress' );
+ } )
+ // In most skins (at least Monobook and Vector), the font-size is messed up in <body>.
+ // (they use 2 elements to get a sane font-height). So, instead of making exceptions for
+ // each skin or adding more stylesheets, just copy it from the active element so auto-fit.
+ .each( function () {
+ var $this = $( this );
+ $this
+ .data( 'suggestions-context' )
+ .data.$container
+ .css( 'fontSize', $this.css( 'fontSize' ) );
+ } );
+
+ // Ensure that the thing is actually present!
+ if ( $searchRegion.length === 0 ) {
+ // Don't try to set anything up if simpleSearch is disabled sitewide.
+ // The loader code loads us if the option is present, even if we're
+ // not actually enabled (anymore).
+ return;
+ }
+
+ // Special suggestions functionality for skin-provided search box
+ $searchInput.suggestions( {
+ special: {
+ render: specialRenderFunction,
+ select: function ( $input ) {
+ $input.closest( 'form' )
+ .append( $( '<input type="hidden" name="fulltext" value="1"/>' ) );
+ return true; // allow the form to be submitted
+ }
+ },
+ $region: $searchRegion
+ } );
+
+ // If the form includes any fallback fulltext search buttons, remove them
+ $searchInput.closest( 'form' ).find( '.mw-fallbackSearchButton' ).remove();
+ } );
+
+}( mediaWiki, jQuery ) );