RCFilters UI: Define interaction states for filters
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / mw.rcfilters.Controller.js
index ea44b8b..ff34bb8 100644 (file)
@@ -1,14 +1,14 @@
-( function ( mw ) {
+( function ( mw, $ ) {
        /**
         * Controller for the filters in Recent Changes
         *
-        * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+        * @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Filters view model
+        * @param {mw.rcfilters.dm.ChangesListViewModel} changesListModel Changes list view model
         */
-       mw.rcfilters.Controller = function MwRcfiltersController( model ) {
-               this.model = model;
-
-               // TODO: When we are ready, update the URL when a filter is updated
-               // this.model.connect( this, { itemUpdate: 'updateURL' } );
+       mw.rcfilters.Controller = function MwRcfiltersController( filtersModel, changesListModel ) {
+               this.filtersModel = filtersModel;
+               this.changesListModel = changesListModel;
+               this.requestCounter = 0;
        };
 
        /* Initialization */
 
        /**
         * Initialize the filter and parameter states
+        *
+        * @param {Object} filterStructure Filter definition and structure for the model
         */
-       mw.rcfilters.Controller.prototype.initialize = function () {
+       mw.rcfilters.Controller.prototype.initialize = function ( filterStructure ) {
                var uri = new mw.Uri();
 
-               this.model.updateFilters(
-                       // Translate the url params to filter select states
-                       this.model.getFiltersFromParameters( uri.query )
+               // Initialize the model
+               this.filtersModel.initializeFilters( filterStructure );
+
+               // Set filter states based on defaults and URL params
+               this.filtersModel.updateFilters(
+                       this.filtersModel.getFiltersFromParameters(
+                               // Merge defaults with URL params for initialization
+                               $.extend(
+                                       true,
+                                       {},
+                                       this.filtersModel.getDefaultParams(),
+                                       // URI query overrides defaults
+                                       uri.query
+                               )
+                       )
                );
+
+               // Check all filter interactions
+               this.filtersModel.reassessFilterInteractions();
+       };
+
+       /**
+        * Reset to default filters
+        */
+       mw.rcfilters.Controller.prototype.resetToDefaults = function () {
+               this.filtersModel.setFiltersToDefaults();
+               this.updateURL();
+               this.updateChangesList();
+       };
+
+       /**
+        * Empty all selected filters
+        */
+       mw.rcfilters.Controller.prototype.emptyFilters = function () {
+               this.filtersModel.emptyAllFilters();
+               this.updateURL();
+               this.updateChangesList();
        };
 
        /**
                var obj = {};
 
                obj[ filterName ] = isSelected;
-               this.model.updateFilters( obj );
+
+               this.filtersModel.updateFilters( obj );
+               this.updateURL();
+               this.updateChangesList();
+
+               // Check filter interactions
+               this.filtersModel.reassessFilterInteractions( this.filtersModel.getItemByName( filterName ) );
        };
 
        /**
                // TODO: Clean up the list of filters; perhaps 'falsy' filters
                // shouldn't appear at all? Or compare to existing query string
                // and see if current state of a specific filter is needed?
-               uri.extend( this.model.getParametersFromFilters() );
+               uri.extend( this.filtersModel.getParametersFromFilters() );
 
                // Update the URL itself
                window.history.pushState( { tag: 'rcfilters' }, document.title, uri.toString() );
        };
-}( mediaWiki ) );
+
+       /**
+        * Fetch the list of changes from the server for the current filters
+        *
+        * @returns {jQuery.Promise} Promise object that will resolve with the changes list
+        */
+       mw.rcfilters.Controller.prototype.fetchChangesList = function () {
+               var uri = new mw.Uri(),
+                       requestId = ++this.requestCounter,
+                       latestRequest = function () {
+                               return requestId === this.requestCounter;
+                       }.bind( this );
+               uri.extend( this.filtersModel.getParametersFromFilters() );
+               return $.ajax( uri.toString(), { contentType: 'html' } )
+                       .then( function ( html ) {
+                               return latestRequest() ?
+                                       $( $.parseHTML( html ) ).find( '.mw-changeslist' ).first().contents() :
+                                       null;
+                       } ).then( null, function () {
+                               return latestRequest() ? 'NO_RESULTS' : null;
+                       } );
+       };
+
+       /**
+        * Update the list of changes and notify the model
+        */
+       mw.rcfilters.Controller.prototype.updateChangesList = function () {
+               this.changesListModel.invalidate();
+               this.fetchChangesList()
+                       .always( function ( changesListContent ) {
+                               if ( changesListContent ) {
+                                       this.changesListModel.update( changesListContent );
+                               }
+                       }.bind( this ) );
+       };
+}( mediaWiki, jQuery ) );