+ /**
+ * Update filter view model state based on a parameter object
+ *
+ * @param {Object} params Parameters object
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.updateStateFromParams = function ( params ) {
+ // For arbitrary numeric single_option values make sure the values
+ // are normalized to fit within the limits
+ $.each( this.getFilterGroups(), function ( groupName, groupModel ) {
+ params[ groupName ] = groupModel.normalizeArbitraryValue( params[ groupName ] );
+ } );
+
+ // Update filter states
+ this.toggleFiltersSelected(
+ this.getFiltersFromParameters(
+ params
+ )
+ );
+
+ // Update highlight state
+ this.getItemsSupportingHighlights().forEach( function ( filterItem ) {
+ var color = params[ filterItem.getName() + '_color' ];
+ if ( color ) {
+ filterItem.setHighlightColor( color );
+ } else {
+ filterItem.clearHighlightColor();
+ }
+ } );
+ this.toggleHighlight( !!Number( params.highlight ) );
+
+ // Check all filter interactions
+ this.reassessFilterInteractions();
+ };
+
+ /**
+ * Get a representation of an empty (falsey) parameter state
+ *
+ * @return {Object} Empty parameter state
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getEmptyParameterState = function () {
+ if ( !this.emptyParameterState ) {
+ this.emptyParameterState = $.extend(
+ true,
+ {},
+ this.getParametersFromFilters( {} ),
+ this.getEmptyHighlightParameters(),
+ { highlight: '0' }
+ );
+ }
+ return this.emptyParameterState;
+ };
+
+ /**
+ * Get a representation of only the non-falsey parameters
+ *
+ * @param {Object} [parameters] A given parameter state to minimize. If not given the current
+ * state of the system will be used.
+ * @return {Object} Empty parameter state
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getMinimizedParamRepresentation = function ( parameters ) {
+ var result = {};
+
+ parameters = parameters ? $.extend( true, {}, parameters ) : this.getCurrentParameterState();
+
+ // Params
+ $.each( this.getEmptyParameterState(), function ( param, value ) {
+ if ( parameters[ param ] !== undefined && parameters[ param ] !== value ) {
+ result[ param ] = parameters[ param ];
+ }
+ } );
+
+ // Highlights
+ Object.keys( this.getEmptyHighlightParameters() ).forEach( function ( param ) {
+ if ( param !== 'highlight' && parameters[ param ] ) {
+ // If a highlight parameter is not undefined and not null
+ // add it to the result
+ // Ignore "highlight" parameter because that, we checked already with
+ // the empty parameter state (and this soon changes to an implicit value)
+ result[ param ] = parameters[ param ];
+ }
+ } );
+
+ return result;
+ };
+
+ /**
+ * Get a representation of the full parameter list, including all base values
+ *
+ * @param {Object} [parameters] A given parameter state to minimize. If not given the current
+ * state of the system will be used.
+ * @param {boolean} [removeExcluded] Remove excluded and sticky parameters
+ * @return {Object} Full parameter representation
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getExpandedParamRepresentation = function ( parameters, removeExcluded ) {
+ var result = {};
+
+ parameters = parameters ? $.extend( true, {}, parameters ) : this.getCurrentParameterState();
+
+ result = $.extend(
+ true,
+ {},
+ this.getEmptyParameterState(),
+ parameters
+ );
+
+ if ( removeExcluded ) {
+ result = this.removeExcludedParams( result );
+ }
+
+ return result;
+ };
+
+ /**
+ * Get a parameter representation of the current state of the model
+ *
+ * @param {boolean} [removeExcludedParams] Remove excluded filters from final result
+ * @return {Object} Parameter representation of the current state of the model
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getCurrentParameterState = function ( removeExcludedParams ) {
+ var excludedParams,
+ state = this.getMinimizedParamRepresentation( $.extend(
+ true,
+ {},
+ this.getParametersFromFilters( this.getSelectedState() ),
+ this.getHighlightParameters(),
+ {
+ // HACK: Add highlight. This is only needed while it's
+ // stored as an outside state
+ highlight: String( Number( this.isHighlightEnabled() ) )
+ }
+ ) );
+
+ if ( removeExcludedParams ) {
+ excludedParams = this.getExcludedParams();
+ // Delete all excluded filters
+ $.each( state, function ( param ) {
+ if ( excludedParams.indexOf( param ) > -1 ) {
+ delete state[ param ];
+ }
+ } );
+ }
+
+ return state;
+ };
+
+ /**
+ * Delete excluded and sticky filters from given object. If object isn't given, output
+ * the current filter state without the excluded values
+ *
+ * @param {Object} [filterState] Filter state
+ * @return {Object} Filter state without excluded filters
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.removeExcludedFilters = function ( filterState ) {
+ filterState = filterState !== undefined ?
+ $.extend( true, {}, filterState ) :
+ this.getFiltersFromParameters();
+
+ // Remove excluded filters
+ Object.keys( this.getExcludedFiltersState() ).forEach( function ( filterName ) {
+ delete filterState[ filterName ];
+ } );
+
+ // Remove sticky filters
+ Object.keys( this.getStickyFiltersState() ).forEach( function ( filterName ) {
+ delete filterState[ filterName ];
+ } );
+
+ return filterState;
+ };
+ /**
+ * Delete excluded and sticky parameters from given object. If object isn't given, output
+ * the current param state without the excluded values
+ *
+ * @param {Object} [paramState] Parameter state
+ * @return {Object} Parameter state without excluded filters
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.removeExcludedParams = function ( paramState ) {
+ paramState = paramState !== undefined ?
+ $.extend( true, {}, paramState ) :
+ this.getCurrentParameterState();
+
+ // Remove excluded filters
+ this.getExcludedParams().forEach( function ( paramName ) {
+ delete paramState[ paramName ];
+ } );
+
+ // Remove sticky filters
+ this.getStickyParams().forEach( function ( paramName ) {
+ delete paramState[ paramName ];
+ } );
+
+ return paramState;
+ };
+