Commits

Christoffer Niska committed 463f528

Added plugin registration api and removed automatic CSS registration.

Changed BootInput to abstract and implmented BootInputHorizontal.
Improved BootTabbed.

Comments (0)

Files changed (12)

components/Bootstrap.php

  */
 class Bootstrap extends CApplicationComponent
 {
-	/**
-	 * @var boolean whether to register the Boostrap core CSS.
-	 */
-	public $coreCss = true;
-	/**
-	 * @var boolean whether to register the Bootstrap reponsive CSS.
-	 */
-	public $responsiveCss = true;
-	/**
-	 * @var boolean whether to enable CSS transitions.
-	 * @since 0.9.8
-	 */
-	public $transitions = true;
-	/**
-	 * @var boolean whether to enable scrollspy.
-	 * @see http://twitter.github.com/bootstrap/javascript.html#scrollspy
-	 * @since 0.9.8
-	 */
-	public $scrollspy = true;
+	// The Bootstrap core plugins.
+	const PLUGIN_ALERT = 'alert';
+	const PLUGIN_BUTTON = 'button';
+	const PLUGIN_CAROUSEL = 'carousel';
+	const PLUGIN_COLLAPSE = 'collapse';
+	const PLUGIN_DROPDOWN = 'dropdown';
+	const PLUGIN_MODAL = 'modal';
+	const PLUGIN_POPOVER = 'popover';
+	const PLUGIN_SCROLLSPY = 'scrollspy';
+	const PLUGIN_TAB = 'tab';
+	const PLUGIN_TOOLTIP = 'tooltip';
+	const PLUGIN_TRANSITION = 'transition';
+	const PLUGIN_TYPEAHEAD = 'typeahead';
+
 	/**
 	 * @var array the plugin options (name=>options).
 	 * @since 0.9.8
 	public $plugins = array();
 
 	protected $_assetsUrl;
-	protected $_registeredPlugins = array();
+	protected $_rp = array();
 
 	/**
 	 * Initializes the component.
 		if (!Yii::getPathOfAlias('bootstrap'))
 			Yii::setPathOfAlias('bootstrap', realpath(dirname(__FILE__).'/..'));
 
-		$this->registerCoreScript();
+		Yii::app()->clientScript->registerCoreScript('jquery');
+		$this->registerCorePlugins();
+	}
 
-		if ($this->coreCss)
-			$this->registerCoreCss();
-
-		if ($this->responsiveCss)
-			$this->registerResponsiveCss();
+	/**
+	 * Returns whether a plugin is registered.
+	 * @param string $name the name of the plugin
+	 * @return boolean the result
+	 */
+	public function isPluginRegistered($name)
+	{
+		return isset($this->_rp[$name]);
 	}
 
 	/**
 	}
 
 	/**
-	 * Registers the Bootstrap core JavaScript functionality.
+	 * Registers the core JavaScript plugins.
+	 * @since 0.9.8
 	 */
-	protected function registerCoreScript()
+	protected function registerCorePlugins()
 	{
-		if ($this->transitions)
-			$this->registerScriptFile('bootstrap-transition.js');
+		if (!$this->isPluginDisabled(self::PLUGIN_TRANSITION))
+			$this->enableTransitions();
 
-		$plugins = array('button', 'collapse', 'dropdown', 'tooltip', 'popover');
+		if (!$this->isPluginDisabled(self::PLUGIN_BUTTON))
+			$this->registerButton();
 
-		foreach ($plugins as $name)
-		{
-			if (!isset($this->plugins[$name]) || isset($this->plugins[$name]) && $this->plugins[$name] !== false)
-			{
-				switch ($name)
-				{
-					case 'button':
-						$this->registerButton();
-						break;
+		if (!$this->isPluginDisabled(self::PLUGIN_TOOLTIP))
+			$this->registerTooltip();
 
-					case 'collapse':
-						$this->registerCollapse();
-						break;
+		if (!$this->isPluginDisabled(self::PLUGIN_POPOVER))
+			$this->registerPopover();
+	}
 
-					case 'dropdown':
-						$this->registerDropdown();
-						break;
-
-					case 'tooltip':
-						$this->registerTooltip();
-						break;
-
-					case 'popover':
-						$this->registerPopover();
-						break;
-				}
-			}
-		}
-
-		if ($this->scrollspy)
-			Yii::app()->clientScript->registerScript(__CLASS__.'.scrollspy', "jQuery('body').attr('data-spy', 'scroll');");
+	/**
+	 * Returns whether a plugin is disabled in the plugin configuration.
+	 * @param string $name the name of the plugin
+	 * @return boolean the result
+	 * @since 0.9.8
+	 */
+	protected function isPluginDisabled($name)
+	{
+		return isset($this->plugins[$name]) || (isset($this->plugins[$name]) && $this->plugins[$name] !== false);
 	}
 
 	/**
 	 * Registers a Bootstrap JavaScript plugin.
 	 * @param string $name the name of the plugin
-	 * @param string $defaultSelector the default selector, when null the plugin is not bound to any element.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
+	 * @param string $defaultSelector the default selector to use
 	 * @since 0.9.8
 	 */
-	protected function registerPlugin($name, $defaultSelector = null)
+	protected function registerPlugin($name, $selector = null, $options = array(), $defaultSelector = null)
 	{
 		if (!$this->isPluginRegistered($name))
 		{
 			$this->registerScriptFile("bootstrap-{$name}.js");
-			$options = isset($this->plugins[$name]) ? $this->plugins[$name] : array();
+			$this->_rp[$name] = true;
+		}
 
-			if (isset($options['selector']))
-			{
-				$selector = $options['selector'];
+		if (!isset($selector) && empty($options))
+		{
+			// Initialization from extension configuration.
+			$config = isset($this->plugins[$name]) ? $this->plugins[$name] : array();
 
-				if ($name !== 'tooltip' && $name !== 'popover')
-					unset($options['selector']);
-			}
-			else
+			if (isset($config['selector']))
+				$selector = $config['selector'];
+
+			if (isset($config['options']))
+				$options = $config['options'];
+
+			if (!isset($selector))
 				$selector = $defaultSelector;
+		}
 
-			if ($selector !== null)
-			{
-				$options = !empty($options) ? CJavaScript::encode($options) : '';
-				Yii::app()->clientScript->registerScript(__CLASS__.'.'.$name,
-						"jQuery('{$selector}').{$name}({$options});");
-			}
-
-			$this->_registeredPlugins[$name] = true;
+		if (isset($selector))
+		{
+			$key = __CLASS__.'.'.md5($name.$selector.serialize($options).$defaultSelector);
+			$options = !empty($options) ? CJavaScript::encode($options) : '';
+			Yii::app()->clientScript->registerScript($key, "jQuery('{$selector}').{$name}({$options});");
 		}
 	}
 
 	/**
+	 * Enables the Bootstrap transitions plugin.
+	 * @since 0.9.8
+	 */
+	public function enableTransitions()
+	{
+		$this->registerPlugin(self::PLUGIN_TRANSITION);
+	}
+
+	/**
+	 * Registers the Bootstrap alert plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
+	 * @see http://twitter.github.com/bootstrap/javascript.html#alerts
+	 * @since 0.9.8
+	 */
+	public function registerAlert($selector = null, $options = array())
+	{
+		$this->registerPlugin(self::PLUGIN_ALERT, $selector, $options);
+	}
+
+	/**
 	 * Registers the Bootstrap buttons plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
 	 * @see http://twitter.github.com/bootstrap/javascript.html#buttons
 	 * @since 0.9.8
 	 */
-	protected function registerButton()
+	public function registerButton($selector = null, $options = array())
 	{
-		$this->registerPlugin('button');
+		$this->registerPlugin(self::PLUGIN_BUTTON, $selector, $options);
+	}
+
+	/**
+	 * Registers the Bootstrap carousel plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
+	 * @see http://twitter.github.com/bootstrap/javascript.html#carousel
+	 * @since 0.9.8
+	 */
+	public function registerCarousel($selector = null, $options = array())
+	{
+		$this->registerPlugin(self::PLUGIN_CAROUSEL, $selector, $options);
 	}
 
 	/**
 	 * Registers the Bootstrap collapse plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
 	 * @see http://twitter.github.com/bootstrap/javascript.html#collapse
 	 * @since 0.9.8
 	 */
-	protected function registerCollapse()
+	public function registerCollapse($selector = null, $options = array())
 	{
-		$this->registerPlugin('collapse', '.collapse');
+		$this->registerPlugin(self::PLUGIN_COLLAPSE, $selector, $options, '.collapse');
 	}
 
 	/**
-	 * Registers the Bootstrap dropdown plugin.
+	 * Registers the Bootstrap dropdowns plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
 	 * @see http://twitter.github.com/bootstrap/javascript.html#dropdowns
 	 * @since 0.9.8
 	 */
-	protected function registerDropdown()
+	public function registerDropdown($selector = null, $options = array())
 	{
-		$this->registerPlugin('dropdown', '.dropdown-toggle');
+		$this->registerPlugin(self::PLUGIN_DROPDOWN, $selector, $options, '.dropdown-toggle[data-dropdown="dropdown"]');
+	}
+
+	/**
+	 * Registers the Bootstrap modal plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
+	 * @see http://twitter.github.com/bootstrap/javascript.html#modal
+	 * @since 0.9.8
+	 */
+	public function registerModal($selector = null, $options = array())
+	{
+		$this->registerPlugin(self::PLUGIN_MODAL, $selector, $options);
+	}
+
+	/**
+	 * Registers the Bootstrap scrollspy plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
+	 * @see http://twitter.github.com/bootstrap/javascript.html#scrollspy
+	 * @since 0.9.8
+	 */
+	public function registerScrollSpy($selector = null, $options = array())
+	{
+		$this->registerPlugin(self::PLUGIN_SCROLLSPY, $selector, $options);
+
+		if (!isset($selector))
+		{
+			$selector = isset($this->plugins[self::PLUGIN_SCROLLSPY], $this->plugins[self::PLUGIN_SCROLLSPY]['selector'])
+					? $this->plugins[self::PLUGIN_SCROLLSPY]['selector']
+					: 'body';
+		}
+
+		Yii::app()->clientScript->registerScript(__CLASS__.'.scrollspy', "jQuery({$selector}).attr('data-spy', 'scroll');");
+	}
+
+	/**
+	 * Registers the Bootstrap popover plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
+	 * @see http://twitter.github.com/bootstrap/javascript.html#popover
+	 * @since 0.9.8
+	 */
+	public function registerPopover($selector = null, $options = array())
+	{
+		$this->registerTooltip(); // Popover requires the tooltip plugin
+		$this->registerPlugin(self::PLUGIN_POPOVER, $selector, $options, 'a[rel="popover"]');
+	}
+
+	/**
+	 * Registers the Bootstrap tabs plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
+	 * @see http://twitter.github.com/bootstrap/javascript.html#tabs
+	 * @since 0.9.8
+	 */
+	public function registerTabs($selector = null, $options = array())
+	{
+		$this->registerPlugin(self::PLUGIN_TAB, $selector, $options);
 	}
 
 	/**
 	 * Registers the Bootstrap tooltip plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
 	 * @see http://twitter.github.com/bootstrap/javascript.html#tooltip
 	 * @since 0.9.8
 	 */
-	protected function registerTooltip()
+	public function registerTooltip($selector = null, $options = array())
 	{
-		$this->registerPlugin('tooltip', 'a[rel="tooltip"]');
+		$this->registerPlugin(self::PLUGIN_TOOLTIP, $selector, $options, 'a[rel="tooltip"]');
 	}
 
 	/**
-	 * Registers the Bootstrap popover plugin.
-	 * @see http://twitter.github.com/bootstrap/javascript.html#popover
+	 * Registers the Bootstrap typeahead plugin.
+	 * @param string $selector the CSS selector
+	 * @param array $options the plugin options
+	 * @see http://twitter.github.com/bootstrap/javascript.html#typeahead
 	 * @since 0.9.8
 	 */
-	protected function registerPopover()
+	public function registerTypeAHead($selector = null, $options = array())
 	{
-		$this->registerTooltip(); // Popover requires the tooltip plugin
-		$this->registerPlugin('popover', 'a[rel="popover"]');
-	}
-
-	public function isPluginRegistered($name)
-	{
-		return isset($this->_registeredPlugins[$name]);
+		$this->registerPlugin(self::PLUGIN_TYPEAHEAD, $selector, $options);
 	}
 
 	/**
 	 * @param string $fileName the file name.
      * @param integer $position the position of the JavaScript file.
 	 */
-	public function registerScriptFile($fileName, $position=CClientScript::POS_END)
+	protected function registerScriptFile($fileName, $position=CClientScript::POS_END)
 	{
 		Yii::app()->clientScript->registerScriptFile($this->getAssetsUrl().'/js/'.$fileName, $position);
 	}

demo/protected/config/main.php

 	'components'=>array(
 		'bootstrap'=>array(
 			'class'=>'bootstrap.components.Bootstrap',
-			'coreCss'=>false,
-			'responsiveCss'=>false,
 		),
 		'errorHandler'=>array(
 			'errorAction'=>'site/error',

demo/protected/views/layouts/main.php

 
 <?php $this->widget('BootNavbar',array(
 	'brand'=>CHtml::encode(Yii::app()->name),
+	'collapse'=>true,
 	'items'=>array(
 		array(
 			'class'=>'bootstrap.widgets.BootMenu',

demo/protected/views/site/index.php

 				'fixed'=>false,
 				'brand'=>'Project name',
 				'brandUrl'=>'#',
+				'collapse'=>true, // requires bootstrap-responsive.css
 				'items'=>array(
 					array(
 						'class'=>'bootstrap.widgets.BootMenu',
 	'fixed'=>false,
 	'brand'=>'Project name',
 	'brandUrl'=>'#',
+	'collapse'=>true, // requires bootstrap-responsive.css
 	'items'=>array(
 		array(
 			'class'=>'bootstrap.widgets.BootMenu',

widgets/BootActiveForm.php

 	// The different form types.
 	const TYPE_VERTICAL = 'form-vertical';
 	const TYPE_INLINE = 'form-inline';
-	const TYPE_SEARCH = 'form-search';
 	const TYPE_HORIZONTAL = 'form-horizontal';
 
+	const INPUT_HORIZONTAL = 'bootstrap.widgets.BootInputHorizontal';
+	const INPUT_INLINE = 'bootstrap.widgets.BootInputInline';
+	const INPUT_VERTICAL = 'bootstrap.widgets.BootInputVertical';
+
 	/**
 	 * @var string the form type. See class constants.
 	 */
 	 */
 	public function inputRow($type, $model, $attribute, $data = null, $htmlOptions = array())
 	{
+		// Determine the input widget class name.
+		switch ($this->type)
+		{
+			case self::TYPE_INLINE:
+			case self::TYPE_HORIZONTAL:
+			case self::TYPE_VERTICAL:
+			default:
+				$className = self::INPUT_HORIZONTAL;
+				break;
+
+			/*
+			case self::TYPE_INLINE:
+				$className = self::INPUT_INLINE;
+				break;
+
+			case self::TYPE_VERTICAL:
+			default:
+				$className = self::INPUT_VERTICAL;
+				break;
+			*/
+
+		}
+
 		ob_start();
-		Yii::app()->controller->widget('BootInput',array(
+		Yii::app()->controller->widget($className, array(
 			'type'=>$type,
 			'form'=>$this,
 			'model'=>$model,

widgets/BootAlert.php

 	/**
 	 * @var string the template to use for displaying flash messages.
 	 */
-	public $template = '<div class="alert alert-block alert-{key} fade in"><a class="close" data-dismiss="alert">&times;</a>{message}</div>';
+	public $template = '<div class="alert alert-block alert-{key}{class}"><a class="close" data-dismiss="alert">&times;</a>{message}</div>';
 	/**
 	 * @var array the html options.
 	 */
 	public function init()
 	{
 		parent::init();
-		$this->registerScriptFile('bootstrap-alert.js');
-		$this->htmlOptions['id'] = $this->getId();
+
+		Yii::app()->bootstrap->registerAlert();
+
+		if (!isset($this->htmlOptions['id']))
+			$this->htmlOptions['id'] = $this->getId();
 	}
 
 	/**
 
 		echo CHtml::openTag('div', $this->htmlOptions);
 
+		$transitions = Yii::app()->bootstrap->isPluginRegistered(Bootstrap::PLUGIN_TRANSITION);
+
 		foreach ($this->keys as $key)
 		{
 			if (Yii::app()->user->hasFlash($key))
-				echo strtr($this->template, array('{key}'=>$key, '{message}'=>Yii::app()->user->getFlash($key)));
+			{
+				echo strtr($this->template, array(
+					'{class}'=>$transitions ? ' fade in' : '',
+					'{key}'=>$key,
+					'{message}'=>Yii::app()->user->getFlash($key),
+				));
+			}
 		}
 
 		echo '</div>';

widgets/BootInput.php

 <?php
 /**
- * BootInputBlock class file.
+ * BootInput class file.
  * @author Christoffer Niska <ChristofferNiska@gmail.com>
  * @copyright Copyright &copy; Christoffer Niska 2011-
  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
 
 /**
  * Bootstrap input widget.
- * Used for rendering inputs with boostrap standards.
+ * Used for rendering inputs according to Bootstrap standards.
+ * @todo Implement BootInputInline and BootInputVertical. http://twitter.github.com/bootstrap/base-css.html#forms
  */
-class BootInput extends CInputWidget
+abstract class BootInput extends CInputWidget
 {
 	// The different input types.
 	const TYPE_CHECKBOX = 'checkbox';
 	/**
 	 * Renders a checkbox.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function checkBox()
-	{
-		echo '<div class="controls">';
-		echo '<label class="checkbox" for="'.CHtml::getIdByName(CHtml::resolveName($this->model, $this->attribute)).'">';
-		echo $this->form->checkBox($this->model, $this->attribute, $this->htmlOptions).PHP_EOL;
-		echo $this->model->getAttributeLabel($this->attribute);
-		echo $this->getError().$this->getHint();
-		echo '</label></div>';
-	}
+	abstract protected function checkBox();
 
 	/**
 	 * Renders a list of checkboxes.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function checkBoxList()
-	{
-		echo $this->getLabel().'<div class="controls">';
-		echo $this->form->checkBoxList($this->model, $this->attribute, $this->data, $this->htmlOptions);
-		echo $this->getError().$this->getHint();
-		echo '</div>';
-	}
+	abstract protected function checkBoxList();
 
 	/**
 	 * Renders a list of inline checkboxes.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function checkBoxListInline()
-	{
-		$this->htmlOptions['inline'] = true;
-		$this->checkBoxList();
-	}
+	abstract protected function checkBoxListInline();
 
 	/**
 	 * Renders a drop down list (select).
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function dropDownList()
-	{
-		echo $this->getLabel().'<div class="controls">';
-		echo $this->form->dropDownList($this->model, $this->attribute, $this->data, $this->htmlOptions);
-		echo $this->getError().$this->getHint();
-		echo '</div>';
-	}
+	abstract protected function dropDownList();
 
 	/**
 	 * Renders a file field.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function fileField()
-	{
-		echo $this->getLabel().'<div class="controls">';
-		echo $this->form->fileField($this->model, $this->attribute, $this->htmlOptions);
-		echo $this->getError().$this->getHint();
-		echo '</div>';
-	}
+	abstract protected function fileField();
 
 	/**
 	 * Renders a password field.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function passwordField()
-	{
-		echo $this->getLabel().'<div class="controls">';
-		echo $this->form->passwordField($this->model, $this->attribute, $this->htmlOptions);
-		echo $this->getError().$this->getHint();
-		echo '</div>';
-	}
+	abstract protected function passwordField();
 
 	/**
 	 * Renders a radio button.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function radioButton()
-	{
-		echo '<div class="controls">';
-		echo '<label class="radio" for="'.CHtml::getIdByName(CHtml::resolveName($this->model, $this->attribute)).'">';
-		echo $this->form->radioButton($this->model, $this->attribute, $this->htmlOptions).PHP_EOL;
-		echo $this->model->getAttributeLabel($this->attribute);
-		echo $this->getError().$this->getHint();
-		echo '</label></div>';
-	}
+	abstract protected function radioButton();
 
 	/**
 	 * Renders a list of radio buttons.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function radioButtonList()
-	{
-		echo $this->getLabel().'<div class="controls">';
-		echo $this->form->radioButtonList($this->model, $this->attribute, $this->data, $this->htmlOptions);
-		echo $this->getError().$this->getHint();
-		echo '</div>';
-	}
+	abstract protected function radioButtonList();
 
 	/**
 	 * Renders a list of inline radio buttons.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function radioButtonListInline()
-	{
-		$this->htmlOptions['inline'] = true;
-		$this->radioButtonList();
-	}
+	abstract protected function radioButtonListInline();
 
 	/**
 	 * Renders a textarea.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function textArea()
-	{
-		echo $this->getLabel().'<div class="controls">';
-		echo $this->form->textArea($this->model, $this->attribute, $this->htmlOptions);
-		echo $this->getError().$this->getHint();
-		echo '</div>';
-	}
+	abstract protected function textArea();
 
 	/**
 	 * Renders a text field.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function textField()
-	{
-		echo $this->getLabel().'<div class="controls">';
-		echo $this->form->textField($this->model, $this->attribute, $this->htmlOptions);
-		echo $this->getError().$this->getHint();
-		echo '</div>';
-	}
+	abstract protected function textField();
 
 	/**
 	 * Renders a CAPTCHA.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function captcha()
-	{
-		echo $this->getLabel().'<div class="controls"><div class="captcha">';
-		echo '<div class="widget">'.$this->widget('CCaptcha', array('showRefreshButton'=>false), true).'</div>';
-		echo $this->form->textField($this->model, $this->attribute, $this->htmlOptions);
-		echo $this->getError().$this->getHint();
-		echo '</div></div>';
-	}
+	abstract protected function captcha();
 
 	/**
 	 * Renders an uneditable field.
 	 * @return string the rendered content
+	 * @abstract
 	 */
-	protected function uneditableField()
-	{
-		echo $this->getLabel().'<div class="controls">';
-		echo '<span class="uneditable-input">'.$this->model->{$this->attribute}.'</span>';
-		echo $this->getError().$this->getHint();
-		echo '</div>';
-	}
+	abstract protected function uneditableField();
 
 	/**
 	 * Returns the label for this block.
 	 * @return string the label
+	 * @abstract
 	 */
-	protected function getLabel()
-	{
-		if ($this->label !== false && !in_array($this->type, array('checkbox', 'radio')) && $this->hasModel())
-			return $this->form->labelEx($this->model, $this->attribute);
-		else if ($this->label !== null)
-			return $this->label;
-		else
-			return '';
-	}
+	abstract protected function getLabel();
 
 	/**
 	 * Returns the hint text for this block.
 	 * @return string the hint text
+	 * @abstract
 	 */
-	protected function getHint()
-	{
-		if (isset($this->htmlOptions['hint']))
-		{
-			$hint = $this->htmlOptions['hint'];
-			unset($this->htmlOptions['hint']);
-			return '<p class="help-block">'.$hint.'</p>';
-		}
-		else
-			return '';
-	}
+	abstract protected function getHint();
 
 	/**
 	 * Returns the error text for this block.
 	 * @return string the error text
+	 * @abstract
 	 */
-	protected function getError()
-	{
-		return $this->form->error($this->model, $this->attribute);
-	}
+	abstract protected function getError();
 }

widgets/BootInputHorizontal.php

+<?php
+/**
+ * BootInputHorizontal class file.
+ * @author Christoffer Niska <ChristofferNiska@gmail.com>
+ * @copyright Copyright &copy; Christoffer Niska 2011-
+ * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
+ */
+
+Yii::import('bootstrap.widgets.BootInput');
+
+/**
+ * Bootstrap horizontal form input widget.
+ * @since 0.9.8
+ */
+class BootInputHorizontal extends BootInput
+{
+	/**
+	 * Renders a checkbox.
+	 * @return string the rendered content
+	 */
+	protected function checkBox()
+	{
+		echo '<div class="controls">';
+		echo '<label class="checkbox" for="'.CHtml::getIdByName(CHtml::resolveName($this->model, $this->attribute)).'">';
+		echo $this->form->checkBox($this->model, $this->attribute, $this->htmlOptions).PHP_EOL;
+		echo $this->model->getAttributeLabel($this->attribute);
+		echo $this->getError().$this->getHint();
+		echo '</label></div>';
+	}
+
+	/**
+	 * Renders a list of checkboxes.
+	 * @return string the rendered content
+	 */
+	protected function checkBoxList()
+	{
+		echo $this->getLabel().'<div class="controls">';
+		echo $this->form->checkBoxList($this->model, $this->attribute, $this->data, $this->htmlOptions);
+		echo $this->getError().$this->getHint();
+		echo '</div>';
+	}
+
+	/**
+	 * Renders a list of inline checkboxes.
+	 * @return string the rendered content
+	 */
+	protected function checkBoxListInline()
+	{
+		$this->htmlOptions['inline'] = true;
+		$this->checkBoxList();
+	}
+
+	/**
+	 * Renders a drop down list (select).
+	 * @return string the rendered content
+	 */
+	protected function dropDownList()
+	{
+		echo $this->getLabel().'<div class="controls">';
+		echo $this->form->dropDownList($this->model, $this->attribute, $this->data, $this->htmlOptions);
+		echo $this->getError().$this->getHint();
+		echo '</div>';
+	}
+
+	/**
+	 * Renders a file field.
+	 * @return string the rendered content
+	 */
+	protected function fileField()
+	{
+		echo $this->getLabel().'<div class="controls">';
+		echo $this->form->fileField($this->model, $this->attribute, $this->htmlOptions);
+		echo $this->getError().$this->getHint();
+		echo '</div>';
+	}
+
+	/**
+	 * Renders a password field.
+	 * @return string the rendered content
+	 */
+	protected function passwordField()
+	{
+		echo $this->getLabel().'<div class="controls">';
+		echo $this->form->passwordField($this->model, $this->attribute, $this->htmlOptions);
+		echo $this->getError().$this->getHint();
+		echo '</div>';
+	}
+
+	/**
+	 * Renders a radio button.
+	 * @return string the rendered content
+	 */
+	protected function radioButton()
+	{
+		echo '<div class="controls">';
+		echo '<label class="radio" for="'.CHtml::getIdByName(CHtml::resolveName($this->model, $this->attribute)).'">';
+		echo $this->form->radioButton($this->model, $this->attribute, $this->htmlOptions).PHP_EOL;
+		echo $this->model->getAttributeLabel($this->attribute);
+		echo $this->getError().$this->getHint();
+		echo '</label></div>';
+	}
+
+	/**
+	 * Renders a list of radio buttons.
+	 * @return string the rendered content
+	 */
+	protected function radioButtonList()
+	{
+		echo $this->getLabel().'<div class="controls">';
+		echo $this->form->radioButtonList($this->model, $this->attribute, $this->data, $this->htmlOptions);
+		echo $this->getError().$this->getHint();
+		echo '</div>';
+	}
+
+	/**
+	 * Renders a list of inline radio buttons.
+	 * @return string the rendered content
+	 */
+	protected function radioButtonListInline()
+	{
+		$this->htmlOptions['inline'] = true;
+		$this->radioButtonList();
+	}
+
+	/**
+	 * Renders a textarea.
+	 * @return string the rendered content
+	 */
+	protected function textArea()
+	{
+		echo $this->getLabel().'<div class="controls">';
+		echo $this->form->textArea($this->model, $this->attribute, $this->htmlOptions);
+		echo $this->getError().$this->getHint();
+		echo '</div>';
+	}
+
+	/**
+	 * Renders a text field.
+	 * @return string the rendered content
+	 */
+	protected function textField()
+	{
+		echo $this->getLabel().'<div class="controls">';
+		echo $this->form->textField($this->model, $this->attribute, $this->htmlOptions);
+		echo $this->getError().$this->getHint();
+		echo '</div>';
+	}
+
+	/**
+	 * Renders a CAPTCHA.
+	 * @return string the rendered content
+	 */
+	protected function captcha()
+	{
+		echo $this->getLabel().'<div class="controls"><div class="captcha">';
+		echo '<div class="widget">'.$this->widget('CCaptcha', array('showRefreshButton'=>false), true).'</div>';
+		echo $this->form->textField($this->model, $this->attribute, $this->htmlOptions);
+		echo $this->getError().$this->getHint();
+		echo '</div></div>';
+	}
+
+	/**
+	 * Renders an uneditable field.
+	 * @return string the rendered content
+	 */
+	protected function uneditableField()
+	{
+		echo $this->getLabel().'<div class="controls">';
+		echo '<span class="uneditable-input">'.$this->model->{$this->attribute}.'</span>';
+		echo $this->getError().$this->getHint();
+		echo '</div>';
+	}
+
+	/**
+	 * Returns the label for this block.
+	 * @return string the label
+	 */
+	protected function getLabel()
+	{
+		if ($this->label !== false && !in_array($this->type, array('checkbox', 'radio')) && $this->hasModel())
+			return $this->form->labelEx($this->model, $this->attribute);
+		else if ($this->label !== null)
+			return $this->label;
+		else
+			return '';
+	}
+
+	/**
+	 * Returns the hint text for this block.
+	 * @return string the hint text
+	 */
+	protected function getHint()
+	{
+		if (isset($this->htmlOptions['hint']))
+		{
+			$hint = $this->htmlOptions['hint'];
+			unset($this->htmlOptions['hint']);
+			return '<p class="help-block">'.$hint.'</p>';
+		}
+		else
+			return '';
+	}
+
+	/**
+	 * Returns the error text for this block.
+	 * @return string the error text
+	 */
+	protected function getError()
+	{
+		return $this->form->error($this->model, $this->attribute);
+	}
+}

widgets/BootMenu.php

 	 */
 	public function init()
 	{
-		$id = $this->getId();
-        if (isset($this->htmlOptions['id']))
-            $id = $this->htmlOptions['id'];
-        else
-            $this->htmlOptions['id'] = $id;
+        if (!isset($this->htmlOptions['id']))
+            $this->htmlOptions['id'] = $this->getId();
 
 		$route = $this->controller->getRoute();
 		$this->items = $this->normalizeItems($this->items, $route);
-
-		if ($this->scrollspy)
-			Yii::app()->clientScript->registerScript(__CLASS__.'#'.$this->id, "jQuery('#{$id}').scrollspy();");
 	}
 
 	/**
 			echo CHtml::openTag('ul', $this->htmlOptions).PHP_EOL;
 			$this->renderItems($this->items);
 			echo '</ul>';
+
+			Yii::app()->bootstrap->registerDropdown();
+
+			if ($this->scrollspy)
+				Yii::app()->bootstrap->registerScrollSpy('#'.$this->id);
 		}
 	}
 

widgets/BootModal.php

 	public function init()
 	{
 		parent::init();
-		$this->registerScriptFile('bootstrap-modal.js');
-		$this->htmlOptions['id'] = $this->getId();
+
+		Yii::app()->bootstrap->registerModal();
+
+		if (!isset($this->htmlOptions['id']))
+			$this->htmlOptions['id'] = $this->getId();
+
+		if (isset($this->htmlOptions['class']))
+			$this->htmlOptions['class'] .= ' modal';
+		else
+			$this->htmlOptions['class'] = 'modal';
+
+		if (Yii::app()->bootstrap->isPluginRegistered(Bootstrap::PLUGIN_TRANSITION))
+			$this->htmlOptions['class'] .= ' fade';
 
 		echo CHtml::openTag('div', $this->htmlOptions).PHP_EOL;
 	}
 		if (isset($this->events['show']))
 		{
 			$fn = CJavaScript::encode($this->events['show']);
-			Yii::app()->clientScript->registerScript(__CLASS__.'#'.$this->id.'.show', "jQuery('#{$this->id}').on('show', {$fn});");
+			Yii::app()->clientScript->registerScript(__CLASS__.'#'.$this->id.'.show',
+					"jQuery('#{$this->id}').on('show', {$fn});");
 		}
 
 		// Register the "shown" event-handler.
 		if (isset($this->events['shown']))
 		{
 			$fn = CJavaScript::encode($this->events['shown']);
-			Yii::app()->clientScript->registerScript(__CLASS__.'#'.$this->id.'.shown', "jQuery('#{$this->id}').on('shown', {$fn});");
+			Yii::app()->clientScript->registerScript(__CLASS__.'#'.$this->id.'.shown',
+					"jQuery('#{$this->id}').on('shown', {$fn});");
 		}
 
 		// Register the "hide" event-handler.
 		if (isset($this->events['hide']))
 		{
 			$fn = CJavaScript::encode($this->events['hide']);
-			Yii::app()->clientScript->registerScript(__CLASS__.'#'.$this->id.'.hide', "jQuery('#{$this->id}').on('hide', {$fn});");
+			Yii::app()->clientScript->registerScript(__CLASS__.'#'.$this->id.'.hide',
+					"jQuery('#{$this->id}').on('hide', {$fn});");
 		}
 
 		// Register the "hidden" event-handler.
 		if (isset($this->events['hidden']))
 		{
 			$fn = CJavaScript::encode($this->events['hidden']);
-			Yii::app()->clientScript->registerScript(__CLASS__.'#'.$this->id.'.hidden', "jQuery('#{$this->id}').on('hidden', {$fn});");
+			Yii::app()->clientScript->registerScript(__CLASS__.'#'.$this->id.'.hidden',
+					"jQuery('#{$this->id}').on('hidden', {$fn});");
 		}
 	}
 }

widgets/BootNavbar.php

 	 */
 	public $fixed = true;
 	/**
-	 * @var boolean whether to enable collapsing on narrow screens.
-	 * Enabled by default if the collapse plugin is registered.
+	 * @var boolean whether to enable collapsing on narrow screens. Default to false.
 	 */
-	public $collapse = null;
+	public $collapse = false;
 
 	/**
 	 * Initializes the widget.
 				$this->brandUrl = Yii::app()->homeUrl;
 		}
 
-		if (!isset($this->collapse))
-			$this->collapse = Yii::app()->bootstrap->isPluginRegistered('collapse');
+		if ($this->collapse)
+			Yii::app()->bootstrap->registerCollapse();
 	}
 
 	/**

widgets/BootTabbed.php

 	 * @var array the tab configuration.
 	 */
     public $tabs = array();
-
+	/**
+	 * @var boolean whether to encode item labels.
+	 */
 	public $encodeLabel = true;
 
     /**
     public function init()
     {
         parent::init();
-        $this->registerScriptFile('bootstrap-tab.js');
+
+        Yii::app()->bootstrap->registerTabs();
+
+		if (!isset($this->htmlOptions['id']))
+			$this->htmlOptions['id'] = $this->getId();
     }
 
     /**
      */
     public function run()
     {
-        $id = $this->getId();
-        if (isset($this->htmlOptions['id']))
-            $id = $this->htmlOptions['id'];
-        else
-            $this->htmlOptions['id'] = $id;
-
 	    $panes = array();
 	    $items = $this->normalizeTabs($this->tabs, $panes);
 
 
 	    $this->controller->widget('bootstrap.widgets.BootMenu', array(
 			'type'=>$this->type,
+			'encodeLabel'=>$this->encodeLabel,
 		    'items'=>$items,
 	    ));
 
 		echo implode('', $panes);
 	    echo '</div></div>';
 
-	    $this->registerScript(__CLASS__.'#'.$id, "jQuery('{$id}').tab('show');");
+	    $this->registerScript(__CLASS__.'#'.$this->id, "jQuery('{$this->id}').tab('show');");
 
 	    /*
         // Register the "show" event-handler.
 	protected function normalizeTabs($tabs, &$panes, &$i = 0)
 	{
 		$id = $this->getId();
-		$transitions = Yii::app()->bootstrap->transitions;
+		$transitions = Yii::app()->bootstrap->isPluginRegistered(Bootstrap::PLUGIN_TRANSITION);
 
 		$items = array();
 
-	    foreach ($tabs as &$tab)
+	    foreach ($tabs as $tab)
 	    {
 		    $i++;
-		    $item = array();
+			$item = $tab;
 
-		    $itemId = isset($tab['id']) ? $tab['id'] : $id.'_tab_'.$i;
+			if (!isset($item['id']))
+				$item['id'] = $id.'_tab_'.$i;
 
-		    $item['label'] = isset($tab['label']) ? $tab['label'] : '';
+			if (!isset($item['label']))
+				$item['label'] = '';
 
-		    if (!isset($tab['items']))
-			    $item['url'] = '#'.$itemId;
+			$item['url'] = '#'.$item['id'];
 
-		    if (isset($tab['itemOptions']))
-			    $item['itemOptions'] = $tab['itemOptions'];
+			if (!isset($item['itemOptions']))
+				$item['itemOptions'] = array();
 
 		    if ($i === 1)
 		    {
 		            $item['itemOptions']['class'] = 'active';
 		    }
 
+			$item['linkOptions']['data-toggle'] = 'tab';
+
 		    if (isset($tab['items']))
-				$item['items'] = $this->normalizeTabs($tab['items'], $panes, $i);
+			{
+				$item['items'] = $this->normalizeTabs($item['items'], $panes, $i);
+				unset($item['url']);
+			}
 
-		    $item['linkOptions']['data-toggle'] = 'tab';
+		    if (!isset($item['content']))
+			    $item['content'] = '';
 
-		    if (!isset($tab['content']))
-			    $tab['content'] = '';
+			$content = $item['content'];
+			unset($item['content']);
 
-		    if (!isset($tab['paneOptions']))
-			    $tab['paneOptions'] = array();
+		    if (!isset($item['paneOptions']))
+				$item['paneOptions'] = array();
 
-		    $tab['paneOptions']['id'] = $itemId;
+			$paneOptions = $item['paneOptions'];
+			unset($item['paneOptions']);
+
+			$paneOptions['id'] = $item['id'];
 
 		    if (isset($tab['paneOptions']['class']))
-			    $tab['paneOptions']['class'] .= ' tab-pane';
+				$paneOptions['class'] .= ' tab-pane';
 		    else
-			    $tab['paneOptions']['class'] = 'tab-pane';
+				$paneOptions['class'] = 'tab-pane';
 
 		    if ($transitions)
-		        $tab['paneOptions']['class'] .= ' fade';
+				$paneOptions['class'] .= ' fade';
 
 		    if ($i === 1)
 		    {
 			    if ($transitions)
-					$tab['paneOptions']['class'] .= ' in';
+					$paneOptions['class'] .= ' in';
 
-			    $tab['paneOptions']['class'] .= ' active';
+				$paneOptions['class'] .= ' active';
 		    }
 
-		    $items[] = $item;
-		    $panes[] = CHtml::tag('div', $tab['paneOptions'], $tab['content']);
+		    $panes[] = CHtml::tag('div', $paneOptions, $content);
+			$items[] = $item;
 	    }
 
 		return $items;
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.