Sidenav.js
3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//this defines a simple model class for loading basic page data which is read from a json file
var fs = require('fs');
module.exports = function() {
var $navList = null;
var $active_page = null;
var $breadcrumbs = {};
var nav_items = {}
this.mark_active_item = function(active_page) {
$active_page = active_page;
$breadcrumbs = {};
if($navList) {
this.mark_items($navList , 1);
if('links' in $breadcrumbs && 'reverse' in $breadcrumbs['links']) $breadcrumbs['links'].reverse();
}
}
this.set_items = function(navList) {
$navList = navList;
}
this.get_items = function() {
return nav_items;
}
this.mark_items = function(navList , level) {
this.reset_items(navList);
var ret = false;
for(var i = 0 ; i < navList.length; i++)
{
var item = navList[i];
item['icon'] = item['icon'] || false;
//if there is no icon for this item, we set it as false
//otherwise in recursive modes it will lookup the parent's scope and use that one's icon (Mustache only)
item['class'] = item['class'] || false;//same as above
item['submenu?'] = ('submenu' in item);//same as above
item['badge'] = item['badge'] || false;//same as above
item['label'] = item['label'] || false;//same as above
item['level-'+level] = true;//in printing out menu items, we use a partial recursively, but we have different needs for level-1 & level-2, etc items ... so we should know on what level we are
for(var l = level - 1 ; l > 0 ; l--) item['level-'+l] = false;
//why? because when we have "level-2"=true then parent's "level-1" will also be true,
//and mustache looks up the parent context's value as well, so the part between {{#level-1}}{{/level-1}} will be
//executed even when we are printing level-2 menu items (i.e submenu) recursively
//see views/layouts/partials/default/sidenav/items.mustache
//maybe using something like handlebars with a little bit of logic is better here
//or perhaps not using recursive partials, and a different partial for each submenu level
if($active_page != null && $active_page == item['link'])
{
item['class'] = 'active';
if(item['submenu?']) item['class'] += ' no-active-child';//rare case, it means that this item has been directly selected, not a child of it, so it's not opened and take care of the caret using "no-active-child" class
$breadcrumbs['title'] = item['title'];//add the active page's title to breadcrumb object
ret = true;//this item is active so we return true
}//if current page
if(item['submenu?'])
{
isOpen = this.mark_items(item['submenu'] , level+1);
if(isOpen)
{
item['class'] = 'active open';//an item in the submenu of this item is active, so set this as "active" & "open"
//create the array if it doesn't exist
$breadcrumbs['links'] = $breadcrumbs['links'] || [];
//add the parent of this active submenu item to the breadcrumbs list
$breadcrumbs['links'].push({
'link': item['link'] || '#',
'title': item['title']
});
ret = true;
}
}//it has submenu
if(item['link'] != null) nav_items[item['link']] = true;
}//for
return ret;
}
//this navList is used multiple times to produce multiple pages in one place
//therefore we need to reset the classes we assigned to previously "active" or "open" items and recalculate
this.reset_items = function(navList) {
for(var i in navList)
{
if(!navList.hasOwnProperty(i)) continue;
var item = navList[i];
item['class'] = false;
if('submenu' in item)
{
this.reset_items(item['submenu']);
}
}
}
this.get_breadcrumbs = function() {
return $breadcrumbs
}
}