Remove the basic styles that vector coppied from monobook from both monobook and...
[lhc/web/wiklou.git] / skins / common / protect.js
1
2 window.ProtectionForm = {
3 'existingMatch': false,
4
5 /**
6 * Set up the protection chaining interface (i.e. "unlock move permissions" checkbox)
7 * on the protection form
8 *
9 * @param opts Object : parameters with members:
10 * tableId Identifier of the table containing UI bits
11 * labelText Text to use for the checkbox label
12 * numTypes The number of protection types
13 * existingMatch True if all the existing expiry times match
14 */
15 'init': function( opts ) {
16 if( !( document.createTextNode && document.getElementById && document.getElementsByTagName ) )
17 return false;
18
19 var box = document.getElementById( opts.tableId );
20 if( !box )
21 return false;
22
23 var boxbody = box.getElementsByTagName('tbody')[0];
24 var row = document.createElement( 'tr' );
25 boxbody.insertBefore( row, boxbody.firstChild.nextSibling );
26
27 this.existingMatch = opts.existingMatch;
28
29 var cell = document.createElement( 'td' );
30 row.appendChild( cell );
31 // If there is only one protection type, there is nothing to chain
32 if( opts.numTypes > 1 ) {
33 var check = document.createElement( 'input' );
34 check.id = 'mwProtectUnchained';
35 check.type = 'checkbox';
36 cell.appendChild( check );
37 addClickHandler( check, function() { ProtectionForm.onChainClick(); } );
38
39 cell.appendChild( document.createTextNode( ' ' ) );
40 var label = document.createElement( 'label' );
41 label.htmlFor = 'mwProtectUnchained';
42 label.appendChild( document.createTextNode( opts.labelText ) );
43 cell.appendChild( label );
44
45 check.checked = !this.areAllTypesMatching();
46 this.enableUnchainedInputs( check.checked );
47 }
48
49 $( '#mwProtect-reason' ).byteLimit( 180 );
50
51 this.updateCascadeCheckbox();
52
53 return true;
54 },
55
56 /**
57 * Sets the disabled attribute on the cascade checkbox depending on the current selected levels
58 */
59 'updateCascadeCheckbox': function() {
60 // For non-existent titles, there is no cascade option
61 if( !document.getElementById( 'mwProtect-cascade' ) ) {
62 return;
63 }
64 var lists = this.getLevelSelectors();
65 for( var i = 0; i < lists.length; i++ ) {
66 if( lists[i].selectedIndex > -1 ) {
67 var items = lists[i].getElementsByTagName( 'option' );
68 var selected = items[ lists[i].selectedIndex ].value;
69 if( !this.isCascadeableLevel(selected) ) {
70 document.getElementById( 'mwProtect-cascade' ).checked = false;
71 document.getElementById( 'mwProtect-cascade' ).disabled = true;
72 return;
73 }
74 }
75 }
76 document.getElementById( 'mwProtect-cascade' ).disabled = false;
77 },
78
79 /**
80 * Is this protection level cascadeable?
81 * @param level String
82 *
83 * @return boolean
84 *
85 */
86 'isCascadeableLevel': function( level ) {
87 for (var k = 0; k < wgCascadeableLevels.length; k++) {
88 if ( wgCascadeableLevels[k] == level ) {
89 return true;
90 }
91 }
92 return false;
93 },
94
95 /**
96 * When protection levels are locked together, update the rest
97 * when one action's level changes
98 *
99 * @param source Element Level selector that changed
100 */
101 'updateLevels': function(source) {
102 if( !this.isUnchained() )
103 this.setAllSelectors( source.selectedIndex );
104 this.updateCascadeCheckbox();
105 },
106
107 /**
108 * When protection levels are locked together, update the
109 * expiries when one changes
110 *
111 * @param source Element expiry input that changed
112 */
113
114 'updateExpiry': function(source) {
115 if( !this.isUnchained() ) {
116 var expiry = source.value;
117 this.forEachExpiryInput(function(element) {
118 element.value = expiry;
119 });
120 }
121 var listId = source.id.replace( /^mwProtect-(\w+)-expires$/, 'mwProtectExpirySelection-$1' );
122 var list = document.getElementById( listId );
123 if (list && list.value != 'othertime' ) {
124 if ( this.isUnchained() ) {
125 list.value = 'othertime';
126 } else {
127 this.forEachExpirySelector(function(element) {
128 element.value = 'othertime';
129 });
130 }
131 }
132 },
133
134 /**
135 * When protection levels are locked together, update the
136 * expiry lists when one changes and clear the custom inputs
137 *
138 * @param source Element expiry selector that changed
139 */
140 'updateExpiryList': function(source) {
141 if( !this.isUnchained() ) {
142 var expiry = source.value;
143 this.forEachExpirySelector(function(element) {
144 element.value = expiry;
145 });
146 this.forEachExpiryInput(function(element) {
147 element.value = '';
148 });
149 }
150 },
151
152 /**
153 * Update chain status and enable/disable various bits of the UI
154 * when the user changes the "unlock move permissions" checkbox
155 */
156 'onChainClick': function() {
157 if( this.isUnchained() ) {
158 this.enableUnchainedInputs( true );
159 } else {
160 this.setAllSelectors( this.getMaxLevel() );
161 this.enableUnchainedInputs( false );
162 }
163 this.updateCascadeCheckbox();
164 },
165
166 /**
167 * Returns true if the named attribute in all objects in the given array are matching
168 */
169 'matchAttribute' : function( objects, attrName ) {
170 var value = null;
171
172 // Check levels
173 for ( var i = 0; i < objects.length; i++ ) {
174 var element = objects[i];
175 if ( value == null ) {
176 value = element[attrName];
177 } else {
178 if ( value != element[attrName] ) {
179 return false;
180 }
181 }
182 }
183 return true;
184 },
185
186 /**
187 * Are all actions protected at the same level, with the same expiry time?
188 *
189 * @return boolean
190 */
191 'areAllTypesMatching': function() {
192 return this.existingMatch
193 && this.matchAttribute( this.getLevelSelectors(), 'selectedIndex' )
194 && this.matchAttribute( this.getExpirySelectors(), 'selectedIndex' )
195 && this.matchAttribute( this.getExpiryInputs(), 'value' );
196 },
197
198 /**
199 * Is protection chaining off?
200 *
201 * @return bool
202 */
203 'isUnchained': function() {
204 var element = document.getElementById( 'mwProtectUnchained' );
205 return element
206 ? element.checked
207 : true; // No control, so we need to let the user set both levels
208 },
209
210 /**
211 * Find the highest protection level in any selector
212 */
213 'getMaxLevel': function() {
214 var maxIndex = -1;
215 this.forEachLevelSelector(function(element) {
216 if (element.selectedIndex > maxIndex) {
217 maxIndex = element.selectedIndex;
218 }
219 });
220 return maxIndex;
221 },
222
223 /**
224 * Protect all actions at the specified level
225 *
226 * @param index int Protection level
227 */
228 'setAllSelectors': function(index) {
229 this.forEachLevelSelector(function(element) {
230 if (element.selectedIndex != index) {
231 element.selectedIndex = index;
232 }
233 });
234 },
235
236 /**
237 * Apply a callback to each protection selector
238 *
239 * @param func callable Callback function
240 */
241 'forEachLevelSelector': function(func) {
242 var selectors = this.getLevelSelectors();
243 for (var i = 0; i < selectors.length; i++) {
244 func(selectors[i]);
245 }
246 },
247
248 /**
249 * Get a list of all protection selectors on the page
250 *
251 * @return Array
252 */
253 'getLevelSelectors': function() {
254 var all = document.getElementsByTagName("select");
255 var ours = [];
256 for (var i = 0; i < all.length; i++) {
257 var element = all[i];
258 if (element.id.match(/^mwProtect-level-/)) {
259 ours[ours.length] = element;
260 }
261 }
262 return ours;
263 },
264
265 /**
266 * Apply a callback to each expiry input
267 *
268 * @param func callable Callback function
269 */
270 'forEachExpiryInput': function(func) {
271 var inputs = this.getExpiryInputs();
272 for (var i = 0; i < inputs.length; i++) {
273 func(inputs[i]);
274 }
275 },
276
277 /**
278 * Get a list of all expiry inputs on the page
279 *
280 * @return Array
281 */
282 'getExpiryInputs': function() {
283 var all = document.getElementsByTagName("input");
284 var ours = [];
285 for (var i = 0; i < all.length; i++) {
286 var element = all[i];
287 if (element.name.match(/^mwProtect-expiry-/)) {
288 ours[ours.length] = element;
289 }
290 }
291 return ours;
292 },
293
294 /**
295 * Apply a callback to each expiry selector list
296 * @param func callable Callback function
297 */
298 'forEachExpirySelector': function(func) {
299 var inputs = this.getExpirySelectors();
300 for (var i = 0; i < inputs.length; i++) {
301 func(inputs[i]);
302 }
303 },
304
305 /**
306 * Get a list of all expiry selector lists on the page
307 *
308 * @return Array
309 */
310 'getExpirySelectors': function() {
311 var all = document.getElementsByTagName("select");
312 var ours = [];
313 for (var i = 0; i < all.length; i++) {
314 var element = all[i];
315 if (element.id.match(/^mwProtectExpirySelection-/)) {
316 ours[ours.length] = element;
317 }
318 }
319 return ours;
320 },
321
322 /**
323 * Enable/disable protection selectors and expiry inputs
324 *
325 * @param val boolean Enable?
326 */
327 'enableUnchainedInputs': function(val) {
328 var first = true;
329 this.forEachLevelSelector(function(element) {
330 if (first) {
331 first = false;
332 } else {
333 element.disabled = !val;
334 }
335 });
336 first = true;
337 this.forEachExpiryInput(function(element) {
338 if (first) {
339 first = false;
340 } else {
341 element.disabled = !val;
342 }
343 });
344 first = true;
345 this.forEachExpirySelector(function(element) {
346 if (first) {
347 first = false;
348 } else {
349 element.disabled = !val;
350 }
351 });
352 }
353 };