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;