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.
Files changed (182) hide show
  1. package/README.md +169 -0
  2. package/index.js +3 -0
  3. package/package.json +27 -0
  4. package/sample.js +37 -0
  5. package/scripts/airbnb.js +73 -0
  6. package/scripts/airbnb2.js +74 -0
  7. package/scripts/airbnb2_queries.js +231 -0
  8. package/scripts/airbnb_queries.js +264 -0
  9. package/scripts/downloadFile.js +42 -0
  10. package/scripts/express.js +46 -0
  11. package/scripts/fastify.js +79 -0
  12. package/scripts/flights.js +75 -0
  13. package/scripts/flights2.js +81 -0
  14. package/scripts/flights2_queries.js +453 -0
  15. package/scripts/flights_queries.js +403 -0
  16. package/src/QyAcl.js +252 -0
  17. package/src/QyAclSaver.js +14 -0
  18. package/src/QyAclSaver_Worker.js +29 -0
  19. package/src/QyAclWriter.js +19 -0
  20. package/src/QyBatch.js +501 -0
  21. package/src/QyBinWriter.js +140 -0
  22. package/src/QyCD.js +61 -0
  23. package/src/QyCache.js +212 -0
  24. package/src/QyCompressor.js +60 -0
  25. package/src/QyCompressor_Worker.js +13 -0
  26. package/src/QyDB.js +122 -0
  27. package/src/QyDefaultOptions.js +59 -0
  28. package/src/QyDir.js +192 -0
  29. package/src/QyFetch.js +38 -0
  30. package/src/QyFile.js +124 -0
  31. package/src/QyFileContentUtils.js +175 -0
  32. package/src/QyFileLogger.js +58 -0
  33. package/src/QyIndex.js +237 -0
  34. package/src/QyIndexPropTree.js +92 -0
  35. package/src/QyIntersectNode.js +48 -0
  36. package/src/QyItem.js +105 -0
  37. package/src/QyJsonSaver.js +20 -0
  38. package/src/QyKVData.js +289 -0
  39. package/src/QyKVDataCleaner.js +17 -0
  40. package/src/QyKVDataCleaner_Worker.js +94 -0
  41. package/src/QyKVDataLoader.js +65 -0
  42. package/src/QyKVDataSaver.js +17 -0
  43. package/src/QyKVDataSaver_Worker.js +81 -0
  44. package/src/QyLogFileSaver.js +14 -0
  45. package/src/QyLogFileSaver_Worker.js +26 -0
  46. package/src/QyLogger.js +76 -0
  47. package/src/QyMessageWorker.js +41 -0
  48. package/src/QyMessager.js +84 -0
  49. package/src/QyMessager_Run.js +13 -0
  50. package/src/QyMod.js +15 -0
  51. package/src/QyOpRunner.js +73 -0
  52. package/src/QyQueue.js +60 -0
  53. package/src/QySaver.js +83 -0
  54. package/src/QySnapshotCompactor.js +17 -0
  55. package/src/QySnapshotCompactor_Worker.js +151 -0
  56. package/src/QySnapshotSaver.js +17 -0
  57. package/src/QySnapshotSaver_Worker.js +164 -0
  58. package/src/QySnapshots.js +354 -0
  59. package/src/QyStructure.js +50 -0
  60. package/src/QyTrigger.js +133 -0
  61. package/src/QyUnionNode.js +105 -0
  62. package/src/QyUtils.js +250 -0
  63. package/src/QyWorker.js +33 -0
  64. package/src/hackernews.js +93 -0
  65. package/src/rpc/evalCode.js +9 -0
  66. package/src/rpc/getFileContent.js +16 -0
  67. package/src/rpc/getSubItems.js +32 -0
  68. package/src/rpc/queryFiles.js +33 -0
  69. package/src/rpc/reloadRpc.js +1 -0
  70. package/src/simulate.js +114 -0
  71. package/src/simulate2.js +110 -0
  72. package/src/soc_pokec.js +43 -0
  73. package/static/bootstrap-5.3.8-dist/css/bootstrap.min.css +6 -0
  74. package/static/bootstrap-5.3.8-dist/js/bootstrap.bundle.js +6312 -0
  75. package/static/datafolderui/QyStyledElement.js +30 -0
  76. package/static/datafolderui/QyUIFolderTree.js +203 -0
  77. package/static/datafolderui/QyUIUtils.js +42 -0
  78. package/static/datafolderui/display-tree.js +108 -0
  79. package/static/datafolderui/explore-tree.js +122 -0
  80. package/static/datafolderui/folder-tree.js +5 -0
  81. package/static/datafolderui/hscrpt.js +25 -0
  82. package/static/datafolderui/index.css +6 -0
  83. package/static/datafolderui/index.html +20 -0
  84. package/static/datafolderui/json-view.js +74 -0
  85. package/static/datafolderui/kv-input.js +66 -0
  86. package/static/datafolderui/list-input.js +52 -0
  87. package/static/datafolderui/main-page.js +98 -0
  88. package/static/datafolderui/num-input.js +27 -0
  89. package/static/datafolderui/query-editor.js +229 -0
  90. package/static/datafolderui/querySelectorShadowRoot.js +24 -0
  91. package/static/datafolderui/resizable-input.js +67 -0
  92. package/static/favicon.ico +0 -0
  93. package/static/icons-1.13.1/font/bootstrap-icons.min.css +5 -0
  94. package/static/icons-1.13.1/font/fonts/bootstrap-icons.woff +0 -0
  95. package/static/icons-1.13.1/font/fonts/bootstrap-icons.woff2 +0 -0
  96. package/static/json-view/dist/jsonview.js +433 -0
  97. package/static/tree.js/tree.css +106 -0
  98. package/static/tree.js/tree.js +374 -0
  99. package/static/w2ui/dist/w2ui.min.css +2 -0
  100. package/static/w2ui/src/less/icons/icons.json +1 -0
  101. package/static/w2ui/src/less/icons/preview.html +33 -0
  102. package/static/w2ui/src/less/icons/readme.md +15 -0
  103. package/static/w2ui/src/less/icons/svg/box.svg +3 -0
  104. package/static/w2ui/src/less/icons/svg/check.svg +3 -0
  105. package/static/w2ui/src/less/icons/svg/colors.svg +3 -0
  106. package/static/w2ui/src/less/icons/svg/columns.svg +5 -0
  107. package/static/w2ui/src/less/icons/svg/cross.svg +4 -0
  108. package/static/w2ui/src/less/icons/svg/drop.svg +6 -0
  109. package/static/w2ui/src/less/icons/svg/empty.svg +3 -0
  110. package/static/w2ui/src/less/icons/svg/eye-dropper.svg +4 -0
  111. package/static/w2ui/src/less/icons/svg/info.svg +8 -0
  112. package/static/w2ui/src/less/icons/svg/paste.svg +4 -0
  113. package/static/w2ui/src/less/icons/svg/pencil.svg +5 -0
  114. package/static/w2ui/src/less/icons/svg/plus.svg +3 -0
  115. package/static/w2ui/src/less/icons/svg/reload.svg +5 -0
  116. package/static/w2ui/src/less/icons/svg/search.svg +3 -0
  117. package/static/w2ui/src/less/icons/svg/settings.svg +8 -0
  118. package/static/w2ui/src/less/icons/w2ui-font.css +36 -0
  119. package/static/w2ui/src/less/icons/w2ui-font.woff +0 -0
  120. package/static/w2ui/src/less/src/buttons.less +184 -0
  121. package/static/w2ui/src/less/src/common.less +541 -0
  122. package/static/w2ui/src/less/src/fields.less +302 -0
  123. package/static/w2ui/src/less/src/form.less +319 -0
  124. package/static/w2ui/src/less/src/grid.less +1057 -0
  125. package/static/w2ui/src/less/src/icons.less +37 -0
  126. package/static/w2ui/src/less/src/layout.less +86 -0
  127. package/static/w2ui/src/less/src/mixins.less +87 -0
  128. package/static/w2ui/src/less/src/popup.less +277 -0
  129. package/static/w2ui/src/less/src/sidebar.less +343 -0
  130. package/static/w2ui/src/less/src/tabs.less +145 -0
  131. package/static/w2ui/src/less/src/toolbar.less +219 -0
  132. package/static/w2ui/src/less/src/tooltip.less +948 -0
  133. package/static/w2ui/src/less/w2ui.less +196 -0
  134. package/static/w2ui/src/locale/az-az.json +114 -0
  135. package/static/w2ui/src/locale/ba-ba.json +114 -0
  136. package/static/w2ui/src/locale/bg-bg.json +114 -0
  137. package/static/w2ui/src/locale/ca-es.json +114 -0
  138. package/static/w2ui/src/locale/da-dk.json +114 -0
  139. package/static/w2ui/src/locale/de-de.json +114 -0
  140. package/static/w2ui/src/locale/en-gb.json +17 -0
  141. package/static/w2ui/src/locale/en-us.json +17 -0
  142. package/static/w2ui/src/locale/es-ar.json +115 -0
  143. package/static/w2ui/src/locale/es-cr.json +119 -0
  144. package/static/w2ui/src/locale/es-es.json +114 -0
  145. package/static/w2ui/src/locale/es-mx.json +114 -0
  146. package/static/w2ui/src/locale/fr-fr.json +114 -0
  147. package/static/w2ui/src/locale/gl-es.json +114 -0
  148. package/static/w2ui/src/locale/hr-hr.json +114 -0
  149. package/static/w2ui/src/locale/hu-hu.json +114 -0
  150. package/static/w2ui/src/locale/id-id.json +114 -0
  151. package/static/w2ui/src/locale/it-it.json +114 -0
  152. package/static/w2ui/src/locale/ja-jp.json +114 -0
  153. package/static/w2ui/src/locale/kk-kz.json +116 -0
  154. package/static/w2ui/src/locale/ko-kr.json +114 -0
  155. package/static/w2ui/src/locale/lt-lt.json +114 -0
  156. package/static/w2ui/src/locale/nl-nl.json +114 -0
  157. package/static/w2ui/src/locale/no-no.json +114 -0
  158. package/static/w2ui/src/locale/pl-pl.json +114 -0
  159. package/static/w2ui/src/locale/pt-br.json +114 -0
  160. package/static/w2ui/src/locale/ru-ru.json +116 -0
  161. package/static/w2ui/src/locale/sk-sk.json +114 -0
  162. package/static/w2ui/src/locale/sl-si.json +116 -0
  163. package/static/w2ui/src/locale/sr-rs.json +114 -0
  164. package/static/w2ui/src/locale/tr-tr.json +114 -0
  165. package/static/w2ui/src/locale/uk-ua.json +114 -0
  166. package/static/w2ui/src/locale/zh-cn.json +114 -0
  167. package/static/w2ui/src/locale/zh-tw.json +114 -0
  168. package/static/w2ui/src/query.js +583 -0
  169. package/static/w2ui/src/readme.md +11 -0
  170. package/static/w2ui/src/w2base.js +311 -0
  171. package/static/w2ui/src/w2compat.js +207 -0
  172. package/static/w2ui/src/w2field.js +1854 -0
  173. package/static/w2ui/src/w2form.js +2411 -0
  174. package/static/w2ui/src/w2grid.js +8916 -0
  175. package/static/w2ui/src/w2layout.js +1194 -0
  176. package/static/w2ui/src/w2locale.js +129 -0
  177. package/static/w2ui/src/w2popup.js +909 -0
  178. package/static/w2ui/src/w2sidebar.js +1769 -0
  179. package/static/w2ui/src/w2tabs.js +669 -0
  180. package/static/w2ui/src/w2toolbar.js +1180 -0
  181. package/static/w2ui/src/w2tooltip.js +3134 -0
  182. package/static/w2ui/src/w2utils.js +2457 -0
