Merge "Align "What's this" vertically"
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / dm / mw.rcfilters.dm.ItemModel.js
1 ( function ( mw ) {
2 /**
3 * RCFilter base item model
4 *
5 * @mixins OO.EventEmitter
6 *
7 * @constructor
8 * @param {string} param Filter param name
9 * @param {Object} config Configuration object
10 * @cfg {string} [label] The label for the filter
11 * @cfg {string} [description] The description of the filter
12 * @cfg {string|Object} [labelPrefixKey] An i18n key defining the prefix label for this
13 * group. If the prefix has 'invert' state, the parameter is expected to be an object
14 * with 'default' and 'inverted' as keys.
15 * @cfg {boolean} [active=true] The filter is active and affecting the result
16 * @cfg {boolean} [selected] The item is selected
17 * @cfg {boolean} [inverted] The item is inverted, meaning the search is excluding
18 * this parameter.
19 * @cfg {string} [namePrefix='item_'] A prefix to add to the param name to act as a unique
20 * identifier
21 * @cfg {string} [cssClass] The class identifying the results that match this filter
22 * @cfg {string[]} [identifiers] An array of identifiers for this item. They will be
23 * added and considered in the view.
24 */
25 mw.rcfilters.dm.ItemModel = function MwRcfiltersDmItemModel( param, config ) {
26 config = config || {};
27
28 // Mixin constructor
29 OO.EventEmitter.call( this );
30
31 this.param = param;
32 this.namePrefix = config.namePrefix || 'item_';
33 this.name = this.namePrefix + param;
34
35 this.label = config.label || this.name;
36 this.labelPrefixKey = config.labelPrefixKey;
37 this.description = config.description || '';
38 this.selected = !!config.selected;
39
40 this.inverted = !!config.inverted;
41 this.identifiers = config.identifiers || [];
42
43 // Highlight
44 this.cssClass = config.cssClass;
45 this.highlightColor = null;
46 this.highlightEnabled = false;
47 };
48
49 /* Initialization */
50
51 OO.initClass( mw.rcfilters.dm.ItemModel );
52 OO.mixinClass( mw.rcfilters.dm.ItemModel, OO.EventEmitter );
53
54 /* Events */
55
56 /**
57 * @event update
58 *
59 * The state of this filter has changed
60 */
61
62 /* Methods */
63
64 /**
65 * Return the representation of the state of this item.
66 *
67 * @return {Object} State of the object
68 */
69 mw.rcfilters.dm.ItemModel.prototype.getState = function () {
70 return {
71 selected: this.isSelected(),
72 inverted: this.isInverted()
73 };
74 };
75
76 /**
77 * Get the name of this filter
78 *
79 * @return {string} Filter name
80 */
81 mw.rcfilters.dm.ItemModel.prototype.getName = function () {
82 return this.name;
83 };
84
85 /**
86 * Get a prefixed label
87 *
88 * @return {string} Prefixed label
89 */
90 mw.rcfilters.dm.ItemModel.prototype.getPrefixedLabel = function () {
91 if ( this.labelPrefixKey ) {
92 if ( typeof this.labelPrefixKey === 'string' ) {
93 return mw.message( this.labelPrefixKey, this.getLabel() ).parse();
94 } else {
95 return mw.message(
96 this.labelPrefixKey[
97 // Only use inverted-prefix if the item is selected
98 // Highlight-only an inverted item makes no sense
99 this.isInverted() && this.isSelected() ?
100 'inverted' : 'default'
101 ],
102 this.getLabel()
103 ).parse();
104 }
105 } else {
106 return this.getLabel();
107 }
108 };
109
110 /**
111 * Get the param name or value of this filter
112 *
113 * @return {string} Filter param name
114 */
115 mw.rcfilters.dm.ItemModel.prototype.getParamName = function () {
116 return this.param;
117 };
118
119 /**
120 * Get the message representing the state of this model.
121 *
122 * @return {string} State message
123 */
124 mw.rcfilters.dm.ItemModel.prototype.getStateMessage = function () {
125 // Display description
126 return this.getDescription();
127 };
128
129 /**
130 * Get the label of this filter
131 *
132 * @return {string} Filter label
133 */
134 mw.rcfilters.dm.ItemModel.prototype.getLabel = function () {
135 return this.label;
136 };
137
138 /**
139 * Get the description of this filter
140 *
141 * @return {string} Filter description
142 */
143 mw.rcfilters.dm.ItemModel.prototype.getDescription = function () {
144 return this.description;
145 };
146
147 /**
148 * Get the default value of this filter
149 *
150 * @return {boolean} Filter default
151 */
152 mw.rcfilters.dm.ItemModel.prototype.getDefault = function () {
153 return this.default;
154 };
155
156 /**
157 * Get the selected state of this filter
158 *
159 * @return {boolean} Filter is selected
160 */
161 mw.rcfilters.dm.ItemModel.prototype.isSelected = function () {
162 return this.selected;
163 };
164
165 /**
166 * Toggle the selected state of the item
167 *
168 * @param {boolean} [isSelected] Filter is selected
169 * @fires update
170 */
171 mw.rcfilters.dm.ItemModel.prototype.toggleSelected = function ( isSelected ) {
172 isSelected = isSelected === undefined ? !this.selected : isSelected;
173
174 if ( this.selected !== isSelected ) {
175 this.selected = isSelected;
176 this.emit( 'update' );
177 }
178 };
179
180 /**
181 * Get the inverted state of this item
182 *
183 * @return {boolean} Item is inverted
184 */
185 mw.rcfilters.dm.ItemModel.prototype.isInverted = function () {
186 return this.inverted;
187 };
188
189 /**
190 * Toggle the inverted state of the item
191 *
192 * @param {boolean} [isInverted] Item is inverted
193 * @fires update
194 */
195 mw.rcfilters.dm.ItemModel.prototype.toggleInverted = function ( isInverted ) {
196 isInverted = isInverted === undefined ? !this.inverted : isInverted;
197
198 if ( this.inverted !== isInverted ) {
199 this.inverted = isInverted;
200 this.emit( 'update' );
201 }
202 };
203
204 /**
205 * Set the highlight color
206 *
207 * @param {string|null} highlightColor
208 */
209 mw.rcfilters.dm.ItemModel.prototype.setHighlightColor = function ( highlightColor ) {
210 if ( this.highlightColor !== highlightColor ) {
211 this.highlightColor = highlightColor;
212 this.emit( 'update' );
213 }
214 };
215
216 /**
217 * Clear the highlight color
218 */
219 mw.rcfilters.dm.ItemModel.prototype.clearHighlightColor = function () {
220 this.setHighlightColor( null );
221 };
222
223 /**
224 * Get the highlight color, or null if none is configured
225 *
226 * @return {string|null}
227 */
228 mw.rcfilters.dm.ItemModel.prototype.getHighlightColor = function () {
229 return this.highlightColor;
230 };
231
232 /**
233 * Get the CSS class that matches changes that fit this filter
234 * or null if none is configured
235 *
236 * @return {string|null}
237 */
238 mw.rcfilters.dm.ItemModel.prototype.getCssClass = function () {
239 return this.cssClass;
240 };
241
242 /**
243 * Get the item's identifiers
244 *
245 * @return {string[]}
246 */
247 mw.rcfilters.dm.ItemModel.prototype.getIdentifiers = function () {
248 return this.identifiers;
249 };
250
251 /**
252 * Toggle the highlight feature on and off for this filter.
253 * It only works if highlight is supported for this filter.
254 *
255 * @param {boolean} enable Highlight should be enabled
256 */
257 mw.rcfilters.dm.ItemModel.prototype.toggleHighlight = function ( enable ) {
258 enable = enable === undefined ? !this.highlightEnabled : enable;
259
260 if ( !this.isHighlightSupported() ) {
261 return;
262 }
263
264 if ( enable === this.highlightEnabled ) {
265 return;
266 }
267
268 this.highlightEnabled = enable;
269 this.emit( 'update' );
270 };
271
272 /**
273 * Check if the highlight feature is currently enabled for this filter
274 *
275 * @return {boolean}
276 */
277 mw.rcfilters.dm.ItemModel.prototype.isHighlightEnabled = function () {
278 return !!this.highlightEnabled;
279 };
280
281 /**
282 * Check if the highlight feature is supported for this filter
283 *
284 * @return {boolean}
285 */
286 mw.rcfilters.dm.ItemModel.prototype.isHighlightSupported = function () {
287 return !!this.getCssClass();
288 };
289
290 /**
291 * Check if the filter is currently highlighted
292 *
293 * @return {boolean}
294 */
295 mw.rcfilters.dm.ItemModel.prototype.isHighlighted = function () {
296 return this.isHighlightEnabled() && !!this.getHighlightColor();
297 };
298 }( mediaWiki ) );