Merge "Improve sorting on SpecialWanted*-Pages"
[mediawiki.git] / resources / src / mediawiki.widgets / MediaSearch / mw.widgets.APIResultsQueue.js
blob3bc1d51bac5648516fc74eb9d84d3581058d5a75
1 /*!
2  * MediaWiki Widgets - APIResultsQueue class.
3  *
4  * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org
5  */
6 ( function ( $, mw ) {
8         /**
9          * API Results Queue object.
10          *
11          * @class
12          * @mixins OO.EventEmitter
13          *
14          * @constructor
15          * @param {Object} [config] Configuration options
16          * @cfg {number} limit The default number of results to fetch
17          * @cfg {number} 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: $.noop } );
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                 var fetchingPromise = null,
63                         me = this;
65                 howMany = howMany || this.limit;
67                 // Check if the queue has enough items
68                 if ( this.queue.length < howMany + this.threshold ) {
69                         // Call for more results
70                         fetchingPromise = this.queryProviders( howMany + this.threshold )
71                                 .then( function ( items ) {
72                                         // Add to the queue
73                                         me.queue = me.queue.concat.apply( me.queue, items );
74                                 } );
75                 }
77                 return $.when( fetchingPromise )
78                         .then( function () {
79                                 return me.queue.splice( 0, howMany );
80                         } );
82         };
84         /**
85          * Get results from all providers
86          *
87          * @param {number} [howMany] How many items to retrieve. Defaults to the
88          *  default limit supplied on initialization.
89          * @return {jQuery.Promise} Promise that is resolved into an array
90          *  of fetched items. Note: The promise must have an .abort() functionality.
91          */
92         mw.widgets.APIResultsQueue.prototype.queryProviders = function ( howMany ) {
93                 var i, len,
94                         queue = this;
96                 // Make sure there are resources set up
97                 return this.setup()
98                         .then( function () {
99                                 // Abort previous requests
100                                 for ( i = 0, len = queue.providerPromises.length; i < len; i++ ) {
101                                         queue.providerPromises[ i ].abort();
102                                 }
103                                 queue.providerPromises = [];
104                                 // Set up the query to all providers
105                                 for ( i = 0, len = queue.providers.length; i < len; i++ ) {
106                                         if ( !queue.providers[ i ].isDepleted() ) {
107                                                 queue.providerPromises.push(
108                                                         queue.providers[ i ].getResults( howMany )
109                                                 );
110                                         }
111                                 }
113                                 return $.when.apply( $, queue.providerPromises )
114                                         .then( Array.prototype.concat.bind( [] ) );
115                         } );
116         };
118         /**
119          * Set the search query for all the providers.
120          *
121          * This also makes sure to abort any previous promises.
122          *
123          * @param {Object} params API search parameters
124          */
125         mw.widgets.APIResultsQueue.prototype.setParams = function ( params ) {
126                 var i, len;
127                 if ( !OO.compare( params, this.params, true ) ) {
128                         this.reset();
129                         this.params = $.extend( this.params, params );
130                         // Reset queue
131                         this.queue = [];
132                         // Reset promises
133                         for ( i = 0, len = this.providerPromises.length; i < len; i++ ) {
134                                 this.providerPromises[ i ].abort();
135                         }
136                         // Change queries
137                         for ( i = 0, len = this.providers.length; i < len; i++ ) {
138                                 this.providers[ i ].setUserParams( this.params );
139                         }
140                 }
141         };
143         /**
144          * Reset the queue and all its providers
145          */
146         mw.widgets.APIResultsQueue.prototype.reset = function () {
147                 var i, len;
148                 // Reset queue
149                 this.queue = [];
150                 // Reset promises
151                 for ( i = 0, len = this.providerPromises.length; i < len; i++ ) {
152                         this.providerPromises[ i ].abort();
153                 }
154                 // Change queries
155                 for ( i = 0, len = this.providers.length; i < len; i++ ) {
156                         this.providers[ i ].reset();
157                 }
158         };
160         /**
161          * Get the data parameters sent to the API
162          *
163          * @return {Object} params API search parameters
164          */
165         mw.widgets.APIResultsQueue.prototype.getParams = function () {
166                 return this.params;
167         };
169         /**
170          * Set the providers
171          *
172          * @param {mw.widgets.APIResultsProvider[]} providers An array of providers
173          */
174         mw.widgets.APIResultsQueue.prototype.setProviders = function ( providers ) {
175                 this.providers = providers;
176         };
178         /**
179          * Add a provider to the group
180          *
181          * @param {mw.widgets.APIResultsProvider} provider A provider object
182          */
183         mw.widgets.APIResultsQueue.prototype.addProvider = function ( provider ) {
184                 this.providers.push( provider );
185         };
187         /**
188          * Set the providers
189          *
190          * @return {mw.widgets.APIResultsProvider[]} providers An array of providers
191          */
192         mw.widgets.APIResultsQueue.prototype.getProviders = function () {
193                 return this.providers;
194         };
196         /**
197          * Get the queue size
198          *
199          * @return {number} Queue size
200          */
201         mw.widgets.APIResultsQueue.prototype.getQueueSize = function () {
202                 return this.queue.length;
203         };
205         /**
206          * Set queue threshold
207          *
208          * @param {number} threshold Queue threshold, below which we will
209          *  request more items
210          */
211         mw.widgets.APIResultsQueue.prototype.setThreshold = function ( threshold ) {
212                 this.threshold = threshold;
213         };
215         /**
216          * Get queue threshold
217          *
218          * @return {number} threshold Queue threshold, below which we will
219          *  request more items
220          */
221         mw.widgets.APIResultsQueue.prototype.getThreshold = function () {
222                 return this.threshold;
223         };
224 }( jQuery, mediaWiki ) );