diff --git a/docs/en/changelogs/3.1.0.md b/docs/en/changelogs/3.1.0.md index f5935c4db..08a883616 100644 --- a/docs/en/changelogs/3.1.0.md +++ b/docs/en/changelogs/3.1.0.md @@ -15,4 +15,5 @@ * `SiteTree::$nested_urls` enabled by default. To disable, call `SiteTree::disable_nested_urls()`. * Removed CMS permission checks from `File->canEdit()` and `File->canDelete()`. If you have unsecured controllers relying on these permissions, please override them through a `DataExtension`. * Deprecated global email methods `htmlEmail()` and `plaintextEmail`, as well as various email helper methods like `encodeMultipart()`. Use the `Email` API, or the `Mailer` class where applicable. - * Removed non-functional `$inlineImages` option for sending emails \ No newline at end of file + * Removed non-functional `$inlineImages` option for sending emails * Removed support for keyed arrays in `SelectionGroup`, use new `SelectionGroup_Item` object + to populate the list instead (see [API docs](api:SelectionGroup)). \ No newline at end of file diff --git a/forms/SelectionGroup.php b/forms/SelectionGroup.php index b17eee819..19390ce55 100644 --- a/forms/SelectionGroup.php +++ b/forms/SelectionGroup.php @@ -1,9 +1,25 @@ + * $items = array( + * new SelectionGroup_Item( + * 'one', + * new LiteralField('one', 'one view'), + * 'one title' + * ), + * new SelectionGroup_Item( + * 'two', + * new LiteralField('two', 'two view'), + * 'two title' + * ), + * ); + * $field = new SelectionGroup('MyGroup', $items); + * * * @package forms * @subpackage fields-structural @@ -12,18 +28,29 @@ class SelectionGroup extends CompositeField { /** * Create a new selection group. - * @param name The field name of the selection group. - * @param items The list of items to show. This should be a map. The keys will be the radio - * button option names, and the values should be the associated field to display. If you want, - * you can make this field a composite field. * - * If you want to a have a title that is different from the value of the key, you can express it - * as "InternalVal//This is the Title" + * @param name The field name of the selection group. + * @param items The list of {@link SelectionGroup_Item} */ public function __construct($name, $items) { $this->name = $name; - parent::__construct($items); + $selectionItems = array(); + foreach($items as $key => $item) { + if($item instanceof SelectionGroup_Item) { + $selectionItems[] = $item; + } else { + // Convert legacy format + if(strpos($key,'//') !== false) { + list($key,$title) = explode('//', $key,2); + } else { + $title = null; + } + $selectionItems[] = new SelectionGroup_Item($key, $item, $title); + } + } + + parent::__construct($selectionItems); Requirements::css(FRAMEWORK_DIR . '/css/SelectionGroup.css'); } @@ -34,33 +61,39 @@ class SelectionGroup extends CompositeField { public function FieldList() { $items = parent::FieldList()->toArray(); - $count = 0; - $firstSelected = $checked =""; $newItems = array(); - foreach($items as $key => $item) { - if(strpos($key,'//') !== false) { - list($key,$title) = explode('//', $key,2); - } else { - $title = $key; - } - if($this->value == $key) { + foreach($items as $item) { + if($this->value == $item->getValue()) { $firstSelected = " class=\"selected\""; - $checked = " checked=\"checked\""; + $checked = true; + } else { + $firstSelected = ""; + $checked = false; } $itemID = $this->ID() . '_' . (++$count); $extra = array( - "RadioButton" => "name\"" - . " value=\"$key\"$checked />", - "RadioLabel" => "", + "RadioButton" => FormField::create_tag( + 'input', + array( + 'class' => 'selector', + 'type' => 'radio', + 'id' => $itemID, + 'name' => $this->name, + 'value' => $item->getValue(), + 'checked' => $checked + ) + ), + "RadioLabel" => FormField::create_tag( + 'label', + array('for' => $itemID), + $item->getTitle() + ), "Selected" => $firstSelected, ); - if(is_object($item)) $newItems[] = $item->customise($extra); - else $newItems[] = new ArrayData($extra); - - $firstSelected = $checked =""; + $newItems[] = $item->customise($extra); } return new ArrayList($newItems); @@ -81,3 +114,47 @@ class SelectionGroup extends CompositeField { } } +class SelectionGroup_Item extends CompositeField { + + /** + * @var String + */ + protected $value; + + /** + * @var String + */ + protected $title; + + /** + * @param String $value Form field identifier + * @param FormField $field Contents of the option + * @param String $title Title to show for the radio button option + */ + function __construct($value, $fields = null, $title = null) { + $this->value = $value; + $this->title = ($title) ? $title : $value; + if($fields && !is_array($fields)) $fields = array($fields); + + parent::__construct($fields); + } + + function getTitle() { + return $this->title; + } + + function setTitle($title) { + $this->title = $title; + return $this; + } + + function getValue() { + return $this->value; + } + + function setValue($Value) { + $this->value = $Value; + return $this; + } + +} \ No newline at end of file diff --git a/javascript/SelectionGroup.js b/javascript/SelectionGroup.js index 733ce99c5..7270d4e11 100644 --- a/javascript/SelectionGroup.js +++ b/javascript/SelectionGroup.js @@ -1,7 +1,7 @@ (function($) { $(document).ready(function() { $('ul.SelectionGroup input.selector').live('click', function() { - var li = $(this).parent('li') + var li = $(this).closest('li'); li.addClass('selected'); var prev = li.prevAll('li.selected'); diff --git a/tests/forms/SelectionGroupTest.php b/tests/forms/SelectionGroupTest.php new file mode 100644 index 000000000..0b227e1f9 --- /dev/null +++ b/tests/forms/SelectionGroupTest.php @@ -0,0 +1,69 @@ +FieldHolder()); + $listEls = $parser->getBySelector('li'); + $listElOne = $listEls[0]; + $listElTwo = $listEls[1]; + + $this->assertEquals('one', (string)$listElOne->input[0]['value']); + $this->assertEquals('two', (string)$listElTwo->input[0]['value']); + + $this->assertEquals('one title', $listElOne->label[0]); + $this->assertEquals('two title', $listElTwo->label[0]); + + $this->assertContains('one view', (string)$listElOne); + $this->assertContains('two view', (string)$listElTwo); + } + + function testLegacyItemsFieldHolder() { + $items = array( + 'one' => new LiteralField('one', 'one view'), + 'two' => new LiteralField('two', 'two view'), + ); + $field = new SelectionGroup('MyGroup', $items); + $parser = new CSSContentParser($field->FieldHolder()); + $listEls = $parser->getBySelector('li'); + $listElOne = $listEls[0]; + $listElTwo = $listEls[1]; + + $this->assertEquals('one', (string)$listElOne->input[0]['value']); + $this->assertEquals('two', (string)$listElTwo->input[0]['value']); + + $this->assertEquals('one', $listElOne->label[0]); + $this->assertEquals('two', $listElTwo->label[0]); + } + + function testLegacyItemsFieldHolderWithTitle() { + $items = array( + 'one//one title' => new LiteralField('one', 'one view'), + 'two//two title' => new LiteralField('two', 'two view'), + ); + $field = new SelectionGroup('MyGroup', $items); + $parser = new CSSContentParser($field->FieldHolder()); + $listEls = $parser->getBySelector('li'); + $listElOne = $listEls[0]; + $listElTwo = $listEls[1]; + + $this->assertEquals('one', (string)$listElOne->input[0]['value']); + $this->assertEquals('two', (string)$listElTwo->input[0]['value']); + + $this->assertEquals('one title', $listElOne->label[0]); + $this->assertEquals('two title', $listElTwo->label[0]); + } + +} \ No newline at end of file