Add OOUI for HTMLFormFieldCloner

The JavaScript for the cloner fields has been updated to function
when using OOUI Cloners.

The buttons are packed quite tight together, but there does not
seem to be any CSS that enforced the spacing that I could find.

Bug: T171666
Change-Id: Iba6eed9d6cee922d56855bbe2e836956bfd90f42
This commit is contained in:
mainframe98 2018-03-22 20:46:54 +01:00
parent 809d9b6845
commit 8b48c99889
2 changed files with 168 additions and 42 deletions

View file

@ -11,7 +11,7 @@
* of fields.
* required - If specified, at least one group of fields must be submitted.
* format - HTMLForm display format to use when displaying the subfields:
* 'table', 'div', or 'raw'.
* 'table', 'div', or 'raw'. This is ignored when using OOUI.
* row-legend - If non-empty, each group of subfields will be enclosed in a
* fieldset. The value is the name of a message key to use as the legend.
* create-button-message - Message to use as the text of the button to
@ -303,22 +303,12 @@ class HTMLFormFieldCloner extends HTMLFormField {
}
if ( !isset( $fields['delete'] ) ) {
$name = "{$this->mName}[$key][delete]";
$label = $this->mParams['delete-button-message'] ?? 'htmlform-cloner-delete';
$field = HTMLForm::loadInputFromParameters( $name, [
'type' => 'submit',
'formnovalidate' => true,
'name' => $name,
'id' => Sanitizer::escapeIdForAttribute( "{$this->mID}--$key--delete" ),
'cssclass' => 'mw-htmlform-cloner-delete-button',
'default' => $this->getMessage( $label )->text(),
], $this->mParent );
$v = $field->getDefault();
$field = $this->getDeleteButtonHtml( $key );
if ( $displayFormat === 'table' ) {
$html .= $field->$getFieldHtmlMethod( $v );
$html .= $field->$getFieldHtmlMethod( $field->getDefault() );
} else {
$html .= $field->getInputHTML( $v );
$html .= $field->getInputHTML( $field->getDefault() );
}
}
@ -354,6 +344,37 @@ class HTMLFormFieldCloner extends HTMLFormField {
return $html;
}
/**
* @param string $key Array key indicating to which field the delete button belongs
* @return HTMLFormField
*/
protected function getDeleteButtonHtml( $key ) : HTMLFormField {
$name = "{$this->mName}[$key][delete]";
$label = $this->mParams['delete-button-message'] ?? 'htmlform-cloner-delete';
$field = HTMLForm::loadInputFromParameters( $name, [
'type' => 'submit',
'formnovalidate' => true,
'name' => $name,
'id' => Sanitizer::escapeIdForAttribute( "{$this->mID}--$key--delete" ),
'cssclass' => 'mw-htmlform-cloner-delete-button',
'default' => $this->getMessage( $label )->text(),
], $this->mParent );
return $field;
}
protected function getCreateButtonHtml() : HTMLFormField {
$name = "{$this->mName}[create]";
$label = $this->mParams['create-button-message'] ?? 'htmlform-cloner-create';
return HTMLForm::loadInputFromParameters( $name, [
'type' => 'submit',
'formnovalidate' => true,
'name' => $name,
'id' => Sanitizer::escapeIdForAttribute( "{$this->mID}--create" ),
'cssclass' => 'mw-htmlform-cloner-create-button',
'default' => $this->getMessage( $label )->text(),
], $this->mParent );
}
public function getInputHTML( $values ) {
$html = '';
@ -374,18 +395,92 @@ class HTMLFormFieldCloner extends HTMLFormField {
'data-unique-id' => $this->uniqueId,
], $html );
$name = "{$this->mName}[create]";
$label = $this->mParams['create-button-message'] ?? 'htmlform-cloner-create';
$field = HTMLForm::loadInputFromParameters( $name, [
'type' => 'submit',
'formnovalidate' => true,
'name' => $name,
'id' => Sanitizer::escapeIdForAttribute( "{$this->mID}--create" ),
'cssclass' => 'mw-htmlform-cloner-create-button',
'default' => $this->getMessage( $label )->text(),
], $this->mParent );
$field = $this->getCreateButtonHtml();
$html .= $field->getInputHTML( $field->getDefault() );
return $html;
}
/**
* Get the input OOUI HTML for the specified key.
*
* @param string $key Array key under which the fields should be named
* @param array $values
* @return string
*/
protected function getInputOOUIForKey( $key, array $values ) {
$html = '';
$hidden = '';
$fields = $this->createFieldsForKey( $key );
foreach ( $fields as $fieldname => $field ) {
$v = array_key_exists( $fieldname, $values )
? $values[$fieldname]
: $field->getDefault();
if ( $field instanceof HTMLHiddenField ) {
// HTMLHiddenField doesn't generate its own HTML
list( $name, $value, $params ) = $field->getHiddenFieldData( $v );
$hidden .= Html::hidden( $name, $value, $params ) . "\n";
} else {
$html .= $field->getOOUI( $v );
}
}
if ( !isset( $fields['delete'] ) ) {
$field = $this->getDeleteButtonHtml( $key );
$fieldHtml = $field->getInputOOUI( $field->getDefault() );
$fieldHtml->setInfusable( true );
$html .= $fieldHtml;
}
$classes = [
'mw-htmlform-cloner-row',
];
$attribs = [
'class' => implode( ' ', $classes ),
];
$html = Html::rawElement( 'div', $attribs, "\n$html\n" );
$html .= $hidden;
if ( !empty( $this->mParams['row-legend'] ) ) {
$legend = $this->msg( $this->mParams['row-legend'] )->text();
$html = Xml::fieldset( $legend, $html );
}
return $html;
}
public function getInputOOUI( $values ) {
$html = '';
foreach ( (array)$values as $key => $value ) {
if ( $key === 'nonjs' ) {
continue;
}
$html .= Html::rawElement( 'li', [ 'class' => 'mw-htmlform-cloner-li' ],
$this->getInputOOUIForKey( $key, $value )
);
}
$template = $this->getInputOOUIForKey( $this->uniqueId, [] );
$html = Html::rawElement( 'ul', [
'id' => "mw-htmlform-cloner-list-{$this->mID}",
'class' => 'mw-htmlform-cloner-ul',
'data-template' => $template,
'data-unique-id' => $this->uniqueId,
], $html );
$field = $this->getCreateButtonHtml();
$fieldHtml = $field->getInputOOUI( $field->getDefault() );
$fieldHtml->setInfusable( true );
$html .= $fieldHtml;
return $html;
}
}

