/** * 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 BSHtml::error($model, $attribute, $htmlOptions); } $id = CHtml::activeId($model, $attribute); $inputID = \bootstrap\helpers\BSArray::getValue('inputID', $htmlOptions, $id); unset($htmlOptions['inputID']); \bootstrap\helpers\BSArray::defaultValue('id', $inputID . '_em_', $htmlOptions); $option = array('id' => $id, 'inputID' => $inputID, 'errorID' => $htmlOptions['id'], 'model' => get_class($model), 'name' => $attribute, 'enableAjaxValidation' => $enableAjaxValidation, 'inputContainer' => 'div.form-group', 'errorCssClass' => $this->errorMessageCssClass, 'successCssClass' => $this->successMessageCssClass); $optionNames = array('validationDelay', 'validateOnChange', 'validateOnType', 'hideErrorMessage', 'inputContainer', 'errorCssClass', 'successCssClass', 'validatingCssClass', 'beforeValidateAttribute', 'afterValidateAttribute'); foreach ($optionNames as $name) { if (isset($htmlOptions[$name])) { $option[$name] = \bootstrap\helpers\BSArray::popValue($name, $htmlOptions); } } if ($model instanceof CActiveRecord && !$model->isNewRecord) { $option['status'] = 1; } if ($enableClientValidation) { $validators = \bootstrap\helpers\BSArray::getValue('clientValidation', $htmlOptions, array()); $attributeName = $attribute; if (($pos = strrpos($attribute, ']')) !== false && $pos !== strlen($attribute) - 1) { $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 = BSHtml::error($model, $attribute, $htmlOptions); if ($html === '') { $htmlOptions['type'] = $this->helpType; BSHtml::addCssStyle('display:none', $htmlOptions); $html = BSHtml::help('', $htmlOptions); } $this->attributes[$inputID] = $option; return $html; }
/** * Generates an image carousel. * @param array $items the item configurations. * @param array $htmlOptions additional HTML attributes. * @return string the generated carousel. */ public static function carousel(array $items, $htmlOptions = array()) { if (!empty($items)) { $id = \bootstrap\helpers\BSArray::getValue('id', $htmlOptions, parent::ID_PREFIX . parent::$count++); \bootstrap\helpers\BSArray::defaultValue('id', $id, $htmlOptions); $selector = '#' . $id; self::addCssClass('carousel', $htmlOptions); if (\bootstrap\helpers\BSArray::popValue('slide', $htmlOptions, true)) { self::addCssClass('slide', $htmlOptions); } $interval = \bootstrap\helpers\BSArray::popValue('data-interval', $htmlOptions); if ($interval) { $htmlOptions['data-interval'] = $interval; } $pause = \bootstrap\helpers\BSArray::popValue('data-pause', $htmlOptions); if ($pause) { $htmlOptions['data-pause'] = $pause; } $indicatorOptions = \bootstrap\helpers\BSArray::popValue('indicatorOptions', $htmlOptions, array()); $innerOptions = \bootstrap\helpers\BSArray::popValue('innerOptions', $htmlOptions, array()); self::addCssClass('carousel-inner', $innerOptions); $prevOptions = \bootstrap\helpers\BSArray::popValue('prevOptions', $htmlOptions, array()); $prevLabel = \bootstrap\helpers\BSArray::popValue('label', $prevOptions, '‹'); $nextOptions = \bootstrap\helpers\BSArray::popValue('nextOptions', $htmlOptions, array()); $nextLabel = \bootstrap\helpers\BSArray::popValue('label', $nextOptions, '›'); $hidePrevAndNext = \bootstrap\helpers\BSArray::popValue('hidePrevAndNext', $htmlOptions, false); $output = self::openTag('div', $htmlOptions); $output .= self::carouselIndicators($selector, count($items), $indicatorOptions); $output .= self::openTag('div', $innerOptions); foreach ($items as $i => $itemOptions) { if (isset($itemOptions['visible']) && $itemOptions['visible'] === false) { continue; } if ($i === 0) { // first item should be active self::addCssClass('active', $itemOptions); } $content = \bootstrap\helpers\BSArray::popValue('content', $itemOptions, ''); $image = \bootstrap\helpers\BSArray::popValue('image', $itemOptions, ''); $imageOptions = \bootstrap\helpers\BSArray::popValue('imageOptions', $itemOptions, array()); $imageAlt = \bootstrap\helpers\BSArray::popValue('alt', $imageOptions, ''); if (!empty($image)) { $content = parent::image($image, $imageAlt, $imageOptions); } $label = \bootstrap\helpers\BSArray::popValue('label', $itemOptions); $caption = \bootstrap\helpers\BSArray::popValue('caption', $itemOptions); $output .= self::carouselItem($content, $label, $caption, $itemOptions); } $output .= '</div>'; if (!$hidePrevAndNext) { $output .= self::carouselPrevLink($prevLabel, $selector, $prevOptions); $output .= self::carouselNextLink($nextLabel, $selector, $nextOptions); } $output .= '</div>'; return $output; } return ''; }