1 /* eslint-disable no-restricted-properties */
4 reasonCodePointLimit
= mw
.config
.get( 'wgCommentCodePointLimit' ),
5 reasonByteLimit
= mw
.config
.get( 'wgCommentByteLimit' );
7 ProtectionForm
= window
.ProtectionForm
= {
9 * Set up the protection chaining interface (i.e. "unlock move permissions" checkbox)
10 * on the protection form
15 var $cell
= $( '<td>' ),
16 $row
= $( '<tr>' ).append( $cell
);
18 if ( !$( '#mwProtectSet' ).length
) {
22 if ( mw
.config
.get( 'wgCascadeableLevels' ) !== undefined ) {
23 $( 'form#mw-Protect-Form' ).submit( this.toggleUnchainedInputs
.bind( ProtectionForm
, true ) );
25 this.getExpirySelectors().each( function () {
26 $( this ).change( ProtectionForm
.updateExpiryList
.bind( ProtectionForm
, this ) );
28 this.getExpiryInputs().each( function () {
29 $( this ).on( 'keyup change', ProtectionForm
.updateExpiry
.bind( ProtectionForm
, this ) );
31 this.getLevelSelectors().each( function () {
32 $( this ).change( ProtectionForm
.updateLevels
.bind( ProtectionForm
, this ) );
35 $( '#mwProtectSet > tbody > tr:first' ).after( $row
);
37 // If there is only one protection type, there is nothing to chain
38 if ( $( '[id ^= mw-protect-table-]' ).length
> 1 ) {
41 .attr( { id
: 'mwProtectUnchained', type
: 'checkbox' } )
42 .click( this.onChainClick
.bind( this ) )
43 .prop( 'checked', !this.areAllTypesMatching() ),
44 document
.createTextNode( ' ' ),
46 .attr( 'for', 'mwProtectUnchained' )
47 .text( mw
.msg( 'protect-unchain-permissions' ) )
50 this.toggleUnchainedInputs( !this.areAllTypesMatching() );
53 // Arbitrary 75 to leave some space for the autogenerated null edit's summary
54 if ( reasonCodePointLimit
) {
55 $( '#mwProtect-reason' ).codePointLimit( reasonCodePointLimit
- 75 );
56 } else if ( reasonByteLimit
) {
57 $( '#mwProtect-reason' ).byteLimit( reasonByteLimit
- 75 );
60 this.updateCascadeCheckbox();
65 * Sets the disabled attribute on the cascade checkbox depending on the current selected levels
67 updateCascadeCheckbox: function () {
68 this.getLevelSelectors().each( function () {
69 if ( !ProtectionForm
.isCascadeableLevel( $( this ).val() ) ) {
70 $( '#mwProtect-cascade' ).prop( { checked
: false, disabled
: true } );
73 $( '#mwProtect-cascade' ).prop( 'disabled', false );
79 * Checks if a certain protection level is cascadeable.
81 * @param {string} level
84 isCascadeableLevel: function ( level
) {
85 return $.inArray( level
, mw
.config
.get( 'wgCascadeableLevels' ) ) !== -1;
89 * When protection levels are locked together, update the rest
90 * when one action's level changes
92 * @param {Element} source Level selector that changed
94 updateLevels: function ( source
) {
95 if ( !this.isUnchained() ) {
96 this.setAllSelectors( source
.selectedIndex
);
98 this.updateCascadeCheckbox();
102 * When protection levels are locked together, update the
103 * expiries when one changes
105 * @param {Element} source expiry input that changed
108 updateExpiry: function ( source
) {
109 if ( !this.isUnchained() ) {
110 this.getExpiryInputs().each( function () {
111 this.value
= source
.value
;
114 if ( this.isUnchained() ) {
115 $( '#' + source
.id
.replace( /^mwProtect-(\w+)-expires$/, 'mwProtectExpirySelection-$1' ) ).val( 'othertime' );
117 this.getExpirySelectors().each( function () {
118 this.value
= 'othertime';
124 * When protection levels are locked together, update the
125 * expiry lists when one changes and clear the custom inputs
127 * @param {Element} source Expiry selector that changed
129 updateExpiryList: function ( source
) {
130 if ( !this.isUnchained() ) {
131 this.getExpirySelectors().each( function () {
132 this.value
= source
.value
;
134 this.getExpiryInputs().each( function () {
141 * Update chain status and enable/disable various bits of the UI
142 * when the user changes the "unlock move permissions" checkbox
144 onChainClick: function () {
145 this.toggleUnchainedInputs( this.isUnchained() );
146 if ( !this.isUnchained() ) {
147 this.setAllSelectors( this.getMaxLevel() );
149 this.updateCascadeCheckbox();
153 * Returns true if the named attribute in all objects in the given array are matching
155 * @param {Object[]} objects
156 * @param {string} attrName
159 matchAttribute: function ( objects
, attrName
) {
160 return $.map( objects
, function ( object
) {
161 return object
[ attrName
];
162 } ).filter( function ( item
, index
, a
) {
163 return index
=== a
.indexOf( item
);
168 * Are all actions protected at the same level, with the same expiry time?
172 areAllTypesMatching: function () {
173 return this.matchAttribute( this.getLevelSelectors(), 'selectedIndex' ) &&
174 this.matchAttribute( this.getExpirySelectors(), 'selectedIndex' ) &&
175 this.matchAttribute( this.getExpiryInputs(), 'value' );
179 * Is protection chaining off?
183 isUnchained: function () {
184 var element
= document
.getElementById( 'mwProtectUnchained' );
187 true; // No control, so we need to let the user set both levels
191 * Find the highest protection level in any selector
195 getMaxLevel: function () {
196 return Math
.max
.apply( Math
, this.getLevelSelectors().map( function () {
197 return this.selectedIndex
;
202 * Protect all actions at the specified level
204 * @param {number} index Protection level
206 setAllSelectors: function ( index
) {
207 this.getLevelSelectors().each( function () {
208 this.selectedIndex
= index
;
213 * Get a list of all protection selectors on the page
217 getLevelSelectors: function () {
218 return $( 'select[id ^= mwProtect-level-]' );
222 * Get a list of all expiry inputs on the page
226 getExpiryInputs: function () {
227 return $( 'input[id ^= mwProtect-][id $= -expires]' );
231 * Get a list of all expiry selector lists on the page
235 getExpirySelectors: function () {
236 return $( 'select[id ^= mwProtectExpirySelection-]' );
240 * Enable/disable protection selectors and expiry inputs
242 * @param {boolean} val Enable?
244 toggleUnchainedInputs: function ( val
) {
245 var setDisabled = function () { this.disabled
= !val
; };
246 this.getLevelSelectors().slice( 1 ).each( setDisabled
);
247 this.getExpiryInputs().slice( 1 ).each( setDisabled
);
248 this.getExpirySelectors().slice( 1 ).each( setDisabled
);
252 $( ProtectionForm
.init
.bind( ProtectionForm
) );
254 }( mediaWiki
, jQuery
) );