2b17897b04c9b1118c4a62dd72c708f097cf8816
3 * View model for saved queries
6 * @mixins OO.EventEmitter
7 * @mixins OO.EmitterList
10 * @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Filters model
11 * @param {Object} [config] Configuration options
12 * @cfg {string} [default] Default query ID
14 mw
.rcfilters
.dm
.SavedQueriesModel
= function MwRcfiltersDmSavedQueriesModel( filtersModel
, config
) {
15 config
= config
|| {};
18 OO
.EventEmitter
.call( this );
19 OO
.EmitterList
.call( this );
21 this.default = config
.default;
22 this.filtersModel
= filtersModel
;
23 this.converted
= false;
26 this.aggregate( { update
: 'itemUpdate' } );
31 OO
.initClass( mw
.rcfilters
.dm
.SavedQueriesModel
);
32 OO
.mixinClass( mw
.rcfilters
.dm
.SavedQueriesModel
, OO
.EventEmitter
);
33 OO
.mixinClass( mw
.rcfilters
.dm
.SavedQueriesModel
, OO
.EmitterList
);
40 * Model is initialized
45 * @param {mw.rcfilters.dm.SavedQueryItemModel} Changed item
52 * @param {string} New default ID
54 * The default has changed
60 * Initialize the saved queries model by reading it from the user's settings.
61 * The structure of the saved queries is:
63 * version: (string) Version number; if version 2, the query represents
64 * parameters. Otherwise, the older version represented filters
65 * and needs to be readjusted,
66 * default: (string) Query ID
70 * filters: (Object) Minimal definition of the filters
71 * highlights: (Object) Definition of the highlights
73 * label: (optional) Name of this query
78 * @param {Object} [savedQueries] An object with the saved queries with
79 * the above structure.
82 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.initialize = function ( savedQueries
) {
84 excludedParams
= this.filtersModel
.getExcludedParams();
86 savedQueries
= savedQueries
|| {};
90 this.converted
= false;
92 if ( savedQueries
.version
!== '2' ) {
93 // Old version dealt with filter names. We need to migrate to the new structure
96 // version: (string) '2',
97 // default: (string) Query ID,
100 // label: (string) Name of the query
102 // params: (object) Representing all the parameter states
103 // highlights: (object) Representing all the filter highlight states
107 $.each( savedQueries
.queries
|| {}, function ( id
, obj
) {
108 if ( obj
.data
&& obj
.data
.filters
) {
109 obj
.data
= model
.convertToParameters( obj
.data
);
113 this.converted
= true;
114 savedQueries
.version
= '2';
117 // Initialize the query items
118 $.each( savedQueries
.queries
|| {}, function ( id
, obj
) {
119 var normalizedData
= obj
.data
,
120 isDefault
= String( savedQueries
.default ) === String( id
);
122 if ( normalizedData
&& normalizedData
.params
) {
123 // Backwards-compat fix: Remove excluded parameters from
124 // the given data, if they exist
125 excludedParams
.forEach( function ( name
) {
126 delete normalizedData
.params
[ name
];
130 model
.addNewQuery( obj
.label
, normalizedData
, isDefault
, id
);
138 this.emit( 'initialize' );
142 * Convert from representation of filters to representation of parameters
144 * @param {Object} data Query data
145 * @return {Object} New converted query data
147 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.convertToParameters = function ( data
) {
149 defaultFilters
= this.filtersModel
.getFiltersFromParameters( this.filtersModel
.getDefaultParams() ),
150 fullFilterRepresentation
= $.extend( true, {}, defaultFilters
, data
.filters
),
151 highlightEnabled
= data
.highlights
.highlight
;
153 delete data
.highlights
.highlight
;
156 newData
.params
= this.filtersModel
.getParametersFromFilters( fullFilterRepresentation
);
158 // Highlights (taking out 'highlight' itself, appending _color to keys)
159 newData
.highlights
= {};
160 Object
.keys( data
.highlights
).forEach( function ( highlightedFilterName
) {
161 newData
.highlights
[ highlightedFilterName
+ '_color' ] = data
.highlights
[ highlightedFilterName
];
164 // Add highlight and invert toggles to params
165 newData
.params
.highlight
= String( Number( highlightEnabled
|| 0 ) );
166 newData
.params
.invert
= String( Number( data
.invert
|| 0 ) );
172 * Get an object representing the base state of parameters
175 * This is meant to make sure that the saved queries that are
176 * in memory are always the same structure as what we would get
177 * by calling the current model's "getSelectedState" and by checking
180 * In cases where a user saved a query when the system had a certain
181 * set of params, and then a filter was added to the system, we want
182 * to make sure that the stored queries can still be comparable to
183 * the current state, which means that we need the base state for
186 * - Saved queries are stored in "minimal" view (only changed params
187 * are stored); When we initialize the system, we merge each minimal
188 * query with the base state (using 'getMinimalParamList') so all
189 * saved queries have the exact same structure as what we would get
190 * by checking the getSelectedState of the filter.
191 * - When we save the queries, we minimize the object to only represent
192 * whatever has actually changed, rather than store the entire
193 * object. To check what actually is different so we can store it,
194 * we need to obtain a base state to compare against, this is
195 * what #getMinimalParamList does
197 * @return {Object} Base parameter state
199 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.getBaseParamState = function () {
201 highlightedItems
= {};
203 if ( !this.baseParamState
) {
204 allParams
= this.filtersModel
.getParametersFromFilters( {} );
206 // Prepare highlights
207 this.filtersModel
.getItemsSupportingHighlights().forEach( function ( item
) {
208 highlightedItems
[ item
.getName() + '_color' ] = null;
211 this.baseParamState
= {
212 params
: $.extend( true, { invert
: '0', highlight
: '0' }, allParams
),
213 highlights
: highlightedItems
217 return this.baseParamState
;
221 * Get an object that holds only the parameters and highlights that have
222 * values different than the base value.
224 * This is the reverse of the normalization we do initially on loading and
225 * initializing the saved queries model.
227 * @param {Object} valuesObject Object representing the state of both
228 * filters and highlights in its normalized version, to be minimized.
229 * @return {Object} Minimal filters and highlights list
231 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.getMinimalParamList = function ( valuesObject
) {
232 var result
= { params
: {}, highlights
: {} },
233 baseState
= this.getBaseParamState();
236 $.each( valuesObject
.params
, function ( name
, value
) {
237 if ( baseState
.params
!== undefined && baseState
.params
[ name
] !== value
) {
238 result
.params
[ name
] = value
;
242 $.each( valuesObject
.highlights
, function ( name
, value
) {
243 if ( baseState
.highlights
!== undefined && baseState
.highlights
[ name
] !== value
) {
244 result
.highlights
[ name
] = value
;
254 * @param {string} label Label for the new query
255 * @param {Object} data Data for the new query
256 * @param {boolean} isDefault Item is default
257 * @param {string} [id] Query ID, if exists. If this isn't given, a random
258 * new ID will be created.
259 * @return {string} ID of the newly added query
261 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.addNewQuery = function ( label
, data
, isDefault
, id
) {
262 var randomID
= String( id
|| ( new Date() ).getTime() ),
263 normalizedData
= this.getMinimalParamList( data
);
267 new mw
.rcfilters
.dm
.SavedQueryItemModel(
271 { 'default': isDefault
}
276 this.setDefault( randomID
);
283 * Remove query from model
285 * @param {string} queryID Query ID
287 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.removeQuery = function ( queryID
) {
288 var query
= this.getItemByID( queryID
);
291 // Check if this item was the default
292 if ( String( this.getDefault() ) === String( queryID
) ) {
293 // Nulify the default
294 this.setDefault( null );
297 this.removeItems( [ query
] );
302 * Get an item that matches the requested query
304 * @param {Object} fullQueryComparison Object representing all filters and highlights to compare
305 * @return {mw.rcfilters.dm.SavedQueryItemModel} Matching item model
307 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.findMatchingQuery = function ( fullQueryComparison
) {
308 // Minimize before comparison
309 fullQueryComparison
= this.getMinimalParamList( fullQueryComparison
);
311 return this.getItems().filter( function ( item
) {
320 * Get query by its identifier
322 * @param {string} queryID Query identifier
323 * @return {mw.rcfilters.dm.SavedQueryItemModel|undefined} Item matching
324 * the search. Undefined if not found.
326 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.getItemByID = function ( queryID
) {
327 return this.getItems().filter( function ( item
) {
328 return item
.getID() === queryID
;
333 * Get an item's full data
335 * @param {string} queryID Query identifier
336 * @return {Object} Item's full data
338 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.getItemFullData = function ( queryID
) {
339 var item
= this.getItemByID( queryID
);
341 // Fill in the base params
342 return item
? $.extend( true, {}, this.getBaseParamState(), item
.getData() ) : {};
346 * Get the object representing the state of the entire model and items
348 * @return {Object} Object representing the state of the model and items
350 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.getState = function () {
352 obj
= { queries
: {}, version
: '2' };
354 // Translate the items to the saved object
355 this.getItems().forEach( function ( item
) {
356 var itemState
= item
.getState();
358 itemState
.data
= model
.getMinimalParamList( itemState
.data
);
360 obj
.queries
[ item
.getID() ] = itemState
;
363 if ( this.getDefault() ) {
364 obj
.default = this.getDefault();
371 * Set a default query. Null to unset default.
373 * @param {string} itemID Query identifier
376 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.setDefault = function ( itemID
) {
377 if ( this.default !== itemID
) {
378 this.default = itemID
;
380 // Set for individual itens
381 this.getItems().forEach( function ( item
) {
382 item
.toggleDefault( item
.getID() === itemID
);
385 this.emit( 'default', itemID
);
390 * Get the default query ID
392 * @return {string} Default query identifier
394 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.getDefault = function () {
399 * Check if the saved queries were converted
401 * @return {boolean} Saved queries were converted from the previous
402 * version to the new version
404 mw
.rcfilters
.dm
.SavedQueriesModel
.prototype.isConverted = function () {
405 return this.converted
;
407 }( mediaWiki
, jQuery
) );