2 window
.ProtectionForm
= {
3 'existingMatch': false,
6 * Set up the protection chaining interface (i.e. "unlock move permissions" checkbox)
7 * on the protection form
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
15 'init': function( opts
) {
16 if( !( document
.createTextNode
&& document
.getElementById
&& document
.getElementsByTagName
) )
19 var box
= document
.getElementById( opts
.tableId
);
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
);
49 $( '#mwProtect-reason' ).byteLimit( 180 );
51 this.updateCascadeCheckbox();
57 * Sets the disabled attribute on the cascade checkbox depending on the current selected levels
59 'updateCascadeCheckbox': function() {
60 // For non-existent titles, there is no cascade option
61 if( !document
.getElementById( 'mwProtect-cascade' ) ) {
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;
76 document
.getElementById( 'mwProtect-cascade' ).disabled
= false;
80 * Is this protection level cascadeable?
86 'isCascadeableLevel': function( level
) {
87 for (var k
= 0; k
< wgCascadeableLevels
.length
; k
++) {
88 if ( wgCascadeableLevels
[k
] == level
) {
96 * When protection levels are locked together, update the rest
97 * when one action's level changes
99 * @param source Element Level selector that changed
101 'updateLevels': function(source
) {
102 if( !this.isUnchained() )
103 this.setAllSelectors( source
.selectedIndex
);
104 this.updateCascadeCheckbox();
108 * When protection levels are locked together, update the
109 * expiries when one changes
111 * @param source Element expiry input that changed
114 'updateExpiry': function(source
) {
115 if( !this.isUnchained() ) {
116 var expiry
= source
.value
;
117 this.forEachExpiryInput(function(element
) {
118 element
.value
= expiry
;
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';
127 this.forEachExpirySelector(function(element
) {
128 element
.value
= 'othertime';
135 * When protection levels are locked together, update the
136 * expiry lists when one changes and clear the custom inputs
138 * @param source Element expiry selector that changed
140 'updateExpiryList': function(source
) {
141 if( !this.isUnchained() ) {
142 var expiry
= source
.value
;
143 this.forEachExpirySelector(function(element
) {
144 element
.value
= expiry
;
146 this.forEachExpiryInput(function(element
) {
153 * Update chain status and enable/disable various bits of the UI
154 * when the user changes the "unlock move permissions" checkbox
156 'onChainClick': function() {
157 if( this.isUnchained() ) {
158 this.enableUnchainedInputs( true );
160 this.setAllSelectors( this.getMaxLevel() );
161 this.enableUnchainedInputs( false );
163 this.updateCascadeCheckbox();
167 * Returns true if the named attribute in all objects in the given array are matching
169 'matchAttribute' : function( objects
, attrName
) {
173 for ( var i
= 0; i
< objects
.length
; i
++ ) {
174 var element
= objects
[i
];
175 if ( value
== null ) {
176 value
= element
[attrName
];
178 if ( value
!= element
[attrName
] ) {
187 * Are all actions protected at the same level, with the same expiry time?
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' );
199 * Is protection chaining off?
203 'isUnchained': function() {
204 var element
= document
.getElementById( 'mwProtectUnchained' );
207 : true; // No control, so we need to let the user set both levels
211 * Find the highest protection level in any selector
213 'getMaxLevel': function() {
215 this.forEachLevelSelector(function(element
) {
216 if (element
.selectedIndex
> maxIndex
) {
217 maxIndex
= element
.selectedIndex
;
224 * Protect all actions at the specified level
226 * @param index int Protection level
228 'setAllSelectors': function(index
) {
229 this.forEachLevelSelector(function(element
) {
230 if (element
.selectedIndex
!= index
) {
231 element
.selectedIndex
= index
;
237 * Apply a callback to each protection selector
239 * @param func callable Callback function
241 'forEachLevelSelector': function(func
) {
242 var selectors
= this.getLevelSelectors();
243 for (var i
= 0; i
< selectors
.length
; i
++) {
249 * Get a list of all protection selectors on the page
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
;
266 * Apply a callback to each expiry input
268 * @param func callable Callback function
270 'forEachExpiryInput': function(func
) {
271 var inputs
= this.getExpiryInputs();
272 for (var i
= 0; i
< inputs
.length
; i
++) {
278 * Get a list of all expiry inputs on the page
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
;
295 * Apply a callback to each expiry selector list
296 * @param func callable Callback function
298 'forEachExpirySelector': function(func
) {
299 var inputs
= this.getExpirySelectors();
300 for (var i
= 0; i
< inputs
.length
; i
++) {
306 * Get a list of all expiry selector lists on the page
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
;
323 * Enable/disable protection selectors and expiry inputs
325 * @param val boolean Enable?
327 'enableUnchainedInputs': function(val
) {
329 this.forEachLevelSelector(function(element
) {
333 element
.disabled
= !val
;
337 this.forEachExpiryInput(function(element
) {
341 element
.disabled
= !val
;
345 this.forEachExpirySelector(function(element
) {
349 element
.disabled
= !val
;