1: <?php
2:
3: namespace ZCL\BT;
4:
5: use \Zippy\Interfaces\AjaxRender;
6: use \Zippy\WebApplication;
7: use \Zippy\Interfaces\SubmitDataRequest;
8: use \Zippy\Html\HtmlComponent;
9: use \Zippy\Event;
10: use \Zippy\Interfaces\EventReceiver;
11:
12: /**
13: * Компонент древовидного меню
14: * https://github.com/maxwells/bootstrap-treeview
15: */
16: class Tree extends HtmlComponent implements \Zippy\Interfaces\Requestable
17: {
18:
19: private $number = 1;
20: public $children = array(); // массив дочерних
21: public $nodes = array(); //массив всех nodes
22: private $options = array();
23: private $event = null;
24: private $selectedid = -1; //id узла на клиенте
25: private $selectednodeid = -1;// кастомное id (например treeentry id)
26: private $expanded = array();
27:
28: public function __construct($id, $options = array()) {
29: HtmlComponent::__construct($id);
30: if (is_array($options)) {
31: $this->options = $options;
32: }
33: }
34:
35: public function onSelectNode(EventReceiver $receiver, $handler, $ajax = false) {
36:
37: $this->event = new Event($receiver, $handler);
38: $this->event->isajax = $ajax;
39: }
40:
41: public function RenderImpl() {
42: $url = $this->owner->getURLNode() . "::" . $this->id . "&ajax=true";
43:
44:
45: $js = "
46: $('#{$this->id}').treeview({
47: data: getTree(),
48: expandIcon:'fa fa-plus',
49: collapseIcon:'fa fa-minus',
50: checkedIcon:'fa fa-check-square-o',
51: uncheckedIcon:'fa fa-square-o',
52: showBorder: false,
53: showTags: true,
54: ";
55:
56: if (@$this->options['showTags'] === true) {
57: $js .= " showTags:true, ";
58: }
59: if (@$this->options['enableLinks'] === true) {
60: $js .= " enableLinks:true, ";
61: }
62:
63: $js .= " emptyIcon:'fa '
64:
65:
66: });
67: ";
68: WebApplication::$app->getResponse()->addJavaScript($js, true);
69:
70: $url = $this->owner->getURLNode() . "::" . $this->id;
71:
72: if ($this->event instanceof Event) {
73:
74:
75: $js = " $('#{$this->id}').on('nodeSelected', function(event, node) {
76:
77:
78:
79:
80: var url ='{$url}:sel:' + node.nodeId+':'+ node.zippyid +':'+getExpanded() ";
81: if ($this->event->isajax) {
82: $js .= "
83:
84:
85: url= url+'&ajax=true' ;
86: \$.ajax({
87: url: url,
88: success: function (data, textStatus) {
89: // eval(data);
90: }
91: }); ";
92: } else {
93: $js .= "
94: window.location=url
95: ";
96:
97: }
98: $js .= " }); ";
99:
100: $js .= " $('#{$this->id}').on('nodeUnselected ', function(event, node) {
101:
102:
103:
104:
105: url ='{$url}:sel:-1:-1:'+getExpanded() ";
106: if ($this->event->isajax) {
107: $js .= "
108:
109:
110: url= url+'&ajax=true' ;
111: \$.ajax({
112: url: url,
113: success: function (data, textStatus) {
114: // eval(data);
115: }
116: }); ";
117: } else {
118: $js .= "
119: window.location=url
120: ";
121:
122: }
123: $js .= " }); ";
124:
125:
126: WebApplication::$app->getResponse()->addJavaScript($js, true);
127: }
128:
129:
130: $js = "
131:
132:
133: function getExpanded(){
134: var explist ='';
135: var arr= $('#{$this->id}').treeview('getExpanded');
136: arr.forEach(function(entry) {
137: explist = explist +','+ entry.nodeId;
138: });
139: return explist;
140: }
141:
142:
143: function getTree(){
144: var tree =
145: [";
146:
147: $c = array();
148: foreach ($this->children as $child) {
149: $c[] = $child->Render();
150: }
151:
152:
153: $js .= implode(',', $c);
154:
155: $js .= "
156: ] ;
157: return tree;
158: }
159: ";
160:
161:
162: WebApplication::$app->getResponse()->addJavaScript($js);
163:
164:
165: if ($this->selectedid >= 0) {
166: $js = "var allNodes= $('#{$this->id}').treeview('getEnabled');
167: ; ";
168: $js .= "$(allNodes).each(function(index, element) {
169: ";
170: $js .= " if(element.zippyid=={$this->selectedid}) {
171: $('#{$this->id}').treeview('selectNode', [ element, { silent: true } ]);
172: $('#{$this->id}').treeview('revealNode', [ element, { silent: true } ]);
173: };
174: });";
175: WebApplication::$app->getResponse()->addJavaScript($js, true);
176: } else {
177: if ($this->selectednodeid > 0) {
178: $js = " $('#{$this->id}').treeview('selectNode', [ {$this->selectednodeid}, { silent: true } ]); ";
179: WebApplication::$app->getResponse()->addJavaScript($js, true);
180: }
181: }
182:
183: if (count($this->expanded) > 0) {
184: $js = "";
185: foreach ($this->expanded as $id) {
186: $js .= " $('#{$this->id}').treeview('expandNode', [ {$id}, { silent: true } ]);
187: ";
188: }
189:
190: WebApplication::$app->getResponse()->addJavaScript($js, true);
191: }
192: }
193:
194: public final function RequestHandle() {
195: $params = WebApplication::$app->getRequest()->request_params[$this->id];
196:
197: $op = $params[0];
198: $this->selectedid = $params[2];
199: $this->selectednodeid = $params[1];
200:
201: if (strlen($params[3]) > 0) {
202: $this->expanded = explode(',', trim($params[3], ','));
203: }
204:
205: if ($this->event != null && $op == 'sel') {
206: $this->event->onEvent($this, $this->selectedid);
207: }
208: }
209:
210: public function addNode(TreeNode $node, TreeNode $parentnode = null) {
211:
212:
213: $node->owner = $this;
214: $node->parent = $parentnode;
215: $node->number = $this->number++;
216: $this->nodes[$node->number] = $node;
217:
218: if ($parentnode == null) {
219:
220: $this->children[] = $node;
221: } else {
222: // $parentnode->setSelected(false);
223: if (in_array($parentnode, $this->nodes)) {
224: //$parentnode->addNode($node);
225: $parentnode->children[] = $node;
226: } else {
227: throw new \Zippy\Exception(ERROR_INVALID_PARENT_NODE);
228: }
229: }
230: return $node;
231: }
232:
233: /**
234: * возвращает или устанавливает кастомный id активного узла
235: *
236: */
237: public function selectedNodeId($id = null) {
238:
239: if (is_integer($id)) {
240: $this->selectedid = $id;
241: $this->selectednodeid = $id;
242: }
243: return $this->selectedid;
244:
245: }
246:
247: public function removeNodes() {
248: $this->nodes = array();
249: $this->children = array();
250: $this->number = 1;
251: $this->selectedid = -1;
252: $this->selectednodeid = -1;
253: $this->expanded = array();
254: }
255: }
256:
257: class TreeNode
258: {
259:
260: protected $text;
261: public $children = array();
262: public $tags;
263: public $expand = false;
264: public $number, $owner, $parent = null;
265: public $isselected = false;
266: public $icon = ""; //иконки для узла
267: public $checked = false;
268: public $link = '';
269: public $zippyid = 0;
270:
271:
272: public function __construct($text, $id) {
273: $this->text = $text;
274: $this->zippyid = $id;
275:
276: }
277:
278: public function Render() {
279: $js = "{ text: \"{$this->text}\",zippyid:{$this->zippyid} ";
280:
281: if (strlen($this->link) > 0) {
282: $js .= "
283: ,href: \"{$this->link}\"";
284: }
285: if (strlen($this->tags) > 0) {
286: $js .= ",tags: ['{$this->tags}'] ";
287: }
288: if (strlen($this->icon) > 0) {
289: $js .= ",icon: '{$this->icon}' ";
290: }
291: if ($this->isselected != null) {
292: $js .= "
293: ,selectable: true";
294: }
295: $js .= "
296: ,state:{ ";
297: if ($this->isselected === true) {
298:
299: $js .= " selected: true ";
300:
301: }
302: $js .= " } ";
303:
304: $c = array();
305: foreach ($this->children as $child) {
306: $c[] = $child->Render();
307: }
308: if (count($c) > 0) {
309: $js .= '
310: ,nodes: [
311: ' . implode(',', $c) . '
312: ]
313: ';
314: }
315:
316:
317: return $js . "
318: }";
319: }
320:
321:
322: }
323: