Carousel.php 5.04 KB
Newer Older
Antonio Ramirez committed
1 2 3 4 5 6 7 8 9
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\bootstrap;

Qiang Xue committed
10
use yii\base\InvalidConfigException;
Antonio Ramirez committed
11
use yii\helpers\ArrayHelper;
Antonio Ramirez committed
12 13 14 15 16
use yii\helpers\Html;

/**
 * Carousel renders a carousel bootstrap javascript component.
 *
17
 * For example:
Antonio Ramirez committed
18 19 20 21
 *
 * ```php
 * echo Carousel::widget(array(
 *     'items' => array(
Qiang Xue committed
22
 *         // the item contains only the image
Antonio Ramirez committed
23
 *         '<img src="http://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-01.jpg"/>',
Qiang Xue committed
24
 *         // equivalent to the above
Antonio Ramirez committed
25
 *         array(
Antonio Ramirez committed
26
 *             'content' => '<img src="http://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-02.jpg"/>',
Antonio Ramirez committed
27
 *         ),
Qiang Xue committed
28
 *         // the item contains both the image and the caption
Antonio Ramirez committed
29
 *         array(
Antonio Ramirez committed
30
 *             'content' => '<img src="http://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-03.jpg"/>',
31
 *             'caption' => '<h4>This is title</h4><p>This is the caption text</p>',
32
 *             'options' => array(...),
Antonio Ramirez committed
33 34 35 36 37 38 39 40 41 42 43 44
 *         ),
 *     )
 * ));
 * ```
 *
 * @see http://twitter.github.io/bootstrap/javascript.html#carousel
 * @author Antonio Ramirez <amigo.cobos@gmail.com>
 * @since 2.0
 */
class Carousel extends Widget
{
	/**
Qiang Xue committed
45 46
	 * @var array|boolean the labels for the previous and the next control buttons.
	 * If false, it means the previous and the next control buttons should not be displayed.
Antonio Ramirez committed
47
	 */
48
	public $controls = array('&lsaquo;', '&rsaquo;');
Antonio Ramirez committed
49
	/**
Qiang Xue committed
50 51
	 * @var array list of slides in the carousel. Each array element represents a single
	 * slide with the following structure:
Antonio Ramirez committed
52 53 54
	 *
	 * ```php
	 * array(
Qiang Xue committed
55 56 57
	 *     // required, slide content (HTML), such as an image tag
	 *     'content' => '<img src="http://twitter.github.io/bootstrap/assets/img/bootstrap-mdo-sfmoma-01.jpg"/>',
	 *     // optional, the caption (HTML) of the slide
58
	 *     'caption' => '<h4>This is title</h4><p>This is the caption text</p>',
Qiang Xue committed
59 60
	 *     // optional the HTML attributes of the slide container
	 *     'options' => array(),
Antonio Ramirez committed
61 62 63 64 65 66 67 68 69 70 71 72
	 * )
	 * ```
	 */
	public $items = array();


	/**
	 * Initializes the widget.
	 */
	public function init()
	{
		parent::init();
73
		Html::addCssClass($this->options, 'carousel');
Antonio Ramirez committed
74 75 76 77 78 79 80 81
	}

	/**
	 * Renders the widget.
	 */
	public function run()
	{
		echo Html::beginTag('div', $this->options) . "\n";
82 83
		echo $this->renderIndicators() . "\n";
		echo $this->renderItems() . "\n";
Qiang Xue committed
84
		echo $this->renderControls() . "\n";
Antonio Ramirez committed
85
		echo Html::endTag('div') . "\n";
86
		$this->registerPlugin('carousel');
Antonio Ramirez committed
87 88 89
	}

