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