Skip to content

Commit

Permalink
ENHANCEMENT Custom form attributes through Form->setAttribute()
Browse files Browse the repository at this point in the history
  • Loading branch information
chillu committed Jan 2, 2012
1 parent 0dab75c commit 72694d8
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 25 deletions.
89 changes: 66 additions & 23 deletions forms/Form.php
Expand Up @@ -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.
*
Expand Down Expand Up @@ -576,6 +582,40 @@ function unsetActionByName($name) {
$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
*
Expand Down Expand Up @@ -603,37 +643,40 @@ public function unsetFieldFromTab($tabName, $fieldName) {
/**
* 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';
}

// 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) . "\"";
// 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) . "\"";
}

return $preparedAttributes;

return implode(' ', $parts);
}

function FormAttributes() {
return $this->getAttributesHTML();
}

/**
Expand Down
2 changes: 1 addition & 1 deletion templates/Includes/Form.ss
@@ -1,5 +1,5 @@
<% if IncludeFormTag %>
<form $FormAttributes>
<form $AttributesHTML>
<% end_if %>
<% if Message %>
<p id="{$FormName}_error" class="message $MessageType">$Message</p>
Expand Down
32 changes: 31 additions & 1 deletion tests/forms/FormTest.php
Expand Up @@ -340,9 +340,39 @@ public function testEncType() {
$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()
Expand Down

0 comments on commit 72694d8

Please sign in to comment.