Merge "Fix Title::loadRestrictions() for create-protected titles"
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / mw.rcfilters.init.js
1 /*!
2 * JavaScript for Special:RecentChanges
3 */
4 ( function ( mw, $ ) {
5 /**
6 * @class mw.rcfilters
7 * @singleton
8 */
9 var rcfilters = {
10 /** */
11 init: function () {
12 var filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
13 changesListModel = new mw.rcfilters.dm.ChangesListViewModel(),
14 controller = new mw.rcfilters.Controller( filtersModel, changesListModel ),
15 $overlay = $( '<div>' )
16 .addClass( 'mw-rcfilters-ui-overlay' ),
17 filtersWidget = new mw.rcfilters.ui.FilterWrapperWidget(
18 controller, filtersModel, { $overlay: $overlay } );
19
20 // eslint-disable-next-line no-new
21 new mw.rcfilters.ui.ChangesListWrapperWidget(
22 filtersModel, changesListModel, $( '.mw-changeslist, .mw-changeslist-empty' ) );
23
24 // eslint-disable-next-line no-new
25 new mw.rcfilters.ui.FormWrapperWidget(
26 changesListModel, controller, $( 'fieldset.rcoptions' ) );
27
28 controller.initialize( {
29 registration: {
30 title: mw.msg( 'rcfilters-filtergroup-registration' ),
31 type: 'send_unselected_if_any',
32 fullCoverage: true,
33 filters: [
34 {
35 name: 'hideliu',
36 label: mw.msg( 'rcfilters-filter-registered-label' ),
37 description: mw.msg( 'rcfilters-filter-registered-description' ),
38 'class': 'mw-changeslist-liu'
39 },
40 {
41 name: 'hideanons',
42 label: mw.msg( 'rcfilters-filter-unregistered-label' ),
43 description: mw.msg( 'rcfilters-filter-unregistered-description' ),
44 'class': 'mw-changeslist-anon'
45 }
46 ]
47 },
48 userExpLevel: {
49 title: mw.msg( 'rcfilters-filtergroup-userExpLevel' ),
50 // Type 'string_options' means that the group is evaluated by
51 // string values separated by comma; for example, param=opt1,opt2
52 // If all options are selected they are replaced by the term "all".
53 // The filters are the values for the parameter defined by the group.
54 // ** In this case, the parameter name is the group name. **
55 type: 'string_options',
56 separator: ',',
57 fullCoverage: false,
58 filters: [
59 {
60 name: 'newcomer',
61 label: mw.msg( 'rcfilters-filter-userExpLevel-newcomer-label' ),
62 description: mw.msg( 'rcfilters-filter-userExpLevel-newcomer-description' ),
63 conflicts: [ 'hideanons' ],
64 'class': 'mw-changeslist-user-newcomer'
65 },
66 {
67 name: 'learner',
68 label: mw.msg( 'rcfilters-filter-userExpLevel-learner-label' ),
69 description: mw.msg( 'rcfilters-filter-userExpLevel-learner-description' ),
70 conflicts: [ 'hideanons' ],
71 'class': 'mw-changeslist-user-learner'
72 },
73 {
74 name: 'experienced',
75 label: mw.msg( 'rcfilters-filter-userExpLevel-experienced-label' ),
76 description: mw.msg( 'rcfilters-filter-userExpLevel-experienced-description' ),
77 conflicts: [ 'hideanons' ],
78 'class': 'mw-changeslist-user-experienced'
79 }
80 ]
81 },
82 authorship: {
83 title: mw.msg( 'rcfilters-filtergroup-authorship' ),
84 // Type 'send_unselected_if_any' means that the controller will go over
85 // all unselected filters in the group and use their parameters
86 // as truthy in the query string.
87 // This is to handle the "negative" filters. We are showing users
88 // a positive message ("Show xxx") but the filters themselves are
89 // based on "hide YYY". The purpose of this is to correctly map
90 // the functionality to the UI, whether we are dealing with 2
91 // parameters in the group or more.
92 type: 'send_unselected_if_any',
93 fullCoverage: true,
94 filters: [
95 {
96 name: 'hidemyself',
97 label: mw.msg( 'rcfilters-filter-editsbyself-label' ),
98 description: mw.msg( 'rcfilters-filter-editsbyself-description' ),
99 'class': 'mw-changeslist-self'
100 },
101 {
102 name: 'hidebyothers',
103 label: mw.msg( 'rcfilters-filter-editsbyother-label' ),
104 description: mw.msg( 'rcfilters-filter-editsbyother-description' ),
105 'class': 'mw-changeslist-others'
106 }
107 ]
108 },
109 automated: {
110 title: mw.msg( 'rcfilters-filtergroup-automated' ),
111 type: 'send_unselected_if_any',
112 fullCoverage: true,
113 filters: [
114 {
115 name: 'hidebots',
116 label: mw.msg( 'rcfilters-filter-bots-label' ),
117 description: mw.msg( 'rcfilters-filter-bots-description' ),
118 'default': true,
119 'class': 'mw-changeslist-bot'
120 },
121 {
122 name: 'hidehumans',
123 label: mw.msg( 'rcfilters-filter-humans-label' ),
124 description: mw.msg( 'rcfilters-filter-humans-description' ),
125 'default': false,
126 'class': 'mw-changeslist-human'
127 }
128 ]
129 },
130 significance: {
131 title: mw.msg( 'rcfilters-filtergroup-significance' ),
132 type: 'send_unselected_if_any',
133 fullCoverage: true,
134 filters: [
135 {
136 name: 'hideminor',
137 label: mw.msg( 'rcfilters-filter-minor-label' ),
138 description: mw.msg( 'rcfilters-filter-minor-description' ),
139 'class': 'mw-changeslist-minor'
140 },
141 {
142 name: 'hidemajor',
143 label: mw.msg( 'rcfilters-filter-major-label' ),
144 description: mw.msg( 'rcfilters-filter-major-description' ),
145 'class': 'mw-changeslist-major'
146 }
147 ]
148 },
149 changetype: {
150 title: mw.msg( 'rcfilters-filtergroup-changetype' ),
151 type: 'send_unselected_if_any',
152 fullCoverage: true,
153 filters: [
154 {
155 name: 'hidepageedits',
156 label: mw.msg( 'rcfilters-filter-pageedits-label' ),
157 description: mw.msg( 'rcfilters-filter-pageedits-description' ),
158 'default': false,
159 'class': 'mw-changeslist-src-mw-edit'
160
161 },
162 {
163 name: 'hidenewpages',
164 label: mw.msg( 'rcfilters-filter-newpages-label' ),
165 description: mw.msg( 'rcfilters-filter-newpages-description' ),
166 'default': false,
167 'class': 'mw-changeslist-src-mw-new'
168 },
169 {
170 name: 'hidecategorization',
171 label: mw.msg( 'rcfilters-filter-categorization-label' ),
172 description: mw.msg( 'rcfilters-filter-categorization-description' ),
173 'default': true,
174 'class': 'mw-changeslist-src-mw-categorize'
175 },
176 {
177 name: 'hidelog',
178 label: mw.msg( 'rcfilters-filter-logactions-label' ),
179 description: mw.msg( 'rcfilters-filter-logactions-description' ),
180 'default': false,
181 'class': 'mw-changeslist-src-mw-log'
182 }
183 ]
184 }
185 } );
186
187 $( '.rcfilters-container' ).append( filtersWidget.$element );
188 $( 'body' ).append( $overlay );
189
190 // HACK: Remove old-style filter links for filters handled by the widget
191 // Ideally the widget would handle all filters and we'd just remove .rcshowhide entirely
192 $( '.rcshowhide' ).children().each( function () {
193 // HACK: Interpret the class name to get the filter name
194 // This should really be set as a data attribute
195 var i,
196 name = null,
197 // Some of the older browsers we support don't have .classList,
198 // so we have to interpret the class attribute manually.
199 classes = this.getAttribute( 'class' ).split( ' ' );
200 for ( i = 0; i < classes.length; i++ ) {
201 if ( classes[ i ].substr( 0, 'rcshow'.length ) === 'rcshow' ) {
202 name = classes[ i ].substr( 'rcshow'.length );
203 break;
204 }
205 }
206 if ( name === null ) {
207 return;
208 }
209 if ( name === 'hidemine' ) {
210 // HACK: the span for hidemyself is called hidemine
211 name = 'hidemyself';
212 }
213 // This span corresponds to a filter that's in our model, so remove it
214 if ( filtersModel.getItemByName( name ) ) {
215 // HACK: Remove the text node after the span.
216 // If there isn't one, we're at the end, so remove the text node before the span.
217 // This would be unnecessary if we added separators with CSS.
218 if ( this.nextSibling && this.nextSibling.nodeType === Node.TEXT_NODE ) {
219 this.parentNode.removeChild( this.nextSibling );
220 } else if ( this.previousSibling && this.previousSibling.nodeType === Node.TEXT_NODE ) {
221 this.parentNode.removeChild( this.previousSibling );
222 }
223 // Remove the span itself
224 this.parentNode.removeChild( this );
225 }
226 } );
227
228 window.addEventListener( 'popstate', function () {
229 controller.updateChangesList();
230 } );
231
232 $( 'a.mw-helplink' ).attr(
233 'href',
234 'https://www.mediawiki.org/wiki/Special:MyLanguage/Help:New_filters_for_edit_review'
235 );
236 }
237 };
238
239 $( rcfilters.init );
240
241 module.exports = rcfilters;
242
243 }( mediaWiki, jQuery ) );