Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

174 lines
5.8KB

  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\bootstrap;
  8. use yii\base\InvalidConfigException;
  9. use yii\helpers\ArrayHelper;
  10. /**
  11. * Collapse renders an accordion bootstrap javascript component.
  12. *
  13. * For example:
  14. *
  15. * ```php
  16. * echo Collapse::widget([
  17. * 'items' => [
  18. * // equivalent to the above
  19. * [
  20. * 'label' => 'Collapsible Group Item #1',
  21. * 'content' => 'Anim pariatur cliche...',
  22. * // open its content by default
  23. * 'contentOptions' => ['class' => 'in']
  24. * ],
  25. * // another group item
  26. * [
  27. * 'label' => 'Collapsible Group Item #1',
  28. * 'content' => 'Anim pariatur cliche...',
  29. * 'contentOptions' => [...],
  30. * 'options' => [...],
  31. * ],
  32. * // if you want to swap out .panel-body with .list-group, you may use the following
  33. * [
  34. * 'label' => 'Collapsible Group Item #1',
  35. * 'content' => [
  36. * 'Anim pariatur cliche...',
  37. * 'Anim pariatur cliche...'
  38. * ],
  39. * 'contentOptions' => [...],
  40. * 'options' => [...],
  41. * 'footer' => 'Footer' // the footer label in list-group
  42. * ],
  43. * ]
  44. * ]);
  45. * ```
  46. *
  47. * @see http://getbootstrap.com/javascript/#collapse
  48. * @author Antonio Ramirez <amigo.cobos@gmail.com>
  49. * @since 2.0
  50. */
  51. class Collapse extends Widget
  52. {
  53. /**
  54. * @var array list of groups in the collapse widget. Each array element represents a single
  55. * group with the following structure:
  56. *
  57. * - label: string, required, the group header label.
  58. * - encode: boolean, optional, whether this label should be HTML-encoded. This param will override
  59. * global `$this->encodeLabels` param.
  60. * - content: array|string|object, required, the content (HTML) of the group
  61. * - options: array, optional, the HTML attributes of the group
  62. * - contentOptions: optional, the HTML attributes of the group's content
  63. */
  64. public $items = [];
  65. /**
  66. * @var boolean whether the labels for header items should be HTML-encoded.
  67. */
  68. public $encodeLabels = true;
  69. /**
  70. * Initializes the widget.
  71. */
  72. public function init()
  73. {
  74. parent::init();
  75. Html::addCssClass($this->options, ['widget' => 'panel-group']);
  76. }
  77. /**
  78. * Renders the widget.
  79. */
  80. public function run()
  81. {
  82. $this->registerPlugin('collapse');
  83. return implode("\n", [
  84. Html::beginTag('div', $this->options),
  85. $this->renderItems(),
  86. Html::endTag('div')
  87. ]) . "\n";
  88. }
  89. /**
  90. * Renders collapsible items as specified on [[items]].
  91. * @throws InvalidConfigException if label isn't specified
  92. * @return string the rendering result
  93. */
  94. public function renderItems()
  95. {
  96. $items = [];
  97. $index = 0;
  98. foreach ($this->items as $item) {
  99. if (!array_key_exists('label', $item)) {
  100. throw new InvalidConfigException("The 'label' option is required.");
  101. }
  102. $header = $item['label'];
  103. $options = ArrayHelper::getValue($item, 'options', []);
  104. Html::addCssClass($options, ['panel' => 'panel', 'widget' => 'panel-default']);
  105. $items[] = Html::tag('div', $this->renderItem($header, $item, ++$index), $options);
  106. }
  107. return implode("\n", $items);
  108. }
  109. /**
  110. * Renders a single collapsible item group
  111. * @param string $header a label of the item group [[items]]
  112. * @param array $item a single item from [[items]]
  113. * @param integer $index the item index as each item group content must have an id
  114. * @return string the rendering result
  115. * @throws InvalidConfigException
  116. */
  117. public function renderItem($header, $item, $index)
  118. {
  119. if (array_key_exists('content', $item)) {
  120. $id = $this->options['id'] . '-collapse' . $index;
  121. $options = ArrayHelper::getValue($item, 'contentOptions', []);
  122. $options['id'] = $id;
  123. Html::addCssClass($options, ['widget' => 'panel-collapse', 'collapse' => 'collapse']);
  124. $encodeLabel = isset($item['encode']) ? $item['encode'] : $this->encodeLabels;
  125. if ($encodeLabel) {
  126. $header = Html::encode($header);
  127. }
  128. $headerToggle = Html::a($header, '#' . $id, [
  129. 'class' => 'collapse-toggle',
  130. 'data-toggle' => 'collapse',
  131. 'data-parent' => '#' . $this->options['id']
  132. ]) . "\n";
  133. $header = Html::tag('h4', $headerToggle, ['class' => 'panel-title']);
  134. if (is_string($item['content']) || is_object($item['content'])) {
  135. $content = Html::tag('div', $item['content'], ['class' => 'panel-body']) . "\n";
  136. } elseif (is_array($item['content'])) {
  137. $content = Html::ul($item['content'], [
  138. 'class' => 'list-group',
  139. 'itemOptions' => [
  140. 'class' => 'list-group-item'
  141. ],
  142. 'encode' => false,
  143. ]) . "\n";
  144. if (isset($item['footer'])) {
  145. $content .= Html::tag('div', $item['footer'], ['class' => 'panel-footer']) . "\n";
  146. }
  147. } else {
  148. throw new InvalidConfigException('The "content" option should be a string, array or object.');
  149. }
  150. } else {
  151. throw new InvalidConfigException('The "content" option is required.');
  152. }
  153. $group = [];
  154. $group[] = Html::tag('div', $header, ['class' => 'panel-heading']);
  155. $group[] = Html::tag('div', $content, $options);
  156. return implode("\n", $group);
  157. }
  158. }