Merge "selenium: invoke jobs to enforce eventual consistency"
[lhc/web/wiklou.git] / resources / src / mediawiki.rcfilters / dm / mw.rcfilters.dm.ItemModel.js
1 ( function () {
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 {*} [value] The value of this item
18 * @cfg {string} [namePrefix='item_'] A prefix to add to the param name to act as a unique
19 * identifier
20 * @cfg {string} [cssClass] The class identifying the results that match this filter
21 * @cfg {string[]} [identifiers] An array of identifiers for this item. They will be
22 * added and considered in the view.
23 * @cfg {string} [defaultHighlightColor=null] If set, highlight this filter by default with this color
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.setValue( config.value || config.selected );
39
40 this.identifiers = config.identifiers || [];
41
42 // Highlight
43 this.cssClass = config.cssClass;
44 this.highlightColor = config.defaultHighlightColor || null;
45 };
46
47 /* Initialization */
48
49 OO.initClass( mw.rcfilters.dm.ItemModel );
50 OO.mixinClass( mw.rcfilters.dm.ItemModel, OO.EventEmitter );
51
52 /* Events */
53
54 /**
55 * @event update
56 *
57 * The state of this filter has changed
58 */
59
60 /* Methods */
61
62 /**
63 * Return the representation of the state of this item.
64 *
65 * @return {Object} State of the object
66 */
67 mw.rcfilters.dm.ItemModel.prototype.getState = function () {
68 return {
69 selected: this.isSelected()
70 };
71 };
72
73 /**
74 * Get the name of this filter
75 *
76 * @return {string} Filter name
77 */
78 mw.rcfilters.dm.ItemModel.prototype.getName = function () {
79 return this.name;
80 };
81
82 /**
83 * Get the message key to use to wrap the label. This message takes the label as a parameter.
84 *
85 * @param {boolean} inverted Whether this item should be considered inverted
86 * @return {string|null} Message key, or null if no message
87 */
88 mw.rcfilters.dm.ItemModel.prototype.getLabelMessageKey = function ( inverted ) {
89 if ( this.labelPrefixKey ) {
90 if ( typeof this.labelPrefixKey === 'string' ) {
91 return this.labelPrefixKey;
92 }
93 return this.labelPrefixKey[
94 // Only use inverted-prefix if the item is selected
95 // Highlight-only an inverted item makes no sense
96 inverted && this.isSelected() ?
97 'inverted' : 'default'
98 ];
99 }
100 return null;
101 };
102
103 /**
104 * Get the param name or value of this filter
105 *
106 * @return {string} Filter param name
107 */
108 mw.rcfilters.dm.ItemModel.prototype.getParamName = function () {
109 return this.param;
110 };
111
112 /**
113 * Get the message representing the state of this model.
114 *
115 * @return {string} State message
116 */
117 mw.rcfilters.dm.ItemModel.prototype.getStateMessage = function () {
118 // Display description
119 return this.getDescription();
120 };
121
122 /**
123 * Get the label of this filter
124 *
125 * @return {string} Filter label
126 */
127 mw.rcfilters.dm.ItemModel.prototype.getLabel = function () {
128 return this.label;
129 };
130
131 /**
132 * Get the description of this filter
133 *
134 * @return {string} Filter description
135 */
136 mw.rcfilters.dm.ItemModel.prototype.getDescription = function () {
137 return this.description;
138 };
139
140 /**
141 * Get the default value of this filter
142 *
143 * @return {boolean} Filter default
144 */
145 mw.rcfilters.dm.ItemModel.prototype.getDefault = function () {
146 return this.default;
147 };
148
149 /**
150 * Get the selected state of this filter
151 *
152 * @return {boolean} Filter is selected
153 */
154 mw.rcfilters.dm.ItemModel.prototype.isSelected = function () {
155 return !!this.value;
156 };
157
158 /**
159 * Toggle the selected state of the item
160 *
161 * @param {boolean} [isSelected] Filter is selected
162 * @fires update
163 */
164 mw.rcfilters.dm.ItemModel.prototype.toggleSelected = function ( isSelected ) {
165 isSelected = isSelected === undefined ? !this.isSelected() : isSelected;
166 this.setValue( isSelected );
167 };
168
169 /**
170 * Get the value
171 *
172 * @return {*}
173 */
174 mw.rcfilters.dm.ItemModel.prototype.getValue = function () {
175 return this.value;
176 };
177
178 /**
179 * Convert a given value to the appropriate representation based on group type
180 *
181 * @param {*} value
182 * @return {*}
183 */
184 mw.rcfilters.dm.ItemModel.prototype.coerceValue = function ( value ) {
185 return this.getGroupModel().getType() === 'any_value' ? value : !!value;
186 };
187
188 /**
189 * Set the value
190 *
191 * @param {*} newValue
192 */
193 mw.rcfilters.dm.ItemModel.prototype.setValue = function ( newValue ) {
194 newValue = this.coerceValue( newValue );
195 if ( this.value !== newValue ) {
196 this.value = newValue;
197 this.emit( 'update' );
198 }
199 };
200
201 /**
202 * Set the highlight color
203 *
204 * @param {string|null} highlightColor
205 */
206 mw.rcfilters.dm.ItemModel.prototype.setHighlightColor = function ( highlightColor ) {
207 if ( !this.isHighlightSupported() ) {
208 return;
209 }
210 // If the highlight color on the item and in the parameter is null/undefined, return early.
211 if ( !this.highlightColor && !highlightColor ) {
212 return;
213 }
214
215 if ( this.highlightColor !== highlightColor ) {
216 this.highlightColor = highlightColor;
217 this.emit( 'update' );
218 }
219 };
220
221 /**
222 * Clear the highlight color
223 */
224 mw.rcfilters.dm.ItemModel.prototype.clearHighlightColor = function () {
225 this.setHighlightColor( null );
226 };
227
228 /**
229 * Get the highlight color, or null if none is configured
230 *
231 * @return {string|null}
232 */
233 mw.rcfilters.dm.ItemModel.prototype.getHighlightColor = function () {
234 return this.highlightColor;
235 };
236
237 /**
238 * Get the CSS class that matches changes that fit this filter
239 * or null if none is configured
240 *
241 * @return {string|null}
242 */
243 mw.rcfilters.dm.ItemModel.prototype.getCssClass = function () {
244 return this.cssClass;
245 };
246
247 /**
248 * Get the item's identifiers
249 *
250 * @return {string[]}
251 */
252 mw.rcfilters.dm.ItemModel.prototype.getIdentifiers = function () {
253 return this.identifiers;
254 };
255
256 /**
257 * Check if the highlight feature is supported for this filter
258 *
259 * @return {boolean}
260 */
261 mw.rcfilters.dm.ItemModel.prototype.isHighlightSupported = function () {
262 return !!this.getCssClass();
263 };
264
265 /**
266 * Check if the filter is currently highlighted
267 *
268 * @return {boolean}
269 */
270 mw.rcfilters.dm.ItemModel.prototype.isHighlighted = function () {
271 return !!this.getHighlightColor();
272 };
273 }() );