/**
     * Renders the widget.
     *
     * @param  string $name        The element name
     * @param  string $value       The value selected in this widget
     * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
     * @param  array  $errors      An array of errors for the field
     *
     * @return string An HTML tag string
     *
     * @see sfWidgetForm
     */
    public function render($name, $value = null, $attributes = array(), $errors = array())
    {
        if ('[]' != substr($name, -2)) {
            $name .= '[]';
        }
        if (isset($attributes['id'])) {
            $this->setId($attributes['id']);
        } else {
            $this->setId($this->generateId($name, 'checkboxgroup'));
        }
        $this->setAllCheckboxId($this->getId() . '_allcheck');
        $html = parent::render($name, $value, $attributes, $errors);
        // Add javascript (only if we have an 'All' checkbox
        if ($this->getOption('show_all_option')) {
            $allOptionId = $this->getAllCheckboxId();
            $template = <<<EOF
<script type="text/javascript">

\$(document).ready(function() {

    \$('#{all.checkbox.id}').click(function() {
       var checked = \$(this).is(":checked");
       \$('#{container.id} input[type="checkbox"]').attr('checked', checked);
    });
                                
    \$('#{container.id} input[type="checkbox"]').click(function() {
        var notCheckedCount = \$('#{container.id} input[name="{field.name}"]:not(:checked)').length;
        var check = (notCheckedCount == 0);

        \$('#{all.checkbox.id}').attr('checked', check);
    });
});

 </script>
EOF;
            $templateVars = array('{all.checkbox.id}' => $allOptionId, '{container.id}' => $this->getId(), '{field.name}' => $name);
            $javascript = strtr($template, $templateVars);
            $html .= $javascript;
        }
        return $html;
    }
