Files: 3e757a68dfb99a069819809d6d5e59e86d3bc91f / menu.js
3255 bytesRaw
1 | var h = require('hyperscript') |
2 | var u = require('./util') |
3 | var each = u.each |
4 | var find = u.find |
5 | |
6 | function displayable (el) { |
7 | return el.style.display !== 'none' |
8 | } |
9 | |
10 | function toggle_focus(el) { |
11 | if(el.style.display === 'none') |
12 | focus(el) |
13 | else |
14 | blur(el) |
15 | } |
16 | |
17 | function focus(el) { |
18 | if(el.style.display !== 'flex') { |
19 | el.style.display = 'flex' |
20 | el.dispatchEvent(new CustomEvent('focus', {target: el})) |
21 | } |
22 | } |
23 | |
24 | function blur (el) { |
25 | if(el.style.display !== 'none') { |
26 | el.style.display = 'none' |
27 | el.dispatchEvent(new CustomEvent('blur', {target: el})) |
28 | } |
29 | } |
30 | |
31 | function moveTo(el, list, i) { |
32 | if(!list.children.length || i >= list.children.length) |
33 | list.appendChild(el) |
34 | else |
35 | list.insertBefore(el, list.children[i]) |
36 | } |
37 | |
38 | module.exports = function (list, onSelect) { |
39 | var menu = h('ul.nav.navbar-nav') |
40 | var header = h('div.navbar-header', |
41 | // Page brand |
42 | h('a.navbar-brand.logo', {href: "#"}, "PB")) |
43 | header.insertBefore(menu, null) |
44 | var wrap = header |
45 | |
46 | var selection |
47 | |
48 | function tab_button (el, onclick) { |
49 | var link = h('a.shrink.hypertabs__button', {href: '#', onclick: function (ev) { |
50 | if(ev.shiftKey) toggle_focus(el) |
51 | else { |
52 | each(list.children, function (tab) { |
53 | if(tab == el) focus(tab) |
54 | else blur(tab) |
55 | }) |
56 | } |
57 | ev.preventDefault() |
58 | ev.stopPropagation() |
59 | }}, el.title || el.id || el.tagName) |
60 | var rm = h('button.hypertabs__x.close', {href: '#', type: 'button', onclick: function (ev) { |
61 | el.parentNode.removeChild(el) |
62 | menu.removeChild(wrap) |
63 | }}, 'x') |
64 | |
65 | var wrap = h('li', link, rm) |
66 | |
67 | function isSelected () { |
68 | if(displayable(el)) |
69 | wrap.classList.add('active') |
70 | else |
71 | wrap.classList.remove('active') |
72 | |
73 | if(el.classList.contains('hypertabs--notify')) { |
74 | wrap.classList.add('hypertabs--notify') |
75 | } else |
76 | wrap.classList.remove('hypertabs--notify') |
77 | } |
78 | |
79 | new MutationObserver(function (changes) { |
80 | if(el.title !== link.innerText) |
81 | link.innerText = el.title || el.id || el.tagName |
82 | isSelected() |
83 | onSelect && onSelect() |
84 | }).observe(el, {attributes: true, attributeFilter: ['title', 'style', 'class']}) |
85 | |
86 | isSelected() |
87 | wrap.follows = el |
88 | return wrap |
89 | } |
90 | |
91 | new MutationObserver(function (changes) { |
92 | //iterate over the list, and check that menu is in same order, |
93 | //add any which do not exist, remove any which no longer exist. |
94 | |
95 | //check if a tab represented by a menu item has been removed. |
96 | each(menu.children, function (btn) { |
97 | if(btn.follows.parentNode != list) menu.removeChild(btn) |
98 | }) |
99 | |
100 | //check if each thing in the list has a tab. |
101 | each(list.children, function (tab, i) { |
102 | var j |
103 | if(menu.children[i] && menu.children[i].follows === tab) { |
104 | //already set, and in correct place. do nothing |
105 | } else if(~(j = find(menu, function (btn) { return btn.follows === tab }))) { |
106 | moveTo(menu[j], list, i) |
107 | } else { |
108 | menu.appendChild(tab_button(tab)) } |
109 | }) |
110 | |
111 | //check if a tab represented by a menu item has been removed. |
112 | each(menu.children, function (btn) { |
113 | if(btn.follows.parentNode != list) menu.removeChild(btn) |
114 | }) |
115 | |
116 | }).observe(list, {childList: true}) |
117 | return wrap |
118 | } |
119 |
Built with git-ssb-web