Merge "RC filters: update the state of the app on popstate."
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 8 Mar 2017 01:32:35 +0000 (01:32 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 8 Mar 2017 01:32:35 +0000 (01:32 +0000)
1  2 
resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CapsuleItemWidget.js

         * @param {Object} filterStructure Filter definition and structure for the model
         */
        mw.rcfilters.Controller.prototype.initialize = function ( filterStructure ) {
-               var uri = new mw.Uri();
                // Initialize the model
                this.filtersModel.initializeFilters( filterStructure );
+               this.updateStateBasedOnUrl();
+       };
+       /**
+        * Update filter state (selection and highlighting) based
+        * on current URL and default values.
+        */
+       mw.rcfilters.Controller.prototype.updateStateBasedOnUrl = function () {
+               var uri = new mw.Uri();
  
                // Set filter states based on defaults and URL params
-               this.filtersModel.updateFilters(
+               this.filtersModel.toggleFiltersSelected(
                        this.filtersModel.getFiltersFromParameters(
                                // Merge defaults with URL params for initialization
                                $.extend(
                this.filtersModel.toggleHighlight( !!uri.query.highlight );
                this.filtersModel.getItems().forEach( function ( filterItem ) {
                        var color = uri.query[ filterItem.getName() + '_color' ];
-                       if ( !color ) {
-                               return;
+                       if ( color ) {
+                               filterItem.setHighlightColor( color );
+                       } else {
+                               filterItem.clearHighlightColor();
                        }
-                       filterItem.setHighlightColor( color );
                } );
  
                // Check all filter interactions
@@@ -59,7 -66,6 +66,7 @@@
         */
        mw.rcfilters.Controller.prototype.resetToDefaults = function () {
                this.filtersModel.setFiltersToDefaults();
 +              this.filtersModel.clearAllHighlightColors();
                // Check all filter interactions
                this.filtersModel.reassessFilterInteractions();
  
         * @param {boolean} [isSelected] Filter selected state
         */
        mw.rcfilters.Controller.prototype.toggleFilterSelect = function ( filterName, isSelected ) {
-               var obj = {},
-                       filterItem = this.filtersModel.getItemByName( filterName );
+               var filterItem = this.filtersModel.getItemByName( filterName );
  
                isSelected = isSelected === undefined ? !filterItem.isSelected() : isSelected;
  
                if ( filterItem.isSelected() !== isSelected ) {
-                       obj[ filterName ] = isSelected;
-                       this.filtersModel.updateFilters( obj );
+                       this.filtersModel.toggleFilterSelected( filterName, isSelected );
  
                        this.updateChangesList();
  
                        // Check filter interactions
-                       this.filtersModel.reassessFilterInteractions( this.filtersModel.getItemByName( filterName ) );
+                       this.filtersModel.reassessFilterInteractions( filterItem );
                }
        };
  
         * @param {Object} [params] Extra parameters to add to the API call
         */
        mw.rcfilters.Controller.prototype.updateURL = function ( params ) {
-               var uri;
+               var updatedUri,
+                       notEquivalent = function ( obj1, obj2 ) {
+                               var keys = Object.keys( obj1 ).concat( Object.keys( obj2 ) );
+                               return keys.some( function ( key ) {
+                                       return obj1[ key ] != obj2[ key ]; // eslint-disable-line eqeqeq
+                               } );
+                       };
  
                params = params || {};
  
-               uri = this.getUpdatedUri();
-               uri.extend( params );
+               updatedUri = this.getUpdatedUri();
+               updatedUri.extend( params );
  
-               window.history.pushState( { tag: 'rcfilters' }, document.title, uri.toString() );
+               if ( notEquivalent( updatedUri.query, new mw.Uri().query ) ) {
+                       window.history.pushState( { tag: 'rcfilters' }, document.title, updatedUri.toString() );
+               }
        };
  
        /**
                this.filtersModel.clearHighlightColor( filterName );
                this.updateURL();
        };
+       /**
+        * Clear both highlight and selection of a filter
+        *
+        * @param {string} filterName Name of the filter item
+        */
+       mw.rcfilters.Controller.prototype.clearFilter = function ( filterName ) {
+               var filterItem = this.filtersModel.getItemByName( filterName );
+               if ( filterItem.isSelected() || filterItem.isHighlighted() ) {
+                       this.filtersModel.clearHighlightColor( filterName );
+                       this.filtersModel.toggleFilterSelected( filterName, false );
+                       this.updateChangesList();
+                       this.filtersModel.reassessFilterInteractions( filterItem );
+               }
+       };
+       /**
+        * Synchronize the URL with the current state of the filters
+        * without adding an history entry.
+        */
+       mw.rcfilters.Controller.prototype.replaceUrl = function () {
+               window.history.replaceState(
+                       { tag: 'rcfilters' },
+                       document.title,
+                       this.getUpdatedUri().toString()
+               );
+       };
  }( mediaWiki, jQuery ) );
@@@ -38,7 -38,6 +38,7 @@@
                        popup: {
                                padded: false,
                                align: 'center',
 +                              position: 'above',
                                $content: $popupContent
                                        .append( descLabelWidget.$element ),
                                $floatableContainer: this.$element,
                }
  
                // Respond to user removing the filter
-               this.controller.toggleFilterSelect( this.model.getName(), false );
-               this.controller.clearHighlightColor( this.model.getName() );
+               this.controller.clearFilter( this.model.getName() );
        };
  
        mw.rcfilters.ui.CapsuleItemWidget.prototype.setHighlightColor = function () {
        mw.rcfilters.ui.CapsuleItemWidget.prototype.onMouseEnter = function () {
                if ( this.model.getDescription() ) {
                        if ( !this.positioned ) {
 -                              // Recalculate position to be center of the capsule item
 -                              this.popup.$element.css( 'margin-left', ( this.$element.width() / 2 ) );
 +                              // Recalculate anchor position to be center of the capsule item
 +                              this.popup.$anchor.css( 'margin-left', ( this.$element.width() / 2 ) );
                                this.positioned = true;
                        }