Merge "RCFilters: Don't reload the list if the change was highlights-only"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 9 Nov 2017 00:35:01 +0000 (00:35 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 9 Nov 2017 00:35:02 +0000 (00:35 +0000)
1  2 
resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js

         * @param {Object} [tagList] Tag definition
         */
        mw.rcfilters.Controller.prototype.initialize = function ( filterStructure, namespaceStructure, tagList ) {
 -              var parsedSavedQueries,
 +              var parsedSavedQueries, pieces,
                        displayConfig = mw.config.get( 'StructuredChangeFiltersDisplayConfig' ),
                        defaultSavedQueryExists = mw.config.get( 'wgStructuredChangeFiltersDefaultSavedQueryExists' ),
                        controller = this,
                        views = {},
                        items = [],
 -                      uri = new mw.Uri(),
 -                      $changesList = $( '.mw-changeslist' ).first().contents();
 +                      uri = new mw.Uri();
  
                // Prepare views
                if ( namespaceStructure ) {
                        // 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 === 'NO_RESULTS_TIMEOUT',
                                true // We're using existing DOM elements
                        );
                }
                }
        };
  
 +      /**
 +       * Extracts information from the changes list DOM
 +       *
 +       * @param {jQuery} $root Root DOM to find children from
 +       * @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 ) {
 +              var info, isTimeout,
 +                      $changesListContents = $root.find( '.mw-changeslist' ).first().contents(),
 +                      areResults = !!$changesListContents.length;
 +
 +              info = {
 +                      changes: $changesListContents.length ? $changesListContents : 'NO_RESULTS',
 +                      fieldset: $root.find( 'fieldset.cloptions' ).first()
 +              };
 +
 +              if ( !areResults ) {
 +                      isTimeout = !!$root.find( '.mw-changeslist-timeout' ).length;
 +                      info.noResultsDetails = isTimeout ? 'NO_RESULTS_TIMEOUT' : 'NO_RESULTS_NORMAL';
 +              }
 +
 +              return info;
 +      };
 +
        /**
         * Create filter data from a number, for the filters that are numerical value
         *
         * Reset to default filters
         */
        mw.rcfilters.Controller.prototype.resetToDefaults = function () {
-               this.filtersModel.updateStateFromParams( this._getDefaultParams() );
-               this.updateChangesList();
+               if ( this.applyParamChange( this._getDefaultParams() ) ) {
+                       // Only update the changes list if there was a change to actual filters
+                       this.updateChangesList();
+               }
        };
  
        /**
         * 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.updateStateFromParams( {} );
-               this.updateChangesList();
+               if ( this.applyParamChange( {} ) ) {
+                       // Only update the changes list if there was a change to actual filters
+                       this.updateChangesList();
+               }
  
                if ( highlightedFilterNames ) {
                        this._trackHighlight( 'clearAll', highlightedFilterNames );
                        return;
                }
  
-               // Apply parameters to model
-               this.filtersModel.updateStateFromParams( params );
-               this.updateChangesList();
+               if ( this.applyParamChange( params ) ) {
+                       // Update changes list only if there was a difference in filter selection
+                       this.updateChangesList();
+               }
  
                // 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 () {
                return this.savedQueriesModel.findMatchingQuery(
         * without adding an history entry.
         */
        mw.rcfilters.Controller.prototype.replaceUrl = function () {
 -              this.uriProcessor.replaceUpdatedUri();
 +              this.uriProcessor.updateURL();
        };
  
        /**
                                        this.changesListModel.update(
                                                $changesListContent,
                                                $fieldset,
 +                                              pieces.noResultsDetails,
                                                false,
                                                // separator between old and new changes
                                                updateMode === this.SHOW_NEW_CHANGES || updateMode === this.LIVE_UPDATE
                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.content ) ) );
 +
 +                                      return this._extractChangesListInfo( $parsed );
 +
 +                              }.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
         */