-( function () {
- var SavedQueryItemModel = require( './SavedQueryItemModel.js' ),
- SavedQueriesModel;
-
- /**
- * View model for saved queries
- *
- * @class mw.rcfilters.dm.SavedQueriesModel
- * @mixins OO.EventEmitter
- * @mixins OO.EmitterList
- *
- * @constructor
- * @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Filters model
- * @param {Object} [config] Configuration options
- * @cfg {string} [default] Default query ID
- */
- SavedQueriesModel = function MwRcfiltersDmSavedQueriesModel( filtersModel, config ) {
- config = config || {};
-
- // Mixin constructor
- OO.EventEmitter.call( this );
- OO.EmitterList.call( this );
-
- this.default = config.default;
- this.filtersModel = filtersModel;
- this.converted = false;
-
- // Events
- this.aggregate( { update: 'itemUpdate' } );
- };
-
- /* Initialization */
-
- OO.initClass( SavedQueriesModel );
- OO.mixinClass( SavedQueriesModel, OO.EventEmitter );
- OO.mixinClass( SavedQueriesModel, OO.EmitterList );
-
- /* Events */
-
- /**
- * @event initialize
- *
- * Model is initialized
- */
-
- /**
- * @event itemUpdate
- * @param {mw.rcfilters.dm.SavedQueryItemModel} Changed item
- *
- * An item has changed
- */
-
- /**
- * @event default
- * @param {string} New default ID
- *
- * The default has changed
- */
-
- /* Methods */
-
- /**
- * Initialize the saved queries model by reading it from the user's settings.
- * The structure of the saved queries is:
- * {
- * version: (string) Version number; if version 2, the query represents
- * parameters. Otherwise, the older version represented filters
- * and needs to be readjusted,
- * default: (string) Query ID
- * queries:{
- * query_id_1: {
- * data:{
- * filters: (Object) Minimal definition of the filters
- * highlights: (Object) Definition of the highlights
- * },
- * label: (optional) Name of this query
- * }
- * }
- * }
- *
- * @param {Object} [savedQueries] An object with the saved queries with
- * the above structure.
- * @fires initialize
- */
- SavedQueriesModel.prototype.initialize = function ( savedQueries ) {
- var model = this;
-
- savedQueries = savedQueries || {};
-
- this.clearItems();
- this.default = null;
- this.converted = false;
-
- if ( savedQueries.version !== '2' ) {
- // Old version dealt with filter names. We need to migrate to the new structure
- // The new structure:
- // {
- // version: (string) '2',
- // default: (string) Query ID,
- // queries: {
- // query_id: {
- // label: (string) Name of the query
- // data: {
- // params: (object) Representing all the parameter states
- // highlights: (object) Representing all the filter highlight states
- // }
- // }
- // }
- // eslint-disable-next-line no-jquery/no-each-util
- $.each( savedQueries.queries || {}, function ( id, obj ) {
- if ( obj.data && obj.data.filters ) {
- obj.data = model.convertToParameters( obj.data );
- }
- } );
-
- this.converted = true;
- savedQueries.version = '2';
- }
-
- // Initialize the query items
+var SavedQueryItemModel = require( './SavedQueryItemModel.js' ),
+ SavedQueriesModel;
+
+/**
+ * View model for saved queries
+ *
+ * @class mw.rcfilters.dm.SavedQueriesModel
+ * @mixins OO.EventEmitter
+ * @mixins OO.EmitterList
+ *
+ * @constructor
+ * @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Filters model
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [default] Default query ID
+ */
+SavedQueriesModel = function MwRcfiltersDmSavedQueriesModel( filtersModel, config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+ OO.EmitterList.call( this );
+
+ this.default = config.default;
+ this.filtersModel = filtersModel;
+ this.converted = false;
+
+ // Events
+ this.aggregate( { update: 'itemUpdate' } );
+};
+
+/* Initialization */
+
+OO.initClass( SavedQueriesModel );
+OO.mixinClass( SavedQueriesModel, OO.EventEmitter );
+OO.mixinClass( SavedQueriesModel, OO.EmitterList );
+
+/* Events */
+
+/**
+ * @event initialize
+ *
+ * Model is initialized
+ */
+
+/**
+ * @event itemUpdate
+ * @param {mw.rcfilters.dm.SavedQueryItemModel} Changed item
+ *
+ * An item has changed
+ */
+
+/**
+ * @event default
+ * @param {string} New default ID
+ *
+ * The default has changed
+ */
+
+/* Methods */
+
+/**
+ * Initialize the saved queries model by reading it from the user's settings.
+ * The structure of the saved queries is:
+ * {
+ * version: (string) Version number; if version 2, the query represents
+ * parameters. Otherwise, the older version represented filters
+ * and needs to be readjusted,
+ * default: (string) Query ID
+ * queries:{
+ * query_id_1: {
+ * data:{
+ * filters: (Object) Minimal definition of the filters
+ * highlights: (Object) Definition of the highlights
+ * },
+ * label: (optional) Name of this query
+ * }
+ * }
+ * }
+ *
+ * @param {Object} [savedQueries] An object with the saved queries with
+ * the above structure.
+ * @fires initialize
+ */
+SavedQueriesModel.prototype.initialize = function ( savedQueries ) {
+ var model = this;
+
+ savedQueries = savedQueries || {};
+
+ this.clearItems();
+ this.default = null;
+ this.converted = false;
+
+ if ( savedQueries.version !== '2' ) {
+ // Old version dealt with filter names. We need to migrate to the new structure
+ // The new structure:
+ // {
+ // version: (string) '2',
+ // default: (string) Query ID,
+ // queries: {
+ // query_id: {
+ // label: (string) Name of the query
+ // data: {
+ // params: (object) Representing all the parameter states
+ // highlights: (object) Representing all the filter highlight states
+ // }
+ // }
+ // }
// eslint-disable-next-line no-jquery/no-each-util
$.each( savedQueries.queries || {}, function ( id, obj ) {
- var normalizedData = obj.data,
- isDefault = String( savedQueries.default ) === String( id );
-
- if ( normalizedData && normalizedData.params ) {
- // Backwards-compat fix: Remove sticky parameters from
- // the given data, if they exist
- normalizedData.params = model.filtersModel.removeStickyParams( normalizedData.params );
-
- // Correct the invert state for effective selection
- if ( normalizedData.params.invert && !normalizedData.params.namespace ) {
- delete normalizedData.params.invert;
- }
-
- model.cleanupHighlights( normalizedData );
-
- id = String( id );
-
- // Skip the addNewQuery method because we don't want to unnecessarily manipulate
- // the given saved queries unless we literally intend to (like in backwards compat fixes)
- // And the addNewQuery method also uses a minimization routine that checks for the
- // validity of items and minimizes the query. This isn't necessary for queries loaded
- // from the backend, and has the risk of removing values if they're temporarily
- // invalid (example: if we temporarily removed a cssClass from a filter in the backend)
- model.addItems( [
- new SavedQueryItemModel(
- id,
- obj.label,
- normalizedData,
- { default: isDefault }
- )
- ] );
-
- if ( isDefault ) {
- model.default = id;
- }
+ if ( obj.data && obj.data.filters ) {
+ obj.data = model.convertToParameters( obj.data );
}
} );
- this.emit( 'initialize' );
- };
-
- /**
- * Clean up highlight parameters.
- * 'highlight' used to be stored, it's not inferred based on the presence of absence of
- * filter colors.
- *
- * @param {Object} data Saved query data
- */
- SavedQueriesModel.prototype.cleanupHighlights = function ( data ) {
- if (
- data.params.highlight === '0' &&
- data.highlights && Object.keys( data.highlights ).length
- ) {
- data.highlights = {};
- }
- delete data.params.highlight;
- };
-
- /**
- * Convert from representation of filters to representation of parameters
- *
- * @param {Object} data Query data
- * @return {Object} New converted query data
- */
- SavedQueriesModel.prototype.convertToParameters = function ( data ) {
- var newData = {},
- defaultFilters = this.filtersModel.getFiltersFromParameters( this.filtersModel.getDefaultParams() ),
- fullFilterRepresentation = $.extend( true, {}, defaultFilters, data.filters ),
- highlightEnabled = data.highlights.highlight;
-
- delete data.highlights.highlight;
-
- // Filters
- newData.params = this.filtersModel.getMinimizedParamRepresentation(
- this.filtersModel.getParametersFromFilters( fullFilterRepresentation )
- );
+ this.converted = true;
+ savedQueries.version = '2';
+ }
- // Highlights: appending _color to keys
- newData.highlights = {};
- // eslint-disable-next-line no-jquery/no-each-util
- $.each( data.highlights, function ( highlightedFilterName, value ) {
- if ( value ) {
- newData.highlights[ highlightedFilterName + '_color' ] = data.highlights[ highlightedFilterName ];
- }
- } );
+ // Initialize the query items
+ // eslint-disable-next-line no-jquery/no-each-util
+ $.each( savedQueries.queries || {}, function ( id, obj ) {
+ var normalizedData = obj.data,
+ isDefault = String( savedQueries.default ) === String( id );
- // Add highlight
- newData.params.highlight = String( Number( highlightEnabled || 0 ) );
-
- return newData;
- };
-
- /**
- * Add a query item
- *
- * @param {string} label Label for the new query
- * @param {Object} fulldata Full data representation for the new query, combining highlights and filters
- * @param {boolean} isDefault Item is default
- * @param {string} [id] Query ID, if exists. If this isn't given, a random
- * new ID will be created.
- * @return {string} ID of the newly added query
- */
- SavedQueriesModel.prototype.addNewQuery = function ( label, fulldata, isDefault, id ) {
- var normalizedData = { params: {}, highlights: {} },
- highlightParamNames = Object.keys( this.filtersModel.getEmptyHighlightParameters() ),
- randomID = String( id || ( new Date() ).getTime() ),
- data = this.filtersModel.getMinimizedParamRepresentation( fulldata );
-
- // Split highlight/params
- // eslint-disable-next-line no-jquery/no-each-util
- $.each( data, function ( param, value ) {
- if ( param !== 'highlight' && highlightParamNames.indexOf( param ) > -1 ) {
- normalizedData.highlights[ param ] = value;
- } else {
- normalizedData.params[ param ] = value;
+ if ( normalizedData && normalizedData.params ) {
+ // Backwards-compat fix: Remove sticky parameters from
+ // the given data, if they exist
+ normalizedData.params = model.filtersModel.removeStickyParams( normalizedData.params );
+
+ // Correct the invert state for effective selection
+ if ( normalizedData.params.invert && !normalizedData.params.namespace ) {
+ delete normalizedData.params.invert;
}
- } );
- // Correct the invert state for effective selection
- if ( normalizedData.params.invert && !this.filtersModel.areNamespacesEffectivelyInverted() ) {
- delete normalizedData.params.invert;
+ model.cleanupHighlights( normalizedData );
+
+ id = String( id );
+
+ // Skip the addNewQuery method because we don't want to unnecessarily manipulate
+ // the given saved queries unless we literally intend to (like in backwards compat fixes)
+ // And the addNewQuery method also uses a minimization routine that checks for the
+ // validity of items and minimizes the query. This isn't necessary for queries loaded
+ // from the backend, and has the risk of removing values if they're temporarily
+ // invalid (example: if we temporarily removed a cssClass from a filter in the backend)
+ model.addItems( [
+ new SavedQueryItemModel(
+ id,
+ obj.label,
+ normalizedData,
+ { default: isDefault }
+ )
+ ] );
+
+ if ( isDefault ) {
+ model.default = id;
+ }
}
-
- // Add item
- this.addItems( [
- new SavedQueryItemModel(
- randomID,
- label,
- normalizedData,
- { default: isDefault }
- )
- ] );
-
- if ( isDefault ) {
- this.setDefault( randomID );
+ } );
+
+ this.emit( 'initialize' );
+};
+
+/**
+ * Clean up highlight parameters.
+ * 'highlight' used to be stored, it's not inferred based on the presence of absence of
+ * filter colors.
+ *
+ * @param {Object} data Saved query data
+ */
+SavedQueriesModel.prototype.cleanupHighlights = function ( data ) {
+ if (
+ data.params.highlight === '0' &&
+ data.highlights && Object.keys( data.highlights ).length
+ ) {
+ data.highlights = {};
+ }
+ delete data.params.highlight;
+};
+
+/**
+ * Convert from representation of filters to representation of parameters
+ *
+ * @param {Object} data Query data
+ * @return {Object} New converted query data
+ */
+SavedQueriesModel.prototype.convertToParameters = function ( data ) {
+ var newData = {},
+ defaultFilters = this.filtersModel.getFiltersFromParameters( this.filtersModel.getDefaultParams() ),
+ fullFilterRepresentation = $.extend( true, {}, defaultFilters, data.filters ),
+ highlightEnabled = data.highlights.highlight;
+
+ delete data.highlights.highlight;
+
+ // Filters
+ newData.params = this.filtersModel.getMinimizedParamRepresentation(
+ this.filtersModel.getParametersFromFilters( fullFilterRepresentation )
+ );
+
+ // Highlights: appending _color to keys
+ newData.highlights = {};
+ // eslint-disable-next-line no-jquery/no-each-util
+ $.each( data.highlights, function ( highlightedFilterName, value ) {
+ if ( value ) {
+ newData.highlights[ highlightedFilterName + '_color' ] = data.highlights[ highlightedFilterName ];
}
-
- return randomID;
- };
-
- /**
- * Remove query from model
- *
- * @param {string} queryID Query ID
- */
- SavedQueriesModel.prototype.removeQuery = function ( queryID ) {
- var query = this.getItemByID( queryID );
-
- if ( query ) {
- // Check if this item was the default
- if ( String( this.getDefault() ) === String( queryID ) ) {
- // Nulify the default
- this.setDefault( null );
- }
-
- this.removeItems( [ query ] );
+ } );
+
+ // Add highlight
+ newData.params.highlight = String( Number( highlightEnabled || 0 ) );
+
+ return newData;
+};
+
+/**
+ * Add a query item
+ *
+ * @param {string} label Label for the new query
+ * @param {Object} fulldata Full data representation for the new query, combining highlights and filters
+ * @param {boolean} isDefault Item is default
+ * @param {string} [id] Query ID, if exists. If this isn't given, a random
+ * new ID will be created.
+ * @return {string} ID of the newly added query
+ */
+SavedQueriesModel.prototype.addNewQuery = function ( label, fulldata, isDefault, id ) {
+ var normalizedData = { params: {}, highlights: {} },
+ highlightParamNames = Object.keys( this.filtersModel.getEmptyHighlightParameters() ),
+ randomID = String( id || ( new Date() ).getTime() ),
+ data = this.filtersModel.getMinimizedParamRepresentation( fulldata );
+
+ // Split highlight/params
+ // eslint-disable-next-line no-jquery/no-each-util
+ $.each( data, function ( param, value ) {
+ if ( param !== 'highlight' && highlightParamNames.indexOf( param ) > -1 ) {
+ normalizedData.highlights[ param ] = value;
+ } else {
+ normalizedData.params[ param ] = value;
}
- };
-
- /**
- * Get an item that matches the requested query
- *
- * @param {Object} fullQueryComparison Object representing all filters and highlights to compare
- * @return {mw.rcfilters.dm.SavedQueryItemModel} Matching item model
- */
- SavedQueriesModel.prototype.findMatchingQuery = function ( fullQueryComparison ) {
- // Minimize before comparison
- fullQueryComparison = this.filtersModel.getMinimizedParamRepresentation( fullQueryComparison );
-
- // Correct the invert state for effective selection
- if ( fullQueryComparison.invert && !this.filtersModel.areNamespacesEffectivelyInverted() ) {
- delete fullQueryComparison.invert;
+ } );
+
+ // Correct the invert state for effective selection
+ if ( normalizedData.params.invert && !this.filtersModel.areNamespacesEffectivelyInverted() ) {
+ delete normalizedData.params.invert;
+ }
+
+ // Add item
+ this.addItems( [
+ new SavedQueryItemModel(
+ randomID,
+ label,
+ normalizedData,
+ { default: isDefault }
+ )
+ ] );
+
+ if ( isDefault ) {
+ this.setDefault( randomID );
+ }
+
+ return randomID;
+};
+
+/**
+ * Remove query from model
+ *
+ * @param {string} queryID Query ID
+ */
+SavedQueriesModel.prototype.removeQuery = function ( queryID ) {
+ var query = this.getItemByID( queryID );
+
+ if ( query ) {
+ // Check if this item was the default
+ if ( String( this.getDefault() ) === String( queryID ) ) {
+ // Nulify the default
+ this.setDefault( null );
}
- return this.getItems().filter( function ( item ) {
- return OO.compare(
- item.getCombinedData(),
- fullQueryComparison
- );
- } )[ 0 ];
- };
-
- /**
- * Get query by its identifier
- *
- * @param {string} queryID Query identifier
- * @return {mw.rcfilters.dm.SavedQueryItemModel|undefined} Item matching
- * the search. Undefined if not found.
- */
- SavedQueriesModel.prototype.getItemByID = function ( queryID ) {
- return this.getItems().filter( function ( item ) {
- return item.getID() === queryID;
- } )[ 0 ];
- };
-
- /**
- * Get the full data representation of the default query, if it exists
- *
- * @return {Object|null} Representation of the default params if exists.
- * Null if default doesn't exist or if the user is not logged in.
- */
- SavedQueriesModel.prototype.getDefaultParams = function () {
- return ( !mw.user.isAnon() && this.getItemParams( this.getDefault() ) ) || {};
- };
-
- /**
- * Get a full parameter representation of an item data
- *
- * @param {Object} queryID Query ID
- * @return {Object} Parameter representation
- */
- SavedQueriesModel.prototype.getItemParams = function ( queryID ) {
- var item = this.getItemByID( queryID ),
- data = item ? item.getData() : {};
-
- return !$.isEmptyObject( data ) ? this.buildParamsFromData( data ) : {};
- };
-
- /**
- * Build a full parameter representation given item data and model sticky values state
- *
- * @param {Object} data Item data
- * @return {Object} Full param representation
- */
- SavedQueriesModel.prototype.buildParamsFromData = function ( data ) {
- data = data || {};
- // Return parameter representation
- return this.filtersModel.getMinimizedParamRepresentation( $.extend( true, {},
- data.params,
- data.highlights
- ) );
- };
-
- /**
- * Get the object representing the state of the entire model and items
- *
- * @return {Object} Object representing the state of the model and items
- */
- SavedQueriesModel.prototype.getState = function () {
- var obj = { queries: {}, version: '2' };
-
- // Translate the items to the saved object
+ this.removeItems( [ query ] );
+ }
+};
+
+/**
+ * Get an item that matches the requested query
+ *
+ * @param {Object} fullQueryComparison Object representing all filters and highlights to compare
+ * @return {mw.rcfilters.dm.SavedQueryItemModel} Matching item model
+ */
+SavedQueriesModel.prototype.findMatchingQuery = function ( fullQueryComparison ) {
+ // Minimize before comparison
+ fullQueryComparison = this.filtersModel.getMinimizedParamRepresentation( fullQueryComparison );
+
+ // Correct the invert state for effective selection
+ if ( fullQueryComparison.invert && !this.filtersModel.areNamespacesEffectivelyInverted() ) {
+ delete fullQueryComparison.invert;
+ }
+
+ return this.getItems().filter( function ( item ) {
+ return OO.compare(
+ item.getCombinedData(),
+ fullQueryComparison
+ );
+ } )[ 0 ];
+};
+
+/**
+ * Get query by its identifier
+ *
+ * @param {string} queryID Query identifier
+ * @return {mw.rcfilters.dm.SavedQueryItemModel|undefined} Item matching
+ * the search. Undefined if not found.
+ */
+SavedQueriesModel.prototype.getItemByID = function ( queryID ) {
+ return this.getItems().filter( function ( item ) {
+ return item.getID() === queryID;
+ } )[ 0 ];
+};
+
+/**
+ * Get the full data representation of the default query, if it exists
+ *
+ * @return {Object|null} Representation of the default params if exists.
+ * Null if default doesn't exist or if the user is not logged in.
+ */
+SavedQueriesModel.prototype.getDefaultParams = function () {
+ return ( !mw.user.isAnon() && this.getItemParams( this.getDefault() ) ) || {};
+};
+
+/**
+ * Get a full parameter representation of an item data
+ *
+ * @param {Object} queryID Query ID
+ * @return {Object} Parameter representation
+ */
+SavedQueriesModel.prototype.getItemParams = function ( queryID ) {
+ var item = this.getItemByID( queryID ),
+ data = item ? item.getData() : {};
+
+ return !$.isEmptyObject( data ) ? this.buildParamsFromData( data ) : {};
+};
+
+/**
+ * Build a full parameter representation given item data and model sticky values state
+ *
+ * @param {Object} data Item data
+ * @return {Object} Full param representation
+ */
+SavedQueriesModel.prototype.buildParamsFromData = function ( data ) {
+ data = data || {};
+ // Return parameter representation
+ return this.filtersModel.getMinimizedParamRepresentation( $.extend( true, {},
+ data.params,
+ data.highlights
+ ) );
+};
+
+/**
+ * Get the object representing the state of the entire model and items
+ *
+ * @return {Object} Object representing the state of the model and items
+ */
+SavedQueriesModel.prototype.getState = function () {
+ var obj = { queries: {}, version: '2' };
+
+ // Translate the items to the saved object
+ this.getItems().forEach( function ( item ) {
+ obj.queries[ item.getID() ] = item.getState();
+ } );
+
+ if ( this.getDefault() ) {
+ obj.default = this.getDefault();
+ }
+
+ return obj;
+};
+
+/**
+ * Set a default query. Null to unset default.
+ *
+ * @param {string} itemID Query identifier
+ * @fires default
+ */
+SavedQueriesModel.prototype.setDefault = function ( itemID ) {
+ if ( this.default !== itemID ) {
+ this.default = itemID;
+
+ // Set for individual itens
this.getItems().forEach( function ( item ) {
- obj.queries[ item.getID() ] = item.getState();
+ item.toggleDefault( item.getID() === itemID );
} );
- if ( this.getDefault() ) {
- obj.default = this.getDefault();
- }
-
- return obj;
- };
-
- /**
- * Set a default query. Null to unset default.
- *
- * @param {string} itemID Query identifier
- * @fires default
- */
- SavedQueriesModel.prototype.setDefault = function ( itemID ) {
- if ( this.default !== itemID ) {
- this.default = itemID;
-
- // Set for individual itens
- this.getItems().forEach( function ( item ) {
- item.toggleDefault( item.getID() === itemID );
- } );
-
- this.emit( 'default', itemID );
- }
- };
-
- /**
- * Get the default query ID
- *
- * @return {string} Default query identifier
- */
- SavedQueriesModel.prototype.getDefault = function () {
- return this.default;
- };
-
- /**
- * Check if the saved queries were converted
- *
- * @return {boolean} Saved queries were converted from the previous
- * version to the new version
- */
- SavedQueriesModel.prototype.isConverted = function () {
- return this.converted;
- };
-
- module.exports = SavedQueriesModel;
-}() );
+ this.emit( 'default', itemID );
+ }
+};
+
+/**
+ * Get the default query ID
+ *
+ * @return {string} Default query identifier
+ */
+SavedQueriesModel.prototype.getDefault = function () {
+ return this.default;
+};
+
+/**
+ * Check if the saved queries were converted
+ *
+ * @return {boolean} Saved queries were converted from the previous
+ * version to the new version
+ */
+SavedQueriesModel.prototype.isConverted = function () {
+ return this.converted;
+};
+
+module.exports = SavedQueriesModel;