$t->is($w->render('foo', array('foo', 'foobar')), $output, '->render() has support for groups');
$w->setOption('choices', array('foo' => array('foo' => 'bar', 'bar' => 'foo')));
$output = 'foo <ul class="checkbox_list"><li><input name="foo[]" type="checkbox" value="foo" id="foo_foo" />&nbsp;<label for="foo_foo">bar</label></li>
<li><input name="foo[]" type="checkbox" value="bar" id="foo_bar" checked="checked" />&nbsp;<label for="foo_bar">foo</label></li></ul>';
$t->is($w->render('foo', array('bar')), $output, '->render() accepts a single group');
try {
    $w = new sfWidgetFormSelectCheckbox();
    $t->fail('__construct() throws an RuntimeException if you don\'t pass a choices option');
} catch (RuntimeException $e) {
    $t->pass('__construct() throws an RuntimeException if you don\'t pass a choices option');
}
// choices as a callable
$t->diag('choices as a callable');
function choice_callable()
{
    return array(1, 2, 3);
}
$w = new sfWidgetFormSelectCheckbox(array('choices' => new sfCallable('choice_callable')));
$dom->loadHTML($w->render('foo'));
$css = new sfDomCssSelector($dom);
$t->is(count($css->matchAll('input[type="checkbox"]')->getNodes()), 3, '->render() accepts a sfCallable as a choices option');
// __clone()
$t->diag('__clone()');
$w = new sfWidgetFormSelectCheckbox(array('choices' => new sfCallable(array($w, 'foo'))));
$w1 = clone $w;
$callable = $w1->getOption('choices')->getCallable();
$t->is(spl_object_hash($callable[0]), spl_object_hash($w1), '__clone() changes the choices is a callable and the object is an instance of the current object');
$w = new sfWidgetFormSelectCheckbox(array('choices' => new sfCallable(array($a = new stdClass(), 'foo'))));
$w1 = clone $w;
$callable = $w1->getOption('choices')->getCallable();
$t->is(spl_object_hash($callable[0]), spl_object_hash($a), '__clone() changes nothing if the choices is a callable and the object is not an instance of the current object');
function choice_callable()
{
    return array(1, 2, 3);
}
$w = new sfWidgetFormSelectCheckbox(array('choices' => new sfCallable('choice_callable')));
$dom->loadHTML($w->render('foo'));
$css = new sfDomCssSelector($dom);
$t->is(count($css->matchAll('input[type="checkbox"]')->getNodes()), 3, '->render() accepts a sfCallable as a choices option');
// choices are translated
$t->diag('choices are translated');
$ws = new sfWidgetFormSchema();
$ws->addFormFormatter('stub', new FormFormatterStub());
$ws->setFormFormatterName('stub');
$w = new sfWidgetFormSelectCheckbox(array('choices' => array('foo' => 'bar', 'foobar' => 'foo'), 'separator' => ''));
$w->setParent($ws);
$output = '<ul class="checkbox_list">' . '<li><input name="foo[]" type="checkbox" value="foo" id="foo_foo" />&nbsp;<label for="foo_foo">translation[bar]</label></li>' . '<li><input name="foo[]" type="checkbox" value="foobar" id="foo_foobar" />&nbsp;<label for="foo_foobar">translation[foo]</label></li>' . '</ul>';
$t->is($w->render('foo'), $output, '->render() translates the options');
// choices are escaped
$t->diag('choices are escaped');
$w = new sfWidgetFormSelectCheckbox(array('choices' => array('<b>Hello world</b>')));
$t->is($w->render('foo'), '<ul class="checkbox_list"><li><input name="foo[]" type="checkbox" value="0" id="foo_0" />&nbsp;<label for="foo_0">&lt;b&gt;Hello world&lt;/b&gt;</label></li></ul>', '->render() escapes the choices');
// __clone()
$t->diag('__clone()');
$w = new sfWidgetFormSelectCheckbox(array('choices' => new sfCallable(array($w, 'foo'))));
$w1 = clone $w;
$callable = $w1->getOption('choices')->getCallable();
$t->is(spl_object_hash($callable[0]), spl_object_hash($w1), '__clone() changes the choices is a callable and the object is an instance of the current object');
$w = new sfWidgetFormSelectCheckbox(array('choices' => new sfCallable(array($a = new stdClass(), 'foo'))));
$w1 = clone $w;
$callable = $w1->getOption('choices')->getCallable();
$t->is(spl_object_hash($callable[0]), spl_object_hash($a), '__clone() changes nothing if the choices is a callable and the object is not an instance of the current object');
    $t->pass('__construct() throws an RuntimeException if you don\'t pass a choices option');
}
// choices as a callable
$t->diag('choices as a callable');
function choice_callable()
{
    return array(1, 2, 3);
}
$w = new sfWidgetFormSelectCheckbox(array('choices' => new sfCallable('choice_callable')));
$dom->loadHTML($w->render('foo'));
$css = new sfDomCssSelector($dom);
$t->is(count($css->matchAll('input[type="checkbox"]')->getNodes()), 3, '->render() accepts a sfCallable as a choices option');
// choices are translated
$t->diag('choices are translated');
$ws = new sfWidgetFormSchema();
$ws->addFormFormatter('stub', new FormFormatterStub());
$ws->setFormFormatterName('stub');
$w = new sfWidgetFormSelectCheckbox(array('choices' => array('foo' => 'bar', 'foobar' => 'foo'), 'separator' => ''));
$w->setParent($ws);
$output = '<ul class="checkbox_list">' . '<li><input name="foo[]" type="checkbox" value="foo" id="foo_foo" />&nbsp;<label for="foo_foo">translation[bar]</label></li>' . '<li><input name="foo[]" type="checkbox" value="foobar" id="foo_foobar" />&nbsp;<label for="foo_foobar">translation[foo]</label></li>' . '</ul>';
$t->is($w->render('foo'), $output, '->render() translates the options');
// __clone()
$t->diag('__clone()');
$w = new sfWidgetFormSelectCheckbox(array('choices' => new sfCallable(array($w, 'foo'))));
$w1 = clone $w;
$callable = $w1->getOption('choices')->getCallable();
$t->is(spl_object_hash($callable[0]), spl_object_hash($w1), '__clone() changes the choices is a callable and the object is an instance of the current object');
$w = new sfWidgetFormSelectCheckbox(array('choices' => new sfCallable(array($a = new stdClass(), 'foo'))));
$w1 = clone $w;
$callable = $w1->getOption('choices')->getCallable();
$t->is(spl_object_hash($callable[0]), spl_object_hash($a), '__clone() changes nothing if the choices is a callable and the object is not an instance of the current object');