RCFilters UI: Select filter when searching and add it on 'enter'
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / mw.rcfilters.Controller.js
1 ( function ( mw, $ ) {
2 /**
3 * Controller for the filters in Recent Changes
4 *
5 * @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Filters view model
6 * @param {mw.rcfilters.dm.ChangesListViewModel} changesListModel Changes list view model
7 */
8 mw.rcfilters.Controller = function MwRcfiltersController( filtersModel, changesListModel ) {
9 this.filtersModel = filtersModel;
10 this.changesListModel = changesListModel;
11 this.requestCounter = 0;
12 };
13
14 /* Initialization */
15 OO.initClass( mw.rcfilters.Controller );
16
17 /**
18 * Initialize the filter and parameter states
19 *
20 * @param {Object} filterStructure Filter definition and structure for the model
21 */
22 mw.rcfilters.Controller.prototype.initialize = function ( filterStructure ) {
23 var uri = new mw.Uri();
24
25 // Initialize the model
26 this.filtersModel.initializeFilters( filterStructure );
27
28 // Set filter states based on defaults and URL params
29 this.filtersModel.updateFilters(
30 this.filtersModel.getFiltersFromParameters(
31 // Merge defaults with URL params for initialization
32 $.extend(
33 true,
34 {},
35 this.filtersModel.getDefaultParams(),
36 // URI query overrides defaults
37 uri.query
38 )
39 )
40 );
41
42 // Initialize highlights
43 this.filtersModel.toggleHighlight( !!uri.query.highlight );
44 this.filtersModel.getItems().forEach( function ( filterItem ) {
45 var color = uri.query[ filterItem.getName() + '_color' ];
46 if ( !color ) {
47 return;
48 }
49
50 filterItem.setHighlightColor( color );
51 } );
52
53 // Check all filter interactions
54 this.filtersModel.reassessFilterInteractions();
55 };
56
57 /**
58 * Reset to default filters
59 */
60 mw.rcfilters.Controller.prototype.resetToDefaults = function () {
61 this.filtersModel.setFiltersToDefaults();
62 // Check all filter interactions
63 this.filtersModel.reassessFilterInteractions();
64
65 this.updateURL();
66 this.updateChangesList();
67 };
68
69 /**
70 * Empty all selected filters
71 */
72 mw.rcfilters.Controller.prototype.emptyFilters = function () {
73 this.filtersModel.emptyAllFilters();
74 this.filtersModel.clearAllHighlightColors();
75 // Check all filter interactions
76 this.filtersModel.reassessFilterInteractions();
77
78 this.updateURL();
79 this.updateChangesList();
80 };
81
82 /**
83 * Update the selected state of a filter
84 *
85 * @param {string} filterName Filter name
86 * @param {boolean} [isSelected] Filter selected state
87 */
88 mw.rcfilters.Controller.prototype.toggleFilterSelect = function ( filterName, isSelected ) {
89 var obj = {},
90 filterItem = this.filtersModel.getItemByName( filterName );
91
92 isSelected = isSelected === undefined ? !filterItem.isSelected() : isSelected;
93
94 if ( filterItem.isSelected() !== isSelected ) {
95 obj[ filterName ] = isSelected;
96 this.filtersModel.updateFilters( obj );
97
98 this.updateURL();
99 this.updateChangesList();
100
101 // Check filter interactions
102 this.filtersModel.reassessFilterInteractions( this.filtersModel.getItemByName( filterName ) );
103 }
104 };
105
106 /**
107 * Update the URL of the page to reflect current filters
108 */
109 mw.rcfilters.Controller.prototype.updateURL = function () {
110 var uri = this.getUpdatedUri();
111 window.history.pushState( { tag: 'rcfilters' }, document.title, uri.toString() );
112 };
113
114 /**
115 * Get an updated mw.Uri object based on the model state
116 *
117 * @return {mw.Uri} Updated Uri
118 */
119 mw.rcfilters.Controller.prototype.getUpdatedUri = function () {
120 var uri = new mw.Uri(),
121 highlightParams = this.filtersModel.getHighlightParameters();
122
123 // Add to existing queries in URL
124 // TODO: Clean up the list of filters; perhaps 'falsy' filters
125 // shouldn't appear at all? Or compare to existing query string
126 // and see if current state of a specific filter is needed?
127 uri.extend( this.filtersModel.getParametersFromFilters() );
128
129 // highlight params
130 Object.keys( highlightParams ).forEach( function ( paramName ) {
131 if ( highlightParams[ paramName ] ) {
132 uri.query[ paramName ] = highlightParams[ paramName ];
133 } else {
134 delete uri.query[ paramName ];
135 }
136 } );
137
138 return uri;
139 };
140
141 /**
142 * Fetch the list of changes from the server for the current filters
143 *
144 * @return {jQuery.Promise} Promise object that will resolve with the changes list
145 */
146 mw.rcfilters.Controller.prototype.fetchChangesList = function () {
147 var uri = this.getUpdatedUri(),
148 requestId = ++this.requestCounter,
149 latestRequest = function () {
150 return requestId === this.requestCounter;
151 }.bind( this );
152 uri.extend( this.filtersModel.getParametersFromFilters() );
153 return $.ajax( uri.toString(), { contentType: 'html' } )
154 .then( function ( html ) {
155 return latestRequest() ?
156 $( $.parseHTML( html ) ).find( '.mw-changeslist' ).first().contents() :
157 null;
158 } ).then( null, function () {
159 return latestRequest() ? 'NO_RESULTS' : null;
160 } );
161 };
162
163 /**
164 * Update the list of changes and notify the model
165 */
166 mw.rcfilters.Controller.prototype.updateChangesList = function () {
167 this.changesListModel.invalidate();
168 this.fetchChangesList()
169 .always( function ( changesListContent ) {
170 if ( changesListContent ) {
171 this.changesListModel.update( changesListContent );
172 }
173 }.bind( this ) );
174 };
175
176 /**
177 * Toggle the highlight feature on and off
178 */
179 mw.rcfilters.Controller.prototype.toggleHighlight = function () {
180 this.filtersModel.toggleHighlight();
181 this.updateURL();
182 };
183
184 /**
185 * Set the highlight color for a filter item
186 *
187 * @param {string} filterName Name of the filter item
188 * @param {string} color Selected color
189 */
190 mw.rcfilters.Controller.prototype.setHighlightColor = function ( filterName, color ) {
191 this.filtersModel.setHighlightColor( filterName, color );
192 this.updateURL();
193 };
194
195 /**
196 * Clear highlight for a filter item
197 *
198 * @param {string} filterName Name of the filter item
199 */
200 mw.rcfilters.Controller.prototype.clearHighlightColor = function ( filterName ) {
201 this.filtersModel.clearHighlightColor( filterName );
202 this.updateURL();
203 };
204 }( mediaWiki, jQuery ) );