Follow-up r89835: Accidently comitted from a deeper dir than the diff. Comitting...
[mediawiki.git] / skins / common / protect.js
blobb77c2e067e8ef1e932bbe1e4921fa473db20b0f1
2 window.ProtectionForm = {
3         'existingMatch': false,
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;
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 );
27                 this.existingMatch = opts.existingMatch;
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(); } );
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 );
45                         check.checked = !this.areAllTypesMatching();
46                         this.enableUnchainedInputs( check.checked );
47                 }
48                 
49                 $( '#mwProtect-reason' ).byteLimit( 180 );
51                 this.updateCascadeCheckbox();
53                 return true;
54         },
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         },
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         },
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         },
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          */
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         },
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         },
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         },
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;
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         },
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         },
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         },
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         },
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         },
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         },
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 = new Array();
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         },
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         },
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 = new Array();
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         },
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         },
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 = new Array();
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         },
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         }