	/**
Qiang Xue committed
90 91
	 * Renders carousel indicators.
	 * @return string the rendering result
Antonio Ramirez committed
92 93 94
	 */
	public function renderIndicators()
	{
Qiang Xue committed
95
		$indicators = array();
96
		for ($i = 0, $count = count($this->items); $i < $count; $i++) {
Antonio Ramirez committed
97 98
			$options = array('data-target' => '#' . $this->options['id'], 'data-slide-to' => $i);
			if ($i === 0) {
99
				Html::addCssClass($options, 'active');
Antonio Ramirez committed
100
			}
Qiang Xue committed
101
			$indicators[] = Html::tag('li', '', $options);
Antonio Ramirez committed
102
		}
Qiang Xue committed
103
		return Html::tag('ol', implode("\n", $indicators), array('class' => 'carousel-indicators'));
Antonio Ramirez committed
104 105 106
	}

	/**
Qiang Xue committed
107 108
	 * Renders carousel items as specified on [[items]].
	 * @return string the rendering result
Antonio Ramirez committed
109 110 111
	 */
	public function renderItems()
	{
Qiang Xue committed
112
		$items = array();
113
		for ($i = 0, $count = count($this->items); $i < $count; $i++) {
Qiang Xue committed
114
			$items[] = $this->renderItem($this->items[$i], $i);
Antonio Ramirez committed
115
		}
Qiang Xue committed
116
		return Html::tag('div', implode("\n", $items), array('class' => 'carousel-inner'));
Antonio Ramirez committed
117 118 119 120
	}

	/**
	 * Renders a single carousel item
Qiang Xue committed
121
	 * @param string|array $item a single item from [[items]]
Antonio Ramirez committed
122
	 * @param integer $index the item index as the first item should be set to `active`
Qiang Xue committed
123 124
	 * @return string the rendering result
	 * @throws InvalidConfigException if the item is invalid
Antonio Ramirez committed
125 126 127
	 */
	public function renderItem($item, $index)
	{
Antonio Ramirez committed
128
		if (is_string($item)) {
Qiang Xue committed
129 130 131 132 133 134 135 136 137 138
			$content = $item;
			$caption = null;
			$options = array();
		} elseif (isset($item['content'])) {
			$content = $item['content'];
			$caption = ArrayHelper::getValue($item, 'caption');
			if ($caption !== null) {
				$caption = Html::tag('div', $caption, array('class' => 'carousel-caption'));
			}
			$options = ArrayHelper::getValue($item, 'options', array());
Antonio Ramirez committed
139
		} else {
Qiang Xue committed
140
			throw new InvalidConfigException('The "content" option is required.');
Antonio Ramirez committed
141 142
		}

143
		Html::addCssClass($options, 'item');
Antonio Ramirez committed
144
		if ($index === 0) {
145
			Html::addCssClass($options, 'active');
Antonio Ramirez committed
146
		}
147

Qiang Xue committed
148
		return Html::tag('div', $content . "\n" . $caption, $options);
Antonio Ramirez committed
149 150 151
	}

	/**
Qiang Xue committed
152 153
	 * Renders previous and next control buttons.
	 * @throws InvalidConfigException if [[controls]] is invalid.
Antonio Ramirez committed
154
	 */
Qiang Xue committed
155
	public function renderControls()
Antonio Ramirez committed
156
	{
Qiang Xue committed
157 158
		if (isset($this->controls[0], $this->controls[1])) {
			return Html::a($this->controls[0], '#' . $this->options['id'], array(
Antonio Ramirez committed
159
				'class' => 'left carousel-control',
160 161 162
				'data-slide' => 'prev',
			)) . "\n"
			. Html::a($this->controls[1], '#' . $this->options['id'], array(
Antonio Ramirez committed
163
				'class' => 'right carousel-control',
164
				'data-slide' => 'next',
Antonio Ramirez committed
165
			));
Qiang Xue committed
166 167 168 169 170
		} elseif ($this->controls === false) {
			return '';
		} else {
			throw new InvalidConfigException('The "controls" property must be either false or an array of two elements.');
		}
Antonio Ramirez committed
171
	}
172
}