Test Setup Failed
Push — prerelease ( 30729b...b0ba5c )
by
unknown
06:23
created

TreeWidget.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace devgroup\JsTreeWidget;
4
5
use Yii;
6
use yii\base\InvalidConfigException;
7
use yii\base\Widget;
8
use yii\helpers\Html;
9
use yii\helpers\Json;
10
use yii\helpers\Url;
11
use yii\web\JsExpression;
12
use yii\helpers\ArrayHelper;
13
use yii\web\View;
14
15
/**
16
 * JsTree widget for Yii Framework 2
17
 */
18
class TreeWidget extends Widget
19
{
20
21
    /**
22
     * @var array Enabled jsTree plugins
23
     * @see http://www.jstree.com/plugins/
24
     */
25
    public $plugins = [
26
        'wholerow',
27
        'contextmenu',
28
        'dnd',
29
        'types',
30
        'state',
31
    ];
32
33
    /**
34
     * @var array Configuration for types plugin
35
     * @see http://www.jstree.com/api/#/?f=$.jstree.defaults.types
36
     */
37
    public $types = [
38
        'show' => [
39
            'icon' => 'fa fa-file-o',
40
        ],
41
        'list' => [
42
            'icon' => 'fa fa-list',
43
        ],
44
    ];
45
46
    /**
47
     * Context menu actions configuration.
48
     * @var array
49
     */
50
    public $contextMenuItems = [];
51
52
    /**
53
     * Various options for jsTree plugin. Will be merged with default options.
54
     * @var array
55
     */
56
    public $options = [];
57
58
    /**
59
     * Route to action which returns json data for tree
60
     * @var array
61
     */
62
    public $treeDataRoute = null;
63
64
    /**
65
     * Translation category for Yii::t() which will be applied to labels.
66
     * If translation is not needed - use false.
67
     */
68
    public $menuLabelsTranslationCategory = 'app';
69
70
    /**
71
     * JsExpression for action(callback function) on double click. You can use JsExpression or make custom expression.
72
     * Warning! Callback function differs from native jsTree function - it consumes only one attribute - node(similar to contextmenu action).
0 ignored issues
show
This line exceeds maximum limit of 120 characters; contains 141 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
73
     * Use false if no action needed.
74
     * @var bool|JsExpression
75
     */
76
    public $doubleClickAction = false;
77
78
    public $changeParentAction = false;
79
80
    public $reorderAction = false;
81
82
    public function run()
83
    {
84
        if (!is_array($this->treeDataRoute)) {
85
            throw new InvalidConfigException("Attribute treeDataRoute is required to use TreeWidget.");
86
        }
87
88
        $id = $this->getId();
89
90
        $options = [
91
            'plugins' => $this->plugins,
92
            'core' => [
93
                'check_callback' => true,
94
                'data' => [
95
                    'url' => new JsExpression(
96
                        "function (node) {
97
                            return " . Json::encode(Url::to($this->treeDataRoute)) . ";
98
                        }"
99
                    ),
100
                    'data' => new JsExpression(
101
                        "function (node) {
102
                        return { 'id' : node.id };
103
                        }"
104
                    ),
105
                ]
106
            ]
107
        ];
108
109
        // merge with contextmenu configuration
110
        $options = ArrayHelper::merge($options, $this->contextMenuOptions());
111
112
        // merge with attribute-provided options
113
        $options = ArrayHelper::merge($options, $this->options);
114
115
        $options = Json::encode($options);
116
117
        $this->getView()->registerAssetBundle('devgroup\JsTreeWidget\JsTreeAssetBundle');
118
119
        $doubleClick = '';
120
        if ($this->doubleClickAction !== false) {
121
            $doubleClick = "
122
            jsTree_$id.on('dblclick.jstree', function (e) {
123
                var node = $(e.target).closest('.jstree-node').children('.jstree-anchor');
124
                var callback = " . $this->doubleClickAction . ";
125
                callback(node);
126
                return false;
127
            });\n";
128
        }
129
        $changeParent = '';
130
        if ($this->changeParentAction !== false) {
131
            $changeParent ="
132
             jsTree_$id.bind('move_node.jstree', function(e, data) {
133
                jQuery.get(
134
                    '" . $this->changeParentAction . "',
135
                    {
136
                        'id': data.node.id,
137
                        'parent_id': data.parent
138
                    }
139
                );
140
                return false;
141
            });\n";
142
        }
143
        $reorder = '';
144
        if ($this->reorderAction !== false) {
145
            $reorder ="
146
             jsTree_$id.bind('move_node.jstree', function(e, data) {
147
             var params = [];
148
                 jQuery('.jstree-node').each(function(i, e) {
149
                    params[e.id] = i;
150
                 });
151
                  jQuery.post(
152
                    '" . $this->reorderAction . "',
153
                    {'order':params }
154
                );
155
                return false;
156
            });\n";
157
        }
158
        $this->getView()->registerJs("
159
        var jsTree_$id = \$('#$id').jstree($options);
160
        $doubleClick $changeParent $reorder", View::POS_READY);
161
        return Html::tag('div', '', ['id' => $id]);
162
    }
163
164
    private function contextMenuOptions()
165
    {
166
        $options = [];
167
        if (count($this->contextMenuItems) > 0) {
168
            if (!in_array('contextmenu', $this->plugins)) {
169
                // add missing contextmenu plugin
170
                $options['plugins'] = ['contextmenu'];
171
            }
172
173
            $options['contextmenu']['items'] = [];
174
            foreach ($this->contextMenuItems as $index => $item) {
175
                if ($this->menuLabelsTranslationCategory !== false) {
176
                    $item['label'] = Yii::t($this->menuLabelsTranslationCategory, $item['label']);
177
                }
178
                $options['contextmenu']['items'][$index] = $item;
179
            }
180
        }
181
        return $options;
182
    }
183
}