/** * 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 (is_null($value)) { $value = array(); } $choices = $this->getOption('choices'); if ($choices instanceof sfCallable) { $choices = $choices->call(); } $associated = array(); $unassociated = array(); if (!is_array($value)) { $value = array($value); } foreach ($choices as $key => $option) { if (in_array(strval($key), $value)) { $associated[$key] = $option; } else { $unassociated[$key] = $option; } } $size = isset($attributes['size']) ? $attributes['size'] : (isset($this->attributes['size']) ? $this->attributes['size'] : 10); $id = $this->generateId($name); $error_id = 'error_' . $id; // The two select boxes $associatedWidget = new sfWidgetFormSelect(array('multiple' => true, 'choices' => $associated), array('size' => $size, 'class' => $this->getOption('class_select') . '-selected')); $unassociatedWidget = new sfWidgetFormSelect(array('multiple' => true, 'choices' => $unassociated), array('size' => $size, 'class' => $this->getOption('class_select'))); // The input box used to filter content of unassociated select box $filterWidget = new sfWidgetFormInputText(array(), array('class' => $this->getOption('filter_class'))); // Options to be passed to the renderTag of reset filter image $filterResetOptions = array('src' => '/images/remove.png', 'id' => 'filter_' . $id . "_clear", 'class' => 'filter_clear', 'alt' => __('Reset filter'), 'title' => __('Reset filter')); $addOptionHTML = ''; // If add of a value in distant table is possible and activated if ($this->getOption('add_active')) { // Define the add value input box $addOptionWidget = new sfWidgetFormInputText(array(), array('id' => 'add_' . $id, 'class' => $this->getOption('add_class'))); $addOptionWidget->setLabel(__('Add new value:')); // Options to be passed to the renderTag of add option image $addImageOptions = array('src' => '/images/add_green.png', 'id' => 'add_' . $id . '_image', 'class' => 'add_option', 'alt' => __('Add value'), 'title' => __('Add value')); // Options to be passed to the timer displayed while tryin' to insert a value $addTimerImageOptions = array('src' => '/images/loader.gif', 'id' => 'add_' . $id . '_loader', 'style' => 'display:none;'); $addLinkOptions = array('id' => 'add_' . $id . '_link', 'class' => 'add_option', 'href' => url_for($this->getOption('add_url'))); $addOptionHTML = $this->renderContentTag('label', $addOptionWidget->getLabel(), array('for' => 'add_' . $id)) . $addOptionWidget->render('add_' . $name) . $this->renderContentTag('a', $this->renderTag('img', $addImageOptions), $addLinkOptions) . $this->renderTag('img', $addTimerImageOptions); } return strtr($this->getOption('template'), array('%class%' => $this->getOption('class'), '%class_select%' => $this->getOption('class_select'), '%id%' => $id, '%label_associated%' => $this->getOption('label_associated'), '%label_unassociated%' => $this->getOption('label_unassociated'), '%associate%' => sprintf('<a href="#" id="associate_' . $id . '">%s</a>', $this->getOption('associate')), '%unassociate%' => sprintf('<a href="#" id="unassociate_' . $id . '">%s</a>', $this->getOption('unassociate')), '%associated%' => $associatedWidget->render($name), '%unassociated%' => $unassociatedWidget->render('unassociated_' . $name), '%filter%' => $filterWidget->render('filter_' . $name), '%filter_reset%' => $this->renderTag('img', $filterResetOptions), '%add_option%' => $addOptionHTML, '%error_id%' => $error_id)); }