git ssb

16+

Dominic / patchbay



Tree: d3dcc2d7640822834366e1c87af9581a92ef545e

Files: d3dcc2d7640822834366e1c87af9581a92ef545e / modules_core / tabs.js

5714 bytesRaw
1var Tabs = require('hypertabs')
2var h = require('hyperscript')
3var keyscroll = require('../keyscroll')
4var open = require('open-external')
5
6function ancestor (el) {
7 if(!el) return
8 if(el.tagName !== 'A') return ancestor(el.parentElement)
9 return el
10}
11
12exports.needs = {
13 screen_view: 'first',
14 search_box: 'first',
15 menu: 'first',
16 external_confirm:'first'
17}
18
19exports.gives = 'screen_view'
20
21exports.create = function (api) {
22 return function (path) {
23 if(path !== 'tabs')
24 return
25
26 function setSelected (indexes) {
27 var ids = indexes.map(function (index) {
28 return tabs.get(index).id
29 })
30 if(search)
31 if(ids.length > 1)
32 search.value = 'split('+ids.join(',')+')'
33 else
34 search.value = ids[0]
35 }
36
37 var search
38 var tabs = Tabs(setSelected)
39
40 search = api.search_box(function (path, change) {
41
42 if(tabs.has(path)) {
43 tabs.select(path)
44 return true
45 }
46 var el = api.screen_view(path)
47
48 if(el) {
49 if(!el.title) el.title = path
50 el.scroll = keyscroll(el.querySelector('.scroller__content'))
51 tabs.add(el, change)
52 // localStorage.openTabs = JSON.stringify(tabs.tabs)
53 return change
54 }
55 })
56
57 //reposition hypertabs menu to inside a container...
58 tabs.insertBefore(h('div.header.row',
59 h('div.header__tabs.row', tabs.firstChild), //tabs
60 h('div.header__search.row.end', h('div', search), api.menu())
61 ), tabs.firstChild)
62 // tabs.insertBefore(search, tabs.firstChild.nextSibling)
63
64 var saved = []
65 // try { saved = JSON.parse(localStorage.openTabs) }
66 // catch (_) { }
67
68 if(!saved || saved.length < 3)
69 saved = ['/public', '/private', '/notifications', '/data']
70
71 saved.forEach(function (path) {
72 var el = api.screen_view(path)
73 if(!el) return
74 el.id = el.id || path
75 if (!el) return
76 el.scroll = keyscroll(el.querySelector('.scroller__content'))
77 if(el) tabs.add(el, false, false)
78 })
79
80 tabs.select(0)
81
82 //handle link clicks
83 window.onclick = function (ev) {
84 var link = ancestor(ev.target)
85 if(!link) return
86 var path = link.hash.substring(1)
87
88 ev.preventDefault()
89 ev.stopPropagation()
90
91 //let the application handle this link
92 if (link.getAttribute('href') === '#') return
93
94 //open external links.
95 //this ought to be made into something more runcible
96 if(link.href && open.isExternal(link.href)) return api.external_confirm(link.href)
97
98 if(tabs.has(path))
99 return tabs.select(path, !ev.ctrlKey, !!ev.shiftKey)
100
101 var el = api.screen_view(path)
102 if(el) {
103 el.id = el.id || path
104 el.scroll = keyscroll(el.querySelector('.scroller__content'))
105 tabs.add(el, !ev.ctrlKey, !!ev.shiftKey)
106 // localStorage.openTabs = JSON.stringify(tabs.tabs)
107 }
108
109 return false
110 }
111
112 window.addEventListener('keydown', function (ev) {
113 if (ev.target.nodeName === 'INPUT' || ev.target.nodeName === 'TEXTAREA')
114 return
115 switch(ev.keyCode) {
116
117 // scroll through tabs
118 case 72: // h
119 return tabs.selectRelative(-1)
120 case 76: // l
121 return tabs.selectRelative(1)
122
123 // scroll through messages
124 case 74: // j
125 return tabs.get(tabs.selected[0]).scroll(1)
126 case 75: // k
127 return tabs.get(tabs.selected[0]).scroll(-1)
128
129 // close a tab
130 case 88: // x
131 if (tabs.selected) {
132 var sel = tabs.selected
133 var i = sel.reduce(function (a, b) { return Math.min(a, b) })
134 tabs.remove(sel)
135 tabs.select(Math.max(i-1, 0))
136 }
137 return
138
139 // activate the search field
140 case 191: // /
141 if (ev.shiftKey)
142 search.activate('?', ev)
143 else
144 search.activate('/', ev)
145 return
146
147 // navigate to a feed
148 case 50: // 2
149 if (ev.shiftKey)
150 search.activate('@', ev)
151 return
152
153 // navigate to a channel
154 case 51: // 3
155 if (ev.shiftKey)
156 search.activate('#', ev)
157 return
158
159 // navigate to a message
160 case 53: // 5
161 if (ev.shiftKey)
162 search.activate('%', ev)
163 return
164 }
165 })
166
167 // errors tab
168 var errorsContent = h('div.column.scroller__content')
169 var errors = h('div.column.scroller', {
170 id: 'errors',
171 style: {'overflow':'auto'}
172 }, h('div.scroller__wrapper',
173 errorsContent
174 )
175 )
176
177 // remove loader error handler
178 if (window.onError) {
179 window.removeEventListener('error', window.onError)
180 delete window.onError
181 }
182
183 // put errors in a tab
184 window.addEventListener('error', function (ev) {
185 var err = ev.error || ev
186 if(!tabs.has('errors'))
187 tabs.add(errors, false)
188 var el = h('div.message',
189 h('strong', err.message),
190 h('pre', err.stack))
191 if (errorsContent.firstChild)
192 errorsContent.insertBefore(el, errorsContent.firstChild)
193 else
194 errorsContent.appendChild(el)
195 })
196
197 if (process.versions.electron) {
198 window.addEventListener('contextmenu', function (ev) {
199 ev.preventDefault()
200 var remote = require('electron').remote
201 var Menu = remote.Menu
202 var MenuItem = remote.MenuItem
203 var menu = new Menu()
204 menu.append(new MenuItem({
205 label: 'Inspect Element',
206 click: function () {
207 remote.getCurrentWindow().inspectElement(ev.x, ev.y)
208 }
209 }))
210 menu.popup(remote.getCurrentWindow())
211 })
212 }
213
214 return tabs
215 }
216
217}
218

Built with git-ssb-web