* @param {mw.rcfilters.dm.SavedQueriesModel} savedQueriesModel Saved queries model
* @param {Object} config Additional configuration
* @cfg {string} savedQueriesPreferenceName Where to save the saved queries
+ * @cfg {string} daysPreferenceName Preference name for the days filter
+ * @cfg {string} limitPreferenceName Preference name for the limit filter
+ * @cfg {boolean} [normalizeTarget] Dictates whether or not to go through the
+ * title normalization to separate title subpage/parts into the target= url
+ * parameter
*/
mw.rcfilters.Controller = function MwRcfiltersController( filtersModel, changesListModel, savedQueriesModel, config ) {
this.filtersModel = filtersModel;
this.changesListModel = changesListModel;
this.savedQueriesModel = savedQueriesModel;
this.savedQueriesPreferenceName = config.savedQueriesPreferenceName;
+ this.daysPreferenceName = config.daysPreferenceName;
+ this.limitPreferenceName = config.limitPreferenceName;
+ this.normalizeTarget = !!config.normalizeTarget;
this.requestCounter = {};
this.baseFilterState = {};
* @param {Array} filterStructure Filter definition and structure for the model
* @param {Object} [namespaceStructure] Namespace definition
* @param {Object} [tagList] Tag definition
+ * @param {Object} [conditionalViews] Conditional view definition
*/
- mw.rcfilters.Controller.prototype.initialize = function ( filterStructure, namespaceStructure, tagList ) {
- var parsedSavedQueries,
+ mw.rcfilters.Controller.prototype.initialize = function ( filterStructure, namespaceStructure, tagList, conditionalViews ) {
+ var parsedSavedQueries, pieces,
displayConfig = mw.config.get( 'StructuredChangeFiltersDisplayConfig' ),
defaultSavedQueryExists = mw.config.get( 'wgStructuredChangeFiltersDefaultSavedQueryExists' ),
controller = this,
- views = {},
+ views = $.extend( true, {}, conditionalViews ),
items = [],
- uri = new mw.Uri(),
- $changesList = $( '.mw-changeslist' ).first().contents();
+ uri = new mw.Uri();
// Prepare views
if ( namespaceStructure ) {
separator: ';',
fullCoverage: true,
filters: items
- },
- {
- name: 'invertGroup',
- type: 'boolean',
- hidden: true,
- filters: [ {
- name: 'invert',
- 'default': '0'
- } ]
} ]
};
+ views.invert = {
+ groups: [
+ {
+ name: 'invertGroup',
+ type: 'boolean',
+ hidden: true,
+ filters: [ {
+ name: 'invert',
+ 'default': '0'
+ } ]
+ } ]
+ };
}
if ( tagList ) {
views.tags = {
max: 1000
},
sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); },
- 'default': displayConfig.limitDefault,
- // Temporarily making this not sticky until we resolve the problem
- // with the misleading preference. Note that if this is to be permanent
- // we should remove all sticky behavior methods completely
- // See T172156
- // isSticky: true,
- excludedFromSavedQueries: true,
+ 'default': mw.user.options.get( this.limitPreferenceName, displayConfig.limitDefault ),
+ sticky: true,
filters: displayConfig.limitArray.map( function ( num ) {
return controller._createFilterDataFromNumber( num, num );
} )
( Number( i ) * 24 ).toFixed( 2 ) :
Number( i );
},
- 'default': displayConfig.daysDefault,
- // Temporarily making this not sticky while limit is not sticky, see above
- // isSticky: true,
- excludedFromSavedQueries: true,
+ 'default': mw.user.options.get( this.daysPreferenceName, displayConfig.daysDefault ),
+ sticky: true,
filters: [
// Hours (1, 2, 6, 12)
0.04166, 0.0833, 0.25, 0.5
type: 'boolean',
title: '', // Because it's a hidden group, this title actually appears nowhere
hidden: true,
- isSticky: true,
+ sticky: true,
filters: [
{
name: 'enhanced',
this.filtersModel.initializeFilters( filterStructure, views );
this.uriProcessor = new mw.rcfilters.UriProcessor(
- this.filtersModel
+ this.filtersModel,
+ { normalizeTarget: this.normalizeTarget }
);
if ( !mw.user.isAnon() ) {
// again
this.updateStateFromUrl( false );
+ pieces = this._extractChangesListInfo( $( '#mw-content-text' ) );
+
// Update the changes list with the existing data
// so it gets processed
this.changesListModel.update(
- $changesList.length ? $changesList : 'NO_RESULTS',
- $( 'fieldset.cloptions' ).first(),
+ pieces.changes,
+ pieces.fieldset,
+ pieces.noResultsDetails,
true // We're using existing DOM elements
);
}
}
};
+ /**
+ * Extracts information from the changes list DOM
+ *
+ * @param {jQuery} $root Root DOM to find children from
+ * @param {boolean} [statusCode] Server response status code
+ * @return {Object} Information about changes list
+ * @return {Object|string} return.changes Changes list, or 'NO_RESULTS' if there are no results
+ * (either normally or as an error)
+ * @return {string} [return.noResultsDetails] 'NO_RESULTS_NORMAL' for a normal 0-result set,
+ * 'NO_RESULTS_TIMEOUT' for no results due to a timeout, or omitted for more than 0 results
+ * @return {jQuery} return.fieldset Fieldset
+ */
+ mw.rcfilters.Controller.prototype._extractChangesListInfo = function ( $root, statusCode ) {
+ var info,
+ $changesListContents = $root.find( '.mw-changeslist' ).first().contents(),
+ areResults = !!$changesListContents.length,
+ checkForLogout = !areResults && statusCode === 200;
+
+ // We check if user logged out on different tab/browser or the session has expired.
+ // 205 status code returned from the server, which indicates that we need to reload the page
+ // is not usable on WL page, because we get redirected to login page, which gives 200 OK
+ // status code (if everything else goes well).
+ // Bug: T177717
+ if ( checkForLogout && !!$root.find( '#wpName1' ).length ) {
+ location.reload( false );
+ return;
+ }
+
+ info = {
+ changes: $changesListContents.length ? $changesListContents : 'NO_RESULTS',
+ fieldset: $root.find( 'fieldset.cloptions' ).first()
+ };
+
+ if ( !areResults ) {
+ if ( $root.find( '.mw-changeslist-timeout' ).length ) {
+ info.noResultsDetails = 'NO_RESULTS_TIMEOUT';
+ } else if ( $root.find( '.mw-changeslist-notargetpage' ).length ) {
+ info.noResultsDetails = 'NO_RESULTS_NO_TARGET_PAGE';
+ } else {
+ info.noResultsDetails = 'NO_RESULTS_NORMAL';
+ }
+ }
+
+ return info;
+ };
+
/**
* Create filter data from a number, for the filters that are numerical value
*
} );
};
- /**
- * Switch the view of the filters model
- *
- * @param {string} view Requested view
- */
- mw.rcfilters.Controller.prototype.switchView = function ( view ) {
- this.filtersModel.switchView( view );
- };
-
/**
* Reset to default filters
*/
mw.rcfilters.Controller.prototype.resetToDefaults = function () {
- this.uriProcessor.updateModelBasedOnQuery( this._getDefaultParams() );
-
- this.updateChangesList();
+ var params = this._getDefaultParams();
+ if ( this.applyParamChange( params ) ) {
+ // Only update the changes list if there was a change to actual filters
+ this.updateChangesList();
+ } else {
+ this.uriProcessor.updateURL( params );
+ }
};
/**
* @return {boolean} Defaults are all false
*/
mw.rcfilters.Controller.prototype.areDefaultsEmpty = function () {
- var defaultParams = this._getDefaultParams(),
- defaultFilters = this.filtersModel.getFiltersFromParameters( defaultParams );
-
- this._deleteExcludedValuesFromFilterState( defaultFilters );
-
- if ( Object.keys( defaultParams ).some( function ( paramName ) {
- return paramName.match( /_color$/ ) && defaultParams[ paramName ] !== null;
- } ) ) {
- // There are highlights in the defaults, they're definitely
- // not empty
- return false;
- }
-
- // Defaults can change in a session, so we need to do this every time
- return Object.keys( defaultFilters ).every( function ( filterName ) {
- return !defaultFilters[ filterName ];
- } );
+ return $.isEmptyObject( this._getDefaultParams() );
};
/**
* Empty all selected filters
*/
mw.rcfilters.Controller.prototype.emptyFilters = function () {
- var highlightedFilterNames = this.filtersModel
- .getHighlightedItems()
+ var highlightedFilterNames = this.filtersModel.getHighlightedItems()
.map( function ( filterItem ) { return { name: filterItem.getName() }; } );
- this.filtersModel.emptyAllFilters();
- this.filtersModel.clearAllHighlightColors();
- // Check all filter interactions
- this.filtersModel.reassessFilterInteractions();
-
- this.updateChangesList();
+ if ( this.applyParamChange( {} ) ) {
+ // Only update the changes list if there was a change to actual filters
+ this.updateChangesList();
+ } else {
+ this.uriProcessor.updateURL();
+ }
if ( highlightedFilterNames ) {
this._trackHighlight( 'clearAll', highlightedFilterNames );
*/
mw.rcfilters.Controller.prototype.toggleHighlight = function () {
this.filtersModel.toggleHighlight();
- this._updateURL();
+ this.uriProcessor.updateURL();
if ( this.filtersModel.isHighlightEnabled() ) {
mw.hook( 'RcFilters.highlight.enable' ).fire();
*/
mw.rcfilters.Controller.prototype.toggleInvertedNamespaces = function () {
this.filtersModel.toggleInvertedNamespaces();
-
if (
this.filtersModel.getFiltersByView( 'namespaces' ).filter(
function ( filterItem ) { return filterItem.isSelected(); }
) {
// Only re-fetch results if there are namespace items that are actually selected
this.updateChangesList();
+ } else {
+ this.uriProcessor.updateURL();
}
};
+ /**
+ * Set the value of the 'showlinkedto' parameter
+ * @param {boolean} value
+ */
+ mw.rcfilters.Controller.prototype.setShowLinkedTo = function ( value ) {
+ var targetItem = this.filtersModel.getGroup( 'page' ).getItemByParamName( 'target' ),
+ showLinkedToItem = this.filtersModel.getGroup( 'toOrFrom' ).getItemByParamName( 'showlinkedto' );
+
+ this.filtersModel.toggleFilterSelected( showLinkedToItem.getName(), value );
+ this.uriProcessor.updateURL();
+ // reload the results only when target is set
+ if ( targetItem.getValue() ) {
+ this.updateChangesList();
+ }
+ };
+
+ /**
+ * Set the target page
+ * @param {string} page
+ */
+ mw.rcfilters.Controller.prototype.setTargetPage = function ( page ) {
+ var targetItem = this.filtersModel.getGroup( 'page' ).getItemByParamName( 'target' );
+ targetItem.setValue( page );
+ this.uriProcessor.updateURL();
+ this.updateChangesList();
+ };
+
/**
* Set the highlight color for a filter item
*
*/
mw.rcfilters.Controller.prototype.setHighlightColor = function ( filterName, color ) {
this.filtersModel.setHighlightColor( filterName, color );
- this._updateURL();
+ this.uriProcessor.updateURL();
this._trackHighlight( 'set', { name: filterName, color: color } );
};
*/
mw.rcfilters.Controller.prototype.clearHighlightColor = function ( filterName ) {
this.filtersModel.clearHighlightColor( filterName );
- this._updateURL();
+ this.uriProcessor.updateURL();
this._trackHighlight( 'clear', filterName );
};
}
this._checkForNewChanges()
- .then( function ( newChanges ) {
+ .then( function ( statusCode ) {
+ // no result is 204 with the 'peek' param
+ // logged out is 205
+ var newChanges = statusCode === 200;
+
if ( !this._shouldCheckForNewChanges() ) {
// by the time the response is received,
// it may not be appropriate anymore
return;
}
+ // 205 is the status code returned from server when user's logged in/out
+ // status is not matching while fetching live update changes.
+ // This works only on Recent Changes page. For WL, look _extractChangesListInfo.
+ // Bug: T177717
+ if ( statusCode === 205 ) {
+ location.reload( false );
+ return;
+ }
+
if ( newChanges ) {
if ( this.changesListModel.getLiveUpdate() ) {
return this.updateChangesList( null, this.LIVE_UPDATE );
var params = {
limit: 1,
peek: 1, // bypasses ChangesList specific UI
- from: this.changesListModel.getNextFrom()
+ from: this.changesListModel.getNextFrom(),
+ isAnon: mw.user.isAnon()
};
return this._queryChangesList( 'liveUpdate', params ).then(
function ( data ) {
- // no result is 204 with the 'peek' param
- return data.status === 200;
+ return data.status;
}
);
};
* @param {boolean} [setAsDefault=false] This query should be set as the default
*/
mw.rcfilters.Controller.prototype.saveCurrentQuery = function ( label, setAsDefault ) {
- var highlightedItems = {},
- highlightEnabled = this.filtersModel.isHighlightEnabled(),
- selectedState = this.filtersModel.getSelectedState();
-
- // Prepare highlights
- this.filtersModel.getHighlightedItems().forEach( function ( item ) {
- highlightedItems[ item.getName() + '_color' ] = highlightEnabled ?
- item.getHighlightColor() : null;
- } );
-
- // Delete all excluded filters
- this._deleteExcludedValuesFromFilterState( selectedState );
-
// Add item
this.savedQueriesModel.addNewQuery(
label || mw.msg( 'rcfilters-savedqueries-defaultlabel' ),
- {
- params: $.extend(
- true,
- {
- highlight: String( Number( this.filtersModel.isHighlightEnabled() ) )
- },
- this.filtersModel.getParametersFromFilters( selectedState )
- ),
- highlights: highlightedItems
- },
+ this.filtersModel.getCurrentParameterState( true ),
setAsDefault
);
* @param {string} queryID Query id
*/
mw.rcfilters.Controller.prototype.applySavedQuery = function ( queryID ) {
- var highlights,
- queryItem = this.savedQueriesModel.getItemByID( queryID ),
- data = this.savedQueriesModel.getItemFullData( queryID ),
- currentMatchingQuery = this.findQueryMatchingCurrentState();
+ var currentMatchingQuery,
+ params = this.savedQueriesModel.getItemParams( queryID );
+
+ currentMatchingQuery = this.findQueryMatchingCurrentState();
if (
- queryItem &&
- (
- // If there's already a query, don't reload it
- // if it's the same as the one that already exists
- !currentMatchingQuery ||
- currentMatchingQuery.getID() !== queryItem.getID()
- )
+ currentMatchingQuery &&
+ currentMatchingQuery.getID() === queryID
) {
- highlights = data.highlights;
-
- // Update model state from filters
- this.filtersModel.toggleFiltersSelected(
- // Merge filters with excluded values
- $.extend(
- true,
- {},
- this.filtersModel.getFiltersFromParameters( data.params ),
- this.filtersModel.getExcludedFiltersState()
- )
- );
-
- // Update highlight state
- this.filtersModel.toggleHighlight( !!Number( data.params.highlight ) );
- this.filtersModel.getItems().forEach( function ( filterItem ) {
- var color = highlights[ filterItem.getName() + '_color' ];
- if ( color ) {
- filterItem.setHighlightColor( color );
- } else {
- filterItem.clearHighlightColor();
- }
- } );
-
- // Check all filter interactions
- this.filtersModel.reassessFilterInteractions();
+ // If the query we want to load is the one that is already
+ // loaded, don't reload it
+ return;
+ }
+ if ( this.applyParamChange( params ) ) {
+ // Update changes list only if there was a difference in filter selection
this.updateChangesList();
-
- // Log filter grouping
- this.trackFilterGroupings( 'savedfilters' );
+ } else {
+ this.uriProcessor.updateURL( params );
}
+
+ // Log filter grouping
+ this.trackFilterGroupings( 'savedfilters' );
};
/**
* Check whether the current filter and highlight state exists
* in the saved queries model.
*
- * @return {boolean} Query exists
+ * @return {mw.rcfilters.dm.SavedQueryItemModel} Matching item model
*/
mw.rcfilters.Controller.prototype.findQueryMatchingCurrentState = function () {
- var highlightedItems = {},
- selectedState = this.filtersModel.getSelectedState();
-
- // Prepare highlights of the current query
- this.filtersModel.getItemsSupportingHighlights().forEach( function ( item ) {
- highlightedItems[ item.getName() + '_color' ] = item.getHighlightColor();
- } );
-
- // Remove anything that should be excluded from the saved query
- // this includes sticky filters and filters marked with 'excludedFromSavedQueries'
- this._deleteExcludedValuesFromFilterState( selectedState );
-
return this.savedQueriesModel.findMatchingQuery(
- {
- params: $.extend(
- true,
- {
- highlight: String( Number( this.filtersModel.isHighlightEnabled() ) )
- },
- this.filtersModel.getParametersFromFilters( selectedState )
- ),
- highlights: highlightedItems
- }
+ this.filtersModel.getCurrentParameterState( true )
);
};
- /**
- * Delete sticky filters from given object
- *
- * @param {Object} filterState Filter state
- */
- mw.rcfilters.Controller.prototype._deleteExcludedValuesFromFilterState = function ( filterState ) {
- // Remove excluded filters
- $.each( this.filtersModel.getExcludedFiltersState(), function ( filterName ) {
- delete filterState[ filterName ];
- } );
- };
-
/**
* Save the current state of the saved queries model with all
* query item representation in the user settings.
/**
* Update the limit default value
*
- * param {number} newValue New value
+ * @param {number} newValue New value
*/
- mw.rcfilters.Controller.prototype.updateLimitDefault = function ( /* newValue */ ) {
- // HACK: Temporarily remove this from being sticky
- // See T172156
-
- /*
- if ( !$.isNumeric( newValue ) ) {
- return;
- }
-
- newValue = Number( newValue );
-
- if ( mw.user.options.get( 'rcfilters-rclimit' ) !== newValue ) {
- // Save the preference
- new mw.Api().saveOption( 'rcfilters-rclimit', newValue );
- // Update the preference for this session
- mw.user.options.set( 'rcfilters-rclimit', newValue );
- }
- */
- return;
+ mw.rcfilters.Controller.prototype.updateLimitDefault = function ( newValue ) {
+ this.updateNumericPreference( this.limitPreferenceName, newValue );
};
/**
* Update the days default value
*
- * param {number} newValue New value
+ * @param {number} newValue New value
*/
- mw.rcfilters.Controller.prototype.updateDaysDefault = function ( /* newValue */ ) {
- // HACK: Temporarily remove this from being sticky
- // See T172156
-
- /*
- if ( !$.isNumeric( newValue ) ) {
- return;
- }
-
- newValue = Number( newValue );
-
- if ( mw.user.options.get( 'rcdays' ) !== newValue ) {
- // Save the preference
- new mw.Api().saveOption( 'rcdays', newValue );
- // Update the preference for this session
- mw.user.options.set( 'rcdays', newValue );
- }
- */
- return;
+ mw.rcfilters.Controller.prototype.updateDaysDefault = function ( newValue ) {
+ this.updateNumericPreference( this.daysPreferenceName, newValue );
};
/**
* Update the group by page default value
*
- * @param {number} newValue New value
+ * @param {boolean} newValue New value
*/
mw.rcfilters.Controller.prototype.updateGroupByPageDefault = function ( newValue ) {
+ this.updateNumericPreference( 'usenewrc', Number( newValue ) );
+ };
+
+ /**
+ * Update a numeric preference with a new value
+ *
+ * @param {string} prefName Preference name
+ * @param {number|string} newValue New value
+ */
+ mw.rcfilters.Controller.prototype.updateNumericPreference = function ( prefName, newValue ) {
if ( !$.isNumeric( newValue ) ) {
return;
}
newValue = Number( newValue );
- if ( mw.user.options.get( 'usenewrc' ) !== newValue ) {
+ if ( mw.user.options.get( prefName ) !== newValue ) {
// Save the preference
- new mw.Api().saveOption( 'usenewrc', newValue );
+ new mw.Api().saveOption( prefName, newValue );
// Update the preference for this session
- mw.user.options.set( 'usenewrc', newValue );
+ mw.user.options.set( prefName, newValue );
}
};
* without adding an history entry.
*/
mw.rcfilters.Controller.prototype.replaceUrl = function () {
- mw.rcfilters.UriProcessor.static.replaceState( this._getUpdatedUri() );
+ this.uriProcessor.updateURL();
};
/**
mw.rcfilters.Controller.prototype.updateStateFromUrl = function ( fetchChangesList ) {
fetchChangesList = fetchChangesList === undefined ? true : !!fetchChangesList;
- this.uriProcessor.updateModelBasedOnQuery( new mw.Uri().query );
+ this.uriProcessor.updateModelBasedOnQuery();
// Update the sticky preferences, in case we received a value
// from the URL
updateMode = updateMode === undefined ? this.FILTER_CHANGE : updateMode;
if ( updateMode === this.FILTER_CHANGE ) {
- this._updateURL( params );
+ this.uriProcessor.updateURL( params );
}
if ( updateMode === this.FILTER_CHANGE || updateMode === this.SHOW_NEW_CHANGES ) {
this.changesListModel.invalidate();
this.changesListModel.update(
$changesListContent,
$fieldset,
+ pieces.noResultsDetails,
false,
// separator between old and new changes
updateMode === this.SHOW_NEW_CHANGES || updateMode === this.LIVE_UPDATE
* @return {Object} Default parameters
*/
mw.rcfilters.Controller.prototype._getDefaultParams = function () {
- var savedFilters,
- data = ( !mw.user.isAnon() && this.savedQueriesModel.getItemFullData( this.savedQueriesModel.getDefault() ) ) || {};
-
- if ( !$.isEmptyObject( data ) ) {
- // Merge saved filter state with sticky filter values
- savedFilters = $.extend(
- true, {},
- this.filtersModel.getFiltersFromParameters( data.params ),
- this.filtersModel.getStickyFiltersState()
- );
-
- // Return parameter representation
- return $.extend( true, {},
- this.filtersModel.getParametersFromFilters( savedFilters ),
- data.highlights,
- { highlight: data.params.highlight }
- );
- }
- return this.filtersModel.getDefaultParams();
- };
-
- /**
- * Update the URL of the page to reflect current filters
- *
- * This should not be called directly from outside the controller.
- * If an action requires changing the URL, it should either use the
- * highlighting actions below, or call #updateChangesList which does
- * the uri corrections already.
- *
- * @param {Object} [params] Extra parameters to add to the API call
- */
- mw.rcfilters.Controller.prototype._updateURL = function ( params ) {
- var currentUri = new mw.Uri(),
- updatedUri = this._getUpdatedUri();
-
- updatedUri.extend( params || {} );
-
- if (
- this.uriProcessor.getVersion( currentUri.query ) !== 2 ||
- this.uriProcessor.isNewState( currentUri.query, updatedUri.query )
- ) {
- mw.rcfilters.UriProcessor.static.replaceState( updatedUri );
+ if ( this.savedQueriesModel.getDefault() ) {
+ return this.savedQueriesModel.getDefaultParams();
+ } else {
+ return this.filtersModel.getDefaultParams();
}
};
- /**
- * Get an updated mw.Uri object based on the model state
- *
- * @return {mw.Uri} Updated Uri
- */
- mw.rcfilters.Controller.prototype._getUpdatedUri = function () {
- var uri = new mw.Uri();
-
- // Minimize url
- uri.query = this.uriProcessor.minimizeQuery(
- $.extend(
- true,
- {},
- // We want to retain unrecognized params
- // The uri params from model will override
- // any recognized value in the current uri
- // query, retain unrecognized params, and
- // the result will then be minimized
- uri.query,
- this.uriProcessor.getUriParametersFromModel(),
- { urlversion: '2' }
- )
- );
-
- return uri;
- };
-
/**
* Query the list of changes from the server for the current filters
*
* @return {jQuery.Promise} Promise object resolved with { content, status }
*/
mw.rcfilters.Controller.prototype._queryChangesList = function ( counterId, params ) {
- var uri = this._getUpdatedUri(),
- stickyParams = this.filtersModel.getStickyParams(),
+ var uri = this.uriProcessor.getUpdatedUri(),
+ stickyParams = this.filtersModel.getStickyParamsValues(),
requestId,
latestRequest;
return this._queryChangesList( 'updateChangesList' )
.then(
function ( data ) {
- var $parsed = $( '<div>' ).append( $( $.parseHTML( data.content ) ) ),
- pieces = {
- // Changes list
- changes: $parsed.find( '.mw-changeslist' ).first().contents(),
- // Fieldset
- fieldset: $parsed.find( 'fieldset.cloptions' ).first()
+ var $parsed;
+
+ // Status code 0 is not HTTP status code,
+ // but is valid value of XMLHttpRequest status.
+ // It is used for variety of network errors, for example
+ // when an AJAX call was cancelled before getting the response
+ if ( data && data.status === 0 ) {
+ return {
+ changes: 'NO_RESULTS',
+ // We need empty result set, to avoid exceptions because of undefined value
+ fieldset: $( [] ),
+ noResultsDetails: 'NO_RESULTS_NETWORK_ERROR'
};
-
- if ( pieces.changes.length === 0 ) {
- pieces.changes = 'NO_RESULTS';
}
- return pieces;
- }
+ $parsed = $( '<div>' ).append( $( $.parseHTML(
+ data ? data.content : ''
+ ) ) );
+
+ return this._extractChangesListInfo( $parsed, data.status );
+ }.bind( this )
);
};
}
};
+ /**
+ * Apply a change of parameters to the model state, and check whether
+ * the new state is different than the old state.
+ *
+ * @param {Object} newParamState New parameter state to apply
+ * @return {boolean} New applied model state is different than the previous state
+ */
+ mw.rcfilters.Controller.prototype.applyParamChange = function ( newParamState ) {
+ var after,
+ before = this.filtersModel.getSelectedState();
+
+ this.filtersModel.updateStateFromParams( newParamState );
+
+ after = this.filtersModel.getSelectedState();
+
+ return !OO.compare( before, after );
+ };
+
/**
* Mark all changes as seen on Watchlist
*/
this.updateChangesList( null, 'markSeen' );
}.bind( this ) );
};
+
+ /**
+ * Set the current search for the system.
+ *
+ * @param {string} searchQuery Search query, including triggers
+ */
+ mw.rcfilters.Controller.prototype.setSearch = function ( searchQuery ) {
+ this.filtersModel.setSearch( searchQuery );
+ };
+
+ /**
+ * Switch the view by changing the search query trigger
+ * without changing the search term
+ *
+ * @param {string} view View to change to
+ */
+ mw.rcfilters.Controller.prototype.switchView = function ( view ) {
+ this.setSearch(
+ this.filtersModel.getViewTrigger( view ) +
+ this.filtersModel.removeViewTriggers( this.filtersModel.getSearch() )
+ );
+ };
+
+ /**
+ * Reset the search for a specific view. This means we null the search query
+ * and replace it with the relevant trigger for the requested view
+ *
+ * @param {string} [view='default'] View to change to
+ */
+ mw.rcfilters.Controller.prototype.resetSearchForView = function ( view ) {
+ view = view || 'default';
+
+ this.setSearch(
+ this.filtersModel.getViewTrigger( view )
+ );
+ };
}( mediaWiki, jQuery ) );