@@ -0,0 +1,583 @@
1
+ /* mQuery 0.7 (nightly) (8/15/2023, 11:44:12 AM), vitmalina@gmail.com */
2
+ class Query {
3
+ static version = 0.8
4
+ constructor(selector, context) {
5
+ this.context = context ?? document
6
+ let nodes = []
7
+ if (Array.isArray(selector)) {
8
+ nodes = selector
9
+ } else if (selector instanceof Node || selector instanceof Window) { // any html element or Window
10
+ nodes = [selector]
11
+ } else if (selector instanceof Query) {
12
+ nodes = selector.nodes
13
+ } else if (typeof selector == 'string') {
14
+ if (typeof this.context.querySelector != 'function') {
15
+ throw new Error('Invalid context')
16
+ }
17
+ nodes = Array.from(this.context.querySelectorAll(selector))
18
+ } else if (selector == null) {
19
+ nodes = []
20
+ } else {
21
+ // if selector is itterable, then try to create nodes from it, also supports jQuery
22
+ let arr = Array.from(selector ?? [])
23
+ if (typeof selector == 'object' && Array.isArray(arr)) {
24
+ nodes = arr
25
+ } else {
26
+ throw new Error(`Invalid selector "${selector}"`)
27
+ }
28
+ }
29
+ this.nodes = nodes
30
+ this.length = nodes.length
31
+ // map nodes to object propoerties
32
+ this.each((node, ind) => {
33
+ this[ind] = node
34
+ })
35
+ }
36
+ static _fragment(html) {
37
+ let tmpl = document.createElement('template')
38
+ tmpl.innerHTML = html
39
+ tmpl.content.childNodes.forEach(node => {
40
+ let newNode = Query._scriptConvert(node)
41
+ if (newNode != node) {
42
+ tmpl.content.replaceChild(newNode, node)
43
+ }
44
+ })
45
+ return tmpl.content
46
+ }
47
+ // innerHTML, append, etc. script tags will not be executed unless they are proper script tags
48
+ static _scriptConvert(node) {
49
+ let convert = (txtNode) => {
50
+ let doc = txtNode.ownerDocument
51
+ let scNode = doc.createElement('script')
52
+ scNode.text = txtNode.text
53
+ let attrs = txtNode.attributes
54
+ for (let i = 0; i < attrs.length; i++) {
55
+ scNode.setAttribute(attrs[i].name, attrs[i].value)
56
+ }
57
+ return scNode
58
+ }
59
+ if (node.tagName == 'SCRIPT') {
60
+ node = convert(node)
61
+ }
62
+ if (node.querySelectorAll) {
63
+ node.querySelectorAll('script').forEach(textNode => {
64
+ textNode.parentNode.replaceChild(convert(textNode), textNode)
65
+ })
66
+ }
67
+ return node
68
+ }
69
+ static _fixProp(name) {
70
+ let fixes = {
71
+ cellpadding: 'cellPadding',
72
+ cellspacing: 'cellSpacing',
73
+ class: 'className',
74
+ colspan: 'colSpan',
75
+ contenteditable: 'contentEditable',
76
+ for: 'htmlFor',
77
+ frameborder: 'frameBorder',
78
+ maxlength: 'maxLength',
79
+ readonly: 'readOnly',
80
+ rowspan: 'rowSpan',
81
+ tabindex: 'tabIndex',
82
+ usemap: 'useMap'
83
+ }
84
+ return fixes[name] ? fixes[name] : name
85
+ }
86
+ _insert(method, html) {
87
+ let nodes = []
88
+ let len = this.length
89
+ if (len < 1) return
90
+ let self = this
91
+ // TODO: need good unit test coverage for this function
92
+ if (typeof html == 'string') {
93
+ this.each(node => {
94
+ let clone = Query._fragment(html)
95
+ nodes.push(...clone.childNodes)
96
+ node[method](clone)
97
+ })
98
+ } else if (html instanceof Query) {
99
+ let single = (len == 1) // if inserting into a single container, then move it there
100
+ html.each(el => {
101
+ this.each(node => {
102
+ // if insert before a single node, just move new one, else clone and move it
103
+ let clone = (single ? el : el.cloneNode(true))
104
+ nodes.push(clone)
105
+ node[method](clone)
106
+ Query._scriptConvert(clone)
107
+ })
108
+ })
109
+ if (!single) html.remove()
110
+ } else if (html instanceof Node) { // any HTML element
111
+ this.each(node => {
112
+ // if insert before a single node, just move new one, else clone and move it
113
+ let clone = (len === 1 ? html : Query._fragment(html.outerHTML))
114
+ nodes.push(...(len === 1 ? [html] : clone.childNodes))
115
+ node[method](clone)
116
+ })
117
+ if (len > 1) html.remove()
118
+ } else {
119
+ throw new Error(`Incorrect argument for "${method}(html)". It expects one string argument.`)
120
+ }
121
+ if (method == 'replaceWith') {
122
+ self = new Query(nodes, this.context) // must return a new collection
123
+ }
124
+ return self
125
+ }
126
+ _save(node, name, value) {
127
+ node._mQuery = node._mQuery ?? {}
128
+ if (Array.isArray(value)) {
129
+ node._mQuery[name] = node._mQuery[name] ?? []
130
+ node._mQuery[name].push(...value)
131
+ } else if (value != null) {
132
+ node._mQuery[name] = value
133
+ } else {
134
+ delete node._mQuery[name]
135
+ }
136
+ }
137
+ get(index) {
138
+ if (index < 0) index = this.length + index
139
+ let node = this[index]
140
+ if (node) {
141
+ return node
142
+ }
143
+ if (index != null) {
144
+ return null
145
+ }
146
+ return this.nodes
147
+ }
148
+ eq(index) {
149
+ if (index < 0) index = this.length + index
150
+ let nodes = [this[index]]
151
+ if (nodes[0] == null) nodes = []
152
+ return new Query(nodes, this.context) // must return a new collection
153
+ }
154
+ then(fun) {
155
+ let ret = fun(this)
156
+ return ret != null ? ret : this
157
+ }
158
+ find(selector) {
159
+ let nodes = []
160
+ this.each(node => {
161
+ let nn = Array.from(node.querySelectorAll(selector))
162
+ if (nn.length > 0) {
163
+ nodes.push(...nn)
164
+ }
165
+ })
166
+ return new Query(nodes, this.context) // must return a new collection
167
+ }
168
+ filter(selector) {
169
+ let nodes = []
170
+ this.each(node => {
171
+ if (node === selector
172
+ || (typeof selector == 'string' && node.matches && node.matches(selector))
173
+ || (typeof selector == 'function' && selector(node))
174
+ ) {
175
+ nodes.push(node)
176
+ }
177
+ })
178
+ return new Query(nodes, this.context) // must return a new collection
179
+ }
180
+ next() {
181
+ let nodes = []
182
+ this.each(node => {
183
+ let nn = node.nextElementSibling
184
+ if (nn) { nodes.push(nn) }
185
+ })
186
+ return new Query(nodes, this.context) // must return a new collection
187
+ }
188
+ prev() {
189
+ let nodes = []
190
+ this.each(node => {
191
+ let nn = node.previousElementSibling
192
+ if (nn) { nodes.push(nn)}
193
+ })
194
+ return new Query(nodes, this.context) // must return a new collection
195
+ }
196
+ shadow(selector) {
197
+ let nodes = []
198
+ this.each(node => {
199
+ // select shadow root if available
200
+ if (node.shadowRoot) nodes.push(node.shadowRoot)
201
+ })
202
+ let col = new Query(nodes, this.context)
203
+ return selector ? col.find(selector) : col
204
+ }
205
+ closest(selector) {
206
+ let nodes = []
207
+ this.each(node => {
208
+ let nn = node.closest(selector)
209
+ if (nn) {
210
+ nodes.push(nn)
211
+ }
212
+ })
213
+ return new Query(nodes, this.context) // must return a new collection
214
+ }
215
+ host(all) {
216
+ let nodes = []
217
+ // find shadow root or body
218
+ let top = (node) => {
219
+ if (node.parentNode) {
220
+ return top(node.parentNode)
221
+ } else {
222
+ return node
223
+ }
224
+ }
225
+ let fun = (node) => {
226
+ let nn = top(node)
227
+ nodes.push(nn.host ? nn.host : nn)
228
+ if (nn.host && all) fun(nn.host)
229
+ }
230
+ this.each(node => {
231
+ fun(node)
232
+ })
233
+ return new Query(nodes, this.context) // must return a new collection
234
+ }
235
+ parent(selector) {
236
+ return this.parents(selector, true)
237
+ }
238
+ parents(selector, firstOnly) {
239
+ let nodes = []
240
+ let add = (node) => {
241
+ if (nodes.indexOf(node) == -1) {
242
+ nodes.push(node)
243
+ }
244
+ if (!firstOnly && node.parentNode) {
245
+ return add(node.parentNode)
246
+ }
247
+ }
248
+ this.each(node => {
249
+ if (node.parentNode) add(node.parentNode)
250
+ })
251
+ let col = new Query(nodes, this.context)
252
+ return selector ? col.filter(selector) : col
253
+ }
254
+ add(more) {
255
+ let nodes = more instanceof Query ? more.nodes : (Array.isArray(more) ? more : [more])
256
+ return new Query(this.nodes.concat(nodes), this.context) // must return a new collection
257
+ }
258
+ each(func) {
259
+ this.nodes.forEach((node, ind) => { func(node, ind, this) })
260
+ return this
261
+ }
262
+ append(html) {
263
+ return this._insert('append', html)
264
+ }
265
+ prepend(html) {
266
+ return this._insert('prepend', html)
267
+ }
268
+ after(html) {
269
+ return this._insert('after', html)
270
+ }
271
+ before(html) {
272
+ return this._insert('before', html)
273
+ }
274
+ replace(html) {
275
+ return this._insert('replaceWith', html)
276
+ }
277
+ remove() {
278
+ // remove from dom, but keep in current query
279
+ this.each(node => { node.remove() })
280
+ return this
281
+ }
282
+ css(key, value) {
283
+ let css = key
284
+ let len = arguments.length
285
+ if (len === 0 || (len === 1 && typeof key == 'string')) {
286
+ if (this[0]) {
287
+ let st = this[0].style
288
+ // do not do computedStyleMap as it is not what on immediate element
289
+ if (typeof key == 'string') {
290
+ let pri = st.getPropertyPriority(key)
291
+ return st.getPropertyValue(key) + (pri ? '!' + pri : '')
292
+ } else {
293
+ return Object.fromEntries(
294
+ this[0].style.cssText
295
+ .split(';')
296
+ .filter(a => !!a) // filter non-empty
297
+ .map(a => {
298
+ return a.split(':').map(a => a.trim()) // trim strings
299
+ })
300
+ )
301
+ }
302
+ } else {
303
+ return undefined
304
+ }
305
+ } else {
306
+ if (typeof key != 'object') {
307
+ css = {}
308
+ css[key] = value
309
+ }
310
+ this.each((el, ind) => {
311
+ Object.keys(css).forEach(key => {
312
+ let imp = String(css[key]).toLowerCase().includes('!important') ? 'important' : ''
313
+ el.style.setProperty(key, String(css[key]).replace(/\!important/i, ''), imp)
314
+ })
315
+ })
316
+ return this
317
+ }
318
+ }
319
+ addClass(classes) {
320
+ this.toggleClass(classes, true)
321
+ return this
322
+ }
323
+ removeClass(classes) {
324
+ this.toggleClass(classes, false)
325
+ return this
326
+ }
327
+ toggleClass(classes, force) {
328
+ // split by comma or space
329
+ if (typeof classes == 'string') classes = classes.split(/[,\s]+/)
330
+ this.each(node => {
331
+ let classes2 = classes
332
+ // if not defined, remove all classes
333
+ if (classes2 == null && force === false) classes2 = Array.from(node.classList)
334
+ classes2.forEach(className => {
335
+ if (className !== '') {
336
+ let act = 'toggle'
337
+ if (force != null) act = force ? 'add' : 'remove'
338
+ node.classList[act](className)
339
+ }
340
+ })
341
+ })
342
+ return this
343
+ }
344
+ hasClass(classes) {
345
+ // split by comma or space
346
+ if (typeof classes == 'string') classes = classes.split(/[,\s]+/)
347
+ if (classes == null && this.length > 0) {
348
+ return Array.from(this[0].classList)
349
+ }
350
+ let ret = false
351
+ this.each(node => {
352
+ ret = ret || classes.every(className => {
353
+ return Array.from(node.classList ?? []).includes(className)
354
+ })
355
+ })
356
+ return ret
357
+ }
358
+ on(events, options, callback) {
359
+ if (typeof options == 'function') {
360
+ callback = options
361
+ options = undefined
362
+ }
363
+ let delegate
364
+ if (options?.delegate) {
365
+ delegate = options.delegate
366
+ delete options.delegate // not to pass to addEventListener
367
+ }
368
+ events = events.split(/[,\s]+/) // separate by comma or space
369
+ events.forEach(eventName => {
370
+ let [ event, scope ] = String(eventName).toLowerCase().split('.')
371
+ if (delegate) {
372
+ let fun = callback
373
+ callback = (event) => {
374
+ // event.target or any ancestors match delegate selector
375
+ let parent = query(event.target).parents(delegate)
376
+ if (parent.length > 0) { event.delegate = parent[0] } else { event.delegate = event.target }
377
+ if (event.target.matches(delegate) || parent.length > 0) {
378
+ fun(event)
379
+ }
380
+ }
381
+ }
382
+ this.each(node => {
383
+ this._save(node, 'events', [{ event, scope, callback, options }])
384
+ node.addEventListener(event, callback, options)
385
+ })
386
+ })
387
+ return this
388
+ }
389
+ off(events, options, callback) {
390
+ if (typeof options == 'function') {
391
+ callback = options
392
+ options = undefined
393
+ }
394
+ events = (events ?? '').split(/[,\s]+/) // separate by comma or space
395
+ events.forEach(eventName => {
396
+ let [ event, scope ] = String(eventName).toLowerCase().split('.')
397
+ this.each(node => {
398
+ if (Array.isArray(node._mQuery?.events)) {
399
+ for (let i = node._mQuery.events.length - 1; i >= 0; i--) {
400
+ let evt = node._mQuery.events[i]
401
+ if (scope == null || scope === '') {
402
+ // if no scope, has to be exact match
403
+ if ((evt.event == event || event === '') && (evt.callback == callback || callback == null)) {
404
+ node.removeEventListener(evt.event, evt.callback, evt.options)
405
+ node._mQuery.events.splice(i, 1)
406
+ }
407
+ } else {
408
+ if ((evt.event == event || event === '') && evt.scope == scope) {
409
+ node.removeEventListener(evt.event, evt.callback, evt.options)
410
+ node._mQuery.events.splice(i, 1)
411
+ }
412
+ }
413
+ }
414
+ }
415
+ })
416
+ })
417
+ return this
418
+ }
419
+ trigger(name, options) {
420
+ let event,
421
+ mevent = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove'],
422
+ kevent = ['keydown', 'keyup', 'keypress']
423
+ if (name instanceof Event || name instanceof CustomEvent) {
424
+ // MouseEvent and KeyboardEvent are instances of Event, no need to explicitly add
425
+ event = name
426
+ } else if (mevent.includes(name)) {
427
+ event = new MouseEvent(name, options)
428
+ } else if (kevent.includes(name)) {
429
+ event = new KeyboardEvent(name, options)
430
+ } else {
431
+ event = new Event(name, options)
432
+ }
433
+ this.each(node => { node.dispatchEvent(event) })
434
+ return this
435
+ }
436
+ attr(name, value) {
437
+ if (value === undefined && typeof name == 'string') {
438
+ return this[0] ? this[0].getAttribute(name) : undefined
439
+ } else {
440
+ let obj = {}
441
+ if (typeof name == 'object') obj = name; else obj[name] = value
442
+ this.each(node => {
443
+ Object.entries(obj).forEach(([nm, val]) => { node.setAttribute(nm, val) })
444
+ })
445
+ return this
446
+ }
447
+ }
448
+ removeAttr() {
449
+ this.each(node => {
450
+ Array.from(arguments).forEach(attr => {
451
+ node.removeAttribute(attr)
452
+ })
453
+ })
454
+ return this
455
+ }
456
+ prop(name, value) {
457
+ if (value === undefined && typeof name == 'string') {
458
+ return this[0] ? this[0][name] : undefined
459
+ } else {
460
+ let obj = {}
461
+ if (typeof name == 'object') obj = name; else obj[name] = value
462
+ this.each(node => {
463
+ Object.entries(obj).forEach(([nm, val]) => {
464
+ let prop = Query._fixProp(nm)
465
+ node[prop] = val
466
+ if (prop == 'innerHTML') {
467
+ Query._scriptConvert(node)
468
+ }
469
+ })
470
+ })
471
+ return this
472
+ }
473
+ }
474
+ removeProp() {
475
+ this.each(node => {
476
+ Array.from(arguments).forEach(prop => { delete node[Query._fixProp(prop)] })
477
+ })
478
+ return this
479
+ }
480
+ data(key, value) {
481
+ if (key instanceof Object) {
482
+ Object.entries(key).forEach(item => { this.data(item[0], item[1]) })
483
+ return
484
+ }
485
+ if (key && key.indexOf('-') != -1) {
486
+ console.error(`Key "${key}" contains "-" (dash). Dashes are not allowed in property names. Use camelCase instead.`)
487
+ }
488
+ if (arguments.length < 2) {
489
+ if (this[0]) {
490
+ let data = Object.assign({}, this[0].dataset)
491
+ Object.keys(data).forEach(key => {
492
+ if (data[key].startsWith('[') || data[key].startsWith('{')) {
493
+ try { data[key] = JSON.parse(data[key]) } catch (e) {}
494
+ }
495
+ })
496
+ return key ? data[key] : data
497
+ } else {
498
+ return undefined
499
+ }
500
+ } else {
501
+ this.each(node => {
502
+ if (value != null) {
503
+ node.dataset[key] = value instanceof Object ? JSON.stringify(value) : value
504
+ } else {
505
+ delete node.dataset[key]
506
+ }
507
+ })
508
+ return this
509
+ }
510
+ }
511
+ removeData(key) {
512
+ if (typeof key == 'string') key = key.split(/[,\s]+/)
513
+ this.each(node => {
514
+ key.forEach(k => { delete node.dataset[k] })
515
+ })
516
+ return this
517
+ }
518
+ show() {
519
+ return this.toggle(true)
520
+ }
521
+ hide() {
522
+ return this.toggle(false)
523
+ }
524
+ toggle(force) {
525
+ return this.each(node => {
526
+ let prev = node.style.display
527
+ let dsp = getComputedStyle(node).display
528
+ let isHidden = (prev == 'none' || dsp == 'none')
529
+ if (isHidden && (force == null || force === true)) { // show
530
+ let def = node instanceof HTMLTableRowElement
531
+ ? 'table-row'
532
+ : node instanceof HTMLTableCellElement
533
+ ? 'table-cell'
534
+ : 'block'
535
+ node.style.display = node._mQuery?.prevDisplay ?? (prev == dsp && dsp != 'none' ? '' : def)
536
+ this._save(node, 'prevDisplay', null)
537
+ }
538
+ if (!isHidden && (force == null || force === false)) { // hide
539
+ if (dsp != 'none') this._save(node, 'prevDisplay', dsp)
540
+ node.style.setProperty('display', 'none')
541
+ }
542
+ })
543
+ }
544
+ empty() {
545
+ return this.html('')
546
+ }
547
+ html(html) {
548
+ if (html instanceof HTMLElement) {
549
+ return this.empty().append(html)
550
+ } else {
551
+ return this.prop('innerHTML', html)
552
+ }
553
+ }
554
+ text(text) {
555
+ return this.prop('textContent', text)
556
+ }
557
+ val(value) {
558
+ return this.prop('value', value) // must be prop
559
+ }
560
+ change() {
561
+ return this.trigger('change')
562
+ }
563
+ click() {
564
+ return this.trigger('click')
565
+ }
566
+ }
567
+ // create a new object each time
568
+ let query = function (selector, context) {
569
+ // if a function, use as onload event
570
+ if (typeof selector == 'function') {
571
+ if (document.readyState == 'complete') {
572
+ selector()
573
+ } else {
574
+ window.addEventListener('load', selector)
575
+ }
576
+ } else {
577
+ return new Query(selector, context)
578
+ }
579
+ }
580
+ // str -> doc-fragment
581
+ query.html = (str) => { let frag = Query._fragment(str); return query(frag.children, frag) }
582
+ query.version = Query.version
583
+ export { query as $, query as default, query, Query }
@@ -0,0 +1,11 @@
1
+ ## JS Files
2
+
3
+ Final JS file - w2ui.js, w2ui.min.js - is compiled from a number of files in /src directory. You should not change the files in /dist directory directly, but do all changes in src directory and compile (concatenate and minify) them.
4
+
5
+ ## LESS files
6
+
7
+ Final CSS files are compiled from LESS counterparts. Do not change files in /dist directory. In less/src folder you will find all source files for all widgets, as well as mixing and variables. If you want to create a new theme, you can clone
8
+
9
+ - css/less/w2ui.less
10
+
11
+ and change colors, etc. All of the variables are conveniently included into this file. Once you are done, you can compile the final file with lessc compiler.