Merge "Add Czech aliases to most special pages"
[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 * @cfg {string} [dataLocation='header'] Where the search input field will be
22 * used (header or content).
23 */
24 mw.widgets.SearchInputWidget = function MwWidgetsSearchInputWidget( config ) {
25 config = $.extend( {
26 type: 'search',
27 icon: 'search',
28 maxLength: undefined,
29 performSearchOnClick: true,
30 dataLocation: 'header'
31 }, config );
32
33 // Parent constructor
34 mw.widgets.SearchInputWidget.parent.call( this, config );
35
36 // Initialization
37 this.$element.addClass( 'mw-widget-searchInputWidget' );
38 this.lookupMenu.$element.addClass( 'mw-widget-searchWidget-menu' );
39 if ( !config.pushPending ) {
40 this.pushPending = false;
41 }
42 if ( config.dataLocation ) {
43 this.dataLocation = config.dataLocation;
44 }
45 if ( config.performSearchOnClick ) {
46 this.performSearchOnClick = config.performSearchOnClick;
47 }
48 this.setLookupsDisabled( !this.suggestions );
49 };
50
51 /* Setup */
52
53 OO.inheritClass( mw.widgets.SearchInputWidget, mw.widgets.TitleInputWidget );
54
55 /* Methods */
56
57 /**
58 * @inheritdoc mw.widgets.TitleWidget
59 */
60 mw.widgets.SearchInputWidget.prototype.getSuggestionsPromise = function () {
61 var api = new mw.Api(),
62 promise,
63 self = this;
64
65 // reuse the searchSuggest function from mw.searchSuggest
66 promise = mw.searchSuggest.request( api, this.getQueryValue(), $.noop, this.limit );
67
68 // tracking purposes
69 promise.done( function ( data, jqXHR ) {
70 self.requestType = jqXHR.getResponseHeader( 'X-OpenSearch-Type' );
71 } );
72
73 return promise;
74 };
75
76 /**
77 * @inheritdoc mw.widgets.TitleInputWidget
78 */
79 mw.widgets.SearchInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
80 var resp;
81
82 // mw.widgets.TitleInputWidget uses response.query, which doesn't exist for opensearch,
83 // so return the whole response (titles only, and links)
84 resp = {
85 data: response || {},
86 metadata: {
87 type: this.requestType || 'unknown',
88 query: this.getQueryValue()
89 }
90 };
91 this.requestType = undefined;
92
93 return resp;
94 };
95
96 /**
97 * @inheritdoc mw.widgets.TitleWidget
98 */
99 mw.widgets.SearchInputWidget.prototype.getOptionsFromData = function ( data ) {
100 var items = [],
101 self = this;
102
103 // mw.widgets.TitleWidget does a lot more work here, because the TitleOptionWidgets can
104 // differ a lot, depending on the returned data from the request. With the request used here
105 // we get only the search results.
106 $.each( data.data[ 1 ], function ( i, result ) {
107 items.push( new mw.widgets.TitleOptionWidget(
108 // data[ 3 ][ i ] is the link for this result
109 self.getOptionWidgetData( result, null, data.data[ 3 ][ i ] )
110 ) );
111 } );
112
113 mw.track( 'mw.widgets.SearchInputWidget', {
114 action: 'impression-results',
115 numberOfResults: items.length,
116 resultSetType: data.metadata.type,
117 query: data.metadata.query,
118 inputLocation: this.dataLocation || 'header'
119 } );
120
121 return items;
122 };
123
124 /**
125 * @inheritdoc mw.widgets.TitleWidget
126 *
127 * @param {string} title
128 * @param {Object} data
129 * @param {string} url The Url to the result
130 */
131 mw.widgets.SearchInputWidget.prototype.getOptionWidgetData = function ( title, data, url ) {
132 // the values used in mw.widgets-TitleWidget doesn't exist here, that's why
133 // the values are hard-coded here
134 return {
135 data: title,
136 url: url,
137 imageUrl: null,
138 description: null,
139 missing: false,
140 redirect: false,
141 disambiguation: false,
142 query: this.getQueryValue()
143 };
144 };
145
146 /**
147 * @inheritdoc
148 */
149 mw.widgets.SearchInputWidget.prototype.onLookupMenuItemChoose = function ( item ) {
150 var items;
151
152 // get items which was suggested before the input changes
153 items = this.lookupMenu.items;
154
155 mw.widgets.SearchInputWidget.parent.prototype.onLookupMenuItemChoose.apply( this, arguments );
156
157 mw.track( 'mw.widgets.SearchInputWidget', {
158 action: 'click-result',
159 numberOfResults: items.length,
160 clickIndex: items.indexOf( item ) + 1
161 } );
162
163 if ( this.performSearchOnClick ) {
164 this.$element.closest( 'form' ).submit();
165 }
166 };
167
168 }( jQuery, mediaWiki ) );