datafolder 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -0
- package/index.js +3 -0
- package/package.json +27 -0
- package/sample.js +37 -0
- package/scripts/airbnb.js +73 -0
- package/scripts/airbnb2.js +74 -0
- package/scripts/airbnb2_queries.js +231 -0
- package/scripts/airbnb_queries.js +264 -0
- package/scripts/downloadFile.js +42 -0
- package/scripts/express.js +46 -0
- package/scripts/fastify.js +79 -0
- package/scripts/flights.js +75 -0
- package/scripts/flights2.js +81 -0
- package/scripts/flights2_queries.js +453 -0
- package/scripts/flights_queries.js +403 -0
- package/src/QyAcl.js +252 -0
- package/src/QyAclSaver.js +14 -0
- package/src/QyAclSaver_Worker.js +29 -0
- package/src/QyAclWriter.js +19 -0
- package/src/QyBatch.js +501 -0
- package/src/QyBinWriter.js +140 -0
- package/src/QyCD.js +61 -0
- package/src/QyCache.js +212 -0
- package/src/QyCompressor.js +60 -0
- package/src/QyCompressor_Worker.js +13 -0
- package/src/QyDB.js +122 -0
- package/src/QyDefaultOptions.js +59 -0
- package/src/QyDir.js +192 -0
- package/src/QyFetch.js +38 -0
- package/src/QyFile.js +124 -0
- package/src/QyFileContentUtils.js +175 -0
- package/src/QyFileLogger.js +58 -0
- package/src/QyIndex.js +237 -0
- package/src/QyIndexPropTree.js +92 -0
- package/src/QyIntersectNode.js +48 -0
- package/src/QyItem.js +105 -0
- package/src/QyJsonSaver.js +20 -0
- package/src/QyKVData.js +289 -0
- package/src/QyKVDataCleaner.js +17 -0
- package/src/QyKVDataCleaner_Worker.js +94 -0
- package/src/QyKVDataLoader.js +65 -0
- package/src/QyKVDataSaver.js +17 -0
- package/src/QyKVDataSaver_Worker.js +81 -0
- package/src/QyLogFileSaver.js +14 -0
- package/src/QyLogFileSaver_Worker.js +26 -0
- package/src/QyLogger.js +76 -0
- package/src/QyMessageWorker.js +41 -0
- package/src/QyMessager.js +84 -0
- package/src/QyMessager_Run.js +13 -0
- package/src/QyMod.js +15 -0
- package/src/QyOpRunner.js +73 -0
- package/src/QyQueue.js +60 -0
- package/src/QySaver.js +83 -0
- package/src/QySnapshotCompactor.js +17 -0
- package/src/QySnapshotCompactor_Worker.js +151 -0
- package/src/QySnapshotSaver.js +17 -0
- package/src/QySnapshotSaver_Worker.js +164 -0
- package/src/QySnapshots.js +354 -0
- package/src/QyStructure.js +50 -0
- package/src/QyTrigger.js +133 -0
- package/src/QyUnionNode.js +105 -0
- package/src/QyUtils.js +250 -0
- package/src/QyWorker.js +33 -0
- package/src/hackernews.js +93 -0
- package/src/rpc/evalCode.js +9 -0
- package/src/rpc/getFileContent.js +16 -0
- package/src/rpc/getSubItems.js +32 -0
- package/src/rpc/queryFiles.js +33 -0
- package/src/rpc/reloadRpc.js +1 -0
- package/src/simulate.js +114 -0
- package/src/simulate2.js +110 -0
- package/src/soc_pokec.js +43 -0
- package/static/bootstrap-5.3.8-dist/css/bootstrap.min.css +6 -0
- package/static/bootstrap-5.3.8-dist/js/bootstrap.bundle.js +6312 -0
- package/static/datafolderui/QyStyledElement.js +30 -0
- package/static/datafolderui/QyUIFolderTree.js +203 -0
- package/static/datafolderui/QyUIUtils.js +42 -0
- package/static/datafolderui/display-tree.js +108 -0
- package/static/datafolderui/explore-tree.js +122 -0
- package/static/datafolderui/folder-tree.js +5 -0
- package/static/datafolderui/hscrpt.js +25 -0
- package/static/datafolderui/index.css +6 -0
- package/static/datafolderui/index.html +20 -0
- package/static/datafolderui/json-view.js +74 -0
- package/static/datafolderui/kv-input.js +66 -0
- package/static/datafolderui/list-input.js +52 -0
- package/static/datafolderui/main-page.js +98 -0
- package/static/datafolderui/num-input.js +27 -0
- package/static/datafolderui/query-editor.js +229 -0
- package/static/datafolderui/querySelectorShadowRoot.js +24 -0
- package/static/datafolderui/resizable-input.js +67 -0
- package/static/favicon.ico +0 -0
- package/static/icons-1.13.1/font/bootstrap-icons.min.css +5 -0
- package/static/icons-1.13.1/font/fonts/bootstrap-icons.woff +0 -0
- package/static/icons-1.13.1/font/fonts/bootstrap-icons.woff2 +0 -0
- package/static/json-view/dist/jsonview.js +433 -0
- package/static/tree.js/tree.css +106 -0
- package/static/tree.js/tree.js +374 -0
- package/static/w2ui/dist/w2ui.min.css +2 -0
- package/static/w2ui/src/less/icons/icons.json +1 -0
- package/static/w2ui/src/less/icons/preview.html +33 -0
- package/static/w2ui/src/less/icons/readme.md +15 -0
- package/static/w2ui/src/less/icons/svg/box.svg +3 -0
- package/static/w2ui/src/less/icons/svg/check.svg +3 -0
- package/static/w2ui/src/less/icons/svg/colors.svg +3 -0
- package/static/w2ui/src/less/icons/svg/columns.svg +5 -0
- package/static/w2ui/src/less/icons/svg/cross.svg +4 -0
- package/static/w2ui/src/less/icons/svg/drop.svg +6 -0
- package/static/w2ui/src/less/icons/svg/empty.svg +3 -0
- package/static/w2ui/src/less/icons/svg/eye-dropper.svg +4 -0
- package/static/w2ui/src/less/icons/svg/info.svg +8 -0
- package/static/w2ui/src/less/icons/svg/paste.svg +4 -0
- package/static/w2ui/src/less/icons/svg/pencil.svg +5 -0
- package/static/w2ui/src/less/icons/svg/plus.svg +3 -0
- package/static/w2ui/src/less/icons/svg/reload.svg +5 -0
- package/static/w2ui/src/less/icons/svg/search.svg +3 -0
- package/static/w2ui/src/less/icons/svg/settings.svg +8 -0
- package/static/w2ui/src/less/icons/w2ui-font.css +36 -0
- package/static/w2ui/src/less/icons/w2ui-font.woff +0 -0
- package/static/w2ui/src/less/src/buttons.less +184 -0
- package/static/w2ui/src/less/src/common.less +541 -0
- package/static/w2ui/src/less/src/fields.less +302 -0
- package/static/w2ui/src/less/src/form.less +319 -0
- package/static/w2ui/src/less/src/grid.less +1057 -0
- package/static/w2ui/src/less/src/icons.less +37 -0
- package/static/w2ui/src/less/src/layout.less +86 -0
- package/static/w2ui/src/less/src/mixins.less +87 -0
- package/static/w2ui/src/less/src/popup.less +277 -0
- package/static/w2ui/src/less/src/sidebar.less +343 -0
- package/static/w2ui/src/less/src/tabs.less +145 -0
- package/static/w2ui/src/less/src/toolbar.less +219 -0
- package/static/w2ui/src/less/src/tooltip.less +948 -0
- package/static/w2ui/src/less/w2ui.less +196 -0
- package/static/w2ui/src/locale/az-az.json +114 -0
- package/static/w2ui/src/locale/ba-ba.json +114 -0
- package/static/w2ui/src/locale/bg-bg.json +114 -0
- package/static/w2ui/src/locale/ca-es.json +114 -0
- package/static/w2ui/src/locale/da-dk.json +114 -0
- package/static/w2ui/src/locale/de-de.json +114 -0
- package/static/w2ui/src/locale/en-gb.json +17 -0
- package/static/w2ui/src/locale/en-us.json +17 -0
- package/static/w2ui/src/locale/es-ar.json +115 -0
- package/static/w2ui/src/locale/es-cr.json +119 -0
- package/static/w2ui/src/locale/es-es.json +114 -0
- package/static/w2ui/src/locale/es-mx.json +114 -0
- package/static/w2ui/src/locale/fr-fr.json +114 -0
- package/static/w2ui/src/locale/gl-es.json +114 -0
- package/static/w2ui/src/locale/hr-hr.json +114 -0
- package/static/w2ui/src/locale/hu-hu.json +114 -0
- package/static/w2ui/src/locale/id-id.json +114 -0
- package/static/w2ui/src/locale/it-it.json +114 -0
- package/static/w2ui/src/locale/ja-jp.json +114 -0
- package/static/w2ui/src/locale/kk-kz.json +116 -0
- package/static/w2ui/src/locale/ko-kr.json +114 -0
- package/static/w2ui/src/locale/lt-lt.json +114 -0
- package/static/w2ui/src/locale/nl-nl.json +114 -0
- package/static/w2ui/src/locale/no-no.json +114 -0
- package/static/w2ui/src/locale/pl-pl.json +114 -0
- package/static/w2ui/src/locale/pt-br.json +114 -0
- package/static/w2ui/src/locale/ru-ru.json +116 -0
- package/static/w2ui/src/locale/sk-sk.json +114 -0
- package/static/w2ui/src/locale/sl-si.json +116 -0
- package/static/w2ui/src/locale/sr-rs.json +114 -0
- package/static/w2ui/src/locale/tr-tr.json +114 -0
- package/static/w2ui/src/locale/uk-ua.json +114 -0
- package/static/w2ui/src/locale/zh-cn.json +114 -0
- package/static/w2ui/src/locale/zh-tw.json +114 -0
- package/static/w2ui/src/query.js +583 -0
- package/static/w2ui/src/readme.md +11 -0
- package/static/w2ui/src/w2base.js +311 -0
- package/static/w2ui/src/w2compat.js +207 -0
- package/static/w2ui/src/w2field.js +1854 -0
- package/static/w2ui/src/w2form.js +2411 -0
- package/static/w2ui/src/w2grid.js +8916 -0
- package/static/w2ui/src/w2layout.js +1194 -0
- package/static/w2ui/src/w2locale.js +129 -0
- package/static/w2ui/src/w2popup.js +909 -0
- package/static/w2ui/src/w2sidebar.js +1769 -0
- package/static/w2ui/src/w2tabs.js +669 -0
- package/static/w2ui/src/w2toolbar.js +1180 -0
- package/static/w2ui/src/w2tooltip.js +3134 -0
- package/static/w2ui/src/w2utils.js +2457 -0
|
@@ -0,0 +1,1769 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Part of w2ui 2.0 library
|
|
3
|
+
* - Dependencies: mQuery, w2utils, w2base, w2tooltip, w2menu
|
|
4
|
+
*
|
|
5
|
+
* == TODO ==
|
|
6
|
+
* - dbl click should be like it is in grid (with timer not HTML dbl click event)
|
|
7
|
+
* - node.style is misleading - should be there to apply color for example
|
|
8
|
+
* - node.plus - is not working
|
|
9
|
+
*
|
|
10
|
+
* == 2.0 changes
|
|
11
|
+
* - remove jQuery dependency
|
|
12
|
+
* - deprecarted obj.img, node.img
|
|
13
|
+
* - CSP - fixed inline events
|
|
14
|
+
* - observeResize for the box
|
|
15
|
+
* - search(..., compare) - comparison function
|
|
16
|
+
* - editable = true
|
|
17
|
+
* - edit(id) - new method
|
|
18
|
+
* - onEdit, onRename - new events
|
|
19
|
+
* - reorder = true - to allow reorder
|
|
20
|
+
* - mouseDown - for reorder
|
|
21
|
+
* - onReorder, onDragStart, onDragOver - events
|
|
22
|
+
* - this.mutlti - for multi select (ctrl for one at a time and shift for range)
|
|
23
|
+
* - onSelect, onUnselect - new events
|
|
24
|
+
* - prev(), next(), getChain()
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import { w2base } from './w2base.js'
|
|
28
|
+
import { w2ui, w2utils } from './w2utils.js'
|
|
29
|
+
import { query } from './query.js'
|
|
30
|
+
import { w2tooltip, w2menu } from './w2tooltip.js'
|
|
31
|
+
|
|
32
|
+
class w2sidebar extends w2base {
|
|
33
|
+
constructor(options) {
|
|
34
|
+
super(options.name)
|
|
35
|
+
this.name = null
|
|
36
|
+
this.box = null
|
|
37
|
+
this.sidebar = null
|
|
38
|
+
this.parent = null
|
|
39
|
+
this.nodes = [] // Sidebar child nodes
|
|
40
|
+
this.menu = []
|
|
41
|
+
this.routeData = {} // data for dynamic routes
|
|
42
|
+
this.selected = null // current selected node (readonly)
|
|
43
|
+
this.icon = null
|
|
44
|
+
this.style = ''
|
|
45
|
+
this.topHTML = ''
|
|
46
|
+
this.bottomHTML = ''
|
|
47
|
+
this.multi = false
|
|
48
|
+
this.editable = false
|
|
49
|
+
this.reorder = false
|
|
50
|
+
this.flatButton = false
|
|
51
|
+
this.keyboard = true
|
|
52
|
+
this.flat = false
|
|
53
|
+
this.hasFocus = false
|
|
54
|
+
this.levelPadding = 12
|
|
55
|
+
this.toggleAlign = 'right' // can be left or right
|
|
56
|
+
this.skipRefresh = false
|
|
57
|
+
this.tabIndex = null // will only be set if > 0 and not null
|
|
58
|
+
this.handle = { width: 0, style: '', text: '', tooltip: '' },
|
|
59
|
+
this.badge = null
|
|
60
|
+
this.onClick = null // Fire when user click on Node Text
|
|
61
|
+
this.onSelect = null
|
|
62
|
+
this.onUnselect = null
|
|
63
|
+
this.onDblClick = null // Fire when user dbl clicks
|
|
64
|
+
this.onMouseEnter = null // mouse enter/leave over an item
|
|
65
|
+
this.onMouseLeave = null
|
|
66
|
+
this.onContextMenu = null
|
|
67
|
+
this.onMenuClick = null // when context menu item selected
|
|
68
|
+
this.onExpand = null // Fire when node expands
|
|
69
|
+
this.onCollapse = null // Fire when node collapses
|
|
70
|
+
this.onKeydown = null
|
|
71
|
+
this.onRender = null
|
|
72
|
+
this.onRefresh = null
|
|
73
|
+
this.onResize = null
|
|
74
|
+
this.onDestroy = null
|
|
75
|
+
this.onFocus = null
|
|
76
|
+
this.onBlur = null
|
|
77
|
+
this.onFlat = null
|
|
78
|
+
this.onEdit = null
|
|
79
|
+
this.onRename = null
|
|
80
|
+
this.onReorder = null
|
|
81
|
+
this.onDragStart = null
|
|
82
|
+
this.onDragOver = null
|
|
83
|
+
this.node_template = {
|
|
84
|
+
id: null,
|
|
85
|
+
text: '',
|
|
86
|
+
order: null,
|
|
87
|
+
count: null,
|
|
88
|
+
icon: null,
|
|
89
|
+
nodes: [],
|
|
90
|
+
style: '', // additional style for subitems
|
|
91
|
+
route: null,
|
|
92
|
+
selected: false,
|
|
93
|
+
expanded: false,
|
|
94
|
+
hidden: false,
|
|
95
|
+
disabled: false,
|
|
96
|
+
group: false, // if true, it will build as a group
|
|
97
|
+
groupShowHide: true,
|
|
98
|
+
collapsible: false,
|
|
99
|
+
plus: false, // if true, plus will be shown even if there is no sub nodes
|
|
100
|
+
childOffset: 0,
|
|
101
|
+
// events
|
|
102
|
+
onClick: null,
|
|
103
|
+
onDblClick: null,
|
|
104
|
+
onContextMenu: null,
|
|
105
|
+
onExpand: null,
|
|
106
|
+
onCollapse: null,
|
|
107
|
+
// internal
|
|
108
|
+
parent: null, // node object
|
|
109
|
+
sidebar: null
|
|
110
|
+
}
|
|
111
|
+
this.last = {
|
|
112
|
+
badge: {},
|
|
113
|
+
renaming: false,
|
|
114
|
+
move: null, // object, move details
|
|
115
|
+
}
|
|
116
|
+
let nodes = options.nodes
|
|
117
|
+
delete options.nodes
|
|
118
|
+
// mix in options
|
|
119
|
+
Object.assign(this, options)
|
|
120
|
+
// add item via method to makes sure item_template is applied
|
|
121
|
+
if (Array.isArray(nodes)) this.add(nodes)
|
|
122
|
+
// need to reassign back to keep it in config
|
|
123
|
+
options.nodes = nodes
|
|
124
|
+
|
|
125
|
+
// render if box specified
|
|
126
|
+
if (typeof this.box == 'string') this.box = query(this.box).get(0)
|
|
127
|
+
if (this.box) this.render(this.box)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
add(parent, nodes) {
|
|
131
|
+
if (arguments.length == 1) {
|
|
132
|
+
// need to be in reverse order
|
|
133
|
+
nodes = arguments[0]
|
|
134
|
+
parent = this
|
|
135
|
+
}
|
|
136
|
+
if (typeof parent == 'string') parent = this.get(parent)
|
|
137
|
+
if (parent == null || parent == '') parent = this
|
|
138
|
+
return this.insert(parent, null, nodes)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
insert(parent, before, nodes) {
|
|
142
|
+
let txt, ind, tmp, node, nd
|
|
143
|
+
if (arguments.length == 2 && typeof parent == 'string') {
|
|
144
|
+
// need to be in reverse order
|
|
145
|
+
nodes = arguments[1]
|
|
146
|
+
before = arguments[0]
|
|
147
|
+
if (before != null) {
|
|
148
|
+
ind = this.get(before)
|
|
149
|
+
if (ind == null) {
|
|
150
|
+
if (!Array.isArray(nodes)) nodes = [nodes]
|
|
151
|
+
if (nodes[0].caption != null && nodes[0].text == null) {
|
|
152
|
+
console.log('NOTICE: sidebar node.caption property is deprecated, please use node.text. Node -> ', nodes[0])
|
|
153
|
+
nodes[0].text = nodes[0].caption
|
|
154
|
+
}
|
|
155
|
+
txt = nodes[0].text
|
|
156
|
+
console.log('ERROR: Cannot insert node "'+ txt +'" because cannot find node "'+ before +'" to insert before.')
|
|
157
|
+
return null
|
|
158
|
+
}
|
|
159
|
+
parent = this.get(before).parent
|
|
160
|
+
} else {
|
|
161
|
+
parent = this
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (typeof parent == 'string') parent = this.get(parent)
|
|
165
|
+
if (parent == null || parent == '') parent = this
|
|
166
|
+
if (!Array.isArray(nodes)) nodes = [nodes]
|
|
167
|
+
for (let o = 0; o < nodes.length; o++) {
|
|
168
|
+
node = nodes[o]
|
|
169
|
+
if (node.caption != null && node.text == null) {
|
|
170
|
+
console.log('NOTICE: sidebar node.caption property is deprecated, please use node.text')
|
|
171
|
+
node.text = node.caption
|
|
172
|
+
}
|
|
173
|
+
if (typeof node.id == null) {
|
|
174
|
+
txt = node.text
|
|
175
|
+
console.log('ERROR: Cannot insert node "'+ txt +'" because it has no id.')
|
|
176
|
+
continue
|
|
177
|
+
}
|
|
178
|
+
if (this.get(this, node.id) != null) {
|
|
179
|
+
console.log('ERROR: Cannot insert node with id='+ node.id +' (text: '+ node.text + ') because another node with the same id already exists.')
|
|
180
|
+
continue
|
|
181
|
+
}
|
|
182
|
+
tmp = Object.assign({}, this.node_template, node)
|
|
183
|
+
tmp.sidebar = this
|
|
184
|
+
tmp.parent = parent
|
|
185
|
+
nd = tmp.nodes || []
|
|
186
|
+
tmp.nodes = [] // very important to re-init empty nodes array
|
|
187
|
+
if (before == null) { // append to the end
|
|
188
|
+
parent.nodes.push(tmp)
|
|
189
|
+
} else {
|
|
190
|
+
ind = this.get(parent, before, true)
|
|
191
|
+
if (ind == null) {
|
|
192
|
+
console.log('ERROR: Cannot insert node "'+ node.text +'" because cannot find node "'+ before +'" to insert before.')
|
|
193
|
+
return null
|
|
194
|
+
}
|
|
195
|
+
parent.nodes.splice(ind, 0, tmp)
|
|
196
|
+
}
|
|
197
|
+
if (nd.length > 0) {
|
|
198
|
+
this.insert(tmp, null, nd)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (!this.skipRefresh) this.refresh(parent.id)
|
|
202
|
+
return tmp
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
remove() { // multiple arguments
|
|
206
|
+
let effected = 0
|
|
207
|
+
let node
|
|
208
|
+
Array.from(arguments).forEach(arg => {
|
|
209
|
+
node = this.get(arg)
|
|
210
|
+
if (node == null) return
|
|
211
|
+
if (this.selected != null) {
|
|
212
|
+
if (Array.isArray(this.selected)) {
|
|
213
|
+
this.selected.splice(this.selected.indexOf(node.id), 1)
|
|
214
|
+
} else if (this.selected === node.id) {
|
|
215
|
+
this.selected = null
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
let ind = this.get(node.parent, arg, true)
|
|
219
|
+
if (ind == null) return
|
|
220
|
+
if (node.parent.nodes[ind].selected) node.sidebar.unselect(node.id)
|
|
221
|
+
node.parent.nodes.splice(ind, 1)
|
|
222
|
+
node.parent.collapsible = node.parent.nodes.length > 0
|
|
223
|
+
effected++
|
|
224
|
+
})
|
|
225
|
+
if (!this.skipRefresh) {
|
|
226
|
+
if (effected > 0 && arguments.length == 1) this.refresh(node.parent.id); else this.refresh()
|
|
227
|
+
}
|
|
228
|
+
return effected
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
set(parent, id, node) {
|
|
232
|
+
if (arguments.length == 2) {
|
|
233
|
+
// need to be in reverse order
|
|
234
|
+
node = id
|
|
235
|
+
id = parent
|
|
236
|
+
parent = this
|
|
237
|
+
}
|
|
238
|
+
// searches all nested nodes
|
|
239
|
+
if (typeof parent == 'string') parent = this.get(parent)
|
|
240
|
+
if (parent.nodes == null) return null
|
|
241
|
+
for (let i = 0; i < parent.nodes.length; i++) {
|
|
242
|
+
if (parent.nodes[i].id === id) {
|
|
243
|
+
// see if quick update is possible
|
|
244
|
+
let res = this.update(id, node)
|
|
245
|
+
if (Object.keys(res).length != 0) {
|
|
246
|
+
// make sure nodes inserted correctly
|
|
247
|
+
let nodes = node.nodes
|
|
248
|
+
w2utils.extend(parent.nodes[i], node, (nodes != null ? { nodes: [] } : {}))
|
|
249
|
+
if (nodes != null) {
|
|
250
|
+
this.add(parent.nodes[i], nodes)
|
|
251
|
+
}
|
|
252
|
+
if (!this.skipRefresh) this.refresh(id)
|
|
253
|
+
}
|
|
254
|
+
return true
|
|
255
|
+
} else {
|
|
256
|
+
let rv = this.set(parent.nodes[i], id, node)
|
|
257
|
+
if (rv) return true
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return false
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
get(parent, id, returnIndex) { // can be just called get(id) or get(id, true)
|
|
264
|
+
if (arguments.length === 0) {
|
|
265
|
+
let all = []
|
|
266
|
+
let tmp = this.find({})
|
|
267
|
+
for (let t = 0; t < tmp.length; t++) {
|
|
268
|
+
if (tmp[t].id != null) all.push(tmp[t].id)
|
|
269
|
+
}
|
|
270
|
+
return all
|
|
271
|
+
} else {
|
|
272
|
+
if (arguments.length == 1 || (arguments.length == 2 && id === true) ) {
|
|
273
|
+
// need to be in reverse order
|
|
274
|
+
returnIndex = id
|
|
275
|
+
id = parent
|
|
276
|
+
parent = this
|
|
277
|
+
}
|
|
278
|
+
// searches all nested nodes
|
|
279
|
+
if (typeof parent == 'string') parent = this.get(parent)
|
|
280
|
+
if (parent.nodes == null) return null
|
|
281
|
+
for (let i = 0; i < parent.nodes.length; i++) {
|
|
282
|
+
if (parent.nodes[i].id == id) {
|
|
283
|
+
if (returnIndex === true) return i; else return parent.nodes[i]
|
|
284
|
+
} else {
|
|
285
|
+
let rv = this.get(parent.nodes[i], id, returnIndex)
|
|
286
|
+
if (rv || rv === 0) return rv
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return null
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
setCount(id, count, options = {}) {
|
|
294
|
+
let node = this.get(id)
|
|
295
|
+
if (node.group) {
|
|
296
|
+
console.log(`Node "${id}" is a group and groups cannot have counts or badges.`)
|
|
297
|
+
return
|
|
298
|
+
}
|
|
299
|
+
this.last.badge[id] = {
|
|
300
|
+
className: options.className ?? '',
|
|
301
|
+
style: options.style ?? ''
|
|
302
|
+
}
|
|
303
|
+
let btn = query(this.box).find(`#node_${w2utils.escapeId(id)} .w2ui-node-badge`)
|
|
304
|
+
if (btn.length > 0) {
|
|
305
|
+
btn.removeClass()
|
|
306
|
+
.addClass(`w2ui-node-badge ${options.className ?? 'w2ui-node-count'}`)
|
|
307
|
+
.text(count)
|
|
308
|
+
.get(0).style.cssText = options.style || ''
|
|
309
|
+
let item = this.get(id)
|
|
310
|
+
item.count = count
|
|
311
|
+
} else if (!options.noRepeat) {
|
|
312
|
+
this.set(id, { count })
|
|
313
|
+
options.noRepeat = true
|
|
314
|
+
queueMicrotask(() => this.setCount(id, count, options)) // to update styles
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
find(parent, params, results) { // can be just called find({ selected: true })
|
|
319
|
+
// TODO: rewrite with this.each()
|
|
320
|
+
if (arguments.length == 1) {
|
|
321
|
+
// need to be in reverse order
|
|
322
|
+
params = parent
|
|
323
|
+
parent = this
|
|
324
|
+
}
|
|
325
|
+
if (!results) results = []
|
|
326
|
+
// searches all nested nodes
|
|
327
|
+
if (typeof parent == 'string') parent = this.get(parent)
|
|
328
|
+
if (parent.nodes == null) return results
|
|
329
|
+
for (let i = 0; i < parent.nodes.length; i++) {
|
|
330
|
+
let match = true
|
|
331
|
+
for (let prop in params) { // params is an object
|
|
332
|
+
if (parent.nodes[i][prop] != params[prop]) match = false
|
|
333
|
+
}
|
|
334
|
+
if (match) results.push(parent.nodes[i])
|
|
335
|
+
if (parent.nodes[i].nodes.length > 0) results = this.find(parent.nodes[i], params, results)
|
|
336
|
+
}
|
|
337
|
+
return results
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
sort(options, nodes) {
|
|
341
|
+
// default options
|
|
342
|
+
if (!options || typeof options != 'object') options = {}
|
|
343
|
+
if (options.foldersFirst == null) options.foldersFirst = true
|
|
344
|
+
if (options.caseSensitive == null) options.caseSensitive = false
|
|
345
|
+
if (options.reverse == null) options.reverse = false
|
|
346
|
+
|
|
347
|
+
if (nodes == null) {
|
|
348
|
+
nodes = this.nodes
|
|
349
|
+
}
|
|
350
|
+
nodes.sort((a, b) => {
|
|
351
|
+
// folders first
|
|
352
|
+
let isAfolder = (a.nodes && a.nodes.length > 0)
|
|
353
|
+
let isBfolder = (b.nodes && b.nodes.length > 0)
|
|
354
|
+
// both folder or both not folders
|
|
355
|
+
if (options.foldersFirst === false || (!isAfolder && !isBfolder) || (isAfolder && isBfolder)) {
|
|
356
|
+
let aText = a.text
|
|
357
|
+
let bText = b.text
|
|
358
|
+
if (a.order != null) aText = a.order
|
|
359
|
+
if (b.order != null) bText = b.order
|
|
360
|
+
if (!options.caseSensitive) {
|
|
361
|
+
aText = aText.toLowerCase()
|
|
362
|
+
bText = bText.toLowerCase()
|
|
363
|
+
}
|
|
364
|
+
let cmp = w2utils.naturalCompare(aText, bText)
|
|
365
|
+
return (cmp === 1 || cmp === -1) & options.reverse ? -cmp : cmp
|
|
366
|
+
}
|
|
367
|
+
if (isAfolder && !isBfolder) {
|
|
368
|
+
return !options.reverse ? -1 : 1
|
|
369
|
+
}
|
|
370
|
+
if (!isAfolder && isBfolder) {
|
|
371
|
+
return !options.reverse ? 1 : -1
|
|
372
|
+
}
|
|
373
|
+
})
|
|
374
|
+
nodes.forEach(node => {
|
|
375
|
+
if (node.nodes && node.nodes.length > 0) {
|
|
376
|
+
this.sort(options, node.nodes)
|
|
377
|
+
}
|
|
378
|
+
})
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
each(fn, nodes) {
|
|
382
|
+
if (nodes == null) nodes = this.nodes
|
|
383
|
+
nodes.forEach((node) => {
|
|
384
|
+
fn.call(this, node)
|
|
385
|
+
if (node.nodes && node.nodes.length > 0) {
|
|
386
|
+
this.each(fn, node.nodes)
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
search(str, compare = null) {
|
|
392
|
+
let count = 0
|
|
393
|
+
let str2 = str.toLowerCase()
|
|
394
|
+
this.each((node) => {
|
|
395
|
+
let match = false
|
|
396
|
+
if (typeof compare == 'function') {
|
|
397
|
+
match = compare(str, node)
|
|
398
|
+
} else {
|
|
399
|
+
match = !(node.text.toLowerCase().indexOf(str2) === -1)
|
|
400
|
+
}
|
|
401
|
+
if (match) {
|
|
402
|
+
count++
|
|
403
|
+
showParents(node)
|
|
404
|
+
node.hidden = false
|
|
405
|
+
} else {
|
|
406
|
+
node.hidden = true
|
|
407
|
+
}
|
|
408
|
+
})
|
|
409
|
+
this.refresh()
|
|
410
|
+
return count
|
|
411
|
+
|
|
412
|
+
function showParents(node) {
|
|
413
|
+
if (node.parent) {
|
|
414
|
+
node.parent.hidden = false
|
|
415
|
+
showParents(node.parent)
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
show() { // multiple arguments
|
|
421
|
+
let effected = []
|
|
422
|
+
Array.from(arguments).forEach(it => {
|
|
423
|
+
let node = this.get(it)
|
|
424
|
+
if (node == null || node.hidden === false) return
|
|
425
|
+
node.hidden = false
|
|
426
|
+
effected.push(node.id)
|
|
427
|
+
})
|
|
428
|
+
if (effected.length > 0) {
|
|
429
|
+
if (arguments.length == 1) this.refresh(arguments[0]); else this.refresh()
|
|
430
|
+
}
|
|
431
|
+
return effected
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
hide() { // multiple arguments
|
|
435
|
+
let effected = []
|
|
436
|
+
Array.from(arguments).forEach(it => {
|
|
437
|
+
let node = this.get(it)
|
|
438
|
+
if (node == null || node.hidden === true) return
|
|
439
|
+
node.hidden = true
|
|
440
|
+
effected.push(node.id)
|
|
441
|
+
})
|
|
442
|
+
if (effected.length > 0) {
|
|
443
|
+
if (arguments.length == 1) this.refresh(arguments[0]); else this.refresh()
|
|
444
|
+
}
|
|
445
|
+
return effected
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
enable() { // multiple arguments
|
|
449
|
+
let effected = []
|
|
450
|
+
Array.from(arguments).forEach(it => {
|
|
451
|
+
let node = this.get(it)
|
|
452
|
+
if (node == null || node.disabled === false) return
|
|
453
|
+
node.disabled = false
|
|
454
|
+
effected.push(node.id)
|
|
455
|
+
})
|
|
456
|
+
if (effected.length > 0) {
|
|
457
|
+
if (arguments.length == 1) this.refresh(arguments[0]); else this.refresh()
|
|
458
|
+
}
|
|
459
|
+
return effected
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
disable() { // multiple arguments
|
|
463
|
+
let effected = []
|
|
464
|
+
Array.from(arguments).forEach(it => {
|
|
465
|
+
let node = this.get(it)
|
|
466
|
+
if (node == null || node.disabled === true) return
|
|
467
|
+
node.disabled = true
|
|
468
|
+
if (node.selected) this.unselect(node.id)
|
|
469
|
+
effected.push(node.id)
|
|
470
|
+
})
|
|
471
|
+
if (effected.length > 0) {
|
|
472
|
+
if (arguments.length == 1) this.refresh(arguments[0]); else this.refresh()
|
|
473
|
+
}
|
|
474
|
+
return effected
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
select(id) {
|
|
478
|
+
if (Array.isArray(id)) {
|
|
479
|
+
[...id].forEach(id => this.select(id))
|
|
480
|
+
return
|
|
481
|
+
}
|
|
482
|
+
let new_node = this.get(id)
|
|
483
|
+
if (!new_node) return false
|
|
484
|
+
// event before
|
|
485
|
+
let edata = this.trigger('select', { target: id, id, node: new_node })
|
|
486
|
+
if (edata.isCancelled === true) {
|
|
487
|
+
return true
|
|
488
|
+
}
|
|
489
|
+
// if already selected
|
|
490
|
+
if (!this.multi && this.selected == id && new_node.selected) {
|
|
491
|
+
return false
|
|
492
|
+
}
|
|
493
|
+
let $el = query(this.box).find('#node_'+ w2utils.escapeId(id))
|
|
494
|
+
$el.addClass('w2ui-selected')
|
|
495
|
+
.find('.w2ui-icon')
|
|
496
|
+
.addClass('w2ui-icon-selected')
|
|
497
|
+
if ($el.length > 0) {
|
|
498
|
+
if (!this.inView(id)) this.scrollIntoView(id)
|
|
499
|
+
}
|
|
500
|
+
new_node.selected = true
|
|
501
|
+
if (this.multi) {
|
|
502
|
+
if (!Array.isArray(this.selected)) {
|
|
503
|
+
this.selected = this.selected ? [this.selected] : []
|
|
504
|
+
}
|
|
505
|
+
this.selected.push(id)
|
|
506
|
+
} else {
|
|
507
|
+
this.selected = this.multi ? [id] : id
|
|
508
|
+
}
|
|
509
|
+
edata.finish()
|
|
510
|
+
return true
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
unselect(id) {
|
|
514
|
+
// if no arguments provided, unselect selected node
|
|
515
|
+
if (arguments.length === 0) {
|
|
516
|
+
id = this.selected
|
|
517
|
+
}
|
|
518
|
+
if (Array.isArray(id)) {
|
|
519
|
+
[...id].forEach(id => this.unselect(id))
|
|
520
|
+
return
|
|
521
|
+
}
|
|
522
|
+
let current = this.get(id)
|
|
523
|
+
if (!current) return false
|
|
524
|
+
// event before
|
|
525
|
+
let edata = this.trigger('unselect', { target: id, id, node: current })
|
|
526
|
+
if (edata.isCancelled === true) {
|
|
527
|
+
return true
|
|
528
|
+
}
|
|
529
|
+
current.selected = false
|
|
530
|
+
query(this.box).find('#node_'+ w2utils.escapeId(id))
|
|
531
|
+
.removeClass('w2ui-selected')
|
|
532
|
+
.find('.w2ui-icon').removeClass('w2ui-icon-selected')
|
|
533
|
+
if (typeof this.selected == 'string' && this.selected == id) {
|
|
534
|
+
this.selected = null
|
|
535
|
+
}
|
|
536
|
+
if (this.multi && Array.isArray(this.selected)) {
|
|
537
|
+
let ind = this.selected.indexOf(id)
|
|
538
|
+
if (ind != -1) this.selected.splice(ind, 1)
|
|
539
|
+
}
|
|
540
|
+
edata.finish()
|
|
541
|
+
return true
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
async toggle(id) {
|
|
545
|
+
let nd = this.get(id)
|
|
546
|
+
if (nd == null) return false;
|
|
547
|
+
if(!nd._subItemsLoaded && globalThis.qydbUI?.loadSubItems) await globalThis.qydbUI.loadSubItems(nd);
|
|
548
|
+
if (nd.plus) {
|
|
549
|
+
this.set(id, { plus: false })
|
|
550
|
+
this.expand(id)
|
|
551
|
+
this.refresh(id)
|
|
552
|
+
return
|
|
553
|
+
}
|
|
554
|
+
if (nd.nodes.length === 0) return false
|
|
555
|
+
if (!nd.collapsible) return false
|
|
556
|
+
if (this.get(id).expanded) return this.collapse(id); else return this.expand(id)
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
collapse(id) {
|
|
560
|
+
let nd = this.get(id)
|
|
561
|
+
if (nd == null) return false
|
|
562
|
+
// event before
|
|
563
|
+
let edata = this.trigger('collapse', { target: id, object: nd, node: nd })
|
|
564
|
+
if (edata.isCancelled === true) return
|
|
565
|
+
// default action
|
|
566
|
+
query(this.box).find('#node_'+ w2utils.escapeId(id) +'_sub').hide()
|
|
567
|
+
query(this.box).find('#node_'+ w2utils.escapeId(id) +' .w2ui-expanded')
|
|
568
|
+
.removeClass('w2ui-expanded')
|
|
569
|
+
.addClass('w2ui-collapsed')
|
|
570
|
+
nd.expanded = false
|
|
571
|
+
// event after
|
|
572
|
+
edata.finish()
|
|
573
|
+
this.refresh(id)
|
|
574
|
+
return true
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
expand(id) {
|
|
578
|
+
let nd = this.get(id)
|
|
579
|
+
// event before
|
|
580
|
+
let edata = this.trigger('expand', { target: id, object: nd, node: nd })
|
|
581
|
+
if (edata.isCancelled === true) return
|
|
582
|
+
// default action
|
|
583
|
+
query(this.box).find('#node_'+ w2utils.escapeId(id) +'_sub')
|
|
584
|
+
.show()
|
|
585
|
+
query(this.box).find('#node_'+ w2utils.escapeId(id) +' .w2ui-collapsed')
|
|
586
|
+
.removeClass('w2ui-collapsed')
|
|
587
|
+
.addClass('w2ui-expanded')
|
|
588
|
+
nd.expanded = true
|
|
589
|
+
// event after
|
|
590
|
+
edata.finish()
|
|
591
|
+
this.refresh(id)
|
|
592
|
+
return true
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
collapseAll(parent) {
|
|
596
|
+
if (parent == null) parent = this
|
|
597
|
+
if (typeof parent == 'string') parent = this.get(parent)
|
|
598
|
+
if (parent.nodes == null) return false
|
|
599
|
+
for (let i = 0; i < parent.nodes.length; i++) {
|
|
600
|
+
if (parent.nodes[i].expanded === true) parent.nodes[i].expanded = false
|
|
601
|
+
if (parent.nodes[i].nodes && parent.nodes[i].nodes.length > 0) this.collapseAll(parent.nodes[i])
|
|
602
|
+
}
|
|
603
|
+
this.refresh(parent.id)
|
|
604
|
+
return true
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
expandAll(parent) {
|
|
608
|
+
if (parent == null) parent = this
|
|
609
|
+
if (typeof parent == 'string') parent = this.get(parent)
|
|
610
|
+
if (parent.nodes == null) return false
|
|
611
|
+
for (let i = 0; i < parent.nodes.length; i++) {
|
|
612
|
+
if (parent.nodes[i].expanded === false) parent.nodes[i].expanded = true
|
|
613
|
+
if (parent.nodes[i].nodes && parent.nodes[i].nodes.length > 0) this.expandAll(parent.nodes[i])
|
|
614
|
+
}
|
|
615
|
+
this.refresh(parent.id)
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
expandParents(id) {
|
|
619
|
+
let node = this.get(id)
|
|
620
|
+
if (node == null) return false
|
|
621
|
+
if (node.parent) {
|
|
622
|
+
if (!node.parent.expanded) {
|
|
623
|
+
node.parent.expanded = true
|
|
624
|
+
this.refresh(node.parent.id)
|
|
625
|
+
}
|
|
626
|
+
this.expandParents(node.parent.id)
|
|
627
|
+
}
|
|
628
|
+
return true
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
click(id, event) {
|
|
632
|
+
let obj = this
|
|
633
|
+
let nd = this.get(id)
|
|
634
|
+
if (nd == null) return
|
|
635
|
+
if (nd.disabled || nd.group) {
|
|
636
|
+
// even if disabled, it should still emit click event
|
|
637
|
+
let edata = obj.trigger('click', { target: id, originalEvent: event, node: nd, object: nd })
|
|
638
|
+
edata.finish()
|
|
639
|
+
return
|
|
640
|
+
}
|
|
641
|
+
// select new one
|
|
642
|
+
let newNode = query(obj.box).find('#node_'+ w2utils.escapeId(id))
|
|
643
|
+
newNode.addClass('w2ui-selected').find('.w2ui-icon').addClass('w2ui-icon-selected')
|
|
644
|
+
// need timeout to allow rendering
|
|
645
|
+
setTimeout(() => {
|
|
646
|
+
// event before
|
|
647
|
+
let edata = obj.trigger('click', { target: id, originalEvent: event, node: nd, object: nd })
|
|
648
|
+
if (edata.isCancelled === true) {
|
|
649
|
+
// restore selection
|
|
650
|
+
newNode.removeClass('w2ui-selected').find('.w2ui-icon').removeClass('w2ui-icon-selected')
|
|
651
|
+
return
|
|
652
|
+
}
|
|
653
|
+
// default action
|
|
654
|
+
if (this.multi) {
|
|
655
|
+
/**
|
|
656
|
+
* Multi select with shift or ctrl/meta
|
|
657
|
+
*/
|
|
658
|
+
let isShift = event?.shiftKey ?? false
|
|
659
|
+
let isCtrl = (event?.ctrlKey || event?.metaKey) ?? false
|
|
660
|
+
if (typeof this.selected == 'string') {
|
|
661
|
+
this.selected = [this.selected]
|
|
662
|
+
}
|
|
663
|
+
if (isCtrl && !isShift) { // only Ctrl
|
|
664
|
+
if (this.selected?.includes(id)) {
|
|
665
|
+
this.unselect(id)
|
|
666
|
+
return
|
|
667
|
+
} else {
|
|
668
|
+
this.select(id)
|
|
669
|
+
}
|
|
670
|
+
} else if (!isCtrl && isShift) { // only Shift
|
|
671
|
+
// select range in between
|
|
672
|
+
let chain = this.getChain()
|
|
673
|
+
let ind1 = Math.min(this.selected.map(sel => chain.indexOf(sel))) // first item in selection
|
|
674
|
+
let ind2 = chain.indexOf(id)
|
|
675
|
+
for (let i = Math.min(ind1, ind2); i < chain.length && i <= Math.max(ind1, ind2); i++) {
|
|
676
|
+
let node = this.get(chain[i])
|
|
677
|
+
if (!this.selected.includes(chain[i]) && node.hidden != true) {
|
|
678
|
+
this.select(chain[i])
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
} else { // neither
|
|
683
|
+
let ids = this.selected?.filter(sid => sid != id && this.selected.includes(sid))
|
|
684
|
+
this.unselect(ids)
|
|
685
|
+
// only select if it is not selected
|
|
686
|
+
if (!this.selected?.includes(id)) {
|
|
687
|
+
this.select(id)
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
} else if (this.selected !== id) {
|
|
692
|
+
/**
|
|
693
|
+
* Single selection at a time
|
|
694
|
+
*/
|
|
695
|
+
if (this.selected != null) this.unselect(this.selected)
|
|
696
|
+
this.select(id)
|
|
697
|
+
// route processing
|
|
698
|
+
if (typeof nd.route == 'string') {
|
|
699
|
+
let route = nd.route !== '' ? String('/'+ nd.route).replace(/\/{2,}/g, '/') : ''
|
|
700
|
+
let info = w2utils.parseRoute(route)
|
|
701
|
+
if (info.keys.length > 0) {
|
|
702
|
+
for (let k = 0; k < info.keys.length; k++) {
|
|
703
|
+
if (obj.routeData[info.keys[k].name] == null) continue
|
|
704
|
+
route = route.replace((new RegExp(':'+ info.keys[k].name, 'g')), obj.routeData[info.keys[k].name])
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
setTimeout(() => { window.location.hash = route }, 1)
|
|
708
|
+
}
|
|
709
|
+
// if sidebar is flat - show menu
|
|
710
|
+
if (this.flat) {
|
|
711
|
+
let items = _getItems(nd.nodes)
|
|
712
|
+
if (items.length > 0) {
|
|
713
|
+
this.flatMenu(newNode, items)
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
function _getItems(nodes) {
|
|
717
|
+
let items = nodes.map(it => {
|
|
718
|
+
let items = it.nodes.length > 0 ? _getItems(it.nodes) : null
|
|
719
|
+
return { id: it.id, text: it.text, icon: it.icon, items }
|
|
720
|
+
})
|
|
721
|
+
return items
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
// event after
|
|
726
|
+
edata.finish()
|
|
727
|
+
}, 1)
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
flatMenu(el, items) {
|
|
731
|
+
let self = this
|
|
732
|
+
let $el = query(el).find('.w2ui-node-data')
|
|
733
|
+
w2menu.show({
|
|
734
|
+
anchor: $el.get(0),
|
|
735
|
+
name: this.name + '_flat-menu',
|
|
736
|
+
items,
|
|
737
|
+
// class: 'w2ui-dark',
|
|
738
|
+
position: 'right|left',
|
|
739
|
+
onSelect(event) {
|
|
740
|
+
self.unselect()
|
|
741
|
+
self.click(event.detail.item.id, event.detail.originalEvent)
|
|
742
|
+
},
|
|
743
|
+
onHide(event) {
|
|
744
|
+
self.unselect()
|
|
745
|
+
}
|
|
746
|
+
})
|
|
747
|
+
w2tooltip.hide(this.name + '_tooltip')
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
focus(event) {
|
|
751
|
+
let self = this
|
|
752
|
+
// event before
|
|
753
|
+
let edata = this.trigger('focus', { target: this.name, originalEvent: event })
|
|
754
|
+
if (edata.isCancelled === true) return false
|
|
755
|
+
// default behaviour
|
|
756
|
+
this.hasFocus = true
|
|
757
|
+
query(this.box).find('.w2ui-sidebar-body').addClass('w2ui-focus')
|
|
758
|
+
setTimeout(() => {
|
|
759
|
+
let input = query(self.box).find('#sidebar_'+ self.name + '_focus').get(0)
|
|
760
|
+
if (document.activeElement != input) input.focus()
|
|
761
|
+
}, 10)
|
|
762
|
+
// event after
|
|
763
|
+
edata.finish()
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
blur(event) {
|
|
767
|
+
// event before
|
|
768
|
+
let edata = this.trigger('blur', { target: this.name, originalEvent: event })
|
|
769
|
+
if (edata.isCancelled === true) return false
|
|
770
|
+
// default behaviour
|
|
771
|
+
this.hasFocus = false
|
|
772
|
+
query(this.box).find('.w2ui-sidebar-body').removeClass('w2ui-focus')
|
|
773
|
+
// event after
|
|
774
|
+
edata.finish()
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
next(node, noSubs) {
|
|
778
|
+
if (node == null) return null
|
|
779
|
+
let parent = node.parent
|
|
780
|
+
let ind = this.get(node.id, true)
|
|
781
|
+
let nextNode = null
|
|
782
|
+
// jump inside
|
|
783
|
+
if (node.expanded && node.nodes.length > 0 && noSubs !== true) {
|
|
784
|
+
let nd = node.nodes[0]
|
|
785
|
+
if (nd.hidden || nd.disabled || nd.group) nextNode = this.next(nd); else nextNode = nd
|
|
786
|
+
} else {
|
|
787
|
+
if (parent && ind + 1 < parent.nodes.length) {
|
|
788
|
+
nextNode = parent.nodes[ind + 1]
|
|
789
|
+
} else {
|
|
790
|
+
nextNode = this.next(parent, true) // jump to the parent
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
if (nextNode != null && (nextNode.hidden || nextNode.disabled || nextNode.group)) nextNode = this.next(nextNode)
|
|
794
|
+
return nextNode
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
prev(node) {
|
|
798
|
+
if (node == null) return null
|
|
799
|
+
let parent = node.parent
|
|
800
|
+
let ind = this.get(node.id, true)
|
|
801
|
+
let lastChild = (node) => {
|
|
802
|
+
if (node.expanded && node.nodes.length > 0) {
|
|
803
|
+
let nd = node.nodes[node.nodes.length - 1]
|
|
804
|
+
if (nd.hidden || nd.disabled || nd.group) return this.prev(nd); else return lastChild(nd)
|
|
805
|
+
}
|
|
806
|
+
return node
|
|
807
|
+
}
|
|
808
|
+
let prevNode = (ind > 0) ? lastChild(parent.nodes[ind - 1]) : parent
|
|
809
|
+
if (prevNode != null && (prevNode.hidden || prevNode.disabled || prevNode.group)) prevNode = this.prev(prevNode)
|
|
810
|
+
return prevNode
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// returns ids of expanded elements as a flat array
|
|
814
|
+
getChain(nodes, options = {}) {
|
|
815
|
+
options.returnDisabled ??= false
|
|
816
|
+
options.returnGroups ??= false
|
|
817
|
+
let ids = []
|
|
818
|
+
if (nodes == null) nodes = this.nodes
|
|
819
|
+
nodes.forEach(node => {
|
|
820
|
+
// can skip disabled if needed
|
|
821
|
+
if ((!node.disabled && !node.group) || (node.disabled && options.returnDisabled) || (node.group && options.returnGroups)) {
|
|
822
|
+
ids.push(node.id)
|
|
823
|
+
}
|
|
824
|
+
if (Array.isArray(node.nodes) && node.expanded) {
|
|
825
|
+
ids.push(...this.getChain(node.nodes, options))
|
|
826
|
+
}
|
|
827
|
+
})
|
|
828
|
+
return ids
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
keydown(event) {
|
|
832
|
+
let self = this
|
|
833
|
+
let first = Array.isArray(this.selected) ? this.selected[0] : this.selected
|
|
834
|
+
let nd = self.get(first)
|
|
835
|
+
if (this.keyboard !== true) return
|
|
836
|
+
if (!nd) nd = this.nodes[0]
|
|
837
|
+
// if user hits esc and there is active move
|
|
838
|
+
if (event.keyCode == 27) {
|
|
839
|
+
let mv = this.last.move
|
|
840
|
+
if (mv?.reorder && mv?.moved) {
|
|
841
|
+
mv.restore()
|
|
842
|
+
return
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
// trigger event
|
|
846
|
+
let edata = this.trigger('keydown', { target: this.name, originalEvent: event })
|
|
847
|
+
if (edata.isCancelled === true) return
|
|
848
|
+
// default behaviour
|
|
849
|
+
if (event.keyCode == 13 || event.keyCode == 32) { // enter or space
|
|
850
|
+
if (event.keyCode == 13 && this.editable && !event.ctrlKey && !event.metaKey) {
|
|
851
|
+
this.edit(first)
|
|
852
|
+
} else {
|
|
853
|
+
if (nd.nodes.length > 0) {
|
|
854
|
+
this.toggle(first)
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
if (event.keyCode == 37) { // left
|
|
859
|
+
if (nd.nodes.length > 0 && nd.expanded) {
|
|
860
|
+
this.collapse(first)
|
|
861
|
+
} else {
|
|
862
|
+
selectNode(nd.parent)
|
|
863
|
+
if (!nd.parent.group) this.collapse(nd.parent.id)
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
if (event.keyCode == 39) { // right
|
|
867
|
+
if ((nd.nodes.length > 0 || nd.plus) && !nd.expanded) this.expand(first)
|
|
868
|
+
}
|
|
869
|
+
if (event.keyCode == 38) { // up
|
|
870
|
+
if (this.get(first) == null) {
|
|
871
|
+
selectNode(this.nodes[0] || null)
|
|
872
|
+
} else {
|
|
873
|
+
selectNode(neighbor(nd, this.prev))
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
if (event.keyCode == 40) { // down
|
|
877
|
+
if (this.get(first) == null) {
|
|
878
|
+
selectNode(this.nodes[0] || null)
|
|
879
|
+
} else {
|
|
880
|
+
selectNode(neighbor(nd, this.next))
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
// cancel event if needed
|
|
884
|
+
if ([13, 32, 37, 38, 39, 40].includes(event.keyCode)) {
|
|
885
|
+
if (event.preventDefault) event.preventDefault()
|
|
886
|
+
if (event.stopPropagation) event.stopPropagation()
|
|
887
|
+
}
|
|
888
|
+
// event after
|
|
889
|
+
edata.finish()
|
|
890
|
+
|
|
891
|
+
function selectNode(node, event) {
|
|
892
|
+
if (node != null && !node.hidden && !node.disabled && !node.group) {
|
|
893
|
+
self.click(node.id, event)
|
|
894
|
+
if (!self.inView(node.id)) self.scrollIntoView(node.id)
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
function neighbor(node, neighborFunc) {
|
|
899
|
+
node = neighborFunc.call(self, node)
|
|
900
|
+
while (node != null && (node.hidden || node.disabled)) {
|
|
901
|
+
if (node.group) break; else node = neighborFunc(node)
|
|
902
|
+
}
|
|
903
|
+
return node
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
inView(id) {
|
|
908
|
+
let item = query(this.box).find('#node_'+ w2utils.escapeId(id)).get(0)
|
|
909
|
+
if (!item) {
|
|
910
|
+
return false
|
|
911
|
+
}
|
|
912
|
+
let div = query(this.box).find('.w2ui-sidebar-body').get(0)
|
|
913
|
+
if (item.offsetTop < div.scrollTop || (item.offsetTop + item.clientHeight > div.clientHeight + div.scrollTop)) {
|
|
914
|
+
return false
|
|
915
|
+
}
|
|
916
|
+
return true
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
scrollIntoView(id, instant) {
|
|
920
|
+
return new Promise((resolve, reject) => {
|
|
921
|
+
if (id == null) id = Array.isArray(this.selected) ? this.selected[0] : this.selected
|
|
922
|
+
let nd = this.get(id)
|
|
923
|
+
if (nd == null) return
|
|
924
|
+
let item = query(this.box).find('#node_'+ w2utils.escapeId(id)).get(0)
|
|
925
|
+
item.scrollIntoView({ block: 'center', inline: 'center', behavior: instant ? 'atuo' : 'smooth' })
|
|
926
|
+
setTimeout(() => { this.resize(); resolve() }, instant ? 0 : 500)
|
|
927
|
+
})
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
dblClick(id, event) {
|
|
931
|
+
let nd = this.get(id)
|
|
932
|
+
// event before
|
|
933
|
+
let edata = this.trigger('dblClick', { target: id, originalEvent: event, object: nd })
|
|
934
|
+
if (edata.isCancelled === true) return
|
|
935
|
+
// default action
|
|
936
|
+
if (this.editable) {
|
|
937
|
+
this.edit(id)
|
|
938
|
+
} else if (!this.flat) {
|
|
939
|
+
this.toggle(id)
|
|
940
|
+
}
|
|
941
|
+
// event after
|
|
942
|
+
edata.finish()
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
/**
|
|
946
|
+
* This is needed for not reorder
|
|
947
|
+
*/
|
|
948
|
+
mouseDown(id, event) {
|
|
949
|
+
let self = this
|
|
950
|
+
if (this.reorder) {
|
|
951
|
+
this.last.move = {
|
|
952
|
+
x: event.screenX,
|
|
953
|
+
y: event.screenY,
|
|
954
|
+
divX: 0,
|
|
955
|
+
divY: 0,
|
|
956
|
+
reorder: true,
|
|
957
|
+
moved: false
|
|
958
|
+
}
|
|
959
|
+
// display empty record and ghost record
|
|
960
|
+
let mv = this.last.move
|
|
961
|
+
let body = query(this.box).find('.w2ui-sidebar-body')
|
|
962
|
+
if (!mv.ghost) {
|
|
963
|
+
let node = query(this.box).find(`#node_${w2utils.escapeId(id)}`)
|
|
964
|
+
mv.offsetY = event.offsetY
|
|
965
|
+
mv.target = id
|
|
966
|
+
mv.pos = { top: node.get(0).offsetTop - 1, left: node.get(0).offsetLeft }
|
|
967
|
+
// ghost content
|
|
968
|
+
let clone = query(node.find('.w2ui-node-data').get(0).cloneNode(true))
|
|
969
|
+
mv.node = node
|
|
970
|
+
mv.nodeSub = node.next()
|
|
971
|
+
body.append('<div id="sidebar_'+ this.name + '_ghost" class="w2ui-node w2ui-ghost"></div>')
|
|
972
|
+
query(this.box).find('#sidebar_'+ this.name + '_ghost').append(clone)
|
|
973
|
+
mv.ghost = query(this.box).find('#sidebar_'+ this.name + '_ghost')
|
|
974
|
+
mv.ghost.css({ display: 'none' })
|
|
975
|
+
mv.restore = () => {
|
|
976
|
+
mv.resetReorder()
|
|
977
|
+
this.refresh()
|
|
978
|
+
}
|
|
979
|
+
mv.resetReorder = () => {
|
|
980
|
+
this.last.move = null
|
|
981
|
+
query(this.box).find(`#sidebar_${this.name}_ghost`).remove()
|
|
982
|
+
query(document).off(`.w2ui-${this.name}-reorder`)
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
// add mouse move and stop events
|
|
986
|
+
query(document)
|
|
987
|
+
.on(`mousemove.w2ui-${this.name}-reorder`, _mouseMove)
|
|
988
|
+
.on(`mouseup.w2ui-${this.name}-reorder`, _mouseStop)
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
function _mouseMove(event) {
|
|
992
|
+
if (!event.target.tagName) {
|
|
993
|
+
// element has no tagName - most likely the target is the #document itself
|
|
994
|
+
// this can happen is you click+drag and move the mouse out of the DOM area,
|
|
995
|
+
// e.g. into the browser's toolbar area
|
|
996
|
+
return
|
|
997
|
+
}
|
|
998
|
+
let mv = self.last.move
|
|
999
|
+
mv.divX = (event.screenX - mv.x)
|
|
1000
|
+
mv.divY = (event.screenY - mv.y)
|
|
1001
|
+
if (Math.abs(mv.divX) <= 1 && Math.abs(mv.divY) <= 1) return // only if moved more then 1px
|
|
1002
|
+
|
|
1003
|
+
if (self.reorder == true && mv.reorder && !mv.moved) {
|
|
1004
|
+
let edata = self.trigger('dragStart', { target: mv.target, moved: true, node: self.get(mv.target), mv, originalEvent: event })
|
|
1005
|
+
if (edata.isCancelled === true) {
|
|
1006
|
+
mv.restore()
|
|
1007
|
+
return
|
|
1008
|
+
}
|
|
1009
|
+
let rect = mv.node.get(0).getBoundingClientRect()
|
|
1010
|
+
mv.moved = true
|
|
1011
|
+
mv.node.html('')
|
|
1012
|
+
.removeAttr('id', 'data-id')
|
|
1013
|
+
.addClass('w2ui-reorder-empty')
|
|
1014
|
+
.css({ height: rect.height + 'px' })
|
|
1015
|
+
// if there are children
|
|
1016
|
+
if (mv.node.next().css('display') !== 'none') {
|
|
1017
|
+
let rect = mv.node.next().get(0).getBoundingClientRect()
|
|
1018
|
+
mv.node.next()
|
|
1019
|
+
.html('<div class="w2ui-reorder-empty-sub"></div>')
|
|
1020
|
+
.css({ height: rect.height + 'px' })
|
|
1021
|
+
}
|
|
1022
|
+
mv.ghost.css({ display: 'block' })
|
|
1023
|
+
// event after
|
|
1024
|
+
edata.finish()
|
|
1025
|
+
}
|
|
1026
|
+
// move ghost mode
|
|
1027
|
+
mv.ghost.css({
|
|
1028
|
+
top: (mv.pos.top + mv.divY) + 'px',
|
|
1029
|
+
left: 0
|
|
1030
|
+
})
|
|
1031
|
+
let over = query(event.target).closest('.w2ui-node, .w2ui-node-group')
|
|
1032
|
+
let id = over.attr('data-id')
|
|
1033
|
+
// append to the end
|
|
1034
|
+
if (query(event.target).hasClass('w2ui-sidebar-body') && event.layerY > 5 && !mv.append) {
|
|
1035
|
+
let edata = self.trigger('dragOver', { target: mv.target, append: true, mv, originalEvent: event })
|
|
1036
|
+
if (edata.isCancelled === true) {
|
|
1037
|
+
return
|
|
1038
|
+
}
|
|
1039
|
+
mv.ghost.before(mv.node)
|
|
1040
|
+
mv.ghost.before(mv.nodeSub)
|
|
1041
|
+
mv.append = true
|
|
1042
|
+
mv.moveBefore = null
|
|
1043
|
+
// event after
|
|
1044
|
+
edata.finish()
|
|
1045
|
+
} else if (id != null && id != mv.moveBefore) {
|
|
1046
|
+
mv.append = false
|
|
1047
|
+
mv.moveBefore = id
|
|
1048
|
+
// reorder nodes
|
|
1049
|
+
let edata = self.trigger('dragOver', { target: mv.target, moveBefore: id, mv, originalEvent: event })
|
|
1050
|
+
if (edata.isCancelled === true) {
|
|
1051
|
+
return
|
|
1052
|
+
}
|
|
1053
|
+
let el = query(self.box).find(`#node_${w2utils.escapeId(id)}`)
|
|
1054
|
+
el.before(mv.node)
|
|
1055
|
+
el.before(mv.nodeSub)
|
|
1056
|
+
// event after
|
|
1057
|
+
edata.finish()
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
function _mouseStop(event) {
|
|
1062
|
+
let mv = self.last.move
|
|
1063
|
+
mv.resetReorder()
|
|
1064
|
+
if (mv.moved) {
|
|
1065
|
+
if (((mv.moveBefore != null && mv.target != mv.moveBefore) || mv.append)) {
|
|
1066
|
+
let edata = self.trigger('reorder', { target: mv.target, moveBefore: mv.moveBefore, append: mv.append, originalEvent: event })
|
|
1067
|
+
if (edata.isCancelled === true) {
|
|
1068
|
+
self.refresh()
|
|
1069
|
+
return
|
|
1070
|
+
}
|
|
1071
|
+
// remove
|
|
1072
|
+
let target = self.get(mv.target)
|
|
1073
|
+
let targetInd = target.parent.nodes.indexOf(target)
|
|
1074
|
+
let cut = target.parent.nodes.splice(targetInd, 1)
|
|
1075
|
+
// insert
|
|
1076
|
+
if (mv.append) {
|
|
1077
|
+
self.nodes.push(...cut)
|
|
1078
|
+
cut.forEach(nd => nd.parent = self)
|
|
1079
|
+
} else {
|
|
1080
|
+
let before = self.get(mv.moveBefore)
|
|
1081
|
+
let beforeInd = before.parent.nodes.indexOf(before)
|
|
1082
|
+
cut.forEach(nd => nd.parent = before.parent)
|
|
1083
|
+
before.parent.nodes.splice(beforeInd, 0, ...cut)
|
|
1084
|
+
}
|
|
1085
|
+
// refresh
|
|
1086
|
+
self.refresh()
|
|
1087
|
+
// event after
|
|
1088
|
+
edata.finish()
|
|
1089
|
+
} else {
|
|
1090
|
+
self.refresh()
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
edit(id) {
|
|
1097
|
+
let self = this
|
|
1098
|
+
let node = query(this.box).find('#node_'+ w2utils.escapeId(id))
|
|
1099
|
+
let text = node.find('.w2ui-node-text')
|
|
1100
|
+
// event before
|
|
1101
|
+
let edata = this.trigger('edit', { target: id, el: node, textEl: text })
|
|
1102
|
+
if (edata.isCancelled === true) {
|
|
1103
|
+
return
|
|
1104
|
+
}
|
|
1105
|
+
this.last.renaming = true
|
|
1106
|
+
node.addClass('w2ui-editing')
|
|
1107
|
+
text.addClass('w2ui-focus')
|
|
1108
|
+
.css('pointer-events', 'all')
|
|
1109
|
+
.attr('contenteditable', w2utils.isFirefox ? 'true' : 'plaintext-only')
|
|
1110
|
+
.on('blur.node-editing', event => {
|
|
1111
|
+
// timeout is needed to add to the end of the event loop
|
|
1112
|
+
setTimeout(_rename, 0)
|
|
1113
|
+
})
|
|
1114
|
+
.on('keydown.node-editing', event => {
|
|
1115
|
+
if (event.keyCode == 13) _rename(event)
|
|
1116
|
+
if (event.keyCode == 27) _rename(event, true)
|
|
1117
|
+
})
|
|
1118
|
+
.get(0).focus()
|
|
1119
|
+
|
|
1120
|
+
let original = text.text()
|
|
1121
|
+
// select everything inside
|
|
1122
|
+
w2utils.setCursorPosition(text[0], 0, text.text().length)
|
|
1123
|
+
// event after
|
|
1124
|
+
edata.finish()
|
|
1125
|
+
|
|
1126
|
+
return text.get(0) // return editable input
|
|
1127
|
+
|
|
1128
|
+
function _rename(event, cancel) {
|
|
1129
|
+
let renameTo = text.text()
|
|
1130
|
+
node.removeClass('w2ui-editing')
|
|
1131
|
+
text.removeClass('w2ui-focus')
|
|
1132
|
+
.css('pointer-events', 'none')
|
|
1133
|
+
.removeAttr('contenteditable')
|
|
1134
|
+
.off('.node-editing')
|
|
1135
|
+
// send event if it was not cancelled
|
|
1136
|
+
if (!cancel && self.last.renaming && original !== renameTo) {
|
|
1137
|
+
let edata = self.trigger('rename', { target: id, text_previous: original, text_new: renameTo, originalEvent: event })
|
|
1138
|
+
if (edata.isCancelled === true) {
|
|
1139
|
+
text.text(original)
|
|
1140
|
+
self.last.renaming = false
|
|
1141
|
+
self.focus()
|
|
1142
|
+
return
|
|
1143
|
+
}
|
|
1144
|
+
self.set(id, { text: renameTo })
|
|
1145
|
+
edata.finish()
|
|
1146
|
+
}
|
|
1147
|
+
if (cancel) {
|
|
1148
|
+
self.set(id, { text: original })
|
|
1149
|
+
}
|
|
1150
|
+
self.last.renaming = false
|
|
1151
|
+
self.focus()
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
contextMenu(id, event) {
|
|
1156
|
+
let nd = this.get(id)
|
|
1157
|
+
if (Array.isArray(this.selected)) {
|
|
1158
|
+
if (!this.selected.includes(id)) this.click(id)
|
|
1159
|
+
} else {
|
|
1160
|
+
if (id != this.selected) this.click(id)
|
|
1161
|
+
}
|
|
1162
|
+
// event before
|
|
1163
|
+
let edata = this.trigger('contextMenu', { target: id, originalEvent: event, object: nd, allowOnDisabled: false })
|
|
1164
|
+
if (edata.isCancelled === true) return
|
|
1165
|
+
// default action
|
|
1166
|
+
if (nd.disabled && !edata.allowOnDisabled) return
|
|
1167
|
+
if (this.menu.length > 0) {
|
|
1168
|
+
w2menu.hide(this.name + '_menu') // hide previous if any needed when other item's menu is shown
|
|
1169
|
+
w2menu.show({
|
|
1170
|
+
name: this.name + '_menu',
|
|
1171
|
+
anchor: document.body,
|
|
1172
|
+
contextMenu: true,
|
|
1173
|
+
items: this.menu,
|
|
1174
|
+
originalEvent: event
|
|
1175
|
+
})
|
|
1176
|
+
.select(evt => {
|
|
1177
|
+
this.menuClick(id, evt.detail)
|
|
1178
|
+
})
|
|
1179
|
+
}
|
|
1180
|
+
// prevent default context menu
|
|
1181
|
+
if (event.preventDefault) event.preventDefault()
|
|
1182
|
+
// event after
|
|
1183
|
+
edata.finish()
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
menuClick(itemId, detail = {}) {
|
|
1187
|
+
// event before
|
|
1188
|
+
let edata = this.trigger('menuClick', { target: itemId, ...detail })
|
|
1189
|
+
if (edata.isCancelled === true) return
|
|
1190
|
+
// default action
|
|
1191
|
+
// -- empty
|
|
1192
|
+
// event after
|
|
1193
|
+
edata.finish()
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
goFlat() {
|
|
1197
|
+
// event before
|
|
1198
|
+
let edata = this.trigger('flat', { goFlat: !this.flat })
|
|
1199
|
+
if (edata.isCancelled === true) return
|
|
1200
|
+
// default action
|
|
1201
|
+
this.flat = !this.flat
|
|
1202
|
+
this.refresh()
|
|
1203
|
+
if (this.flat) {
|
|
1204
|
+
// collapse all unless it is a group
|
|
1205
|
+
this.nodes.forEach(node => {
|
|
1206
|
+
if (!node.group) {
|
|
1207
|
+
this.collapse(node.id)
|
|
1208
|
+
this.collapseAll(node.id) // sub items too
|
|
1209
|
+
}
|
|
1210
|
+
})
|
|
1211
|
+
this.unselect() // unselects all
|
|
1212
|
+
} else {
|
|
1213
|
+
// expand all unless it is a group
|
|
1214
|
+
this.nodes.forEach(node => {
|
|
1215
|
+
if (!node.group) {
|
|
1216
|
+
this.expand(node.id)
|
|
1217
|
+
this.expandAll(node.id) // sub items too
|
|
1218
|
+
}
|
|
1219
|
+
})
|
|
1220
|
+
}
|
|
1221
|
+
// event after
|
|
1222
|
+
edata.finish()
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
render(box) {
|
|
1226
|
+
let time = Date.now()
|
|
1227
|
+
let obj = this
|
|
1228
|
+
if (typeof box == 'string') box = query(box).get(0)
|
|
1229
|
+
// event before
|
|
1230
|
+
let edata = this.trigger('render', { target: this.name, box: box ?? this.box })
|
|
1231
|
+
if (edata.isCancelled === true) return
|
|
1232
|
+
// default action
|
|
1233
|
+
if (box != null) {
|
|
1234
|
+
this.unmount() // clean previous control
|
|
1235
|
+
this.box = box
|
|
1236
|
+
}
|
|
1237
|
+
if (!this.box) return
|
|
1238
|
+
query(this.box)
|
|
1239
|
+
.attr('name', this.name)
|
|
1240
|
+
.addClass('w2ui-reset w2ui-sidebar')
|
|
1241
|
+
.html(`<div>
|
|
1242
|
+
<div class="w2ui-sidebar-top"></div>
|
|
1243
|
+
<input id="sidebar_${this.name}_focus" ${(this.tabIndex ? 'tabindex="' + this.tabIndex + '"' : '')}
|
|
1244
|
+
style="position: absolute; top: 0; right: 0; width: 1px; z-index: -1; opacity: 0"
|
|
1245
|
+
${(w2utils.isMobile ? 'readonly' : '')}/>
|
|
1246
|
+
<div class="w2ui-sidebar-body"></div>
|
|
1247
|
+
<div class="w2ui-sidebar-bottom"></div>
|
|
1248
|
+
</div>`)
|
|
1249
|
+
let rect = query(this.box).get(0).getBoundingClientRect()
|
|
1250
|
+
query(this.box).find(':scope > div').css({
|
|
1251
|
+
width : rect.width + 'px',
|
|
1252
|
+
height : rect.height + 'px'
|
|
1253
|
+
})
|
|
1254
|
+
query(this.box).get(0).style.cssText += this.style
|
|
1255
|
+
// focus
|
|
1256
|
+
let kbd_timer
|
|
1257
|
+
query(this.box).find('#sidebar_'+ this.name + '_focus')
|
|
1258
|
+
.on('focus', function(event) {
|
|
1259
|
+
clearTimeout(kbd_timer)
|
|
1260
|
+
if (!obj.hasFocus) obj.focus(event)
|
|
1261
|
+
})
|
|
1262
|
+
.on('blur', function(event) {
|
|
1263
|
+
kbd_timer = setTimeout(() => {
|
|
1264
|
+
if (obj.hasFocus) { obj.blur(event) }
|
|
1265
|
+
}, 100)
|
|
1266
|
+
})
|
|
1267
|
+
.on('keydown', function(event) {
|
|
1268
|
+
// do not cancel tab key (keyCode=9) so that event is dispatched to self
|
|
1269
|
+
w2ui[obj.name].keydown.call(w2ui[obj.name], event)
|
|
1270
|
+
})
|
|
1271
|
+
query(this.box).off('mousedown')
|
|
1272
|
+
.on('mousedown', function(event) {
|
|
1273
|
+
// set focus to sidebar
|
|
1274
|
+
setTimeout(() => {
|
|
1275
|
+
// if input then do not focus
|
|
1276
|
+
if (['INPUT', 'TEXTAREA', 'SELECT'].indexOf(event.target.tagName.toUpperCase()) == -1) {
|
|
1277
|
+
let $input = query(obj.box).find('#sidebar_'+ obj.name + '_focus')
|
|
1278
|
+
if (document.activeElement != $input.get(0) && $input.length > 0) {
|
|
1279
|
+
$input.get(0).focus()
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
}, 1)
|
|
1283
|
+
})
|
|
1284
|
+
/**
|
|
1285
|
+
* FlatHTML is always present and in .refresh() it is just refreshed. However topHTML and buttomHTML should be here
|
|
1286
|
+
* because it should never be refreshed, as it could create recursive refresh loop
|
|
1287
|
+
*/
|
|
1288
|
+
let flatHTML = `<div class="w2ui-flat w2ui-flat-${(this.flat ? 'right' : 'left')}" ${this.flatButton == false ? 'style="display: none"' : ''}></div>`
|
|
1289
|
+
if (this.topHTML !== '' || flatHTML !== '') {
|
|
1290
|
+
query(this.box).find('.w2ui-sidebar-top').html(this.topHTML + flatHTML)
|
|
1291
|
+
query(this.box).find('.w2ui-sidebar-body')
|
|
1292
|
+
.css('top', query(this.box).find('.w2ui-sidebar-top').get(0)?.clientHeight + 'px')
|
|
1293
|
+
query(this.box).find('.w2ui-flat')
|
|
1294
|
+
.off('click')
|
|
1295
|
+
.on('click', event => { this.goFlat() })
|
|
1296
|
+
}
|
|
1297
|
+
if (this.bottomHTML !== '') {
|
|
1298
|
+
query(this.box).find('.w2ui-sidebar-bottom').html(this.bottomHTML)
|
|
1299
|
+
query(this.box).find('.w2ui-sidebar-body')
|
|
1300
|
+
.css('bottom', query(this.box).find('.w2ui-sidebar-bottom').get(0)?.clientHeight + 'px')
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
// observe div resize
|
|
1304
|
+
this.last.observeResize = new ResizeObserver(() => { this.resize() })
|
|
1305
|
+
this.last.observeResize.observe(this.box)
|
|
1306
|
+
// event after
|
|
1307
|
+
edata.finish()
|
|
1308
|
+
// ---
|
|
1309
|
+
this.refresh()
|
|
1310
|
+
return Date.now() - time
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
update(id, options = {}) {
|
|
1314
|
+
// quick function to refresh just this item (not sub nodes)
|
|
1315
|
+
// - icon, class, style, text, count
|
|
1316
|
+
let nd = this.get(id)
|
|
1317
|
+
let level
|
|
1318
|
+
if (nd) {
|
|
1319
|
+
let $el = query(this.box).find('#node_'+ w2utils.escapeId(nd.id))
|
|
1320
|
+
if (nd.group) {
|
|
1321
|
+
if (options.text) {
|
|
1322
|
+
nd.text = options.text
|
|
1323
|
+
$el.find('.w2ui-group-text').replace(typeof nd.text == 'function'
|
|
1324
|
+
? nd.text.call(this, nd)
|
|
1325
|
+
: '<span class="w2ui-group-text">'+ nd.text +'</span>')
|
|
1326
|
+
delete options.text
|
|
1327
|
+
}
|
|
1328
|
+
if (options.class) {
|
|
1329
|
+
nd.class = options.class
|
|
1330
|
+
level = $el.data('level')
|
|
1331
|
+
$el.get(0).className = 'w2ui-node-group w2ui-level-'+ level +(nd.class ? ' ' + nd.class : '')
|
|
1332
|
+
delete options.class
|
|
1333
|
+
}
|
|
1334
|
+
if (options.style) {
|
|
1335
|
+
nd.style = options.style
|
|
1336
|
+
$el.get(0).nextElementSibling.style = nd.style +';'+ (!nd.hidden && nd.expanded ? '' : 'display: none;')
|
|
1337
|
+
delete options.style
|
|
1338
|
+
}
|
|
1339
|
+
} else {
|
|
1340
|
+
if (options.icon) {
|
|
1341
|
+
let $icon = $el.find('.w2ui-node-image > span')
|
|
1342
|
+
if ($icon.length > 0) {
|
|
1343
|
+
nd.icon = options.icon
|
|
1344
|
+
$icon[0].className = (typeof nd.icon == 'function' ? nd.icon.call(this, nd) : nd.icon)
|
|
1345
|
+
delete options.icon
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
if (options.count != null) {
|
|
1349
|
+
nd.count = options.count
|
|
1350
|
+
// update counts
|
|
1351
|
+
let txt = nd.count ?? this.badge.text
|
|
1352
|
+
let style = this.badge?.style
|
|
1353
|
+
let last = this.last.badge[nd.id]
|
|
1354
|
+
if (typeof txt == 'function') txt = txt.call(this, nd, level)
|
|
1355
|
+
$el.find('.w2ui-node-badge')
|
|
1356
|
+
.html(txt)
|
|
1357
|
+
.attr('style', `${style}; ${last?.style ?? ''}`)
|
|
1358
|
+
if ($el.find('.w2ui-node-badge').length > 0) delete options.count
|
|
1359
|
+
}
|
|
1360
|
+
if (options.class && $el.length > 0) {
|
|
1361
|
+
nd.class = options.class
|
|
1362
|
+
level = $el.data('level')
|
|
1363
|
+
$el[0].className = 'w2ui-node w2ui-level-'+ level + (nd.selected ? ' w2ui-selected' : '') + (nd.disabled ? ' w2ui-disabled' : '') + (nd.class ? ' ' + nd.class : '')
|
|
1364
|
+
delete options.class
|
|
1365
|
+
}
|
|
1366
|
+
if (options.text != null) {
|
|
1367
|
+
nd.text = options.text
|
|
1368
|
+
$el.find('.w2ui-node-text').html(typeof nd.text == 'function' ? nd.text.call(this, nd) : nd.text)
|
|
1369
|
+
delete options.text
|
|
1370
|
+
}
|
|
1371
|
+
if (options.style && $el.length > 0) {
|
|
1372
|
+
let $txt = $el.find('.w2ui-node-text')
|
|
1373
|
+
nd.style = options.style
|
|
1374
|
+
$txt[0].style = nd.style
|
|
1375
|
+
delete options.style
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
// return what was not set
|
|
1380
|
+
return options
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
refresh(id, options = {}) {
|
|
1384
|
+
if (this.box == null) return
|
|
1385
|
+
let body = query(this.box).find(':scope > div > .w2ui-sidebar-body').get(0)
|
|
1386
|
+
let { scrollTop, scrollLeft } = body ?? {}
|
|
1387
|
+
let time = Date.now()
|
|
1388
|
+
let self = this
|
|
1389
|
+
// event before
|
|
1390
|
+
let edata = this.trigger('refresh', {
|
|
1391
|
+
target: (id != null ? id : this.name),
|
|
1392
|
+
nodeId: (id != null ? id : null),
|
|
1393
|
+
fullRefresh: (id != null ? false : true)
|
|
1394
|
+
})
|
|
1395
|
+
if (edata.isCancelled === true) return
|
|
1396
|
+
if (this.flatButton == true) {
|
|
1397
|
+
query(this.box).find('.w2ui-sidebar-top .w2ui-flat').show()
|
|
1398
|
+
.removeClass('w2ui-flat-left w2ui-flat-right')
|
|
1399
|
+
.addClass(` w2ui-flat-${(this.flat ? 'right' : 'left')}`)
|
|
1400
|
+
|
|
1401
|
+
} else {
|
|
1402
|
+
query(this.box).find('.w2ui-sidebar-top .w2ui-flat').hide()
|
|
1403
|
+
}
|
|
1404
|
+
// default action
|
|
1405
|
+
query(this.box).find(':scope > div').removeClass('w2ui-sidebar-flat').addClass(this.flat ? 'w2ui-sidebar-flat' : '').css({
|
|
1406
|
+
width : query(this.box).get(0)?.clientWidth + 'px',
|
|
1407
|
+
height: query(this.box).get(0)?.clientHeight + 'px'
|
|
1408
|
+
})
|
|
1409
|
+
// if no parent - reset nodes
|
|
1410
|
+
if (this.nodes.length > 0 && this.nodes[0].parent == null) {
|
|
1411
|
+
let tmp = this.nodes
|
|
1412
|
+
this.nodes = []
|
|
1413
|
+
this.add(this, tmp)
|
|
1414
|
+
}
|
|
1415
|
+
let obj = this
|
|
1416
|
+
let node
|
|
1417
|
+
let nodeSubId
|
|
1418
|
+
if (id == null) {
|
|
1419
|
+
node = this
|
|
1420
|
+
nodeSubId = '.w2ui-sidebar-body'
|
|
1421
|
+
} else {
|
|
1422
|
+
node = this.get(id)
|
|
1423
|
+
if (node == null) return
|
|
1424
|
+
nodeSubId = '#node_'+ w2utils.escapeId(node.id) + '_sub'
|
|
1425
|
+
}
|
|
1426
|
+
let nodeId = '#node_'+ w2utils.escapeId(node.id)
|
|
1427
|
+
let nodeHTML
|
|
1428
|
+
if (node !== this) {
|
|
1429
|
+
nodeHTML = getNodeHTML(node)
|
|
1430
|
+
query(this.box).find(nodeId).before('<div id="sidebar_'+ this.name + '_tmp"></div>')
|
|
1431
|
+
query(this.box).find(nodeId).remove()
|
|
1432
|
+
query(this.box).find(nodeSubId).remove()
|
|
1433
|
+
query(this.box).find('#sidebar_'+ this.name + '_tmp').before(nodeHTML)
|
|
1434
|
+
query(this.box).find('#sidebar_'+ this.name + '_tmp').remove()
|
|
1435
|
+
}
|
|
1436
|
+
// remember scroll position
|
|
1437
|
+
let div = query(this.box).find(':scope > div').get(0)
|
|
1438
|
+
let scroll = {
|
|
1439
|
+
top: div?.scrollTop,
|
|
1440
|
+
left: div?.scrollLeft
|
|
1441
|
+
}
|
|
1442
|
+
// refresh sub nodes
|
|
1443
|
+
query(this.box).find(nodeSubId).html('')
|
|
1444
|
+
for (let i = 0; i < node.nodes.length; i++) {
|
|
1445
|
+
let subNode = node.nodes[i]
|
|
1446
|
+
nodeHTML = getNodeHTML(subNode)
|
|
1447
|
+
query(this.box).find(nodeSubId).append(nodeHTML)
|
|
1448
|
+
if (subNode.nodes.length !== 0) {
|
|
1449
|
+
// TODO: here
|
|
1450
|
+
this.refresh(subNode.id, { recursive: true, })
|
|
1451
|
+
} else {
|
|
1452
|
+
// trigger event
|
|
1453
|
+
let edata2 = this.trigger('refresh', { target: subNode.id })
|
|
1454
|
+
if (edata2.isCancelled === true) return
|
|
1455
|
+
// event after
|
|
1456
|
+
edata2.finish()
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
// reset scroll
|
|
1460
|
+
if (div) {
|
|
1461
|
+
div.scrollTop = scroll.top
|
|
1462
|
+
div.scrollLeft = scroll.left
|
|
1463
|
+
}
|
|
1464
|
+
// bind events
|
|
1465
|
+
if (!options.recursive) {
|
|
1466
|
+
let els = query(this.box).find(`${nodeId}, ${nodeId} .w2ui-eaction, ${nodeSubId} .w2ui-eaction`)
|
|
1467
|
+
w2utils.bindEvents(els, this)
|
|
1468
|
+
// restore scroll position
|
|
1469
|
+
query(body).prop({ scrollLeft, scrollTop })
|
|
1470
|
+
}
|
|
1471
|
+
// event after
|
|
1472
|
+
edata.finish()
|
|
1473
|
+
return Date.now() - time
|
|
1474
|
+
|
|
1475
|
+
function getNodeHTML(nd) {
|
|
1476
|
+
let html = ''
|
|
1477
|
+
let icon = nd.icon
|
|
1478
|
+
if (icon == null) icon = obj.icon
|
|
1479
|
+
// -- find out level
|
|
1480
|
+
let tmp = nd.parent
|
|
1481
|
+
let level = 0
|
|
1482
|
+
while (tmp && tmp.parent != null) {
|
|
1483
|
+
// if (tmp.group) level--;
|
|
1484
|
+
tmp = tmp.parent
|
|
1485
|
+
level++
|
|
1486
|
+
}
|
|
1487
|
+
if (nd.caption != null && nd.text == null) nd.text = nd.caption
|
|
1488
|
+
if (nd.caption != null) {
|
|
1489
|
+
console.log('NOTICE: sidebar node.caption property is deprecated, please use node.text. Node -> ', nd)
|
|
1490
|
+
nd.text = nd.caption
|
|
1491
|
+
}
|
|
1492
|
+
if (Array.isArray(nd.nodes) && nd.nodes.length > 0) nd.collapsible = true
|
|
1493
|
+
if (nd.group) {
|
|
1494
|
+
let text = w2utils.lang(typeof nd.text == 'function' ? nd.text.call(obj, nd, level) : nd.text)
|
|
1495
|
+
if (String(text).substr(0, 5) != '<span') {
|
|
1496
|
+
text = `<span class="w2ui-group-text">${text}</span>`
|
|
1497
|
+
}
|
|
1498
|
+
html = `
|
|
1499
|
+
<div id="node_${nd.id}" data-id="${nd.id}" data-level="${level}" style="${nd.hidden ? 'display: none' : ''}"
|
|
1500
|
+
class="w2ui-node-group w2ui-level-${level} ${nd.class ? nd.class : ''} w2ui-eaction"
|
|
1501
|
+
data-click="toggle|${nd.id}"
|
|
1502
|
+
data-contextmenu="contextMenu|${nd.id}|event"
|
|
1503
|
+
data-mouseenter="showPlus|this|inherit"
|
|
1504
|
+
data-mouseleave="showPlus|this|transparent">
|
|
1505
|
+
${nd.groupShowHide && nd.collapsible
|
|
1506
|
+
? `<span>${!nd.hidden && nd.expanded ? w2utils.lang('Hide') : w2utils.lang('Show')}</span>`
|
|
1507
|
+
: '<span></span>'
|
|
1508
|
+
} ${text}
|
|
1509
|
+
</div>
|
|
1510
|
+
<div class="w2ui-node-sub" id="node_${nd.id}_sub" style="${nd.style}; ${!nd.hidden && nd.expanded ? '' : 'display: none;'}">
|
|
1511
|
+
</div>`
|
|
1512
|
+
if (obj.flat) {
|
|
1513
|
+
html = `
|
|
1514
|
+
<div class="w2ui-node-group" id="node_${nd.id}" data-id="${nd.id}"><span> </span></div>
|
|
1515
|
+
<div id="node_${nd.id}_sub" style="${nd.style}; ${!nd.hidden && nd.expanded ? '' : 'display: none;'}"></div>`
|
|
1516
|
+
}
|
|
1517
|
+
} else {
|
|
1518
|
+
if (nd.selected && !nd.disabled) {
|
|
1519
|
+
if (obj.multi) {
|
|
1520
|
+
obj.selected ??= []
|
|
1521
|
+
if (!obj.selected.includes(nd.id)) {
|
|
1522
|
+
obj.selected.push(nd.id)
|
|
1523
|
+
}
|
|
1524
|
+
} else {
|
|
1525
|
+
obj.selected = nd.id
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
// icon or image
|
|
1529
|
+
let image = ''
|
|
1530
|
+
if (icon) {
|
|
1531
|
+
if (icon instanceof Object) {
|
|
1532
|
+
let text = (typeof icon.text == 'function' ? (icon.text.call(obj, nd, level) ?? '') : icon.text)
|
|
1533
|
+
image = `
|
|
1534
|
+
<div class="w2ui-node-image w2ui-eaction" style="${obj.icon.style ?? ''}; pointer-events: all"
|
|
1535
|
+
data-mouseEnter="mouseAction|Enter|this|${nd.id}|event|icon"
|
|
1536
|
+
data-mouseLeave="mouseAction|Leave|this|${nd.id}|event|icon"
|
|
1537
|
+
data-click="mouseAction|click|this|${nd.id}|event|icon">
|
|
1538
|
+
${text}
|
|
1539
|
+
</div>
|
|
1540
|
+
`
|
|
1541
|
+
} else {
|
|
1542
|
+
image = `
|
|
1543
|
+
<div class="w2ui-node-image">
|
|
1544
|
+
<span class="${typeof icon == 'function' ? icon.call(obj, nd, level) : icon}"></span>
|
|
1545
|
+
</div>`
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
let expand = ''
|
|
1549
|
+
let counts = ''
|
|
1550
|
+
if (self.badge != null || nd.count != null) {
|
|
1551
|
+
let txt = nd.count ?? self.badge?.text
|
|
1552
|
+
let style = self.badge?.style
|
|
1553
|
+
let last = obj.last.badge[nd.id]
|
|
1554
|
+
if (typeof txt == 'function') txt = txt.call(self, nd, level)
|
|
1555
|
+
if (txt || txt === 0) { // can be number 0
|
|
1556
|
+
counts = `
|
|
1557
|
+
<div class="w2ui-node-badge w2ui-eaction ${nd.count != null ? 'w2ui-node-count' : ''} ${last?.className ?? ''}"
|
|
1558
|
+
style="${style ?? ''};${last?.style ?? ''}"
|
|
1559
|
+
data-mouseEnter="mouseAction|Enter|this|${nd.id}|event|badge"
|
|
1560
|
+
data-mouseLeave="mouseAction|Leave|this|${nd.id}|event|badge"
|
|
1561
|
+
data-click="mouseAction|click|this|${nd.id}|event|badge"
|
|
1562
|
+
>
|
|
1563
|
+
${txt}
|
|
1564
|
+
</div>`
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
// array with classes
|
|
1568
|
+
let classes = ['w2ui-node', `w2ui-level-${level}`, 'w2ui-eaction']
|
|
1569
|
+
if (nd.selected) classes.push('w2ui-selected')
|
|
1570
|
+
if (nd.disabled) classes.push('w2ui-disabled')
|
|
1571
|
+
if (nd.class) classes.push(nd.class)
|
|
1572
|
+
// collapsible
|
|
1573
|
+
if (nd.collapsible === true) {
|
|
1574
|
+
let toggleClasses = ['w2ui-sb-toggle', 'w2ui-eaction', (nd.expanded ? 'w2ui-expanded' : 'w2ui-collapsed')]
|
|
1575
|
+
if (self.toggleAlign == 'left') toggleClasses.push('w2ui-left-toggle')
|
|
1576
|
+
expand = `<div class="${toggleClasses.join(' ')}" data-click="toggle|${nd.id}"><span></span></div>`
|
|
1577
|
+
classes.push('w2ui-has-children')
|
|
1578
|
+
}
|
|
1579
|
+
let text = w2utils.lang(typeof nd.text == 'function' ? nd.text.call(obj, nd, level) : nd.text)
|
|
1580
|
+
let nodeOffset = nd.parent?.childOffset ?? 0
|
|
1581
|
+
// if (level === 0 && nd.collapsible === true && self.toggleAlign == 'left') {
|
|
1582
|
+
nodeOffset += 12
|
|
1583
|
+
// }
|
|
1584
|
+
html = `
|
|
1585
|
+
<div id="node_${nd.id}" class="${classes.join(' ')}" data-id="${nd.id}" data-level="${level}"
|
|
1586
|
+
style="${nd.hidden ? 'display: none;' : ''}"
|
|
1587
|
+
data-click="click|${nd.id}|event"
|
|
1588
|
+
data-dblclick="dblClick|${nd.id}|event"
|
|
1589
|
+
data-mouseDown="mouseDown|${nd.id}|event"
|
|
1590
|
+
data-contextmenu="contextMenu|${nd.id}|event"
|
|
1591
|
+
data-mouseEnter="mouseAction|Enter|this|${nd.id}|event"
|
|
1592
|
+
data-mouseLeave="mouseAction|Leave|this|${nd.id}|event"
|
|
1593
|
+
>
|
|
1594
|
+
${obj.handle.text
|
|
1595
|
+
? `<div class="w2ui-node-handle w2ui-eaction" style="width: ${obj.handle.width}px; ${obj.handle.style}"
|
|
1596
|
+
data-mouseEnter="mouseAction|Enter|this|${nd.id}|event|handle"
|
|
1597
|
+
data-mouseLeave="mouseAction|Leave|this|${nd.id}|event|handle"
|
|
1598
|
+
data-click="mouseAction|click|this|${nd.id}|event|handle"
|
|
1599
|
+
>
|
|
1600
|
+
${typeof obj.handle.text == 'function' ? obj.handle.text.call(obj, nd, level) ?? '' : obj.handle.text}
|
|
1601
|
+
</div>`
|
|
1602
|
+
: ''
|
|
1603
|
+
}
|
|
1604
|
+
<div class="w2ui-node-data" style="margin-left: ${(level * obj.levelPadding) + nodeOffset + obj.handle.width}px">
|
|
1605
|
+
${expand} ${image} ${counts}
|
|
1606
|
+
<div class="w2ui-node-text ${!image ? 'no-icon' : ''}" style="${nd.style || ''}">${text}</div>
|
|
1607
|
+
</div>
|
|
1608
|
+
</div>
|
|
1609
|
+
<div class="w2ui-node-sub" id="node_${nd.id}_sub" style="${nd.style}; ${!nd.hidden && nd.expanded ? '' : 'display: none;'}"></div>`
|
|
1610
|
+
if (obj.flat) {
|
|
1611
|
+
html = `
|
|
1612
|
+
<div id="node_${nd.id}" class="${classes.join(' ')} w2ui-node-flat" data-id="${nd.id}" style="${nd.hidden ? 'display: none;' : ''}"
|
|
1613
|
+
data-click="click|${nd.id}|event"
|
|
1614
|
+
data-dblclick="dblClick|${nd.id}|event"
|
|
1615
|
+
data-contextmenu="contextMenu|${nd.id}|event"
|
|
1616
|
+
data-mouseEnter="mouseAction|Enter|this|${nd.id}|event|tooltip"
|
|
1617
|
+
data-mouseLeave="mouseAction|Leave|this|${nd.id}|event|tooltip"
|
|
1618
|
+
>
|
|
1619
|
+
<div class="w2ui-node-data">${image}</div>
|
|
1620
|
+
</div>
|
|
1621
|
+
<div class="w2ui-node-sub" id="node_${nd.id}_sub" style="${nd.style}; ${!nd.hidden && nd.expanded ? '' : 'display: none;'}"></div>`
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
return html
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
mouseAction(action, anchor, nodeId, event, type) {
|
|
1629
|
+
let edata
|
|
1630
|
+
let node = this.get(nodeId)
|
|
1631
|
+
if (type == null) {
|
|
1632
|
+
edata = this.trigger('mouse' + action, { target: node.id, node, originalEvent: event })
|
|
1633
|
+
}
|
|
1634
|
+
if (type == 'tooltip') {
|
|
1635
|
+
// this tooltip shows for flat sidebars
|
|
1636
|
+
let text = w2utils.lang(typeof node.text == 'function' ? node.text.call(this, node) : node.text)
|
|
1637
|
+
let tooltip = text + (node.count != null
|
|
1638
|
+
? ' - <span class="w2ui-node-badge w2ui-node-count">'+ node.count +'</span>'
|
|
1639
|
+
: '')
|
|
1640
|
+
if (action == 'Leave' || this.selected == node.id) tooltip = ''
|
|
1641
|
+
this.tooltip(anchor, tooltip)
|
|
1642
|
+
}
|
|
1643
|
+
if (type == 'handle') {
|
|
1644
|
+
if (action == 'click') {
|
|
1645
|
+
let onClick = this.handle.onClick
|
|
1646
|
+
if (typeof onClick == 'function') {
|
|
1647
|
+
onClick.call(this, node, event)
|
|
1648
|
+
}
|
|
1649
|
+
} else {
|
|
1650
|
+
let tooltip = this.handle.tooltip
|
|
1651
|
+
if (typeof tooltip == 'function') {
|
|
1652
|
+
tooltip = tooltip.call(this, node, event)
|
|
1653
|
+
}
|
|
1654
|
+
if (action == 'Leave') tooltip = ''
|
|
1655
|
+
this.otherTooltip(anchor, tooltip)
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
if (type == 'icon') {
|
|
1659
|
+
if (action == 'click') {
|
|
1660
|
+
let onClick = this.icon.onClick
|
|
1661
|
+
if (typeof onClick == 'function') {
|
|
1662
|
+
onClick.call(this, node, event)
|
|
1663
|
+
}
|
|
1664
|
+
} else {
|
|
1665
|
+
let tooltip = this.icon.tooltip
|
|
1666
|
+
if (typeof tooltip == 'function') {
|
|
1667
|
+
tooltip = tooltip.call(this, node, event)
|
|
1668
|
+
}
|
|
1669
|
+
if (action == 'Leave') tooltip = ''
|
|
1670
|
+
this.otherTooltip(anchor, tooltip)
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
if (type == 'badge') {
|
|
1674
|
+
if (action == 'click') {
|
|
1675
|
+
let onClick = this.badge?.onClick
|
|
1676
|
+
if (typeof onClick == 'function') {
|
|
1677
|
+
onClick.call(this, node, event)
|
|
1678
|
+
}
|
|
1679
|
+
} else {
|
|
1680
|
+
let tooltip = this.badge?.tooltip
|
|
1681
|
+
if (typeof tooltip == 'function') {
|
|
1682
|
+
tooltip = tooltip.call(this, node, event)
|
|
1683
|
+
}
|
|
1684
|
+
if (action == 'Leave') tooltip = ''
|
|
1685
|
+
this.otherTooltip(anchor, tooltip)
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
edata?.finish()
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1691
|
+
tooltip(el, text) {
|
|
1692
|
+
let $el = query(el).find('.w2ui-node-data')
|
|
1693
|
+
if (text !== '') {
|
|
1694
|
+
w2tooltip.show({
|
|
1695
|
+
anchor: $el.get(0),
|
|
1696
|
+
name: this.name + '_tooltip',
|
|
1697
|
+
html: text,
|
|
1698
|
+
position: 'right|left'
|
|
1699
|
+
})
|
|
1700
|
+
} else {
|
|
1701
|
+
w2tooltip.hide(this.name + '_tooltip')
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
otherTooltip(el, text) {
|
|
1706
|
+
if (text !== '') {
|
|
1707
|
+
w2tooltip.show({
|
|
1708
|
+
anchor: el,
|
|
1709
|
+
name: this.name + '_tooltip',
|
|
1710
|
+
html: text,
|
|
1711
|
+
position: 'top|bottom'
|
|
1712
|
+
})
|
|
1713
|
+
} else {
|
|
1714
|
+
w2tooltip.hide(this.name + '_tooltip')
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
showPlus(el, color) {
|
|
1719
|
+
query(el).find('span:nth-child(1)').css('color', color)
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
resize() {
|
|
1723
|
+
let time = Date.now()
|
|
1724
|
+
// event before
|
|
1725
|
+
let edata = this.trigger('resize', { target: this.name })
|
|
1726
|
+
if (edata.isCancelled === true) return
|
|
1727
|
+
// default action
|
|
1728
|
+
if (this.box != null) {
|
|
1729
|
+
let rect = query(this.box).get(0).getBoundingClientRect()
|
|
1730
|
+
query(this.box).css('overflow', 'hidden') // container should have no overflow
|
|
1731
|
+
query(this.box).find(':scope > div').css({
|
|
1732
|
+
width : rect.width + 'px',
|
|
1733
|
+
height : rect.height + 'px'
|
|
1734
|
+
})
|
|
1735
|
+
}
|
|
1736
|
+
// event after
|
|
1737
|
+
edata.finish()
|
|
1738
|
+
return Date.now() - time
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
destroy() {
|
|
1742
|
+
// event before
|
|
1743
|
+
let edata = this.trigger('destroy', { target: this.name })
|
|
1744
|
+
if (edata.isCancelled === true) return
|
|
1745
|
+
// clean up
|
|
1746
|
+
if (query(this.box).find('.w2ui-sidebar-body').length > 0) {
|
|
1747
|
+
this.unmount()
|
|
1748
|
+
}
|
|
1749
|
+
delete w2ui[this.name]
|
|
1750
|
+
// event after
|
|
1751
|
+
edata.finish()
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
unmount() {
|
|
1755
|
+
super.unmount()
|
|
1756
|
+
this.last.observeResize?.disconnect()
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
lock(msg, showSpinner) {
|
|
1760
|
+
let args = Array.from(arguments)
|
|
1761
|
+
args.unshift(this.box)
|
|
1762
|
+
w2utils.lock(...args)
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
unlock(speed) {
|
|
1766
|
+
w2utils.unlock(this.box, speed)
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
export { w2sidebar }
|