Tabs.php 3.84 KB
<?php

namespace backend\widgets\Forms;

use yii\base\InvalidConfigException;
use yii\helpers\{
    ArrayHelper, Html
};

/**
 * Class Tabs
 *
 * @package backend\widgets\Forms
 * @author FilamentV <vortex.filament@gmail.com>
 * @copyright (c), Thread
 */
class Tabs extends \yii\bootstrap\Tabs
{
    /**
     * @var string
     */
    public $position = 'left';

    /**
     * Renders the widget.
     */
    public function run()
    {
        $this->registerPlugin('tab');

        echo Html::beginTag('div', ['class' => 'tabs-container', 'style' => ['margin-bottom' => '15px']])
            . Html::beginTag('div', ['class' => 'tabs-' . $this->position])
            . $this->renderItems()
            . Html::endTag('div')
            . Html::endTag('div');

        $this->registerJS();
    }

    /**
     * registerJS save Tabs state
     */
    protected function registerJS()
    {

        $script = <<< JS
    $(function() {
        //save the latest tab (http://stackoverflow.com/a/18845441)
        $('a[data-toggle="tab"]').on('click', function (e) {
            localStorage.setItem('lastTab', $(e.target).attr('href'));
        });

        //go to the latest tab, if it exists:
        var lastTab = localStorage.getItem('lastTab');

        if (lastTab) {
            $('a[href="'+lastTab+'"]').click();
        }
    });
JS;
        \Yii::$app->getView()->registerJs($script, \yii\web\View::POS_END);
    }

    /**
     * Renders tab items as specified on [[items]].
     * @return string the rendering result.
     * @throws InvalidConfigException.
     */
    protected function renderItems()
    {
        $headers = [];
        $panes = [];

        if (!$this->hasActiveTab() && !empty($this->items)) {
            $this->items[0]['active'] = true;
        }

        foreach ($this->items as $n => $item) {
            if (!ArrayHelper::remove($item, 'visible', true)) {
                continue;
            }
            if (!array_key_exists('label', $item)) {
                throw new InvalidConfigException("The 'label' option is required.");
            }
            $encodeLabel = $item['encode']?? $this->encodeLabels;
            $label = $encodeLabel ? Html::encode($item['label']) : $item['label'];
            $headerOptions = array_merge($this->headerOptions, ArrayHelper::getValue($item, 'headerOptions', []));
            $linkOptions = array_merge($this->linkOptions, ArrayHelper::getValue($item, 'linkOptions', []));

            $options = array_merge($this->itemOptions, ArrayHelper::getValue($item, 'options', []));
            $options['id'] = ArrayHelper::getValue($options, 'id', $this->options['id'] . '-tab' . $n);

            Html::addCssClass($options, ['widget' => 'tab-pane']);
            if (ArrayHelper::remove($item, 'active')) {
                Html::addCssClass($options, 'active');
                Html::addCssClass($headerOptions, 'active');
            }

            if (isset($item['url'])) {
                $header = Html::a($label, $item['url'], $linkOptions);
            } else {
                if (!isset($linkOptions['data-toggle'])) {
                    $linkOptions['data-toggle'] = 'tab';
                }
                $header = Html::a($label, '#' . $options['id'], $linkOptions);
            }

            if ($this->renderTabContent && isset($item['content'])) {
                $tag = ArrayHelper::remove($options, 'tag', 'div');
                $item['content'] = Html::tag('div', $item['content'], ['class' => 'panel-body']);
                $panes[] = Html::tag($tag, isset($item['content']) ? $item['content'] : '', $options);
            }

            $headers[] = Html::tag('li', $header, $headerOptions);
        }

        return Html::tag('ul', implode("\n", $headers), $this->options)
            . ($this->renderTabContent ? "\n"
                . Html::tag('div', implode("\n", $panes), ['class' => 'tab-content']) : '');
    }
}