]> scripts.mit.edu Git - autoinstalls/mediawiki.git/blob - skins/common/protect.js
MediaWiki 1.17.0
[autoinstalls/mediawiki.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                 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 level String
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 source Element 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 source Element 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 source Element 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 index int 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 func callable 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 func callable 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 func callable 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 val boolean 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 };