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.js161
1 files changed, 117 insertions, 44 deletions
diff --git a/resources/src/mediawiki/mediawiki.searchSuggest.js b/resources/src/mediawiki/mediawiki.searchSuggest.js
index 7b7ccf3f..6c7484e2 100644
--- a/resources/src/mediawiki/mediawiki.searchSuggest.js
+++ b/resources/src/mediawiki/mediawiki.searchSuggest.js
@@ -2,8 +2,22 @@
* Add search suggestions to the search form.
*/
( function ( mw, $ ) {
+ mw.searchSuggest = {
+ request: function ( api, query, response, maxRows ) {
+ return api.get( {
+ action: 'opensearch',
+ search: query,
+ namespace: 0,
+ limit: maxRows,
+ suggest: ''
+ } ).done( function ( data ) {
+ response( data[ 1 ] );
+ } );
+ }
+ };
+
$( function () {
- var api, map, resultRenderCache, searchboxesSelectors,
+ var api, map, 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.
@@ -12,19 +26,20 @@
// element (not the search form, as that would leave the buttons
// vertically between the input and the suggestions).
$searchRegion = $( '#simpleSearch, #searchInput' ).first(),
- $searchInput = $( '#searchInput' );
+ $searchInput = $( '#searchInput' ),
+ previousSearchText = $searchInput.val();
// Compatibility map
map = {
// SimpleSearch is broken in Opera < 9.6
- opera: [['>=', 9.6]],
+ opera: [ [ '>=', 9.6 ] ],
// Older Konquerors are unable to position the suggestions correctly (bug 50805)
- konqueror: [['>=', '4.11']],
+ 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]]
+ ipod: [ [ '>=', 6 ] ],
+ iphone: [ [ '>=', 6 ] ]
};
if ( !$.client.test( map ) ) {
@@ -32,52 +47,101 @@
}
// Compute form data for search suggestions functionality.
- function computeResultRenderCache( context ) {
+ function getFormData( context ) {
var $form, baseHref, linkParams;
- // Compute common parameters for links' hrefs
- $form = context.config.$region.closest( 'form' );
+ if ( !context.formData ) {
+ // Compute common parameters for links' hrefs
+ $form = context.config.$region.closest( 'form' );
+
+ baseHref = $form.attr( 'action' );
+ baseHref += baseHref.indexOf( '?' ) > -1 ? '&' : '?';
+
+ linkParams = $form.serializeObject();
+
+ context.formData = {
+ textParam: context.data.$textbox.attr( 'name' ),
+ linkParams: linkParams,
+ baseHref: baseHref
+ };
+ }
+
+ return context.formData;
+ }
- baseHref = $form.attr( 'action' );
- baseHref += baseHref.indexOf( '?' ) > -1 ? '&' : '?';
+ /**
+ * Callback that's run when the user changes the search input text
+ * 'this' is the search input box (jQuery object)
+ *
+ * @ignore
+ */
+ function onBeforeUpdate() {
+ var searchText = this.val();
+
+ if ( searchText && searchText !== previousSearchText ) {
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'session-start'
+ } );
+ }
+ previousSearchText = searchText;
+ }
- linkParams = $form.serializeObject();
+ /**
+ * Callback that's run when suggestions have been updated either from the cache or the API
+ * 'this' is the search input box (jQuery object)
+ *
+ * @ignore
+ */
+ function onAfterUpdate() {
+ var context = this.data( 'suggestionsContext' );
- return {
- textParam: context.data.$textbox.attr( 'name' ),
- linkParams: linkParams,
- baseHref: baseHref
- };
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'impression-results',
+ numberOfResults: context.config.suggestions.length,
+ // FIXME: when other types of search become available change this value accordingly
+ // See the API call below (opensearch = prefix)
+ resultSetType: 'prefix'
+ } );
}
// The function used to render the suggestions.
function renderFunction( text, context ) {
- if ( !resultRenderCache ) {
- resultRenderCache = computeResultRenderCache( context );
- }
+ var formData = getFormData( context );
// linkParams object is modified and reused
- resultRenderCache.linkParams[ resultRenderCache.textParam ] = text;
+ formData.linkParams[ formData.textParam ] = text;
// this is the container <div>, jQueryfied
this.text( text )
.wrap(
$( '<a>' )
- .attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) )
+ .attr( 'href', formData.baseHref + $.param( formData.linkParams ) )
.attr( 'title', text )
.addClass( 'mw-searchSuggest-link' )
);
}
- function specialRenderFunction( query, context ) {
- var $el = this;
+ // The function used when the user makes a selection
+ function selectFunction( $input ) {
+ var context = $input.data( 'suggestionsContext' ),
+ text = $input.val();
- if ( !resultRenderCache ) {
- resultRenderCache = computeResultRenderCache( context );
- }
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'click-result',
+ numberOfResults: context.config.suggestions.length,
+ clickIndex: context.config.suggestions.indexOf( text ) + 1
+ } );
+
+ // allow the form to be submitted
+ return true;
+ }
+
+ function specialRenderFunction( query, context ) {
+ var $el = this,
+ formData = getFormData( context );
// linkParams object is modified and reused
- resultRenderCache.linkParams[ resultRenderCache.textParam ] = query;
+ formData.linkParams[ formData.textParam ] = query;
if ( $el.children().length === 0 ) {
$el
@@ -96,11 +160,11 @@
}
if ( $el.parent().hasClass( 'mw-searchSuggest-link' ) ) {
- $el.parent().attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) + '&fulltext=1' );
+ $el.parent().attr( 'href', formData.baseHref + $.param( formData.linkParams ) + '&fulltext=1' );
} else {
$el.wrap(
$( '<a>' )
- .attr( 'href', resultRenderCache.baseHref + $.param( resultRenderCache.linkParams ) + '&fulltext=1' )
+ .attr( 'href', formData.baseHref + $.param( formData.linkParams ) + '&fulltext=1' )
.addClass( 'mw-searchSuggest-link' )
);
}
@@ -120,22 +184,14 @@
$( searchboxesSelectors.join( ', ' ) )
.suggestions( {
fetch: function ( query, response, maxRows ) {
- var node = this[0];
+ var node = this[ 0 ];
api = api || new mw.Api();
- $.data( node, 'request', api.get( {
- action: 'opensearch',
- search: query,
- namespace: 0,
- limit: maxRows,
- suggest: ''
- } ).done( function ( data ) {
- response( data[ 1 ] );
- } ) );
+ $.data( node, 'request', mw.searchSuggest.request( api, query, response, maxRows ) );
},
cancel: function () {
- var node = this[0],
+ var node = this[ 0 ],
request = $.data( node, 'request' );
if ( request ) {
@@ -177,8 +233,16 @@
return;
}
- // Special suggestions functionality for skin-provided search box
+ // Special suggestions functionality and tracking for skin-provided search box
$searchInput.suggestions( {
+ update: {
+ before: onBeforeUpdate,
+ after: onAfterUpdate
+ },
+ result: {
+ render: renderFunction,
+ select: selectFunction
+ },
special: {
render: specialRenderFunction,
select: function ( $input ) {
@@ -190,8 +254,17 @@
$region: $searchRegion
} );
- // If the form includes any fallback fulltext search buttons, remove them
- $searchInput.closest( 'form' ).find( '.mw-fallbackSearchButton' ).remove();
+ $searchInput.closest( 'form' )
+ // track the form submit event
+ .on( 'submit', function () {
+ var context = $searchInput.data( 'suggestionsContext' );
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'submit-form',
+ numberOfResults: context.config.suggestions.length
+ } );
+ } )
+ // If the form includes any fallback fulltext search buttons, remove them
+ .find( '.mw-fallbackSearchButton' ).remove();
} );
}( mediaWiki, jQuery ) );