* @copyright Copyright © Christoffer Niska 2013- * @license http://www.opensource.org/licenses/bsd-license.php New BSD License * @package bootstrap.widgets */ /** * Bootstrap active form widget. */ class TbActiveForm extends CActiveForm { /** * @var string the form layout. */ public $layout; /** * @var string the help type. Valid values are TbHtml::HELP_INLINE and TbHtml::HELP_BLOCK. */ public $helpType = TbHtml::HELP_TYPE_BLOCK; /** * @var string the CSS class name for error messages. */ public $errorMessageCssClass = 'error'; /** * @var string the CSS class name for success messages. */ public $successMessageCssClass = 'success'; /** * @var boolean whether to hide inline errors. Defaults to false. */ public $hideInlineErrors = false; /** * Initializes the widget. */ public function init() { $this->attachBehavior('TbWidget', new TbWidget); $this->copyId(); if ($this->stateful) { echo TbHtml::statefulFormTb($this->layout, $this->action, $this->method, $this->htmlOptions); } else { echo TbHtml::beginFormTb($this->layout, $this->action, $this->method, $this->htmlOptions); } } /** * Displays the first validation error for a model attribute. * @param CModel $model the data model * @param string $attribute the attribute name * @param array $htmlOptions additional HTML attributes to be rendered in the container div tag. * @param boolean $enableAjaxValidation whether to enable AJAX validation for the specified attribute. * @param boolean $enableClientValidation whether to enable client-side validation for the specified attribute. * @return string the validation result (error display or success message). */ public function error( $model, $attribute, $htmlOptions = array(), $enableAjaxValidation = true, $enableClientValidation = true ) { if (!$this->enableAjaxValidation) { $enableAjaxValidation = false; } if (!$this->enableClientValidation) { $enableClientValidation = false; } if (!$enableAjaxValidation && !$enableClientValidation) { return TbHtml::error($model, $attribute, $htmlOptions); } $id = CHtml::activeId($model, $attribute); $inputID = TbArray::getValue('inputID', $htmlOptions, $id); unset($htmlOptions['inputID']); TbArray::defaultValue('id', $inputID . '_em_', $htmlOptions); $option = array( 'id' => $id, 'inputID' => $inputID, 'errorID' => $htmlOptions['id'], 'model' => get_class($model), 'name' => $attribute, 'enableAjaxValidation' => $enableAjaxValidation, 'inputContainer' => 'div.control-group', // Bootstrap requires this ); $optionNames = array( 'validationDelay', 'validateOnChange', 'validateOnType', 'hideErrorMessage', 'inputContainer', 'errorCssClass', 'successCssClass', 'validatingCssClass', 'beforeValidateAttribute', 'afterValidateAttribute', ); foreach ($optionNames as $name) { if (isset($htmlOptions[$name])) { $option[$name] = TbArray::popValue($name, $htmlOptions); } } if ($model instanceof CActiveRecord && !$model->isNewRecord) { $option['status'] = 1; } if ($enableClientValidation) { $validators = TbArray::getValue('clientValidation', $htmlOptions, array()); $attributeName = $attribute; if (($pos = strrpos($attribute, ']')) !== false && $pos !== strlen($attribute) - 1) // e.g. [a]name { $attributeName = substr($attribute, $pos + 1); } foreach ($model->getValidators($attributeName) as $validator) { if ($validator->enableClientValidation) { if (($js = $validator->clientValidateAttribute($model, $attributeName)) != '') { $validators[] = $js; } } } if ($validators !== array()) { $option['clientValidation'] = "js:function(value, messages, attribute) {\n" . implode( "\n", $validators ) . "\n}"; } } $html = TbHtml::error($model, $attribute, $htmlOptions); if ($html === '') { $htmlOptions['type'] = $this->helpType; TbHtml::addCssStyle('display:none', $htmlOptions); $html = TbHtml::help('', $htmlOptions); } $this->attributes[$inputID] = $option; return $html; } /** * Displays a summary of validation errors for one or several models. * @param mixed $models the models whose input errors are to be displayed. * @param string $header a piece of HTML code that appears in front of the errors * @param string $footer a piece of HTML code that appears at the end of the errors * @param array $htmlOptions additional HTML attributes to be rendered in the container div tag. * @return string the error summary. Empty if no errors are found. */ public function errorSummary($models, $header = null, $footer = null, $htmlOptions = array()) { if (!$this->enableAjaxValidation && !$this->enableClientValidation) { return TbHtml::errorSummary($models, $header, $footer, $htmlOptions); } TbArray::defaultValue('id', $this->id . '_es_', $htmlOptions); $html = TbHtml::errorSummary($models, $header, $footer, $htmlOptions); if ($html === '') { if ($header === null) { $header = '

