Alex Monk has uploaded a new change for review.
https://gerrit.wikimedia.org/r/159518
Change subject: Clean up mediawiki.legacy.protect a bit.
......................................................................
Clean up mediawiki.legacy.protect a bit.
Also kills some inline JS stuff in ProtectionForm
Bug: 33871
Change-Id: Ie43c80bf5ebd6107458d5284cc68b7128f29359a
---
M includes/ProtectionForm.php
M resources/Resources.php
M skins/common/protect.js
3 files changed, 93 insertions(+), 258 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core
refs/changes/18/159518/1
diff --git a/includes/ProtectionForm.php b/includes/ProtectionForm.php
index 853e2cc..5bf1fe1 100644
--- a/includes/ProtectionForm.php
+++ b/includes/ProtectionForm.php
@@ -346,7 +346,7 @@
$wgOut->addJsConfigVars( 'wgCascadeableLevels',
$wgCascadingRestrictionLevels );
$out .= Xml::openElement( 'form', array( 'method' =>
'post',
'action' => $this->mTitle->getLocalURL(
'action=protect' ),
- 'id' => 'mw-Protect-Form', 'onsubmit' =>
'ProtectionForm.enableUnchainedInputs(true)' ) );
+ 'id' => 'mw-Protect-Form' ) );
}
$out .= Xml::openElement( 'fieldset' ) .
@@ -420,16 +420,13 @@
array(
'id' =>
"mwProtectExpirySelection-$action",
'name'
=> "wpProtectExpirySelection-$action",
-
'onchange' => "ProtectionForm.updateExpiryList(this)",
'tabindex' => '2' ) + $this->disabledAttrib,
$expiryFormOptions ) .
"</td>
</tr></table>";
}
# Add custom expiry field
- $attribs = array( 'id' => "mwProtect-$action-expires",
- 'onkeyup' =>
'ProtectionForm.updateExpiry(this)',
- 'onchange' =>
'ProtectionForm.updateExpiry(this)' ) + $this->disabledAttrib;
+ $attribs = array( 'id' => "mwProtect-$action-expires" )
+ $this->disabledAttrib;
$out .= "<table><tr>
<td class='mw-label'>" .
$mProtectother .
@@ -550,7 +547,6 @@
$wgUser->getEditToken( array( 'protect',
$this->mTitle->getPrefixedDBkey() ) )
);
$out .= Xml::closeElement( 'form' );
- $wgOut->addScript( $this->buildCleanupScript() );
}
return $out;
@@ -577,8 +573,7 @@
'id' => $id,
'name' => $id,
'size' => count( $levels ),
- 'onchange' => 'ProtectionForm.updateLevels(this)',
- ) + $this->disabledAttrib;
+ ) + $this->disabledAttrib;
$out = Xml::openElement( 'select', $attribs );
foreach ( $levels as $key ) {
@@ -605,19 +600,6 @@
}
return wfMessage( 'protect-fallback', $permission
)->text();
}
- }
-
- function buildCleanupScript() {
- $options = array(
- 'tableId' => 'mwProtectSet',
- 'labelText' => wfMessage( 'protect-unchain-permissions'
)->plain(),
- 'numTypes' => count( $this->mApplicableTypes ),
- 'existingMatch' => count( array_unique(
$this->mExistingExpiry ) ) === 1,
- );
-
- $script = Xml::encodeJsCall( 'ProtectionForm.init', array(
$options ) );
-
- return Html::inlineScript(
ResourceLoader::makeLoaderConditionalScript( $script ) );
}
/**
diff --git a/resources/Resources.php b/resources/Resources.php
index 99e1e4f..ed11627 100644
--- a/resources/Resources.php
+++ b/resources/Resources.php
@@ -1422,7 +1422,7 @@
'dependencies' => array(
'jquery.byteLimit',
),
- 'position' => 'top',
+ 'messages' => array( 'protect-unchain-permissions' )
),
'mediawiki.legacy.shared' => array(
// Used in the web installer. Test it after modifying this
definition!
diff --git a/skins/common/protect.js b/skins/common/protect.js
index dc142ca..e8a229f 100644
--- a/skins/common/protect.js
+++ b/skins/common/protect.js
@@ -1,116 +1,82 @@
( function ( mw, $ ) {
var ProtectionForm = window.ProtectionForm = {
- existingMatch: false,
-
/**
* Set up the protection chaining interface (i.e. "unlock move
permissions" checkbox)
* on the protection form
- *
- * @param opts Object : parameters with members:
- * tableId Identifier of the table containing UI bits
- * labelText Text to use for the checkbox label
- * numTypes The number of protection types
- * existingMatch True if all the existing expiry times match
*/
- init: function ( opts ) {
- var box, boxbody, row, cell, check, label;
+ init: function () {
+ var $cell = $( '<td>' ), $row = $( '<tr>' ).append( $cell );
- if ( !( document.createTextNode && document.getElementById &&
document.getElementsByTagName ) ) {
+ if ( !$( '#mwProtectSet' ).length ) {
return false;
}
- box = document.getElementById( opts.tableId );
- if ( !box ) {
- return false;
+ if ( mw.config.get( 'wgCascadeableLevels' ) !== undefined ) {
+ $( 'form#mw-Protect-Form' ).submit(
this.toggleUnchainedInputs.bind( ProtectionForm, true ) );
}
+ this.getExpirySelectors().each( function () {
+ $( this ).change( ProtectionForm.updateExpiryList.bind(
ProtectionForm, this ) );
+ } );
+ this.getExpiryInputs().each( function () {
+ $( this ).on( 'keyup change',
ProtectionForm.updateExpiry.bind( ProtectionForm, this ) );
+ } );
+ this.getLevelSelectors().each( function () {
+ $( this ).change( ProtectionForm.updateLevels.bind(
ProtectionForm, this ) );
+ } );
- boxbody = box.getElementsByTagName( 'tbody' )[0];
- row = document.createElement( 'tr' );
- boxbody.insertBefore( row, boxbody.firstChild.nextSibling );
+ $( '#mwProtectSet > tbody > tr:first' ).after( $row );
- this.existingMatch = opts.existingMatch;
-
- cell = document.createElement( 'td' );
- row.appendChild( cell );
// If there is only one protection type, there is nothing to
chain
- if ( opts.numTypes > 1 ) {
- check = document.createElement( 'input' );
- check.id = 'mwProtectUnchained';
- check.type = 'checkbox';
- $( check ).click( function () {
- ProtectionForm.onChainClick();
- } );
+ if ( $( '[id ^= mw-protect-table-]' ).length > 1 ) {
+ $cell.append(
+ $( '<input>' )
+ .attr( { id: 'mwProtectUnchained',
type: 'checkbox' } )
+ .click( this.onChainClick.bind( this ) )
+ .prop( 'checked',
!this.areAllTypesMatching() ),
+ document.createTextNode( ' ' ),
+ $( '<label>' )
+ .attr( 'for', 'mwProtectUnchained' )
+ .text( mw.msg(
'protect-unchain-permissions' ) )
+ );
- label = document.createElement( 'label' );
- label.htmlFor = 'mwProtectUnchained';
- label.appendChild( document.createTextNode(
opts.labelText ) );
-
- cell.appendChild( check );
- cell.appendChild( document.createTextNode( ' ' ) );
- cell.appendChild( label );
-
- check.checked = !this.areAllTypesMatching();
- this.enableUnchainedInputs( check.checked );
+ this.toggleUnchainedInputs( !this.areAllTypesMatching()
);
}
$( '#mwProtect-reason' ).byteLimit( 180 );
this.updateCascadeCheckbox();
-
- return true;
},
/**
* Sets the disabled attribute on the cascade checkbox depending on the
current selected levels
*/
updateCascadeCheckbox: function () {
- var i, lists, items, selected;
-
- // For non-existent titles, there is no cascade option
- if ( !document.getElementById( 'mwProtect-cascade' ) ) {
- return;
- }
- lists = this.getLevelSelectors();
- for ( i = 0; i < lists.length; i++ ) {
- if ( lists[i].selectedIndex > -1 ) {
- items = lists[i].getElementsByTagName( 'option'
);
- selected = items[ lists[i].selectedIndex
].value;
- if ( !this.isCascadeableLevel( selected ) ) {
- document.getElementById(
'mwProtect-cascade' ).checked = false;
- document.getElementById(
'mwProtect-cascade' ).disabled = true;
- return;
- }
+ this.getLevelSelectors().each( function () {
+ if ( !ProtectionForm.isCascadeableLevel( $( this
).val() ) ) {
+ $( '#mwProtect-cascade' ).prop( { checked:
false, disabled: true } );
+ return false;
+ } else {
+ $( '#mwProtect-cascade' ).prop( 'disabled',
false );
}
- }
- document.getElementById( 'mwProtect-cascade' ).disabled = false;
+ } );
},
/**
* Checks if a cerain protection level is cascadeable.
- * @param level {String}
- * @return {Boolean}
+ *
+ * @param {string} level
+ * @return {boolean}
*/
- isCascadeableLevel: function ( level ) {
- var cascadeLevels, len, i;
-
- cascadeLevels = mw.config.get( 'wgCascadeableLevels' );
- // cascadeLevels isn't defined on all pages
- if ( cascadeLevels ) {
- for ( i = 0, len = cascadeLevels.length; i < len; i +=
1 ) {
- if ( cascadeLevels[i] === level ) {
- return true;
- }
- }
- }
- return false;
+ isCascadeableLevel: function ( level ) {
+ return $.inArray( mw.config.get( 'wgCascadeableLevels' ), level
) !== -1;
},
/**
* When protection levels are locked together, update the rest
* when one action's level changes
*
- * @param source Element Level selector that changed
+ * @param {Element} source Level selector that changed
*/
updateLevels: function ( source ) {
if ( !this.isUnchained() ) {
@@ -123,28 +89,21 @@
* When protection levels are locked together, update the
* expiries when one changes
*
- * @param source Element expiry input that changed
+ * @param {Element} source expiry input that changed
*/
updateExpiry: function ( source ) {
- var expiry, listId, list;
-
if ( !this.isUnchained() ) {
- expiry = source.value;
- this.forEachExpiryInput( function ( element ) {
- element.value = expiry;
+ this.getExpiryInputs().each( function () {
+ this.value = source.value;
} );
}
- listId = source.id.replace( /^mwProtect-(\w+)-expires$/,
'mwProtectExpirySelection-$1' );
- list = document.getElementById( listId );
- if ( list && list.value !== 'othertime' ) {
- if ( this.isUnchained() ) {
- list.value = 'othertime';
- } else {
- this.forEachExpirySelector( function ( element
) {
- element.value = 'othertime';
- } );
- }
+ if ( this.isUnchained() ) {
+ $( '#' + source.id.replace(
/^mwProtect-(\w+)-expires$/, 'mwProtectExpirySelection-$1' ) ).val( 'othertime'
);
+ } else {
+ this.getExpirySelectors().each( function () {
+ this.value = 'othertime';
+ } );
}
},
@@ -152,17 +111,15 @@
* When protection levels are locked together, update the
* expiry lists when one changes and clear the custom inputs
*
- * @param source Element expiry selector that changed
+ * @param {Element} source Expiry selector that changed
*/
updateExpiryList: function ( source ) {
- var expiry;
if ( !this.isUnchained() ) {
- expiry = source.value;
- this.forEachExpirySelector( function ( element ) {
- element.value = expiry;
+ this.getExpirySelectors().each( function () {
+ this.value = source.value;
} );
- this.forEachExpiryInput( function ( element ) {
- element.value = '';
+ this.getExpiryInputs().each( function () {
+ this.value = '';
} );
}
},
@@ -172,44 +129,35 @@
* when the user changes the "unlock move permissions" checkbox
*/
onChainClick: function () {
- if ( this.isUnchained() ) {
- this.enableUnchainedInputs( true );
- } else {
+ this.toggleUnchainedInputs( this.isUnchained() );
+ if ( !this.isUnchained() ) {
this.setAllSelectors( this.getMaxLevel() );
- this.enableUnchainedInputs( false );
}
this.updateCascadeCheckbox();
},
/**
* Returns true if the named attribute in all objects in the given
array are matching
+ *
+ * @param {Object[]} objects
+ * @param {string} attrName
+ * @return {boolean}
*/
matchAttribute: function ( objects, attrName ) {
- var i, element, value;
-
- // Check levels
- value = null;
- for ( i = 0; i < objects.length; i++ ) {
- element = objects[i];
- if ( value === null ) {
- value = element[attrName];
- } else {
- if ( value !== element[attrName] ) {
- return false;
- }
- }
- }
- return true;
+ return $.map( objects, function ( object ) {
+ return object[attrName];
+ } ).filter( function ( item, index, a ) {
+ return index === a.indexOf( item );
+ } ).length === 1;
},
/**
* Are all actions protected at the same level, with the same expiry
time?
*
- * @return boolean
+ * @return {boolean}
*/
areAllTypesMatching: function () {
- return this.existingMatch
- && this.matchAttribute( this.getLevelSelectors(),
'selectedIndex' )
+ return this.matchAttribute( this.getLevelSelectors(),
'selectedIndex' )
&& this.matchAttribute( this.getExpirySelectors(),
'selectedIndex' )
&& this.matchAttribute( this.getExpiryInputs(), 'value'
);
},
@@ -217,7 +165,7 @@
/**
* Is protection chaining off?
*
- * @return bool
+ * @return {boolean}
*/
isUnchained: function () {
var element = document.getElementById( 'mwProtectUnchained' );
@@ -228,160 +176,65 @@
/**
* Find the highest protection level in any selector
+ * @return {number}
*/
getMaxLevel: function () {
- var maxIndex = -1;
- this.forEachLevelSelector( function ( element ) {
- if ( element.selectedIndex > maxIndex ) {
- maxIndex = element.selectedIndex;
- }
- } );
- return maxIndex;
+ return Math.max.apply( Math, this.getLevelSelectors().map(
function () {
+ return this.selectedIndex;
+ } ) );
},
/**
* Protect all actions at the specified level
*
- * @param index int Protection level
+ * @param {number} index Protection level
*/
setAllSelectors: function ( index ) {
- this.forEachLevelSelector( function ( element ) {
- if ( element.selectedIndex !== index ) {
- element.selectedIndex = index;
- }
+ this.getLevelSelectors().each( function () {
+ this.selectedIndex = index;
} );
- },
-
- /**
- * Apply a callback to each protection selector
- *
- * @param func callable Callback function
- */
- forEachLevelSelector: function ( func ) {
- var i, selectors;
-
- selectors = this.getLevelSelectors();
- for ( i = 0; i < selectors.length; i++ ) {
- func( selectors[i] );
- }
},
/**
* Get a list of all protection selectors on the page
*
- * @return Array
+ * @return {jQuery}
*/
getLevelSelectors: function () {
- var i, ours, all, element;
-
- all = document.getElementsByTagName( 'select' );
- ours = [];
- for ( i = 0; i < all.length; i++ ) {
- element = all[i];
- if ( element.id.match( /^mwProtect-level-/ ) ) {
- ours[ours.length] = element;
- }
- }
- return ours;
- },
-
- /**
- * Apply a callback to each expiry input
- *
- * @param func callable Callback function
- */
- forEachExpiryInput: function ( func ) {
- var i, inputs;
-
- inputs = this.getExpiryInputs();
- for ( i = 0; i < inputs.length; i++ ) {
- func( inputs[i] );
- }
+ return $( 'select[id ^= mwProtect-level-]' );
},
/**
* Get a list of all expiry inputs on the page
*
- * @return Array
+ * @return {jQuery}
*/
getExpiryInputs: function () {
- var i, all, element, ours;
-
- all = document.getElementsByTagName( 'input' );
- ours = [];
- for ( i = 0; i < all.length; i++ ) {
- element = all[i];
- if ( element.name.match( /^mwProtect-expiry-/ ) ) {
- ours[ours.length] = element;
- }
- }
- return ours;
- },
-
- /**
- * Apply a callback to each expiry selector list
- * @param func callable Callback function
- */
- forEachExpirySelector: function ( func ) {
- var i, inputs;
-
- inputs = this.getExpirySelectors();
- for ( i = 0; i < inputs.length; i++ ) {
- func( inputs[i] );
- }
+ return $( 'input[id ^= mwProtect-][id $= -expires]' );
},
/**
* Get a list of all expiry selector lists on the page
*
- * @return Array
+ * @return {jQuery}
*/
getExpirySelectors: function () {
- var i, all, ours, element;
-
- all = document.getElementsByTagName( 'select' );
- ours = [];
- for ( i = 0; i < all.length; i++ ) {
- element = all[i];
- if ( element.id.match( /^mwProtectExpirySelection-/ ) )
{
- ours[ours.length] = element;
- }
- }
- return ours;
+ return $( 'select[id ^= mwProtectExpirySelection-]' );
},
/**
* Enable/disable protection selectors and expiry inputs
*
- * @param val boolean Enable?
+ * @param {boolean} val Enable?
*/
- enableUnchainedInputs: function ( val ) {
- var first = true;
-
- this.forEachLevelSelector( function ( element ) {
- if ( first ) {
- first = false;
- } else {
- element.disabled = !val;
- }
- } );
- first = true;
- this.forEachExpiryInput( function ( element ) {
- if ( first ) {
- first = false;
- } else {
- element.disabled = !val;
- }
- } );
- first = true;
- this.forEachExpirySelector( function ( element ) {
- if ( first ) {
- first = false;
- } else {
- element.disabled = !val;
- }
- } );
+ toggleUnchainedInputs: function ( val ) {
+ var setDisabled = function () { this.disabled = !val; };
+ this.getLevelSelectors().slice( 1 ).each( setDisabled );
+ this.getExpiryInputs().slice( 1 ).each( setDisabled );
+ this.getExpirySelectors().slice( 1 ).each( setDisabled );
}
};
+$( ProtectionForm.init.bind( ProtectionForm ) );
+
}( mediaWiki, jQuery ) );
--
To view, visit https://gerrit.wikimedia.org/r/159518
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie43c80bf5ebd6107458d5284cc68b7128f29359a
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Alex Monk <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits