* @param {Function} options.result.select Called in context of the suggestions-result-current element.
* @param {jQuery} options.result.select.$textbox
*
+ * @param {Object} [options.update] Set of callbacks for listening to a change in the text input.
+ *
+ * @param {Function} options.update.before Called right after the user changes the textbox text.
+ * @param {Function} options.update.after Called after results are updated either from the cache or
+ * the API as a result of the user input.
+ *
* @param {jQuery} [options.$region=this] The element to place the suggestions below and match width of.
*
* @param {string[]} [options.suggestions] Array of suggestions to display.
* @param {boolean} [options.positionFromLeft] Sets `expandFrom=left`, for backwards
* compatibility.
*
- * @param {boolean} [options.highlightInput=false] Whether to hightlight matched portions of the
+ * @param {boolean} [options.highlightInput=false] Whether to highlight matched portions of the
* input or not.
*/
( function ( $ ) {
cache = context.data.cache,
cacheHit;
+ if ( typeof context.config.update.before === 'function' ) {
+ context.config.update.before.call( context.data.$textbox );
+ }
+
// Only fetch if the value in the textbox changed and is not empty, or if the results were hidden
// if the textbox is empty then clear the result div, but leave other settings intouched
if ( val.length === 0 ) {
if ( context.config.cache && hasOwn.call( cache, val ) ) {
if ( +new Date() - cache[ val ].timestamp < context.config.cacheMaxAge ) {
context.data.$textbox.suggestions( 'suggestions', cache[ val ].suggestions );
+ if ( typeof context.config.update.after === 'function' ) {
+ context.config.update.after.call( context.data.$textbox );
+ }
cacheHit = true;
} else {
// Cache expired
function ( suggestions ) {
suggestions = suggestions.slice( 0, context.config.maxRows );
context.data.$textbox.suggestions( 'suggestions', suggestions );
+ if ( typeof context.config.update.after === 'function' ) {
+ context.config.update.after.call( context.data.$textbox );
+ }
if ( context.config.cache ) {
cache[ val ] = {
suggestions: suggestions,
case 'cancel':
case 'special':
case 'result':
+ case 'update':
case '$region':
case 'expandFrom':
context.config[property] = value;
cancel: function () {},
special: {},
result: {},
+ update: {},
$region: $( this ),
suggestions: [],
maxRows: 10,
// 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 = {
};
}
+ /**
+ * 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;
+ }
+
+ /**
+ * 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' );
+
+ 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 ) {
);
}
+ // The function used when the user makes a selection
+ function selectFunction( $input ) {
+ var context = $input.data( 'suggestionsContext' ),
+ text = $input.val();
+
+ 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;
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 ) {