fwtoolkit 0.1.0-alpha.6 → 0.1.0-beta.1
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/css/alerts.css +7 -0
- package/css/dialog.css +62 -0
- package/css/overview_menu.css +7 -0
- package/dist/basic.d.ts +49 -36
- package/dist/basic.d.ts.map +1 -1
- package/dist/basic.js +58 -39
- package/dist/basic.js.map +1 -1
- package/dist/blob.d.ts +1 -1
- package/dist/blob.d.ts.map +1 -1
- package/dist/blob.js +0 -1
- package/dist/blob.js.map +1 -1
- package/dist/content_menu.d.ts +63 -20
- package/dist/content_menu.d.ts.map +1 -1
- package/dist/content_menu.js +23 -20
- package/dist/content_menu.js.map +1 -1
- package/dist/datatable_bulk.d.ts +34 -6
- package/dist/datatable_bulk.d.ts.map +1 -1
- package/dist/datatable_bulk.js +4 -5
- package/dist/datatable_bulk.js.map +1 -1
- package/dist/dialog.d.ts +82 -7
- package/dist/dialog.d.ts.map +1 -1
- package/dist/dialog.js +21 -16
- package/dist/dialog.js.map +1 -1
- package/dist/events.d.ts +1 -1
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +3 -3
- package/dist/events.js.map +1 -1
- package/dist/faq_dialog.d.ts +13 -4
- package/dist/faq_dialog.d.ts.map +1 -1
- package/dist/faq_dialog.js +4 -2
- package/dist/faq_dialog.js.map +1 -1
- package/dist/file/dialog.d.ts +33 -13
- package/dist/file/dialog.d.ts.map +1 -1
- package/dist/file/dialog.js +6 -8
- package/dist/file/dialog.js.map +1 -1
- package/dist/file/index.d.ts.map +1 -1
- package/dist/file/index.js +0 -1
- package/dist/file/index.js.map +1 -1
- package/dist/file/new_folder_dialog.d.ts +5 -2
- package/dist/file/new_folder_dialog.d.ts.map +1 -1
- package/dist/file/new_folder_dialog.js +1 -2
- package/dist/file/new_folder_dialog.js.map +1 -1
- package/dist/file/selector.d.ts +47 -14
- package/dist/file/selector.d.ts.map +1 -1
- package/dist/file/selector.js +11 -9
- package/dist/file/selector.js.map +1 -1
- package/dist/file/templates.d.ts +1 -1
- package/dist/file/templates.d.ts.map +1 -1
- package/dist/file/templates.js +0 -1
- package/dist/file/templates.js.map +1 -1
- package/dist/file/tools.d.ts +4 -4
- package/dist/file/tools.d.ts.map +1 -1
- package/dist/file/tools.js +4 -4
- package/dist/file/tools.js.map +1 -1
- package/dist/focus.d.ts +1 -1
- package/dist/focus.d.ts.map +1 -1
- package/dist/focus.js +5 -5
- package/dist/focus.js.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -3
- package/dist/index.js.map +1 -1
- package/dist/network.d.ts +19 -7
- package/dist/network.d.ts.map +1 -1
- package/dist/network.js +15 -12
- package/dist/network.js.map +1 -1
- package/dist/overview_menu.d.ts +77 -18
- package/dist/overview_menu.d.ts.map +1 -1
- package/dist/overview_menu.js +54 -35
- package/dist/overview_menu.js.map +1 -1
- package/dist/settings.d.ts +7 -2
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +0 -1
- package/dist/settings.js.map +1 -1
- package/dist/user.d.ts +8 -2
- package/dist/user.d.ts.map +1 -1
- package/dist/user.js +1 -2
- package/dist/user.js.map +1 -1
- package/dist/worker.d.ts +1 -1
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +1 -2
- package/dist/worker.js.map +1 -1
- package/dist/ws.d.ts +59 -25
- package/dist/ws.d.ts.map +1 -1
- package/dist/ws.js +19 -15
- package/dist/ws.js.map +1 -1
- package/package.json +2 -1
- package/src/basic.ts +136 -69
- package/src/blob.ts +1 -2
- package/src/content_menu.ts +127 -44
- package/src/datatable_bulk.ts +72 -35
- package/src/dialog.ts +156 -61
- package/src/diff-dom.d.ts +16 -0
- package/src/events.ts +3 -3
- package/src/faq_dialog.ts +25 -11
- package/src/file/dialog.ts +48 -14
- package/src/file/index.ts +0 -1
- package/src/file/new_folder_dialog.ts +7 -5
- package/src/file/selector.ts +86 -36
- package/src/file/templates.ts +2 -3
- package/src/file/tools.ts +17 -8
- package/src/focus.ts +11 -13
- package/src/global.d.ts +11 -4
- package/src/index.ts +0 -3
- package/src/network.ts +58 -20
- package/src/overview_menu.ts +183 -109
- package/src/settings.ts +9 -4
- package/src/user.ts +10 -5
- package/src/w3c-keyname.d.ts +3 -0
- package/src/worker.ts +1 -2
- package/src/ws.ts +115 -50
- package/css/ui_dialogs.css +0 -144
- package/dist/templates.d.ts +0 -7
- package/dist/templates.d.ts.map +0 -1
- package/dist/templates.js +0 -43
- package/dist/templates.js.map +0 -1
- package/dist/user_util.d.ts +0 -7
- package/dist/user_util.d.ts.map +0 -1
- package/dist/user_util.js +0 -19
- package/dist/user_util.js.map +0 -1
- package/src/templates.ts +0 -43
- package/src/user_util.ts +0 -17
package/src/content_menu.ts
CHANGED
|
@@ -1,4 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
export type ContentMenuItemTitle = string | ((page: unknown) => string)
|
|
2
|
+
|
|
3
|
+
export interface ContentMenuBaseItem {
|
|
4
|
+
type?: "header" | "separator" | "action"
|
|
5
|
+
title?: ContentMenuItemTitle
|
|
6
|
+
tooltip?: string
|
|
7
|
+
action?: (page: unknown) => void
|
|
8
|
+
disabled?: (page: unknown) => boolean
|
|
9
|
+
selected?: boolean
|
|
10
|
+
order?: number
|
|
11
|
+
icon?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface ContentMenuHeaderItem extends ContentMenuBaseItem {
|
|
15
|
+
type: "header"
|
|
16
|
+
title: ContentMenuItemTitle
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ContentMenuSeparatorItem extends ContentMenuBaseItem {
|
|
20
|
+
type: "separator"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ContentMenuActionItem extends ContentMenuBaseItem {
|
|
24
|
+
type?: "action"
|
|
25
|
+
title: ContentMenuItemTitle
|
|
26
|
+
action: (page: unknown) => void
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type ContentMenuItem =
|
|
30
|
+
| ContentMenuHeaderItem
|
|
31
|
+
| ContentMenuSeparatorItem
|
|
32
|
+
| ContentMenuActionItem
|
|
33
|
+
|
|
34
|
+
export interface ContentMenuInit {
|
|
35
|
+
content: ContentMenuItem[]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ContentMenuPosition {
|
|
39
|
+
X: number
|
|
40
|
+
Y: number
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface ContentMenuOptions {
|
|
44
|
+
id?: string | false
|
|
45
|
+
page?: unknown | false
|
|
46
|
+
classes?: string | false
|
|
47
|
+
menu?: ContentMenuInit
|
|
48
|
+
height?: number | false
|
|
49
|
+
width?: number | false
|
|
50
|
+
onClose?: (() => void) | false
|
|
51
|
+
scroll?: boolean | false
|
|
52
|
+
dialogEl?: HTMLElement | false
|
|
53
|
+
backdropEl?: HTMLElement | false
|
|
54
|
+
menuPos?: ContentMenuPosition | false
|
|
55
|
+
}
|
|
56
|
+
|
|
2
57
|
const menuTemplate = ({
|
|
3
58
|
id,
|
|
4
59
|
classes,
|
|
@@ -8,6 +63,15 @@ const menuTemplate = ({
|
|
|
8
63
|
menu,
|
|
9
64
|
scroll,
|
|
10
65
|
page
|
|
66
|
+
}: {
|
|
67
|
+
id: string | false
|
|
68
|
+
classes: string | false
|
|
69
|
+
height: string
|
|
70
|
+
width: string
|
|
71
|
+
zIndex: number
|
|
72
|
+
menu: ContentMenuInit
|
|
73
|
+
scroll: boolean | false
|
|
74
|
+
page: unknown | false
|
|
11
75
|
}) =>
|
|
12
76
|
`<div tabindex="-1" role="incontent_menu"
|
|
13
77
|
class="ui-content-menu ui-corner-all ui-widget ui-widget-content ui-front"
|
|
@@ -19,7 +83,7 @@ const menuTemplate = ({
|
|
|
19
83
|
.map((menuItem, index) => {
|
|
20
84
|
switch (menuItem.type) {
|
|
21
85
|
case "header":
|
|
22
|
-
return `<li><span class="content-menu-item-header" title="${menuItem.tooltip}">${
|
|
86
|
+
return `<li><span class="content-menu-item-header" title="${menuItem.tooltip || ""}">${
|
|
23
87
|
typeof menuItem.title === "function"
|
|
24
88
|
? menuItem.title(page)
|
|
25
89
|
: menuItem.title
|
|
@@ -33,7 +97,7 @@ const menuTemplate = ({
|
|
|
33
97
|
: menuItem.selected
|
|
34
98
|
? " selected"
|
|
35
99
|
: ""
|
|
36
|
-
}" title='${menuItem.tooltip}'>
|
|
100
|
+
}" title='${menuItem.tooltip || ""}'>
|
|
37
101
|
${
|
|
38
102
|
typeof menuItem.title === "function"
|
|
39
103
|
? menuItem.title(page)
|
|
@@ -54,6 +118,21 @@ const menuTemplate = ({
|
|
|
54
118
|
<div class="ui-widget-overlay ui-front" style="z-index: ${zIndex - 1}"></div>`
|
|
55
119
|
|
|
56
120
|
export class ContentMenu {
|
|
121
|
+
id: string | false
|
|
122
|
+
page: unknown | false
|
|
123
|
+
classes: string | false
|
|
124
|
+
menu: ContentMenuInit
|
|
125
|
+
height: string
|
|
126
|
+
width: string
|
|
127
|
+
onClose: (() => void) | false
|
|
128
|
+
scroll: boolean | false
|
|
129
|
+
dialogEl!: HTMLElement
|
|
130
|
+
backdropEl!: HTMLElement
|
|
131
|
+
menuPos: ContentMenuPosition | false
|
|
132
|
+
|
|
133
|
+
focusedIndex: number
|
|
134
|
+
previouslyFocusedElement: Element | null
|
|
135
|
+
|
|
57
136
|
constructor({
|
|
58
137
|
id = false,
|
|
59
138
|
page = false,
|
|
@@ -66,7 +145,7 @@ export class ContentMenu {
|
|
|
66
145
|
dialogEl = false,
|
|
67
146
|
backdropEl = false,
|
|
68
147
|
menuPos = false
|
|
69
|
-
}) {
|
|
148
|
+
}: ContentMenuOptions = {}) {
|
|
70
149
|
this.id = id
|
|
71
150
|
this.page = page
|
|
72
151
|
this.classes = classes
|
|
@@ -75,15 +154,15 @@ export class ContentMenu {
|
|
|
75
154
|
this.width = width ? `${width}px` : "auto"
|
|
76
155
|
this.onClose = onClose
|
|
77
156
|
this.scroll = scroll
|
|
78
|
-
this.dialogEl = dialogEl
|
|
79
|
-
this.backdropEl = backdropEl
|
|
157
|
+
this.dialogEl = (dialogEl || null) as HTMLElement
|
|
158
|
+
this.backdropEl = (backdropEl || null) as HTMLElement
|
|
80
159
|
this.menuPos = menuPos
|
|
81
160
|
|
|
82
161
|
this.focusedIndex = 0
|
|
83
162
|
this.previouslyFocusedElement = null
|
|
84
163
|
}
|
|
85
164
|
|
|
86
|
-
open() {
|
|
165
|
+
open(): void {
|
|
87
166
|
if (this.dialogEl) {
|
|
88
167
|
return
|
|
89
168
|
}
|
|
@@ -103,9 +182,10 @@ export class ContentMenu {
|
|
|
103
182
|
page: this.page
|
|
104
183
|
})
|
|
105
184
|
)
|
|
106
|
-
this.backdropEl = document.body.lastElementChild
|
|
107
|
-
this.dialogEl = this.backdropEl
|
|
108
|
-
|
|
185
|
+
this.backdropEl = document.body.lastElementChild as HTMLElement
|
|
186
|
+
this.dialogEl = this.backdropEl
|
|
187
|
+
.previousElementSibling as HTMLElement
|
|
188
|
+
if (this.menuPos && this.menuPos.X && this.menuPos.Y) {
|
|
109
189
|
this.positionDialog()
|
|
110
190
|
} else {
|
|
111
191
|
this.centerDialog()
|
|
@@ -115,7 +195,7 @@ export class ContentMenu {
|
|
|
115
195
|
this.focusFirstMenuItem()
|
|
116
196
|
}
|
|
117
197
|
|
|
118
|
-
renderColumnsHtml(columns) {
|
|
198
|
+
renderColumnsHtml(columns: number): string {
|
|
119
199
|
const itemsPerColumn = Math.ceil(this.menu.content.length / columns)
|
|
120
200
|
let html = '<div class="content-menu-columns">'
|
|
121
201
|
for (let col = 0; col < columns; col++) {
|
|
@@ -132,7 +212,7 @@ export class ContentMenu {
|
|
|
132
212
|
const menuItem = this.menu.content[i]
|
|
133
213
|
switch (menuItem.type) {
|
|
134
214
|
case "header":
|
|
135
|
-
html += `<li><span class="content-menu-item-header" title="${menuItem.tooltip}">${
|
|
215
|
+
html += `<li><span class="content-menu-item-header" title="${menuItem.tooltip || ""}">${
|
|
136
216
|
typeof menuItem.title === "function"
|
|
137
217
|
? menuItem.title(this.page)
|
|
138
218
|
: menuItem.title
|
|
@@ -149,7 +229,7 @@ export class ContentMenu {
|
|
|
149
229
|
: menuItem.selected
|
|
150
230
|
? " selected"
|
|
151
231
|
: ""
|
|
152
|
-
}" title='${menuItem.tooltip}'>
|
|
232
|
+
}" title='${menuItem.tooltip || ""}'>
|
|
153
233
|
${
|
|
154
234
|
typeof menuItem.title === "function"
|
|
155
235
|
? menuItem.title(this.page)
|
|
@@ -168,7 +248,7 @@ export class ContentMenu {
|
|
|
168
248
|
return html
|
|
169
249
|
}
|
|
170
250
|
|
|
171
|
-
checkAndAddColumns() {
|
|
251
|
+
checkAndAddColumns(): void {
|
|
172
252
|
const dialogRect = this.dialogEl.getBoundingClientRect()
|
|
173
253
|
const viewportHeight = window.innerHeight
|
|
174
254
|
const viewportWidth = window.innerWidth
|
|
@@ -178,8 +258,8 @@ export class ContentMenu {
|
|
|
178
258
|
if (dialogRect.height >= maxHeight) {
|
|
179
259
|
const contentEl = this.dialogEl.querySelector(
|
|
180
260
|
".ui-content-menu-content"
|
|
181
|
-
)
|
|
182
|
-
const contentDiv = contentEl.querySelector(":scope > div")
|
|
261
|
+
) as HTMLElement
|
|
262
|
+
const contentDiv = contentEl.querySelector(":scope > div") as HTMLElement
|
|
183
263
|
let columns = 2
|
|
184
264
|
while (columns <= 6) {
|
|
185
265
|
contentDiv.innerHTML = this.renderColumnsHtml(columns)
|
|
@@ -192,7 +272,7 @@ export class ContentMenu {
|
|
|
192
272
|
}
|
|
193
273
|
const newRect = this.dialogEl.getBoundingClientRect()
|
|
194
274
|
if (newRect.height < maxHeight && newRect.width < maxWidth) {
|
|
195
|
-
if (this.menuPos
|
|
275
|
+
if (this.menuPos && this.menuPos.X && this.menuPos.Y) {
|
|
196
276
|
this.positionDialog()
|
|
197
277
|
} else {
|
|
198
278
|
this.centerDialog()
|
|
@@ -205,9 +285,9 @@ export class ContentMenu {
|
|
|
205
285
|
contentDiv.innerHTML = `<ul class="content-menu-list">${this.renderSingleColumnHtml()}</ul>`
|
|
206
286
|
contentEl.style.width = this.width
|
|
207
287
|
this.dialogEl
|
|
208
|
-
.querySelector(".ui-content-menu-content")
|
|
288
|
+
.querySelector(".ui-content-menu-content")!
|
|
209
289
|
.classList.add("ui-scrollable")
|
|
210
|
-
if (this.menuPos
|
|
290
|
+
if (this.menuPos && this.menuPos.X && this.menuPos.Y) {
|
|
211
291
|
this.positionDialog()
|
|
212
292
|
} else {
|
|
213
293
|
this.centerDialog()
|
|
@@ -215,12 +295,12 @@ export class ContentMenu {
|
|
|
215
295
|
}
|
|
216
296
|
}
|
|
217
297
|
|
|
218
|
-
renderSingleColumnHtml() {
|
|
298
|
+
renderSingleColumnHtml(): string {
|
|
219
299
|
return this.menu.content
|
|
220
300
|
.map((menuItem, index) => {
|
|
221
301
|
switch (menuItem.type) {
|
|
222
302
|
case "header":
|
|
223
|
-
return `<li><span class="content-menu-item-header" title="${menuItem.tooltip}">${
|
|
303
|
+
return `<li><span class="content-menu-item-header" title="${menuItem.tooltip || ""}">${
|
|
224
304
|
typeof menuItem.title === "function"
|
|
225
305
|
? menuItem.title(this.page)
|
|
226
306
|
: menuItem.title
|
|
@@ -234,7 +314,7 @@ export class ContentMenu {
|
|
|
234
314
|
: menuItem.selected
|
|
235
315
|
? " selected"
|
|
236
316
|
: ""
|
|
237
|
-
}" title='${menuItem.tooltip}'>
|
|
317
|
+
}" title='${menuItem.tooltip || ""}'>
|
|
238
318
|
${
|
|
239
319
|
typeof menuItem.title === "function"
|
|
240
320
|
? menuItem.title(this.page)
|
|
@@ -250,7 +330,7 @@ export class ContentMenu {
|
|
|
250
330
|
.join("")
|
|
251
331
|
}
|
|
252
332
|
|
|
253
|
-
centerDialog() {
|
|
333
|
+
centerDialog(): void {
|
|
254
334
|
const totalWidth = window.innerWidth,
|
|
255
335
|
totalHeight = window.innerHeight,
|
|
256
336
|
dialogRect = this.dialogEl.getBoundingClientRect(),
|
|
@@ -262,7 +342,7 @@ export class ContentMenu {
|
|
|
262
342
|
this.dialogEl.style.left = `${(totalWidth - dialogWidth) / 2 + scrollLeftOffset}px`
|
|
263
343
|
}
|
|
264
344
|
|
|
265
|
-
positionDialog() {
|
|
345
|
+
positionDialog(): void {
|
|
266
346
|
const dialogHeight = this.dialogEl.getBoundingClientRect().height + 10,
|
|
267
347
|
dialogWidth = this.dialogEl.getBoundingClientRect().width + 10,
|
|
268
348
|
scrollTopOffset = window.pageYOffset,
|
|
@@ -271,8 +351,8 @@ export class ContentMenu {
|
|
|
271
351
|
|
|
272
352
|
// We try to ensure that the menu is seen in the browser at the preferred location.
|
|
273
353
|
// Adjustments are made in case it doesn't fit.
|
|
274
|
-
let top = this.menuPos.Y,
|
|
275
|
-
left = this.menuPos.X
|
|
354
|
+
let top = this.menuPos ? this.menuPos.Y : 0,
|
|
355
|
+
left = this.menuPos ? this.menuPos.X : 0
|
|
276
356
|
|
|
277
357
|
if (top + dialogHeight > scrollTopOffset + clientHeight) {
|
|
278
358
|
top -= top + dialogHeight - (scrollTopOffset + clientHeight)
|
|
@@ -290,7 +370,7 @@ export class ContentMenu {
|
|
|
290
370
|
this.dialogEl.style.left = `${left}px`
|
|
291
371
|
}
|
|
292
372
|
|
|
293
|
-
bind() {
|
|
373
|
+
bind(): void {
|
|
294
374
|
this.backdropEl.addEventListener("click", () => this.close())
|
|
295
375
|
this.dialogEl.addEventListener("click", event => this.onclick(event))
|
|
296
376
|
this.dialogEl.addEventListener("keydown", event =>
|
|
@@ -299,34 +379,34 @@ export class ContentMenu {
|
|
|
299
379
|
this.dialogEl.focus()
|
|
300
380
|
}
|
|
301
381
|
|
|
302
|
-
getHighestDialogZIndex() {
|
|
382
|
+
getHighestDialogZIndex(): number {
|
|
303
383
|
let zIndex = 100
|
|
304
384
|
document
|
|
305
385
|
.querySelectorAll("div.ui-content-menu")
|
|
306
386
|
.forEach(
|
|
307
|
-
dialogEl => (zIndex = Math.max(zIndex, dialogEl.style.zIndex))
|
|
387
|
+
dialogEl => (zIndex = Math.max(zIndex, parseInt((dialogEl as HTMLElement).style.zIndex) || 100))
|
|
308
388
|
)
|
|
309
389
|
document
|
|
310
390
|
.querySelectorAll("div.ui-dialog")
|
|
311
391
|
.forEach(
|
|
312
|
-
dialogEl => (zIndex = Math.max(zIndex, dialogEl.style.zIndex))
|
|
392
|
+
dialogEl => (zIndex = Math.max(zIndex, parseInt((dialogEl as HTMLElement).style.zIndex) || 100))
|
|
313
393
|
)
|
|
314
394
|
return zIndex
|
|
315
395
|
}
|
|
316
396
|
|
|
317
|
-
close() {
|
|
397
|
+
close(): void {
|
|
318
398
|
if (!this.dialogEl || !this.dialogEl.parentElement) {
|
|
319
399
|
return
|
|
320
400
|
}
|
|
321
401
|
this.dialogEl.parentElement.removeChild(this.dialogEl)
|
|
322
|
-
this.backdropEl.parentElement
|
|
402
|
+
this.backdropEl.parentElement!.removeChild(this.backdropEl)
|
|
323
403
|
|
|
324
404
|
// Restore focus to the previously focused element
|
|
325
405
|
if (
|
|
326
406
|
this.previouslyFocusedElement &&
|
|
327
|
-
this.previouslyFocusedElement.focus
|
|
407
|
+
(this.previouslyFocusedElement as HTMLElement).focus
|
|
328
408
|
) {
|
|
329
|
-
this.previouslyFocusedElement.focus()
|
|
409
|
+
(this.previouslyFocusedElement as HTMLElement).focus()
|
|
330
410
|
}
|
|
331
411
|
|
|
332
412
|
if (this.onClose) {
|
|
@@ -334,13 +414,16 @@ export class ContentMenu {
|
|
|
334
414
|
}
|
|
335
415
|
}
|
|
336
416
|
|
|
337
|
-
onclick(event) {
|
|
417
|
+
onclick(event: MouseEvent): void {
|
|
338
418
|
event.preventDefault()
|
|
339
419
|
event.stopImmediatePropagation()
|
|
340
|
-
const target = event.target.closest("li.content-menu-item")
|
|
420
|
+
const target = (event.target as Element).closest("li.content-menu-item") as HTMLElement
|
|
341
421
|
if (target) {
|
|
342
422
|
const menuNumber = target.dataset.index
|
|
343
|
-
|
|
423
|
+
if (menuNumber === undefined) {
|
|
424
|
+
return
|
|
425
|
+
}
|
|
426
|
+
const menuItem = this.menu.content[parseInt(menuNumber)] as ContentMenuActionItem
|
|
344
427
|
if (menuItem.disabled?.(this.page)) {
|
|
345
428
|
return
|
|
346
429
|
}
|
|
@@ -349,7 +432,7 @@ export class ContentMenu {
|
|
|
349
432
|
}
|
|
350
433
|
}
|
|
351
434
|
|
|
352
|
-
onKeyDown(event) {
|
|
435
|
+
onKeyDown(event: KeyboardEvent): void {
|
|
353
436
|
const {key} = event
|
|
354
437
|
const menuItems = this.dialogEl.querySelectorAll(
|
|
355
438
|
"li.content-menu-item:not(.disabled)"
|
|
@@ -381,10 +464,10 @@ export class ContentMenu {
|
|
|
381
464
|
this.focusMenuItem(this.focusedIndex)
|
|
382
465
|
break
|
|
383
466
|
case "ArrowLeft":
|
|
467
|
+
event.preventDefault()
|
|
384
468
|
if (totalColumns <= 1) {
|
|
385
469
|
break
|
|
386
470
|
}
|
|
387
|
-
event.preventDefault()
|
|
388
471
|
{
|
|
389
472
|
const currentCol = Math.floor(
|
|
390
473
|
this.focusedIndex / itemsPerColumn
|
|
@@ -406,10 +489,10 @@ export class ContentMenu {
|
|
|
406
489
|
}
|
|
407
490
|
break
|
|
408
491
|
case "ArrowRight":
|
|
492
|
+
event.preventDefault()
|
|
409
493
|
if (totalColumns <= 1) {
|
|
410
494
|
break
|
|
411
495
|
}
|
|
412
|
-
event.preventDefault()
|
|
413
496
|
{
|
|
414
497
|
const currentCol = Math.floor(
|
|
415
498
|
this.focusedIndex / itemsPerColumn
|
|
@@ -445,7 +528,7 @@ export class ContentMenu {
|
|
|
445
528
|
case "Enter":
|
|
446
529
|
case " ": {
|
|
447
530
|
event.preventDefault()
|
|
448
|
-
const menuItem = this.menu.content[this.focusedIndex]
|
|
531
|
+
const menuItem = this.menu.content[this.focusedIndex] as ContentMenuActionItem
|
|
449
532
|
if (!menuItem.disabled?.(this.page)) {
|
|
450
533
|
menuItem.action(this.page)
|
|
451
534
|
this.close()
|
|
@@ -455,7 +538,7 @@ export class ContentMenu {
|
|
|
455
538
|
}
|
|
456
539
|
}
|
|
457
540
|
|
|
458
|
-
focusFirstMenuItem() {
|
|
541
|
+
focusFirstMenuItem(): void {
|
|
459
542
|
const menuItems = this.dialogEl.querySelectorAll(
|
|
460
543
|
"li.content-menu-item:not(.disabled)"
|
|
461
544
|
)
|
|
@@ -465,12 +548,12 @@ export class ContentMenu {
|
|
|
465
548
|
}
|
|
466
549
|
}
|
|
467
550
|
|
|
468
|
-
focusMenuItem(index) {
|
|
551
|
+
focusMenuItem(index: number): void {
|
|
469
552
|
const menuItems = this.dialogEl.querySelectorAll(
|
|
470
553
|
"li.content-menu-item:not(.disabled)"
|
|
471
554
|
)
|
|
472
555
|
if (menuItems[index]) {
|
|
473
|
-
menuItems[index].focus()
|
|
556
|
+
(menuItems[index] as HTMLElement).focus()
|
|
474
557
|
}
|
|
475
558
|
}
|
|
476
559
|
}
|
package/src/datatable_bulk.ts
CHANGED
|
@@ -1,13 +1,50 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
1
|
import {keyName} from "w3c-keyname"
|
|
3
2
|
|
|
4
3
|
import {whenReady} from "./basic.js"
|
|
5
|
-
import {ContentMenu} from "./content_menu.js"
|
|
4
|
+
import {ContentMenu, ContentMenuInit} from "./content_menu.js"
|
|
5
|
+
|
|
6
|
+
export interface DataTableCell {
|
|
7
|
+
data: unknown
|
|
8
|
+
text: string
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface DataTableRow {
|
|
12
|
+
cells: DataTableCell[]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DataTableData {
|
|
16
|
+
data: DataTableRow[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface DataTable {
|
|
20
|
+
dom: HTMLElement
|
|
21
|
+
data: DataTableData
|
|
22
|
+
update: () => void
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface DatatableBulkPage {
|
|
26
|
+
dom: HTMLElement
|
|
27
|
+
getSelected: () => unknown[]
|
|
28
|
+
}
|
|
6
29
|
|
|
7
30
|
let bulkId = 0
|
|
8
31
|
|
|
9
32
|
export class DatatableBulk {
|
|
10
|
-
|
|
33
|
+
page: DatatableBulkPage
|
|
34
|
+
model: ContentMenuInit
|
|
35
|
+
checkboxColumn: number
|
|
36
|
+
|
|
37
|
+
id: string
|
|
38
|
+
table: DataTable | undefined
|
|
39
|
+
boundOnClick: ((event: MouseEvent) => void) | undefined
|
|
40
|
+
boundOnTableCheckChange: ((event: Event) => void) | undefined
|
|
41
|
+
boundOnKeyDown: ((event: KeyboardEvent) => void) | undefined
|
|
42
|
+
|
|
43
|
+
constructor(
|
|
44
|
+
page: DatatableBulkPage,
|
|
45
|
+
model: ContentMenuInit,
|
|
46
|
+
checkboxColumn: number
|
|
47
|
+
) {
|
|
11
48
|
this.page = page
|
|
12
49
|
this.model = model
|
|
13
50
|
this.checkboxColumn = checkboxColumn
|
|
@@ -15,31 +52,31 @@ export class DatatableBulk {
|
|
|
15
52
|
this.id = `dt-bulk-${++bulkId}`
|
|
16
53
|
}
|
|
17
54
|
|
|
18
|
-
init(table) {
|
|
55
|
+
init(table: DataTable): void {
|
|
19
56
|
this.table = table
|
|
20
57
|
whenReady().then(() => this.bindEvents())
|
|
21
58
|
}
|
|
22
59
|
|
|
23
|
-
update() {
|
|
60
|
+
update(): void {
|
|
24
61
|
this.model.content = this.model.content.sort(
|
|
25
|
-
(a, b) => a.order - b.order
|
|
62
|
+
(a, b) => (a.order || 0) - (b.order || 0)
|
|
26
63
|
)
|
|
27
64
|
}
|
|
28
65
|
|
|
29
|
-
bindEvents() {
|
|
66
|
+
bindEvents(): void {
|
|
30
67
|
// Store the bound functions as instance variables so we can remove them later
|
|
31
68
|
this.boundOnClick = this.onClick.bind(this)
|
|
32
69
|
this.boundOnTableCheckChange = this.onTableCheckChange.bind(this)
|
|
33
70
|
this.boundOnKeyDown = this.onKeyDown.bind(this)
|
|
34
71
|
|
|
35
72
|
this.page.dom.addEventListener("click", this.boundOnClick)
|
|
36
|
-
this.table
|
|
37
|
-
this.table
|
|
73
|
+
this.table!.dom.addEventListener("change", this.boundOnTableCheckChange)
|
|
74
|
+
this.table!.dom.addEventListener("keydown", this.boundOnKeyDown)
|
|
38
75
|
this.onTableCheckChange()
|
|
39
76
|
}
|
|
40
77
|
|
|
41
78
|
// The new destroy() method removes all event listeners that were added and cleans up DOM elements.
|
|
42
|
-
destroy() {
|
|
79
|
+
destroy(): void {
|
|
43
80
|
if (this.page && this.page.dom && this.boundOnClick) {
|
|
44
81
|
this.page.dom.removeEventListener("click", this.boundOnClick)
|
|
45
82
|
}
|
|
@@ -65,12 +102,12 @@ export class DatatableBulk {
|
|
|
65
102
|
}
|
|
66
103
|
|
|
67
104
|
// Clear any references to help garbage collection
|
|
68
|
-
this.page = null
|
|
69
|
-
this.table =
|
|
70
|
-
this.model =
|
|
105
|
+
this.page = null as unknown as DatatableBulkPage
|
|
106
|
+
this.table = undefined
|
|
107
|
+
this.model = {content: []}
|
|
71
108
|
}
|
|
72
109
|
|
|
73
|
-
onKeyDown(event) {
|
|
110
|
+
onKeyDown(event: KeyboardEvent): void {
|
|
74
111
|
const key = keyName(event)
|
|
75
112
|
const el = this.page.dom.querySelector(`#${this.id}`)
|
|
76
113
|
|
|
@@ -89,8 +126,8 @@ export class DatatableBulk {
|
|
|
89
126
|
width: 280,
|
|
90
127
|
page: this.page,
|
|
91
128
|
menuPos: {
|
|
92
|
-
X: Number.parseInt(el.getBoundingClientRect().left),
|
|
93
|
-
Y: Number.parseInt(el.getBoundingClientRect().bottom)
|
|
129
|
+
X: Number.parseInt(el.getBoundingClientRect().left as unknown as string),
|
|
130
|
+
Y: Number.parseInt(el.getBoundingClientRect().bottom as unknown as string)
|
|
94
131
|
}
|
|
95
132
|
})
|
|
96
133
|
contentMenu.open()
|
|
@@ -115,7 +152,7 @@ export class DatatableBulk {
|
|
|
115
152
|
}
|
|
116
153
|
}
|
|
117
154
|
|
|
118
|
-
toggleSelectAll(checked) {
|
|
155
|
+
toggleSelectAll(checked: boolean): void {
|
|
119
156
|
// Update the DataTable instance
|
|
120
157
|
if (this.table) {
|
|
121
158
|
this.table.data.data.forEach(row => {
|
|
@@ -130,26 +167,26 @@ export class DatatableBulk {
|
|
|
130
167
|
this.onTableCheckChange()
|
|
131
168
|
}
|
|
132
169
|
|
|
133
|
-
onTableCheckChange() {
|
|
170
|
+
onTableCheckChange(): void {
|
|
134
171
|
const el = this.page.dom.querySelector(`#${this.id}`)
|
|
135
172
|
if (!el) {
|
|
136
173
|
return
|
|
137
174
|
}
|
|
138
175
|
|
|
139
176
|
const allChecked = this.isAllChecked()
|
|
140
|
-
el.querySelector("input[type=checkbox]").checked = allChecked
|
|
177
|
+
;(el.querySelector("input[type=checkbox]") as HTMLInputElement).checked = allChecked
|
|
141
178
|
}
|
|
142
179
|
|
|
143
|
-
isAllChecked() {
|
|
180
|
+
isAllChecked(): boolean {
|
|
144
181
|
const checkboxes = Array.from(
|
|
145
|
-
this.table
|
|
182
|
+
this.table!.dom.querySelectorAll("input.entry-select[type=checkbox]")
|
|
146
183
|
)
|
|
147
|
-
const unchecked = checkboxes.filter(box => !box.checked)
|
|
148
|
-
return !unchecked.length && checkboxes.length
|
|
184
|
+
const unchecked = checkboxes.filter(box => !(box as HTMLInputElement).checked)
|
|
185
|
+
return !unchecked.length && checkboxes.length > 0
|
|
149
186
|
}
|
|
150
187
|
|
|
151
|
-
onClick(event) {
|
|
152
|
-
const target = event.target
|
|
188
|
+
onClick(event: MouseEvent): void {
|
|
189
|
+
const target = event.target as Element
|
|
153
190
|
if (target.matches(`#${this.id} *`)) {
|
|
154
191
|
event.preventDefault()
|
|
155
192
|
event.stopImmediatePropagation()
|
|
@@ -164,8 +201,8 @@ export class DatatableBulk {
|
|
|
164
201
|
width: 280,
|
|
165
202
|
page: this.page,
|
|
166
203
|
menuPos: {
|
|
167
|
-
X: Number.parseInt(event.pageX),
|
|
168
|
-
Y: Number.parseInt(event.pageY)
|
|
204
|
+
X: Number.parseInt(event.pageX as unknown as string),
|
|
205
|
+
Y: Number.parseInt(event.pageY as unknown as string)
|
|
169
206
|
}
|
|
170
207
|
})
|
|
171
208
|
contentMenu.open()
|
|
@@ -176,9 +213,9 @@ export class DatatableBulk {
|
|
|
176
213
|
// Click on bulk checkbox
|
|
177
214
|
const isChecked = this.isAllChecked()
|
|
178
215
|
this.toggleSelectAll(!isChecked)
|
|
179
|
-
target
|
|
180
|
-
.closest("div.datatable-wrapper")
|
|
181
|
-
.querySelector("input[type=checkbox]").checked = !isChecked
|
|
216
|
+
;(target
|
|
217
|
+
.closest("div.datatable-wrapper")!
|
|
218
|
+
.querySelector("input[type=checkbox]") as HTMLInputElement).checked = !isChecked
|
|
182
219
|
this.onTableCheckChange()
|
|
183
220
|
}
|
|
184
221
|
} else if (target.matches(".fw-data-table .entry-select + label")) {
|
|
@@ -186,18 +223,18 @@ export class DatatableBulk {
|
|
|
186
223
|
event.preventDefault()
|
|
187
224
|
event.stopImmediatePropagation()
|
|
188
225
|
event.stopPropagation()
|
|
189
|
-
const tr = target.closest("tr")
|
|
190
|
-
const index = parseInt(tr.dataset.index)
|
|
191
|
-
const row = this.table
|
|
226
|
+
const tr = target.closest("tr") as HTMLTableRowElement
|
|
227
|
+
const index = parseInt(tr.dataset.index!)
|
|
228
|
+
const row = this.table!.data.data[index]
|
|
192
229
|
const cell = row.cells[this.checkboxColumn]
|
|
193
230
|
cell.data = !cell.data
|
|
194
231
|
cell.text = String(cell.data)
|
|
195
|
-
this.table
|
|
232
|
+
this.table!.update()
|
|
196
233
|
this.onTableCheckChange()
|
|
197
234
|
}
|
|
198
235
|
}
|
|
199
236
|
|
|
200
|
-
getHTML() {
|
|
237
|
+
getHTML(): string {
|
|
201
238
|
return `<div id="${this.id}" class="dt-bulk" role="group" aria-label="Bulk actions">
|
|
202
239
|
<input type="checkbox" id="${this.id}_check" class="fw-check" aria-label="Select all">
|
|
203
240
|
<label for="${this.id}_check"></label>
|