Localisation updates from https://translatewiki.net.
[mediawiki.git] / resources / src / mediawiki.widgets / MediaSearch / mw.widgets.APIResultsQueue.js
blob5dddd0af3f0efb656c39703fe19065d1024465d1
1 /*!
2  * MediaWiki Widgets - APIResultsQueue class.
3  *
4  * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org
5  */
6 ( function () {
8         /**
9          * @classdesc API results queue.
10          *
11          * @class
12          * @mixes OO.EventEmitter
13          *
14          * @constructor
15          * @param {Object} [config] Configuration options
16          * @param {number} config.limit The default number of results to fetch
17          * @param {number} config.threshold The default number of extra results
18          *  that the queue should always strive to have on top of the
19          *  individual requests for items.
20          */
21         mw.widgets.APIResultsQueue = function MwWidgetsAPIResultsQueue( config ) {
22                 config = config || {};
24                 this.fileRepoPromise = null;
25                 this.providers = [];
26                 this.providerPromises = [];
27                 this.queue = [];
29                 this.params = {};
31                 this.limit = config.limit || 20;
32                 this.setThreshold( config.threshold || 10 );
34                 // Mixin constructors
35                 OO.EventEmitter.call( this );
36         };
38         /* Setup */
39         OO.mixinClass( mw.widgets.APIResultsQueue, OO.EventEmitter );
41         /* Methods */
43         /**
44          * Set up the queue and its resources.
45          * This should be overridden if there are any setup steps to perform.
46          *
47          * @return {jQuery.Promise} Promise that resolves when the resources
48          *  are set up. Note: The promise must have an .abort() functionality.
49          */
50         mw.widgets.APIResultsQueue.prototype.setup = function () {
51                 return $.Deferred().resolve().promise( { abort: function () {} } );
52         };
54         /**
55          * Get items from the queue.
56          *
57          * @param {number} [howMany] How many items to retrieve. Defaults to the
58          *  default limit supplied on initialization.
59          * @return {jQuery.Promise} Promise that resolves into an array of items.
60          */
61         mw.widgets.APIResultsQueue.prototype.get = function ( howMany ) {
62                 let fetchingPromise = null;
64                 howMany = howMany || this.limit;
66                 // Check if the queue has enough items
67                 if ( this.queue.length < howMany + this.threshold ) {
68                         // Call for more results
69                         fetchingPromise = this.queryProviders( howMany + this.threshold )
70                                 .then( ( items ) => {
71                                         // Add to the queue
72                                         this.queue = this.queue.concat.apply( this.queue, items );
73                                 } );
74                 }
76                 return $.when( fetchingPromise )
77                         .then( () => this.queue.splice( 0, howMany ) );
79         };
81         /**
82          * Get results from all providers.
83          *
84          * @param {number} [howMany] How many items to retrieve. Defaults to the
85          *  default limit supplied on initialization.
86          * @return {jQuery.Promise} Promise that is resolved into an array
87          *  of fetched items. Note: The promise must have an .abort() functionality.
88          */
89         mw.widgets.APIResultsQueue.prototype.queryProviders = function ( howMany ) {
90                 // Make sure there are resources set up
91                 return this.setup()
92                         .then( () => {
93                                 // Abort previous requests
94                                 for ( let i = 0, iLen = this.providerPromises.length; i < iLen; i++ ) {
95                                         this.providerPromises[ i ].abort();
96                                 }
97                                 this.providerPromises = [];
98                                 // Set up the query to all providers
99                                 for ( let j = 0, jLen = this.providers.length; j < jLen; j++ ) {
100                                         if ( !this.providers[ j ].isDepleted() ) {
101                                                 this.providerPromises.push(
102                                                         this.providers[ j ].getResults( howMany )
103                                                 );
104                                         }
105                                 }
107                                 return $.when( ...this.providerPromises )
108                                         .then( Array.prototype.concat.bind( [] ) );
109                         } );
110         };
112         /**
113          * Set the search query for all the providers.
114          *
115          * This also makes sure to abort any previous promises.
116          *
117          * @param {Object} params API search parameters
118          */
119         mw.widgets.APIResultsQueue.prototype.setParams = function ( params ) {
120                 if ( !OO.compare( params, this.params, true ) ) {
121                         this.reset();
122                         this.params = Object.assign( this.params, params );
123                         // Reset queue
124                         this.queue = [];
125                         // Reset promises
126                         for ( let i = 0, iLen = this.providerPromises.length; i < iLen; i++ ) {
127                                 this.providerPromises[ i ].abort();
128                         }
129                         // Change queries
130                         for ( let j = 0, jLen = this.providers.length; j < jLen; j++ ) {
131                                 this.providers[ j ].setUserParams( this.params );
132                         }
133                 }
134         };
136         /**
137          * Reset the queue and all its providers.
138          */
139         mw.widgets.APIResultsQueue.prototype.reset = function () {
140                 // Reset queue
141                 this.queue = [];
142                 // Reset promises
143                 for ( let i = 0, iLen = this.providerPromises.length; i < iLen; i++ ) {
144                         this.providerPromises[ i ].abort();
145                 }
146                 // Reset options
147                 for ( let j = 0, jLen = this.providers.length; j < jLen; j++ ) {
148                         this.providers[ j ].reset();
149                 }
150         };
152         /**
153          * Get the data parameters sent to the API.
154          *
155          * @return {Object} params API search parameters
156          */
157         mw.widgets.APIResultsQueue.prototype.getParams = function () {
158                 return this.params;
159         };
161         /**
162          * Set the providers.
163          *
164          * @param {mw.widgets.APIResultsProvider[]} providers An array of providers
165          */
166         mw.widgets.APIResultsQueue.prototype.setProviders = function ( providers ) {
167                 this.providers = providers;
168                 for ( let i = 0, len = this.providers.length; i < len; i++ ) {
169                         this.providers[ i ].setUserParams( this.params );
170                         this.providers[ i ].setLang( this.lang );
171                 }
172         };
174         /**
175          * Add a provider to the group.
176          *
177          * @param {mw.widgets.APIResultsProvider} provider A provider object
178          */
179         mw.widgets.APIResultsQueue.prototype.addProvider = function ( provider ) {
180                 this.providers.push( provider );
181                 provider.setUserParams( this.params );
182                 provider.setLang( this.lang );
183         };
185         /**
186          * Set the providers.
187          *
188          * @return {mw.widgets.APIResultsProvider[]} providers An array of providers
189          */
190         mw.widgets.APIResultsQueue.prototype.getProviders = function () {
191                 return this.providers;
192         };
194         /**
195          * Get the queue size.
196          *
197          * @return {number} Queue size
198          */
199         mw.widgets.APIResultsQueue.prototype.getQueueSize = function () {
200                 return this.queue.length;
201         };
203         /**
204          * Set queue threshold.
205          *
206          * @param {number} threshold Queue threshold, below which we will
207          *  request more items
208          */
209         mw.widgets.APIResultsQueue.prototype.setThreshold = function ( threshold ) {
210                 this.threshold = threshold;
211         };
213         /**
214          * Get queue threshold.
215          *
216          * @return {number} threshold Queue threshold, below which we will
217          *  request more items
218          */
219         mw.widgets.APIResultsQueue.prototype.getThreshold = function () {
220                 return this.threshold;
221         };
223         /**
224          * Set language for the query results.
225          *
226          * @param {string|undefined} lang Language
227          */
228         mw.widgets.APIResultsQueue.prototype.setLang = function ( lang ) {
229                 this.lang = lang;
230                 for ( let i = 0, len = this.providers.length; i < len; i++ ) {
231                         this.providers[ i ].setLang( this.lang );
232                 }
233         };
235         /**
236          * Get language for the query results.
237          *
238          * @return {string|undefined} lang Language
239          */
240         mw.widgets.APIResultsQueue.prototype.getLang = function () {
241                 return this.lang;
242         };
243 }() );