* 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
}
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() );
}
}
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 = '';
'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;
+ }
}
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 ) );
+ } );
+ }
} );
}() );