Merge "OutputPage: Use PageViewLanguage instead of PageLanguage for mw.config"
[lhc/web/wiklou.git] / resources / src / mediawiki.widgets / mw.widgets.SearchInputWidget.js
1 /*!
2 * MediaWiki Widgets - SearchInputWidget class.
3 *
4 * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
5 * @license The MIT License (MIT); see LICENSE.txt
6 */
7 ( function ( $, mw ) {
8
9 /**
10 * Creates a mw.widgets.SearchInputWidget object.
11 *
12 * @class
13 * @extends mw.widgets.TitleInputWidget
14 *
15 * @constructor
16 * @cfg {boolean} [pushPending=true] Visually mark the input field as "pending", while
17 * requesting suggestions.
18 * @cfg {boolean} [performSearchOnClick=true] If true, the script will start a search when-
19 * ever a user hits a suggestion. If false, the text of the suggestion is inserted into the
20 * text field only.
21 */
22 mw.widgets.SearchInputWidget = function MwWidgetsSearchInputWidget( config ) {
23 config = $.extend( {
24 type: 'search',
25 icon: 'search',
26 maxLength: undefined,
27 performSearchOnClick: true
28 }, config );
29
30 // Parent constructor
31 mw.widgets.SearchInputWidget.parent.call( this, config );
32
33 // Initialization
34 this.$element.addClass( 'mw-widget-searchInputWidget' );
35 this.lookupMenu.$element.addClass( 'mw-widget-searchWidget-menu' );
36 if ( !config.pushPending ) {
37 this.pushPending = false;
38 }
39 if ( config.dataLocation ) {
40 this.dataLocation = config.dataLocation;
41 }
42 if ( config.performSearchOnClick ) {
43 this.performSearchOnClick = config.performSearchOnClick;
44 }
45 this.setLookupsDisabled( !this.suggestions );
46 };
47
48 /* Setup */
49
50 OO.inheritClass( mw.widgets.SearchInputWidget, mw.widgets.TitleInputWidget );
51
52 /* Methods */
53
54 /**
55 * @inheritdoc mw.widgets.TitleWidget
56 */
57 mw.widgets.SearchInputWidget.prototype.getSuggestionsPromise = function () {
58 var api = new mw.Api(),
59 promise,
60 self = this;
61
62 // reuse the searchSuggest function from mw.searchSuggest
63 promise = mw.searchSuggest.request( api, this.getQueryValue(), $.noop, this.limit );
64
65 // tracking purposes
66 promise.done( function ( data, jqXHR ) {
67 self.requestType = jqXHR.getResponseHeader( 'X-OpenSearch-Type' );
68 } );
69
70 return promise;
71 };
72
73 /**
74 * @inheritdoc mw.widgets.TitleInputWidget
75 */
76 mw.widgets.SearchInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
77 var resp;
78
79 // mw.widgets.TitleInputWidget uses response.query, which doesn't exist for opensearch,
80 // so return the whole response (titles only, and links)
81 resp = {
82 data: response || {},
83 metadata: {
84 type: this.requestType || 'unknown',
85 query: this.getQueryValue()
86 }
87 };
88 this.requestType = undefined;
89
90 return resp;
91 };
92
93 /**
94 * @inheritdoc mw.widgets.TitleWidget
95 */
96 mw.widgets.SearchInputWidget.prototype.getOptionsFromData = function ( data ) {
97 var items = [],
98 self = this;
99
100 // mw.widgets.TitleWidget does a lot more work here, because the TitleOptionWidgets can
101 // differ a lot, depending on the returned data from the request. With the request used here
102 // we get only the search results.
103 $.each( data.data[ 1 ], function ( i, result ) {
104 items.push( new mw.widgets.TitleOptionWidget(
105 // data[ 3 ][ i ] is the link for this result
106 self.getOptionWidgetData( result, null, data.data[ 3 ][ i ] )
107 ) );
108 } );
109
110 mw.track( 'mw.widgets.SearchInputWidget', {
111 action: 'impression-results',
112 numberOfResults: items.length,
113 resultSetType: data.metadata.type,
114 query: data.metadata.query,
115 inputLocation: this.dataLocation || 'header'
116 } );
117
118 return items;
119 };
120
121 /**
122 * @inheritdoc mw.widgets.TitleWidget
123 *
124 * @param {string} title
125 * @param {Object} data
126 * @param {string} url The Url to the result
127 */
128 mw.widgets.SearchInputWidget.prototype.getOptionWidgetData = function ( title, data, url ) {
129 // the values used in mw.widgets-TitleWidget doesn't exist here, that's why
130 // the values are hard-coded here
131 return {
132 data: title,
133 url: url,
134 imageUrl: null,
135 description: null,
136 missing: false,
137 redirect: false,
138 disambiguation: false,
139 query: this.getQueryValue()
140 };
141 };
142
143 /**
144 * @inheritdoc
145 */
146 mw.widgets.SearchInputWidget.prototype.onLookupMenuItemChoose = function ( item ) {
147 var items;
148
149 // get items which was suggested before the input changes
150 items = this.lookupMenu.items;
151
152 mw.widgets.SearchInputWidget.parent.prototype.onLookupMenuItemChoose.apply( this, arguments );
153
154 mw.track( 'mw.widgets.SearchInputWidget', {
155 action: 'click-result',
156 numberOfResults: items.length,
157 clickIndex: items.indexOf( item ) + 1
158 } );
159
160 if ( this.performSearchOnClick ) {
161 this.$element.closest( 'form' ).submit();
162 }
163 };
164
165 }( jQuery, mediaWiki ) );