View file

@ -6,31 +6,62 @@
var cloneCounter = 0;
mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
$root.find( '.mw-htmlform-cloner-delete-button' ).filter( ':input' ).click( function ( ev ) {
ev.preventDefault();
$( this ).closest( 'li.mw-htmlform-cloner-li' ).remove();
} );
$root.find( '.mw-htmlform-cloner-create-button' ).filter( ':input' ).click( function ( ev ) {
var $ul, $li, html;
ev.preventDefault();
$ul = $( this ).prev( 'ul.mw-htmlform-cloner-ul' );
/**
* Appends a new row with fields to the cloner.
*
* @ignore
* @param {jQuery} $createButton
*/
function appendToCloner( $createButton ) {
var $li,
$ul = $createButton.prev( 'ul.mw-htmlform-cloner-ul' ),
html = $ul.data( 'template' ).replace(
new RegExp( mw.RegExp.escape( $ul.data( 'uniqueId' ) ), 'g' ),
'clone' + ( ++cloneCounter )
);
$li = $( '<li>' )
.addClass( 'mw-htmlform-cloner-li' )
.html( html )
.appendTo( $ul );
$li = $( '<li>' )
.addClass( 'mw-htmlform-cloner-li' )
.html( html )
.appendTo( $ul );
mw.hook( 'htmlform.enhance' ).fire( $li );
mw.hook( 'htmlform.enhance' ).fire( $li );
}
mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
var $deleteElement = $root.find( '.mw-htmlform-cloner-delete-button' ),
$createElement = $root.find( '.mw-htmlform-cloner-create-button' ),
createButton;
$deleteElement.each( function () {
var $element = $( this ),
deleteButton;
if ( $element.hasClass( 'oo-ui-widget' ) ) {
deleteButton = OO.ui.infuse( $element );
deleteButton.on( 'click', function () {
deleteButton.$element.closest( 'li.mw-htmlform-cloner-li' ).remove();
} );
} else {
$element.filter( ':input' ).click( function ( ev ) {
ev.preventDefault();
$( this ).closest( 'li.mw-htmlform-cloner-li' ).remove();
} );
}
} );
if ( $createElement.hasClass( 'oo-ui-widget' ) ) {
createButton = OO.ui.infuse( $createElement );
createButton.on( 'click', function () {
appendToCloner( createButton.$element );
} );
} else {
$createElement.filter( ':input' ).click( function ( ev ) {
ev.preventDefault();
appendToCloner( $( this ) );
} );
}
} );
}() );