PrefixSearch: Avoid notice when no subpage exists
[mediawiki.git] / resources / src / mediawiki / mediawiki.searchSuggest.js
bloba214cb3f295c81bac93b6754ed373aeb04b523b0
1 /*!
2  * Add search suggestions to the search form.
3  */
4 ( function ( mw, $ ) {
5         $( function () {
6                 var api, map, resultRenderCache, searchboxesSelectors,
7                         // Region where the suggestions box will appear directly below
8                         // (using the same width). Can be a container element or the input
9                         // itself, depending on what suits best in the environment.
10                         // For Vector the suggestion box should align with the simpleSearch
11                         // container's borders, in other skins it should align with the input
12                         // element (not the search form, as that would leave the buttons
13                         // vertically between the input and the suggestions).
14                         $searchRegion = $( '#simpleSearch, #searchInput' ).first(),
15                         $searchInput = $( '#searchInput' );
17                 // Compatibility map
18                 map = {
19                         // SimpleSearch is broken in Opera < 9.6
20                         opera: [['>=', 9.6]],
21                         // Older Konquerors are unable to position the suggestions correctly (bug 50805)
22                         konqueror: [['>=', '4.11']],
23                         docomo: false,
24                         blackberry: false,
25                         // Support for iOS 6 or higher. It has not been tested on iOS 5 or lower
26                         ipod: [['>=', 6]],
27                         iphone: [['>=', 6]]
28                 };
30                 if ( !$.client.test( map ) ) {
31                         return;
32                 }
34                 // Compute form data for search suggestions functionality.
35                 function computeResultRenderCache( context ) {
36                         var $form, baseHref, linkParams;
38                         // Compute common parameters for links' hrefs
39                         $form = context.config.$region.closest( 'form' );
41                         baseHref = $form.attr( 'action' );
42                         baseHref += baseHref.indexOf( '?' ) > -1 ? '&' : '?';
44                         linkParams = {};
45                         $.each( $form.serializeArray(), function ( idx, obj ) {
46                                 linkParams[ obj.name ] = obj.value;
47                         } );
49                         return {
50                                 textParam: context.data.$textbox.attr( 'name' ),
51                                 linkParams: linkParams,
52                                 baseHref: baseHref
53                         };
54                 }
56                 // The function used to render the suggestions.
57                 function renderFunction( text, context ) {
58                         if ( !resultRenderCache ) {
59                                 resultRenderCache = computeResultRenderCache( context );
60                         }
62                         // linkParams object is modified and reused
63                         resultRenderCache.linkParams[ resultRenderCache.textParam ] = text;
65                         // this is the container <div>, jQueryfied
66                         this.text( text )
67                                 .wrap(
68                                         $( '<a>' )
69                                                 .attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) )
70                                                 .attr( 'title', text )
71                                                 .addClass( 'mw-searchSuggest-link' )
72                                 );
73                 }
75                 function specialRenderFunction( query, context ) {
76                         var $el = this;
78                         if ( !resultRenderCache ) {
79                                 resultRenderCache = computeResultRenderCache( context );
80                         }
82                         // linkParams object is modified and reused
83                         resultRenderCache.linkParams[ resultRenderCache.textParam ] = query;
85                         if ( $el.children().length === 0 ) {
86                                 $el
87                                         .append(
88                                                 $( '<div>' )
89                                                         .addClass( 'special-label' )
90                                                         .text( mw.msg( 'searchsuggest-containing' ) ),
91                                                 $( '<div>' )
92                                                         .addClass( 'special-query' )
93                                                         .text( query )
94                                         )
95                                         .show();
96                         } else {
97                                 $el.find( '.special-query' )
98                                         .text( query );
99                         }
101                         if ( $el.parent().hasClass( 'mw-searchSuggest-link' ) ) {
102                                 $el.parent().attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) + '&fulltext=1' );
103                         } else {
104                                 $el.wrap(
105                                         $( '<a>' )
106                                                 .attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) + '&fulltext=1' )
107                                                 .addClass( 'mw-searchSuggest-link' )
108                                 );
109                         }
110                 }
112                 // Generic suggestions functionality for all search boxes
113                 searchboxesSelectors = [
114                         // Primary searchbox on every page in standard skins
115                         '#searchInput',
116                         // Special:Search
117                         '#powerSearchText',
118                         '#searchText',
119                         // Generic selector for skins with multiple searchboxes (used by CologneBlue)
120                         // and for MediaWiki itself (special pages with page title inputs)
121                         '.mw-searchInput'
122                 ];
123                 $( searchboxesSelectors.join( ', ' ) )
124                         .suggestions( {
125                                 fetch: function ( query, response ) {
126                                         var node = this[0];
128                                         api = api || new mw.Api();
130                                         $.data( node, 'request', api.get( {
131                                                 action: 'opensearch',
132                                                 search: query,
133                                                 namespace: 0,
134                                                 suggest: ''
135                                         } ).done( function ( data ) {
136                                                 response( data[ 1 ] );
137                                         } ) );
138                                 },
139                                 cancel: function () {
140                                         var node = this[0],
141                                                 request = $.data( node, 'request' );
143                                         if ( request ) {
144                                                 request.abort();
145                                                 $.removeData( node, 'request' );
146                                         }
147                                 },
148                                 result: {
149                                         render: renderFunction,
150                                         select: function () {
151                                                 // allow the form to be submitted
152                                                 return true;
153                                         }
154                                 },
155                                 cache: true,
156                                 highlightInput: true
157                         } )
158                         .bind( 'paste cut drop', function () {
159                                 // make sure paste and cut events from the mouse and drag&drop events
160                                 // trigger the keypress handler and cause the suggestions to update
161                                 $( this ).trigger( 'keypress' );
162                         } )
163                         // In most skins (at least Monobook and Vector), the font-size is messed up in <body>.
164                         // (they use 2 elements to get a sane font-height). So, instead of making exceptions for
165                         // each skin or adding more stylesheets, just copy it from the active element so auto-fit.
166                         .each( function () {
167                                 var $this = $( this );
168                                 $this
169                                         .data( 'suggestions-context' )
170                                         .data.$container
171                                                 .css( 'fontSize', $this.css( 'fontSize' ) );
172                         } );
174                 // Ensure that the thing is actually present!
175                 if ( $searchRegion.length === 0 ) {
176                         // Don't try to set anything up if simpleSearch is disabled sitewide.
177                         // The loader code loads us if the option is present, even if we're
178                         // not actually enabled (anymore).
179                         return;
180                 }
182                 // Special suggestions functionality for skin-provided search box
183                 $searchInput.suggestions( {
184                         special: {
185                                 render: specialRenderFunction,
186                                 select: function ( $input ) {
187                                         $input.closest( 'form' )
188                                                 .append( $( '<input type="hidden" name="fulltext" value="1"/>' ) );
189                                         return true; // allow the form to be submitted
190                                 }
191                         },
192                         $region: $searchRegion
193                 } );
195                 // If the form includes any fallback fulltext search buttons, remove them
196                 $searchInput.closest( 'form' ).find( '.mw-fallbackSearchButton' ).remove();
197         } );
199 }( mediaWiki, jQuery ) );