1
0

Added Yiistrap

This commit is contained in:
2014-05-13 14:06:18 +02:00
parent 5e21ecb401
commit 826c4bdfb3
118 changed files with 31164 additions and 54 deletions

View File

@@ -0,0 +1,733 @@
<?php
/**
* TbActiveForm class file.
* @author Antonio Ramirez <ramirez.cobos@gmail.com>
* @copyright Copyright &copy; 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 = '<p>' . Yii::t('yii', 'Please fix the following input errors:') . '</p>';
}
TbHtml::addCssClass(TbHtml::$errorSummaryCss, $htmlOptions);
TbHtml::addCssStyle('display:none', $htmlOptions);
$html = CHtml::tag('div', $htmlOptions, $header . '<ul><li>dummy</li></ul>' . $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;
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* TbAffix class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap affix widget.
* @see http://twitter.github.com/bootstrap/javascript.html#affix
*/
class TbAffix extends CWidget
{
/**
* @var string the HTML tag for the container.
*/
public $tagName = 'div';
/**
* @var mixed pixels to offset from screen when calculating position of scroll.
*/
public $offset;
/**
* @var array the HTML attributes for the container.
*/
public $htmlOptions = array();
/**
* Initializes the widget.
*/
public function init()
{
$this->attachBehavior('TbWidget', new TbWidget);
$this->copyId();
$this->htmlOptions['data-spy'] = 'affix';
if (isset($this->offset)) {
if (is_string($this->offset)) {
$this->offset = array('top', $this->offset);
}
if (is_array($this->offset) && count($this->offset) === 2) {
list($position, $offset) = $this->offset;
$this->htmlOptions['data-offset-' . $position] = $offset;
}
}
echo TbHtml::openTag($this->tagName, $this->htmlOptions);
}
/**
* Runs the widget.
*/
public function run()
{
echo CHtml::closeTag($this->tagName);
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* TbAlert class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap alert widget.
* @see http://twitter.github.com/bootstrap/javascript.html#alerts
*/
class TbAlert extends CWidget
{
/**
* @var array the alerts configurations (style=>config).
*/
public $alerts;
/**
* @var string|boolean the close link text. If this is set false, no close link will be displayed.
*/
public $closeText = TbHtml::CLOSE_TEXT;
/**
* @var boolean indicates whether the alert should be an alert block. Defaults to 'true'.
*/
public $block = true;
/**
* @var boolean indicates whether alerts should use transitions. Defaults to 'true'.
*/
public $fade = true;
/**
* @var string[] the JavaScript event configuration (name=>handler).
*/
public $events = array();
/**
* @var array the HTML attributes for the alert container.
*/
public $htmlOptions = array();
/**
* Initializes the widget.
*/
public function init()
{
$this->attachBehavior('TbWidget', new TbWidget);
$this->copyId();
if (is_string($this->alerts)) {
$colors = explode(' ', $this->alerts);
} else {
if (!isset($this->alerts)) {
$colors = array(
TbHtml::ALERT_COLOR_SUCCESS,
TbHtml::ALERT_COLOR_WARNING,
TbHtml::ALERT_COLOR_INFO,
TbHtml::ALERT_COLOR_ERROR
); // render all styles by default
}
}
if (isset($colors)) {
$this->alerts = array();
foreach ($colors as $color) {
$this->alerts[$color] = array();
}
}
}
/**
* Runs the widget.
*/
public function run()
{
/* @var $user CWebUser */
$user = Yii::app()->getUser();
if (count($user->getFlashes(false)) == 0) {
return;
}
echo TbHtml::openTag('div', $this->htmlOptions);
foreach ($this->alerts as $color => $alert) {
if (isset($alert['visible']) && !$alert['visible']) {
continue;
}
if ($user->hasFlash($color)) {
$htmlOptions = TbArray::popValue('htmlOptions', $alert, array());
TbArray::defaultValue('closeText', $this->closeText, $htmlOptions);
TbArray::defaultValue('block', $this->block, $htmlOptions);
TbArray::defaultValue('fade', $this->fade, $htmlOptions);
echo TbHtml::alert($color, $user->getFlash($color), $htmlOptions);
}
}
echo '</div>';
$this->registerEvents("#{$this->htmlOptions['id']} > .alert", $this->events);
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* TbBreadcrumbs class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
*/
/**
* Bootstrap breadcrumb widget.
* @see http://twitter.github.com/bootstrap/components.html#breadcrumbs
* @package bootstrap.widgets
*/
class TbBreadcrumb extends CWidget
{
/**
* @var string the divider between links in the breadcrumbs.
*/
public $divider = '/';
/**
* @var boolean whether to HTML encode the link labels.
*/
public $encodeLabel = true;
/**
* @var string the label for the first link in the breadcrumb.
*/
public $homeLabel;
/**
* @var array the url for the first link in the breadcrumb
*/
public $homeUrl;
/**
* @var array the HTML attributes for the breadcrumbs.
*/
public $htmlOptions = array();
/**
* @var array list of links to appear in the breadcrumbs.
*/
public $links = array();
/**
* Initializes the widget.
*/
public function init()
{
$this->htmlOptions['divider'] = $this->divider;
}
/**
* Runs the widget.
*/
public function run()
{
// todo: consider adding control property for displaying breadcrumbs even when empty.
if (!empty($this->links)) {
$links = array();
if ($this->homeLabel !== false) {
$label = $this->homeLabel !== null ? $this->homeLabel : TbHtml::icon('home');
$links[$label] = $this->homeUrl !== null ? $this->homeUrl : Yii::app()->homeUrl;
}
foreach ($this->links as $label => $url) {
if (is_string($label)) {
if ($this->encodeLabel) {
$label = CHtml::encode($label);
}
$links[$label] = $url;
} else {
$links[] = $this->encodeLabel ? CHtml::encode($url) : $url;
}
}
echo TbHtml::breadcrumbs($links, $this->htmlOptions);
}
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* TbButtonColumn class file.
* @author Antonio Ramirez <ramirez.cobos@gmail.com>
* @author Christoffer Niska <ChristofferNiska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
Yii::import('zii.widgets.grid.CButtonColumn');
/**
* Bootstrap button column widget.
*/
class TbButtonColumn extends CButtonColumn
{
/**
* @var string the view button icon (defaults to TbHtml::ICON_EYE_OPEN).
*/
public $viewButtonIcon = TbHtml::ICON_EYE_OPEN;
/**
* @var string the update button icon (defaults to TbHtml::ICON_PENCIL).
*/
public $updateButtonIcon = TbHtml::ICON_PENCIL;
/**
* @var string the delete button icon (defaults to TbHtml::ICON_TRASH).
*/
public $deleteButtonIcon = TbHtml::ICON_TRASH;
/**
* Initializes the default buttons (view, update and delete).
*/
protected function initDefaultButtons()
{
parent::initDefaultButtons();
if ($this->viewButtonIcon !== false && !isset($this->buttons['view']['icon'])) {
$this->buttons['view']['icon'] = $this->viewButtonIcon;
}
if ($this->updateButtonIcon !== false && !isset($this->buttons['update']['icon'])) {
$this->buttons['update']['icon'] = $this->updateButtonIcon;
}
if ($this->deleteButtonIcon !== false && !isset($this->buttons['delete']['icon'])) {
$this->buttons['delete']['icon'] = $this->deleteButtonIcon;
}
}
/**
* Renders a link button.
* @param string $id the ID of the button
* @param array $button the button configuration which may contain 'label', 'url', 'imageUrl' and 'options' elements.
* @param integer $row the row number (zero-based)
* @param mixed $data the data object associated with the row
*/
protected function renderButton($id, $button, $row, $data)
{
if (isset($button['visible']) && !$this->evaluateExpression(
$button['visible'],
array('row' => $row, 'data' => $data)
)
) {
return;
}
$url = TbArray::popValue('url', $button);
if ($url !== '#') {
$url = $this->evaluateExpression($url, array('data' => $data, 'row' => $row));
}
$imageUrl = TbArray::popValue('imageUrl', $button, false);
$label = TbArray::popValue('label', $button, $id);
$options = TbArray::popValue('options', $button, array());
TbArray::defaultValue('title', $label, $options);
TbArray::defaultValue('rel', 'tooltip', $options);
if ($icon = TbArray::popValue('icon', $button, false)) {
echo CHtml::link(TbHtml::icon($icon), $url, $options);
} else {
if ($imageUrl && is_string($imageUrl)) {
echo CHtml::link(CHtml::image($imageUrl, $label), $url, $options);
} else {
echo CHtml::link($label, $url, $options);
}
}
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* TbCollapse class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap collapse widget.
* @see http://twitter.github.com/bootstrap/javascript.html#collapse
*/
class TbCollapse extends CWidget
{
/**
* @var string the HTML tag for the container.
*/
public $tagName = 'div';
/**
* @var string the content text.
*/
public $content;
/**
* @var string the path to a partial view.
*/
public $view;
/**
* @var string the CSS selector for the parent element.
*/
public $parent;
/**
* @var boolean whether to be collapsed on invocation.
*/
public $toggle;
/**
* @var string[] $events the JavaScript event configuration (name=>handler).
*/
public $events = array();
/**
* @var array the HTML attributes for the container.
*/
public $htmlOptions = array();
/**
* @var array additional data to be passed to the view.
*/
public $viewData = array();
/**
* Initializes the widget.
*/
public function init()
{
$this->attachBehavior('TbWidget', new TbWidget);
$this->copyId();
TbHtml::addCssClass('collapse', $this->htmlOptions);
if (isset($this->parent)) {
TbArray::defaultValue('data-parent', $this->parent, $this->htmlOptions);
}
if (isset($this->toggle) && $this->toggle) {
TbHtml::addCssClass('in', $this->htmlOptions);
}
if (isset($this->view)) {
$controller = $this->getController();
if (isset($controller) && $controller->getViewFile($this->view) !== false) {
$this->content = $this->controller->renderPartial($this->view, $this->viewData, true);
}
}
echo TbHtml::openTag($this->tagName, $this->htmlOptions);
echo $this->content;
}
/**
* Runs the widget.
*/
public function run()
{
echo CHtml::closeTag($this->tagName);
$selector = '#' . $this->htmlOptions['id'];
$this->registerEvents($selector, $this->events);
}
}

View File

@@ -0,0 +1,103 @@
<?php
/**
* TbDataColumn class file.
* @author Antonio Ramirez <ramirez.cobos@gmail.com>
* @author Christoffer Niska <ChristofferNiska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
Yii::import('zii.widgets.grid.CDataColumn');
/**
* Bootstrap grid data column.
*/
class TbDataColumn extends CDataColumn
{
/**
* @var array HTML options for filter input
* @link {TbDataColumn::renderFilterCellContent()}
*/
public $filterInputOptions;
/**
* Renders the header cell content.
* This method will render a link that can trigger the sorting if the column is sortable.
*/
protected function renderHeaderCellContent()
{
if ($this->grid->enableSorting && $this->sortable && $this->name !== null) {
$sort = $this->grid->dataProvider->getSort();
$label = isset($this->header) ? $this->header : $sort->resolveLabel($this->name);
if ($sort->resolveAttribute($this->name) !== false) {
$label .= '<span class="caret"></span>';
}
echo $sort->link($this->name, $label, array('class' => 'sort-link'));
} else {
if ($this->name !== null && $this->header === null) {
if ($this->grid->dataProvider instanceof CActiveDataProvider) {
echo CHtml::encode($this->grid->dataProvider->model->getAttributeLabel($this->name));
} else {
echo CHtml::encode($this->name);
}
} else {
parent::renderHeaderCellContent();
}
}
}
/**
* Renders the filter cell.
*/
public function renderFilterCell()
{
echo CHtml::openTag('td', $this->filterHtmlOptions);
echo '<div class="filter-container">';
$this->renderFilterCellContent();
echo '</div>';
echo CHtml::closeTag('td');
}
/**
* Renders the filter cell content. Here we can provide HTML options for actual filter input
*/
protected function renderFilterCellContent()
{
if (is_string($this->filter)) {
echo $this->filter;
} else {
if ($this->filter !== false && $this->grid->filter !== null && $this->name !== null && strpos(
$this->name,
'.'
) === false
) {
if ($this->filterInputOptions) {
$filterInputOptions = $this->filterInputOptions;
if (empty($filterInputOptions['id'])) {
$filterInputOptions['id'] = false;
}
} else {
$filterInputOptions = array();
}
if (is_array($this->filter)) {
$filterInputOptions['prompt'] = '';
echo CHtml::activeDropDownList(
$this->grid->filter,
$this->name,
$this->filter,
$filterInputOptions
);
} else {
if ($this->filter === null) {
echo CHtml::activeTextField($this->grid->filter, $this->name, $filterInputOptions);
}
}
} else {
parent::renderFilterCellContent();
}
}
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* TbDetailView class file.
* @author Sam Stenvall <sam@supportersplace.com>
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Sam Stenvall 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
Yii::import('zii.widgets.CDetailView');
/**
* Bootstrap Zii detail widget.
*/
class TbDetailView extends CDetailView
{
/**
* @var string|array the detail view style.
* Valid values are TbHtml::DETAIL_STRIPED, TbHtml::DETAIL_BORDERED, TbHtml::DETAIL_CONDENSED and/or TbHtml::DETAIL_HOVER.
*/
public $type = array(TbHtml::DETAIL_TYPE_STRIPED, TbHtml::DETAIL_TYPE_CONDENSED);
/**
* @var string the URL of the CSS file used by this grid view.
* Defaults to false, meaning that no CSS will be included.
*/
public $cssFile = false;
/**
* Initializes the widget.
*/
public function init()
{
parent::init();
$classes = array('table');
if (!empty($this->type)) {
if (is_string($this->type)) {
$this->type = explode(' ', $this->type);
}
foreach ($this->type as $type) {
$classes[] = 'table-' . $type;
}
}
TbHtml::addCssClass($classes, $this->htmlOptions);
}
}

View File

@@ -0,0 +1,106 @@
<?php
/**
* TbGridView class file.
* @author Antonio Ramirez <ramirez.cobos@gmail.com>
* @author Christoffer Niska <ChristofferNiska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
Yii::import('zii.widgets.grid.CGridView');
/**
* Bootstrap Zii grid view.
*/
class TbGridView extends CGridView
{
/**
* @var string|array the table style.
* Valid values are TbHtml::GRID_TYPE_STRIPED, TbHtml::GRID_TYPE_BORDERED, TbHtml::GRID_TYPE_CONDENSED and/or
* TbHtml::GRID_TYPE_HOVER.
*/
public $type;
/**
* @var string the CSS class name for the pager container. Defaults to 'pagination'.
*/
public $pagerCssClass = 'pagination';
/**
* @var array the configuration for the pager.
* Defaults to <code>array('class'=>'ext.bootstrap.widgets.TbPager')</code>.
*/
public $pager = array('class' => 'bootstrap.widgets.TbPager');
/**
* @var string the URL of the CSS file used by this grid view.
* Defaults to false, meaning that no CSS will be included.
*/
public $cssFile = false;
/**
* @var string the template to be used to control the layout of various sections in the view.
*/
public $template = "{items}\n<div class=\"row-fluid\"><div class=\"span6\">{pager}</div><div class=\"span6\">{summary}</div></div>";
/**
* Initializes the widget.
*/
public function init()
{
parent::init();
$classes = array('table');
if (isset($this->type) && !empty($this->type)) {
if (is_string($this->type)) {
$this->type = explode(' ', $this->type);
}
foreach ($this->type as $type) {
$classes[] = 'table-' . $type;
}
}
if (!empty($classes)) {
$classes = implode(' ', $classes);
if (isset($this->itemsCssClass)) {
$this->itemsCssClass .= ' ' . $classes;
} else {
$this->itemsCssClass = $classes;
}
}
}
/**
* Creates column objects and initializes them.
*/
protected function initColumns()
{
foreach ($this->columns as $i => $column) {
if (is_array($column) && !isset($column['class'])) {
$this->columns[$i]['class'] = 'bootstrap.widgets.TbDataColumn';
}
}
parent::initColumns();
}
/**
* Creates a column based on a shortcut column specification string.
* @param mixed $text the column specification string
* @return \TbDataColumn|\CDataColumn the column instance
* @throws CException if the column format is incorrect
*/
protected function createDataColumn($text)
{
if (!preg_match('/^([\w\.]+)(:(\w*))?(:(.*))?$/', $text, $matches)) {
throw new CException(Yii::t(
'zii',
'The column must be specified in the format of "Name:Type:Label", where "Type" and "Label" are optional.'
));
}
$column = new TbDataColumn($this);
$column->name = $matches[1];
if (isset($matches[3]) && $matches[3] !== '') {
$column->type = $matches[3];
}
if (isset($matches[5])) {
$column->header = $matches[5];
}
return $column;
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* TbHeroUnit class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap hero unit widget.
* @see http://twitter.github.com/bootstrap/javascript.html#affix
*/
class TbHeroUnit extends CWidget
{
/**
* @var string the heading text.
*/
public $heading;
/**
* @var array the HTML attributes for the heading.
*/
public $headingOptions = array();
/**
* @var string the content text.
*/
public $content;
/**
* @var string the path to a partial view.
*/
public $view;
/**
* @var array the HTML attributes for the container tag.
*/
public $htmlOptions = array();
/**
* @var array additional data to be passed to the view.
*/
public $viewData = array();
/**
* Initializes the widget.
*/
public function init()
{
if (isset($this->view)) {
$controller = $this->getController();
if (isset($controller) && $controller->getViewFile($this->view) !== false) {
$this->content = $this->controller->renderPartial($this->view, $this->viewData, true);
}
}
$this->htmlOptions['headingOptions'] = $this->headingOptions;
}
/**
* Runs the widget.
*/
public function run()
{
echo TbHtml::heroUnit($this->heading, $this->content, $this->htmlOptions);
}
}

View File

@@ -0,0 +1,44 @@
<?php
/**
* TbListView class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
Yii::import('zii.widgets.CListView');
/**
* Bootstrap Zii list view.
*/
class TbListView extends CListView
{
/**
* @var string the CSS class name for the pager container. Defaults to 'pagination'.
*/
public $pagerCssClass = 'pagination';
/**
* @var array the configuration for the pager.
* Defaults to <code>array('class'=>'ext.bootstrap.widgets.TbPager')</code>.
*/
public $pager = array('class' => 'bootstrap.widgets.TbPager');
/**
* @var string the URL of the CSS file used by this detail view.
* Defaults to false, meaning that no CSS will be included.
*/
public $cssFile = false;
/**
* @var string the template to be used to control the layout of various sections in the view.
*/
public $template = "{items}\n<div class=\"row-fluid\"><div class=\"span6\">{pager}</div><div class=\"span6\">{summary}</div></div>";
/**
* Renders the empty message when there is no data.
*/
public function renderEmptyText()
{
$emptyText = $this->emptyText === null ? Yii::t('zii', 'No results found.') : $this->emptyText;
echo TbHtml::tag('div', array('class' => 'empty', 'span' => 12), $emptyText);
}
}

View File

@@ -0,0 +1,261 @@
<?php
/**
* TbModal class file.
* @author Antonio Ramirez <ramirez.cobos@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap modal widget.
*/
class TbModal extends CWidget
{
/**
* @var array the HTML options for the view container tag.
*/
public $htmlOptions = array();
/**
* @var array The additional HTML attributes of the button that will show the modal. If empty array, only
* the markup of the modal will be rendered on the page, so users can easily call the modal manually with their own
* scripts. The following special attributes are available:
* <ul>
* <li>label: string, the label of the button</li>
* </ul>
*
* For available options of the button trigger, see http://twitter.github.com/bootstrap/javascript.html#modals.
*/
public $buttonOptions = array();
/**
* @var boolean indicates whether the modal should use transitions. Defaults to 'true'.
*/
public $fade = true;
/**
* @var bool $keyboard, closes the modal when escape key is pressed.
*/
public $keyboard = true;
/**
* @var bool $show, shows the modal when initialized.
*/
public $show = false;
/**
* @var mixed includes a modal-backdrop element. Alternatively, specify `static` for a backdrop which doesn't close
* the modal on click.
*/
public $backdrop = true;
/**
* @var mixed the remote url. If a remote url is provided, content will be loaded via jQuery's load method and
* injected into the .modal-body of the modal.
*/
public $remote;
/**
* @var string a javascript function that will be invoked immediately when the `show` instance method is called.
*/
public $onShow;
/**
* @var string a javascript function that will be invoked when the modal has been made visible to the user
* (will wait for css transitions to complete).
*/
public $onShown;
/**
* @var string a javascript function that will be invoked immediately when the hide instance method has been called.
*/
public $onHide;
/**
* @var string a javascript function that will be invoked when the modal has finished being hidden from the user
* (will wait for css transitions to complete).
*/
public $onHidden;
/**
* @var string[] the Javascript event handlers.
*/
protected $events = array();
/**
* @var array $options the plugin options.
*/
protected $options = array();
/**
* @var string
*/
public $closeText = TbHtml::CLOSE_TEXT;
/**
* @var string header content
*/
public $header;
/**
* @var string body of modal
*/
public $content;
/**
* @var string footer content
*/
public $footer;
/**
* Widget's initialization method
*/
public function init()
{
$this->attachBehavior('TbWidget', new TbWidget);
TbArray::defaultValue('id', $this->getId(), $this->htmlOptions);
TbArray::defaultValue('role', 'dialog', $this->htmlOptions);
TbArray::defaultValue('tabindex', '-1', $this->htmlOptions);
TbHtml::addCssClass('modal hide', $this->htmlOptions);
if ($this->fade) {
TbHtml::addCssClass('fade', $this->htmlOptions);
}
if (is_array($this->footer)) {
$this->footer = implode('&nbsp;', $this->footer);
}
$this->initOptions();
$this->initEvents();
}
/**
* Initialize events if any
*/
public function initEvents()
{
foreach (array('onShow', 'onShown', 'onHide', 'onHidden') as $event) {
if ($this->$event !== null) {
$modalEvent = strtolower(substr($event, 2));
if ($this->$event instanceof CJavaScriptExpression) {
$this->events[$modalEvent] = $this->$event;
} else {
$this->events[$modalEvent] = new CJavaScriptExpression($this->$event);
}
}
}
}
/**
* Initialize plugin options.
* ***Important***: The display of the button overrides the initialization of the modal bootstrap widget.
*/
public function initOptions()
{
if ($remote = TbArray::popValue('remote', $this->options)) {
$this->options['remote'] = CHtml::normalizeUrl($remote);
}
TbArray::defaultValue('backdrop', $this->backdrop, $this->options);
TbArray::defaultValue('keyboard', $this->keyboard, $this->options);
TbArray::defaultValue('show', $this->show, $this->options);
}
/**
* Widget's run method
*/
public function run()
{
$this->renderModal();
$this->renderButton();
$this->registerClientScript();
}
/**
* Renders the button
*/
public function renderButton()
{
if (!empty($this->buttonOptions) && is_array($this->buttonOptions)) {
TbArray::defaultValue('data-toggle', 'modal', $this->buttonOptions);
if ($this->remote !== null) {
$this->buttonOptions['data-remote'] = CHtml::normalizeUrl($this->remote);
}
$selector = '#' . $this->htmlOptions['id'];
$label = TbArray::popValue('label', $this->buttonOptions, 'button');
$attr = isset($this->buttonOptions['data-remote']) ? 'data-target' : 'href';
TbArray::defaultValue($attr, $selector, $this->buttonOptions);
echo TbHtml::button($label, $this->buttonOptions);
}
}
/**
* Renders the modal markup
*/
public function renderModal()
{
echo TbHtml::openTag('div', $this->htmlOptions) . PHP_EOL;
$this->renderModalHeader();
$this->renderModalBody();
$this->renderModalFooter();
echo '</div>' . PHP_EOL;
}
/**
* Renders the header HTML markup of the modal
*/
public function renderModalHeader()
{
echo '<div class="modal-header">' . PHP_EOL;
if ($this->closeText) {
echo TbHtml::closeButton($this->closeText, array('data-dismiss' => 'modal'));
}
echo TbHtml::tag('h3', array(), $this->header);
echo '</div>' . PHP_EOL;
}
/**
* Renders the HTML markup for the body of the modal
*/
public function renderModalBody()
{
echo '<div class="modal-body">' . PHP_EOL;
echo $this->content;
echo '</div>' . PHP_EOL;
}
/**
* Renders the HTML markup for the footer of the modal
*/
public function renderModalFooter()
{
echo '<div class="modal-footer">' . PHP_EOL;
echo $this->footer;
echo '</div>' . PHP_EOL;
}
/**
* Registers necessary client scripts.
*/
public function registerClientScript()
{
$selector = '#' . $this->htmlOptions['id'];
// do we render a button? If so, bootstrap will handle its behavior through its
// mark-up, otherwise, register the plugin.
if (empty($this->buttonOptions)) {
$this->registerPlugin(TbApi::PLUGIN_MODAL, $selector, $this->options);
}
$this->registerEvents($selector, $this->events);
}
}

View File

@@ -0,0 +1,171 @@
<?php
/**
* TbNav class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap navigation menu widget.
* @see http://twitter.github.com/bootstrap/components.html#navbar
*/
class TbNav extends CWidget
{
/**
* @var string the menu type.
*/
public $type;
/**
* @var boolean whether the menu items should be stacked on top of each other.
*/
public $stacked = false;
/**
* @var string|array the scrollspy target or configuration.
*/
public $scrollspy;
/**
* @var array list of menu items. Each menu item is specified as an array of name-value pairs.
*/
public $items = array();
/**
* @var boolean whether the labels for menu items should be HTML-encoded. Defaults to true.
*/
public $encodeLabel = true;
/**
* @var boolean whether to automatically activate items according to whether their route setting
* matches the currently requested route. Defaults to true.
*/
public $activateItems = true;
/**
* @var boolean whether to activate parent menu items when one of the corresponding child menu items is active.
*/
public $activateParents = false;
/**
* @var boolean whether to hide empty menu items.
*/
public $hideEmptyItems = true;
/**
* @var array HTML attributes for the menu's root container tag.
*/
public $htmlOptions = array();
// todo: consider supporting these.
//public $submenuHtmlOptions = array();
//public $linkLabelWrapper;
//public $linkLabelWrapperHtmlOptions=array();
//public $itemCssClass;
/**
* Initializes the widget.
*/
public function init()
{
$this->attachBehavior('TbWidget', new TbWidget);
$this->copyId();
$route = $this->controller->getRoute();
if ($this->stacked) {
TbHtml::addCssClass('nav-stacked', $this->htmlOptions);
}
if (isset($this->scrollspy)) {
if (is_string($this->scrollspy)) {
$this->scrollspy = array('target' => $this->scrollspy);
}
$this->widget('bootstrap.widgets.TbScrollspy', $this->scrollspy);
}
$this->items = $this->normalizeItems($this->items, $route, $hasActiveChild);
}
/**
* Runs the widget.
*/
public function run()
{
if (!empty($this->items)) {
echo TbHtml::nav($this->type, $this->items, $this->htmlOptions);
}
}
/**
* Normalizes the menu items.
* @param array $items the items to be normalized.
* @param string $route the route of the current request.
* @param boolean $active whether there is an active child menu item.
* @return array the normalized menu items.
*/
protected function normalizeItems($items, $route, &$active)
{
foreach ($items as $i => $item) {
// skip dividers
if (is_string($item)) {
continue;
}
if (isset($item['visible']) && !$item['visible']) {
unset($items[$i]);
continue;
}
TbArray::defaultValue('label', '', $item);
if ($this->encodeLabel) {
$items[$i]['label'] = CHtml::encode($item['label']);
}
$hasActiveChild = false;
if (isset($item['items']) && !empty($item['items'])) {
$items[$i]['items'] = $this->normalizeItems($item['items'], $route, $hasActiveChild);
if (empty($items[$i]['items']) && $this->hideEmptyItems) {
unset($items[$i]['items']);
if (!isset($item['url'])) {
unset($items[$i]);
continue;
}
}
}
if (!isset($item['active'])) {
if ($this->activateParents && $hasActiveChild || $this->activateItems && $this->isItemActive(
$item,
$route
)
) {
$active = $items[$i]['active'] = true;
} else {
$items[$i]['active'] = false;
}
} else {
if ($item['active']) {
$active = true;
}
}
}
return array_values($items);
}
/**
* Checks whether a menu item is active.
* @param array $item the menu item to be checked.
* @param string $route the route of the current request.
* @return boolean whether the menu item is active.
*/
protected function isItemActive($item, $route)
{
if (isset($item['url']) && is_array($item['url']) && !strcasecmp(trim($item['url'][0], '/'), $route)) {
unset($item['url']['#']);
if (count($item['url']) > 1) {
foreach (array_splice($item['url'], 1) as $name => $value) {
if (!isset($_GET[$name]) || $_GET[$name] != $value) {
return false;
}
}
}
return true;
}
return false;
}
}

View File

@@ -0,0 +1,129 @@
<?php
/**
* TbNavbar class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap navbar widget.
* @see http://twitter.github.com/bootstrap/components.html#navbar
*/
class TbNavbar extends CWidget
{
/**
* @var string the navbar color.
*/
public $color;
/**
* @var string the brand label text.
*/
public $brandLabel;
/**
* @var mixed the brand url.
*/
public $brandUrl;
/**
* @var array the HTML attributes for the brand link.
*/
public $brandOptions = array();
/**
* @var string nanvbar display type.
*/
public $display = TbHtml::NAVBAR_DISPLAY_FIXEDTOP;
/**
* @var boolean whether the navbar spans over the whole page.
*/
public $fluid = false;
/**
* @var boolean whether to enable collapsing of the navbar on narrow screens.
*/
public $collapse = false;
/**
* @var array additional HTML attributes for the collapse widget.
*/
public $collapseOptions = array();
/**
* @var array list of navbar item.
*/
public $items = array();
/**
* @var array the HTML attributes for the navbar.
*/
public $htmlOptions = array();
/**
* Initializes the widget.
*/
public function init()
{
if ($this->brandLabel !== false) {
if (!isset($this->brandLabel)) {
$this->brandLabel = CHtml::encode(Yii::app()->name);
}
if (!isset($this->brandUrl)) {
$this->brandUrl = Yii::app()->homeUrl;
}
}
if (isset($this->color)) {
TbArray::defaultValue('color', $this->color, $this->htmlOptions);
}
if (isset($this->display) && $this->display !== TbHtml::NAVBAR_DISPLAY_NONE) {
TbArray::defaultValue('display', $this->display, $this->htmlOptions);
}
}
/**
* Runs the widget.
*/
public function run()
{
$brand = $this->brandLabel !== false
? TbHtml::navbarBrandLink($this->brandLabel, $this->brandUrl, $this->brandOptions)
: '';
ob_start();
foreach ($this->items as $item) {
if (is_string($item)) {
echo $item;
} else {
$widgetClassName = TbArray::popValue('class', $item);
if ($widgetClassName !== null) {
$this->controller->widget($widgetClassName, $item);
}
}
}
$items = ob_get_clean();
ob_start();
if ($this->collapse !== false) {
TbHtml::addCssClass('nav-collapse', $this->collapseOptions);
ob_start();
/* @var TbCollapse $collapseWidget */
$collapseWidget = $this->controller->widget(
'bootstrap.widgets.TbCollapse',
array(
'toggle' => false, // navbars are collapsed by default
'content' => $items,
'htmlOptions' => $this->collapseOptions,
)
);
$collapseContent = ob_get_clean();
echo TbHtml::navbarCollapseLink('#' . $collapseWidget->getId());
echo $brand . $collapseContent;
} else {
echo $brand . $items;
}
$containerContent = ob_get_clean();
$containerOptions = TbArray::popValue('containerOptions', $this->htmlOptions, array());
TbHtml::addCssClass($this->fluid ? 'container-fluid' : 'container', $containerOptions);
ob_start();
echo TbHtml::openTag('div', $containerOptions);
echo $containerContent;
echo '</div>';
$content = ob_get_clean();
echo TbHtml::navbar($content, $this->htmlOptions);
}
}

View File

@@ -0,0 +1,158 @@
<?php
/**
* TbPager class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap pager widget.
* http://twitter.github.com/bootstrap/components.html#pagination
*/
class TbPager extends CBasePager
{
/**
* @var string the pager size.
*/
public $size;
/**
* @var integer maximum number of page buttons that can be displayed.
*/
public $maxButtonCount = 5;
/**
* @var string the text label for the next page button.
*/
public $nextPageLabel = '&rsaquo;';
/**
* @var string the text label for the previous page button.
*/
public $prevPageLabel = '&lsaquo;';
/**
* @var string the text label for the first page button.
*/
public $firstPageLabel = '&laquo;';
/**
* @var string the text label for the last page button.
*/
public $lastPageLabel = '&raquo;';
/**
* @var boolean whether the "first" and "last" buttons should be hidden.
* Defaults to false.
*/
public $hideFirstAndLast = false;
/**
* @var array HTML attributes for the pager container tag.
*/
public $htmlOptions = array();
/**
* Initializes the widget.
*/
public function init()
{
$this->attachBehavior('TbWidget', new TbWidget);
$this->copyId();
if (isset($this->size)) {
TbArray::defaultValue('size', $this->size, $this->htmlOptions);
}
}
/**
* Runs the widget.
*/
public function run()
{
$links = $this->createPageLinks();
if (!empty($links)) {
echo TbHtml::pagination($links, $this->htmlOptions);
}
}
/**
* Creates the page buttons.
* @return array a list of page buttons (in HTML code).
*/
protected function createPageLinks()
{
if (($pageCount = $this->getPageCount()) <= 1) {
return array();
}
list($beginPage, $endPage) = $this->getPageRange();
$currentPage = $this->getCurrentPage(false); // currentPage is calculated in getPageRange()
$links = array();
// first page
if (!$this->hideFirstAndLast) {
$links[] = $this->createPageLink($this->firstPageLabel, 0, $currentPage <= 0, false);
}
// prev page
if (($page = $currentPage - 1) < 0) {
$page = 0;
}
$links[] = $this->createPageLink($this->prevPageLabel, $page, $currentPage <= 0, false);
// internal pages
for ($i = $beginPage; $i <= $endPage; ++$i) {
$links[] = $this->createPageLink($i + 1, $i, false, $i == $currentPage);
}
// next page
if (($page = $currentPage + 1) >= $pageCount - 1) {
$page = $pageCount - 1;
}
$links[] = $this->createPageLink($this->nextPageLabel, $page, $currentPage >= $pageCount - 1, false);
// last page
if (!$this->hideFirstAndLast) {
$links[] = $this->createPageLink(
$this->lastPageLabel,
$pageCount - 1,
$currentPage >= $pageCount - 1,
false
);
}
return $links;
}
/**
* Creates a page link.
* @param string $label the link label text.
* @param integer $page the page number.
* @param boolean $visible whether the link is disabled.
* @param boolean $active whether the link is active.
* @return string the generated link.
*/
protected function createPageLink($label, $page, $disabled, $active)
{
return array(
'label' => $label,
'url' => $this->createPageUrl($page),
'disabled' => $disabled,
'active' => $active,
);
}
/**
* @return array the begin and end pages that need to be displayed.
*/
protected function getPageRange()
{
$currentPage = $this->getCurrentPage();
$pageCount = $this->getPageCount();
$beginPage = max(0, $currentPage - (int)($this->maxButtonCount / 2));
if (($endPage = $beginPage + $this->maxButtonCount - 1) >= $pageCount) {
$endPage = $pageCount - 1;
$beginPage = max(0, $endPage - $this->maxButtonCount + 1);
}
return array($beginPage, $endPage);
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* TbScrollspy class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap scrollspy widget.
* @see http://twitter.github.com/bootstrap/javascript.html#scrollspy
*/
class TbScrollspy extends CWidget
{
/**
* @var string the CSS selector for the scrollspy element.
*/
public $selector = 'body';
/**
* @var string the CSS selector for the spying element.
*/
public $target;
/**
* @var integer the scroll offset (in pixels).
*/
public $offset;
/**
* @var string[] $events the JavaScript event configuration (name=>handler).
*/
public $events = array();
/**
* Initializes the widget.
*/
public function init()
{
$this->attachBehavior('TbWidget', new TbWidget);
}
/**
* Runs the widget.
*/
public function run()
{
// todo: think of a better way of doing this.
$script = "jQuery('{$this->selector}').attr('data-spy', 'scroll');";
if (isset($this->target)) {
$script .= "jQuery('{$this->selector}').attr('data-target', '{$this->target}');";
}
if (isset($this->offset)) {
$script .= "jQuery('{$this->selector}').attr('data-offset', '{$this->offset}');";
}
Yii::app()->clientScript->registerScript($this->getId(), $script, CClientScript::POS_BEGIN);
$this->registerEvents($this->selector, $this->events);
}
}

View File

@@ -0,0 +1,125 @@
<?php
/**
* TbTabs class file.
* @author Antonio Ramirez <ramirez.cobos@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap tabs widget.
*/
class TbTabs extends CWidget
{
/**
* @var string the type of tabs to display. Valid values are 'tabs' and 'pills' (defaults to 'tabs').
* @see TbHtml::$navStyles
*/
public $type = TbHtml::NAV_TYPE_TABS;
/**
* @var string the placement of the tabs. Valid values are 'right, 'left' and 'below'.
* @see TbHtml::tabPlacements
*/
public $placement;
/**
* @var array the tab configuration.
*/
public $tabs = array();
/**
* @var array additional data submitted to the views.
*/
public $viewData;
/**
* @var string a javascript function that This event fires on tab show, but before the new tab has been shown.
* Use `event.target` and `event.relatedTarget` to target the active tab and the previous active tab (if available)
* respectively.
*/
public $onShow;
/**
* @var string a javascript function that fires on tab show after a tab has been shown. Use `event.target` and
* `event.relatedTarget` to target the active tab and the previous active tab (if available) respectively.
*/
public $onShown;
/**
* @var array the HTML attributes for the widget container.
*/
public $htmlOptions = array();
/**
* @var string[] the Javascript event handlers.
*/
protected $events = array();
/**
* Widget's initialization method
*/
public function init()
{
$this->attachBehavior('TbWidget', new TbWidget);
$this->copyId();
TbArray::defaultValue('placement', $this->placement, $this->htmlOptions);
$this->initEvents();
}
/**
* Initialize events if any
*/
public function initEvents()
{
foreach (array('onShow', 'onShown') as $event) {
if ($this->$event !== null) {
$modalEvent = strtolower(substr($event, 2));
if ($this->$event instanceof CJavaScriptExpression) {
$this->events[$modalEvent] = $this->$event;
} else {
$this->events[$modalEvent] = new CJavaScriptExpression($this->$event);
}
}
}
}
/**
* Widget's run method
*/
public function run()
{
$this->tabs = $this->normalizeTabs($this->tabs);
echo TbHtml::tabbable($this->type, $this->tabs, $this->htmlOptions);
$this->registerClientScript();
}
/**
* Normalizes the tab configuration.
* @param array $tabs a reference to the tabs tab configuration.
*/
protected function normalizeTabs($tabs)
{
$controller = $this->getController();
if (isset($controller)) {
foreach ($tabs as &$tabOptions) {
$items = TbArray::getValue('items', $tabOptions, array());
if (!empty($items)) {
$tabOptions['items'] = $this->normalizeTabs($items);
} else {
if (isset($tabOptions['view'])) {
$view = TbArray::popValue('view', $tabOptions);
if ($controller->getViewFile($view) !== false) {
$tabOptions['content'] = $controller->renderPartial($view, $this->viewData, true);
}
}
}
}
}
return $tabs;
}
/**
* Registers necessary client scripts.
*/
public function registerClientScript()
{
$selector = '#' . $this->htmlOptions['id'];
Yii::app()->clientScript->registerScript(__CLASS__ . $selector, "jQuery('{$selector}').tab('show');");
$this->registerEvents($selector, $this->events);
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* TbThumbnails class file.
* @author Christoffer Niska <christoffer.niska@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap thumbnails widget.
* http://twitter.github.com/bootstrap/components.html#thumbnails
*/
class TbThumbnails extends TbListView
{
/**
* @var mixed a PHP expression that is evaluated for every item and whose result is used
* as the URL for the thumbnail.
*/
public $url;
/**
* @var integer the number of grid columns that the thumbnails spans over.
*/
public $span;
/**
* Initializes the widget
*/
public function init()
{
parent::init();
if (isset($this->itemsCssClass)) {
TbHtml::addCssClass($this->itemsCssClass, $this->htmlOptions);
}
}
/**
* Renders the data items for the view.
* Each item is corresponding to a single data model instance.
*/
public function renderItems()
{
$thumbnails = array();
$data = $this->dataProvider->getData();
if (!empty($data)) {
$owner = $this->getOwner();
$render = $owner instanceof CController ? 'renderPartial' : 'render';
foreach ($data as $i => $row) {
$thumbnail = array();
$d = $this->viewData;
$d['index'] = $i;
$d['data'] = $row;
$d['widget'] = $this;
$thumbnail['caption'] = $owner->$render($this->itemView, $d, true);
if (isset($this->url)) {
$thumbnail['url'] = $this->evaluateExpression($this->url, array('data' => $row));
}
if (isset($this->span)) {
$thumbnail['span'] = $this->span;
}
$thumbnails[] = $thumbnail;
}
echo TbHtml::thumbnails($thumbnails, $this->htmlOptions);
} else {
$this->renderEmptyText();
}
}
}

View File

@@ -0,0 +1,134 @@
<?php
/**
* TbModal class file.
* @author Antonio Ramirez <ramirez.cobos@gmail.com>
* @copyright Copyright &copy; Christoffer Niska 2013-
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @package bootstrap.widgets
*/
/**
* Bootstrap typeahead widget.
*/
class TbTypeAhead extends CInputWidget
{
/**
* @var mixed the data source to query against. May be an array of strings or a function. The function is passed
* two arguments, the query value in the input field and the process callback. The function may be used synchronously
* by returning the data source directly or asynchronously via the process callback's single argument.
*/
public $source = array();
/**
* @var int the max number of items to display in the dropdown. Defaults to 8.
*/
public $items = 8;
/**
* @var int the minimum character length needed before triggering autocomplete suggestions
*/
public $minLength = 1;
/**
* @var string javascript function the method used to determine if a query matches an item. Accepts a single argument, the item
* against which to test the query. Access the current query with this.query. Return a boolean true if query is a
* match. Case insensitive.
*/
public $matcher;
/**
* @var string javascript function method used to sort autocomplete results. Accepts a single argument items and has
* the scope of the typeahead instance. Reference the current query with this.query. Exact match, case sensitive,
* case insensitive
*/
public $sorter;
/**
* @var string javascript the method used to return selected item. Accepts a single argument, the item and has the
* scope of the typeahead instance. Returns selected item.
*/
public $updater;
/**
* @var string javascript method used to highlight autocomplete results. Accepts a single argument item and has the
* scope of the typeahead instance. Should return html. Highlights all default matches
*/
public $highlighter;
/**
* @var array the plugin options
*/
protected $pluginOptions = array();
/**
* Widget's initialization method.
*/
public function init()
{
$this->attachBehavior('TbWidget', new TbWidget);
$this->initOptions();
}
/**
* Initializes the plugin options
*/
public function initOptions()
{
$options = array();
foreach (array('matcher', 'sorter', 'updater', 'highlighter') as $fn) {
if ($this->$fn !== null) {
if ($this->$fn instanceof CJavaScriptExpression) {
$options[$fn] = $this->$fn;
} else {
$options[$fn] = new CJavaScriptExpression($this->$fn);
}
}
}
$this->pluginOptions = TbArray::merge(
array(
'source' => $this->source,
'items' => $this->items,
'minLength' => $this->minLength
),
$options
);
}
/**
* Widget's run method.
*/
public function run()
{
$this->renderField();
$this->registerClientScript();
}
/**
* Renders field
*/
public function renderField()
{
list($name, $id) = $this->resolveNameID();
TbArray::defaultValue('id', $id, $this->htmlOptions);
TbArray::defaultValue('name', $name, $this->htmlOptions);
// by using TbHtml we support all bootstrap options
if ($this->hasModel()) {
echo TbHtml::activeTextField($this->model, $this->attribute, $this->htmlOptions);
} else {
echo TbHtml::textField($name, $this->value, $this->htmlOptions);
}
}
/**
* Register required scripts.
*/
public function registerClientScript()
{
/** @var TbApi $api */
$selector = '#' . TbArray::getValue('id', $this->htmlOptions, $this->getId());
$this->registerPlugin(TbApi::PLUGIN_TYPEAHEAD, $selector, $this->pluginOptions);
}
}