ENHANCEMENT Custom form attributes through Form->setAttribute()

This commit is contained in:
Ingo Schommer 2011-12-22 18:05:20 +01:00
parent 0dab75c3a0
commit 72694d8349
3 changed files with 98 additions and 25 deletions

View File

@ -145,6 +145,12 @@ class Form extends RequestHandler {
*/
protected $encType;
/**
* @var array Any custom form attributes set through {@link setAttributes()}.
* Some attributes are calculated on the fly, so please use {@link getAttributes()} to access them.
*/
protected $attributes = array();
/**
* Create a new form, with the given fields an action buttons.
*
@ -576,6 +582,40 @@ class Form extends RequestHandler {
$this->actions->removeByName($name);
}
/**
* @param String
* @param String
*/
function setAttribute($name, $value) {
$this->attributes[$name] = $value;
}
/**
* @return String
*/
function getAttribute($name) {
return @$this->attributes[$name];
}
function getAttributes() {
$attrs = array(
'id' => $this->FormName(),
'action' => $this->FormAction(),
'method' => $this->FormMethod(),
'enctype' => $this->getEncType(),
'target' => $this->target,
'class' => $this->extraClass(),
);
if($this->validator && $this->validator->getErrors()) {
if(!isset($attrs['class'])) $attrs['class'] = '';
$attrs['class'] .= ' validationerror';
}
$attrs = array_merge($attrs, $this->attributes);
return $attrs;
}
/**
* Unset the form's dataField by its name
*
@ -603,37 +643,40 @@ class Form extends RequestHandler {
/**
* Return the attributes of the form tag - used by the templates.
*
* @return string The attribute string
* @param Array Custom attributes to process. Falls back to {@link getAttributes()}.
* If at least one argument is passed as a string, all arguments act as excludes by name.
* @return String HTML attributes, ready for insertion into an HTML tag
*/
function FormAttributes() {
$attributes = array();
function getAttributesHTML($attrs = null) {
$exclude = (is_string($attrs)) ? func_get_args() : null;
if(!$attrs || is_string($attrs)) $attrs = $this->getAttributes();
// Forms shouldn't be cached, cos their error messages won't be shown
HTTP::set_cache_age(0);
// workaround to include javascript validation
if($this->validator && !$this->jsValidationIncluded) $this->validator->includeJavascriptValidation();
$attrs = $this->getAttributes();
// Remove empty
$attrs = array_filter((array)$attrs, create_function('$v', 'return ($v || $v === 0);'));
// compile attributes
$attributes['id'] = $this->FormName();
$attributes['action'] = $this->FormAction();
$attributes['method'] = $this->FormMethod();
$attributes['enctype'] = $this->getEncType();
if($this->target) $attributes['target'] = $this->target;
if($this->extraClass()) $attributes['class'] = $this->extraClass();
if($this->validator && $this->validator->getErrors()) {
if(!isset($attributes['class'])) $attributes['class'] = '';
$attributes['class'] .= ' validationerror';
// Remove excluded
if($exclude) $attrs = array_diff_key($attrs, array_flip($exclude));
// Create markkup
$parts = array();
foreach($attrs as $name => $value) {
$parts[] = ($value === true) ? "{$name}=\"{$name}\"" : "{$name}=\"" . Convert::raw2att($value) . "\"";
}
// implode attributes into string
$preparedAttributes = '';
foreach($attributes as $k => $v) {
// Note: as indicated by the $k == value item here; the decisions over what to include in the attributes can sometimes get finicky
if(!empty($v) || $v === '0' || $k == 'value') $preparedAttributes .= " $k=\"" . Convert::raw2att($v) . "\"";
}
return $preparedAttributes;
return implode(' ', $parts);
}
function FormAttributes() {
return $this->getAttributesHTML();
}
/**

View File

@ -1,5 +1,5 @@
<% if IncludeFormTag %>
<form $FormAttributes>
<form $AttributesHTML>
<% end_if %>
<% if Message %>
<p id="{$FormName}_error" class="message $MessageType">$Message</p>

View File

@ -340,9 +340,39 @@ class FormTest extends FunctionalTest {
$this->assertEquals('application/x-www-form-urlencoded', $form->getEncType());
}
function testAttributes() {
$form = $this->getStubForm();
$form->setAttribute('foo', 'bar');
$this->assertEquals('bar', $form->getAttribute('foo'));
$attrs = $form->getAttributes();
$this->assertArrayHasKey('foo', $attrs);
$this->assertEquals('bar', $attrs['foo']);
}
function testAttributesHTML() {
$form = $this->getStubForm();
$form->setAttribute('foo', 'bar');
$this->assertContains('foo="bar"', $form->getAttributesHTML());
$form->setAttribute('foo', null);
$this->assertNotContains('foo="bar"', $form->getAttributesHTML());
$form->setAttribute('foo', true);
$this->assertContains('foo="foo"', $form->getAttributesHTML());
$form->setAttribute('one', 1);
$form->setAttribute('two', 2);
$form->setAttribute('three', 3);
$this->assertNotContains('one="1"', $form->getAttributesHTML('one', 'two'));
$this->assertNotContains('two="2"', $form->getAttributesHTML('one', 'two'));
$this->assertContains('three="3"', $form->getAttributesHTML('one', 'two'));
}
protected function getStubForm() {
return new Form(
new Controller(),
new FormTest_Controller(),
'Form',
new FieldList(new TextField('key1')),
new FieldList()