' . Yii::t('yii', 'Please fix the following input errors:') . '

'; } TbHtml::addCssClass(TbHtml::$errorSummaryCss, $htmlOptions); TbHtml::addCssStyle('display:none', $htmlOptions); $html = CHtml::tag('div', $htmlOptions, $header . '' . $footer); } $this->summaryID = $htmlOptions['id']; return $html; } /** * Generates a text field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated input field. * @see TbHtml::activeTextField */ public function textField($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_TEXT, $model, $attribute, $htmlOptions); } /** * Generates a password field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated input field. * @see TbHtml::activePasswordField */ public function passwordField($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_PASSWORD, $model, $attribute, $htmlOptions); } /** * Generates an url field for a model attribute. * @param CModel $model the data model * @param string $attribute the attribute * @param array $htmlOptions additional HTML attributes. * @return string the generated input field * @see TbHtml::activeUrlField */ public function urlField($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_URL, $model, $attribute, $htmlOptions); } /** * Generates an email field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated input field. * @see TbHtml::activeEmailField */ public function emailField($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_EMAIL, $model, $attribute, $htmlOptions); } /** * Generates a number field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated input field. * @see TbHtml::activeNumberField */ public function numberField($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_NUMBER, $model, $attribute, $htmlOptions); } /** * Generates a range field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated input field. * @see TbHtml::activeRangeField */ public function rangeField($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_RANGE, $model, $attribute, $htmlOptions); } /** * Generates a date field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated input field. */ public function dateField($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_DATE, $model, $attribute, $htmlOptions); } /** * Generates a text area for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated text area. * @see TbHtml::activeTextArea */ public function textArea($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_TEXTAREA, $model, $attribute, $htmlOptions); } /** * Generates a file field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes * @return string the generated input field. * @see TbHtml::activeFileField */ public function fileField($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_FILE, $model, $attribute, $htmlOptions); } /** * Generates a radio button for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated radio button. * @see TbHtml::activeRadioButton */ public function radioButton($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_RADIOBUTTON, $model, $attribute, $htmlOptions); } /** * Generates a checkbox for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated check box. * @see TbHtml::activeCheckBox */ public function checkBox($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_CHECKBOX, $model, $attribute, $htmlOptions); } /** * Generates a dropdown list for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $data data for generating the list options (value=>display). * @param array $htmlOptions additional HTML attributes. * @return string the generated drop down list. * @see TbHtml::activeDropDownList */ public function dropDownList($model, $attribute, $data, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_DROPDOWNLIST, $model, $attribute, $htmlOptions, $data); } /** * Generates a list box for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $data data for generating the list options (value=>display). * @param array $htmlOptions additional HTML attributes. * @return string the generated list box. * @see TbHtml::activeListBox */ public function listBox($model, $attribute, $data, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_LISTBOX, $model, $attribute, $htmlOptions, $data); } /** * Generates a radio button list for a model attribute * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $data data for generating the list options (value=>display) * @param array $htmlOptions additional HTML attributes. * @return string the generated radio button list. * @see TbHtml::activeRadioButtonList */ public function radioButtonList($model, $attribute, $data, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_RADIOBUTTONLIST, $model, $attribute, $htmlOptions, $data); } /** * Generates an inline radio button list for a model attribute * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $data data for generating the list options (value=>display) * @param array $htmlOptions additional HTML attributes. * @return string the generated radio button list. * @see TbHtml::activeInlineRadioButtonList */ public function inlineRadioButtonList($model, $attribute, $data, $htmlOptions = array()) { $htmlOptions['inline'] = true; return $this->createInput(TbHtml::INPUT_TYPE_RADIOBUTTONLIST, $model, $attribute, $htmlOptions, $data); } /** * Generates a checkbox list for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $data data for generating the list options (value=>display) * @param array $htmlOptions additional HTML attributes. * @return string the generated checkbox list. * @see TbHtml::activeCheckBoxList */ public function checkBoxList($model, $attribute, $data, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_CHECKBOXLIST, $model, $attribute, $htmlOptions, $data); } /** * Generates an inline checkbox list for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $data data for generating the list options (value=>display) * @param array $htmlOptions additional HTML attributes. * @return string the generated checkbox list. * @see TbHtml::activeInlineCheckBoxList */ public function inlineCheckBoxList($model, $attribute, $data, $htmlOptions = array()) { $htmlOptions['inline'] = true; return $this->createInput(TbHtml::INPUT_TYPE_CHECKBOXLIST, $model, $attribute, $htmlOptions, $data); } /** * Generates an uneditable field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated field. * @see TbHtml::activeUneditableField */ public function uneditableField($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_UNEDITABLE, $model, $attribute, $htmlOptions); } /** * Generates a search query field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @return string the generated input. * @see TbHtml::activeSearchField */ public function searchQuery($model, $attribute, $htmlOptions = array()) { return $this->createInput(TbHtml::INPUT_TYPE_SEARCH, $model, $attribute, $htmlOptions); } /** * Generates an input for a model attribute. * @param string $type the input type. * @param CModel $model the data model. * @param string $attribute the attribute. * @param array $htmlOptions additional HTML attributes. * @param array $data data for generating the list options (value=>display). * @return string the generated input. * @see TbHtml::createActiveInput */ public function createInput($type, $model, $attribute, $htmlOptions = array(), $data = array()) { return TbHtml::createActiveInput($type, $model, $attribute, $htmlOptions, $data); } /** * Generates a control group with a text field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeTextFieldControlGroup */ public function textFieldControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_TEXT, $model, $attribute, $htmlOptions); } /** * Generates a control group with a password field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activePasswordFieldControlGroup */ public function passwordFieldControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_PASSWORD, $model, $attribute, $htmlOptions); } /** * Generates a control group with an url field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeUrlFieldControlGroup */ public function urlFieldControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_URL, $model, $attribute, $htmlOptions); } /** * Generates a control group with an email field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeEmailFieldControlGroup */ public function emailFieldControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_EMAIL, $model, $attribute, $htmlOptions); } /** * Generates a control group with a number field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeNumberFieldControlGroup */ public function numberFieldControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_NUMBER, $model, $attribute, $htmlOptions); } /** * Generates a control group with a range field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeRangeFieldControlGroup */ public function rangeFieldControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_RANGE, $model, $attribute, $htmlOptions); } /** * Generates a control group with a date field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeDateFieldControlGroup */ public function dateFieldControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_DATE, $model, $attribute, $htmlOptions); } /** * Generates a control group with a text area for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeTextAreaControlGroup */ public function textAreaControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_TEXTAREA, $model, $attribute, $htmlOptions); } /** * Generates a control group with a check box for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeCheckBoxControlGroup */ public function checkBoxControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_CHECKBOX, $model, $attribute, $htmlOptions); } /** * Generates a control group with a radio button for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeRadioButtonControlGroup */ public function radioButtonControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_RADIOBUTTON, $model, $attribute, $htmlOptions); } /** * Generates a control group with a drop down list for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $data data for generating the list options (value=>display). * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeDropDownListControlGroup */ public function dropDownListControlGroup($model, $attribute, $data, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_DROPDOWNLIST, $model, $attribute, $htmlOptions, $data); } /** * Generates a control group with a list box for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $data data for generating the list options (value=>display). * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeListBoxControlGroup */ public function listBoxControlGroup($model, $attribute, $data, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_LISTBOX, $model, $attribute, $htmlOptions, $data); } /** * Generates a control group with a file field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeFileFieldControlGroup */ public function fileFieldControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_FILE, $model, $attribute, $htmlOptions); } /** * Generates a control group with a radio button list for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $data data for generating the list options (value=>display). * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeRadioButtonListControlGroup */ public function radioButtonListControlGroup($model, $attribute, $data, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_RADIOBUTTONLIST, $model, $attribute, $htmlOptions, $data); } /** * Generates a control group with an inline radio button list for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $data data for generating the list options (value=>display). * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeInlineCheckBoxListControlGroup */ public function inlineRadioButtonListControlGroup($model, $attribute, $data, $htmlOptions = array()) { $htmlOptions['inline'] = true; return $this->createControlGroup(TbHtml::INPUT_TYPE_RADIOBUTTONLIST, $model, $attribute, $htmlOptions, $data); } /** * Generates a control group with a check box list for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $data data for generating the list options (value=>display). * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeCheckBoxListControlGroup */ public function checkBoxListControlGroup($model, $attribute, $data, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_CHECKBOXLIST, $model, $attribute, $htmlOptions, $data); } /** * Generates a control group with an inline check box list for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $data data for generating the list options (value=>display). * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeInlineCheckBoxListControlGroup */ public function inlineCheckBoxListControlGroup($model, $attribute, $data, $htmlOptions = array()) { $htmlOptions['inline'] = true; return $this->createControlGroup(TbHtml::INPUT_TYPE_CHECKBOXLIST, $model, $attribute, $htmlOptions, $data); } /** * Generates a control group with an uneditable field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeUneditableFieldControlGroup */ public function uneditableFieldControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_UNEDITABLE, $model, $attribute, $htmlOptions); } /** * Generates a control group with a search field for a model attribute. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @return string the generated control group. * @see TbHtml::activeSearchFieldControlGroup */ public function searchQueryControlGroup($model, $attribute, $htmlOptions = array()) { return $this->createControlGroup(TbHtml::INPUT_TYPE_SEARCH, $model, $attribute, $htmlOptions); } /** * Generates a control group for a model attribute. * @param string $type the input type. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $htmlOptions additional HTML attributes. * @param array $data data for generating the list options (value=>display). * @return string the generated control group. * @see TbHtml::activeControlGroup */ public function createControlGroup($type, $model, $attribute, $htmlOptions = array(), $data = array()) { $htmlOptions = $this->processControlGroupOptions($model, $attribute, $htmlOptions); return TbHtml::activeControlGroup($type, $model, $attribute, $htmlOptions, $data); } /** * Processes the options for a input row. * @param CModel $model the data model. * @param string $attribute the attribute name. * @param array $options the options. * @return array the processed options. */ protected function processControlGroupOptions($model, $attribute, $options) { $errorOptions = TbArray::popValue('errorOptions', $options, array()); $enableAjaxValidation = TbArray::popValue('enableAjaxValidation', $errorOptions, true); $enableClientValidation = TbArray::popValue('enableClientValidation', $errorOptions, true); $errorOptions['type'] = $this->helpType; $error = $this->error($model, $attribute, $errorOptions, $enableAjaxValidation, $enableClientValidation); // kind of a hack for ajax forms but this works for now. if (!empty($error) && strpos($error, 'display:none') === false) { $options['color'] = TbHtml::INPUT_COLOR_ERROR; } if (!$this->hideInlineErrors) { $options['error'] = $error; } $helpOptions = TbArray::popValue('helpOptions', $options, array()); $helpOptions['type'] = $this->helpType; $options['helpOptions'] = $helpOptions; return $options; } }