'table',
'div',
'raw',
+ 'vform',
);
/**
}
$field = self::loadInputFromParameters( $fieldname, $info );
+ // FIXME During field's construct, the parent form isn't available!
+ // could add a 'parent' name-value to $info, could add a third parameter.
$field->mParent = $this;
+ // vform gets too much space if empty labels generate HTML.
+ if ( $this->isVForm() ) {
+ $field->setShowEmptyLabel( false );
+ }
+
$setSection =& $loadedDescriptor;
if ( $section ) {
$sectionParts = explode( '/', $section );
return $this->displayFormat;
}
+ /**
+ * Test if displayFormat is 'vform'
+ * @since 1.22
+ * @return Bool
+ */
+ public function isVForm() {
+ return $this->displayFormat === 'vform';
+ }
+
/**
* Add the HTMLForm-specific JavaScript, if it hasn't been
* done already.
# For good measure (it is the default)
$this->getOutput()->preventClickjacking();
$this->getOutput()->addModules( 'mediawiki.htmlform' );
+ if ( $this->isVForm() ) {
+ $this->getOutput()->addModuleStyles( 'mediawiki.ui' );
+ // TODO should vertical form set setWrapperLegend( false )
+ // to hide ugly fieldsets?
+ }
$html = ''
. $this->getErrors( $submitResult )
$attribs = array(
'action' => $this->getAction(),
'method' => $this->getMethod(),
- 'class' => 'visualClear',
+ 'class' => array( 'visualClear' ),
'enctype' => $encType,
);
if ( !empty( $this->mId ) ) {
$attribs['id'] = $this->mId;
}
+ if ( $this->isVForm() ) {
+ array_push( $attribs['class'], 'mw-ui-vform', 'mw-ui-container' );
+ }
return Html::rawElement( 'form', $attribs, $html );
}
$attribs += Linker::tooltipAndAccesskeyAttribs( $this->mSubmitTooltip );
}
- $attribs['class'] = 'mw-htmlform-submit';
+ $attribs['class'] = array( 'mw-htmlform-submit' );
+
+ if ( $this->isVForm() ) {
+ // mw-ui-block is necessary because the buttons aren't necessarily in an
+ // immediate child div of the vform.
+ array_push( $attribs['class'], 'mw-ui-button', 'mw-ui-big', 'mw-ui-primary', 'mw-ui-block' );
+ }
$html .= Xml::submitButton( $this->getSubmitText(), $attribs ) . "\n";
+
+ // Buttons are top-level form elements in table and div layouts,
+ // but vform wants all elements inside divs to get spaced-out block
+ // styling.
+ if ( $this->isVForm() ) {
+ $html = Html::rawElement( 'div', null, "\n$html\n" );
+ }
}
if ( $this->mShowReset ) {
/**
* Prompt the whole form to be wrapped in a "<fieldset>", with
* this text as its "<legend>" element.
- * @param string $legend HTML to go inside the "<legend>" element.
+ * @param string|false $legend HTML to go inside the "<legend>" element, or
+ * false for no <legend>
* Will be escaped
* @return HTMLForm $this for chaining calls (since 1.20)
*/
/**
* @todo Document
- * @param $fields array[]|HTMLFormField[] array of fields (either arrays or objects)
+ * @param array[]|HTMLFormField[] $fields array of fields (either arrays or objects)
* @param string $sectionName ID attribute of the "<table>" tag for this section, ignored if empty
* @param string $fieldsetIDPrefix ID prefix for the "<fieldset>" tag of each subsection, ignored if empty
* @param boolean &$hasUserVisibleFields Whether the section had user-visible fields
$subsectionHtml = '';
$hasLabel = false;
- $getFieldHtmlMethod = ( $displayFormat == 'table' ) ? 'getTableRow' : 'get' . ucfirst( $displayFormat );
+ switch( $displayFormat ) {
+ case 'table':
+ $getFieldHtmlMethod = 'getTableRow';
+ break;
+ case 'vform':
+ // Close enough to a div.
+ $getFieldHtmlMethod = 'getDiv';
+ break;
+ default:
+ $getFieldHtmlMethod = 'get' . ucfirst( $displayFormat );
+ }
foreach ( $fields as $key => $value ) {
if ( $value instanceof HTMLFormField ) {
if ( $displayFormat === 'table' ) {
$html = Html::rawElement( 'table', $attribs,
Html::rawElement( 'tbody', array(), "\n$html\n" ) ) . "\n";
- } elseif ( $displayFormat === 'div' ) {
+ } elseif ( $displayFormat === 'div' || $displayFormat === 'vform' ) {
$html = Html::rawElement( 'div', $attribs, "\n$html\n" );
}
}
return true;
}
+ /**
+ * Tell the field whether to generate a separate label element if its label
+ * is blank.
+ *
+ * @since 1.22
+ * @param bool $show Set to false to not generate a label.
+ * @return void
+ */
+ public function setShowEmptyLabel( $show ) {
+ $this->mShowEmptyLabels = $show;
+ }
+
/**
* Get the value that this input has been set to from a posted form,
* or the input's default value if it has not been set.
array( 'class' => $outerDivClass ) + $cellAttributes,
$inputHtml . "\n$errors"
);
+ $divCssClasses = array( "mw-htmlform-field-$fieldType", $this->mClass, $errorClass );
+ if ( $this->mParent->isVForm() ) {
+ $divCssClasses[] = 'mw-ui-vform-div';
+ }
$html = Html::rawElement( 'div',
- array( 'class' => "mw-htmlform-field-$fieldType {$this->mClass} $errorClass" ),
+ array( 'class' => $divCssClasses ),
$label . $field );
$html .= $helptext;
return $html;
$attr['class'] = $this->mClass;
}
- return Xml::check( $this->mName, $value, $attr ) . ' ' .
- Html::rawElement( 'label', array( 'for' => $this->mID ), $this->mLabel );
+ if ( $this->mParent->isVForm() ) {
+ // Nest checkbox inside label.
+ return Html::rawElement(
+ 'label',
+ array(
+ 'class' => 'mw-ui-checkbox-label'
+ ),
+ Xml::check(
+ $this->mName,
+ $value,
+ $attr
+ ) .
+ // Html:rawElement doesn't escape contents.
+ htmlspecialchars( $this->mLabel )
+ );
+ } else {
+ return Xml::check( $this->mName, $value, $attr ) . ' ' .
+ Html::rawElement( 'label', array( 'for' => $this->mID ), $this->mLabel );
+ }
}
/**
return ' ';
}
+ /**
+ * checkboxes don't need a label.
+ */
+ protected function needsLabel() {
+ return false;
+ }
+
/**
* @param $request WebRequest
* @return String
$form = new HTMLForm( $this->fields, $this->getContext(), $this->getMessagePrefix() );
$form->setSubmitCallback( array( $this, 'onSubmit' ) );
- $form->setWrapperLegendMsg( $this->getMessagePrefix() . '-legend' );
+ // If the form is a compact vertical form, then don't output this ugly
+ // fieldset surrounding it.
+ // XXX Special pages can setDisplayFormat to 'vform' in alterForm(), but that
+ // is called after this.
+ if ( !$form->isVForm() ) {
+ $form->setWrapperLegendMsg( $this->getMessagePrefix() . '-legend' );
+ }
$headerMsg = $this->msg( $this->getMessagePrefix() . '-text' );
if ( !$headerMsg->isDisabled() ) {
public function alterForm( HTMLForm $form ) {
global $wgPasswordResetRoutes;
+ $form->setDisplayFormat( 'vform' );
+ // Turn the old-school line around the form off.
+ // XXX This wouldn't be necessary here if we could set the format of
+ // the HTMLForm to 'vform' at its creation, but there's no way to do so
+ // from a FormSpecialPage class.
+ $form->setWrapperLegend( false );
+
$i = 0;
if ( isset( $wgPasswordResetRoutes['username'] ) && $wgPasswordResetRoutes['username'] ) {
$i++;
+@charset "UTF-8";
/**
* Provide Agora appearance for mw-ui-* classes when using a skin other than
* Vector.
box-sizing: border-box;
width: 290px;
}
-/* line 19, sourcefiles/scss/components/default/_forms.scss */
+/* line 20, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div {
display: block;
margin: 0 0 15px 0;
padding: 0;
width: 100%;
}
-/* line 27, sourcefiles/scss/components/default/_forms.scss */
+/* line 28, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div input,
.mw-ui-vform > div .mw-ui-button {
display: block;
margin: 0;
width: 100%;
}
-/* line 36, sourcefiles/scss/components/default/_forms.scss */
+/* line 37, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div input:not([type=button]):not([type=submit]):not([type=file]) {
border-style: solid;
border-width: 1px;
.mw-ui-vform > div input:not([type=button]):not([type=submit]):not([type=file]):focus:not([type=checkbox]):not([type=radio]) {
outline: 0;
}
-/* line 40, sourcefiles/scss/components/default/_forms.scss */
+/* line 41, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div label {
display: block;
-webkit-box-sizing: border-box;
.mw-ui-vform > div label * {
font-weight: normal;
}
-/* line 51, sourcefiles/scss/components/default/_forms.scss */
+/* line 52, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div input[type="checkbox"],
.mw-ui-vform > div input[type="radio"] {
display: inline;
box-sizing: content-box;
width: auto;
}
+/* line 63, sourcefiles/scss/components/default/_forms.scss */
+.mw-ui-vform .error {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ font-size: 0.9em;
+ margin: 0 0 1em 0;
+ padding: 0.5em;
+ color: #cc0000;
+ border: 1px solid #fac5c5;
+ background-color: #fae3e3;
+ text-shadow: 0 1px #fae3e3;
+ word-wrap: break-word;
+}
+
+/* line 86, sourcefiles/scss/components/default/_forms.scss */
+.mw-ui-vform-div {
+ display: block;
+ margin: 0 0 15px 0;
+ padding: 0;
+ width: 100%;
+}
-/* line 67, sourcefiles/scss/components/default/_forms.scss */
+/* line 96, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-input {
border-style: solid;
border-width: 1px;
outline: 0;
}
-/* line 74, sourcefiles/scss/components/default/_forms.scss */
+/* line 103, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-label {
font-size: 0.9em;
color: #4a4a4a;
font-weight: normal;
}
-/* line 83, sourcefiles/scss/components/default/_forms.scss */
+/* line 112, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-checkbox-label, .mw-ui-radio-label {
margin-bottom: 0.5em;
cursor: pointer;
+@charset "UTF-8";
/**
* Provide Agora appearance for mw-ui-* classes when using the Vector skin.
* Compass builds these Agora styles from source Sass files in
box-sizing: border-box;
width: 290px;
}
-/* line 19, sourcefiles/scss/components/default/_forms.scss */
+/* line 20, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div {
display: block;
margin: 0 0 15px 0;
padding: 0;
width: 100%;
}
-/* line 27, sourcefiles/scss/components/default/_forms.scss */
+/* line 28, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div input,
.mw-ui-vform > div .mw-ui-button {
display: block;
margin: 0;
width: 100%;
}
-/* line 36, sourcefiles/scss/components/default/_forms.scss */
+/* line 37, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div input:not([type=button]):not([type=submit]):not([type=file]) {
border-style: solid;
border-width: 1px;
.mw-ui-vform > div input:not([type=button]):not([type=submit]):not([type=file]):focus:not([type=checkbox]):not([type=radio]) {
outline: 0;
}
-/* line 40, sourcefiles/scss/components/default/_forms.scss */
+/* line 41, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div label {
display: block;
-webkit-box-sizing: border-box;
.mw-ui-vform > div label * {
font-weight: normal;
}
-/* line 51, sourcefiles/scss/components/default/_forms.scss */
+/* line 52, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-vform > div input[type="checkbox"],
.mw-ui-vform > div input[type="radio"] {
display: inline;
box-sizing: content-box;
width: auto;
}
+/* line 63, sourcefiles/scss/components/default/_forms.scss */
+.mw-ui-vform .error {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ font-size: 0.9em;
+ margin: 0 0 1em 0;
+ padding: 0.5em;
+ color: #cc0000;
+ border: 1px solid #fac5c5;
+ background-color: #fae3e3;
+ text-shadow: 0 1px #fae3e3;
+ word-wrap: break-word;
+}
+
+/* line 86, sourcefiles/scss/components/default/_forms.scss */
+.mw-ui-vform-div {
+ display: block;
+ margin: 0 0 15px 0;
+ padding: 0;
+ width: 100%;
+}
-/* line 67, sourcefiles/scss/components/default/_forms.scss */
+/* line 96, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-input {
border-style: solid;
border-width: 1px;
outline: 0;
}
-/* line 74, sourcefiles/scss/components/default/_forms.scss */
+/* line 103, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-label {
font-size: 0.9em;
color: #4a4a4a;
font-weight: normal;
}
-/* line 83, sourcefiles/scss/components/default/_forms.scss */
+/* line 112, sourcefiles/scss/components/default/_forms.scss */
.mw-ui-checkbox-label, .mw-ui-radio-label {
margin-bottom: 0.5em;
cursor: pointer;
width: $defaultFormWidth;
+ // Immediate divs in a vform are block and spaced-out.
& > div {
display: block;
margin: 0 0 15px 0;
}
}
+
+ // HTMLForm uses error, SpecialUserlogin (login and create account) uses
+ // errorbox.
+ // TODO move errorbox from mediawiki.special.vforms.css into here.
+ .error {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ font-size: 0.9em;
+ margin: 0 0 1em 0;
+ padding: 0.5em;
+ color: #cc0000;
+ border: 1px solid #fac5c5;
+ background-color: #fae3e3;
+ text-shadow: 0 1px #fae3e3;
+ word-wrap: break-word;
+ }
}
// --------------------------------------------------------------------------
// Elements
// --------------------------------------------------------------------------
+// Apply this to individual elements to style them.
+// You generally don't need to use this class on divs within an Agora
+// form container such as mw-ui-vform
+// XXX DRY: This repeats earlier styling, use an @include agora-div-styling ?
+.mw-ui-vform-div {
+ display: block;
+ margin: 0 0 15px 0;
+ padding: 0;
+ width: 100%;
+}
+
// Apply mw-ui-input to individual input fields to style them.
// You generally don't need to use this class if <input> is within an Agora
// form container such as mw-ui-vform