luci-theme-openwrt: rework menu rendering
[oweals/luci.git] / themes / luci-theme-openwrt / htdocs / luci-static / resources / menu-openwrt.js
1 'use strict';
2 'require baseclass';
3 'require ui';
4
5 return baseclass.extend({
6         __init__: function() {
7                 ui.menu.load().then(L.bind(this.render, this));
8         },
9
10         render: function(tree) {
11                 var node = tree,
12                     url = '';
13
14                 this.renderModeMenu(tree);
15
16                 if (L.env.dispatchpath.length >= 3) {
17                         for (var i = 0; i < 3 && node; i++) {
18                                 node = node.children[L.env.dispatchpath[i]];
19                                 url = url + (url ? '/' : '') + L.env.dispatchpath[i];
20                         }
21
22                         if (node)
23                                 this.renderTabMenu(node, url);
24                 }
25         },
26
27         handleMenuExpand: function(ev) {
28                 var a = ev.target, ul1 = a.parentNode.parentNode, ul2 = a.nextElementSibling;
29
30                 document.querySelectorAll('ul.mainmenu.l1 > li.active').forEach(function(li) {
31                         if (li !== a.parentNode)
32                                 li.classList.remove('active');
33                 });
34
35                 if (!ul2)
36                         return;
37
38                 if (ul2.parentNode.offsetLeft + ul2.offsetWidth <= ul1.offsetLeft + ul1.offsetWidth)
39                         ul2.classList.add('align-left');
40
41                 ul1.classList.add('active');
42                 a.parentNode.classList.add('active');
43                 a.blur();
44
45                 ev.preventDefault();
46                 ev.stopPropagation();
47         },
48
49         renderMainMenu: function(tree, url, level) {
50                 var l = (level || 0) + 1,
51                     ul = E('ul', { 'class': 'mainmenu l%d'.format(l) }),
52                     children = ui.menu.getChildren(tree);
53
54                 if (children.length == 0 || l > 2)
55                         return E([]);
56
57                 for (var i = 0; i < children.length; i++) {
58                         var isActive = (L.env.dispatchpath[l] == children[i].name),
59                             activeClass = 'mainmenu-item-%s%s'.format(children[i].name, isActive ? ' selected' : '');
60
61                         ul.appendChild(E('li', { 'class': activeClass }, [
62                                 E('a', {
63                                         'href': L.url(url, children[i].name),
64                                         'click': (l == 1) ? this.handleMenuExpand : null,
65                                 }, [ _(children[i].title) ]),
66                                 this.renderMainMenu(children[i], url + '/' + children[i].name, l)
67                         ]));
68                 }
69
70                 if (l == 1) {
71                         var container = document.querySelector('#mainmenu');
72
73                         container.appendChild(ul);
74                         container.style.display = '';
75                 }
76
77                 return ul;
78         },
79
80         renderModeMenu: function(tree) {
81                 var ul = document.querySelector('#modemenu'),
82                     children = ui.menu.getChildren(tree);
83
84                 for (var i = 0; i < children.length; i++) {
85                         var isActive = (L.env.requestpath.length ? children[i].name == L.env.requestpath[0] : i == 0);
86
87                         ul.appendChild(E('li', {}, [
88                                 E('a', {
89                                         'href': L.url(children[i].name),
90                                         'class': isActive ? 'active' : null
91                                 }, [ _(children[i].title) ])
92                         ]));
93
94                         if (isActive)
95                                 this.renderMainMenu(children[i], children[i].name);
96                 }
97
98                 if (ul.children.length > 1)
99                         ul.style.display = '';
100         },
101
102         renderTabMenu: function(tree, url, level) {
103                 var container = document.querySelector('#tabmenu'),
104                     l = (level || 0) + 1,
105                     ul = E('ul', { 'class': 'cbi-tabmenu' }),
106                     children = ui.menu.getChildren(tree),
107                     activeNode = null;
108
109                 if (children.length == 0)
110                         return E([]);
111
112                 for (var i = 0; i < children.length; i++) {
113                         var isActive = (L.env.dispatchpath[l + 2] == children[i].name),
114                             activeClass = isActive ? ' cbi-tab' : '',
115                             className = 'tabmenu-item-%s %s'.format(children[i].name, activeClass);
116
117                         ul.appendChild(E('li', { 'class': className }, [
118                                 E('a', { 'href': L.url(url, children[i].name) }, [ _(children[i].title) ] )
119                         ]));
120
121                         if (isActive)
122                                 activeNode = children[i];
123                 }
124
125                 container.appendChild(ul);
126                 container.style.display = '';
127
128                 if (activeNode)
129                         container.appendChild(this.renderTabMenu(activeNode, url + '/' + activeNode.name, l));
130
131                 return ul;
132         }
133 });