OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-note commits / 89108cf

Add spreadsheet editor with Jspreadsheet CE + Yjs cell-level collaboration
- New note type: 'spreadsheet' alongside existing 'markdown' (backward compatible) - Jspreadsheet CE v5 vendor files for zero-CDN spreadsheet editing - Y.Map-based cell storage (row:col keys) for CRDT conflict resolution via Autobase - Type selector in editor toolbar, read-only spreadsheet view, note card type labels - Server-side: type field flows through create/update/list/search/recentNotes paths Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
89108cf214dfaf3fc83cbc6df09cd78e340a4ec6
by plankatron <fleeky@gmail.com> · 2026-03-18T18:27:11.000Z

Changed files (12) +30104 -41

lib/multiwriter/notebook-apply.js +1 -0
……@@ -38,6 +38,7 @@ export async function notebookApply (batch, view, base) {
3838 slug: op.slug || '',
3939 author: op.author,
4040 tags: op.tags || [],
41 type: op.noteType || 'markdown',
4142 createdAt: op.timestamp,
4243 updatedAt: op.timestamp
4344 })
lib/multiwriter/shared-notebook.js +74 -1
……@@ -82,7 +82,7 @@ export class SharedNotebook {
8282
8383 // ── Notes ──
8484
85 async createNote ({ title, slug, author, tags }) {
85 async createNote ({ title, slug, author, tags, type }) {
8686 const noteId = generateNoteId()
8787 await this._base.append(encodeOp({
8888 type: 'create-note',
……@@ -91,6 +91,7 @@ export class SharedNotebook {
9191 slug: slug || '',
9292 author: author || 'unknown',
9393 tags: tags || [],
94 noteType: type || 'markdown',
9495 timestamp: Date.now()
9596 }))
9697 await this._base.update()
……@@ -237,6 +238,78 @@ export class SharedNotebook {
237238 return this._docs.get(noteId) || null
238239 }
239240
241 // ── Spreadsheet (Y.Map-based) ──
242
243 /**
244 * Apply a spreadsheet update. Parses JSON content, builds a fresh Y.Doc
245 * with cell-level Y.Map entries, and stores the full state. This gives
246 * per-cell conflict resolution via Yjs CRDT semantics.
247 */
248 async applySpreadsheetUpdate (noteId, contentJson, author) {
249 let parsed
250 try {
251 parsed = JSON.parse(contentJson)
252 } catch {
253 parsed = { data: [[]] }
254 }
255
256 // Build a fresh doc with the new spreadsheet state
257 const doc = new Y.Doc()
258 const cells = doc.getMap('cells')
259 const meta = doc.getMap('meta')
260
261 doc.transact(() => {
262 const data = parsed.data || [[]]
263 for (let r = 0; r < data.length; r++) {
264 const row = data[r] || []
265 for (let c = 0; c < row.length; c++) {
266 const val = row[c] !== undefined && row[c] !== null ? String(row[c]) : ''
267 if (val) cells.set(r + ':' + c, val)
268 }
269 }
270
271 meta.set('rows', data.length)
272 meta.set('cols', data.length > 0 ? Math.max(...data.map(r => (r || []).length), 0) : 0)
273 if (parsed.columns) meta.set('columns', JSON.stringify(parsed.columns))
274 if (parsed.options) meta.set('options', JSON.stringify(parsed.options))
275 })
276
277 await this.applyYjsUpdate(noteId, Y.encodeStateAsUpdate(doc), author)
278 }
279
280 /**
281 * Get spreadsheet content as JSON string by reading the Y.Map cells.
282 */
283 async getSpreadsheetContent (noteId) {
284 const doc = await this.reconstructDoc(noteId)
285 const cells = doc.getMap('cells')
286 const meta = doc.getMap('meta')
287
288 const rows = meta.get('rows') || 0
289 const cols = meta.get('cols') || 0
290
291 const data = []
292 for (let r = 0; r < rows; r++) {
293 const row = []
294 for (let c = 0; c < cols; c++) {
295 row.push(cells.get(r + ':' + c) || '')
296 }
297 data.push(row)
298 }
299
300 const result = { data }
301 const columnsStr = meta.get('columns')
302 if (columnsStr) {
303 try { result.columns = JSON.parse(columnsStr) } catch {}
304 }
305 const optionsStr = meta.get('options')
306 if (optionsStr) {
307 try { result.options = JSON.parse(optionsStr) } catch {}
308 }
309
310 return JSON.stringify(result)
311 }
312
240313 // ── Media ──
241314
242315 async addMedia (noteId, { hash, mimeType, filename, size, blobId }, author) {
lib/note-manager.js +68 -24
……@@ -557,9 +557,11 @@ export class NoteManager {
557557
558558 // ==================== NOTE METHODS ====================
559559
560 async createNote (notebook, { title, content, tags } = {}) {
560 async createNote (notebook, { title, content, tags, type } = {}) {
561561 this.validateTitle(title)
562562
563 const noteType = (type === 'spreadsheet') ? 'spreadsheet' : 'markdown'
564
563565 // Generate slug from title
564566 const baseSlug = slugify(title) || 'untitled'
565567 const noteSlug = await this._ensureUniqueSlug(notebook, baseSlug, null)
……@@ -571,13 +573,18 @@ export class NoteManager {
571573 title,
572574 slug: noteSlug,
573575 author: 'user',
574 tags: Array.isArray(tags) ? tags : []
576 tags: Array.isArray(tags) ? tags : [],
577 type: noteType
575578 })
576579 if (content) {
577 const Y = (await import('yjs'))
578 const doc = new Y.Doc()
579 doc.getText('content').insert(0, content)
580 await snb.applyYjsUpdate(noteId, Y.encodeStateAsUpdate(doc), 'user')
580 if (noteType === 'spreadsheet') {
581 await snb.applySpreadsheetUpdate(noteId, content, 'user')
582 } else {
583 const Y = (await import('yjs'))
584 const doc = new Y.Doc()
585 doc.getText('content').insert(0, content)
586 await snb.applyYjsUpdate(noteId, Y.encodeStateAsUpdate(doc), 'user')
587 }
581588 }
582589 const result = {
583590 id: noteId,
……@@ -585,6 +592,7 @@ export class NoteManager {
585592 title,
586593 content: content || '',
587594 tags: Array.isArray(tags) ? tags : [],
595 type: noteType,
588596 createdAt: Date.now(),
589597 updatedAt: Date.now()
590598 }
……@@ -610,6 +618,7 @@ export class NoteManager {
610618 title,
611619 content: content || '',
612620 tags: Array.isArray(tags) ? tags : [],
621 type: noteType,
613622 createdAt: now,
614623 updatedAt: now
615624 }
……@@ -644,8 +653,13 @@ export class NoteManager {
644653 if (snb) {
645654 const note = await snb.getNote(noteId)
646655 if (!note) return null
647 const doc = await snb.reconstructDoc(noteId)
648 const content = doc.getText('content').toString()
656 let content
657 if (note.type === 'spreadsheet') {
658 content = await snb.getSpreadsheetContent(noteId)
659 } else {
660 const doc = await snb.reconstructDoc(noteId)
661 content = doc.getText('content').toString()
662 }
649663 const result = { ...note, id: note.noteId, content }
650664 if (!result.slug) {
651665 result.slug = slugify(result.title) || 'untitled-' + noteId.substring(0, 8)
……@@ -681,14 +695,20 @@ export class NoteManager {
681695 const enriched = []
682696 for (const note of notes) {
683697 try {
684 const doc = await snb.reconstructDoc(note.noteId)
685 const content = doc.getText('content').toString()
698 let content
699 if (note.type === 'spreadsheet') {
700 content = await snb.getSpreadsheetContent(note.noteId)
701 } else {
702 const doc = await snb.reconstructDoc(note.noteId)
703 content = doc.getText('content').toString()
704 }
686705 const n = {
687706 id: note.noteId,
688707 slug: note.slug || slugify(note.title) || 'untitled-' + note.noteId.substring(0, 8),
689708 title: note.title,
690709 content,
691710 tags: note.tags || [],
711 type: note.type || 'markdown',
692712 createdAt: note.createdAt,
693713 updatedAt: note.updatedAt
694714 }
……@@ -700,6 +720,7 @@ export class NoteManager {
700720 title: note.title,
701721 content: '',
702722 tags: note.tags || [],
723 type: note.type || 'markdown',
703724 createdAt: note.createdAt,
704725 updatedAt: note.updatedAt
705726 })
……@@ -791,21 +812,32 @@ export class NoteManager {
791812 await snb.updateNoteTitle(noteId, updates.title, 'user')
792813 }
793814 if (updates.content !== undefined) {
794 const Y = (await import('yjs'))
795 const doc = await snb.reconstructDoc(noteId)
796 const text = doc.getText('content')
797 doc.transact(() => {
798 text.delete(0, text.length)
799 text.insert(0, updates.content)
800 })
801 await snb.applyYjsUpdate(noteId, Y.encodeStateAsUpdate(doc), 'user')
815 // Check note type to determine storage strategy
816 const existingNote = await snb.getNote(noteId)
817 if (existingNote && existingNote.type === 'spreadsheet') {
818 await snb.applySpreadsheetUpdate(noteId, updates.content, 'user')
819 } else {
820 const Y = (await import('yjs'))
821 const doc = await snb.reconstructDoc(noteId)
822 const text = doc.getText('content')
823 doc.transact(() => {
824 text.delete(0, text.length)
825 text.insert(0, updates.content)
826 })
827 await snb.applyYjsUpdate(noteId, Y.encodeStateAsUpdate(doc), 'user')
828 }
802829 }
803830 const note = await snb.getNote(noteId)
804831 if (!note) {
805832 throw new NotFoundError("Note '" + noteId + "' not found", 'note')
806833 }
807 const doc = await snb.reconstructDoc(noteId)
808 const content = doc.getText('content').toString()
834 let content
835 if (note.type === 'spreadsheet') {
836 content = await snb.getSpreadsheetContent(noteId)
837 } else {
838 const doc = await snb.reconstructDoc(noteId)
839 content = doc.getText('content').toString()
840 }
809841 const result = { ...note, id: note.noteId, content }
810842 // Regenerate TOC if title changed
811843 if (titleChanged) this.regenerateToc(notebook).catch(() => {})
……@@ -1066,14 +1098,20 @@ export class NoteManager {
10661098 for (const note of notes) {
10671099 if (count >= perNotebookCap) break
10681100 try {
1069 const doc = await snb.reconstructDoc(note.noteId)
1070 const content = doc.getText('content').toString()
1101 let content
1102 if (note.type === 'spreadsheet') {
1103 content = await snb.getSpreadsheetContent(note.noteId)
1104 } else {
1105 const doc = await snb.reconstructDoc(note.noteId)
1106 content = doc.getText('content').toString()
1107 }
10711108 allNotes.push({
10721109 id: note.noteId,
10731110 slug: note.slug || slugify(note.title) || 'untitled-' + note.noteId.substring(0, 8),
10741111 title: note.title,
10751112 content,
10761113 tags: note.tags || [],
1114 type: note.type || 'markdown',
10771115 createdAt: note.createdAt,
10781116 updatedAt: note.updatedAt,
10791117 notebook: nb.slug,
……@@ -1111,6 +1149,7 @@ export class NoteManager {
11111149 title: note.title,
11121150 content: note.content,
11131151 tags: note.tags || [],
1152 type: note.type || 'markdown',
11141153 createdAt: note.createdAt,
11151154 updatedAt: note.updatedAt,
11161155 notebook: nb.slug,
……@@ -1151,8 +1190,13 @@ export class NoteManager {
11511190 for (const note of notes) {
11521191 if (results.length >= maxResults) break
11531192 try {
1154 const doc = await snb.reconstructDoc(note.noteId)
1155 const content = doc.getText('content').toString()
1193 let content
1194 if (note.type === 'spreadsheet') {
1195 content = await snb.getSpreadsheetContent(note.noteId)
1196 } else {
1197 const doc = await snb.reconstructDoc(note.noteId)
1198 content = doc.getText('content').toString()
1199 }
11561200 const titleMatch = note.title && note.title.toLowerCase().includes(q)
11571201 const contentMatch = content && content.toLowerCase().includes(q)
11581202 if (titleMatch || contentMatch) {
lib/routes/notebooks.js +2 -1
……@@ -249,7 +249,8 @@ export function registerNotebookRoutes (router, server) {
249249 const note = await nm.createNote(req.params.notebook, {
250250 title: body.title,
251251 content: body.content,
252 tags: body.tags
252 tags: body.tags,
253 type: body.type
253254 })
254255 json(res, note, 201)
255256 // Update site drive in background
package-lock.json +129 -2
……@@ -1,12 +1,12 @@
11{
22 "name": "hypernote",
3 "version": "0.2.0",
3 "version": "0.3.0",
44 "lockfileVersion": 3,
55 "requires": true,
66 "packages": {
77 "": {
88 "name": "hypernote",
9 "version": "0.2.0",
9 "version": "0.3.0",
1010 "hasInstallScript": true,
1111 "dependencies": {
1212 "@noble/ed25519": "^2.0.0",
……@@ -29,6 +29,8 @@
2929 "hypercore-crypto": "^3.0.0",
3030 "hyperdrive": "^11.13.4",
3131 "hyperswarm": "^4.7.0",
32 "jspreadsheet-ce": "^5.0.4",
33 "jsuites": "^6.3.1",
3234 "keet-identity-key": "github:holepunchto/keet-identity-key",
3335 "pear-runtime": "^0.5.0",
3436 "secure-prompt": "github:holepunchto/secure-prompt",
……@@ -102,6 +104,95 @@
102104 "@jridgewell/sourcemap-codec": "^1.4.14"
103105 }
104106 },
107 "node_modules/@jspreadsheet/formula": {
108 "version": "2.0.2",
109 "resolved": "https://registry.npmjs.org/@jspreadsheet/formula/-/formula-2.0.2.tgz",
110 "integrity": "sha512-PDQYf9REQA53I7tVYkvkeyQxrd5jcjUeHgItYnRpjN2QiIQwawSqBDtGGEVQTSboTG+JwgGCuhvOpj7FxeKwew=="
111 },
112 "node_modules/@jsuites/utils": {
113 "version": "6.0.4",
114 "resolved": "https://registry.npmjs.org/@jsuites/utils/-/utils-6.0.4.tgz",
115 "integrity": "sha512-7iPXMP9/7LpdBbcK6QTEsMBVesJ9CK65R6Wl56qrcTWhsWke8F9jsznT+IbPmMxS8s3QFnFqSeH6+NmBoJZYjg=="
116 },
117 "node_modules/@lemonadejs/calendar": {
118 "version": "5.8.4",
119 "resolved": "https://registry.npmjs.org/@lemonadejs/calendar/-/calendar-5.8.4.tgz",
120 "integrity": "sha512-IVRsE8nu+oCANRhwai7NH2K5QlAMF/uCw39LtF9gFkE6VvEdqgYJES6oz1UsAnKfU07PV4SxhvcjFSHmPY897A==",
121 "dependencies": {
122 "@jsuites/utils": "^6.0.3",
123 "@lemonadejs/modal": "^5.8.0",
124 "lemonadejs": "^5.3.6"
125 }
126 },
127 "node_modules/@lemonadejs/color": {
128 "version": "5.8.0",
129 "resolved": "https://registry.npmjs.org/@lemonadejs/color/-/color-5.8.0.tgz",
130 "integrity": "sha512-ep9yJAgRvRPrrx56p/3hGVctqcXgc5F3wJtefjvwKJv/CVMY19clZ3+vRoZm7Ndth6kN8h+Q6Pu5EkHkl/WLZQ==",
131 "dependencies": {
132 "@lemonadejs/modal": "^5.8.0",
133 "@lemonadejs/tabs": "^5.8.0",
134 "lemonadejs": "^5.3.2"
135 }
136 },
137 "node_modules/@lemonadejs/contextmenu": {
138 "version": "5.8.3",
139 "resolved": "https://registry.npmjs.org/@lemonadejs/contextmenu/-/contextmenu-5.8.3.tgz",
140 "integrity": "sha512-AQtgGLEoBGKjaqS2tc936DqT6/lHsgCzkUm/fRccF9szraPqL5cYG43MgHY7Icfu2j2KsGLK8nIgg+issCMg+w==",
141 "dependencies": {
142 "@lemonadejs/modal": "^5.8.2",
143 "lemonadejs": "^5.3.6"
144 }
145 },
146 "node_modules/@lemonadejs/dropdown": {
147 "version": "5.8.2",
148 "resolved": "https://registry.npmjs.org/@lemonadejs/dropdown/-/dropdown-5.8.2.tgz",
149 "integrity": "sha512-QzbHCiF6G4juuIbo3EonYQU/bBcZPTeutyFZHZI3ppS18HVyf3TR3XXKBFRdJT61hilUJ+bX4vWWEgidpzY/Pg==",
150 "dependencies": {
151 "@lemonadejs/modal": "^5.8.2",
152 "lemonadejs": "^5.3.6"
153 }
154 },
155 "node_modules/@lemonadejs/modal": {
156 "version": "5.8.2",
157 "resolved": "https://registry.npmjs.org/@lemonadejs/modal/-/modal-5.8.2.tgz",
158 "integrity": "sha512-wMsc6W+zf36/WcvUtfODG7IimAE/nEecvuHLKkfseGVgvPXlBB6OA4Kw+T3mmDwdWE1U8guSXcrcyvOoaUuqIQ==",
159 "dependencies": {
160 "lemonadejs": "^5.3.6"
161 }
162 },
163 "node_modules/@lemonadejs/rating": {
164 "version": "5.8.1",
165 "resolved": "https://registry.npmjs.org/@lemonadejs/rating/-/rating-5.8.1.tgz",
166 "integrity": "sha512-g/FJVJ/ay1BmcdqHDHX/2CHBQ1vBViJipWuEMdsqnwbnGGpkKf2q5Ml3xI2GMwCVw8ovvcy/++3UP1xs9GLyMQ==",
167 "dependencies": {
168 "lemonadejs": "^5.3.2"
169 }
170 },
171 "node_modules/@lemonadejs/switch": {
172 "version": "5.8.0",
173 "resolved": "https://registry.npmjs.org/@lemonadejs/switch/-/switch-5.8.0.tgz",
174 "integrity": "sha512-EpqK5iCpQj3o1bN8wW+jka6O4aMIKP5IbLXtD9iTv/ipasyQgxz2oZNkHD8yS6JrpGffSd87FNi37qm/XcJN3w==",
175 "dependencies": {
176 "lemonadejs": "^5.3.2"
177 }
178 },
179 "node_modules/@lemonadejs/tabs": {
180 "version": "5.8.0",
181 "resolved": "https://registry.npmjs.org/@lemonadejs/tabs/-/tabs-5.8.0.tgz",
182 "integrity": "sha512-nyqHOVwqKnFvqOxwidT5VFzKuFJ/Bzdfvqs7QY30LK9CXK3MrQBgLrijpQOTL3Als1Qp6qp3Q0HRQqUsLARhyA==",
183 "dependencies": {
184 "lemonadejs": "^5.3.2"
185 }
186 },
187 "node_modules/@lemonadejs/topmenu": {
188 "version": "5.8.0",
189 "resolved": "https://registry.npmjs.org/@lemonadejs/topmenu/-/topmenu-5.8.0.tgz",
190 "integrity": "sha512-mkWnaiE+0c/i+wv9cz88d2U4GOTxVIVj4aEOad4rQ2JCKkQfw02sP6PS/NaXWJMgDsF1cJOMnO3BThnP5/BqVw==",
191 "dependencies": {
192 "@lemonadejs/contextmenu": "^5.8.0",
193 "lemonadejs": "^5.3.2"
194 }
195 },
105196 "node_modules/@noble/ed25519": {
106197 "version": "2.0.0",
107198 "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-2.0.0.tgz",
……@@ -1787,6 +1878,37 @@
17871878 "url": "https://github.com/sponsors/dmonad"
17881879 }
17891880 },
1881 "node_modules/jspreadsheet-ce": {
1882 "version": "5.0.4",
1883 "resolved": "https://registry.npmjs.org/jspreadsheet-ce/-/jspreadsheet-ce-5.0.4.tgz",
1884 "integrity": "sha512-ra1JI1n+tEGgRMzTzNkPZjG0HZz8W6bFGAiTiHl+eYarXdRmS5qDc/ua3l2ev7oZ6Og9kjfrXYHVLUWiVc308w==",
1885 "dependencies": {
1886 "@jspreadsheet/formula": "^2.0.2",
1887 "jsuites": "^5.12.0"
1888 }
1889 },
1890 "node_modules/jspreadsheet-ce/node_modules/jsuites": {
1891 "version": "5.13.5",
1892 "resolved": "https://registry.npmjs.org/jsuites/-/jsuites-5.13.5.tgz",
1893 "integrity": "sha512-cvkcpy/v5I3+IAcNPE4UP38PFCEfUQw9JI5NN61dlcXLwkD+2UTIOsRPvgMLeqI1eDWHL4AHfrbcE/+TFciUsw=="
1894 },
1895 "node_modules/jsuites": {
1896 "version": "6.3.1",
1897 "resolved": "https://registry.npmjs.org/jsuites/-/jsuites-6.3.1.tgz",
1898 "integrity": "sha512-TS5jU+pjJOGSPVnldFz4LFiTmYULjBLiDq5VFAjnYPBnWOOaxm4goA6NA2Hp+/rR6ZGLUNNAtfupyTnUpZT3QQ==",
1899 "dependencies": {
1900 "@jsuites/utils": "^6.0.4",
1901 "@lemonadejs/calendar": "^5.8.4",
1902 "@lemonadejs/color": "^5.8.0",
1903 "@lemonadejs/contextmenu": "^5.8.3",
1904 "@lemonadejs/dropdown": "^5.8.2",
1905 "@lemonadejs/modal": "^5.8.2",
1906 "@lemonadejs/rating": "^5.8.1",
1907 "@lemonadejs/switch": "^5.8.0",
1908 "@lemonadejs/tabs": "^5.8.0",
1909 "@lemonadejs/topmenu": "^5.8.0"
1910 }
1911 },
17901912 "node_modules/kademlia-routing-table": {
17911913 "version": "1.0.6",
17921914 "resolved": "https://registry.npmjs.org/kademlia-routing-table/-/kademlia-routing-table-1.0.6.tgz",
……@@ -1809,6 +1931,11 @@
18091931 "sodium-universal": "^5.0.1"
18101932 }
18111933 },
1934 "node_modules/lemonadejs": {
1935 "version": "5.3.6",
1936 "resolved": "https://registry.npmjs.org/lemonadejs/-/lemonadejs-5.3.6.tgz",
1937 "integrity": "sha512-GfmoZvCcnesiRsU9oC3OJDZ2VU+U4TsOJKD3A+rEV7dwm2IBO0xaBkLYtpgY3kcoFQjm7u5k9KSQXEtIkanjHQ=="
1938 },
18121939 "node_modules/lib0": {
18131940 "version": "0.2.117",
18141941 "resolved": "https://registry.npmjs.org/lib0/-/lib0-0.2.117.tgz",
package.json +2 -0
……@@ -33,6 +33,8 @@
3333 "hypercore-crypto": "^3.0.0",
3434 "hyperdrive": "^11.13.4",
3535 "hyperswarm": "^4.7.0",
36 "jspreadsheet-ce": "^5.0.4",
37 "jsuites": "^6.3.1",
3638 "keet-identity-key": "github:holepunchto/keet-identity-key",
3739 "pear-runtime": "^0.5.0",
3840 "secure-prompt": "github:holepunchto/secure-prompt",
web/index.html +29 -1
……@@ -7,6 +7,8 @@
77 <script>document.documentElement.setAttribute('data-theme',localStorage.getItem('hn-theme')||'dark')</script>
88 <link rel="stylesheet" href="web/css/app.css?v=24">
99 <link rel="stylesheet" href="web/vendor/toastui-editor.min.css">
10 <link rel="stylesheet" href="web/vendor/jsuites.css">
11 <link rel="stylesheet" href="web/vendor/jspreadsheet.css">
1012 <style>
1113 .notebook-readme {
1214 background: var(--bg-secondary, #1e1e2e);
……@@ -41,6 +43,25 @@
4143 .readme-body ul { padding-left: 20px; }
4244 .readme-body a { color: var(--color-primary, #6c9eff); }
4345 .readme-body a:hover { text-decoration: underline; }
46 #editor-type {
47 padding: 6px 10px;
48 border: 1px solid var(--border-color, #333);
49 border-radius: 4px;
50 background: var(--bg-secondary, #1e1e2e);
51 color: var(--text-color, #ccc);
52 font-size: 0.85rem;
53 }
54 #spreadsheet-container {
55 border: 1px solid var(--border-color, #333);
56 border-radius: 4px;
57 overflow: auto;
58 }
59 #note-spreadsheet-view {
60 border: 1px solid var(--border-color, #333);
61 border-radius: 4px;
62 overflow: auto;
63 margin-top: 12px;
64 }
4465 </style>
4566</head>
4667<body>
……@@ -108,12 +129,17 @@
108129 <div class="editor-toolbar">
109130 <input type="text" id="editor-title" placeholder="Note title">
110131 <input type="text" id="editor-tags" placeholder="Tags (comma-separated)">
132 <select id="editor-type" title="Note type">
133 <option value="markdown">Markdown</option>
134 <option value="spreadsheet">Spreadsheet</option>
135 </select>
111136 <div class="editor-actions">
112137 <button id="btn-save-note" class="btn-primary">Save</button>
113138 <button id="btn-cancel-edit">Cancel</button>
114139 </div>
115140 </div>
116141 <div id="editor-container"></div>
142 <div id="spreadsheet-container" style="display:none"></div>
117143 </div>
118144
119145 <div id="view-search" class="view" style="display:none">
……@@ -151,9 +177,11 @@
151177 </div>
152178
153179 <script src="web/vendor/toastui-editor-all.min.js"></script>
180 <script src="web/vendor/jsuites.js"></script>
181 <script src="web/vendor/jspreadsheet.js"></script>
154182 <script src="web/js/identity.js?v=27"></script>
155183 <script src="web/js/api.js?v=28"></script>
156184 <script src="web/js/markdown.js?v=23"></script>
157 <script src="web/js/app.js?v=28"></script>
185 <script src="web/js/app.js?v=29"></script>
158186</body>
159187</html>
web/js/app.js +126 -12
……@@ -165,8 +165,11 @@
165165 // Editor
166166 var $editorTitle = document.getElementById('editor-title')
167167 var $editorTags = document.getElementById('editor-tags')
168 var $editorType = document.getElementById('editor-type')
168169 var $editorContainer = document.getElementById('editor-container')
170 var $spreadsheetContainer = document.getElementById('spreadsheet-container')
169171 var tuiEditor = null
172 var spreadsheetInstance = null
170173
171174 // Notebook view
172175 var $notebookTitle = document.getElementById('notebook-title')
……@@ -768,12 +771,23 @@
768771
769772 var h3 = document.createElement('h3')
770773 h3.textContent = note.title || 'Untitled'
774 if (note.type === 'spreadsheet') {
775 var typeLabel = document.createElement('span')
776 typeLabel.className = 'note-type-label'
777 typeLabel.textContent = 'spreadsheet'
778 typeLabel.style.cssText = 'font-size:0.7em;background:var(--color-primary,#6c9eff);color:#fff;padding:2px 6px;border-radius:3px;margin-left:8px;vertical-align:middle'
779 h3.appendChild(typeLabel)
780 }
771781 card.appendChild(h3)
772782
773783 if (note.content) {
774784 var snippet = document.createElement('div')
775785 snippet.className = 'snippet'
776 snippet.textContent = note.content.substring(0, 120) + (note.content.length > 120 ? '...' : '')
786 if (note.type === 'spreadsheet') {
787 snippet.textContent = '(spreadsheet data)'
788 } else {
789 snippet.textContent = note.content.substring(0, 120) + (note.content.length > 120 ? '...' : '')
790 }
777791 card.appendChild(snippet)
778792 }
779793
……@@ -820,7 +834,7 @@
820834 updateBreadcrumb()
821835 renderNotebookList()
822836
823 // Render markdown content
837 // Render note content (markdown or spreadsheet)
824838 $noteContent.className = 'markdown-body'
825839 $noteContent.innerHTML = '<h1>' + esc(state.currentNote.title) + '</h1>'
826840 if (state.currentNote.tags && state.currentNote.tags.length > 0) {
……@@ -831,7 +845,35 @@
831845 tagsHtml += '</div>'
832846 $noteContent.innerHTML += tagsHtml
833847 }
834 $noteContent.innerHTML += window.renderMarkdown(rewriteMediaUrls(state.currentNote.content))
848
849 if (state.currentNote.type === 'spreadsheet') {
850 // Render read-only spreadsheet
851 var ssContainer = document.createElement('div')
852 ssContainer.id = 'note-spreadsheet-view'
853 $noteContent.appendChild(ssContainer)
854 var ssData
855 try {
856 ssData = state.currentNote.content ? JSON.parse(state.currentNote.content) : {}
857 } catch (e) {
858 ssData = {}
859 }
860 var cellData = ssData.data && ssData.data.length ? ssData.data : [['']]
861 var wsViewConfig = {
862 data: cellData,
863 minDimensions: [4, 4],
864 tableOverflow: true,
865 tableWidth: '100%',
866 tableHeight: '400px',
867 defaultColWidth: 120,
868 editable: false
869 }
870 if (ssData.columns) wsViewConfig.columns = ssData.columns
871 jspreadsheet(ssContainer, {
872 worksheets: [wsViewConfig]
873 })
874 } else {
875 $noteContent.innerHTML += window.renderMarkdown(rewriteMediaUrls(state.currentNote.content))
876 }
835877
836878 // Add media hover overlays for writers
837879 if (state.canWrite) addMediaOverlays()
……@@ -1285,6 +1327,7 @@
12851327 state.editing = true
12861328
12871329 var initialContent = ''
1330 var noteType = 'markdown'
12881331
12891332 if (noteId) {
12901333 // Edit existing — noteId may be a slug, resolve to hex ID
……@@ -1295,6 +1338,7 @@
12951338 $editorTitle.value = note.title || ''
12961339 $editorTags.value = (note.tags || []).join(', ')
12971340 initialContent = rewriteMediaUrls(note.content)
1341 noteType = note.type || 'markdown'
12981342 state.currentNote = note
12991343 } catch (err) {
13001344 console.error('Failed to load note for editing:', err)
……@@ -1302,23 +1346,68 @@
13021346 return
13031347 }
13041348 } else {
1305 // New note
1349 // New note — preserve type selector if already set (user may have toggled it)
13061350 state.editingId = null
1307 $editorTitle.value = ''
1308 $editorTags.value = ''
1351 if (!$editorTitle.value) $editorTitle.value = ''
1352 $editorTags.value = $editorTags.value || ''
13091353 initialContent = ''
1354 noteType = $editorType.value || 'markdown'
13101355 state.currentNote = null
13111356 }
13121357
1358 // Set type selector
1359 $editorType.value = noteType
1360 // Lock type for existing notes (changing type after creation is not supported)
1361 $editorType.disabled = !!noteId
1362
13131363 showView('editor')
13141364 updateBreadcrumb()
13151365 renderNotebookList()
13161366
1317 // Destroy previous editor instance if any
1367 // Destroy previous editor instances
13181368 if (tuiEditor) {
13191369 tuiEditor.destroy()
13201370 tuiEditor = null
13211371 }
1372 if (spreadsheetInstance) {
1373 try {
1374 if (spreadsheetInstance[0] && spreadsheetInstance[0].parent) {
1375 jspreadsheet.destroy($spreadsheetContainer)
1376 }
1377 } catch (e) {}
1378 spreadsheetInstance = null
1379 }
1380 $spreadsheetContainer.innerHTML = ''
1381
1382 // Branch: spreadsheet or markdown editor
1383 if (noteType === 'spreadsheet') {
1384 $editorContainer.style.display = 'none'
1385 $spreadsheetContainer.style.display = ''
1386 var ssData
1387 try {
1388 ssData = initialContent ? JSON.parse(initialContent) : {}
1389 } catch (e) {
1390 ssData = {}
1391 }
1392 var cellData = ssData.data && ssData.data.length ? ssData.data : [['', '', '', ''], ['', '', '', ''], ['', '', '', ''], ['', '', '', '']]
1393 var wsConfig = {
1394 data: cellData,
1395 minDimensions: [4, 4],
1396 tableOverflow: true,
1397 tableWidth: '100%',
1398 tableHeight: 'calc(100vh - 240px)',
1399 defaultColWidth: 120
1400 }
1401 if (ssData.columns) wsConfig.columns = ssData.columns
1402 spreadsheetInstance = jspreadsheet($spreadsheetContainer, {
1403 worksheets: [wsConfig]
1404 })
1405 return // Skip Toast UI setup
1406 }
1407
1408 // Markdown editor path
1409 $editorContainer.style.display = ''
1410 $spreadsheetContainer.style.display = 'none'
13221411
13231412 // Helper: insert raw markdown without WYSIWYG escaping
13241413 // Switches to markdown mode, inserts at end, adds trailing newline for cursor escape
……@@ -1619,15 +1708,23 @@
16191708 if (!await ensureIdentity()) return
16201709 var notebook = state.currentNotebook.slug
16211710 var title = $editorTitle.value.trim()
1622 var content = tuiEditor ? tuiEditor.getMarkdown() : ''
1623 // Normalize gallery blocks — ensure ```gallery is on its own line with no trailing whitespace
1624 content = content.replace(/[ \t]*```gallery[ \t]*/g, '```gallery')
1625 content = content.replace(/([^\n])```gallery/g, '$1\n```gallery')
1711 var noteType = $editorType.value
1712 var content
16261713 var tags = $editorTags.value
16271714 .split(',')
16281715 .map(function (t) { return t.trim() })
16291716 .filter(function (t) { return t.length > 0 })
16301717
1718 if (noteType === 'spreadsheet' && spreadsheetInstance) {
1719 var ssData = spreadsheetInstance[0].getData()
1720 content = JSON.stringify({ data: ssData })
1721 } else {
1722 content = tuiEditor ? tuiEditor.getMarkdown() : ''
1723 // Normalize gallery blocks — ensure ```gallery is on its own line with no trailing whitespace
1724 content = content.replace(/[ \t]*```gallery[ \t]*/g, '```gallery')
1725 content = content.replace(/([^\n])```gallery/g, '$1\n```gallery')
1726 }
1727
16311728 if (!title) {
16321729 alert('Title is required')
16331730 return
……@@ -1641,7 +1738,7 @@
16411738 navigate('#/' + encodeURIComponent(notebook) + '/' + encodeURIComponent(updatedNote.slug || state.editingId))
16421739 } else {
16431740 // Create new note
1644 var data = await HnApi.createNote(notebook, { title: title, content: content, tags: tags })
1741 var data = await HnApi.createNote(notebook, { title: title, content: content, tags: tags, type: noteType })
16451742 var note = data.note || data
16461743 navigate('#/' + encodeURIComponent(notebook) + '/' + encodeURIComponent(note.slug || note.id))
16471744 }
……@@ -2978,6 +3075,23 @@
29783075 document.getElementById('btn-note-links').addEventListener('click', showLinks)
29793076 document.getElementById('btn-note-backlinks').addEventListener('click', showBacklinks)
29803077
3078 // Editor type selector — swap editor when creating new notes
3079 $editorType.addEventListener('change', function () {
3080 if (state.editingId) return // Can't change type of existing notes
3081 var notebook = state.currentNotebook ? state.currentNotebook.slug : null
3082 if (!notebook) return
3083 // Warn if switching would discard content
3084 var hasContent = (tuiEditor && tuiEditor.getMarkdown().trim()) ||
3085 (spreadsheetInstance && spreadsheetInstance[0] && spreadsheetInstance[0].getData().some(function (row) { return row.some(function (c) { return c !== '' }) }))
3086 if (hasContent && !confirm('Switching note type will discard current content. Continue?')) {
3087 // Revert the selector
3088 $editorType.value = spreadsheetInstance ? 'spreadsheet' : 'markdown'
3089 return
3090 }
3091 // Re-run loadEditor which will pick up the new type value
3092 loadEditor(notebook, null)
3093 })
3094
29813095 // Editor save/cancel
29823096 document.getElementById('btn-save-note').addEventListener('click', saveNote)
29833097 document.getElementById('btn-cancel-edit').addEventListener('click', function () {
web/vendor/jspreadsheet.css +716 -0
……@@ -0,0 +1,716 @@
1:root {
2 --jss-border-color:#000;
3}
4
5.jss_spreadsheet {
6 outline: none;
7}
8
9.jss_container {
10 display:inline-block;
11 padding-right:2px;
12 box-sizing: border-box;
13 overscroll-behavior: contain;
14 outline: none;
15}
16
17.fullscreen {
18 position:fixed !important;
19 top:0px;
20 left:0px;
21 width:100%;
22 height:100%;
23 z-index:21;
24
25 display: flex;
26 flex-direction: column;
27
28 background-color:#ffffff;
29}
30
31.fullscreen .jtabs-content {
32 flex: 1;
33 overflow: hidden;
34}
35
36.fullscreen .jss_content {
37 overflow:auto;
38 width: 100% !important;
39 height:100%;
40 max-height: 100% !important;
41}
42
43.fullscreen .jss_container {
44 height:100%;
45}
46
47.jss_content {
48 display:inline-block;
49 box-sizing: border-box;
50 padding-right:3px;
51 padding-bottom:3px;
52 position:relative;
53 scrollbar-width: thin;
54 scrollbar-color: #666 transparent;
55}
56
57@supports (-moz-appearance:none) {
58 .jss_content { padding-right:10px; }
59}
60
61.jss_content::-webkit-scrollbar {
62 width: 8px;
63 height: 8px;
64}
65
66.jss_content::-webkit-scrollbar-track {
67 background: #eee;
68}
69
70.jss_content::-webkit-scrollbar-thumb {
71 background: #666;
72}
73
74.jss_worksheet {
75 border-collapse: separate;
76 table-layout: fixed;
77 white-space: nowrap;
78 empty-cells: show;
79 border: 0px;
80 background-color: #fff;
81 width: 0;
82
83 border-top: 1px solid transparent;
84 border-left: 1px solid transparent;
85 border-right: 1px solid #ccc;
86 border-bottom: 1px solid #ccc;
87}
88
89.jss_worksheet > thead > tr > td
90{
91 border-top: 1px solid #ccc;
92 border-left: 1px solid #ccc;
93 border-right: 1px solid transparent;
94 border-bottom: 1px solid transparent;
95 background-color: #f3f3f3;
96 padding: 2px;
97 cursor: pointer;
98 box-sizing: border-box;
99 overflow: hidden;
100 position: -webkit-sticky;
101 position: sticky;
102 top: 0;
103 z-index:2;
104}
105
106.jss_worksheet > thead > tr > td.dragging
107{
108 opacity:0.5;
109}
110
111.jss_worksheet > thead > tr > td.selected
112{
113 background-color:#dcdcdc;
114}
115
116.jss_worksheet > thead > tr > td.arrow-up
117{
118 background-repeat:no-repeat;
119 background-position:center right 5px;
120 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath d='M7 14l5-5 5 5H7z' fill='gray'/%3E%3C/svg%3E");
121 text-decoration:underline;
122}
123
124.jss_worksheet > thead > tr > td.arrow-down
125{
126 background-repeat:no-repeat;
127 background-position:center right 5px;
128 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath d='M7 10l5 5 5-5H7z' fill='gray'/%3E%3C/svg%3E");
129 text-decoration:underline;
130}
131
132.jss_worksheet > tbody > tr > td:first-child
133{
134 position:relative;
135 background-color:#f3f3f3;
136 text-align:center;
137}
138
139.jss_worksheet > tbody.resizable > tr > td:first-child::before
140{
141 content:'\00a0';
142 width:100%;
143 height:3px;
144 position:absolute;
145 bottom:0px;
146 left:0px;
147 cursor:row-resize;
148}
149
150.jss_worksheet > tbody.draggable > tr > td:first-child::after
151{
152 content:'\00a0';
153 width:3px;
154 height:100%;
155 position:absolute;
156 top:0px;
157 right:0px;
158 cursor:move;
159}
160
161.jss_worksheet > tbody > tr.dragging > td
162{
163 background-color:#eee;
164 opacity:0.5;
165}
166
167.jss_worksheet > tbody > tr > td
168{
169 border-top:1px solid #ccc;
170 border-left:1px solid #ccc;
171 border-right:1px solid transparent;
172 border-bottom:1px solid transparent;
173 padding:4px;
174 white-space: nowrap;
175 box-sizing: border-box;
176 line-height:1em;
177}
178
179.jss_overflow > tbody > tr > td {
180 overflow: hidden;
181}
182
183.jss_worksheet > tbody > tr > td:last-child
184{
185 overflow: hidden;
186}
187
188.jss_worksheet > tbody > tr > td > img
189{
190 display:inline-block;
191 max-width:100px;
192}
193
194.jss_worksheet > tbody > tr > td.readonly
195{
196 color:rgba(0,0,0,0.3)
197}
198.jss_worksheet > tbody > tr.selected > td:first-child
199{
200 background-color:#dcdcdc;
201}
202.jss_worksheet > tbody > tr > td > select,
203.jss_worksheet > tbody > tr > td > input,
204.jss_worksheet > tbody > tr > td > textarea
205{
206 border:0px;
207 border-radius:0px;
208 outline:0px;
209 width:100%;
210 margin:0px;
211 padding:0px;
212 padding-right:2px;
213 background-color:transparent;
214 box-sizing: border-box;
215}
216
217.jss_worksheet > tbody > tr > td > textarea
218{
219 resize: none;
220 padding-top:6px !important;
221}
222
223.jss_worksheet > tbody > tr > td > input[type=checkbox]
224{
225 width:12px;
226 margin-top:2px;
227}
228.jss_worksheet > tbody > tr > td > input[type=radio]
229{
230 width:12px;
231 margin-top:2px;
232}
233
234.jss_worksheet > tbody > tr > td > select
235{
236 -webkit-appearance: none;
237 -moz-appearance: none;
238 appearance: none;
239 background-repeat: no-repeat;
240 background-position-x: 100%;
241 background-position-y: 40%;
242 background-image: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSdibGFjaycgaGVpZ2h0PScyNCcgdmlld0JveD0nMCAwIDI0IDI0JyB3aWR0aD0nMjQnIHhtbG5zPSdodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Zyc+PHBhdGggZD0nTTcgMTBsNSA1IDUtNXonLz48cGF0aCBkPSdNMCAwaDI0djI0SDB6JyBmaWxsPSdub25lJy8+PC9zdmc+);
243}
244
245.jss_worksheet > tbody > tr > td.jss_dropdown
246{
247 background-repeat: no-repeat;
248 background-position:top 50% right 5px;
249 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath d='M7 10l5 5 5-5H7z' fill='lightgray'/%3E%3C/svg%3E");
250 text-overflow: ellipsis;
251 overflow-x:hidden;
252}
253
254.jss_worksheet > tbody > tr > td.jss_dropdown.jss_comments
255{
256 background:url("data:image/svg+xml,%0A%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath fill='none' d='M0 0h24v24H0V0z'/%3E%3Cpath d='M7 10l5 5 5-5H7z' fill='lightgray'/%3E%3C/svg%3E") top 50% right 5px no-repeat, url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFuGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTAxLTMxVDE4OjU1OjA4WiIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wMS0zMVQxODo1NTowOFoiIHhtcDpNb2RpZnlEYXRlPSIyMDE5LTAxLTMxVDE4OjU1OjA4WiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDphMTlhZDJmOC1kMDI2LTI1NDItODhjOS1iZTRkYjkyMmQ0MmQiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDpkOGI5NDUyMS00ZjEwLWQ5NDktYjUwNC0wZmU1N2I3Nzk1MDEiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDplMzdjYmE1ZS1hYTMwLWNkNDUtYTAyNS1lOWYxZjk2MzUzOGUiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDplMzdjYmE1ZS1hYTMwLWNkNDUtYTAyNS1lOWYxZjk2MzUzOGUiIHN0RXZ0OndoZW49IjIwMTktMDEtMzFUMTg6NTU6MDhaIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOmExOWFkMmY4LWQwMjYtMjU0Mi04OGM5LWJlNGRiOTIyZDQyZCIgc3RFdnQ6d2hlbj0iMjAxOS0wMS0zMVQxODo1NTowOFoiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4En6MDAAAAX0lEQVQYlX3KOw6AIBBAwS32RpJADXfx0pTET+ERZJ8F8RODFtONsG0QAoh0CSDM82dqodaBdQXnfoLZQM7gPai+wjNNE8R4pTuAYNZSKZASqL7CMy0LxNgJp30fKYUDi3+vIqb/+rUAAAAASUVORK5CYII=') top right no-repeat;
257}
258
259.jss_worksheet > tbody > tr > td > .color
260{
261 width:90%;
262 height:10px;
263 margin:auto;
264}
265
266.jss_worksheet > tbody > tr > td > a {
267 text-decoration: underline;
268}
269
270.jss_worksheet > tbody > tr > td.highlight > a {
271 color: blue;
272 cursor: pointer;
273}
274
275.jss_worksheet > tfoot > tr > td
276{
277 border-top: 1px solid #ccc;
278 border-left: 1px solid #ccc;
279 border-right: 1px solid transparent;
280 border-bottom: 1px solid transparent;
281 background-color: #f3f3f3;
282 padding: 2px;
283 cursor: pointer;
284 box-sizing: border-box;
285 overflow: hidden;
286}
287
288.jss_worksheet .highlight {
289 background-color:rgba(0,0,0,0.05);
290}
291
292.jss_worksheet .highlight-top {
293 border-top:1px solid #000;
294 box-shadow: 0px -1px #ccc;
295}
296
297.jss_worksheet .highlight-left {
298 border-left:1px solid #000;
299 box-shadow: -1px 0px #ccc;
300}
301
302.jss_worksheet .highlight-right {
303 border-right:1px solid #000;
304}
305
306.jss_worksheet .highlight-bottom {
307 border-bottom:1px solid #000;
308}
309
310.jss_worksheet .highlight-top.highlight-left {
311 box-shadow: -1px -1px #ccc;
312 -webkit-box-shadow: -1px -1px #ccc;
313 -moz-box-shadow: -1px -1px #ccc;
314}
315
316.jss_worksheet .highlight-selected
317{
318 background-color:rgba(0,0,0,0.0);
319}
320.jss_worksheet .selection
321{
322 background-color:rgba(0,0,0,0.05);
323}
324.jss_worksheet .selection-left
325{
326 border-left:1px dotted #000;
327}
328.jss_worksheet .selection-right
329{
330 border-right:1px dotted #000;
331}
332.jss_worksheet .selection-top
333{
334 border-top:1px dotted #000;
335}
336.jss_worksheet .selection-bottom
337{
338 border-bottom:1px dotted #000;
339}
340.jss_corner
341{
342 position:absolute;
343 background-color: rgb(0, 0, 0);
344 height: 1px;
345 width: 1px;
346 border: 1px solid rgb(255, 255, 255);
347 top:-2000px;
348 left:-2000px;
349 cursor:crosshair;
350 box-sizing: initial;
351 z-index:20;
352 padding: 2px;
353}
354
355.jss_worksheet .editor
356{
357 outline:0px solid transparent;
358 overflow:visible;
359 white-space: nowrap;
360 text-align:left;
361 padding:0px;
362 box-sizing: border-box;
363 overflow:visible !important;
364}
365
366.jss_worksheet .editor > input
367{
368 padding-left:4px;
369}
370
371.jss_worksheet .editor .jupload
372{
373 position:fixed;
374 top:100%;
375 z-index:40;
376 user-select:none;
377 -webkit-font-smoothing: antialiased;
378 font-size: .875rem;
379 letter-spacing: .2px;
380 -webkit-border-radius: 4px;
381 border-radius: 4px;
382 -webkit-box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.2);
383 box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.2);
384 padding:10px;
385 background-color:#fff;
386 width:300px;
387 min-height:225px;
388 margin-top:2px;
389}
390
391.jss_worksheet .editor .jupload img
392{
393 width:100%;
394 height:auto;
395}
396
397.jss_worksheet .editor .jss_richtext
398{
399 position:fixed;
400 top:100%;
401 z-index:40;
402 user-select:none;
403 -webkit-font-smoothing: antialiased;
404 font-size: .875rem;
405 letter-spacing: .2px;
406 -webkit-box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.2);
407 box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.2);
408 padding:10px;
409 background-color:#fff;
410 width:358px;
411 margin-top:2px;
412 text-align:left;
413 white-space: initial;
414}
415
416.jss_worksheet .editor .jclose:after
417{
418 position:absolute;
419 top:0;
420 right:0;
421 margin:10px;
422 content:'close';
423 font-family:'Material icons';
424 font-size:24px;
425 width:24px;
426 height:24px;
427 line-height:24px;
428 cursor:pointer;
429 text-shadow: 0px 0px 5px #fff;
430}
431
432.jss_worksheet, .jss_worksheet td, .jss_corner
433{
434 -webkit-touch-callout: none;
435 -webkit-user-select: none;
436 -khtml-user-select: none;
437 -moz-user-select: none;
438 -ms-user-select: none;
439 user-select: none;
440 -webkit-user-drag: none;
441 -khtml-user-drag: none;
442 -moz-user-drag: none;
443 -o-user-drag: none;
444 user-drag: none;
445}
446
447.jss_textarea
448{
449 position:absolute;
450 top:-999px;
451 left:-999px;
452 width:1px;
453 height:1px;
454}
455.jss_worksheet .dragline
456{
457 position:absolute;
458}
459.jss_worksheet .dragline div
460{
461 position:relative;
462 top:-6px;
463 height:5px;
464 width:22px;
465}
466.jss_worksheet .dragline div:hover
467{
468 cursor:move;
469}
470
471.jss_worksheet .onDrag
472{
473 background-color:rgba(0,0,0,0.6);
474}
475
476.jss_worksheet .error
477{
478 border:1px solid red;
479}
480
481.jss_worksheet thead td.resizing
482{
483 border-right-style:dotted !important;
484 border-right-color:red !important;
485}
486
487.jss_worksheet tbody tr.resizing > td
488{
489 border-bottom-style:dotted !important;
490 border-bottom-color:red !important;
491}
492
493.jss_worksheet tbody td.resizing
494{
495 border-right-style:dotted !important;
496 border-right-color:red !important;
497}
498
499.jss_worksheet .jdropdown-header
500{
501 border:0px !important;
502 outline:none !important;
503 width:100% !important;
504 height:100% !important;
505 padding:0px !important;
506 padding-left:8px !important;
507}
508
509.jss_worksheet .jdropdown-container
510{
511 margin-top:1px;
512}
513
514.jss_worksheet .jdropdown-container-header {
515 padding: 0px;
516 margin: 0px;
517 height: inherit;
518}
519
520.jss_worksheet .jdropdown-picker
521{
522 border:0px !important;
523 padding:0px !important;
524 width:inherit;
525 height:inherit;
526}
527
528.jss_worksheet .jss_comments
529{
530 background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFuGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdEV2dD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlRXZlbnQjIiB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTAxLTMxVDE4OjU1OjA4WiIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wMS0zMVQxODo1NTowOFoiIHhtcDpNb2RpZnlEYXRlPSIyMDE5LTAxLTMxVDE4OjU1OjA4WiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDphMTlhZDJmOC1kMDI2LTI1NDItODhjOS1iZTRkYjkyMmQ0MmQiIHhtcE1NOkRvY3VtZW50SUQ9ImFkb2JlOmRvY2lkOnBob3Rvc2hvcDpkOGI5NDUyMS00ZjEwLWQ5NDktYjUwNC0wZmU1N2I3Nzk1MDEiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDplMzdjYmE1ZS1hYTMwLWNkNDUtYTAyNS1lOWYxZjk2MzUzOGUiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIj4gPHhtcE1NOkhpc3Rvcnk+IDxyZGY6U2VxPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0iY3JlYXRlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDplMzdjYmE1ZS1hYTMwLWNkNDUtYTAyNS1lOWYxZjk2MzUzOGUiIHN0RXZ0OndoZW49IjIwMTktMDEtMzFUMTg6NTU6MDhaIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOmExOWFkMmY4LWQwMjYtMjU0Mi04OGM5LWJlNGRiOTIyZDQyZCIgc3RFdnQ6d2hlbj0iMjAxOS0wMS0zMVQxODo1NTowOFoiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCBDQyAyMDE5IChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4En6MDAAAAX0lEQVQYlX3KOw6AIBBAwS32RpJADXfx0pTET+ERZJ8F8RODFtONsG0QAoh0CSDM82dqodaBdQXnfoLZQM7gPai+wjNNE8R4pTuAYNZSKZASqL7CMy0LxNgJp30fKYUDi3+vIqb/+rUAAAAASUVORK5CYII=');
531 background-repeat: no-repeat;
532 background-position: top right;
533}
534
535.jss_worksheet .sp-replacer
536{
537 margin: 2px;
538 border:0px;
539}
540
541.jss_worksheet > thead > tr.jss_filter > td > input
542{
543 border:0px;
544 width:100%;
545 outline:none;
546}
547
548.jss_about {
549 float: right;
550 font-size: 0.7em;
551 padding: 2px;
552 text-transform: uppercase;
553 letter-spacing: 1px;
554 display: none;
555}
556.jss_about a {
557 color: #ccc;
558 text-decoration: none;
559}
560
561.jss_about img {
562 display: none;
563}
564
565.jss_filter
566{
567 display:flex;
568 justify-content:space-between;
569 margin-bottom:4px;
570}
571
572.jss_filter > div
573{
574 padding:8px;
575 align-items:center;
576}
577
578.jss_pagination
579{
580 display:flex;
581 justify-content:space-between;
582 align-items:center;
583}
584
585.jss_pagination > div
586{
587 display:flex;
588 padding:10px;
589}
590
591.jss_pagination > div:last-child
592{
593 padding-right:10px;
594 padding-top:10px;
595}
596
597.jss_pagination > div > div
598{
599 text-align:center;
600 width:36px;
601 height:36px;
602 line-height:34px;
603 border:1px solid #ccc;
604 box-sizing: border-box;
605 margin-left:2px;
606 cursor:pointer;
607}
608
609.jss_page
610{
611 font-size:0.8em;
612}
613
614.jss_page_selected
615{
616 font-weight:bold;
617 background-color:#f3f3f3;
618}
619
620.jss_toolbar
621{
622 display:flex;
623 background-color:#f3f3f3;
624 border:1px solid #ccc;
625 padding:4px;
626 margin:0px 2px 4px 1px;
627}
628
629.jss_toolbar:empty
630{
631 display:none;
632}
633
634.jss_worksheet .dragging-left
635{
636 background-repeat: no-repeat;
637 background-position:top 50% left 0px;
638 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M14 7l-5 5 5 5V7z'/%3E%3Cpath fill='none' d='M24 0v24H0V0h24z'/%3E%3C/svg%3E");
639}
640
641.jss_worksheet .dragging-right
642{
643 background-repeat: no-repeat;
644 background-position:top 50% right 0px;
645 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M10 17l5-5-5-5v10z'/%3E%3Cpath fill='none' d='M0 24V0h24v24H0z'/%3E%3C/svg%3E");
646}
647
648.jss_hidden_index > tbody > tr > td:first-child,
649.jss_hidden_index > thead > tr > td:first-child,
650.jss_hidden_index > tfoot > tr > td:first-child,
651.jss_hidden_index > colgroup > col:first-child
652{
653 display:none;
654}
655
656
657
658.jss_worksheet .jrating {
659 display: inline-flex;
660}
661.jss_worksheet .jrating > div {
662 zoom: 0.55;
663}
664
665.jss_worksheet .copying-top {
666 border-top:1px dashed #000;
667}
668
669.jss_worksheet .copying-left {
670 border-left:1px dashed #000;
671}
672
673.jss_worksheet .copying-right {
674 border-right:1px dashed #000;
675}
676
677.jss_worksheet .copying-bottom {
678 border-bottom:1px dashed #000;
679}
680
681.jss_worksheet .jss_column_filter {
682 background-repeat: no-repeat;
683 background-position: top 50% right 5px;
684 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='gray' width='18px' height='18px'%3E%3Cpath d='M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z'/%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E");
685 text-overflow: ellipsis;
686 overflow: hidden;
687 padding: 0px;
688 padding-left: 6px;
689 padding-right: 20px;
690}
691
692.jss_worksheet thead .jss_freezed, .jss_worksheet tfoot .jss_freezed {
693 left: 0px;
694 z-index: 3 !important;
695 box-shadow: 2px 0px 2px 0.2px #ccc !important;
696 -webkit-box-shadow: 2px 0px 2px 0.2px #ccc !important;
697 -moz-box-shadow: 2px 0px 2px 0.2px #ccc !important;
698}
699
700.jss_worksheet tbody .jss_freezed {
701 position: relative;
702 background-color: #fff;
703 box-shadow: 1px 1px 1px 1px #ccc !important;
704 -webkit-box-shadow: 2px 4px 4px 0.1px #ccc !important;
705 -moz-box-shadow: 2px 4px 4px 0.1px #ccc !important;
706}
707
708.red {
709 color: red;
710}
711
712.jss_worksheet > tbody > tr > td.readonly > input[type=checkbox],
713.jss_worksheet > tbody > tr > td.readonly > input[type=radio] {
714 pointer-events: none;
715 opacity: 0.5;
716}
web/vendor/jspreadsheet.js +18 -0
……@@ -0,0 +1,18 @@
1if (! jSuites && typeof(require) === 'function') {
2 var jSuites = require('jsuites');
3}
4
5if (! formula && typeof(require) === 'function') {
6 var formula = require('@jspreadsheet/formula');
7}
8
9;(function (global, factory) {
10 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
11 typeof define === 'function' && define.amd ? define(factory) :
12 global.jspreadsheet = factory();
13}(this, (function () {
14
15var jspreadsheet;(function(){"use strict";var __webpack_modules__={805:function(e,t){const s=function(e){const t=this,s=[];for(let n=0;n<e.length;n++){const o=e[n].x,r=e[n].y,l=t.options.columns[o].name?t.options.columns[o].name:o;s[r]||(s[r]={row:r,data:{}}),s[r].data[l]=e[n].value}return s.filter((function(e){return null!=e}))},n=function(e,t){const s=this,n=o.call(s.parent,"onbeforesave",s.parent,s,t);if(n)t=n;else if(!1===n)return!1;jSuites.ajax({url:e,method:"POST",dataType:"json",data:{data:JSON.stringify(t)},success:function(e){o.call(s,"onsave",s.parent,s,t)}})},o=function(e){const t=this;let o=null,r=t.parent?t.parent:t;if(!r.ignoreEvents&&("function"==typeof r.config.onevent&&(o=r.config.onevent.apply(this,arguments)),"function"==typeof r.config[e]&&(o=r.config[e].apply(this,Array.prototype.slice.call(arguments,1))),"object"==typeof r.plugins)){const e=Object.keys(r.plugins);for(let t=0;t<e.length;t++){const s=e[t],n=r.plugins[s];"function"==typeof n.onevent&&(o=n.onevent.apply(this,arguments))}}if("onafterchanges"==e){const e=arguments;if("object"==typeof r.plugins&&Object.entries(r.plugins).forEach((function([,s]){"function"==typeof s.persistence&&s.persistence(t,"setValue",{data:e[2]})})),t.options.persistence){const e=1==t.options.persistence?t.options.url:t.options.persistence,o=s.call(t,arguments[2]);n.call(t,e,o)}}return o};t.A=o},829:function(e,t,s){s.d(t,{F8:function(){return l},N$:function(){return r},dr:function(){return i}});var n=s(530),o=s(657);const r=function(e){const t=this;if(t.options.filters){e=parseInt(e),t.resetSelection();let s=[];if("checkbox"==t.options.columns[e].type)s.push({id:"true",name:"True"}),s.push({id:"false",name:"False"});else{const n=[];let o=!1;for(let s=0;s<t.options.data.length;s++){const r=t.options.data[s][e],l=t.records[s][e].element.innerHTML;r&&l?n[r]=l:o=!0}const r=Object.keys(n);s=[];for(let e=0;e<r.length;e++)s.push({id:r[e],name:n[r[e]]});o&&s.push({value:"",id:"",name:"(Blanks)"})}const n=document.createElement("div");t.filter.children[e+1].innerHTML="",t.filter.children[e+1].appendChild(n),t.filter.children[e+1].style.paddingLeft="0px",t.filter.children[e+1].style.paddingRight="0px",t.filter.children[e+1].style.overflow="initial";const r={data:s,multiple:!0,autocomplete:!0,opened:!0,value:void 0!==t.filters[e]?t.filters[e]:null,width:"100%",position:1==t.options.tableOverflow||1==t.parent.config.fullscreen,onclose:function(s){i.call(t),t.filters[e]=s.dropdown.getValue(!0),t.filter.children[e+1].innerHTML=s.dropdown.getText(),t.filter.children[e+1].style.paddingLeft="",t.filter.children[e+1].style.paddingRight="",t.filter.children[e+1].style.overflow="",l.call(t,e),o.G9.call(t)}};jSuites.dropdown(n,r)}else console.log("Jspreadsheet: filters not enabled.")},l=function(e){const t=this;if(!e)for(let s=0;s<t.filter.children.length;s++)t.filters[s]&&(e=s);const s=function(e,s,n){for(let o=0;o<e.length;o++){const r=""+t.options.data[n][s],l=""+t.records[n][s].element.innerHTML;if(e[o]==r||e[o]==l)return!0}return!1},o=t.filters[e];t.results=[];for(let n=0;n<t.options.data.length;n++)s(o,e,n)&&t.results.push(n);t.results.length||(t.results=null),n.hG.call(t)},i=function(){const e=this;if(e.options.filters)for(let t=0;t<e.filter.children.length;t++)e.filter.children[t].innerHTML="&nbsp;",e.filters[t]=null;e.results=null,n.hG.call(e)}},160:function(e,t,s){s.d(t,{e:function(){return o}});var n=s(530);const o=function(e){const t=this;if(e&&(t.options.footers=e),t.options.footers){t.tfoot||(t.tfoot=document.createElement("tfoot"),t.table.appendChild(t.tfoot));for(let e=0;e<t.options.footers.length;e++){let s;if(t.tfoot.children[e])s=t.tfoot.children[e];else{s=document.createElement("tr");const e=document.createElement("td");s.appendChild(e),t.tfoot.appendChild(s)}for(let o=0;o<t.headers.length;o++){let r;if(t.options.footers[e][o]||(t.options.footers[e][o]=""),t.tfoot.children[e].children[o+1])r=t.tfoot.children[e].children[o+1];else{r=document.createElement("td"),s.appendChild(r);const e=t.options.columns[o].align||t.options.defaultColAlign||"center";r.style.textAlign=e}r.textContent=n.$x.call(t,+t.records.length+o,e,t.options.footers[e][o]),r.style.display=t.cols[o].colElement.style.display}}}}},296:function(e,t,s){s.d(t,{w:function(){return n}});const n=function(){const e=this;let t=0;if(e.options.freezeColumns>0)for(let s=0;s<e.options.freezeColumns;s++){let n;n=e.options.columns&&e.options.columns[s]&&void 0!==e.options.columns[s].width?parseInt(e.options.columns[s].width):void 0!==e.options.defaultColWidth?parseInt(e.options.defaultColWidth):100,t+=n}return t}},978:function(e,t,s){s.r(t),s.d(t,{createFromTable:function(){return u},getCaretIndex:function(){return o},getCellNameFromCoords:function(){return i},getColumnName:function(){return l},getCoordsFromCellName:function(){return a},getCoordsFromRange:function(){return c},invert:function(){return r},parseCSV:function(){return d}});var n=s(689);const o=function(e){let t;t=this.config.root?this.config.root:window;let s=0;const n=t.getSelection();if(n&&0!==n.rangeCount){const t=n.getRangeAt(0),o=t.cloneRange();o.selectNodeContents(e),o.setEnd(t.endContainer,t.endOffset),s=o.toString().length}return s},r=function(e){const t=[],s=Object.keys(e);for(let n=0;n<s.length;n++)t[e[s[n]]]=s[n];return t},l=function(e){let t,s=e+1,n="";for(;s>0;)t=(s-1)%26,n=String.fromCharCode(65+t).toString()+n,s=parseInt((s-t)/26);return n},i=function(e,t){return l(parseInt(e))+(parseInt(t)+1)},a=function(e){const t=/^[a-zA-Z]+/.exec(e);if(t){let s=0;for(let e=0;e<t[0].length;e++)s+=parseInt(t[0].charCodeAt(e)-64)*Math.pow(26,t[0].length-1-e);s--,s<0&&(s=0);let n=parseInt(/[0-9]+$/.exec(e))||null;return n>0&&n--,[s,n]}},c=function(e){const[t,s]=e.split(":");return[...a(t),...a(s)]},d=function(e,t){t=t||",",e=e.replace(/\r?\n$|\r$|\n$/g,"");const s=[];let n=!1,o=0,r=0,l=0;for(let i=0;i<e.length;i++){const a=e[i],c=e[i+1];s[r]=s[r]||[],s[r][l]=s[r][l]||"",'"'==a&&n&&'"'==c?(s[r][l]+=a,++i):'"'!=a?a!=t||n?"\r"!=a||"\n"!=c||n?"\n"==a&&!n||"\r"==a&&!n?(++r,o=Math.max(o,l),l=0):s[r][l]+=a:(++r,o=Math.max(o,l),l=0,++i):++l:n=!n}return s.forEach(((e,t)=>{for(let t=e.length;t<=o;t++)e.push("")})),s},u=function(e,t){if("TABLE"==e.tagName){t||(t={}),t.columns=[],t.data=[];const s=e.querySelectorAll("colgroup > col");if(s.length)for(let e=0;e<s.length;e++){let n=s[e].style.width;n||(n=s[e].getAttribute("width")),n&&(t.columns[e]||(t.columns[e]={}),t.columns[e].width=n)}const o=function(e,s){let n=e.getBoundingClientRect();const o=n.width>50?n.width:50;t.columns[s]||(t.columns[s]={}),e.getAttribute("data-celltype")?t.columns[s].type=e.getAttribute("data-celltype"):t.columns[s].type="text",t.columns[s].width=o+"px",t.columns[s].title=e.innerHTML,e.style.textAlign&&(t.columns[s].align=e.style.textAlign),(n=e.getAttribute("name"))&&(t.columns[s].name=n),(n=e.getAttribute("id"))&&(t.columns[s].id=n),(n=e.getAttribute("data-mask"))&&(t.columns[s].mask=n)},r=[];let l=e.querySelectorAll(":scope > thead > tr");if(l.length){for(let e=0;e<l.length-1;e++){const t=[];for(let s=0;s<l[e].children.length;s++){const n={title:l[e].children[s].textContent,colspan:l[e].children[s].getAttribute("colspan")||1};t.push(n)}r.push(t)}l=l[l.length-1].children;for(let e=0;e<l.length;e++)o(l[e],e)}let i=0;const a={},c={},d={},u={};let p=e.querySelectorAll(":scope > tr, :scope > tbody > tr");for(let e=0;e<p.length;e++)if(t.data[i]=[],1!=t.parseTableFirstRowAsHeader||l.length||0!=e){for(let s=0;s<p[e].children.length;s++){let o=p[e].children[s].getAttribute("data-formula");o?"="!=o.substr(0,1)&&(o="="+o):o=p[e].children[s].innerHTML,t.data[i].push(o);const r=(0,n.t3)([s,e]),l=p[e].children[s].getAttribute("class");l&&(u[r]=l);const c=parseInt(p[e].children[s].getAttribute("colspan"))||0,h=parseInt(p[e].children[s].getAttribute("rowspan"))||0;(c||h)&&(a[r]=[c||1,h||1]),p[e].children[s].style&&"none"==p[e].children[s].style.display&&(p[e].children[s].style.display="");const m=p[e].children[s].getAttribute("style");m&&(d[r]=m),p[e].children[s].classList.contains("styleBold")&&(d[r]?d[r]+="; font-weight:bold;":d[r]="font-weight:bold;")}p[e].style&&p[e].style.height&&(c[e]={height:p[e].style.height}),i++}else for(let t=0;t<p[e].children.length;t++)o(p[e].children[t],t);if(Object.keys(r).length>0&&(t.nestedHeaders=r),Object.keys(d).length>0&&(t.style=d),Object.keys(a).length>0&&(t.mergeCells=a),Object.keys(c).length>0&&(t.rows=c),Object.keys(u).length>0&&(t.classes=u),p=e.querySelectorAll("tfoot tr"),p.length){const e=[];for(let t=0;t<p.length;t++){let s=[];for(let e=0;e<p[t].children.length;e++)s.push(p[t].children[e].textContent);e.push(s)}Object.keys(e).length>0&&(t.footers=e)}if(1==t.parseTableAutoCellType){const e=[];for(let s=0;s<t.columns.length;s++){let n=!0,o=!0;e[s]=[];for(let r=0;r<t.data.length;r++){const l=t.data[r][s];e[s][l]||(e[s][l]=0),e[s][l]++,l.length>25&&(n=!1),10==l.length&&"-"==l.substr(4,1)&&"-"==l.substr(7,1)||(o=!1)}const r=Object.keys(e[s]).length;o?t.columns[s].type="calendar":1==n&&r>1&&r<=parseInt(.1*t.data.length)&&(t.columns[s].type="dropdown",t.columns[s].source=Object.keys(e[s]))}}return t}console.log("Element is not a table")}},911:function(e,t,s){s.d(t,{Dh:function(){return c},ZS:function(){return h},tN:function(){return p}});var n=s(805),o=s(689),r=s(530),l=s(910),i=s(94),a=s(657);const c=function(e){const t=this;if(1!=t.ignoreHistory){const s=++t.historyIndex;t.history=t.history=t.history.slice(0,s+1),t.history[s]=e}},d=function(e,t){const s=this,n=t.insertBefore?+t.rowNumber:t.rowNumber+1;if(1==s.options.search&&s.results&&s.results.length!=s.rows.length&&s.resetSearch(),1==e){const e=t.numOfRows;for(let t=n;t<e+n;t++)s.rows[t].element.parentNode.removeChild(s.rows[t].element);s.records.splice(n,e),s.options.data.splice(n,e),s.rows.splice(n,e),a.at.call(s,1,n,e+n-1)}else{const e=t.rowRecords.map((e=>[...e]));s.records=(0,o.Hh)(s.records,n,e);const r=t.rowData.map((e=>[...e]));s.options.data=(0,o.Hh)(s.options.data,n,r),s.rows=(0,o.Hh)(s.rows,n,t.rowNode);let l=0;for(let e=n;e<t.numOfRows+n;e++)s.tbody.insertBefore(t.rowNode[l].element,s.tbody.children[e]),l++}for(let e=n;e<s.rows.length;e++)s.rows[e].y=e;for(let e=n;e<s.records.length;e++)for(let t=0;t<s.records[e].length;t++)s.records[e][t].y=e;s.options.pagination>0&&s.page(s.pageNumber),r.o8.call(s)},u=function(e,t){const s=this,n=t.insertBefore?t.columnNumber:t.columnNumber+1;if(1==e){const e=t.numOfColumns;s.options.columns.splice(n,e);for(let t=n;t<e+n;t++)s.headers[t].parentNode.removeChild(s.headers[t]),s.cols[t].colElement.parentNode.removeChild(s.cols[t].colElement);s.headers.splice(n,e),s.cols.splice(n,e);for(let o=0;o<t.data.length;o++){for(let t=n;t<e+n;t++)s.records[o][t].element.parentNode.removeChild(s.records[o][t].element);s.records[o].splice(n,e),s.options.data[o].splice(n,e)}if(s.options.footers)for(let t=0;t<s.options.footers.length;t++)s.options.footers[t].splice(n,e)}else{s.options.columns=(0,o.Hh)(s.options.columns,n,t.columns),s.headers=(0,o.Hh)(s.headers,n,t.headers),s.cols=(0,o.Hh)(s.cols,n,t.cols);let e=0;for(let o=n;o<t.numOfColumns+n;o++)s.headerContainer.insertBefore(t.headers[e],s.headerContainer.children[o+1]),s.colgroupContainer.insertBefore(t.cols[e].colElement,s.colgroupContainer.children[o+1]),e++;for(let e=0;e<t.data.length;e++){s.options.data[e]=(0,o.Hh)(s.options.data[e],n,t.data[e]),s.records[e]=(0,o.Hh)(s.records[e],n,t.records[e]);let r=0;for(let o=n;o<t.numOfColumns+n;o++)s.rows[e].element.insertBefore(t.records[e][r].element,s.rows[e].element.children[o+1]),r++}if(s.options.footers)for(let e=0;e<s.options.footers.length;e++)s.options.footers[e]=(0,o.Hh)(s.options.footers[e],n,t.footers[e])}for(let e=n;e<s.cols.length;e++)s.cols[e].x=e;for(let e=0;e<s.records.length;e++)for(let t=n;t<s.records[e].length;t++)s.records[e][t].x=t;if(s.options.nestedHeaders&&s.options.nestedHeaders.length>0&&s.options.nestedHeaders[0]&&s.options.nestedHeaders[0][0])for(let n=0;n<s.options.nestedHeaders.length;n++){let o;o=1==e?parseInt(s.options.nestedHeaders[n][s.options.nestedHeaders[n].length-1].colspan)-t.numOfColumns:parseInt(s.options.nestedHeaders[n][s.options.nestedHeaders[n].length-1].colspan)+t.numOfColumns,s.options.nestedHeaders[n][s.options.nestedHeaders[n].length-1].colspan=o,s.thead.children[n].children[s.thead.children[n].children.length-1].setAttribute("colspan",o)}r.o8.call(s)},p=function(){const e=this,t=!!e.parent.ignoreEvents,s=!!e.ignoreHistory;e.parent.ignoreEvents=!0,e.ignoreHistory=!0;const o=[];let r;if(e.historyIndex>=0)if(r=e.history[e.historyIndex--],"insertRow"==r.action)d.call(e,1,r);else if("deleteRow"==r.action)d.call(e,0,r);else if("insertColumn"==r.action)u.call(e,1,r);else if("deleteColumn"==r.action)u.call(e,0,r);else if("moveRow"==r.action)e.moveRow(r.newValue,r.oldValue);else if("moveColumn"==r.action)e.moveColumn(r.newValue,r.oldValue);else if("setMerge"==r.action)e.removeMerge(r.column,r.data);else if("setStyle"==r.action)e.setStyle(r.oldValue,null,null,1);else if("setWidth"==r.action)e.setWidth(r.column,r.oldValue);else if("setHeight"==r.action)e.setHeight(r.row,r.oldValue);else if("setHeader"==r.action)e.setHeader(r.column,r.oldValue);else if("setComments"==r.action)e.setComments(r.oldValue);else if("orderBy"==r.action){let t=[];for(let e=0;e<r.rows.length;e++)t[r.rows[e]]=e;i.Th.call(e,r.column,r.order?0:1),i.iY.call(e,t)}else if("setValue"==r.action){for(let t=0;t<r.records.length;t++)o.push({x:r.records[t].x,y:r.records[t].y,value:r.records[t].oldValue}),r.oldStyle&&e.resetStyle(r.oldStyle);e.setValue(o),r.selection&&e.updateSelectionFromCoords(r.selection[0],r.selection[1],r.selection[2],r.selection[3])}e.parent.ignoreEvents=t,e.ignoreHistory=s,n.A.call(e,"onundo",e,r)},h=function(){const e=this,t=!!e.parent.ignoreEvents,s=!!e.ignoreHistory;let o;if(e.parent.ignoreEvents=!0,e.ignoreHistory=!0,e.historyIndex<e.history.length-1)if(o=e.history[++e.historyIndex],"insertRow"==o.action)d.call(e,0,o);else if("deleteRow"==o.action)d.call(e,1,o);else if("insertColumn"==o.action)u.call(e,0,o);else if("deleteColumn"==o.action)u.call(e,1,o);else if("moveRow"==o.action)e.moveRow(o.oldValue,o.newValue);else if("moveColumn"==o.action)e.moveColumn(o.oldValue,o.newValue);else if("setMerge"==o.action)l.FU.call(e,o.column,o.colspan,o.rowspan,1);else if("setStyle"==o.action)e.setStyle(o.newValue,null,null,1);else if("setWidth"==o.action)e.setWidth(o.column,o.newValue);else if("setHeight"==o.action)e.setHeight(o.row,o.newValue);else if("setHeader"==o.action)e.setHeader(o.column,o.newValue);else if("setComments"==o.action)e.setComments(o.newValue);else if("orderBy"==o.action)i.Th.call(e,o.column,o.order),i.iY.call(e,o.rows);else if("setValue"==o.action){e.setValue(o.records);for(let t=0;t<o.records.length;t++)o.oldStyle&&e.resetStyle(o.newStyle);o.selection&&e.updateSelectionFromCoords(o.selection[0],o.selection[1],o.selection[2],o.selection[3])}e.parent.ignoreEvents=t,e.ignoreHistory=s,n.A.call(e,"onredo",e,o)}},530:function(__unused_webpack_module,__webpack_exports__,__webpack_require__){__webpack_require__.d(__webpack_exports__,{$O:function(){return getWorksheetActive},$x:function(){return parseValue},C6:function(){return showIndex},Em:function(){return executeFormula},P9:function(){return createCell},Rs:function(){return updateScroll},TI:function(){return hideIndex},Xr:function(){return getCellFromCoords},Y5:function(){return fullscreen},am:function(){return updateTable},dw:function(){return isFormula},eN:function(){return getWorksheetInstance},hG:function(){return updateResult},ju:function(){return createNestedHeader},k9:function(){return updateCell},o8:function(){return updateTableReferences},p9:function(){return getLabel},rS:function(){return getMask},tT:function(){return getCell},xF:function(){return updateFormulaChain},yB:function(){return updateFormula}});var _dispatch_js__WEBPACK_IMPORTED_MODULE_3__=__webpack_require__(805),_selection_js__WEBPACK_IMPORTED_MODULE_1__=__webpack_require__(657),_helpers_js__WEBPACK_IMPORTED_MODULE_4__=__webpack_require__(978),_meta_js__WEBPACK_IMPORTED_MODULE_5__=__webpack_require__(654),_freeze_js__WEBPACK_IMPORTED_MODULE_6__=__webpack_require__(296),_pagination_js__WEBPACK_IMPORTED_MODULE_7__=__webpack_require__(167),_footer_js__WEBPACK_IMPORTED_MODULE_0__=__webpack_require__(160),_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__=__webpack_require__(689);const updateTable=function(){const e=this;if(e.options.minSpareRows>0){let t=0;for(let s=e.rows.length-1;s>=0;s--){let n=!1;for(let t=0;t<e.headers.length;t++)e.options.data[s][t]&&(n=!0);if(n)break;t++}e.options.minSpareRows-t>0&&e.insertRow(e.options.minSpareRows-t)}if(e.options.minSpareCols>0){let t=0;for(let s=e.headers.length-1;s>=0;s--){let n=!1;for(let t=0;t<e.rows.length;t++)e.options.data[t][s]&&(n=!0);if(n)break;t++}e.options.minSpareCols-t>0&&e.insertColumn(e.options.minSpareCols-t)}e.options.footers&&_footer_js__WEBPACK_IMPORTED_MODULE_0__.e.call(e),setTimeout((function(){_selection_js__WEBPACK_IMPORTED_MODULE_1__.Aq.call(e)}),0)},parseNumber=function(e,t){const s=t&&this.options.columns[t].decimal?this.options.columns[t].decimal:".";let n=""+e;return n=n.split(s),n[0]=n[0].match(/[+-]?[0-9]/g),n[0]&&(n[0]=n[0].join("")),n[1]&&(n[1]=n[1].match(/[0-9]*/g).join("")),n[0]&&Number.isInteger(Number(n[0]))?n[1]?Number(n[0]+"."+n[1]):Number(n[0]+".00"):null},executeFormula=function(expression,x,y){const obj=this,formulaResults=[],formulaLoopProtection=[],execute=function(expression,x,y){const parentId=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.t3)([x,y]);if(formulaLoopProtection[parentId])return console.error("Reference loop detected"),"#ERROR";formulaLoopProtection[parentId]=!0;const tokensUpdate=function(e){for(let t=0;t<e.length;t++){const s=[],n=e[t].split(":"),o=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.vu)(n[0],!0),r=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.vu)(n[1],!0);let l,i,a,c;o[0]<=r[0]?(l=o[0],i=r[0]):(l=r[0],i=o[0]),o[1]<=r[1]?(a=o[1],c=r[1]):(a=r[1],c=o[1]);for(let e=a;e<=c;e++)for(let t=l;t<=i;t++)s.push((0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.t3)([t,e]));expression=expression.replace(e[t],s.join(","))}};expression=expression.replace(/\$?([A-Z]+)\$?([0-9]+)/g,"$1$2");let tokens=expression.match(/([A-Z]+[0-9]+)\:([A-Z]+[0-9]+)/g);if(tokens&&tokens.length&&tokensUpdate(tokens),tokens=expression.match(/([A-Z]+[0-9]+)/g),tokens&&tokens.indexOf(parentId)>-1)return console.error("Self Reference detected"),"#ERROR";{const formulaExpressions={};if(tokens)for(let i=0;i<tokens.length;i++)if(obj.formula[tokens[i]]||(obj.formula[tokens[i]]=[]),obj.formula[tokens[i]].indexOf(parentId)<0&&obj.formula[tokens[i]].push(parentId),eval("typeof("+tokens[i]+') == "undefined"')){const e=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.vu)(tokens[i],1);let t;if(t=void 0!==obj.options.data[e[1]]&&void 0!==obj.options.data[e[1]][e[0]]?obj.options.data[e[1]][e[0]]:"","="==(""+t).substr(0,1)&&(void 0!==formulaResults[tokens[i]]?t=formulaResults[tokens[i]]:(t=execute(t,e[0],e[1]),formulaResults[tokens[i]]=t)),""==(""+t).trim())formulaExpressions[tokens[i]]=null;else if(t==Number(t)&&0!=obj.parent.config.autoCasting)formulaExpressions[tokens[i]]=Number(t);else{const s=parseNumber.call(obj,t,e[0]);0!=obj.parent.config.autoCasting&&s?formulaExpressions[tokens[i]]=s:formulaExpressions[tokens[i]]='"'+t+'"'}}const ret=_dispatch_js__WEBPACK_IMPORTED_MODULE_3__.A.call(obj,"onbeforeformula",obj,expression,x,y);if(!1===ret)return expression;let res;ret&&(expression=ret);try{res=formula(expression.substr(1),formulaExpressions,x,y,obj),"function"==typeof res&&(res="#ERROR")}catch(e){res="#ERROR",!0===obj.parent.config.debugFormulas&&console.log(expression.substr(1),formulaExpressions,e)}return res}};return execute(expression,x,y)},parseValue=function(e,t,s,n){const o=this;"="==(""+s).substr(0,1)&&0!=o.parent.config.parseFormulas&&(s=executeFormula.call(o,s,e,t));const r=o.options.columns&&o.options.columns[e];if(r&&!isFormula(s)){let e=null;if(e=getMask(r)){s&&s==Number(s)&&(s=Number(s));let t=jSuites.mask.render(s,e,!0);if(n&&e.mask){const o=e.mask.split(";");o[1]&&(o[1].match(new RegExp("\\[Red\\]","gi"))&&(s<0?n.classList.add("red"):n.classList.remove("red")),o[1].match(new RegExp("\\(","gi"))&&s<0&&(t="("+t+")"))}t&&(s=t)}}return s},getDropDownValue=function(e,t){const s=this,n=[];if(s.options.columns&&s.options.columns[e]&&s.options.columns[e].source){const o=[],r=s.options.columns[e].source;for(let e=0;e<r.length;e++)"object"==typeof r[e]?o[r[e].id]=r[e].name:o[r[e]]=r[e];const l=Array.isArray(t)?t:(""+t).split(";");for(let e=0;e<l.length;e++)"object"==typeof l[e]?n.push(o[l[e].id]):o[l[e]]&&n.push(o[l[e]])}else console.error("Invalid column");return n.length>0?n.join("; "):""},validDate=function(e){return"-"==(e=""+e).substr(4,1)&&"-"==e.substr(7,1)||4==(e=e.split("-"))[0].length&&e[0]==Number(e[0])&&2==e[1].length&&e[1]==Number(e[1])},stripScript=function(e){const t=new Option;t.innerHTML=e;let s=null;for(e=t.getElementsByTagName("script");s=e[0];)s.parentNode.removeChild(s);return t.innerHTML},createCell=function(e,t,s){const n=this;let o=document.createElement("td");if(o.setAttribute("data-x",e),o.setAttribute("data-y",t),"none"===n.headers[e].style.display&&(o.style.display="none"),"="==(""+s).substr(0,1)&&1==n.options.secureFormulas){const e=secureFormula(s);e!=s&&(s=e)}if(n.options.columns&&n.options.columns[e]&&"object"==typeof n.options.columns[e].type)!0===n.parent.config.parseHTML?o.innerHTML=s:o.textContent=s,"function"==typeof n.options.columns[e].type.createCell&&n.options.columns[e].type.createCell(o,s,parseInt(e),parseInt(t),n,n.options.columns[e]);else if(n.options.columns&&n.options.columns[e]&&"hidden"==n.options.columns[e].type)o.style.display="none",o.textContent=s;else if(n.options.columns&&n.options.columns[e]&&("checkbox"==n.options.columns[e].type||"radio"==n.options.columns[e].type)){const r=document.createElement("input");r.type=n.options.columns[e].type,r.name="c"+e,r.checked=1==s||1==s||"true"==s,r.onclick=function(){n.setValue(o,this.checked)},1!=n.options.columns[e].readOnly&&0!=n.options.editable||r.setAttribute("disabled","disabled"),o.appendChild(r),n.options.data[t][e]=r.checked}else if(n.options.columns&&n.options.columns[e]&&"calendar"==n.options.columns[e].type){let t=null;if(!validDate(s)){const o=jSuites.calendar.extractDateFromString(s,n.options.columns[e].options&&n.options.columns[e].options.format||"YYYY-MM-DD");o&&(t=o)}o.textContent=jSuites.calendar.getDateString(t||s,n.options.columns[e].options&&n.options.columns[e].options.format)}else if(n.options.columns&&n.options.columns[e]&&"dropdown"==n.options.columns[e].type)o.classList.add("jss_dropdown"),o.textContent=getDropDownValue.call(n,e,s);else if(n.options.columns&&n.options.columns[e]&&"color"==n.options.columns[e].type)if("square"==n.options.columns[e].render){const e=document.createElement("div");e.className="color",e.style.backgroundColor=s,o.appendChild(e)}else o.style.color=s,o.textContent=s;else if(n.options.columns&&n.options.columns[e]&&"image"==n.options.columns[e].type){if(s&&"data:image"==s.substr(0,10)){const e=document.createElement("img");e.src=s,o.appendChild(e)}}else n.options.columns&&n.options.columns[e]&&"html"==n.options.columns[e].type||!0===n.parent.config.parseHTML?o.innerHTML=stripScript(parseValue.call(this,e,t,s,o)):o.textContent=parseValue.call(this,e,t,s,o);n.options.columns&&n.options.columns[e]&&1==n.options.columns[e].readOnly&&(o.className="readonly");const r=n.options.columns&&n.options.columns[e]&&n.options.columns[e].align||n.options.defaultColAlign||"center";return o.style.textAlign=r,n.options.columns&&n.options.columns[e]&&0==n.options.columns[e].wordWrap||!(1==n.options.wordWrap||n.options.columns&&n.options.columns[e]&&1==n.options.columns[e].wordWrap||o.innerHTML.length>200)||(o.style.whiteSpace="pre-wrap"),e>0&&1==this.options.textOverflow&&(s||o.innerHTML?n.records[t][e-1].element.style.overflow="hidden":e==n.options.columns.length-1&&(o.style.overflow="hidden")),_dispatch_js__WEBPACK_IMPORTED_MODULE_3__.A.call(n,"oncreatecell",n,o,e,t,s),o},updateCell=function(e,t,s,n){const o=this;let r;if(1!=o.records[t][e].element.classList.contains("readonly")||n){if("="==(""+s).substr(0,1)&&1==o.options.secureFormulas){const e=secureFormula(s);e!=s&&(s=e)}const n=_dispatch_js__WEBPACK_IMPORTED_MODULE_3__.A.call(o,"onbeforechange",o,o.records[t][e].element,e,t,s);if(null!=n&&(s=n),o.options.columns&&o.options.columns[e]&&"object"==typeof o.options.columns[e].type&&"function"==typeof o.options.columns[e].type.updateCell){const n=o.options.columns[e].type.updateCell(o.records[t][e].element,s,parseInt(e),parseInt(t),o,o.options.columns[e]);void 0!==n&&(s=n)}r={x:e,y:t,col:e,row:t,value:s,oldValue:o.options.data[t][e]};let l=o.options.columns&&o.options.columns[e]&&"object"==typeof o.options.columns[e].type?o.options.columns[e].type:null;if(l)o.options.data[t][e]=s,"function"==typeof l.setValue&&l.setValue(o.records[t][e].element,s);else if(o.options.columns&&o.options.columns[e]&&("checkbox"==o.options.columns[e].type||"radio"==o.options.columns[e].type)){if("radio"==o.options.columns[e].type)for(let t=0;t<o.options.data.length;t++)o.options.data[t][e]=!1;o.records[t][e].element.children[0].checked=1==s||1==s||"true"==s||"TRUE"==s,o.options.data[t][e]=o.records[t][e].element.children[0].checked}else if(o.options.columns&&o.options.columns[e]&&"dropdown"==o.options.columns[e].type)o.options.data[t][e]=s,o.records[t][e].element.textContent=getDropDownValue.call(o,e,s);else if(o.options.columns&&o.options.columns[e]&&"calendar"==o.options.columns[e].type){let n=null;if(!validDate(s)){const t=jSuites.calendar.extractDateFromString(s,o.options.columns[e].options&&o.options.columns[e].options.format||"YYYY-MM-DD");t&&(n=t)}o.options.data[t][e]=s,o.records[t][e].element.textContent=jSuites.calendar.getDateString(n||s,o.options.columns[e].options&&o.options.columns[e].options.format)}else if(o.options.columns&&o.options.columns[e]&&"color"==o.options.columns[e].type)if(o.options.data[t][e]=s,"square"==o.options.columns[e].render){const n=document.createElement("div");n.className="color",n.style.backgroundColor=s,o.records[t][e].element.textContent="",o.records[t][e].element.appendChild(n)}else o.records[t][e].element.style.color=s,o.records[t][e].element.textContent=s;else if(o.options.columns&&o.options.columns[e]&&"image"==o.options.columns[e].type){if(s=""+s,o.options.data[t][e]=s,o.records[t][e].element.innerHTML="",s&&"data:image"==s.substr(0,10)){const n=document.createElement("img");n.src=s,o.records[t][e].element.appendChild(n)}}else o.options.data[t][e]=s,o.options.columns&&o.options.columns[e]&&"html"==o.options.columns[e].type?o.records[t][e].element.innerHTML=stripScript(parseValue.call(o,e,t,s)):!0===o.parent.config.parseHTML?o.records[t][e].element.innerHTML=stripScript(parseValue.call(o,e,t,s,o.records[t][e].element)):o.records[t][e].element.textContent=parseValue.call(o,e,t,s,o.records[t][e].element),o.options.columns&&o.options.columns[e]&&0==o.options.columns[e].wordWrap||!(1==o.options.wordWrap||o.options.columns&&o.options.columns[e]&&1==o.options.columns[e].wordWrap||o.records[t][e].element.innerHTML.length>200)?o.records[t][e].element.style.whiteSpace="":o.records[t][e].element.style.whiteSpace="pre-wrap";e>0&&(o.records[t][e-1].element.style.overflow=s?"hidden":""),o.options.columns&&o.options.columns[e]&&"function"==typeof o.options.columns[e].render&&o.options.columns[e].render(o.records[t]&&o.records[t][e]?o.records[t][e].element:null,s,parseInt(e),parseInt(t),o,o.options.columns[e]),_dispatch_js__WEBPACK_IMPORTED_MODULE_3__.A.call(o,"onchange",o,o.records[t]&&o.records[t][e]?o.records[t][e].element:null,e,t,s,r.oldValue)}else r={x:e,y:t,col:e,row:t};return r},isFormula=function(e){const t=(""+e)[0];return"="==t||"#"==t},getMask=function(e){if(e.format||e.mask||e.locale){const t={};return e.mask?t.mask=e.mask:e.format?t.mask=e.format:(t.locale=e.locale,t.options=e.options),e.decimal&&(t.options||(t.options={}),t.options={decimal:e.decimal}),t}return null},secureFormula=function(e){let t="",s=0;for(let n=0;n<e.length;n++)'"'==e[n]&&(s=0==s?1:0),t+=1==s?e[n]:e[n].toUpperCase();return t};let chainLoopProtection=[];const updateFormulaChain=function(e,t,s){const n=this,o=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.t3)([e,t]);if(n.formula[o]&&n.formula[o].length>0)if(chainLoopProtection[o])n.records[t][e].element.innerHTML="#ERROR",n.formula[o]="";else{chainLoopProtection[o]=!0;for(let e=0;e<n.formula[o].length;e++){const t=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.vu)(n.formula[o][e],!0),r=""+n.options.data[t[1]][t[0]];"="==r.substr(0,1)?s.push(updateCell.call(n,t[0],t[1],r,!0)):Object.keys(n.formula)[e]=null,updateFormulaChain.call(n,t[0],t[1],s)}}chainLoopProtection=[]},updateFormula=function(e,t){const s=/[A-Z]/,n=/[0-9]/;let o="",r=null,l=null,i="";for(let a=0;a<e.length;a++)s.exec(e[a])?(r=1,l=0,i+=e[a]):n.exec(e[a])?(l=r?1:0,i+=e[a]):(r&&l&&(i=t[i]?t[i]:i),o+=i,o+=e[a],r=0,l=0,i="");return i&&(r&&l&&(i=t[i]?t[i]:i),o+=i),o},updateFormulas=function(e){const t=this;for(let s=0;s<t.options.data.length;s++)for(let n=0;n<t.options.data[0].length;n++){const o=""+t.options.data[s][n];if("="==o.substr(0,1)){const r=updateFormula(o,e);r!=o&&(t.options.data[s][n]=r)}}const s=[],n=Object.keys(t.formula);for(let o=0;o<n.length;o++){let r=n[o];const l=t.formula[r];e[r]&&(r=e[r]),s[r]=[];for(let t=0;t<l.length;t++){let n=l[t];e[n]&&(n=e[n]),s[r].push(n)}}t.formula=s},updateTableReferences=function(){const e=this;if(e.skipUpdateTableReferences)return;for(let t=0;t<e.headers.length;t++)e.headers[t].getAttribute("data-x")!=t&&(e.headers[t].setAttribute("data-x",t),e.headers[t].getAttribute("title")||(e.headers[t].innerHTML=(0,_helpers_js__WEBPACK_IMPORTED_MODULE_4__.getColumnName)(t)));for(let t=0;t<e.rows.length;t++)e.rows[t]&&e.rows[t].element.getAttribute("data-y")!=t&&(e.rows[t].element.setAttribute("data-y",t),e.rows[t].element.children[0].setAttribute("data-y",t),e.rows[t].element.children[0].innerHTML=t+1);const t=[],s=[],n=function(s,n,o,r){if(s!=o&&e.records[r][o].element.setAttribute("data-x",o),n!=r&&e.records[r][o].element.setAttribute("data-y",r),s!=o||n!=r){const e=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.t3)([s,n]),l=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.t3)([o,r]);t[e]=l}};for(let t=0;t<e.records.length;t++)for(let o=0;o<e.records[0].length;o++)if(e.records[t][o]){const r=e.records[t][o].element.getAttribute("data-x"),l=e.records[t][o].element.getAttribute("data-y");if(e.records[t][o].element.getAttribute("data-merged")){const e=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.t3)([r,l]),n=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.t3)([o,t]);if(null==s[e])if(e==n)s[e]=!1;else{const i=parseInt(o-r),a=parseInt(t-l);s[e]=[n,i,a]}}else n(r,l,o,t)}const o=Object.keys(s);if(o.length)for(let t=0;t<o.length;t++)if(s[o[t]]){const r=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.vu)(o[t],!0);let l=r[0],i=r[1];n(l,i,l+s[o[t]][1],i+s[o[t]][2]);const a=o[t],c=s[o[t]][0];for(let n=0;n<e.options.mergeCells[a][2].length;n++)l=parseInt(e.options.mergeCells[a][2][n].getAttribute("data-x")),i=parseInt(e.options.mergeCells[a][2][n].getAttribute("data-y")),e.options.mergeCells[a][2][n].setAttribute("data-x",l+s[o[t]][1]),e.options.mergeCells[a][2][n].setAttribute("data-y",i+s[o[t]][2]);e.options.mergeCells[c]=e.options.mergeCells[a],delete e.options.mergeCells[a]}updateFormulas.call(e,t),_meta_js__WEBPACK_IMPORTED_MODULE_5__.hs.call(e,t),_selection_js__WEBPACK_IMPORTED_MODULE_1__.G9.call(e),updateTable.call(e)},updateScroll=function(e){const t=this,s=t.content.getBoundingClientRect(),n=s.left,o=s.top,r=s.width,l=s.height,i=t.records[t.selectedCell[3]][t.selectedCell[2]].element.getBoundingClientRect(),a=i.left,c=i.top,d=i.width,u=i.height;let p,h;0==e||1==e?(p=a-n+t.content.scrollLeft,h=c-o+t.content.scrollTop-2):(p=a-n+t.content.scrollLeft+d,h=c-o+t.content.scrollTop+u),h>t.content.scrollTop+30&&h<t.content.scrollTop+l||(h<t.content.scrollTop+30?t.content.scrollTop=h-u:t.content.scrollTop=h-(l-2));const m=_freeze_js__WEBPACK_IMPORTED_MODULE_6__.w.call(t);p>t.content.scrollLeft+m&&p<t.content.scrollLeft+r||(p<t.content.scrollLeft+30?(t.content.scrollLeft=p,t.content.scrollLeft<50&&(t.content.scrollLeft=0)):p<t.content.scrollLeft+m?t.content.scrollLeft=p-m-1:t.content.scrollLeft=p-(r-20))},updateResult=function(){const e=this;let t=0,s=0;for(t=1==e.options.lazyLoading?100:e.options.pagination>0?e.options.pagination:e.results?e.results.length:e.rows.length;e.tbody.firstChild;)e.tbody.removeChild(e.tbody.firstChild);for(let n=0;n<e.rows.length;n++)!e.results||e.results.indexOf(n)>-1?(s<t&&(e.tbody.appendChild(e.rows[n].element),s++),e.rows[n].element.style.display=""):e.rows[n].element.style.display="none";return e.options.pagination>0&&_pagination_js__WEBPACK_IMPORTED_MODULE_7__.IV.call(e),_selection_js__WEBPACK_IMPORTED_MODULE_1__.Aq.call(e),t},getCell=function(e,t){if("string"==typeof e){const s=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.vu)(e,!0);e=s[0],t=s[1]}return this.records[t][e].element},getCellFromCoords=function(e,t){return this.records[t][e].element},getLabel=function(e,t){if("string"==typeof e){const s=(0,_internalHelpers_js__WEBPACK_IMPORTED_MODULE_2__.vu)(e,!0);e=s[0],t=s[1]}return this.records[t][e].element.innerHTML},fullscreen=function(e){const t=this;null==e&&(e=!t.config.fullscreen),t.config.fullscreen!=e&&(t.config.fullscreen=e,1==e?t.element.classList.add("fullscreen"):t.element.classList.remove("fullscreen"))},showIndex=function(){this.table.classList.remove("jss_hidden_index")},hideIndex=function(){this.table.classList.add("jss_hidden_index")},createNestedHeader=function(e){const t=this,s=document.createElement("tr");s.classList.add("jss_nested");const n=document.createElement("td");n.classList.add("jss_selectall"),s.appendChild(n),e.element=s;let o=0;for(let n=0;n<e.length;n++){e[n].colspan||(e[n].colspan=1),e[n].title||(e[n].title=""),e[n].id||(e[n].id="");let r=e[n].colspan;const l=[];for(let e=0;e<r;e++)t.options.columns[o]&&"hidden"==t.options.columns[o].type&&r++,l.push(o),o++;const i=document.createElement("td");i.setAttribute("data-column",l.join(",")),i.setAttribute("colspan",e[n].colspan),i.setAttribute("align",e[n].align||"center"),i.setAttribute("id",e[n].id),i.textContent=e[n].title,s.appendChild(i)}return s},getWorksheetActive=function(){const e=this.parent?this.parent:this;return e.element.tabs?e.element.tabs.getActive():0},getWorksheetInstance=function(e){const t=void 0!==e?e:getWorksheetActive.call(this);return this.worksheets[t]}},689:function(e,t,s){s.d(t,{Hh:function(){return o},t3:function(){return l},vu:function(){return r}});var n=s(978);const o=function(e,t,s){if(t<=e.length)return e.slice(0,t).concat(s).concat(e.slice(t));const n=e.slice(0,e.length);for(;t>n.length;)n.push(void 0);return n.concat(s)},r=function(e,t){const s=/^[a-zA-Z]+/.exec(e);if(s){let n=0;for(let e=0;e<s[0].length;e++)n+=parseInt(s[0].charCodeAt(e)-64)*Math.pow(26,s[0].length-1-e);n--,n<0&&(n=0);let o=parseInt(/[0-9]+$/.exec(e));o>0&&o--,e=1==t?[n,o]:n+"-"+o}return e},l=function(e){return Array.isArray(e)||(e=e.split("-")),(0,n.getColumnName)(parseInt(e[0]))+(parseInt(e[1])+1)}},497:function(e,t,s){s.d(t,{AG:function(){return o},G_:function(){return r},p6:function(){return l},wu:function(){return n}});const n=function(e){const t=this;let s;s=1!=t.options.search&&1!=t.options.filters||!t.results?t.rows:t.results;const n=100;null!=e&&-1!=e||(e=Math.ceil(s.length/n)-1);let o=e*n,r=e*n+n;r>s.length&&(r=s.length),o=r-100,o<0&&(o=0);for(let e=o;e<r;e++)1!=t.options.search&&1!=t.options.filters||!t.results?t.tbody.appendChild(t.rows[e].element):t.tbody.appendChild(t.rows[s[e]].element),t.tbody.children.length>n&&t.tbody.removeChild(t.tbody.firstChild)},o=function(){const e=this;if(e.selectedCell){const t=parseInt(e.tbody.firstChild.getAttribute("data-y"))/100,s=parseInt(e.selectedCell[3]/100),n=parseInt(e.rows.length/100);if(t!=s&&s<=n&&!Array.prototype.indexOf.call(e.tbody.children,e.rows[e.selectedCell[3]].element))return e.loadPage(s),!0}return!1},r=function(){const e=this;let t;t=1!=e.options.search&&1!=e.options.filters||!e.results?e.rows:e.results;let s=0;if(t.length>100){let n=parseInt(e.tbody.firstChild.getAttribute("data-y"));if(1!=e.options.search&&1!=e.options.filters||!e.results||(n=t.indexOf(n)),n>0)for(let o=0;o<30;o++)n-=1,n>-1&&(1!=e.options.search&&1!=e.options.filters||!e.results?e.tbody.insertBefore(e.rows[n].element,e.tbody.firstChild):e.tbody.insertBefore(e.rows[t[n]].element,e.tbody.firstChild),e.tbody.children.length>100&&(e.tbody.removeChild(e.tbody.lastChild),s=1))}return s},l=function(){const e=this;let t;t=1!=e.options.search&&1!=e.options.filters||!e.results?e.rows:e.results;let s=0;if(t.length>100){let n=parseInt(e.tbody.lastChild.getAttribute("data-y"));if(1!=e.options.search&&1!=e.options.filters||!e.results||(n=t.indexOf(n)),n<e.rows.length-1)for(let o=0;o<=30;o++)n<t.length&&(1!=e.options.search&&1!=e.options.filters||!e.results?e.tbody.appendChild(e.rows[n].element):e.tbody.appendChild(e.rows[t[n]].element),e.tbody.children.length>100&&(e.tbody.removeChild(e.tbody.firstChild),s=1)),n+=1}return s}},910:function(e,t,s){s.d(t,{D0:function(){return c},FU:function(){return u},Lt:function(){return a},VP:function(){return h},Zp:function(){return p},fd:function(){return d}});var n=s(689),o=s(530),r=s(911),l=s(805),i=s(657);const a=function(e,t){const s=this,o=[];if(s.options.mergeCells){const r=Object.keys(s.options.mergeCells);for(let l=0;l<r.length;l++){const i=(0,n.vu)(r[l],!0),a=s.options.mergeCells[r[l]][0],c=i[0],d=i[0]+(a>1?a-1:0);null==t?c<=e&&d>=e&&o.push(r[l]):t?c<e&&d>=e&&o.push(r[l]):c<=e&&d>e&&o.push(r[l])}}return o},c=function(e,t){const s=this,o=[];if(s.options.mergeCells){const r=Object.keys(s.options.mergeCells);for(let l=0;l<r.length;l++){const i=(0,n.vu)(r[l],!0),a=s.options.mergeCells[r[l]][1],c=i[1],d=i[1]+(a>1?a-1:0);null==t?c<=e&&d>=e&&o.push(r[l]):t?c<e&&d>=e&&o.push(r[l]):c<=e&&d>e&&o.push(r[l])}}return o},d=function(e){const t=this;let s={};if(e)s=t.options.mergeCells&&t.options.mergeCells[e]?[t.options.mergeCells[e][0],t.options.mergeCells[e][1]]:null;else if(t.options.mergeCells){t.options.mergeCells;const e=Object.keys(t.options.mergeCells);for(let n=0;n<e.length;n++)s[e[n]]=[t.options.mergeCells[e[n]][0],t.options.mergeCells[e[n]][1]]}return s},u=function(e,t,s,a){const c=this;let d=!1;if(e){if("string"!=typeof e)return null}else{if(!c.highlighted.length)return alert(jSuites.translate("No cells selected")),null;{const o=parseInt(c.highlighted[0].getAttribute("data-x")),r=parseInt(c.highlighted[0].getAttribute("data-y")),l=parseInt(c.highlighted[c.highlighted.length-1].getAttribute("data-x")),i=parseInt(c.highlighted[c.highlighted.length-1].getAttribute("data-y"));e=(0,n.t3)([o,r]),t=l-o+1,s=i-r+1}}const u=(0,n.vu)(e,!0);if(c.options.mergeCells&&c.options.mergeCells[e])c.records[u[1]][u[0]].element.getAttribute("data-merged")&&(d="Cell already merged");else if((!t||t<2)&&(!s||s<2))d="Invalid merged properties";else for(let e=u[1];e<u[1]+s;e++)for(let s=u[0];s<u[0]+t;s++)(0,n.t3)([s,e]),c.records[e][s].element.getAttribute("data-merged")&&(d="There is a conflict with another merged cell");if(d)alert(jSuites.translate(d));else{t>1?c.records[u[1]][u[0]].element.setAttribute("colspan",t):t=1,s>1?c.records[u[1]][u[0]].element.setAttribute("rowspan",s):s=1,c.options.mergeCells||(c.options.mergeCells={}),c.options.mergeCells[e]=[t,s,[]],c.records[u[1]][u[0]].element.setAttribute("data-merged","true"),c.records[u[1]][u[0]].element.style.overflow="hidden";const n=[];for(let r=u[1];r<u[1]+s;r++)for(let s=u[0];s<u[0]+t;s++)u[0]==s&&u[1]==r||(n.push(c.options.data[r][s]),o.k9.call(c,s,r,"",!0),c.options.mergeCells[e][2].push(c.records[r][s].element),c.records[r][s].element.style.display="none",c.records[r][s].element=c.records[u[1]][u[0]].element);i.c6.call(c,c.records[u[1]][u[0]].element),a||(r.Dh.call(c,{action:"setMerge",column:e,colspan:t,rowspan:s,data:n}),l.A.call(c,"onmerge",c,{[e]:[t,s]}))}},p=function(e,t,s){const r=this;if(r.options.mergeCells&&r.options.mergeCells[e]){const l=(0,n.vu)(e,!0);r.records[l[1]][l[0]].element.removeAttribute("colspan"),r.records[l[1]][l[0]].element.removeAttribute("rowspan"),r.records[l[1]][l[0]].element.removeAttribute("data-merged");const a=r.options.mergeCells[e];let c,d,u=0;for(c=0;c<a[1];c++)for(d=0;d<a[0];d++)(c>0||d>0)&&(r.records[l[1]+c][l[0]+d].element=a[2][u],r.records[l[1]+c][l[0]+d].element.style.display="",t&&t[u]&&o.k9.call(r,l[0]+d,l[1]+c,t[u]),u++);i.c6.call(r,r.records[l[1]][l[0]].element,r.records[l[1]+c-1][l[0]+d-1].element),s||delete r.options.mergeCells[e]}},h=function(e){const t=this;if(t.options.mergeCells){t.options.mergeCells;const s=Object.keys(t.options.mergeCells);for(let n=0;n<s.length;n++)p.call(t,s[n],null,e)}}},654:function(e,t,s){s.d(t,{IQ:function(){return o},hs:function(){return r},iZ:function(){return l}});var n=s(805);const o=function(e,t){const s=this;return e?t?s.options.meta&&s.options.meta[e]&&s.options.meta[e][t]?s.options.meta[e][t]:null:s.options.meta&&s.options.meta[e]?s.options.meta[e]:null:s.options.meta},r=function(e){const t=this;if(t.options.meta){const s={},n=Object.keys(t.options.meta);for(let o=0;o<n.length;o++)e[n[o]]?s[e[n[o]]]=t.options.meta[n[o]]:s[n[o]]=t.options.meta[n[o]];t.options.meta=s}},l=function(e,t,s){const o=this;if(o.options.meta||(o.options.meta={}),t&&s)o.options.meta[e]||(o.options.meta[e]={}),o.options.meta[e][t]=s,n.A.call(o,"onchangemeta",o,{[e]:{[t]:s}});else{const t=Object.keys(e);for(let s=0;s<t.length;s++){o.options.meta[t[s]]||(o.options.meta[t[s]]={});const n=Object.keys(e[t[s]]);for(let r=0;r<n.length;r++)o.options.meta[t[s]][n[r]]=e[t[s]][n[r]]}n.A.call(o,"onchangemeta",o,e)}}},94:function(e,t,s){s.d(t,{My:function(){return d},Th:function(){return a},iY:function(){return c}});var n=s(911),o=s(805),r=s(530),l=s(497),i=s(829);const a=function(e,t){const s=this;for(let e=0;e<s.headers.length;e++)s.headers[e].classList.remove("arrow-up"),s.headers[e].classList.remove("arrow-down");t?s.headers[e].classList.add("arrow-up"):s.headers[e].classList.add("arrow-down")},c=function(e){const t=this;let s=[];for(let n=0;n<e.length;n++)s[n]=t.options.data[e[n]];t.options.data=s,s=[];for(let n=0;n<e.length;n++){s[n]=t.records[e[n]];for(let e=0;e<s[n].length;e++)s[n][e].y=n}t.records=s,s=[];for(let n=0;n<e.length;n++)s[n]=t.rows[e[n]],s[n].y=n;if(t.rows=s,r.o8.call(t),t.results&&t.results.length)t.searchInput.value?t.search(t.searchInput.value):i.F8.call(t);else if(t.results=null,t.pageNumber=0,t.options.pagination>0)t.page(0);else if(1==t.options.lazyLoading)l.wu.call(t,0);else for(let e=0;e<t.rows.length;e++)t.tbody.appendChild(t.rows[e].element)},d=function(e,t){const s=this;if(e>=0){if(s.options.mergeCells&&Object.keys(s.options.mergeCells).length>0){if(!confirm(jSuites.translate("This action will destroy any existing merged cells. Are you sure?")))return!1;s.destroyMerge()}t=null==t?s.headers[e].classList.contains("arrow-down")?1:0:t?1:0;let r=[];if(s.options.columns&&s.options.columns[e]&&("number"==s.options.columns[e].type||"numeric"==s.options.columns[e].type||"percentage"==s.options.columns[e].type||"autonumber"==s.options.columns[e].type||"color"==s.options.columns[e].type))for(let t=0;t<s.options.data.length;t++)r[t]=[t,Number(s.options.data[t][e])];else if(s.options.columns&&s.options.columns[e]&&("calendar"==s.options.columns[e].type||"checkbox"==s.options.columns[e].type||"radio"==s.options.columns[e].type))for(let t=0;t<s.options.data.length;t++)r[t]=[t,s.options.data[t][e]];else for(let t=0;t<s.options.data.length;t++)r[t]=[t,s.records[t][e].element.textContent.toLowerCase()];"function"!=typeof s.parent.config.sorting&&(s.parent.config.sorting=function(e){return function(t,s){const n=t[1],o=s[1];return e?""===n&&""!==o?1:""!==n&&""===o||n>o?-1:n<o?1:0:""===n&&""!==o?1:""!==n&&""===o?-1:n>o?1:n<o?-1:0}}),r=r.sort(s.parent.config.sorting(t));const l=[];for(let e=0;e<r.length;e++)l[e]=r[e][0];return n.Dh.call(s,{action:"orderBy",rows:l,column:e,order:t}),a.call(s,e,t),c.call(s,l),o.A.call(s,"onsort",s,e,t,l.map((e=>e))),!0}}},167:function(e,t,s){s.d(t,{$f:function(){return a},IV:function(){return l},MY:function(){return i},ho:function(){return r}});var n=s(805),o=s(657);const r=function(e){const t=this;return 1!=t.options.search&&1!=t.options.filters||!t.results||(e=t.results.indexOf(e)),Math.ceil((parseInt(e)+1)/parseInt(t.options.pagination))-1},l=function(){const e=this;if(e.pagination.children[0].innerHTML="",e.pagination.children[1].innerHTML="",e.options.pagination){let t;if(t=1!=e.options.search&&1!=e.options.filters||!e.results?e.rows.length:e.results.length,t){const s=Math.ceil(t/e.options.pagination);let n,o;if(e.pageNumber<6?(n=1,o=s<10?s:10):s-e.pageNumber<5?(n=s-9,o=s,n<1&&(n=1)):(n=e.pageNumber-4,o=e.pageNumber+5),n>1){const t=document.createElement("div");t.className="jss_page",t.innerHTML="<",t.title=1,e.pagination.children[1].appendChild(t)}for(let t=n;t<=o;t++){const s=document.createElement("div");s.className="jss_page",s.innerHTML=t,e.pagination.children[1].appendChild(s),e.pageNumber==t-1&&s.classList.add("jss_page_selected")}if(o<s){const t=document.createElement("div");t.className="jss_page",t.innerHTML=">",t.title=s,e.pagination.children[1].appendChild(t)}const r=function(e){const t=Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,(function(e,s){return void 0!==t[s]?t[s]:e}))};e.pagination.children[0].innerHTML=r(jSuites.translate("Showing page {0} of {1} entries"),e.pageNumber+1,s)}else e.pagination.children[0].innerHTML=jSuites.translate("No records found")}},i=function(e){const t=this,s=t.pageNumber;let r;r=1!=t.options.search&&1!=t.options.filters||!t.results?t.rows:t.results;const i=parseInt(t.options.pagination);null!=e&&-1!=e||(e=Math.ceil(r.length/i)-1),t.pageNumber=e;let a=e*i,c=e*i+i;for(c>r.length&&(c=r.length),a<0&&(a=0);t.tbody.firstChild;)t.tbody.removeChild(t.tbody.firstChild);for(let e=a;e<c;e++)1!=t.options.search&&1!=t.options.filters||!t.results?t.tbody.appendChild(t.rows[e].element):t.tbody.appendChild(t.rows[r[e]].element);t.options.pagination>0&&l.call(t),o.Aq.call(t),n.A.call(t,"onchangepage",t,e,s,t.options.pagination)},a=function(){const e=this;let t;return t=1!=e.options.search&&1!=e.options.filters||!e.results?e.rows.length:e.results.length,Math.ceil(t/e.options.pagination)}},657:function(e,t,s){s.d(t,{AH:function(){return m},Aq:function(){return d},G9:function(){return g},Jg:function(){return f},Lo:function(){return v},R5:function(){return _},Ub:function(){return B},at:function(){return w},c6:function(){return p},eO:function(){return x},ef:function(){return A},gE:function(){return u},gG:function(){return y},kA:function(){return h},kF:function(){return C},kV:function(){return k},sp:function(){return E},tW:function(){return j}});var n=s(805),o=s(296),r=s(978),l=s(911),i=s(530),a=s(689),c=s(392);const d=function(){const e=this;if(e.highlighted&&e.highlighted.length){const t=e.highlighted[e.highlighted.length-1].element,s=t.getAttribute("data-x"),n=e.content.getBoundingClientRect(),r=n.left,l=n.top,i=t.getBoundingClientRect(),a=i.left,c=i.top,d=i.width,u=i.height,p=a-r+e.content.scrollLeft+d-4,h=c-l+e.content.scrollTop+u-4;if(e.corner.style.top=h+"px",e.corner.style.left=p+"px",e.options.freezeColumns){const t=o.w.call(e);s>e.options.freezeColumns-1&&a-r+d<t?e.corner.style.display="none":0!=e.options.selectionCopy&&(e.corner.style.display="")}else 0!=e.options.selectionCopy&&(e.corner.style.display="")}else e.corner.style.top="-2000px",e.corner.style.left="-2000px";(0,c.nK)(e)},u=function(e){const t=this;let s;if(t.highlighted&&t.highlighted.length){s=1;for(let e=0;e<t.highlighted.length;e++){t.highlighted[e].element.classList.remove("highlight"),t.highlighted[e].element.classList.remove("highlight-left"),t.highlighted[e].element.classList.remove("highlight-right"),t.highlighted[e].element.classList.remove("highlight-top"),t.highlighted[e].element.classList.remove("highlight-bottom"),t.highlighted[e].element.classList.remove("highlight-selected");const s=parseInt(t.highlighted[e].element.getAttribute("data-x")),n=parseInt(t.highlighted[e].element.getAttribute("data-y"));let o,r;if(t.highlighted[e].element.getAttribute("data-merged")){const l=parseInt(t.highlighted[e].element.getAttribute("colspan")),i=parseInt(t.highlighted[e].element.getAttribute("rowspan"));o=l>0?s+(l-1):s,r=i>0?n+(i-1):n}else o=s,r=n;for(let e=s;e<=o;e++)t.headers[e]&&t.headers[e].classList.remove("selected");for(let e=n;e<=r;e++)t.rows[e]&&t.rows[e].element.classList.remove("selected")}}else s=0;return t.highlighted=[],t.selectedCell=null,t.corner.style.top="-2000px",t.corner.style.left="-2000px",1==e&&1==s&&n.A.call(t,"onblur",t),s},p=function(e,t,s){const n=e.getAttribute("data-x"),o=e.getAttribute("data-y");let r,l;t?(r=t.getAttribute("data-x"),l=t.getAttribute("data-y")):(r=n,l=o),m.call(this,n,o,r,l,s)},h=function(){const e=document.querySelectorAll(".jss_worksheet .copying");for(let t=0;t<e.length;t++)e[t].classList.remove("copying"),e[t].classList.remove("copying-left"),e[t].classList.remove("copying-right"),e[t].classList.remove("copying-top"),e[t].classList.remove("copying-bottom")},m=function(e,t,s,o,r){const l=this;if(null==t){if(t=0,o=l.rows.length-1,null==e)return}else null==e&&(e=0,s=l.options.data[0].length-1);null==s&&(s=e),null==o&&(o=t),e>=l.headers.length&&(e=l.headers.length-1),t>=l.rows.length&&(t=l.rows.length-1),s>=l.headers.length&&(s=l.headers.length-1),o>=l.rows.length&&(o=l.rows.length-1);let i,a,c,u,p=null,m=null,f=null,g=null;parseInt(e)<parseInt(s)?(i=parseInt(e),a=parseInt(s)):(i=parseInt(s),a=parseInt(e)),parseInt(t)<parseInt(o)?(c=parseInt(t),u=parseInt(o)):(c=parseInt(o),u=parseInt(t));for(let e=i;e<=a;e++)for(let t=c;t<=u;t++)if(l.records[t][e]&&l.records[t][e].element.getAttribute("data-merged")){const s=parseInt(l.records[t][e].element.getAttribute("data-x")),n=parseInt(l.records[t][e].element.getAttribute("data-y")),o=parseInt(l.records[t][e].element.getAttribute("colspan")),r=parseInt(l.records[t][e].element.getAttribute("rowspan"));o>1&&(s<i&&(i=s),s+o>a&&(a=s+o-1)),r&&(n<c&&(c=n),n+r>u&&(u=n+r-1))}for(let e=c;e<=u;e++)"none"!=l.rows[e].element.style.display&&(null==f&&(f=e),g=e);for(let e=i;e<=a;e++)for(let t=c;t<=u;t++)l.options.columns&&l.options.columns[e]&&"hidden"==l.options.columns[e].type||(null==p&&(p=e),m=e);if(p||(p=0),m||(m=0),!1===n.A.call(l,"onbeforeselection",l,p,f,m,g,r))return!1;const y=l.resetSelection();l.selectedCell=[e,t,s,o],l.records[t][e]&&l.records[t][e].element.classList.add("highlight-selected");for(let e=i;e<=a;e++)for(let t=c;t<=u;t++)"none"!=l.rows[t].element.style.display&&"none"!=l.records[t][e].element.style.display&&(l.records[t][e].element.classList.add("highlight"),l.highlighted.push(l.records[t][e]));for(let e=p;e<=m;e++)l.options.columns&&l.options.columns[e]&&"hidden"==l.options.columns[e].type||!l.cols[e].colElement.style||"none"==l.cols[e].colElement.style.display||(l.records[f]&&l.records[f][e]&&l.records[f][e].element.classList.add("highlight-top"),l.records[g]&&l.records[g][e]&&l.records[g][e].element.classList.add("highlight-bottom"),l.headers[e].classList.add("selected"));for(let e=f;e<=g;e++)l.rows[e]&&"none"!=l.rows[e].element.style.display&&(l.records[e][p].element.classList.add("highlight-left"),l.records[e][m].element.classList.add("highlight-right"),l.rows[e].element.classList.add("selected"));l.selectedContainer=[p,f,m,g],0==y&&(n.A.call(l,"onfocus",l),h()),n.A.call(l,"onselection",l,p,f,m,g,r),d.call(l)},f=function(e){const t=this;if(!t.selectedCell)return[];const s=[];for(let n=Math.min(t.selectedCell[0],t.selectedCell[2]);n<=Math.max(t.selectedCell[0],t.selectedCell[2]);n++)e&&"none"==t.headers[n].style.display||s.push(n);return s},g=function(){const e=this;e.selectedCell&&e.updateSelectionFromCoords(e.selectedCell[0],e.selectedCell[1],e.selectedCell[2],e.selectedCell[3])},y=function(){const e=this;for(let t=0;t<e.selection.length;t++)e.selection[t].classList.remove("selection"),e.selection[t].classList.remove("selection-left"),e.selection[t].classList.remove("selection-right"),e.selection[t].classList.remove("selection-top"),e.selection[t].classList.remove("selection-bottom");e.selection=[]},b=function(e){return 1==(e=""+e).length&&(e="0"+e),e},C=function(e,t){const s=this,o=s.getData(!0,!1),r=s.selectedContainer,c=parseInt(e.getAttribute("data-x")),d=parseInt(e.getAttribute("data-y")),u=parseInt(t.getAttribute("data-x")),p=parseInt(t.getAttribute("data-y")),h=[];let m,f,g=!1;r[0]==c?(m=d<r[1]?d-r[1]:1,f=0):(f=c<r[0]?c-r[0]:1,m=0);let y=0,C=0;for(let e=d;e<=p;e++)if(!s.rows[e]||"none"!=s.rows[e].element.style.display){null==o[C]&&(C=0),y=0,r[0]!=c&&(f=c<r[0]?c-r[0]:1);for(let t=c;t<=u;t++){if(s.records[e][t]&&!s.records[e][t].element.classList.contains("readonly")&&"none"!=s.records[e][t].element.style.display&&0==g){if(!s.selection.length&&""!=s.options.data[e][t]){g=!0;continue}(null==o[C]||null==o[C][y])&&(y=0);let n=o[C][y];if(n&&!o[1]&&0!=s.parent.config.autoIncrement)if(!s.options.columns||!s.options.columns[t]||s.options.columns[t].type&&"text"!=s.options.columns[t].type&&"number"!=s.options.columns[t].type){if(s.options.columns&&s.options.columns[t]&&"calendar"==s.options.columns[t].type){const e=new Date(n);e.setDate(e.getDate()+m),n=e.getFullYear()+"-"+b(parseInt(e.getMonth()+1))+"-"+b(e.getDate())+" 00:00:00"}}else if("="==(""+n).substr(0,1)){const e=n.match(/([A-Z]+[0-9]+)/g);if(e){const t=[];for(let s=0;s<e.length;s++){const n=(0,a.vu)(e[s],1);n[0]+=f,n[1]+=m,n[1]<0&&(n[1]=0);const o=(0,a.t3)([n[0],n[1]]);o!=e[s]&&(t[e[s]]=o)}t&&(n=(0,i.yB)(n,t))}}else n==Number(n)&&(n=Number(n)+m);h.push(i.k9.call(s,t,e,n)),i.xF.call(s,t,e,h)}y++,r[0]!=c&&f++}C++,m++}l.Dh.call(s,{action:"setValue",records:h,selection:s.selectedCell}),i.am.call(s);const j=h.map((function(e){return{x:e.x,y:e.y,value:e.value,oldValue:e.oldValue}}));n.A.call(s,"onafterchanges",s,j)},j=function(e){let t,s,n=0;if(!e||0===e.length)return n;for(t=0;t<e.length;t++)s=e.charCodeAt(t),n=(n<<5)-n+s,n|=0;return n},w=function(e,t,s){const n=this;if(1==e){if(n.selectedCell&&(t>=n.selectedCell[1]&&t<=n.selectedCell[3]||s>=n.selectedCell[1]&&s<=n.selectedCell[3]))return void n.resetSelection()}else if(n.selectedCell&&(t>=n.selectedCell[0]&&t<=n.selectedCell[2]||s>=n.selectedCell[0]&&s<=n.selectedCell[2]))return void n.resetSelection()},_=function(e){const t=this;if(!t.selectedCell)return[];const s=[];for(let n=Math.min(t.selectedCell[1],t.selectedCell[3]);n<=Math.max(t.selectedCell[1],t.selectedCell[3]);n++)e&&"none"==t.rows[n].element.style.display||s.push(n);return s},B=function(){const e=this;e.selectedCell||(e.selectedCell=[]),e.selectedCell[0]=0,e.selectedCell[1]=0,e.selectedCell[2]=e.headers.length-1,e.selectedCell[3]=e.records.length-1,e.updateSelectionFromCoords(e.selectedCell[0],e.selectedCell[1],e.selectedCell[2],e.selectedCell[3])},v=function(){const e=this;return e.selectedCell?[Math.min(e.selectedCell[0],e.selectedCell[2]),Math.min(e.selectedCell[1],e.selectedCell[3]),Math.max(e.selectedCell[0],e.selectedCell[2]),Math.max(e.selectedCell[1],e.selectedCell[3])]:null},A=function(e){const t=this,s=v.call(t);if(!s)return[];const n=[];for(let o=s[1];o<=s[3];o++)for(let l=s[0];l<=s[2];l++)e?n.push((0,r.getCellNameFromCoords)(l,o)):n.push(t.records[o][l]);return n},x=function(){const e=this,t=v.call(e);if(!t)return"";const s=(0,r.getCellNameFromCoords)(t[0],t[1]),n=(0,r.getCellNameFromCoords)(t[2],t[3]);return s===n?e.options.worksheetName+"!"+s:e.options.worksheetName+"!"+s+":"+n},E=function(e,t){const s=v.call(this);return e>=s[0]&&e<=s[2]&&t>=s[1]&&t<=s[3]},k=function(){const e=v.call(this);return e?[e]:[]}},392:function(e,t,s){s.d(t,{Ar:function(){return u},ll:function(){return d},nK:function(){return c}});var n=s(978),o=s(530);const r=function(e,t){0!=t.options.editable?e.classList.remove("jtoolbar-disabled"):e.classList.add("jtoolbar-disabled")},l=function(){const e=[],t=this,s=function(){return o.eN.call(t)};e.push({content:"undo",onclick:function(){s().undo()}}),e.push({content:"redo",onclick:function(){s().redo()}}),e.push({content:"save",onclick:function(){const e=s();e&&e.download()}}),e.push({type:"divisor"}),e.push({type:"select",width:"120px",options:["Default","Verdana","Arial","Courier New"],render:function(e){return'<span style="font-family:'+e+'">'+e+"</span>"},onchange:function(e,t,n,o,r){const l=s();let i=l.getSelected(!0);if(i){let e=r?o:"";l.setStyle(Object.fromEntries(i.map((function(t){return[t,"font-family: "+e]}))))}},updateState:function(e,t,n){r(n,s())}}),e.push({type:"select",width:"48px",content:"format_size",options:["x-small","small","medium","large","x-large"],render:function(e){return'<span style="font-size:'+e+'">'+e+"</span>"},onchange:function(e,t,n,o){const r=s();let l=r.getSelected(!0);l&&r.setStyle(Object.fromEntries(l.map((function(e){return[e,"font-size: "+o]}))))},updateState:function(e,t,n){r(n,s())}}),e.push({type:"select",options:["left","center","right","justify"],render:function(e){return'<i class="material-icons">format_align_'+e+"</i>"},onchange:function(e,t,n,o){const r=s();let l=r.getSelected(!0);l&&r.setStyle(Object.fromEntries(l.map((function(e){return[e,"text-align: "+o]}))))},updateState:function(e,t,n){r(n,s())}}),e.push({content:"format_bold",onclick:function(e,t,n){const o=s();let r=o.getSelected(!0);r&&o.setStyle(Object.fromEntries(r.map((function(e){return[e,"font-weight:bold"]}))))},updateState:function(e,t,n){r(n,s())}}),e.push({type:"color",content:"format_color_text",k:"color",updateState:function(e,t,n){r(n,s())}}),e.push({type:"color",content:"format_color_fill",k:"background-color",updateState:function(e,t,n,o){r(n,s())}});let l=["top","middle","bottom"];return e.push({type:"select",options:["vertical_align_top","vertical_align_center","vertical_align_bottom"],render:function(e){return'<i class="material-icons">'+e+"</i>"},value:1,onchange:function(e,t,n,o,r){const i=s();let a=i.getSelected(!0);a&&i.setStyle(Object.fromEntries(a.map((function(e){return[e,"vertical-align: "+l[r]]}))))},updateState:function(e,t,n){r(n,s())}}),e.push({content:"web",tooltip:jSuites.translate("Merge the selected cells"),onclick:function(){const e=s();if(e.selectedCell&&confirm(jSuites.translate("The merged cells will retain the value of the top-left cell only. Are you sure?"))){const t=[Math.min(e.selectedCell[0],e.selectedCell[2]),Math.min(e.selectedCell[1],e.selectedCell[3]),Math.max(e.selectedCell[0],e.selectedCell[2]),Math.max(e.selectedCell[1],e.selectedCell[3])];let s=(0,n.getCellNameFromCoords)(t[0],t[1]);if(e.records[t[1]][t[0]].element.getAttribute("data-merged"))e.removeMerge(s);else{let n=t[2]-t[0]+1,o=t[3]-t[1]+1;1===n&&1===o||e.setMerge(s,n,o)}}},updateState:function(e,t,n){r(n,s())}}),e.push({type:"select",options:["border_all","border_outer","border_inner","border_horizontal","border_vertical","border_left","border_top","border_right","border_bottom","border_clear"],columns:5,render:function(e){return'<i class="material-icons">'+e+"</i>"},right:!0,onchange:function(e,t,o,r){const l=s();if(l.selectedCell){const e=[Math.min(l.selectedCell[0],l.selectedCell[2]),Math.min(l.selectedCell[1],l.selectedCell[3]),Math.max(l.selectedCell[0],l.selectedCell[2]),Math.max(l.selectedCell[1],l.selectedCell[3])];let s=r;if(e){let o=t.thickness||1,r=t.color||"black";const i=t.style||"solid";"double"===i&&(o+=2);let a={},c=e[0],d=e[1],u=e[2],p=e[3];const h=function(e,t,n){let l=["","","",""];l[0]=("border_top"===s||"border_outer"===s)&&n===d||("border_inner"===s||"border_horizontal"===s)&&n>d||"border_all"===s?"border-top: "+o+"px "+i+" "+r:"border-top: ",l[1]="border_all"!==s&&"border_right"!==s&&"border_outer"!==s||t!==u?"border-right: ":"border-right: "+o+"px "+i+" "+r,l[2]="border_all"!==s&&"border_bottom"!==s&&"border_outer"!==s||n!==p?"border-bottom: ":"border-bottom: "+o+"px "+i+" "+r,l[3]=("border_left"===s||"border_outer"===s)&&t===c||("border_inner"===s||"border_vertical"===s)&&t>c||"border_all"===s?"border-left: "+o+"px "+i+" "+r:"border-left: ",a[e]=l.join(";")};for(let t=e[1];t<=e[3];t++)for(let s=e[0];s<=e[2];s++)h((0,n.getCellNameFromCoords)(s,t),s,t),l.records[t][s].element.getAttribute("data-merged")&&h((0,n.getCellNameFromCoords)(e[0],e[1]),s,t);Object.keys(a)&&l.setStyle(a)}}},onload:function(e,t){let s=document.createElement("div"),n=document.createElement("div");s.appendChild(n);let o=jSuites.color(n,{closeOnChange:!1,onchange:function(e,s){e.parentNode.children[1].style.color=s,t.color=s}}),r=document.createElement("i");r.classList.add("material-icons"),r.innerHTML="color_lens",r.onclick=function(){o.open()},s.appendChild(r),e.children[1].appendChild(s),n=document.createElement("div"),jSuites.picker(n,{type:"select",data:[1,2,3,4,5],render:function(e){return'<div style="height: '+e+'px; width: 30px; background-color: black;"></div>'},onchange:function(e,s,n,o){t.thickness=o},width:"50px"}),e.children[1].appendChild(n);const l=document.createElement("div");jSuites.picker(l,{type:"select",data:["solid","dotted","dashed","double"],render:function(e){return"double"===e?'<div style="width: 30px; border-top: 3px '+e+' black;"></div>':'<div style="width: 30px; border-top: 2px '+e+' black;"></div>'},onchange:function(e,s,n,o){t.style=o},width:"50px"}),e.children[1].appendChild(l),n=document.createElement("div"),n.style.flex="1",e.children[1].appendChild(n)},updateState:function(e,t,n){r(n,s())}}),e.push({type:"divisor"}),e.push({content:"fullscreen",tooltip:"Toggle Fullscreen",onclick:function(e,s,n){"fullscreen"===n.children[0].textContent?(t.fullscreen(!0),n.children[0].textContent="fullscreen_exit"):(t.fullscreen(!1),n.children[0].textContent="fullscreen")},updateState:function(e,t,s,n){!0===n.parent.config.fullscreen?s.children[0].textContent="fullscreen_exit":s.children[0].textContent="fullscreen"}}),e},i=function(e){const t=this,s=e.items;for(let e=0;e<s.length;e++)s[e].tooltip&&(s[e].title=s[e].tooltip,delete s[e].tooltip),"select"==s[e].type?s[e].options?(s[e].data=s[e].options,delete s[e].options):(s[e].data=s[e].v,delete s[e].v,s[e].k&&!s[e].onchange&&(s[e].onchange=function(n,r,l){const i=o.eN.call(t),a=i.getSelected(!0);i.setStyle(Object.fromEntries(a.map((function(t){return[t,s[e].k+": "+l]}))))})):"color"==s[e].type&&(s[e].type="i",s[e].onclick=function(n,r,l){l.color||(jSuites.color(l,{onchange:function(n,r){const l=o.eN.call(t),i=l.getSelected(!0);l.setStyle(Object.fromEntries(i.map((function(t){return[t,s[e].k+": "+r]}))))},onopen:function(e){e.color.select("")}}),l.color.open())})},a=function(e){const t=this,s=document.createElement("div");return s.classList.add("jss_toolbar"),i.call(t,e),"object"==typeof t.plugins&&Object.entries(t.plugins).forEach((function([,t]){if("function"==typeof t.toolbar){const s=t.toolbar(e);s&&(e=s)}})),jSuites.toolbar(s,e),s},c=function(e){e.parent.toolbar&&e.parent.toolbar.toolbar.update(e)},d=function(){const e=this;if(e.config.toolbar&&!e.toolbar){let t;Array.isArray(e.config.toolbar)?t={items:e.config.toolbar}:"object"==typeof e.config.toolbar?t=e.config.toolbar:(t={items:l.call(e)},"function"==typeof e.config.toolbar&&(t=e.config.toolbar(t))),e.toolbar=e.element.insertBefore(a.call(e,t),e.element.children[1])}},u=function(){const e=this;e.toolbar&&(e.toolbar.parentNode.removeChild(e.toolbar),delete e.toolbar)}}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var s=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](s,s.exports,__webpack_require__),s.exports}__webpack_require__.d=function(e,t){for(var s in t)__webpack_require__.o(t,s)&&!__webpack_require__.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},__webpack_require__.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},__webpack_require__.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__={};__webpack_require__.d(__webpack_exports__,{default:function(){return src}});const lib={jspreadsheet:{}};var libraryBase=lib,dispatch=__webpack_require__(805),internal=__webpack_require__(530),utils_history=__webpack_require__(911);const openEditor=function(e,t,s){const n=this,o=e.getAttribute("data-y"),r=e.getAttribute("data-x");dispatch.A.call(n,"oneditionstart",n,e,parseInt(r),parseInt(o)),r>0&&(n.records[o][r-1].element.style.overflow="hidden");const l=function(t){const s=e.getBoundingClientRect(),n=document.createElement(t);return n.style.width=s.width+"px",n.style.height=s.height-2+"px",n.style.minHeight=s.height-2+"px",e.classList.add("editor"),e.innerHTML="",e.appendChild(n),n};if(1==e.classList.contains("readonly"));else if(n.edition=[n.records[o][r].element,n.records[o][r].element.innerHTML,r,o],n.options.columns&&n.options.columns[r]&&"object"==typeof n.options.columns[r].type)n.options.columns[r].type.openEditor(e,n.options.data[o][r],parseInt(r),parseInt(o),n,n.options.columns[r],s),dispatch.A.call(n,"oncreateeditor",n,e,parseInt(r),parseInt(o),null,n.options.columns[r]);else if(n.options.columns&&n.options.columns[r]&&"hidden"==n.options.columns[r].type);else if(n.options.columns&&n.options.columns[r]&&("checkbox"==n.options.columns[r].type||"radio"==n.options.columns[r].type)){const t=!e.children[0].checked;n.setValue(e,t),n.edition=null}else if(n.options.columns&&n.options.columns[r]&&"dropdown"==n.options.columns[r].type){let t,s=n.options.data[o][r];n.options.columns[r].multiple&&!Array.isArray(s)&&(s=s.split(";")),t="function"==typeof n.options.columns[r].filter?n.options.columns[r].filter(n.element,e,r,o,n.options.columns[r].source):n.options.columns[r].source;const i=[];if(t)for(let e=0;e<t.length;e++)i.push(t[e]);const a=l("div");dispatch.A.call(n,"oncreateeditor",n,e,parseInt(r),parseInt(o),null,n.options.columns[r]);const c={data:i,multiple:!!n.options.columns[r].multiple,autocomplete:!!n.options.columns[r].autocomplete,opened:!0,value:s,width:"100%",height:a.style.minHeight,position:1==n.options.tableOverflow||1==n.parent.config.fullscreen,onclose:function(){closeEditor.call(n,e,!0)}};n.options.columns[r].options&&n.options.columns[r].options.type&&(c.type=n.options.columns[r].options.type),jSuites.dropdown(a,c)}else if(n.options.columns&&n.options.columns[r]&&("calendar"==n.options.columns[r].type||"color"==n.options.columns[r].type)){const t=n.options.data[o][r],s=l("input");dispatch.A.call(n,"oncreateeditor",n,e,parseInt(r),parseInt(o),null,n.options.columns[r]),s.value=t;const i=n.options.columns[r].options?{...n.options.columns[r].options}:{};if(1!=n.options.tableOverflow&&1!=n.parent.config.fullscreen||(i.position=!0),i.value=n.options.data[o][r],i.opened=!0,i.onclose=function(t,s){closeEditor.call(n,e,!0)},"color"==n.options.columns[r].type){jSuites.color(s,i);const t=e.getBoundingClientRect();i.position&&(s.nextSibling.children[1].style.top=t.top+t.height+"px",s.nextSibling.children[1].style.left=t.left+"px")}else i.format||(i.format="YYYY-MM-DD"),jSuites.calendar(s,i);s.focus()}else if(n.options.columns&&n.options.columns[r]&&"html"==n.options.columns[r].type){const t=n.options.data[o][r],s=l("div");dispatch.A.call(n,"oncreateeditor",n,e,parseInt(r),parseInt(o),null,n.options.columns[r]),s.style.position="relative";const i=document.createElement("div");i.classList.add("jss_richtext"),s.appendChild(i),jSuites.editor(i,{focus:!0,value:t});const a=e.getBoundingClientRect(),c=i.getBoundingClientRect();window.innerHeight<a.bottom+c.height?i.style.top=a.bottom-(c.height+2)+"px":i.style.top=a.top+"px",window.innerWidth<a.left+c.width?i.style.left=a.right-(c.width+2)+"px":i.style.left=a.left+"px"}else if(n.options.columns&&n.options.columns[r]&&"image"==n.options.columns[r].type){const t=e.children[0],s=l("div");dispatch.A.call(n,"oncreateeditor",n,e,parseInt(r),parseInt(o),null,n.options.columns[r]),s.style.position="relative";const i=document.createElement("div");i.classList.add("jclose"),t&&t.src&&i.appendChild(t),s.appendChild(i),jSuites.image(i,n.options.columns[r]);const a=e.getBoundingClientRect(),c=i.getBoundingClientRect();window.innerHeight<a.bottom+c.height?i.style.top=a.top-(c.height+2)+"px":i.style.top=a.top+"px",i.style.left=a.left+"px"}else{const s=1==t?"":n.options.data[o][r];let i;i=n.options.columns&&n.options.columns[r]&&0==n.options.columns[r].wordWrap||!(1==n.options.wordWrap||n.options.columns&&n.options.columns[r]&&1==n.options.columns[r].wordWrap)?l("input"):l("textarea"),dispatch.A.call(n,"oncreateeditor",n,e,parseInt(r),parseInt(o),null,n.options.columns[r]),i.focus(),i.value=s;const a=n.options.columns&&n.options.columns[r];if(!(0,internal.dw)(s)&&a){const e=(0,internal.rS)(a);if(e){if(!a.disabledMaskOnEdition)if(a.mask){const e=a.mask.split(";");i.setAttribute("data-mask",e[0])}else a.locale&&i.setAttribute("data-locale",a.locale);e.input=i,i.mask=e,jSuites.mask.render(s,e,!1)}}i.onblur=function(){closeEditor.call(n,e,!0)},i.scrollLeft=i.scrollWidth}},closeEditor=function(e,t){const s=this,n=parseInt(e.getAttribute("data-x")),o=parseInt(e.getAttribute("data-y"));let r;if(1==t){if(s.options.columns&&s.options.columns[n]&&"object"==typeof s.options.columns[n].type)r=s.options.columns[n].type.closeEditor(e,t,parseInt(n),parseInt(o),s,s.options.columns[n]);else if(s.options.columns&&s.options.columns[n]&&("checkbox"==s.options.columns[n].type||"radio"==s.options.columns[n].type||"hidden"==s.options.columns[n].type));else if(s.options.columns&&s.options.columns[n]&&"dropdown"==s.options.columns[n].type)r=e.children[0].dropdown.close(!0);else if(s.options.columns&&s.options.columns[n]&&"calendar"==s.options.columns[n].type)r=e.children[0].calendar.close(!0);else if(s.options.columns&&s.options.columns[n]&&"color"==s.options.columns[n].type)r=e.children[0].color.close(!0);else if(s.options.columns&&s.options.columns[n]&&"html"==s.options.columns[n].type)r=e.children[0].children[0].editor.getData();else if(s.options.columns&&s.options.columns[n]&&"image"==s.options.columns[n].type){const t=e.children[0].children[0].children[0];r=t&&"IMG"==t.tagName?t.src:""}else if(s.options.columns&&s.options.columns[n]&&"numeric"==s.options.columns[n].type)r=e.children[0].value,"="!=(""+r).substr(0,1)&&""==r&&(r=s.options.columns[n].allowEmpty?"":0),e.children[0].onblur=null;else{r=e.children[0].value,e.children[0].onblur=null;const t=s.options.columns&&s.options.columns[n];if(t){const e=(0,internal.rS)(t);if(e&&""!==r&&!(0,internal.dw)(r)&&"number"!=typeof r){const t=jSuites.mask.extract(r,e,!0);t&&""!==t.value&&(r=t.value)}}}s.options.data[o][n]==r?e.innerHTML=s.edition[1]:s.setValue(e,r)}else s.options.columns&&s.options.columns[n]&&"object"==typeof s.options.columns[n].type?s.options.columns[n].type.closeEditor(e,t,parseInt(n),parseInt(o),s,s.options.columns[n]):s.options.columns&&s.options.columns[n]&&"dropdown"==s.options.columns[n].type?e.children[0].dropdown.close(!0):s.options.columns&&s.options.columns[n]&&"calendar"==s.options.columns[n].type?e.children[0].calendar.close(!0):s.options.columns&&s.options.columns[n]&&"color"==s.options.columns[n].type?e.children[0].color.close(!0):e.children[0].onblur=null,e.innerHTML=s.edition&&s.edition[1]?s.edition[1]:"";dispatch.A.call(s,"oneditionend",s,e,n,o,r,t),e.classList.remove("editor"),s.edition=null},setCheckRadioValue=function(){const e=this,t=[],s=Object.keys(e.highlighted);for(let n=0;n<s.length;n++){const s=e.highlighted[n].element.getAttribute("data-x"),o=e.highlighted[n].element.getAttribute("data-y");"checkbox"!=e.options.columns[s].type&&"radio"!=e.options.columns[s].type||t.push(internal.k9.call(e,s,o,!e.options.data[o][s]))}if(t.length){utils_history.Dh.call(e,{action:"setValue",records:t,selection:e.selectedCell});const s=t.map((function(e){return{x:e.x,y:e.y,value:e.value,oldValue:e.oldValue}}));dispatch.A.call(e,"onafterchanges",e,s)}};var lazyLoading=__webpack_require__(497);const upGet=function(e,t){const s=this;e=parseInt(e);for(let n=(t=parseInt(t))-1;n>=0;n--)if("none"!=s.records[n][e].element.style.display&&"none"!=s.rows[n].element.style.display){if(s.records[n][e].element.getAttribute("data-merged")&&s.records[n][e].element==s.records[t][e].element)continue;t=n;break}return t},upVisible=function(e,t){const s=this;let n,o;if(0==e?(n=parseInt(s.selectedCell[0]),o=parseInt(s.selectedCell[1])):(n=parseInt(s.selectedCell[2]),o=parseInt(s.selectedCell[3])),0==t){for(let e=0;e<o;e++)if("none"!=s.records[e][n].element.style.display&&"none"!=s.rows[e].element.style.display){o=e;break}}else o=upGet.call(s,n,o);0==e?(s.selectedCell[0]=n,s.selectedCell[1]=o):(s.selectedCell[2]=n,s.selectedCell[3]=o)},up=function(e,t){const s=this;if(e?s.selectedCell[3]>0&&upVisible.call(s,1,t?0:1):(s.selectedCell[1]>0&&upVisible.call(s,0,t?0:1),s.selectedCell[2]=s.selectedCell[0],s.selectedCell[3]=s.selectedCell[1]),s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]),1==s.options.lazyLoading)if(0==s.selectedCell[1]||0==s.selectedCell[3])lazyLoading.wu.call(s,0),s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]);else if(lazyLoading.AG.call(s))s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]);else{const e=parseInt(s.tbody.firstChild.getAttribute("data-y"));s.selectedCell[1]-e<30&&(lazyLoading.G_.call(s),s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]))}else if(s.options.pagination>0){const e=s.whichPage(s.selectedCell[3]);e!=s.pageNumber&&s.page(e)}internal.Rs.call(s,1)},rightGet=function(e,t){const s=this;e=parseInt(e),t=parseInt(t);for(let n=e+1;n<s.headers.length;n++)if("none"!=s.records[t][n].element.style.display){if(s.records[t][n].element.getAttribute("data-merged")&&s.records[t][n].element==s.records[t][e].element)continue;e=n;break}return e},rightVisible=function(e,t){const s=this;let n,o;if(0==e?(n=parseInt(s.selectedCell[0]),o=parseInt(s.selectedCell[1])):(n=parseInt(s.selectedCell[2]),o=parseInt(s.selectedCell[3])),0==t){for(let e=s.headers.length-1;e>n;e--)if("none"!=s.records[o][e].element.style.display){n=e;break}}else n=rightGet.call(s,n,o);0==e?(s.selectedCell[0]=n,s.selectedCell[1]=o):(s.selectedCell[2]=n,s.selectedCell[3]=o)},right=function(e,t){const s=this;e?s.selectedCell[2]<s.headers.length-1&&rightVisible.call(s,1,t?0:1):(s.selectedCell[0]<s.headers.length-1&&rightVisible.call(s,0,t?0:1),s.selectedCell[2]=s.selectedCell[0],s.selectedCell[3]=s.selectedCell[1]),s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]),internal.Rs.call(s,2)},downGet=function(e,t){const s=this;e=parseInt(e);for(let n=(t=parseInt(t))+1;n<s.rows.length;n++)if("none"!=s.records[n][e].element.style.display&&"none"!=s.rows[n].element.style.display){if(s.records[n][e].element.getAttribute("data-merged")&&s.records[n][e].element==s.records[t][e].element)continue;t=n;break}return t},downVisible=function(e,t){const s=this;let n,o;if(0==e?(n=parseInt(s.selectedCell[0]),o=parseInt(s.selectedCell[1])):(n=parseInt(s.selectedCell[2]),o=parseInt(s.selectedCell[3])),0==t){for(let e=s.rows.length-1;e>o;e--)if("none"!=s.records[e][n].element.style.display&&"none"!=s.rows[e].element.style.display){o=e;break}}else o=downGet.call(s,n,o);0==e?(s.selectedCell[0]=n,s.selectedCell[1]=o):(s.selectedCell[2]=n,s.selectedCell[3]=o)},down=function(e,t){const s=this;if(e?s.selectedCell[3]<s.records.length-1&&downVisible.call(s,1,t?0:1):(s.selectedCell[1]<s.records.length-1&&downVisible.call(s,0,t?0:1),s.selectedCell[2]=s.selectedCell[0],s.selectedCell[3]=s.selectedCell[1]),s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]),1==s.options.lazyLoading)s.selectedCell[1]==s.records.length-1||s.selectedCell[3]==s.records.length-1?(lazyLoading.wu.call(s,-1),s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3])):lazyLoading.AG.call(s)?s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]):parseInt(s.tbody.lastChild.getAttribute("data-y"))-s.selectedCell[3]<30&&(lazyLoading.p6.call(s),s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]));else if(s.options.pagination>0){const e=s.whichPage(s.selectedCell[3]);e!=s.pageNumber&&s.page(e)}internal.Rs.call(s,3)},leftGet=function(e,t){const s=this;e=parseInt(e),t=parseInt(t);for(let n=e-1;n>=0;n--)if("none"!=s.records[t][n].element.style.display){if(s.records[t][n].element.getAttribute("data-merged")&&s.records[t][n].element==s.records[t][e].element)continue;e=n;break}return e},leftVisible=function(e,t){const s=this;let n,o;if(0==e?(n=parseInt(s.selectedCell[0]),o=parseInt(s.selectedCell[1])):(n=parseInt(s.selectedCell[2]),o=parseInt(s.selectedCell[3])),0==t){for(let e=0;e<n;e++)if("none"!=s.records[o][e].element.style.display){n=e;break}}else n=leftGet.call(s,n,o);0==e?(s.selectedCell[0]=n,s.selectedCell[1]=o):(s.selectedCell[2]=n,s.selectedCell[3]=o)},left=function(e,t){const s=this;e?s.selectedCell[2]>0&&leftVisible.call(s,1,t?0:1):(s.selectedCell[0]>0&&leftVisible.call(s,0,t?0:1),s.selectedCell[2]=s.selectedCell[0],s.selectedCell[3]=s.selectedCell[1]),s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]),internal.Rs.call(s,0)},first=function(e,t){const s=this;if(e?t?s.selectedCell[3]=0:leftVisible.call(s,1,0):(t?s.selectedCell[1]=0:leftVisible.call(s,0,0),s.selectedCell[2]=s.selectedCell[0],s.selectedCell[3]=s.selectedCell[1]),1!=s.options.lazyLoading||0!=s.selectedCell[1]&&0!=s.selectedCell[3]){if(s.options.pagination>0){const e=s.whichPage(s.selectedCell[3]);e!=s.pageNumber&&s.page(e)}}else lazyLoading.wu.call(s,0);s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]),internal.Rs.call(s,1)},last=function(e,t){const s=this;if(e?t?s.selectedCell[3]=s.records.length-1:rightVisible.call(s,1,0):(t?s.selectedCell[1]=s.records.length-1:rightVisible.call(s,0,0),s.selectedCell[2]=s.selectedCell[0],s.selectedCell[3]=s.selectedCell[1]),1!=s.options.lazyLoading||s.selectedCell[1]!=s.records.length-1&&s.selectedCell[3]!=s.records.length-1){if(s.options.pagination>0){const e=s.whichPage(s.selectedCell[3]);e!=s.pageNumber&&s.page(e)}}else lazyLoading.wu.call(s,-1);s.updateSelectionFromCoords(s.selectedCell[0],s.selectedCell[1],s.selectedCell[2],s.selectedCell[3]),internal.Rs.call(s,3)};var merges=__webpack_require__(910),selection=__webpack_require__(657),helpers=__webpack_require__(978),internalHelpers=__webpack_require__(689);const copy=function(e,t,s,n,o,r,l){const i=this;t||(t="\t");const a=new RegExp(t,"ig"),c=[];let d=[],u=[];const p=[],h=[],m=i.options.data[0].length,f=i.options.data.length;let g="",y=!1,b="",C="",j=0,w=0,_=0,B=0,v=!0;for(let t=0;t<f;t++)for(let s=0;s<m;s++)e&&!i.records[t][s].element.classList.contains("highlight")||(_<=s&&(_=s),B<=t&&(B=t));if(m===_+1&&f===B+1&&!1,o&&(1==i.parent.config.includeHeadersOnDownload||n)){if(i.options.nestedHeaders&&i.options.nestedHeaders.length>0){g=i.options.nestedHeaders;for(let e=0;e<g.length;e++){const s=[];for(let t=0;t<g[e].length;t++){const n=parseInt(g[e][t].colspan);s.push(g[e][t].title);for(let e=0;e<n-1;e++)s.push("")}C+=s.join(t)+"\r\n"}}y=!0}i.style=[];for(let s=0;s<f;s++){d=[],u=[];for(let t=0;t<m;t++)if(!e||i.records[s][t].element.classList.contains("highlight")){1==y&&c.push(i.headers[t].textContent);let e,n=i.options.data[s][t];n.match&&(n.match(a)||n.match(/,/g)||n.match(/\n/)||n.match(/\"/))&&(n=n.replace(new RegExp('"',"g"),'""'),n='"'+n+'"'),d.push(n),i.options.columns&&i.options.columns[t]&&("checkbox"==i.options.columns[t].type||"radio"==i.options.columns[t].type)?e=n:(e=i.records[s][t].element.innerHTML,e.match&&(e.match(a)||e.match(/,/g)||e.match(/\n/)||e.match(/\"/))&&(e=e.replace(new RegExp('"',"g"),'""'),e='"'+e+'"')),u.push(e),g=i.records[s][t].element.getAttribute("style"),g=g.replace("display: none;",""),i.style.push(g||"")}d.length&&(y&&(j=d.length,p.push(c.join(t))),p.push(d.join(t))),u.length&&(w++,y&&(h.push(c.join(t)),y=!1),h.push(u.join(t)))}m==j&&f==w&&(b=C);const A=b+p.join("\r\n");let x=b+h.join("\r\n");if(!s){const e=[Math.min(i.selectedCell[0],i.selectedCell[2]),Math.min(i.selectedCell[1],i.selectedCell[3]),Math.max(i.selectedCell[0],i.selectedCell[2]),Math.max(i.selectedCell[1],i.selectedCell[3])],t=dispatch.A.call(i,"oncopy",i,e,x,r);if(t)x=t;else if(!1===t)return!1;i.textarea.value=x,i.textarea.select(),document.execCommand("copy")}if(i.data=1==l?x:A,i.hashString=selection.tW.call(i,i.data),!s&&(selection.kA.call(i),i.highlighted))for(let e=0;e<i.highlighted.length;e++)i.highlighted[e].element.classList.add("copying"),i.highlighted[e].element.classList.contains("highlight-left")&&i.highlighted[e].element.classList.add("copying-left"),i.highlighted[e].element.classList.contains("highlight-right")&&i.highlighted[e].element.classList.add("copying-right"),i.highlighted[e].element.classList.contains("highlight-top")&&i.highlighted[e].element.classList.add("copying-top"),i.highlighted[e].element.classList.contains("highlight-bottom")&&i.highlighted[e].element.classList.add("copying-bottom");return i.data},paste=function(e,t,s){const n=this,o=(0,selection.tW)(s);let r=o==n.hashString?n.style:null;o==n.hashString&&(s=n.data),s=(0,helpers.parseCSV)(s,"\t");const l=n.selectedCell[2]-e+1,i=n.selectedCell[3]-t+1,a=s[0].length;if(l>1&Number.isInteger(l/a)){const e=l/a;if(r){const t=[];for(let s=0;s<r.length;s+=a){const n=r.slice(s,s+a);for(let s=0;s<e;s++)t.push(...n)}r=t}const t=s.map((function(t,s){const n=Array.apply(null,{length:e*t.length}).map((function(e,s){return t[s%t.length]}));return n}));s=t}const c=s.length;if(i>1&Number.isInteger(i/c)){const e=i/c;if(r){const t=[];for(let s=0;s<e;s++)t.push(...r);r=t}const t=Array.apply(null,{length:e*c}).map((function(e,t){return s[t%c]}));s=t}const d=dispatch.A.call(n,"onbeforepaste",n,s.map((function(e){return e.map((function(e){return{value:e}}))})),e,t);if(!1===d)return!1;if(d&&(s=d),null!=e&&null!=t&&s){let o=0,l=0;const i=[],a={},c={};let d=0,u=parseInt(e),p=parseInt(t),h=null;const m=n.headers.slice(u).filter((e=>"none"===e.style.display)).length,f=u+m+s[0].length,g=n.headers.length;f>g&&(n.skipUpdateTableReferences=!0,n.insertColumn(f-g));const y=n.rows.slice(p).filter((e=>"none"===e.element.style.display)).length,b=p+y+s.length,C=n.rows.length;for(b>C&&(n.skipUpdateTableReferences=!0,n.insertRow(b-C)),n.skipUpdateTableReferences&&(n.skipUpdateTableReferences=!1,internal.o8.call(n));h=s[l];){for(o=0,u=parseInt(e);null!=h[o];){let e=h[o];n.options.columns&&n.options.columns[o]&&"calendar"==n.options.columns[o].type&&(e=jSuites.calendar.extractDateFromString(e,n.options.columns[o].options&&n.options.columns[o].options.format||"YYYY-MM-DD"));const t=internal.k9.call(n,u,p,e);if(i.push(t),internal.xF.call(n,u,p,i),r&&r[d]){const e=(0,internalHelpers.t3)([u,p]);a[e]=r[d],c[e]=n.getStyle(e),n.records[p][u].element.setAttribute("style",r[d]),d++}if(o++,null!=h[o]){if(u>=n.headers.length-1){if(0==n.options.allowInsertColumn)break;n.insertColumn()}u=rightGet.call(n,u,p)}}if(l++,s[l]){if(p>=n.rows.length-1){if(0==n.options.allowInsertRow)break;n.insertRow()}p=downGet.call(n,e,p)}}selection.AH.call(n,e,t,u,p),utils_history.Dh.call(n,{action:"setValue",records:i,selection:n.selectedCell,newStyle:a,oldStyle:c}),internal.am.call(n);const j=[];for(let n=0;n<s.length;n++)for(let o=0;o<s[n].length;o++)j.push({x:o+e,y:n+t,value:s[n][o]});dispatch.A.call(n,"onpaste",n,j);const w=i.map((function(e){return{x:e.x,y:e.y,value:e.value,oldValue:e.oldValue}}));dispatch.A.call(n,"onafterchanges",n,w)}(0,selection.kA)()};var filter=__webpack_require__(829),footer=__webpack_require__(160);const getNumberOfColumns=function(){const e=this;let t=e.options.columns&&e.options.columns.length||0;if(e.options.data&&void 0!==e.options.data[0]){const s=Object.keys(e.options.data[0]);s.length>t&&(t=s.length)}return e.options.minDimensions&&e.options.minDimensions[0]>t&&(t=e.options.minDimensions[0]),t},createCellHeader=function(e){const t=this,s=t.options.columns&&t.options.columns[e]&&t.options.columns[e].width||t.options.defaultColWidth||100,n=t.options.columns&&t.options.columns[e]&&t.options.columns[e].align||t.options.defaultColAlign||"center";t.headers[e]=document.createElement("td"),t.headers[e].textContent=t.options.columns&&t.options.columns[e]&&t.options.columns[e].title||(0,helpers.getColumnName)(e),t.headers[e].setAttribute("data-x",e),t.headers[e].style.textAlign=n,t.options.columns&&t.options.columns[e]&&t.options.columns[e].title&&t.headers[e].setAttribute("title",t.headers[e].innerText),t.options.columns&&t.options.columns[e]&&t.options.columns[e].id&&t.headers[e].setAttribute("id",t.options.columns[e].id);const o=document.createElement("col");o.setAttribute("width",s),t.cols[e]={colElement:o,x:e},t.options.columns&&t.options.columns[e]&&"hidden"==t.options.columns[e].type&&(t.headers[e].style.display="none",o.style.display="none")},insertColumn=function(e,t,s,n){const o=this;if(0!=o.options.allowInsertColumn){let r,l=[];Array.isArray(e)?(r=1,e&&(l=e)):r="number"==typeof e?e:1,s=!!s;const i=Math.max(o.options.columns.length,...o.options.data.map((function(e){return e.length})))-1;(null==t||t>=parseInt(i)||t<0)&&(t=i),n||(n=[]);for(let e=0;e<r;e++)n[e]||(n[e]={});const a=[];if(Array.isArray(e)){const r=[];for(let t=0;t<o.options.data.length;t++)r.push(t<e.length?e[t]:"");const l={column:t+(s?0:1),options:Object.assign({},n[0]),data:r};a.push(l)}else for(let o=0;o<e;o++){const e={column:t+o+(s?0:1),options:Object.assign({},n[o])};a.push(e)}if(!1===dispatch.A.call(o,"onbeforeinsertcolumn",o,a))return!1;if(o.options.mergeCells&&Object.keys(o.options.mergeCells).length>0&&merges.Lt.call(o,t,s).length){if(!confirm(jSuites.translate("This action will destroy any existing merged cells. Are you sure?")))return!1;o.destroyMerge()}const c=s?t:t+1;o.options.columns=(0,internalHelpers.Hh)(o.options.columns,c,n);const d=o.headers.splice(c),u=o.cols.splice(c),p=[],h=[],m=[],f=[],g=[];for(let e=c;e<r+c;e++)createCellHeader.call(o,e),o.headerContainer.insertBefore(o.headers[e],o.headerContainer.children[e+1]),o.colgroupContainer.insertBefore(o.cols[e].colElement,o.colgroupContainer.children[e+1]),p.push(o.headers[e]),h.push(o.cols[e]);if(o.options.footers)for(let e=0;e<o.options.footers.length;e++){g[e]=[];for(let t=0;t<r;t++)g[e].push("");o.options.footers[e].splice(c,0,g[e])}for(let e=0;e<o.options.data.length;e++){const t=o.options.data[e].splice(c),s=o.records[e].splice(c);f[e]=[],m[e]=[];for(let t=c;t<r+c;t++){const s=l[e]?l[e]:"";o.options.data[e][t]=s;const n=internal.P9.call(o,t,e,o.options.data[e][t]);o.records[e][t]={element:n,y:e},o.rows[e]&&o.rows[e].element.insertBefore(n,o.rows[e].element.children[t+1]),o.options.columns&&o.options.columns[t]&&"function"==typeof o.options.columns[t].render&&o.options.columns[t].render(n,s,parseInt(t),parseInt(e),o,o.options.columns[t]),f[e].push(s),m[e].push({element:n,x:t,y:e})}Array.prototype.push.apply(o.options.data[e],t),Array.prototype.push.apply(o.records[e],s)}Array.prototype.push.apply(o.headers,d),Array.prototype.push.apply(o.cols,u);for(let e=c;e<o.cols.length;e++)o.cols[e].x=e;for(let e=0;e<o.records.length;e++)for(let t=0;t<o.records[e].length;t++)o.records[e][t].x=t;if(o.options.nestedHeaders&&o.options.nestedHeaders.length>0&&o.options.nestedHeaders[0]&&o.options.nestedHeaders[0][0])for(let e=0;e<o.options.nestedHeaders.length;e++){const t=parseInt(o.options.nestedHeaders[e][o.options.nestedHeaders[e].length-1].colspan)+r;o.options.nestedHeaders[e][o.options.nestedHeaders[e].length-1].colspan=t,o.thead.children[e].children[o.thead.children[e].children.length-1].setAttribute("colspan",t);let s=o.thead.children[e].children[o.thead.children[e].children.length-1].getAttribute("data-column");s=s.split(",");for(let e=c;e<r+c;e++)s.push(e);o.thead.children[e].children[o.thead.children[e].children.length-1].setAttribute("data-column",s)}utils_history.Dh.call(o,{action:"insertColumn",columnNumber:t,numOfColumns:r,insertBefore:s,columns:n,headers:p,cols:h,records:m,footers:g,data:f}),internal.o8.call(o),dispatch.A.call(o,"oninsertcolumn",o,a)}},moveColumn=function(e,t){const s=this;if(s.options.mergeCells&&Object.keys(s.options.mergeCells).length>0){let n;if(n=e>t?1:0,merges.Lt.call(s,e).length||merges.Lt.call(s,t,n).length){if(!confirm(jSuites.translate("This action will destroy any existing merged cells. Are you sure?")))return!1;s.destroyMerge()}}if((e=parseInt(e))>(t=parseInt(t))){s.headerContainer.insertBefore(s.headers[e],s.headers[t]),s.colgroupContainer.insertBefore(s.cols[e].colElement,s.cols[t].colElement);for(let n=0;n<s.rows.length;n++)s.rows[n].element.insertBefore(s.records[n][e].element,s.records[n][t].element)}else{s.headerContainer.insertBefore(s.headers[e],s.headers[t].nextSibling),s.colgroupContainer.insertBefore(s.cols[e].colElement,s.cols[t].colElement.nextSibling);for(let n=0;n<s.rows.length;n++)s.rows[n].element.insertBefore(s.records[n][e].element,s.records[n][t].element.nextSibling)}s.options.columns.splice(t,0,s.options.columns.splice(e,1)[0]),s.headers.splice(t,0,s.headers.splice(e,1)[0]),s.cols.splice(t,0,s.cols.splice(e,1)[0]);const n=Math.min(e,t),o=Math.max(e,t);for(let n=0;n<s.rows.length;n++)s.options.data[n].splice(t,0,s.options.data[n].splice(e,1)[0]),s.records[n].splice(t,0,s.records[n].splice(e,1)[0]);for(let e=n;e<=o;e++)s.cols[e].x=e;for(let e=0;e<s.records.length;e++)for(let t=n;t<=o;t++)s.records[e][t].x=t;if(s.options.footers)for(let n=0;n<s.options.footers.length;n++)s.options.footers[n].splice(t,0,s.options.footers[n].splice(e,1)[0]);utils_history.Dh.call(s,{action:"moveColumn",oldValue:e,newValue:t}),internal.o8.call(s),dispatch.A.call(s,"onmovecolumn",s,e,t,1)},deleteColumn=function(e,t){const s=this;if(0!=s.options.allowDeleteColumn)if(s.headers.length>1){if(null==e){const n=s.getSelectedColumns(!0);n.length?(e=parseInt(n[0]),t=parseInt(n.length)):(e=s.headers.length-1,t=1)}const n=s.options.data[0].length-1;(null==e||e>n||e<0)&&(e=n),t||(t=1),t>s.options.data[0].length-e&&(t=s.options.data[0].length-e);const o=[];for(let s=0;s<t;s++)o.push(s+e);if(!1===dispatch.A.call(s,"onbeforedeletecolumn",s,o))return!1;if(parseInt(e)>-1){let n=!1;if(s.options.mergeCells&&Object.keys(s.options.mergeCells).length>0)for(let o=e;o<e+t;o++)merges.Lt.call(s,o,null).length&&(n=!0);if(n){if(!confirm(jSuites.translate("This action will destroy any existing merged cells. Are you sure?")))return!1;s.destroyMerge()}const r=s.options.columns?s.options.columns.splice(e,t):void 0;for(let n=e;n<e+t;n++)s.cols[n].colElement.className="",s.headers[n].className="",s.cols[n].colElement.parentNode.removeChild(s.cols[n].colElement),s.headers[n].parentNode.removeChild(s.headers[n]);const l=s.headers.splice(e,t),i=s.cols.splice(e,t),a=[],c=[],d=[];for(let n=0;n<s.options.data.length;n++)for(let o=e;o<e+t;o++)s.records[n][o].element.className="",s.records[n][o].element.parentNode.removeChild(s.records[n][o].element);for(let n=0;n<s.options.data.length;n++)c[n]=s.options.data[n].splice(e,t),a[n]=s.records[n].splice(e,t);for(let t=e;t<s.cols.length;t++)s.cols[t].x=t;for(let t=0;t<s.records.length;t++)for(let n=e;n<s.records[t].length;n++)s.records[t][n].x=n;if(s.options.footers)for(let n=0;n<s.options.footers.length;n++)d[n]=s.options.footers[n].splice(e,t);if(selection.at.call(s,0,e,e+t-1),s.options.nestedHeaders&&s.options.nestedHeaders.length>0&&s.options.nestedHeaders[0]&&s.options.nestedHeaders[0][0])for(let e=0;e<s.options.nestedHeaders.length;e++){const n=parseInt(s.options.nestedHeaders[e][s.options.nestedHeaders[e].length-1].colspan)-t;s.options.nestedHeaders[e][s.options.nestedHeaders[e].length-1].colspan=n,s.thead.children[e].children[s.thead.children[e].children.length-1].setAttribute("colspan",n)}utils_history.Dh.call(s,{action:"deleteColumn",columnNumber:e,numOfColumns:t,insertBefore:1,columns:r,headers:l,cols:i,records:a,footers:d,data:c}),internal.o8.call(s),dispatch.A.call(s,"ondeletecolumn",s,o)}}else console.error("Jspreadsheet: It is not possible to delete the last column")},getWidth=function(e){const t=this;let s;if(void 0===e){s=[];for(let e=0;e<t.headers.length;e++)s.push(t.options.columns&&t.options.columns[e]&&t.options.columns[e].width||t.options.defaultColWidth||100)}else s=parseInt(t.cols[e].colElement.getAttribute("width"));return s},setWidth=function(e,t,s){const n=this;if(t){if(Array.isArray(e)){s||(s=[]);for(let o=0;o<e.length;o++){s[o]||(s[o]=parseInt(n.cols[e[o]].colElement.getAttribute("width")));const r=Array.isArray(t)&&t[o]?t[o]:t;n.cols[e[o]].colElement.setAttribute("width",r),n.options.columns||(n.options.columns=[]),n.options.columns[e[o]]||(n.options.columns[e[o]]={}),n.options.columns[e[o]].width=r}}else s||(s=parseInt(n.cols[e].colElement.getAttribute("width"))),n.cols[e].colElement.setAttribute("width",t),n.options.columns||(n.options.columns=[]),n.options.columns[e]||(n.options.columns[e]={}),n.options.columns[e].width=t;utils_history.Dh.call(n,{action:"setWidth",column:e,oldValue:s,newValue:t}),dispatch.A.call(n,"onresizecolumn",n,e,t,s),selection.Aq.call(n)}},showColumn=function(e){const t=this;Array.isArray(e)||(e=[e]);for(let s=0;s<e.length;s++){const n=e[s];t.headers[n].style.display="",t.cols[n].colElement.style.display="",t.filter&&t.filter.children.length>n+1&&(t.filter.children[n+1].style.display="");for(let e=0;e<t.options.data.length;e++)t.records[e][n].element.style.display=""}t.options.footers&&footer.e.call(t),t.resetSelection()},hideColumn=function(e){const t=this;Array.isArray(e)||(e=[e]);for(let s=0;s<e.length;s++){const n=e[s];t.headers[n].style.display="none",t.cols[n].colElement.style.display="none",t.filter&&t.filter.children.length>n+1&&(t.filter.children[n+1].style.display="none");for(let e=0;e<t.options.data.length;e++)t.records[e][n].element.style.display="none"}t.options.footers&&footer.e.call(t),t.resetSelection()},getColumnData=function(e,t){const s=this,n=[];for(let o=0;o<s.options.data.length;o++)t?n.push(s.records[o][e].element.innerHTML):n.push(s.options.data[o][e]);return n},setColumnData=function(e,t,s){const n=this;for(let o=0;o<n.rows.length;o++){const r=(0,internalHelpers.t3)([e,o]);null!=t[o]&&n.setValue(r,t[o],s)}},createRow=function(e,t){const s=this;s.records[e]||(s.records[e]=[]),t||(t=s.options.data[e]);const n={element:document.createElement("tr"),y:e};s.rows[e]=n,n.element.setAttribute("data-y",e);let o=null;s.options.defaultRowHeight&&(n.element.style.height=s.options.defaultRowHeight+"px"),s.options.rows&&s.options.rows[e]&&(s.options.rows[e].height&&(n.element.style.height=s.options.rows[e].height),s.options.rows[e].title&&(o=s.options.rows[e].title)),o||(o=parseInt(e+1));const r=document.createElement("td");r.innerHTML=o,r.setAttribute("data-y",e),r.className="jss_row",n.element.appendChild(r);const l=getNumberOfColumns.call(s);for(let o=0;o<l;o++)s.records[e][o]={element:internal.P9.call(this,o,e,t[o]),x:o,y:e},n.element.appendChild(s.records[e][o].element),s.options.columns&&s.options.columns[o]&&"function"==typeof s.options.columns[o].render&&s.options.columns[o].render(s.records[e][o].element,t[o],parseInt(o),parseInt(e),s,s.options.columns[o]);return n},insertRow=function(e,t,s){const n=this;if(0!=n.options.allowInsertRow){let o,r=[];Array.isArray(e)?(o=1,e&&(r=e)):o=void 0!==e?e:1,s=!!s;const l=n.options.data.length-1;(null==t||t>=parseInt(l)||t<0)&&(t=l);const i=[];for(let e=0;e<o;e++){const o=[];for(let e=0;e<n.options.columns.length;e++)o[e]=r[e]?r[e]:"";i.push({row:e+t+(s?0:1),data:o})}if(!1===dispatch.A.call(n,"onbeforeinsertrow",n,i))return!1;if(n.options.mergeCells&&Object.keys(n.options.mergeCells).length>0&&merges.D0.call(n,t,s).length){if(!confirm(jSuites.translate("This action will destroy any existing merged cells. Are you sure?")))return!1;n.destroyMerge()}if(1==n.options.search){if(n.results&&n.results.length!=n.rows.length){if(!confirm(jSuites.translate("This action will clear your search results. Are you sure?")))return!1;n.resetSearch()}n.results=null}const a=s?t:t+1,c=n.records.splice(a),d=n.options.data.splice(a),u=n.rows.splice(a),p=[],h=[],m=[];for(let e=a;e<o+a;e++){n.options.data[e]=[];for(let t=0;t<n.options.columns.length;t++)n.options.data[e][t]=r[t]?r[t]:"";const s=createRow.call(n,e,n.options.data[e]);u[0]?Array.prototype.indexOf.call(n.tbody.children,u[0].element)>=0&&n.tbody.insertBefore(s.element,u[0].element):Array.prototype.indexOf.call(n.tbody.children,n.rows[t].element)>=0&&n.tbody.appendChild(s.element),p.push([...n.records[e]]),h.push([...n.options.data[e]]),m.push(s)}Array.prototype.push.apply(n.records,c),Array.prototype.push.apply(n.options.data,d),Array.prototype.push.apply(n.rows,u);for(let e=a;e<n.rows.length;e++)n.rows[e].y=e;for(let e=a;e<n.records.length;e++)for(let t=0;t<n.records[e].length;t++)n.records[e][t].y=e;n.options.pagination>0&&n.page(n.pageNumber),utils_history.Dh.call(n,{action:"insertRow",rowNumber:t,numOfRows:o,insertBefore:s,rowRecords:p,rowData:h,rowNode:m}),internal.o8.call(n),dispatch.A.call(n,"oninsertrow",n,i)}},moveRow=function(e,t,s){const n=this;if(n.options.mergeCells&&Object.keys(n.options.mergeCells).length>0){let s;if(s=e>t?1:0,merges.D0.call(n,e).length||merges.D0.call(n,t,s).length){if(!confirm(jSuites.translate("This action will destroy any existing merged cells. Are you sure?")))return!1;n.destroyMerge()}}if(1==n.options.search){if(n.results&&n.results.length!=n.rows.length){if(!confirm(jSuites.translate("This action will clear your search results. Are you sure?")))return!1;n.resetSearch()}n.results=null}s||(Array.prototype.indexOf.call(n.tbody.children,n.rows[t].element)>=0?e>t?n.tbody.insertBefore(n.rows[e].element,n.rows[t].element):n.tbody.insertBefore(n.rows[e].element,n.rows[t].element.nextSibling):n.tbody.removeChild(n.rows[e].element)),n.rows.splice(t,0,n.rows.splice(e,1)[0]),n.records.splice(t,0,n.records.splice(e,1)[0]),n.options.data.splice(t,0,n.options.data.splice(e,1)[0]);const o=Math.min(e,t),r=Math.max(e,t);for(let e=o;e<=r;e++)n.rows[e].y=e;for(let e=o;e<=r;e++)for(let t=0;t<n.records[e].length;t++)n.records[e][t].y=e;n.options.pagination>0&&n.tbody.children.length!=n.options.pagination&&n.page(n.pageNumber),utils_history.Dh.call(n,{action:"moveRow",oldValue:e,newValue:t}),internal.o8.call(n),dispatch.A.call(n,"onmoverow",n,parseInt(e),parseInt(t),1)},deleteRow=function(e,t){const s=this;if(0!=s.options.allowDeleteRow)if(1==s.options.allowDeletingAllRows||s.options.data.length>1){if(null==e){const n=selection.R5.call(s);0===n.length?(e=s.options.data.length-1,t=1):(e=n[0],t=n.length)}let n=s.options.data.length-1;(null==e||e>n||e<0)&&(e=n),t||(t=1),e+t>=s.options.data.length&&(t=s.options.data.length-e);const o=[];for(let s=0;s<t;s++)o.push(s+e);if(!1===dispatch.A.call(s,"onbeforedeleterow",s,o))return!1;if(parseInt(e)>-1){let r=!1;if(s.options.mergeCells&&Object.keys(s.options.mergeCells).length>0)for(let n=e;n<e+t;n++)merges.D0.call(s,n,!1).length&&(r=!0);if(r){if(!confirm(jSuites.translate("This action will destroy any existing merged cells. Are you sure?")))return!1;s.destroyMerge()}if(1==s.options.search){if(s.results&&s.results.length!=s.rows.length){if(!confirm(jSuites.translate("This action will clear your search results. Are you sure?")))return!1;s.resetSearch()}s.results=null}1!=s.options.allowDeletingAllRows&&n+1===t&&(t--,console.error("Jspreadsheet: It is not possible to delete the last row"));for(let n=e;n<e+t;n++)Array.prototype.indexOf.call(s.tbody.children,s.rows[n].element)>=0&&(s.rows[n].element.className="",s.rows[n].element.parentNode.removeChild(s.rows[n].element));const l=s.records.splice(e,t),i=s.options.data.splice(e,t),a=s.rows.splice(e,t);for(let t=e;t<s.rows.length;t++)s.rows[t].y=t;for(let t=e;t<s.records.length;t++)for(let e=0;e<s.records[t].length;e++)s.records[t][e].y=t;s.options.pagination>0&&s.tbody.children.length!=s.options.pagination&&s.page(s.pageNumber),selection.at.call(s,1,e,e+t-1),utils_history.Dh.call(s,{action:"deleteRow",rowNumber:e,numOfRows:t,insertBefore:1,rowRecords:l,rowData:i,rowNode:a}),internal.o8.call(s),dispatch.A.call(s,"ondeleterow",s,o)}}else console.error("Jspreadsheet: It is not possible to delete the last row")},getHeight=function(e){const t=this;let s;if(void 0===e){s=[];for(let e=0;e<t.rows.length;e++){const n=t.rows[e].element.style.height;n&&(s[e]=n)}}else"object"==typeof e&&(e=$(e).getAttribute("data-y")),s=t.rows[e].element.style.height;return s},setHeight=function(e,t,s){const n=this;t>0&&(s||(s=n.rows[e].element.getAttribute("height"))||(s=n.rows[e].element.getBoundingClientRect().height),t=parseInt(t),n.rows[e].element.style.height=t+"px",n.options.rows||(n.options.rows=[]),n.options.rows[e]||(n.options.rows[e]={}),n.options.rows[e].height=t,utils_history.Dh.call(n,{action:"setHeight",row:e,oldValue:s,newValue:t}),dispatch.A.call(n,"onresizerow",n,e,t,s),selection.Aq.call(n))},showRow=function(e){const t=this;Array.isArray(e)||(e=[e]),e.forEach((function(e){t.rows[e].element.style.display=""}))},hideRow=function(e){const t=this;Array.isArray(e)||(e=[e]),e.forEach((function(e){t.rows[e].element.style.display="none"}))},getRowData=function(e,t){return t?this.records[e].map((function(e){return e.element.innerHTML})):this.options.data[e]},setRowData=function(e,t,s){const n=this;for(let o=0;o<n.headers.length;o++){const r=(0,internalHelpers.t3)([o,e]);null!=t[o]&&n.setValue(r,t[o],s)}};var version={version:"5.0.0",host:"https://bossanova.uk/jspreadsheet",license:"MIT",print:function(){return[["Jspreadsheet CE",this.version,this.host,this.license].join("\r\n")]}};const getElement=function(e){let t=0,s=0;return function e(n){n.className&&(n.classList.contains("jss_container")&&(s=n),n.classList.contains("jss_spreadsheet")&&(s=n.querySelector(":scope > .jtabs-content > .jtabs-selected"))),"THEAD"==n.tagName?t=1:"TBODY"==n.tagName&&(t=2),n.parentNode&&(s||e(n.parentNode))}(e),[s,t]},mouseUpControls=function(e){if(libraryBase.jspreadsheet.current)if(libraryBase.jspreadsheet.current.resizing){if(libraryBase.jspreadsheet.current.resizing.column){const e=parseInt(libraryBase.jspreadsheet.current.cols[libraryBase.jspreadsheet.current.resizing.column].colElement.getAttribute("width")),t=libraryBase.jspreadsheet.current.getSelectedColumns();if(t.length>1){const s=[];for(let e=0;e<t.length;e++)s.push(parseInt(libraryBase.jspreadsheet.current.cols[t[e]].colElement.getAttribute("width")));s[t.indexOf(parseInt(libraryBase.jspreadsheet.current.resizing.column))]=libraryBase.jspreadsheet.current.resizing.width,setWidth.call(libraryBase.jspreadsheet.current,t,e,s)}else setWidth.call(libraryBase.jspreadsheet.current,parseInt(libraryBase.jspreadsheet.current.resizing.column),e,libraryBase.jspreadsheet.current.resizing.width);libraryBase.jspreadsheet.current.headers[libraryBase.jspreadsheet.current.resizing.column].classList.remove("resizing");for(let e=0;e<libraryBase.jspreadsheet.current.records.length;e++)libraryBase.jspreadsheet.current.records[e][libraryBase.jspreadsheet.current.resizing.column]&&libraryBase.jspreadsheet.current.records[e][libraryBase.jspreadsheet.current.resizing.column].element.classList.remove("resizing")}else{libraryBase.jspreadsheet.current.rows[libraryBase.jspreadsheet.current.resizing.row].element.children[0].classList.remove("resizing");let e=libraryBase.jspreadsheet.current.rows[libraryBase.jspreadsheet.current.resizing.row].element.getAttribute("height");setHeight.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.resizing.row,e,libraryBase.jspreadsheet.current.resizing.height),libraryBase.jspreadsheet.current.resizing.element.classList.remove("resizing")}libraryBase.jspreadsheet.current.resizing=null}else if(libraryBase.jspreadsheet.current.dragging){if(libraryBase.jspreadsheet.current.dragging){if(libraryBase.jspreadsheet.current.dragging.column){const t=e.target.getAttribute("data-x");libraryBase.jspreadsheet.current.headers[libraryBase.jspreadsheet.current.dragging.column].classList.remove("dragging");for(let e=0;e<libraryBase.jspreadsheet.current.rows.length;e++)libraryBase.jspreadsheet.current.records[e][libraryBase.jspreadsheet.current.dragging.column]&&libraryBase.jspreadsheet.current.records[e][libraryBase.jspreadsheet.current.dragging.column].element.classList.remove("dragging");for(let e=0;e<libraryBase.jspreadsheet.current.headers.length;e++)libraryBase.jspreadsheet.current.headers[e].classList.remove("dragging-left"),libraryBase.jspreadsheet.current.headers[e].classList.remove("dragging-right");t&&libraryBase.jspreadsheet.current.dragging.column!=libraryBase.jspreadsheet.current.dragging.destination&&libraryBase.jspreadsheet.current.moveColumn(libraryBase.jspreadsheet.current.dragging.column,libraryBase.jspreadsheet.current.dragging.destination)}else{let e;libraryBase.jspreadsheet.current.dragging.element.nextSibling?(e=parseInt(libraryBase.jspreadsheet.current.dragging.element.nextSibling.getAttribute("data-y")),libraryBase.jspreadsheet.current.dragging.row<e&&(e-=1)):e=parseInt(libraryBase.jspreadsheet.current.dragging.element.previousSibling.getAttribute("data-y")),libraryBase.jspreadsheet.current.dragging.row!=libraryBase.jspreadsheet.current.dragging.destination&&moveRow.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.dragging.row,e,!0),libraryBase.jspreadsheet.current.dragging.element.classList.remove("dragging")}libraryBase.jspreadsheet.current.dragging=null}}else libraryBase.jspreadsheet.current.selectedCorner&&(libraryBase.jspreadsheet.current.selectedCorner=!1,libraryBase.jspreadsheet.current.selection.length>0&&(selection.kF.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.selection[0],libraryBase.jspreadsheet.current.selection[libraryBase.jspreadsheet.current.selection.length-1]),selection.gG.call(libraryBase.jspreadsheet.current)));libraryBase.jspreadsheet.timeControl&&(clearTimeout(libraryBase.jspreadsheet.timeControl),libraryBase.jspreadsheet.timeControl=null),libraryBase.jspreadsheet.isMouseAction=!1},mouseDownControls=function(e){let t;t=(e=e||window.event).buttons?e.buttons:e.button?e.button:e.which;const s=getElement(e.target);if(s[0]?libraryBase.jspreadsheet.current!=s[0].jssWorksheet&&(libraryBase.jspreadsheet.current&&(libraryBase.jspreadsheet.current.edition&&closeEditor.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.edition[0],!0),libraryBase.jspreadsheet.current.resetSelection()),libraryBase.jspreadsheet.current=s[0].jssWorksheet):libraryBase.jspreadsheet.current&&(libraryBase.jspreadsheet.current.edition&&closeEditor.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.edition[0],!0),e.target.classList.contains("jss_object")||(selection.gE.call(libraryBase.jspreadsheet.current,!0),libraryBase.jspreadsheet.current=null)),libraryBase.jspreadsheet.current&&1==t){if(e.target.classList.contains("jss_selectall"))libraryBase.jspreadsheet.current&&selection.Ub.call(libraryBase.jspreadsheet.current);else if(e.target.classList.contains("jss_corner"))0!=libraryBase.jspreadsheet.current.options.editable&&(libraryBase.jspreadsheet.current.selectedCorner=!0);else{if(1==s[1]){const t=e.target.getAttribute("data-x");if(t){const s=e.target.getBoundingClientRect();if(0!=libraryBase.jspreadsheet.current.options.columnResize&&s.width-e.offsetX<6){libraryBase.jspreadsheet.current.resizing={mousePosition:e.pageX,column:t,width:s.width},libraryBase.jspreadsheet.current.headers[t].classList.add("resizing");for(let e=0;e<libraryBase.jspreadsheet.current.records.length;e++)libraryBase.jspreadsheet.current.records[e][t]&&libraryBase.jspreadsheet.current.records[e][t].element.classList.add("resizing")}else if(0!=libraryBase.jspreadsheet.current.options.columnDrag&&s.height-e.offsetY<6)if(merges.Lt.call(libraryBase.jspreadsheet.current,t).length)console.error("Jspreadsheet: This column is part of a merged cell.");else{libraryBase.jspreadsheet.current.resetSelection(),libraryBase.jspreadsheet.current.dragging={element:e.target,column:t,destination:t},libraryBase.jspreadsheet.current.headers[t].classList.add("dragging");for(let e=0;e<libraryBase.jspreadsheet.current.records.length;e++)libraryBase.jspreadsheet.current.records[e][t]&&libraryBase.jspreadsheet.current.records[e][t].element.classList.add("dragging")}else{let s,n;libraryBase.jspreadsheet.current.selectedHeader&&(e.shiftKey||e.ctrlKey)?(s=libraryBase.jspreadsheet.current.selectedHeader,n=t):(libraryBase.jspreadsheet.current.selectedHeader==t&&0!=libraryBase.jspreadsheet.current.options.allowRenameColumn&&(libraryBase.jspreadsheet.timeControl=setTimeout((function(){libraryBase.jspreadsheet.current.setHeader(t)}),800)),libraryBase.jspreadsheet.current.selectedHeader=t,s=t,n=t),selection.AH.call(libraryBase.jspreadsheet.current,s,0,n,libraryBase.jspreadsheet.current.options.data.length-1,e)}}else if(e.target.parentNode.classList.contains("jss_nested")){let t,s;if(e.target.getAttribute("data-column")){const n=e.target.getAttribute("data-column").split(",");t=parseInt(n[0]),s=parseInt(n[n.length-1])}else t=0,s=libraryBase.jspreadsheet.current.options.columns.length-1;selection.AH.call(libraryBase.jspreadsheet.current,t,0,s,libraryBase.jspreadsheet.current.options.data.length-1,e)}}else libraryBase.jspreadsheet.current.selectedHeader=!1;if(2==s[1]){const t=parseInt(e.target.getAttribute("data-y"));if(e.target.classList.contains("jss_row")){const s=e.target.getBoundingClientRect();if(0!=libraryBase.jspreadsheet.current.options.rowResize&&s.height-e.offsetY<6)libraryBase.jspreadsheet.current.resizing={element:e.target.parentNode,mousePosition:e.pageY,row:t,height:s.height},e.target.parentNode.classList.add("resizing");else if(0!=libraryBase.jspreadsheet.current.options.rowDrag&&s.width-e.offsetX<6)merges.D0.call(libraryBase.jspreadsheet.current,t).length?console.error("Jspreadsheet: This row is part of a merged cell"):1==libraryBase.jspreadsheet.current.options.search&&libraryBase.jspreadsheet.current.results?console.error("Jspreadsheet: Please clear your search before perform this action"):(libraryBase.jspreadsheet.current.resetSelection(),libraryBase.jspreadsheet.current.dragging={element:e.target.parentNode,row:t,destination:t},e.target.parentNode.classList.add("dragging"));else{let s,n;null!=libraryBase.jspreadsheet.current.selectedRow&&(e.shiftKey||e.ctrlKey)?(s=libraryBase.jspreadsheet.current.selectedRow,n=t):(libraryBase.jspreadsheet.current.selectedRow=t,s=t,n=t),selection.AH.call(libraryBase.jspreadsheet.current,null,s,null,n,e)}}else if(e.target.classList.contains("jclose")&&e.target.clientWidth-e.offsetX<50&&e.offsetY<50)closeEditor.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.edition[0],!0);else{const t=function(e){const s=e.getAttribute("data-x"),n=e.getAttribute("data-y");return s&&n?[s,n]:e.parentNode?t(e.parentNode):void 0},s=t(e.target);if(s){const t=s[0],n=s[1];libraryBase.jspreadsheet.current.edition&&(libraryBase.jspreadsheet.current.edition[2]==t&&libraryBase.jspreadsheet.current.edition[3]==n||closeEditor.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.edition[0],!0)),libraryBase.jspreadsheet.current.edition||(e.shiftKey?selection.AH.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.selectedCell[0],libraryBase.jspreadsheet.current.selectedCell[1],t,n,e):selection.AH.call(libraryBase.jspreadsheet.current,t,n,void 0,void 0,e)),libraryBase.jspreadsheet.current.selectedHeader=null,libraryBase.jspreadsheet.current.selectedRow=null}}}else libraryBase.jspreadsheet.current.selectedRow=!1;e.target.classList.contains("jss_page")&&("<"==e.target.textContent?libraryBase.jspreadsheet.current.page(0):">"==e.target.textContent?libraryBase.jspreadsheet.current.page(e.target.getAttribute("title")-1):libraryBase.jspreadsheet.current.page(e.target.textContent-1))}libraryBase.jspreadsheet.current.edition?libraryBase.jspreadsheet.isMouseAction=!1:libraryBase.jspreadsheet.isMouseAction=!0}else libraryBase.jspreadsheet.isMouseAction=!1},mouseMoveControls=function(e){let t;if(t=(e=e||window.event).buttons?e.buttons:e.button?e.button:e.which,t||(libraryBase.jspreadsheet.isMouseAction=!1),libraryBase.jspreadsheet.current)if(1==libraryBase.jspreadsheet.isMouseAction){if(libraryBase.jspreadsheet.current.resizing)if(libraryBase.jspreadsheet.current.resizing.column){const t=e.pageX-libraryBase.jspreadsheet.current.resizing.mousePosition;if(libraryBase.jspreadsheet.current.resizing.width+t>0){const e=libraryBase.jspreadsheet.current.resizing.width+t;libraryBase.jspreadsheet.current.cols[libraryBase.jspreadsheet.current.resizing.column].colElement.setAttribute("width",e),selection.Aq.call(libraryBase.jspreadsheet.current)}}else{const t=e.pageY-libraryBase.jspreadsheet.current.resizing.mousePosition;if(libraryBase.jspreadsheet.current.resizing.height+t>0){const e=libraryBase.jspreadsheet.current.resizing.height+t;libraryBase.jspreadsheet.current.rows[libraryBase.jspreadsheet.current.resizing.row].element.setAttribute("height",e),selection.Aq.call(libraryBase.jspreadsheet.current)}}else if(libraryBase.jspreadsheet.current.dragging)if(libraryBase.jspreadsheet.current.dragging.column){const t=e.target.getAttribute("data-x");if(t)if(merges.Lt.call(libraryBase.jspreadsheet.current,t).length)console.error("Jspreadsheet: This column is part of a merged cell.");else{for(let e=0;e<libraryBase.jspreadsheet.current.headers.length;e++)libraryBase.jspreadsheet.current.headers[e].classList.remove("dragging-left"),libraryBase.jspreadsheet.current.headers[e].classList.remove("dragging-right");libraryBase.jspreadsheet.current.dragging.column==t?libraryBase.jspreadsheet.current.dragging.destination=parseInt(t):e.target.clientWidth/2>e.offsetX?(libraryBase.jspreadsheet.current.dragging.column<t?libraryBase.jspreadsheet.current.dragging.destination=parseInt(t)-1:libraryBase.jspreadsheet.current.dragging.destination=parseInt(t),libraryBase.jspreadsheet.current.headers[t].classList.add("dragging-left")):(libraryBase.jspreadsheet.current.dragging.column<t?libraryBase.jspreadsheet.current.dragging.destination=parseInt(t):libraryBase.jspreadsheet.current.dragging.destination=parseInt(t)+1,libraryBase.jspreadsheet.current.headers[t].classList.add("dragging-right"))}}else{const t=e.target.getAttribute("data-y");if(t)if(merges.D0.call(libraryBase.jspreadsheet.current,t).length)console.error("Jspreadsheet: This row is part of a merged cell.");else{const t=e.target.clientHeight/2>e.offsetY?e.target.parentNode.nextSibling:e.target.parentNode;libraryBase.jspreadsheet.current.dragging.element!=t&&(e.target.parentNode.parentNode.insertBefore(libraryBase.jspreadsheet.current.dragging.element,t),libraryBase.jspreadsheet.current.dragging.destination=Array.prototype.indexOf.call(libraryBase.jspreadsheet.current.dragging.element.parentNode.children,libraryBase.jspreadsheet.current.dragging.element))}}}else{const t=e.target.getAttribute("data-x"),s=e.target.getAttribute("data-y"),n=e.target.getBoundingClientRect();libraryBase.jspreadsheet.current.cursor&&(libraryBase.jspreadsheet.current.cursor.style.cursor="",libraryBase.jspreadsheet.current.cursor=null),e.target.parentNode.parentNode&&e.target.parentNode.parentNode.className&&(e.target.parentNode.parentNode.classList.contains("resizable")&&(e.target&&t&&!s&&n.width-(e.clientX-n.left)<6?(libraryBase.jspreadsheet.current.cursor=e.target,libraryBase.jspreadsheet.current.cursor.style.cursor="col-resize"):e.target&&!t&&s&&n.height-(e.clientY-n.top)<6&&(libraryBase.jspreadsheet.current.cursor=e.target,libraryBase.jspreadsheet.current.cursor.style.cursor="row-resize")),e.target.parentNode.parentNode.classList.contains("draggable")&&(e.target&&!t&&s&&n.width-(e.clientX-n.left)<6||e.target&&t&&!s&&n.height-(e.clientY-n.top)<6)&&(libraryBase.jspreadsheet.current.cursor=e.target,libraryBase.jspreadsheet.current.cursor.style.cursor="move"))}},updateCopySelection=function(e,t){const s=this;selection.gG.call(s);const n=s.selectedContainer[0],o=s.selectedContainer[1],r=s.selectedContainer[2],l=s.selectedContainer[3];if(null!=e&&null!=t){let i,a,c,d;e-r>0?(i=parseInt(r)+1,a=parseInt(e)):(i=parseInt(e),a=parseInt(n)-1),t-l>0?(c=parseInt(l)+1,d=parseInt(t)):(c=parseInt(t),d=parseInt(o)-1),a-i<=d-c?(i=parseInt(n),a=parseInt(r)):(c=parseInt(o),d=parseInt(l));for(let e=c;e<=d;e++)for(let t=i;t<=a;t++)s.records[e][t]&&"none"!=s.rows[e].element.style.display&&"none"!=s.records[e][t].element.style.display&&(s.records[e][t].element.classList.add("selection"),s.records[c][t].element.classList.add("selection-top"),s.records[d][t].element.classList.add("selection-bottom"),s.records[e][i].element.classList.add("selection-left"),s.records[e][a].element.classList.add("selection-right"),s.selection.push(s.records[e][t].element))}},mouseOverControls=function(e){let t;if(t=(e=e||window.event).buttons?e.buttons:e.button?e.button:e.which,t||(libraryBase.jspreadsheet.isMouseAction=!1),libraryBase.jspreadsheet.current&&1==libraryBase.jspreadsheet.isMouseAction){const t=getElement(e.target);if(t[0]){if(libraryBase.jspreadsheet.current!=t[0].jssWorksheet&&libraryBase.jspreadsheet.current)return!1;let s=e.target.getAttribute("data-x");const n=e.target.getAttribute("data-y");if(libraryBase.jspreadsheet.current.resizing||libraryBase.jspreadsheet.current.dragging);else{if(1==t[1]&&libraryBase.jspreadsheet.current.selectedHeader){s=e.target.getAttribute("data-x");const t=libraryBase.jspreadsheet.current.selectedHeader,n=s;selection.AH.call(libraryBase.jspreadsheet.current,t,0,n,libraryBase.jspreadsheet.current.options.data.length-1,e)}if(2==t[1])if(e.target.classList.contains("jss_row")){if(null!=libraryBase.jspreadsheet.current.selectedRow){const t=libraryBase.jspreadsheet.current.selectedRow,s=n;selection.AH.call(libraryBase.jspreadsheet.current,0,t,libraryBase.jspreadsheet.current.options.data[0].length-1,s,e)}}else libraryBase.jspreadsheet.current.edition||s&&n&&(libraryBase.jspreadsheet.current.selectedCorner?updateCopySelection.call(libraryBase.jspreadsheet.current,s,n):libraryBase.jspreadsheet.current.selectedCell&&selection.AH.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.selectedCell[0],libraryBase.jspreadsheet.current.selectedCell[1],s,n,e))}}}libraryBase.jspreadsheet.timeControl&&(clearTimeout(libraryBase.jspreadsheet.timeControl),libraryBase.jspreadsheet.timeControl=null)},doubleClickControls=function(e){if(libraryBase.jspreadsheet.current)if(e.target.classList.contains("jss_corner")){if(libraryBase.jspreadsheet.current.highlighted.length>0){const e=libraryBase.jspreadsheet.current.highlighted[0].element.getAttribute("data-x"),t=parseInt(libraryBase.jspreadsheet.current.highlighted[libraryBase.jspreadsheet.current.highlighted.length-1].element.getAttribute("data-y"))+1,s=libraryBase.jspreadsheet.current.highlighted[libraryBase.jspreadsheet.current.highlighted.length-1].element.getAttribute("data-x"),n=libraryBase.jspreadsheet.current.records.length-1;selection.kF.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.records[t][e].element,libraryBase.jspreadsheet.current.records[n][s].element)}}else if(e.target.classList.contains("jss_column_filter")){const t=e.target.getAttribute("data-x");filter.N$.call(libraryBase.jspreadsheet.current,t)}else{const t=getElement(e.target);if(1==t[1]&&0!=libraryBase.jspreadsheet.current.options.columnSorting){const t=e.target.getAttribute("data-x");t&&libraryBase.jspreadsheet.current.orderBy(parseInt(t))}if(2==t[1]&&0!=libraryBase.jspreadsheet.current.options.editable&&!libraryBase.jspreadsheet.current.edition){const t=function(e){if(e.parentNode){const s=e.getAttribute("data-x"),n=e.getAttribute("data-y");return s&&n?e:t(e.parentNode)}},s=t(e.target);s&&s.classList.contains("highlight")&&openEditor.call(libraryBase.jspreadsheet.current,s,void 0,e)}}},pasteControls=function(e){libraryBase.jspreadsheet.current&&libraryBase.jspreadsheet.current.selectedCell&&(libraryBase.jspreadsheet.current.edition||0!=libraryBase.jspreadsheet.current.options.editable&&(e&&e.clipboardData?(paste.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.selectedCell[0],libraryBase.jspreadsheet.current.selectedCell[1],e.clipboardData.getData("text")),e.preventDefault()):window.clipboardData&&paste.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.selectedCell[0],libraryBase.jspreadsheet.current.selectedCell[1],window.clipboardData.getData("text"))))},getRole=function(e){if(e.classList.contains("jss_selectall"))return"select-all";if(e.classList.contains("jss_corner"))return"fill-handle";let t=e;for(;!t.classList.contains("jss_spreadsheet");){if(t.classList.contains("jss_row"))return"row";if(t.classList.contains("jss_nested"))return"nested";if(t.classList.contains("jtabs-headers"))return"tabs";if(t.classList.contains("jtoolbar"))return"toolbar";if(t.classList.contains("jss_pagination"))return"pagination";if("TBODY"===t.tagName)return"cell";if("TFOOT"===t.tagName)return 0===getElementIndex(e)?"grid":"footer";if("THEAD"===t.tagName)return"header";t=t.parentElement}return"applications"},defaultContextMenu=function(e,t,s,n){const o=[];if("header"===n&&(0!=e.options.allowInsertColumn&&o.push({title:jSuites.translate("Insert a new column before"),onclick:function(){e.insertColumn(1,parseInt(t),1)}}),0!=e.options.allowInsertColumn&&o.push({title:jSuites.translate("Insert a new column after"),onclick:function(){e.insertColumn(1,parseInt(t),0)}}),0!=e.options.allowDeleteColumn&&o.push({title:jSuites.translate("Delete selected columns"),onclick:function(){e.deleteColumn(e.getSelectedColumns().length?void 0:parseInt(t))}}),0!=e.options.allowRenameColumn&&o.push({title:jSuites.translate("Rename this column"),onclick:function(){const s=e.getHeader(t),n=prompt(jSuites.translate("Column name"),s);e.setHeader(t,n)}}),0!=e.options.columnSorting&&(o.push({type:"line"}),o.push({title:jSuites.translate("Order ascending"),onclick:function(){e.orderBy(t,0)}}),o.push({title:jSuites.translate("Order descending"),onclick:function(){e.orderBy(t,1)}}))),"row"!==n&&"cell"!==n||(0!=e.options.allowInsertRow&&(o.push({title:jSuites.translate("Insert a new row before"),onclick:function(){e.insertRow(1,parseInt(s),1)}}),o.push({title:jSuites.translate("Insert a new row after"),onclick:function(){e.insertRow(1,parseInt(s))}})),0!=e.options.allowDeleteRow&&o.push({title:jSuites.translate("Delete selected rows"),onclick:function(){e.deleteRow(e.getSelectedRows().length?void 0:parseInt(s))}})),"cell"===n&&0!=e.options.allowComments){o.push({type:"line"});const n=e.records[s][t].element.getAttribute("title")||"";o.push({title:jSuites.translate(n?"Edit comments":"Add comments"),onclick:function(){const o=prompt(jSuites.translate("Comments"),n);o&&e.setComments((0,helpers.getCellNameFromCoords)(t,s),o)}}),n&&o.push({title:jSuites.translate("Clear comments"),onclick:function(){e.setComments((0,helpers.getCellNameFromCoords)(t,s),"")}})}return 0!==o.length&&o.push({type:"line"}),"header"!==n&&"row"!==n&&"cell"!==n||(o.push({title:jSuites.translate("Copy")+"...",shortcut:"Ctrl + C",onclick:function(){copy.call(e,!0)}}),navigator&&navigator.clipboard&&o.push({title:jSuites.translate("Paste")+"...",shortcut:"Ctrl + V",onclick:function(){e.selectedCell&&navigator.clipboard.readText().then((function(t){t&&paste.call(e,e.selectedCell[0],e.selectedCell[1],t)}))}})),0!=e.parent.config.allowExport&&o.push({title:jSuites.translate("Save as")+"...",shortcut:"Ctrl + S",onclick:function(){e.download()}}),0!=e.parent.config.about&&o.push({title:jSuites.translate("About"),onclick:function(){void 0===e.parent.config.about||!0===e.parent.config.about?alert(version.print()):alert(e.parent.config.about)}}),o},getElementIndex=function(e){const t=e.parentElement.children;for(let s=0;s<t.length;s++)if(e===t[s])return s;return-1},contextMenuControls=function(e){if("buttons"in(e=e||window.event)?e.buttons:e.which||e.button,libraryBase.jspreadsheet.current){const t=libraryBase.jspreadsheet.current.parent;if(libraryBase.jspreadsheet.current.edition)e.preventDefault();else if(t.contextMenu.contextmenu.close(),libraryBase.jspreadsheet.current){const s=getRole(e.target);let n=null,o=null;if("cell"===s){let t=e.target;for(;"TD"!==t.tagName;)t=t.parentNode;o=t.getAttribute("data-y"),n=t.getAttribute("data-x"),(!libraryBase.jspreadsheet.current.selectedCell||n<parseInt(libraryBase.jspreadsheet.current.selectedCell[0])||n>parseInt(libraryBase.jspreadsheet.current.selectedCell[2])||o<parseInt(libraryBase.jspreadsheet.current.selectedCell[1])||o>parseInt(libraryBase.jspreadsheet.current.selectedCell[3]))&&selection.AH.call(libraryBase.jspreadsheet.current,n,o,n,o,e)}else if("row"===s||"header"===s)"row"===s?o=e.target.getAttribute("data-y"):n=e.target.getAttribute("data-x"),(!libraryBase.jspreadsheet.current.selectedCell||n<parseInt(libraryBase.jspreadsheet.current.selectedCell[0])||n>parseInt(libraryBase.jspreadsheet.current.selectedCell[2])||o<parseInt(libraryBase.jspreadsheet.current.selectedCell[1])||o>parseInt(libraryBase.jspreadsheet.current.selectedCell[3]))&&selection.AH.call(libraryBase.jspreadsheet.current,n,o,n,o,e);else if("nested"===s){const t=e.target.getAttribute("data-column").split(",");n=getElementIndex(e.target)-1,o=getElementIndex(e.target.parentElement),libraryBase.jspreadsheet.current.selectedCell&&t[0]==parseInt(libraryBase.jspreadsheet.current.selectedCell[0])&&t[t.length-1]==parseInt(libraryBase.jspreadsheet.current.selectedCell[2])&&null==libraryBase.jspreadsheet.current.selectedCell[1]&&null==libraryBase.jspreadsheet.current.selectedCell[3]||selection.AH.call(libraryBase.jspreadsheet.current,t[0],null,t[t.length-1],null,e)}else"select-all"===s?selection.Ub.call(libraryBase.jspreadsheet.current):"tabs"===s?n=getElementIndex(e.target):"footer"===s&&(n=getElementIndex(e.target)-1,o=getElementIndex(e.target.parentElement));let r=defaultContextMenu(libraryBase.jspreadsheet.current,parseInt(n),parseInt(o),s);if("function"==typeof t.config.contextMenu){const l=t.config.contextMenu(libraryBase.jspreadsheet.current,n,o,e,r,s,n,o);if(l)r=l;else if(!1===l)return}"object"==typeof t.plugins&&Object.entries(t.plugins).forEach((function([,t]){if("function"==typeof t.contextMenu){const l=t.contextMenu(libraryBase.jspreadsheet.current,null!==n?parseInt(n):null,null!==o?parseInt(o):null,e,r,s,null!==n?parseInt(n):null,null!==o?parseInt(o):null);l&&(r=l)}})),t.contextMenu.contextmenu.open(e,r),e.preventDefault()}}},touchStartControls=function(e){const t=getElement(e.target);if(t[0]?libraryBase.jspreadsheet.current!=t[0].jssWorksheet&&(libraryBase.jspreadsheet.current&&libraryBase.jspreadsheet.current.resetSelection(),libraryBase.jspreadsheet.current=t[0].jssWorksheet):libraryBase.jspreadsheet.current&&(libraryBase.jspreadsheet.current.resetSelection(),libraryBase.jspreadsheet.current=null),libraryBase.jspreadsheet.current&&!libraryBase.jspreadsheet.current.edition){const t=e.target.getAttribute("data-x"),s=e.target.getAttribute("data-y");t&&s&&(selection.AH.call(libraryBase.jspreadsheet.current,t,s,void 0,void 0,e),libraryBase.jspreadsheet.timeControl=setTimeout((function(){"color"==libraryBase.jspreadsheet.current.options.columns[t].type?libraryBase.jspreadsheet.tmpElement=null:libraryBase.jspreadsheet.tmpElement=e.target,openEditor.call(libraryBase.jspreadsheet.current,e.target,!1,e)}),500))}},touchEndControls=function(e){libraryBase.jspreadsheet.timeControl&&(clearTimeout(libraryBase.jspreadsheet.timeControl),libraryBase.jspreadsheet.timeControl=null,libraryBase.jspreadsheet.tmpElement&&"INPUT"==libraryBase.jspreadsheet.tmpElement.children[0].tagName&&libraryBase.jspreadsheet.tmpElement.children[0].focus(),libraryBase.jspreadsheet.tmpElement=null)},cutControls=function(e){libraryBase.jspreadsheet.current&&(libraryBase.jspreadsheet.current.edition||(copy.call(libraryBase.jspreadsheet.current,!0,void 0,void 0,void 0,void 0,!0),0!=libraryBase.jspreadsheet.current.options.editable&&libraryBase.jspreadsheet.current.setValue(libraryBase.jspreadsheet.current.highlighted.map((function(e){return e.element})),"")))},copyControls=function(e){libraryBase.jspreadsheet.current&&copyControls.enabled&&(libraryBase.jspreadsheet.current.edition||copy.call(libraryBase.jspreadsheet.current,!0))},isMac=function(){return navigator.platform.toUpperCase().indexOf("MAC")>=0},isCtrl=function(e){return isMac()?e.metaKey:e.ctrlKey},keyDownControls=function(e){if(libraryBase.jspreadsheet.current){if(libraryBase.jspreadsheet.current.edition)if(27==e.which)libraryBase.jspreadsheet.current.edition&&closeEditor.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.edition[0],!1),e.preventDefault();else if(13==e.which)if(libraryBase.jspreadsheet.current.options.columns&&libraryBase.jspreadsheet.current.options.columns[libraryBase.jspreadsheet.current.edition[2]]&&"calendar"==libraryBase.jspreadsheet.current.options.columns[libraryBase.jspreadsheet.current.edition[2]].type)closeEditor.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.edition[0],!0);else if(libraryBase.jspreadsheet.current.options.columns&&libraryBase.jspreadsheet.current.options.columns[libraryBase.jspreadsheet.current.edition[2]]&&"dropdown"==libraryBase.jspreadsheet.current.options.columns[libraryBase.jspreadsheet.current.edition[2]].type);else if((1==libraryBase.jspreadsheet.current.options.wordWrap||libraryBase.jspreadsheet.current.options.columns&&libraryBase.jspreadsheet.current.options.columns[libraryBase.jspreadsheet.current.edition[2]]&&1==libraryBase.jspreadsheet.current.options.columns[libraryBase.jspreadsheet.current.edition[2]].wordWrap||libraryBase.jspreadsheet.current.options.data[libraryBase.jspreadsheet.current.edition[3]][libraryBase.jspreadsheet.current.edition[2]]&&libraryBase.jspreadsheet.current.options.data[libraryBase.jspreadsheet.current.edition[3]][libraryBase.jspreadsheet.current.edition[2]].length>200)&&e.altKey){const e=libraryBase.jspreadsheet.current.edition[0].children[0];let t=libraryBase.jspreadsheet.current.edition[0].children[0].value;const s=e.selectionStart;t=t.slice(0,s)+"\n"+t.slice(s),e.value=t,e.focus(),e.selectionStart=s+1,e.selectionEnd=s+1}else libraryBase.jspreadsheet.current.edition[0].children[0].blur();else 9==e.which&&(libraryBase.jspreadsheet.current.options.columns&&libraryBase.jspreadsheet.current.options.columns[libraryBase.jspreadsheet.current.edition[2]]&&["calendar","html"].includes(libraryBase.jspreadsheet.current.options.columns[libraryBase.jspreadsheet.current.edition[2]].type)?closeEditor.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.edition[0],!0):libraryBase.jspreadsheet.current.edition[0].children[0].blur());if(!libraryBase.jspreadsheet.current.edition&&libraryBase.jspreadsheet.current.selectedCell)if(37==e.which)left.call(libraryBase.jspreadsheet.current,e.shiftKey,e.ctrlKey),e.preventDefault();else if(39==e.which)right.call(libraryBase.jspreadsheet.current,e.shiftKey,e.ctrlKey),e.preventDefault();else if(38==e.which)up.call(libraryBase.jspreadsheet.current,e.shiftKey,e.ctrlKey),e.preventDefault();else if(40==e.which)down.call(libraryBase.jspreadsheet.current,e.shiftKey,e.ctrlKey),e.preventDefault();else if(36==e.which)first.call(libraryBase.jspreadsheet.current,e.shiftKey,e.ctrlKey),e.preventDefault();else if(35==e.which)last.call(libraryBase.jspreadsheet.current,e.shiftKey,e.ctrlKey),e.preventDefault();else if(46==e.which||8==e.which)0!=libraryBase.jspreadsheet.current.options.editable&&(null!=libraryBase.jspreadsheet.current.selectedRow?0!=libraryBase.jspreadsheet.current.options.allowDeleteRow&&confirm(jSuites.translate("Are you sure to delete the selected rows?"))&&libraryBase.jspreadsheet.current.deleteRow():libraryBase.jspreadsheet.current.selectedHeader?0!=libraryBase.jspreadsheet.current.options.allowDeleteColumn&&confirm(jSuites.translate("Are you sure to delete the selected columns?"))&&libraryBase.jspreadsheet.current.deleteColumn():libraryBase.jspreadsheet.current.setValue(libraryBase.jspreadsheet.current.highlighted.map((function(e){return e.element})),""));else if(13==e.which)e.shiftKey?up.call(libraryBase.jspreadsheet.current):(0!=libraryBase.jspreadsheet.current.options.allowInsertRow&&0!=libraryBase.jspreadsheet.current.options.allowManualInsertRow&&libraryBase.jspreadsheet.current.selectedCell[1]==libraryBase.jspreadsheet.current.options.data.length-1&&libraryBase.jspreadsheet.current.insertRow(),down.call(libraryBase.jspreadsheet.current)),e.preventDefault();else if(9==e.which)e.shiftKey?left.call(libraryBase.jspreadsheet.current):(0!=libraryBase.jspreadsheet.current.options.allowInsertColumn&&0!=libraryBase.jspreadsheet.current.options.allowManualInsertColumn&&libraryBase.jspreadsheet.current.selectedCell[0]==libraryBase.jspreadsheet.current.options.data[0].length-1&&libraryBase.jspreadsheet.current.insertColumn(),right.call(libraryBase.jspreadsheet.current)),e.preventDefault();else if(!e.ctrlKey&&!e.metaKey||e.shiftKey){if(libraryBase.jspreadsheet.current.selectedCell&&0!=libraryBase.jspreadsheet.current.options.editable){const t=libraryBase.jspreadsheet.current.selectedCell[1],s=libraryBase.jspreadsheet.current.selectedCell[0];32==e.keyCode?(e.preventDefault(),"checkbox"==libraryBase.jspreadsheet.current.options.columns[s].type||"radio"==libraryBase.jspreadsheet.current.options.columns[s].type?setCheckRadioValue.call(libraryBase.jspreadsheet.current):openEditor.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.records[t][s].element,!0,e)):113==e.keyCode?openEditor.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.records[t][s].element,!1,e):1!==e.key.length&&"Process"!==e.key||e.altKey||isCtrl(e)||(openEditor.call(libraryBase.jspreadsheet.current,libraryBase.jspreadsheet.current.records[t][s].element,!0,e),libraryBase.jspreadsheet.current.options.columns&&libraryBase.jspreadsheet.current.options.columns[s]&&"calendar"==libraryBase.jspreadsheet.current.options.columns[s].type&&e.preventDefault())}}else 65==e.which?(selection.Ub.call(libraryBase.jspreadsheet.current),e.preventDefault()):83==e.which?(libraryBase.jspreadsheet.current.download(),e.preventDefault()):89==e.which?(libraryBase.jspreadsheet.current.redo(),e.preventDefault()):90==e.which?(libraryBase.jspreadsheet.current.undo(),e.preventDefault()):67==e.which?(copy.call(libraryBase.jspreadsheet.current,!0),e.preventDefault()):88==e.which?(0!=libraryBase.jspreadsheet.current.options.editable?cutControls():copyControls(),e.preventDefault()):86==e.which&&pasteControls();else e.target.classList.contains("jss_search")&&(libraryBase.jspreadsheet.timeControl&&clearTimeout(libraryBase.jspreadsheet.timeControl),libraryBase.jspreadsheet.timeControl=setTimeout((function(){libraryBase.jspreadsheet.current.search(e.target.value)}),200))}},wheelControls=function(e){const t=this;1==t.options.lazyLoading&&null==libraryBase.jspreadsheet.timeControlLoading&&(libraryBase.jspreadsheet.timeControlLoading=setTimeout((function(){t.content.scrollTop+t.content.clientHeight>=t.content.scrollHeight-10?lazyLoading.p6.call(t)&&(t.content.scrollTop+t.content.clientHeight>t.content.scrollHeight-10&&(t.content.scrollTop=t.content.scrollTop-t.content.clientHeight),selection.Aq.call(t)):t.content.scrollTop<=t.content.clientHeight&&lazyLoading.G_.call(t)&&(t.content.scrollTop<10&&(t.content.scrollTop=t.content.scrollTop+t.content.clientHeight),selection.Aq.call(t)),libraryBase.jspreadsheet.timeControlLoading=null}),100))};let scrollLeft=0;const updateFreezePosition=function(){const e=this;scrollLeft=e.content.scrollLeft;let t=0;if(scrollLeft>50)for(let s=0;s<e.options.freezeColumns;s++){if(s>0&&(!e.options.columns||!e.options.columns[s-1]||"hidden"!==e.options.columns[s-1].type)){let n;n=e.options.columns&&e.options.columns[s-1]&&void 0!==e.options.columns[s-1].width?parseInt(e.options.columns[s-1].width):void 0!==e.options.defaultColWidth?parseInt(e.options.defaultColWidth):100,t+=parseInt(n)}e.headers[s].classList.add("jss_freezed"),e.headers[s].style.left=t+"px";for(let t=0;t<e.rows.length;t++)if(e.rows[t]&&e.records[t][s]){const n=scrollLeft+(s>0?e.records[t][s-1].element.style.width:0)-51+"px";e.records[t][s].element.classList.add("jss_freezed"),e.records[t][s].element.style.left=n}}else for(let t=0;t<e.options.freezeColumns;t++){e.headers[t].classList.remove("jss_freezed"),e.headers[t].style.left="";for(let s=0;s<e.rows.length;s++)e.records[s][t]&&(e.records[s][t].element.classList.remove("jss_freezed"),e.records[s][t].element.style.left="")}selection.Aq.call(e)},scrollControls=function(e){const t=this;wheelControls.call(t),t.options.freezeColumns>0&&t.content.scrollLeft!=scrollLeft&&updateFreezePosition.call(t),1!=t.options.lazyLoading&&1!=t.options.tableOverflow||t.edition&&"jdropdown"!=e.target.className.substr(0,9)&&closeEditor.call(t,t.edition[0],!0)},setEvents=function(e){destroyEvents(e),e.addEventListener("mouseup",mouseUpControls),e.addEventListener("mousedown",mouseDownControls),e.addEventListener("mousemove",mouseMoveControls),e.addEventListener("mouseover",mouseOverControls),e.addEventListener("dblclick",doubleClickControls),e.addEventListener("paste",pasteControls),e.addEventListener("contextmenu",contextMenuControls),e.addEventListener("touchstart",touchStartControls),e.addEventListener("touchend",touchEndControls),e.addEventListener("touchcancel",touchEndControls),e.addEventListener("touchmove",touchEndControls),document.addEventListener("keydown",keyDownControls)},destroyEvents=function(e){e.removeEventListener("mouseup",mouseUpControls),e.removeEventListener("mousedown",mouseDownControls),e.removeEventListener("mousemove",mouseMoveControls),e.removeEventListener("mouseover",mouseOverControls),e.removeEventListener("dblclick",doubleClickControls),e.removeEventListener("paste",pasteControls),e.removeEventListener("contextmenu",contextMenuControls),e.removeEventListener("touchstart",touchStartControls),e.removeEventListener("touchend",touchEndControls),e.removeEventListener("touchcancel",touchEndControls),document.removeEventListener("keydown",keyDownControls)};var toolbar=__webpack_require__(392),pagination=__webpack_require__(167);const setData=function(e){const t=this;if(e&&(t.options.data=e),t.options.data||(t.options.data=[]),t.options.data&&t.options.data[0]&&!Array.isArray(t.options.data[0])){e=[];for(let s=0;s<t.options.data.length;s++){const n=[];for(let e=0;e<t.options.columns.length;e++)n[e]=t.options.data[s][t.options.columns[e].name];e.push(n)}t.options.data=e}let s=0,n=0;const o=t.options.columns&&t.options.columns.length||0,r=t.options.data.length,l=t.options.minDimensions[0],i=t.options.minDimensions[1],a=l>o?l:o,c=i>r?i:r;for(s=0;s<c;s++)for(n=0;n<a;n++)null==t.options.data[s]&&(t.options.data[s]=[]),null==t.options.data[s][n]&&(t.options.data[s][n]="");let d,u;for(t.rows=[],t.results=null,t.records=[],t.history=[],t.historyIndex=-1,t.tbody.innerHTML="",1==t.options.lazyLoading?(d=0,u=t.options.data.length<100?t.options.data.length:100,t.options.pagination&&(t.options.pagination=!1,console.error("Jspreadsheet: Pagination will be disable due the lazyLoading"))):t.options.pagination?(t.pageNumber||(t.pageNumber=0),t.options.pagination,d=t.options.pagination*t.pageNumber,u=t.options.pagination*t.pageNumber+t.options.pagination,t.options.data.length<u&&(u=t.options.data.length)):(d=0,u=t.options.data.length),s=0;s<t.options.data.length;s++){const e=createRow.call(t,s,t.options.data[s]);s>=d&&s<u&&t.tbody.appendChild(e.element)}if(1==t.options.lazyLoading||t.options.pagination&&pagination.IV.call(t),t.options.mergeCells){const e=Object.keys(t.options.mergeCells);for(let s=0;s<e.length;s++){const n=t.options.mergeCells[e[s]];merges.FU.call(t,e[s],n[0],n[1],1)}}internal.am.call(t)},getValue=function(e,t){const s=this;let n,o;if("string"!=typeof e)return null;n=(e=(0,internalHelpers.vu)(e,!0))[0],o=e[1];let r=null;return null!=n&&null!=o&&(s.records[o]&&s.records[o][n]&&t?r=s.records[o][n].element.innerHTML:s.options.data[o]&&"undefined"!=s.options.data[o][n]&&(r=s.options.data[o][n])),r},getValueFromCoords=function(e,t,s){const n=this;let o=null;return null!=e&&null!=t&&(n.records[t]&&n.records[t][e]&&s?o=n.records[t][e].element.innerHTML:n.options.data[t]&&"undefined"!=n.options.data[t][e]&&(o=n.options.data[t][e])),o},setValue=function(e,t,s){const n=this,o=[];if("string"==typeof e){const r=(0,internalHelpers.vu)(e,!0),l=r[0],i=r[1];o.push(internal.k9.call(n,l,i,t,s)),internal.xF.call(n,l,i,o)}else{let r=null,l=null;if(e&&e.getAttribute&&(r=e.getAttribute("data-x"),l=e.getAttribute("data-y")),null!=r&&null!=l)o.push(internal.k9.call(n,r,l,t,s)),internal.xF.call(n,r,l,o);else{const r=Object.keys(e);if(r.length>0)for(let l=0;l<r.length;l++){let r,i;if("string"==typeof e[l]){const t=(0,internalHelpers.vu)(e[l],!0);r=t[0],i=t[1]}else null!=e[l].x&&null!=e[l].y?(r=e[l].x,i=e[l].y,null!=e[l].value&&(t=e[l].value)):(r=e[l].getAttribute("data-x"),i=e[l].getAttribute("data-y"));null!=r&&null!=i&&(o.push(internal.k9.call(n,r,i,t,s)),internal.xF.call(n,r,i,o))}}}utils_history.Dh.call(n,{action:"setValue",records:o,selection:n.selectedCell}),internal.am.call(n);const r=o.map((function(e){return{x:e.x,y:e.y,value:e.value,oldValue:e.oldValue}}));dispatch.A.call(n,"onafterchanges",n,r)},setValueFromCoords=function(e,t,s,n){const o=this,r=[];r.push(internal.k9.call(o,e,t,s,n)),internal.xF.call(o,e,t,r),utils_history.Dh.call(o,{action:"setValue",records:r,selection:o.selectedCell}),internal.am.call(o);const l=r.map((function(e){return{x:e.x,y:e.y,value:e.value,oldValue:e.oldValue}}));dispatch.A.call(o,"onafterchanges",o,l)},getData=function(e,t,s,n){const o=this,r=[];let l=0,i=0;const a=Math.max(...o.options.data.map((function(e){return e.length}))),c=o.options.data.length;for(let s=0;s<c;s++){l=0;for(let n=0;n<a;n++)e&&!o.records[s][n].element.classList.contains("highlight")||(r[i]||(r[i]=[]),r[i][l]=t?o.records[s][n].element.innerHTML:o.options.data[s][n],l++);l>0&&i++}return s?r.map((function(e){return e.join(s)})).join("\r\n")+"\r\n":n?r.map((function(e){const t={};return e.forEach((function(e,s){t[s]=e})),t})):r},getDataFromRange=function(e,t){const s=this,n=(0,helpers.getCoordsFromRange)(e),o=[];for(let e=n[1];e<=n[3];e++){o.push([]);for(let r=n[0];r<=n[2];r++)t?o[o.length-1].push(s.records[e][r].element.innerHTML):o[o.length-1].push(s.options.data[e][r])}return o},search=function(e){const t=this;if(t.options.filters&&filter.dr.call(t),t.resetSelection(),t.pageNumber=0,t.results=[],e){t.searchInput.value!==e&&(t.searchInput.value=e);const s=function(e,s,n){for(let o=0;o<e.length;o++)if((""+e[o]).toLowerCase().search(s)>=0||(""+t.records[n][o].element.innerHTML).toLowerCase().search(s)>=0)return!0;return!1},n=function(e){-1==t.results.indexOf(e)&&t.results.push(e)};let o=e.replace(/[-[\]{}()*+?.,\\^$|#\s]/g,"\\$&");o=new RegExp(o,"i"),t.options.data.forEach((function(e,r){if(s(e,o,r)){const e=merges.D0.call(t,r);if(e.length)for(let s=0;s<e.length;s++){const o=(0,internalHelpers.vu)(e[s],!0);for(let r=0;r<t.options.mergeCells[e[s]][1];r++)n(o[1]+r)}else n(r)}}))}else t.results=null;internal.hG.call(t)},resetSearch=function(){const e=this;e.searchInput.value="",e.search(""),e.results=null},getHeader=function(e){return this.headers[e].textContent},getHeaders=function(e){const t=this,s=[];for(let e=0;e<t.headers.length;e++)s.push(t.getHeader(e));return e?s:s.join(t.options.csvDelimiter)},setHeader=function(e,t){const s=this;if(s.headers[e]){const n=s.headers[e].textContent,o=s.options.columns&&s.options.columns[e]&&s.options.columns[e].title||"";t||(t=(0,helpers.getColumnName)(e)),s.headers[e].textContent=t,s.headers[e].setAttribute("title",t),s.options.columns||(s.options.columns=[]),s.options.columns[e]||(s.options.columns[e]={}),s.options.columns[e].title=t,utils_history.Dh.call(s,{action:"setHeader",column:e,oldValue:n,newValue:t}),dispatch.A.call(s,"onchangeheader",s,parseInt(e),t,o)}},getStyle=function(e,t){const s=this;if(e)return e=(0,internalHelpers.vu)(e,!0),t?s.records[e[1]][e[0]].element.style[t]:s.records[e[1]][e[0]].element.getAttribute("style");{const e={},n=s.options.data[0].length,o=s.options.data.length;for(let r=0;r<o;r++)for(let o=0;o<n;o++){const n=t?s.records[r][o].element.style[t]:s.records[r][o].element.getAttribute("style");n&&(e[(0,internalHelpers.t3)([o,r])]=n)}return e}},setStyle=function(e,t,s,n,o){const r=this,l={},i={},a=function(e,t,s){const o=(0,internalHelpers.vu)(e,!0);if(r.records[o[1]]&&r.records[o[1]][o[0]]&&(0==r.records[o[1]][o[0]].element.classList.contains("readonly")||n)){const a=r.records[o[1]][o[0]].element.style[t];a!=s||n?r.records[o[1]][o[0]].element.style[t]=s:(s="",r.records[o[1]][o[0]].element.style[t]=""),i[e]||(i[e]=[]),l[e]||(l[e]=[]),i[e].push([t+":"+a]),l[e].push([t+":"+s])}};if(t&&s)"string"==typeof e&&a(e,t,s);else{const t=Object.keys(e);for(let s=0;s<t.length;s++){let n=e[t[s]];"string"==typeof n&&(n=n.split(";"));for(let e=0;e<n.length;e++)"string"==typeof n[e]&&(n[e]=n[e].split(":")),n[e][0].trim()&&a(t[s],n[e][0].trim(),n[e][1])}}let c=Object.keys(i);for(let e=0;e<c.length;e++)i[c[e]]=i[c[e]].join(";");c=Object.keys(l);for(let e=0;e<c.length;e++)l[c[e]]=l[c[e]].join(";");o||utils_history.Dh.call(r,{action:"setStyle",oldValue:i,newValue:l}),dispatch.A.call(r,"onchangestyle",r,l)},resetStyle=function(e,t){const s=this,n=Object.keys(e);for(let e=0;e<n.length;e++){const t=(0,internalHelpers.vu)(n[e],!0);s.records[t[1]]&&s.records[t[1]][t[0]]&&s.records[t[1]][t[0]].element.setAttribute("style","")}s.setStyle(e,null,null,null,t)},download=function(e,t){const s=this;if(0==s.parent.config.allowExport)console.error("Export not allowed");else{let n="";n+=copy.call(s,!1,s.options.csvDelimiter,!0,e,!0,void 0,t);const o=new Blob(["\ufeff"+n],{type:"text/csv;charset=utf-8;"});if(window.navigator&&window.navigator.msSaveOrOpenBlob)window.navigator.msSaveOrOpenBlob(o,(s.options.csvFileName||s.options.worksheetName)+".csv");else{const e=document.createElement("a");e.setAttribute("target","_top");const t=URL.createObjectURL(o);e.href=t,e.setAttribute("download",(s.options.csvFileName||s.options.worksheetName)+".csv"),document.body.appendChild(e),e.click(),e.parentNode.removeChild(e)}}},getComments=function(e){const t=this;if(e)return"string"!=typeof e?getComments.call(t):(e=(0,internalHelpers.vu)(e,!0),t.records[e[1]][e[0]].element.getAttribute("title")||"");{const e={};for(let s=0;s<t.options.data.length;s++)for(let n=0;n<t.options.columns.length;n++){const o=t.records[s][n].element.getAttribute("title");o&&(e[(0,internalHelpers.t3)([n,s])]=o)}return e}},setComments=function(e,t){const s=this;let n;n="string"==typeof e?{[e]:t}:e;const o={};Object.entries(n).forEach((function([e,t]){const n=(0,helpers.getCoordsFromCellName)(e);o[e]=s.records[n[1]][n[0]].element.getAttribute("title"),s.records[n[1]][n[0]].element.setAttribute("title",t||""),t?(s.records[n[1]][n[0]].element.classList.add("jss_comments"),s.options.comments||(s.options.comments={}),s.options.comments[e]=t):(s.records[n[1]][n[0]].element.classList.remove("jss_comments"),s.options.comments&&s.options.comments[e]&&delete s.options.comments[e])})),utils_history.Dh.call(s,{action:"setComments",newValue:n,oldValue:o}),dispatch.A.call(s,"oncomments",s,n,o)};var orderBy=__webpack_require__(94);const getWorksheetConfig=function(){return this.options},getSpreadsheetConfig=function(){return this.config},setConfig=function(e,t){const s=this,n=Object.keys(e);let o;s.parent?o=s.parent:(t=!0,o=s),n.forEach((function(n){t?(o.config[n]=e[n],"toolbar"===n&&(!0===e[n]?o.showToolbar():!1===e[n]&&o.hideToolbar())):s.options[n]=e[n]}))};var meta=__webpack_require__(654);const setReadOnly=function(e,t){const s=this;let n;if("string"==typeof e){const t=(0,helpers.getCoordsFromCellName)(e);n=s.records[t[1]][t[0]]}else{const t=parseInt(e.getAttribute("data-x")),o=parseInt(e.getAttribute("data-y"));n=s.records[o][t]}t?n.element.classList.add("readonly"):n.element.classList.remove("readonly")},isReadOnly=function(e,t){if("string"==typeof e&&void 0===t){const s=(0,helpers.getCoordsFromCellName)(e);[e,t]=s}return this.records[t][e].element.classList.contains("readonly")},setWorksheetFunctions=function(e){for(let t=0;t<worksheetPublicMethodsLength;t++){const[s,n]=worksheetPublicMethods[t];e[s]=n.bind(e)}},createTable=function(){let e=this;setWorksheetFunctions(e),e.table=document.createElement("table"),e.thead=document.createElement("thead"),e.tbody=document.createElement("tbody"),e.headers=[],e.cols=[],e.content=document.createElement("div"),e.content.classList.add("jss_content"),e.content.onscroll=function(t){scrollControls.call(e,t)},e.content.onwheel=function(t){wheelControls.call(e,t)};const t=document.createElement("div"),s=document.createElement("label");s.innerHTML=jSuites.translate("Search")+": ",t.appendChild(s),e.searchInput=document.createElement("input"),e.searchInput.classList.add("jss_search"),s.appendChild(e.searchInput),e.searchInput.onfocus=function(){e.resetSelection()};const n=document.createElement("div");if(e.options.pagination>0&&e.options.paginationOptions&&e.options.paginationOptions.length>0){e.paginationDropdown=document.createElement("select"),e.paginationDropdown.classList.add("jss_pagination_dropdown"),e.paginationDropdown.onchange=function(){e.options.pagination=parseInt(this.value),e.page(0)};for(let t=0;t<e.options.paginationOptions.length;t++){const s=document.createElement("option");s.value=e.options.paginationOptions[t],s.innerHTML=e.options.paginationOptions[t],e.paginationDropdown.appendChild(s)}e.paginationDropdown.value=e.options.pagination,n.appendChild(document.createTextNode(jSuites.translate("Show "))),n.appendChild(e.paginationDropdown),n.appendChild(document.createTextNode(jSuites.translate("entries")))}const o=document.createElement("div");o.classList.add("jss_filter"),o.appendChild(n),o.appendChild(t),e.colgroupContainer=document.createElement("colgroup");let r=document.createElement("col");if(r.setAttribute("width","50"),e.colgroupContainer.appendChild(r),e.options.nestedHeaders&&e.options.nestedHeaders.length>0&&e.options.nestedHeaders[0]&&e.options.nestedHeaders[0][0])for(let t=0;t<e.options.nestedHeaders.length;t++)e.thead.appendChild(internal.ju.call(e,e.options.nestedHeaders[t]));e.headerContainer=document.createElement("tr"),r=document.createElement("td"),r.classList.add("jss_selectall"),e.headerContainer.appendChild(r);const l=getNumberOfColumns.call(e);for(let t=0;t<l;t++)createCellHeader.call(e,t),e.headerContainer.appendChild(e.headers[t]),e.colgroupContainer.appendChild(e.cols[t].colElement);if(e.thead.appendChild(e.headerContainer),1==e.options.filters){e.filter=document.createElement("tr");const t=document.createElement("td");e.filter.appendChild(t);for(let t=0;t<e.options.columns.length;t++){const s=document.createElement("td");s.innerHTML="&nbsp;",s.setAttribute("data-x",t),s.className="jss_column_filter","hidden"==e.options.columns[t].type&&(s.style.display="none"),e.filter.appendChild(s)}e.thead.appendChild(e.filter)}e.table=document.createElement("table"),e.table.classList.add("jss_worksheet"),e.table.setAttribute("cellpadding","0"),e.table.setAttribute("cellspacing","0"),e.table.setAttribute("unselectable","yes"),e.table.appendChild(e.colgroupContainer),e.table.appendChild(e.thead),e.table.appendChild(e.tbody),e.options.textOverflow||e.table.classList.add("jss_overflow"),e.corner=document.createElement("div"),e.corner.className="jss_corner",e.corner.setAttribute("unselectable","on"),e.corner.setAttribute("onselectstart","return false"),0==e.options.selectionCopy&&(e.corner.style.display="none"),e.textarea=document.createElement("textarea"),e.textarea.className="jss_textarea",e.textarea.id="jss_textarea",e.textarea.tabIndex="-1",e.textarea.ariaHidden="true";const i=document.createElement("a");i.setAttribute("href","https://bossanova.uk/jspreadsheet/"),e.ads=document.createElement("div"),e.ads.className="jss_about";const a=document.createElement("span");a.innerHTML="Jspreadsheet CE",i.appendChild(a),e.ads.appendChild(i),document.createElement("div").classList.add("jss_table"),e.pagination=document.createElement("div"),e.pagination.classList.add("jss_pagination");const c=document.createElement("div"),d=document.createElement("div");if(e.pagination.appendChild(c),e.pagination.appendChild(d),e.options.pagination||(e.pagination.style.display="none"),1==e.options.search&&e.element.appendChild(o),e.content.appendChild(e.table),e.content.appendChild(e.corner),e.content.appendChild(e.textarea),e.element.appendChild(e.content),e.element.appendChild(e.pagination),e.element.appendChild(e.ads),e.element.classList.add("jss_container"),e.element.jssWorksheet=e,e.element.jspreadsheet=e,1==e.options.tableOverflow&&(e.options.tableHeight&&(e.content.style["overflow-y"]="auto",e.content.style["box-shadow"]="rgb(221 221 221) 2px 2px 5px 0.1px",e.content.style.maxHeight="string"==typeof e.options.tableHeight?e.options.tableHeight:e.options.tableHeight+"px"),e.options.tableWidth&&(e.content.style["overflow-x"]="auto",e.content.style.width="string"==typeof e.options.tableWidth?e.options.tableWidth:e.options.tableWidth+"px")),1!=e.options.tableOverflow&&e.parent.config.toolbar&&e.element.classList.add("with-toolbar"),0!=e.options.columnDrag&&e.thead.classList.add("draggable"),0!=e.options.columnResize&&e.thead.classList.add("resizable"),0!=e.options.rowDrag&&e.tbody.classList.add("draggable"),0!=e.options.rowResize&&e.tbody.classList.add("resizable"),e.setData.call(e),e.options.style&&(e.setStyle(e.options.style,null,null,1,1),delete e.options.style),Object.defineProperty(e.options,"style",{enumerable:!0,configurable:!0,get(){return e.getStyle()}}),e.options.comments&&e.setComments(e.options.comments),e.options.classes){const t=Object.keys(e.options.classes);for(let s=0;s<t.length;s++){const n=(0,internalHelpers.vu)(t[s],!0);e.records[n[1]][n[0]].element.classList.add(e.options.classes[t[s]])}}},prepareTable=function(){const e=this;1==e.options.lazyLoading&&1!=e.options.tableOverflow&&1!=e.parent.config.fullscreen&&(console.error("Jspreadsheet: The lazyloading only works when tableOverflow = yes or fullscreen = yes"),e.options.lazyLoading=!1),e.options.columns||(e.options.columns=[]);let t,s=e.options.columns.length;if(e.options.data&&void 0!==e.options.data[0])if(Array.isArray(e.options.data[0])){const t=e.options.data[0].length;t>s&&(s=t)}else t=Object.keys(e.options.data[0]),t.length>s&&(s=t.length);e.options.minDimensions||(e.options.minDimensions=[0,0]),e.options.minDimensions[0]>s&&(s=e.options.minDimensions[0]);const n=[];for(let o=0;o<s;o++)e.options.columns[o]||(e.options.columns[o]={}),!e.options.columns[o].name&&t&&t[o]&&(e.options.columns[o].name=t[o]),"dropdown"==e.options.columns[o].type&&e.options.columns[o].url&&n.push({url:e.options.columns[o].url,index:o,method:"GET",dataType:"json",success:function(t){e.options.columns[this.index].source||(e.options.columns[this.index].source=[]);for(let s=0;s<t.length;s++)e.options.columns[this.index].source.push(t[s])}});n.length?jSuites.ajax(n,(function(){createTable.call(e)})):createTable.call(e)},getNextDefaultWorksheetName=function(e){const t=/^Sheet(\d+)$/;let s=0;return e.worksheets.forEach((function(e){const n=t.exec(e.options.worksheetName);n&&(s=Math.max(s,parseInt(n[1])))})),"Sheet"+(s+1)},buildWorksheet=async function(){const e=this,t=(e.element,e.parent);"object"==typeof t.plugins&&Object.entries(t.plugins).forEach((function([,t]){"function"==typeof t.beforeinit&&t.beforeinit(e)})),libraryBase.jspreadsheet.current=e;const s=[];if(e.options.csv){const t=new Promise((t=>{jSuites.ajax({url:e.options.csv,method:"GET",dataType:"text",success:function(s){const n=(0,helpers.parseCSV)(s,e.options.csvDelimiter);if(1==e.options.csvHeaders&&n.length>0){const t=n.shift();if(t.length>0){e.options.columns||(e.options.columns=[]);for(let s=0;s<t.length;s++)e.options.columns[s]||(e.options.columns[s]={}),void 0===e.options.columns[s].title&&(e.options.columns[s].title=t[s])}}e.options.data=n,prepareTable.call(e),t()}})}));s.push(t)}else if(e.options.url){const t=new Promise((t=>{jSuites.ajax({url:e.options.url,method:"GET",dataType:"json",success:function(s){e.options.data=s.data?s.data:s,prepareTable.call(e),t()}})}));s.push(t)}else prepareTable.call(e);await Promise.all(s),"object"==typeof t.plugins&&Object.entries(t.plugins).forEach((function([,t]){"function"==typeof t.init&&t.init(e)}))},createWorksheetObj=function(e){const t=this.parent;e.worksheetName||(e.worksheetName=getNextDefaultWorksheetName(this.parent));const s={parent:t,options:e,filters:[],formula:[],history:[],selection:[],historyIndex:-1};return t.config.worksheets.push(s.options),t.worksheets.push(s),s},createWorksheet=function(e){const t=this.parent;t.creationThroughJss=!0,createWorksheetObj.call(this,e),t.element.tabs.create(e.worksheetName)},openWorksheet=function(e){this.parent.element.tabs.open(e)},deleteWorksheet=function(e){const t=this;t.parent.element.tabs.remove(e);const s=t.parent.worksheets.splice(e,1)[0];dispatch.A.call(t.parent,"ondeleteworksheet",s,e)},worksheetPublicMethods=[["selectAll",selection.Ub],["updateSelectionFromCoords",function(e,t,s,n){return selection.AH.call(this,e,t,s,n)}],["resetSelection",function(){return selection.gE.call(this)}],["getSelection",selection.Lo],["getSelected",selection.ef],["getSelectedColumns",selection.Jg],["getSelectedRows",selection.R5],["getData",getData],["setData",setData],["getValue",getValue],["getValueFromCoords",getValueFromCoords],["setValue",setValue],["setValueFromCoords",setValueFromCoords],["getWidth",getWidth],["setWidth",function(e,t){return setWidth.call(this,e,t)}],["insertRow",insertRow],["moveRow",function(e,t){return moveRow.call(this,e,t)}],["deleteRow",deleteRow],["hideRow",hideRow],["showRow",showRow],["getRowData",getRowData],["setRowData",setRowData],["getHeight",getHeight],["setHeight",function(e,t){return setHeight.call(this,e,t)}],["getMerge",merges.fd],["setMerge",function(e,t,s){return merges.FU.call(this,e,t,s)}],["destroyMerge",function(){return merges.VP.call(this)}],["removeMerge",function(e,t){return merges.Zp.call(this,e,t)}],["search",search],["resetSearch",resetSearch],["getHeader",getHeader],["getHeaders",getHeaders],["setHeader",setHeader],["getStyle",getStyle],["setStyle",function(e,t,s,n){return setStyle.call(this,e,t,s,n)}],["resetStyle",resetStyle],["insertColumn",insertColumn],["moveColumn",moveColumn],["deleteColumn",deleteColumn],["getColumnData",getColumnData],["setColumnData",setColumnData],["whichPage",pagination.ho],["page",pagination.MY],["download",download],["getComments",getComments],["setComments",setComments],["orderBy",orderBy.My],["undo",utils_history.tN],["redo",utils_history.ZS],["getCell",internal.tT],["getCellFromCoords",internal.Xr],["getLabel",internal.p9],["getConfig",getWorksheetConfig],["setConfig",setConfig],["getMeta",function(e){return meta.IQ.call(this,e)}],["setMeta",meta.iZ],["showColumn",showColumn],["hideColumn",hideColumn],["showIndex",internal.C6],["hideIndex",internal.TI],["getWorksheetActive",internal.$O],["openEditor",openEditor],["closeEditor",closeEditor],["createWorksheet",createWorksheet],["openWorksheet",openWorksheet],["deleteWorksheet",deleteWorksheet],["copy",function(e){e?cutControls():copy.call(this,!0)}],["paste",paste],["executeFormula",internal.Em],["getDataFromRange",getDataFromRange],["quantiyOfPages",pagination.$f],["getRange",selection.eO],["isSelected",selection.sp],["setReadOnly",setReadOnly],["isReadOnly",isReadOnly],["getHighlighted",selection.kV],["dispatch",dispatch.A],["down",down],["first",first],["last",last],["left",left],["right",right],["up",up],["openFilter",filter.N$],["resetFilters",filter.dr]],worksheetPublicMethodsLength=worksheetPublicMethods.length,factory=function(){},createWorksheets=async function(e,t,s){let n=t.worksheets;if(!n)throw new Error("JSS: worksheets are not defined");{let o={animation:!0,onbeforecreate:function(t,s){return s||getNextDefaultWorksheetName(e)},oncreate:function(s,n){if(e.creationThroughJss)e.creationThroughJss=!1;else{const t=s.tabs.headers.children[s.tabs.headers.children.length-2].innerHTML;createWorksheetObj.call(e.worksheets[0],{minDimensions:[10,15],worksheetName:t})}const o=e.worksheets[e.worksheets.length-1];o.element=n,buildWorksheet.call(o).then((function(){(0,toolbar.nK)(o),dispatch.A.call(o,"oncreateworksheet",o,t,e.worksheets.length-1)}))},onchange:function(t,s,n){0!=e.worksheets.length&&e.worksheets[n]&&(0,toolbar.nK)(e.worksheets[n])}};1==t.tabs?o.allowCreate=!0:o.hideHeaders=!0,o.data=[];let r=1;for(let e=0;e<n.length;e++)n[e].worksheetName||(n[e].worksheetName="Sheet"+r++),o.data.push({title:n[e].worksheetName,content:""});s.classList.add("jss_spreadsheet"),s.tabIndex=0;const l=jSuites.tabs(s,o),i=t.style;delete t.style;for(let t=0;t<n.length;t++)n[t].style&&Object.entries(n[t].style).forEach((function([e,s]){"number"==typeof s&&(n[t].style[e]=i[s])})),e.worksheets.push({parent:e,element:l.content.children[t],options:n[t],filters:[],formula:[],history:[],selection:[],historyIndex:-1}),await buildWorksheet.call(e.worksheets[t])}};factory.spreadsheet=async function(e,t,s){if("TABLE"==e.tagName){t||(t={}),t.worksheets||(t.worksheets=[]);const s=(0,helpers.createFromTable)(e,t.worksheets[0]);t.worksheets[0]=s;const n=document.createElement("div");e.parentNode.insertBefore(n,e),e.remove(),e=n}let n={worksheets:s,config:t,element:e,el:e};return n.contextMenu=document.createElement("div"),n.contextMenu.className="jss_contextmenu",n.getWorksheetActive=internal.$O.bind(n),n.fullscreen=internal.Y5.bind(n),n.showToolbar=toolbar.ll.bind(n),n.hideToolbar=toolbar.Ar.bind(n),n.getConfig=getSpreadsheetConfig.bind(n),n.setConfig=setConfig.bind(n),n.setPlugins=function(e){n.plugins||(n.plugins={}),"object"==typeof e&&Object.entries(e).forEach((function([e,t]){n.plugins[e]=t.call(libraryBase.jspreadsheet,n,{},n.config)}))},n.setPlugins(t.plugins),await createWorksheets(n,t,e),n.element.appendChild(n.contextMenu),jSuites.contextmenu(n.contextMenu,{onclick:function(){n.contextMenu.contextmenu.close(!1)}}),1==n.config.fullscreen&&n.element.classList.add("fullscreen"),toolbar.ll.call(n),t.root?setEvents(t.root):setEvents(document),e.spreadsheet=n,n},factory.worksheet=function(e,t,s){let n={parent:e,options:{}};return void 0===s?e.worksheets.push(n):e.worksheets.splice(s,0,n),Object.assign(n.options,t),n};var utils_factory=factory;libraryBase.jspreadsheet=function(e,t){try{let s=[];return utils_factory.spreadsheet(e,t,s).then((e=>{libraryBase.jspreadsheet.spreadsheet.push(e),dispatch.A.call(e,"onload",e)})),s}catch(e){console.error(e)}},libraryBase.jspreadsheet.getWorksheetInstanceByName=function(e,t){const s=libraryBase.jspreadsheet.spreadsheet.find((e=>e.config.namespace===t));if(s)return{};if(null==e){const e=s.worksheets.map((e=>[e.options.worksheetName,e]));return Object.fromEntries(e)}return s.worksheets.find((t=>t.options.worksheetName===e))},libraryBase.jspreadsheet.setDictionary=function(e){jSuites.setDictionary(e)},libraryBase.jspreadsheet.destroy=function(e,t){if(e.spreadsheet){const s=libraryBase.jspreadsheet.spreadsheet.indexOf(e.spreadsheet);libraryBase.jspreadsheet.spreadsheet.splice(s,1);const n=e.spreadsheet.config.root||document;e.spreadsheet=null,e.innerHTML="",t&&destroyEvents(n)}},libraryBase.jspreadsheet.destroyAll=function(){for(let e=0;e<libraryBase.jspreadsheet.spreadsheet.length;e++){const t=libraryBase.jspreadsheet.spreadsheet[e];libraryBase.jspreadsheet.destroy(t.element)}},libraryBase.jspreadsheet.current=null,libraryBase.jspreadsheet.spreadsheet=[],libraryBase.jspreadsheet.helpers={},libraryBase.jspreadsheet.version=function(){return version},Object.entries(helpers).forEach((([e,t])=>{libraryBase.jspreadsheet.helpers[e]=t}));var src=libraryBase.jspreadsheet;jspreadsheet=__webpack_exports__.default})();
16
17 return jspreadsheet;
18})));
web/vendor/jsuites.css +4965 -0
……@@ -0,0 +1,4965 @@
1:root {
2 --jbutton-color: #298BA8;
3 --jactive-color: #007aff;
4 --jsafe-area-top: env(safe-area-inset-top);
5 --jsafe-area-bottom: env(safe-area-inset-bottom);
6}
7
8[data-visible="false"], .row[data-visible="false"] {
9 display: none;
10}
11
12
13div[data-before]:before {
14 content: attr(data-before);
15}
16
17.unselectable {
18 -webkit-touch-callout: none;
19 -webkit-user-select: none;
20 -khtml-user-select: none;
21 -moz-user-select: none;
22 -ms-user-select: none;
23 user-select: none;
24}
25
26.jreadonly {
27 pointer-events: none;
28}
29
30.jdragging {
31 opacity:0.2;
32 filter: alpha(opacity=20);
33}
34
35.jupload.input {
36 position: relative;
37 box-sizing: border-box;
38 background-size: initial;
39 height: 33px;
40 min-height: initial;
41 padding: 6px;
42 padding-right: 30px;
43}
44
45.jupload.input:before {
46 content: "save";
47 font-size: 18px;
48 font-family: "Material Icons", "Material Symbols Outlined", "FontAwesome";
49 color: #000;
50 position: absolute;
51 right: 5px;
52}
53
54.jupload:empty:before {
55 z-index: 0;
56}
57
58.jupload img {
59 width: 100%;
60}
61
62.jupload.input img {
63 width: initial;
64 max-width: 100%;
65 height: 100%;
66}
67
68.jupload[data-multiple] {
69 padding: 10px;
70}
71
72.jupload[data-multiple] img {
73 height: 70px;
74 width: 100px;
75 object-fit: cover;
76 margin-right: 5px;
77 margin-bottom: 5px;
78}
79
80.jupload {
81 position: relative;
82 border: 1px dotted #eee;
83 cursor: pointer;
84 box-sizing: border-box;
85 width: 100%;
86 max-width: 100%;
87 max-height: 100%;
88 min-height: 180px;
89}
90
91.jupload:not(.input):empty:before {
92 content: "\e2c3";
93 font-family: "Material Icons", "Material Symbols Outlined", "FontAwesome";
94 font-size: 90px;
95 color: #eee;
96 width: 100%;
97 height: 100%;
98 display: flex;
99 align-items: center;
100 justify-content: center;
101 position: absolute;
102}
103
104.jupload-item {
105 padding-right: 22px;
106 border-radius: 1px;
107 display: inline-block;
108 position: relative;
109}
110
111.jphoto {
112 position: relative;
113 border: 1px dotted #eee;
114 cursor: pointer;
115 box-sizing: border-box;
116 width: 100%;
117 display: flex;
118 align-items: center;
119 justify-content: center;
120}
121
122.jphoto:empty:before {
123 content: "\e2c3";
124 font-family: "Material Icons", "Material Symbols Outlined", "FontAwesome";
125 font-size: 90px;
126 color: #eee;
127 width: 100%;
128 height: 100%;
129 text-align: center;
130}
131
132.jremove {
133 opacity: 0.2;
134 filter: alpha(opacity=20);
135}
136
137.round img {
138 border-radius: 1000px;
139}
140
141.jtooltip {
142 position: fixed;
143 top: 10px;
144 left: 10px;
145 z-index: 5;
146
147 font-family: initial;
148 font-size: 12px;
149 color: #000;
150 background-color: #fff;
151 border: 1px solid black;
152 padding: 8px;
153 margin: 10px;
154
155 display: block;
156 animation: jfadeIn 0.5s;
157 pointer-events: none;
158}
159
160.jtooltip:empty {
161 display: none;
162}
163
164@keyframes jfadeIn {
165 0% {
166 opacity: 0;
167 }
168 100% {
169 opacity: 1;
170 }
171}
172
173.jpanel {
174 position: absolute;
175 box-sizing: border-box;
176 z-index: 10;
177}
178
179.jpanel:focus {
180 outline: 2px solid var(--jss-border-outline, #000);
181 outline-offset: -1px;
182 z-index: 1000 !important;
183}
184
185.jpanel-action {
186 position: absolute;
187 width: 8px;
188 height: 8px;
189 background-color: white;
190 border:1px solid black;
191 box-sizing: border-box;
192 pointer-events: auto;
193 z-index: 1000;
194}
195
196.jpanel-action[data-position="n-resize"] {
197 top: -4px;
198 left: calc(50% - 4px);
199}
200
201.jpanel-action[data-position="ne-resize"] {
202 top: -4px;
203 left: calc(100% - 4px);
204}
205
206.jpanel-action[data-position="e-resize"] {
207 top: calc(50% - 4px);
208 left: calc(100% - 4px);
209}
210
211.jpanel-action[data-position="se-resize"] {
212 top: calc(100% - 4px);
213 left: calc(100% - 4px);
214}
215
216.jpanel-action[data-position="s-resize"] {
217 top: calc(100% - 4px);
218 left: calc(50% - 4px);
219}
220
221.jpanel-action[data-position="sw-resize"] {
222 top: calc(100% - 4px);
223 left: -4px;
224}
225
226.jpanel-action[data-position="w-resize"] {
227 top: calc(50% - 4px);
228 left: -4px;
229}
230
231.jpanel-action[data-position="nw-resize"] {
232 top: -4px;
233 left: -4px;
234}
235
236.jpanel-action[data-position="nw-resize"] {
237 top: -4px;
238 left: -4px;
239}
240
241.jpanel-action[data-action="rotate"] {
242 top: -50px;
243 left: calc(50% - 12px);
244 width: 24px;
245 height: 24px;
246 border: 0;
247 cursor: move;
248 background-color: transparent;
249}
250
251.jpanel-action[data-action="rotate"]:before {
252 content: 'refresh';
253 font-family: 'Material Icons', 'Material Symbols Outlined', "FontAwesome";
254 font-size: 24px;
255}
256
257.jpanel-action[data-action="rotate"]:after {
258 position: absolute;
259 content: '';
260 bottom: -22px;
261 left: calc(50% - 1px);
262 width: 1px;
263 height: 26px;
264 background-color: var(--jss-font-color, #000);
265}
266
267.material-icons {
268 font-family: "Material Icons", "Material Symbols Outlined", "FontAwesome";
269 font-size: 24px;
270 font-weight: normal;
271 font-style: normal;
272 line-height: 1;
273 letter-spacing: normal;
274 text-transform: none;
275 display: inline-block;
276 white-space: nowrap;
277 word-wrap: normal;
278 direction: ltr;
279 -webkit-font-feature-settings: 'liga';
280 -webkit-font-smoothing: antialiased;
281}
282/** Loading */
283.jloading {
284 position:fixed;
285 z-index:10001;
286 width:100%;
287 left:0;
288 right:0;
289 top:0;
290 bottom:0;
291 background-color: rgba(0,0,0,0.7);
292}
293
294.jloading::after {
295 content:'';
296 display:block;
297 margin:0 auto;
298 margin-top:50vh;
299 width:40px;
300 height:40px;
301 border-style:solid;
302 border-color:white;
303 border-top-color:transparent;
304 border-width:4px;
305 border-radius:50%;
306 -webkit-animation: jspin .8s linear infinite;
307 animation: jspin .8s linear infinite;
308}
309
310.jloading.jspin {
311 background-color:transparent;
312}
313
314.jloading.jspin::after {
315 margin:0 auto;
316 margin-top:80px;
317 border-color:#aaa;
318 border-top-color:transparent;
319}
320
321/** Animations **/
322.jfade-in {
323 animation: jfade-in 2s forwards;
324}
325
326.jfade-out {
327 animation: jfade-out 1s forwards;
328}
329
330.jslide-left-in {
331 position: relative;
332 animation: jslide-left-in 0.4s forwards;
333}
334
335.jslide-left-out {
336 position: relative;
337 animation: jslide-left-out 0.4s forwards;
338}
339
340.jslide-right-in {
341 position: relative;
342 animation: jslide-right-in 0.4s forwards;
343}
344
345.jslide-right-out {
346 position: relative;
347 animation: jslide-right-out 0.4s forwards;
348}
349
350.jslide-top-in {
351 position: relative;
352 animation: jslide-top-in 0.4s forwards;
353}
354
355.jslide-top-out {
356 position: relative;
357 animation: jslide-top-out 0.2s forwards;
358}
359
360.jslide-bottom-in {
361 position: relative;
362 animation: jslide-bottom-in 0.4s forwards;
363}
364
365.jslide-bottom-out {
366 position: relative;
367 animation: jslide-bottom-out 0.1s forwards;
368}
369
370.jslide-left-in > div {
371 -webkit-transform: translateZ(0px);
372 -webkit-transform: translate3d(0,0,0);
373}
374
375.jslide-left-out > div {
376 -webkit-transform: translateZ(0px);
377 -webkit-transform: translate3d(0,0,0);
378}
379
380.jslide-right-in > div {
381 -webkit-transform: translateZ(0px);
382 -webkit-transform: translate3d(0,0,0);
383}
384
385.jslide-right-out > div {
386 -webkit-transform: translateZ(0px);
387 -webkit-transform: translate3d(0,0,0);
388}
389
390.jspin {
391 animation: jspin 2s infinite linear;
392}
393
394/** Fadein and Fadeout **/
395@keyframes jfade-in {
396 0% { opacity: 0; }
397 100% { opacity: 100; }
398}
399
400@-webkit-keyframes jfade-in {
401 0% { opacity: 0; }
402 100% { opacity: 100; }
403}
404
405@keyframes jfade-out {
406 0% { opacity: 100; }
407 100% { opacity: 0; }
408}
409
410@-webkit-keyframes jfade-out {
411 0% { opacity: 100; }
412 100% { opacity: 0; }
413}
414
415/** Keyframes Left to Right **/
416@keyframes jslide-left-in {
417 0% { left: -100%; }
418 100% { left: 0%; }
419}
420
421@-webkit-keyframes jslide-left-in {
422 0% { left: -100%; }
423 100% { left: 0%; }
424}
425
426@keyframes jslide-left-out {
427 0% { left: 0%; }
428 100% { left: -100%; }
429}
430
431@-webkit-keyframes jslide-left-out {
432 0% { left: 0%; }
433 100% { left: -100%; }
434}
435
436/** Keyframes Right to Left **/
437@keyframes jslide-right-in {
438 0% { left: 100%; }
439 100% { left: 0%; }
440}
441
442@-webkit-keyframes jslide-right-in
443{
444 0% { left: 100%; }
445 100% { left: 0%; }
446}
447
448@keyframes jslide-right-out {
449 0% { left: 0%; }
450 100% { left: 100%; }
451}
452
453@-webkit-keyframes jslide-right-out {
454 0% { left: 0%; }
455 100% { left: 100%; }
456}
457
458/** Keyframes Top to Bottom **/
459@keyframes jslide-top-in {
460 0% { transform: translateY(-100%); }
461 100% { transform: translateY(0%); }
462}
463
464@-webkit-keyframes jslide-top-in {
465 0% { transform: translateY(-100%); }
466 100% { -webkit-transform: translateY(0%); }
467}
468
469@keyframes jslide-top-out {
470 0% { transform: translateY(0%); }
471 100% { transform: translateY(-100%); }
472}
473
474@-webkit-keyframes jslide-top-out {
475 0% { -webkit-transform: translateY(0%); }
476 100% { -webkit-transform: translateY(-100%); }
477}
478
479/** Keyframes Bottom to Top **/
480@keyframes jslide-bottom-in {
481 0% { transform: translateY(100%); }
482 100% { transform: translateY(0%); }
483}
484
485@-webkit-keyframes jslide-bottom-in {
486 0% { transform: translateY(100%); }
487 100% { -webkit-transform: translateY(0%); }
488}
489
490@keyframes jslide-bottom-out {
491 0% { transform: translateY(0%); }
492 100% { transform: translateY(100%); }
493}
494
495@-webkit-keyframes jslide-bottom-out {
496 0% { -webkit-transform: translateY(0%); }
497 100% { -webkit-transform: translateY(100%); }
498}
499
500@-webkit-keyframes jspin {
501 from {
502 -webkit-transform:rotate(0deg);
503 }
504 to {
505 -webkit-transform:rotate(359deg);
506 }
507}
508
509@keyframes jspin {
510 from {
511 transform:rotate(0deg);
512 }
513 to {
514 transform:rotate(359deg);
515 }
516}
517.jcalendar {
518 position:absolute;
519 z-index:9000;
520 display:none;
521 box-sizing:border-box;
522 -webkit-touch-callout: none;
523 -webkit-user-select: none;
524 -khtml-user-select: none;
525 -moz-user-select: none;
526 -ms-user-select: none;
527 user-select: none;
528 -webkit-tap-highlight-color: rgba(0,0,0,0);
529 -webkit-tap-highlight-color: transparent;
530 min-width:280px;
531}
532
533.jcalendar.jcalendar-focus {
534 display:block;
535}
536
537.jcalendar .jcalendar-backdrop {
538 position:fixed;
539 top:0px;
540 left:0px;
541 z-index:9000;
542 min-width:100%;
543 min-height:100%;
544 background-color:rgba(0,0,0,0.5);
545 border:0px;
546 padding:0px;
547 display:none;
548}
549
550.jcalendar .jcalendar-container {
551 position:relative;
552 box-sizing:border-box;
553}
554
555.jcalendar .jcalendar-content {
556 position:absolute;
557 z-index:9001;
558 -webkit-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
559 -moz-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
560 box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
561 background-color:#fff;
562}
563
564.jcalendar-header {
565 text-align:center;
566}
567
568.jcalendar-header span {
569 margin-right:4px;
570 font-size:1.1em;
571 font-weight:bold;
572}
573
574.jcalendar-prev {
575 cursor:pointer;
576 background-image:url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath d=%27M15.41 16.59L10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z%27 fill=%27%23000%27 /%3E%3Cpath fill=%27none%27 d=%27M0 0h24v24H0V0z%27/%3E%3C/svg%3E");
577 background-position:center;
578 background-repeat:no-repeat;
579}
580
581.jcalendar-next {
582 cursor:pointer;
583 background-image:url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath d=%27M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.41z%27 fill=%27%23000%27 /%3E%3Cpath fill=%27none%27 d=%27M0 0h24v24H0V0z%27/%3E%3C/svg%3E");
584 background-position:center;
585 background-repeat:no-repeat;
586}
587
588.jcalendar-weekday {
589 font-weight: 600;
590 background-color: #fcfcfc;
591 padding: 14px;
592}
593
594.jcalendar-table {
595 padding: 10px;
596}
597
598.jcalendar-table > table {
599 width:100%;
600 background-color:#fff;
601}
602
603.jcalendar-table > table > thead {
604 cursor: pointer;
605}
606
607.jcalendar-table thead td {
608 padding: 10px;
609 height: 40px;
610}
611
612.jcalendar-table > table > tbody > tr {
613 height: 34px;
614}
615
616.jcalendar-table > table > tbody td {
617 box-sizing:border-box;
618 cursor:pointer;
619 padding:9px;
620 font-size:0.9em;
621}
622
623.jcalendar-table tfoot td {
624 padding:10px;
625}
626
627.jcalendar-months td, .jcalendar-years td {
628 height:24px;
629}
630
631.jcalendar-input {
632 padding-right:18px;
633 background-image:url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2716%27 height=%2716%27 viewBox=%270 0 24 24%27 fill=%27gray%27%3E%3Cpath d=%27M20 3h-1V1h-2v2H7V1H5v2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 18H4V8h16v13z%27/%3E%3Cpath fill=%27none%27 d=%27M0 0h24v24H0z%27/%3E%3C/svg%3E");
634 background-position:top 50% right 5px;
635 background-repeat:no-repeat;
636 box-sizing: border-box;
637}
638
639.jcalendar-done {
640 -webkit-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
641 -moz-box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
642 box-shadow: 1px 1px 5px 0px rgba(0,0,0,0.39);
643 background-color:#fff;
644}
645
646.jcalendar-update {
647 border:1px solid #ccc;
648 background-color:#fff;
649 border-radius:4px;
650 padding:5px;
651 width:100%;
652}
653
654.jcalendar-container select {
655 width:55px;
656 display:inline-block;
657 border:0px;
658 padding:4px;
659 text-align:center;
660 font-size:1.1em;
661 user-select:none;
662 margin-right:10px;
663}
664
665.jcalendar-container select:first-child {
666 margin-right:2px;
667}
668
669.jcalendar-selected {
670 background-color:#eee;
671}
672
673.jcalendar-reset, .jcalendar-confirm {
674 text-transform:uppercase;
675 cursor:pointer;
676 color: var(--jactive-color);
677}
678
679.jcalendar-controls {
680 padding:15px;
681
682 -webkit-box-sizing: border-box;
683 box-sizing: border-box;
684 vertical-align:middle;
685
686 display: -webkit-box;
687 display: -moz-box;
688 display: -ms-flexbox;
689 display: -webkit-flex;
690 display: flex;
691
692 -webkit-flex-flow: row wrap;
693 justify-content: space-between;
694 align-items:center;
695}
696
697.jcalendar-controls div {
698 font-weight:bold;
699}
700
701.jcalendar-fullsize {
702 position:fixed;
703 width:100%;
704 top:0px;
705 left:0px;
706}
707
708.jcalendar-fullsize .jcalendar-content
709{
710 position:fixed;
711 width:100%;
712 left:0px;
713 bottom:0px;
714}
715
716.jcalendar-focus.jcalendar-fullsize .jcalendar-backdrop {
717 display:block;
718}
719
720.jcalendar-sunday {
721 color: red;
722}
723.jcalendar-disabled {
724 color: #ccc;
725}
726
727.jcalendar-time {
728 display:flex;
729}
730
731.jcalendar_warning {
732 color: red;
733}
734
735.jcalendar-hide-controls .jcalendar-controls {
736 display: none;
737}
738
739.jcolor {
740 display: none;
741 outline: none;
742 position: absolute;
743}
744
745.jcolor-input {
746 padding-right: 24px !important;
747 background: url("data:image/svg+xml,%0A%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27black%27 width=%2718px%27 height=%2718px%27%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3Cpath d=%27M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9c.83 0 1.5-.67 1.5-1.5 0-.39-.15-.74-.39-1.01-.23-.26-.38-.61-.38-.99 0-.83.67-1.5 1.5-1.5H16c2.76 0 5-2.24 5-5 0-4.42-4.03-8-9-8zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 9 6.5 9 8 9.67 8 10.5 7.33 12 6.5 12zm3-4C8.67 8 8 7.33 8 6.5S8.67 5 9.5 5s1.5.67 1.5 1.5S10.33 8 9.5 8zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 5 14.5 5s1.5.67 1.5 1.5S15.33 8 14.5 8zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 9 17.5 9s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z%27/%3E%3C/svg%3E") top 50% right 4px no-repeat, content-box;
748 box-sizing: border-box;
749}
750
751.jcolor-content {
752 position: absolute;
753 z-index: 9000;
754 user-select: none;
755 -webkit-font-smoothing: antialiased;
756 font-size: .875rem;
757 letter-spacing: .2px;
758 -webkit-border-radius: 4px;
759 border-radius: 4px;
760 -webkit-box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.2);
761 box-shadow: 0 8px 10px 1px rgba(0,0,0,0.14), 0 3px 14px 2px rgba(0,0,0,0.12), 0 5px 5px -3px rgba(0,0,0,0.2);
762 background-color:#fff;
763 box-sizing: border-box;
764 min-width: 260px;
765}
766
767.jmodal .jcolor-content {
768 position: fixed;
769}
770
771.jcolor-controls {
772 display: flex;
773 padding: 10px;
774 border-bottom: 1px solid #eee;
775 margin-bottom: 5px;
776}
777
778.jcolor-controls div {
779 flex: 1;
780 font-size: 1em;
781 color: var(--jactive-color);
782 text-transform: uppercase;
783 font-weight: bold;
784 box-sizing: border-box;
785}
786
787.jcolor-content table {
788 border-collapse: collapse;
789 box-sizing: border-box;
790}
791
792.jcolor-focus {
793 display:block;
794}
795
796.jcolor table {
797 width:100%;
798 height:100%;
799 min-height: 160px;
800}
801
802.jcolor td {
803 padding: 7px;
804}
805
806.jcolor-selected {
807 background-repeat:no-repeat;
808 background-size: 16px;
809 background-position: center;
810 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3Cpath d=%27M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z%27 fill=%27white%27/%3E%3C/svg%3E");
811}
812
813.jcolor-fullscreen {
814 position: fixed;
815 left: 0px;
816 bottom: 0px;
817 width:100%;
818 max-height: 290px;
819 border-radius: 0px;
820 box-sizing: border-box;
821}
822
823.jcolor-fullscreen .jcolor-controls {
824 padding: 15px;
825 -webkit-box-shadow: 1px 0px 1px 0px rgba(0,0,0,0.39);
826 -moz-box-shadow: 1px 0px 1px 0px rgba(0,0,0,0.39);
827 box-shadow: 1px 0px 1px 0px rgba(0,0,0,0.39);
828}
829
830.jcolor-reset {
831 text-align: left;
832}
833
834.jcolor-close {
835 text-align: right;
836}
837
838.jcolor-backdrop {
839 position: fixed;
840 top: 0px;
841 left: 0px;
842 min-width: 100%;
843 min-height: 100%;
844 background-color: rgba(0,0,0,0.5);
845 border: 0px;
846 padding: 0px;
847 z-index: 8000;
848 display: none;
849
850 -webkit-touch-callout: none; /* iOS Safari */
851 -webkit-user-select: none; /* Safari */
852 -khtml-user-select: none; /* Konqueror HTML */
853 -moz-user-select: none; /* Firefox */
854 -ms-user-select: none; /* Internet Explorer/Edge */
855 user-select: none; /* Non-prefixed version, currently
856 supported by Chrome and Opera */
857}
858
859.jcolor-content .jtabs-content {
860 padding: 7px;
861}
862
863.jcolor-grid tr:first-child > td:first-child {
864 border-top-left-radius: 3px;
865}
866
867.jcolor-grid tr:first-child > td:last-child {
868 border-top-right-radius: 3px;
869}
870
871.jcolor-grid tr:last-child > td:first-child {
872 border-bottom-left-radius: 3px;
873}
874
875.jcolor-grid tr:last-child > td:last-child {
876 border-bottom-right-radius: 3px;
877}
878
879.jcolor-hsl {
880 box-sizing: border-box;
881}
882
883.jcolor-hsl > div {
884 height: 100%;
885 position: relative;
886}
887
888.jcolor-hsl canvas {
889 display: block;
890 border-radius: 4px;
891 -webkit-user-drag: none;
892}
893
894.jcolor-point {
895 height: 5px;
896 width: 5px;
897 background-color: #000;
898 position: absolute;
899 top: 50%;
900 left: 50%;
901 transform: translate(-50%, -50%);
902 border-radius: 50%;
903}
904
905.jcolor-sliders {
906 padding: 10px 20px 10px 10px;
907}
908
909.jcolor-sliders input {
910 -webkit-appearance: none;
911
912 height: 12px;
913 width: 80%;
914
915 background: #d3d3d3;
916 opacity: 1;
917
918 border-radius: 30px;
919 outline: none;
920}
921
922.jcolor-sliders-input-subcontainer {
923 display: flex;
924 justify-content: space-between;
925 align-items: center;
926}
927
928.jcolor-sliders-input-container {
929 margin-top: 4px;
930 line-height: 0.8em;
931 text-align: left;
932}
933
934.jcolor-sliders-input-container > label {
935 font-size: 10px;
936 text-transform: uppercase;
937 color: #bbbbbd;
938}
939
940.jcolor-sliders-input-subcontainer > input {
941 border: 0px;
942 padding: 1px;
943}
944
945.jcolor-sliders-input-container input::-webkit-slider-thumb {
946 -webkit-appearance: none;
947 height: 12px;
948 width: 12px;
949 border-radius: 50%;
950 background: #000;
951 border: 2px solid #fff;
952 cursor: pointer;
953}
954
955.jcolor-sliders-input-container input::-moz-range-thumb {
956 -webkit-appearance: none;
957 height: 12px;
958 width: 12px;
959 border-radius: 50%;
960 background: #000;
961 border: 2px solid #fff;
962 cursor: pointer;
963}
964
965.jcolor-sliders-final-color {
966 padding: 6px;
967 user-select: all;
968 margin-top: 10px;
969 text-align: center;
970}
971
972.jcolor-sliders-final-color > div:nth-child(2) {
973 width: 71px;
974 text-transform: uppercase;
975}
976
977.jcolor .jtabs .jtabs-headers-container .jtabs-controls {
978 display: none !important;
979}
980
981.jcolor .jtabs .jtabs-headers-container {
982 display: flex !important;
983 justify-content: center;
984 padding: 4px;
985}
986
987.jcolor .jtabs-headers > div:not(.jtabs-border) {
988 padding: 2px !important;
989 padding-left: 15px !important;
990 padding-right: 15px !important;
991 font-size: 0.8em;
992}
993.jcontextmenu {
994 position:fixed;
995 z-index:10000;
996 background:#fff;
997 color: #555;
998 font-size: 11px;
999 -webkit-user-select: none;
1000 -moz-user-select: none;
1001 user-select: none;
1002 -webkit-box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
1003 -moz-box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
1004 box-shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
1005 border: 1px solid #C6C6C6;
1006 padding: 0px;
1007 padding-top:4px;
1008 padding-bottom:4px;
1009 margin:0px;
1010 outline:none;
1011 display:none;
1012}
1013
1014.jcontextmenu.jcontextmenu-focus {
1015 display:inline-block;
1016}
1017
1018.jcontextmenu > div {
1019 box-sizing: border-box;
1020 display: flex;
1021 padding: 8px 8px 8px 32px;
1022 width: 250px;
1023 position: relative;
1024 cursor: default;
1025 font-size: 11px;
1026 font-family:sans-serif;
1027 text-align: left;
1028 -webkit-box-align: center;
1029 align-items: center;
1030}
1031
1032.jcontextmenu > div::before {
1033 content: attr(data-icon);
1034 font-family: 'Material Icons' !important;
1035 font-size: 15px;
1036 position: absolute;
1037 left: 9px;
1038 line-height: 24px;
1039}
1040
1041.jcontextmenu.symbols > div::before {
1042 font-family: 'Material Symbols Outlined' !important;
1043}
1044
1045.jcontextmenu > div.header {
1046 display: none;
1047}
1048
1049.jcontextmenu > div a {
1050 color: #555;
1051 text-decoration: none;
1052 flex: 1;
1053 cursor: pointer;
1054}
1055
1056.jcontextmenu > div span {
1057 margin-right: 10px;
1058 font-size: 0.9em;
1059}
1060
1061.jcontextmenu .jcontextmenu-disabled a {
1062 color: #ccc;
1063}
1064
1065.jcontextmenu .jcontextmenu-disabled::before {
1066 color: #ccc;
1067}
1068
1069.jcontextmenu > div:hover {
1070 background: #ebebeb;
1071}
1072
1073.jcontextmenu hr {
1074 border: 1px solid #e9e9e9;
1075 border-bottom: 0;
1076 margin-top:5px;
1077 margin-bottom:5px;
1078}
1079
1080.jcontextmenu > hr:hover {
1081 background: transparent;
1082}
1083
1084.jcontextmenu .jcontextmenu {
1085 top: 4px;
1086 left: 99%;
1087 opacity: 0;
1088 position: absolute;
1089}
1090
1091.jcontextmenu > div:hover > .jcontextmenu {
1092 display: block;
1093 opacity: 1;
1094 -webkit-transform: translate(0, 0) scale(1);
1095 transform: translate(0, 0) scale(1);
1096 pointer-events: auto;
1097}
1098
1099@media only screen and (max-width: 420px) {
1100 .jcontextmenu {
1101 top: initial !important;
1102 left: 0px !important;
1103 bottom: 0px !important;
1104 width: 100vw;
1105 height: 260px;
1106 overflow: scroll;
1107 animation: jslide-bottom-in 0.4s forwards;
1108 padding-top: 0px;
1109 }
1110 .jcontextmenu div {
1111 width: 100%;
1112 text-align: center;
1113 border-bottom: 1px solid #ccc;
1114 padding: 15px;
1115 }
1116 .jcontextmenu > div.header {
1117 background-color: lightgray;
1118 padding: 5px;
1119 top: 0px;
1120 position: sticky;
1121 z-index: 2;
1122 }
1123 .jcontextmenu > div.header > a.title {
1124 text-align: left;
1125 }
1126
1127 .jcontextmenu > div.header > a.close {
1128 text-align: right;
1129 }
1130 .jcontextmenu a {
1131 font-size: 1.4em;
1132 text-transform: uppercase;
1133 }
1134 .jcontextmenu span {
1135 display: none;
1136 }
1137 .jcontextmenu span {
1138 display: none;
1139 }
1140 .jcontextmenu hr {
1141 display: none;
1142 }
1143}
1144
1145.jdropdown {
1146 cursor:pointer;
1147 -webkit-touch-callout: none;
1148 -webkit-user-select: none;
1149 -khtml-user-select: none;
1150 -moz-user-select: none;
1151 -ms-user-select: none;
1152 user-select: none;
1153 box-sizing: border-box;
1154 background:#fff;
1155 -webkit-tap-highlight-color: transparent;
1156 display: inline-block;
1157}
1158
1159.jdropdown-backdrop {
1160 position:fixed;
1161 top:0px;
1162 left:0px;
1163 min-width:100%;
1164 min-height:100%;
1165 background-color:rgba(0,0,0,0.5);
1166 border:0px;
1167 padding:0px;
1168 z-index:8000;
1169 display:none;
1170}
1171
1172.jdropdown[disabled] {
1173 opacity: 0.5;
1174 pointer-events: none;
1175}
1176
1177.jdropdown-focus {
1178 position:relative;
1179}
1180
1181.jdropdown-focus .jdropdown-container {
1182 transform: translate3d(0,0,0);
1183}
1184
1185.jdropdown-default.jdropdown-focus .jdropdown-header {
1186 outline:auto 5px -webkit-focus-ring-color;
1187}
1188
1189.jdropdown-default.jdropdown-focus .jdropdown-header.jdropdown-add {
1190 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27gray%27 width=%2724px%27 height=%2724px%27%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3Cpath d=%27M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z%27/%3E%3C/svg%3E");
1191}
1192
1193.jdropdown-container-header {
1194 padding:0px;
1195 margin:0px;
1196 position:relative;
1197 box-sizing: border-box;
1198}
1199
1200.jdropdown-header {
1201 width:100%;
1202 appearance: none;
1203 background-repeat: no-repeat;
1204 background-position:top 50% right 5px;
1205 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath fill=%27none%27 d=%27M0 0h24v24H0V0z%27/%3E%3Cpath d=%27M7 10l5 5 5-5H7z%27 fill=%27gray%27/%3E%3C/svg%3E");
1206 text-overflow: ellipsis;
1207 cursor:pointer;
1208 box-sizing: border-box;
1209 -webkit-appearance: none;
1210 -moz-appearance: none;
1211 padding-right:30px !important;
1212}
1213
1214.jdropdown-insert-button {
1215 font-size: 1.4em;
1216 text-transform: uppercase;
1217 position:absolute;
1218 right: 30px;
1219 top: 4px;
1220 display:none;
1221}
1222
1223.jdropdown-container {
1224 min-width: inherit;
1225 transform: translate3d(-10000px,0,0);
1226 position:absolute;
1227 z-index:9001;
1228}
1229
1230.jdropdown-close {
1231 display:none;
1232 font-size:1em;
1233 color: var(--jactive-color);
1234 text-transform:uppercase;
1235 text-align:right;
1236 padding:12px;
1237 font-weight:bold;
1238}
1239
1240.jdropdown-content {
1241 min-width:inherit;
1242 margin:0px;
1243 box-sizing:border-box;
1244}
1245
1246.jdropdown-content:empty {
1247}
1248
1249.jdropdown-item {
1250 white-space: nowrap;
1251 text-align: left;
1252 text-overflow: ellipsis;
1253 overflow-x: hidden;
1254 color: #000;
1255 display: flex;
1256 align-items: center;
1257}
1258
1259.jdropdown-description {
1260 text-overflow: ellipsis;
1261 overflow: hidden;
1262 line-height: 1.5em;
1263}
1264
1265.jdropdown-image {
1266 margin-right:10px;
1267 width: 32px;
1268 height: 32px;
1269 border-radius:20px;
1270}
1271
1272.jdropdown-image-small {
1273 width:24px;
1274 height:24px;
1275}
1276
1277.jdropdown-icon {
1278 margin-right:10px;
1279 font-size: 30px;
1280 margin-left: -5px;
1281}
1282
1283.jdropdown-icon-small {
1284 font-size: 24px;
1285 margin-left: 0px;
1286}
1287
1288.jdropdown-title {
1289 font-size: 0.7em;
1290 text-overflow: ellipsis;
1291 overflow-x: hidden;
1292 display: block;
1293}
1294
1295/** Default visual **/
1296
1297.jdropdown-default .jdropdown-header {
1298 border:1px solid #ccc;
1299 padding:5px;
1300 padding-left:10px;
1301 padding-right:16px;
1302}
1303
1304.jdropdown-default .jdropdown-container {
1305 background-color:#fff;
1306}
1307
1308.jdropdown-default.jdropdown-focus.jdropdown-insert .jdropdown-header {
1309 padding-right:50px;
1310}
1311
1312.jdropdown-default.jdropdown-focus.jdropdown-insert .jdropdown-insert-button {
1313 display:block;
1314}
1315
1316.jdropdown-default .jdropdown-content
1317{
1318 min-width:inherit;
1319 border:1px solid #8fb1e3;
1320 margin:0px;
1321 background-color:#fff;
1322 box-sizing:border-box;
1323 min-height:10px;
1324 max-height:215px;
1325 overflow-y:auto;
1326}
1327
1328.jdropdown-default .jdropdown-item
1329{
1330 padding:4px;
1331 padding-left:8px;
1332 padding-right:40px;
1333}
1334
1335.jdropdown-default .jdropdown-item:hover
1336{
1337 background-color:#1f93ff;
1338 color:#fff;
1339}
1340
1341.jdropdown-default .jdropdown-cursor
1342{
1343 background-color:#eee;
1344}
1345
1346.jdropdown-default .jdropdown-selected
1347{
1348 background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiIGZpbGw9IndoaXRlIiAvPjwvc3ZnPgo=);
1349 background-repeat:no-repeat;
1350 background-position:top 50% right 5px;
1351 background-color:#1f93ff;
1352 color:#fff;
1353}
1354
1355.jdropdown-default .jdropdown-group {
1356 margin-top:5px;
1357}
1358
1359.jdropdown-default .jdropdown-group .jdropdown-item {
1360 padding-left:16px;
1361}
1362
1363.jdropdown-default .jdropdown-group-name {
1364 padding-left: 8px;
1365 font-weight: bold;
1366 text-align: left;
1367}
1368
1369.jdropdown-default .jdropdown-reset_ {
1370 content:'x';
1371 position:absolute;
1372 top:0;
1373 right:0;
1374 margin:5px;
1375 margin-right:10px;
1376 font-size:12px;
1377 width:12px;
1378 cursor:pointer;
1379 text-shadow: 0px 0px 5px #fff;
1380 display:none;
1381 line-height: 1.8em;
1382}
1383
1384.jdropdown-default.jdropdown-focus .jdropdown-reset_ {
1385 display:block;
1386}
1387
1388/** Default render for mobile **/
1389
1390.jdropdown-picker.jdropdown-focus .jdropdown-backdrop {
1391 display:block;
1392}
1393
1394.jdropdown-picker .jdropdown-header {
1395 outline: none;
1396}
1397
1398.jdropdown-picker .jdropdown-container
1399{
1400 position:fixed;
1401 bottom:0px;
1402 left:0px;
1403 border-bottom:1px solid #e6e6e8;
1404 width:100%;
1405 background-color:#fff;
1406 box-sizing: border-box;
1407}
1408
1409.jdropdown-picker .jdropdown-close
1410{
1411 -webkit-box-shadow: 0px -1px 5px 0px rgba(0,0,0,0.39);
1412 -moz-box-shadow: 0px -1px 5px 0px rgba(0,0,0,0.39);
1413 box-shadow: 0px -1px 5px 0px rgba(0,0,0,0.39);
1414 background-color:#fff;
1415 display:block;
1416}
1417
1418.jdropdown-picker .jdropdown-content
1419{
1420 overflow-y:scroll;
1421 height:280px;
1422 background-color:#fafafa;
1423 border-top:1px solid #e6e6e8;
1424}
1425
1426.jdropdown-picker .jdropdown-group-name
1427{
1428 font-size: 1em;
1429 text-transform: uppercase;
1430 padding-top:10px;
1431 padding-bottom:10px;
1432 display: block;
1433 border-bottom: 1px solid #e6e6e8;
1434 padding-left:20px;
1435 padding-right:20px;
1436 text-align:center;
1437 font-weight:bold;
1438}
1439
1440.jdropdown-picker .jdropdown-item
1441{
1442 font-size: 1em;
1443 text-transform: uppercase;
1444 padding-top:10px;
1445 padding-bottom:10px;
1446 border-bottom: 1px solid #e6e6e8;
1447 padding-left:20px;
1448 padding-right:20px;
1449}
1450
1451.jdropdown-picker .jdropdown-selected
1452{
1453 background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPjxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiIGZpbGw9IndoaXRlIiAvPjwvc3ZnPgo=);
1454 background-repeat:no-repeat;
1455 background-position:top 50% right 15px;
1456 background-color:#1f93ff;
1457 color:#fff;
1458}
1459
1460.jdropdown-picker .jdropdown-cursor
1461{
1462 background-color:#1f93ff;
1463 color:#fff;
1464}
1465
1466/** Default render for mobile searchbar **/
1467
1468.jdropdown-searchbar.jdropdown-focus
1469{
1470 position:fixed;
1471 top:0px !important;
1472 left:0px !important;
1473 width:100% !important;
1474 height:100% !important;
1475 background-color:#fafafa;
1476 padding:0px;
1477 z-index:9001;
1478 overflow-y:scroll;
1479 will-change: scroll-position;
1480 -webkit-overflow-scrolling: touch;
1481}
1482
1483.jdropdown-searchbar.jdropdown-focus .jdropdown-container-header
1484{
1485 position: fixed;
1486 top: 0px;
1487 left: 0px;
1488 z-index: 9002;
1489 padding: 6px;
1490 background-color:#fff;
1491 box-shadow: 0 1px 2px rgba(0,0,0,.1);
1492 width: 100%;
1493 height: 40px;
1494}
1495
1496.jdropdown-searchbar.jdropdown-focus .jdropdown-header
1497{
1498 border: 0px !important;
1499 background-position-x: 0% !important;
1500 background-position-y: 40% !important;
1501 background-repeat: no-repeat;
1502 background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMTUuNSAxNGgtLjc5bC0uMjgtLjI3QzE1LjQxIDEyLjU5IDE2IDExLjExIDE2IDkuNSAxNiA1LjkxIDEzLjA5IDMgOS41IDNTMyA1LjkxIDMgOS41IDUuOTEgMTYgOS41IDE2YzEuNjEgMCAzLjA5LS41OSA0LjIzLTEuNTdsLjI3LjI4di43OWw1IDQuOTlMMjAuNDkgMTlsLTQuOTktNXptLTYgMEM3LjAxIDE0IDUgMTEuOTkgNSA5LjVTNy4wMSA1IDkuNSA1IDE0IDcuMDEgMTQgOS41IDExLjk5IDE0IDkuNSAxNHoiIGZpbGw9IiNlNmU2ZTgiLz48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PC9zdmc+);
1503 padding-left: 30px !important;
1504 padding-right: 60px !important;
1505}
1506
1507.jdropdown-searchbar.jdropdown-focus .jdropdown-close
1508{
1509 display:block;
1510}
1511
1512.jdropdown-searchbar .jdropdown-header {
1513 outline: none;
1514}
1515
1516.jdropdown-searchbar .jdropdown-container
1517{
1518 margin-top: 40px;
1519 width:100%;
1520}
1521
1522.jdropdown-searchbar .jdropdown-close
1523{
1524 position:fixed;
1525 top:0px;
1526 right:0px;
1527}
1528
1529.jdropdown-searchbar .jdropdown-content
1530{
1531 margin-top:10px;
1532}
1533
1534.jdropdown-searchbar .jdropdown-group
1535{
1536 margin-top:10px;
1537 margin-bottom:15px;
1538 background-color:#fff;
1539}
1540
1541.jdropdown-searchbar .jdropdown-group-name
1542{
1543 border-top: 1px solid #e6e6e8;
1544 border-bottom: 1px solid #e6e6e8;
1545 padding:10px;
1546 padding-left:12px;
1547 font-weight:bold;
1548}
1549
1550.jdropdown-searchbar .jdropdown-group-arrow
1551{
1552 float:right;
1553 width:24px;
1554 height:24px;
1555 background-repeat:no-repeat;
1556}
1557
1558.jdropdown-searchbar .jdropdown-group-arrow-down
1559{
1560 background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNNy40MSA4LjU5TDEyIDEzLjE3bDQuNTktNC41OEwxOCAxMGwtNiA2LTYtNiAxLjQxLTEuNDF6Ii8+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgyNHYyNEgwVjB6Ii8+PC9zdmc+);
1561}
1562
1563.jdropdown-searchbar .jdropdown-group-arrow-up
1564{
1565 background-image: url(data:image/svg+xml;base64,CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZD0iTTcuNDEgMTUuNDFMMTIgMTAuODNsNC41OSA0LjU4TDE4IDE0bC02LTYtNiA2eiIvPjxwYXRoIGQ9Ik0wIDBoMjR2MjRIMHoiIGZpbGw9Im5vbmUiLz48L3N2Zz4=);
1566}
1567
1568.jdropdown-searchbar .jdropdown-item
1569{
1570 padding-top:10px;
1571 padding-bottom:10px;
1572 border-bottom: 1px solid #e6e6e8;
1573 padding-left:15px;
1574 padding-right:40px;
1575 background-color:#fff;
1576 font-size:0.9em;
1577}
1578
1579.jdropdown-searchbar .jdropdown-description {
1580 text-overflow: ellipsis;
1581 overflow: hidden;
1582 max-width: calc(100% - 20px);
1583}
1584
1585.jdropdown-searchbar .jdropdown-content > .jdropdown-item:first-child
1586{
1587 border-top: 1px solid #e6e6e8;
1588}
1589
1590.jdropdown-searchbar .jdropdown-selected
1591{
1592 background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTkgMTYuMTdMNC44MyAxMmwtMS40MiAxLjQxTDkgMTkgMjEgN2wtMS40MS0xLjQxeiIgZmlsbD0iIzAwN2FmZiIvPjwvc3ZnPg==);
1593 background-repeat:no-repeat;
1594 background-position:top 50% right 15px;
1595}
1596
1597/** List render **/
1598
1599.jdropdown-list
1600{
1601}
1602
1603.jdropdown-list .jdropdown-container
1604{
1605 display:block;
1606}
1607
1608.jdropdown-list .jdropdown-header
1609{
1610 display:none;
1611}
1612
1613.jdropdown-list .jdropdown-group
1614{
1615 background-color:#fff;
1616}
1617
1618.jdropdown-list .jdropdown-group-name
1619{
1620 border-bottom: 1px solid #e6e6e8;
1621 padding-top:10px;
1622 padding-bottom:10px;
1623 font-weight:bold;
1624}
1625
1626.jdropdown-list .jdropdown-item
1627{
1628 padding-top:10px;
1629 padding-bottom:10px;
1630 border-bottom: 1px solid #e6e6e8;
1631 padding-left:10px;
1632 padding-right:40px;
1633 background-color:#fff;
1634}
1635
1636.jdropdown-list .jdropdown-selected
1637{
1638 background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij48cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTkgMTYuMTdMNC44MyAxMmwtMS40MiAxLjQxTDkgMTkgMjEgN2wtMS40MS0xLjQxeiIgZmlsbD0iIzAwN2FmZiIvPjwvc3ZnPg==);
1639 background-repeat:no-repeat;
1640 background-position:top 50% right 10px;
1641}
1642
1643@media only screen and (max-width : 800px)
1644{
1645 .jdropdown-list {
1646 width:100% !important;
1647 border:0px;
1648 padding:0px;
1649 }
1650
1651 .jdropdown-list .jdropdown-container {
1652 min-width:100%;
1653 }
1654
1655 .jdropdown-searchbar.jdropdown-focus .jdropdown-description {
1656 text-transform: uppercase;
1657 }
1658}
1659
1660.app .jdropdown-item {
1661 text-transform:uppercase;
1662}
1663
1664.jdropdown-create-container {
1665 margin: 10px;
1666 border: 1px solid #ccc;
1667 border-radius: 2px;
1668 padding: 6px;
1669}
1670
1671.jdropdown-color {
1672 background-color: #fff;
1673 border: 1px solid transparent;
1674 border-radius: 12px;
1675 width: 12px;
1676 height: 12px;
1677 margin-right: 6px;
1678}
1679
1680.jdropdown-item[data-disabled] {
1681 opacity: 0.5;
1682 pointer-events: none;
1683}
1684.jeditor-container {
1685 border:1px solid #ccc;
1686 box-sizing: border-box;
1687}
1688
1689.jeditor-container.with-margin {
1690 background-color: #f2f2f2;
1691 max-width: 1200px;
1692}
1693
1694.jeditor-dragging {
1695 border:1px dashed #000;
1696}
1697
1698.jeditor {
1699 outline:none;
1700 word-break: break-word;
1701}
1702
1703.jeditor-container.with-margin .jeditor {
1704 background-color: #fff;
1705 margin: 80px;
1706 min-height: 800px;
1707 padding: 80px;
1708 max-width: 800px;
1709}
1710
1711.jeditor[data-placeholder]:empty:before {
1712 content: attr(data-placeholder);
1713 color: lightgray;
1714}
1715
1716/** Snippet **/
1717
1718.jsnippet {
1719 margin-top:15px;
1720 cursor:pointer;
1721 border: 1px solid #ccc;
1722 position:relative;
1723}
1724
1725.jsnippet:focus {
1726 outline: none;
1727}
1728
1729.jsnippet img {
1730 width:100%;
1731}
1732
1733.jsnippet .jsnippet-title {
1734 padding:15px;
1735 font-size:1.4em;
1736}
1737
1738.jsnippet .jsnippet-description {
1739 padding-left:15px;
1740 padding-right:15px;
1741 font-size:1em;
1742}
1743
1744.jsnippet .jsnippet-host {
1745 padding:15px;
1746 text-transform:uppercase;
1747 font-size:0.8em;
1748 color:#777;
1749 text-align:right;
1750}
1751
1752.jsnippet .jsnippet-url {
1753 display:none;
1754}
1755
1756.jeditor .jsnippet:after {
1757 content: 'close';
1758 font-family: 'Material icons';
1759 font-size: 24px;
1760 width: 24px;
1761 height: 24px;
1762 line-height: 24px;
1763 cursor: pointer;
1764 text-shadow: 0px 0px 2px #fff;
1765 position: absolute;
1766 top: 12px;
1767 right: 12px;
1768}
1769
1770.jsnippet * {
1771 -webkit-user-select: none;
1772 -khtml-user-select: none;
1773 -moz-user-select: none;
1774 -o-user-select: none;
1775 user-select: none;
1776
1777 -webkit-user-drag: none;
1778 -khtml-user-drag: none;
1779 -moz-user-drag: none;
1780 -o-user-drag: none;
1781}
1782
1783.jeditor img {
1784 border:2px solid transparent;
1785 box-sizing: border-box;
1786}
1787
1788.jeditor img.resizing {
1789 -webkit-user-select: none;
1790 -khtml-user-select: none;
1791 -moz-user-select: none;
1792 -o-user-select: none;
1793 user-select: none;
1794
1795 -webkit-user-drag: none;
1796 -khtml-user-drag: none;
1797 -moz-user-drag: none;
1798 -o-user-drag: none;
1799}
1800
1801.jeditor img:focus {
1802 border: 2px solid #0096FD;
1803 outline: #0096FD;
1804}
1805
1806.jeditor .pdf {
1807 background-image: url("data:image/svg+xml,%3Csvg version=%271.1%27 id=%27Layer_1%27 xmlns=%27http://www.w3.org/2000/svg%27 xmlns:xlink=%27http://www.w3.org/1999/xlink%27 x=%270px%27 y=%270px%27 viewBox=%270 0 512 512%27 style=%27enable-background:new 0 0 512 512;%27 xml:space=%27preserve%27%3E%3Cpath style=%27fill:%23C30B15;%27 d=%27M511.344,274.266C511.77,268.231,512,262.143,512,256C512,114.615,397.385,0,256,0S0,114.615,0,256 c0,117.769,79.53,216.949,187.809,246.801L511.344,274.266z%27/%3E%3Cpath style=%27fill:%2385080E;%27 d=%27M511.344,274.266L314.991,77.913L119.096,434.087l68.714,68.714C209.522,508.787,232.385,512,256,512 C391.243,512,501.976,407.125,511.344,274.266z%27/%3E%3Cpolygon style=%27fill:%23FFFFFF;%27 points=%27278.328,333.913 255.711,77.913 119.096,77.913 119.096,311.652 %27/%3E%3Cpolygon style=%27fill:%23E8E6E6;%27 points=%27392.904,311.652 392.904,155.826 337.252,133.565 314.991,77.913 255.711,77.913 256.067,333.913 %27/%3E%3Cpolygon style=%27fill:%23FFFFFF;%27 points=%27314.991,155.826 314.991,77.913 392.904,155.826 %27/%3E%3Crect x=%27119.096%27 y=%27311.652%27 style=%27fill:%23FC0F1A;%27 width=%27273.809%27 height=%27122.435%27/%3E%3Cg%3E%3Cpath style=%27fill:%23FFFFFF;%27 d=%27M204.871,346.387c13.547,0,21.341,6.659,21.341,18.465c0,12.412-7.795,19.601-21.341,19.601h-9.611 v14.909h-13.471v-52.975L204.871,346.387L204.871,346.387z M195.26,373.858h8.93c5.904,0,9.308-2.952,9.308-8.552 c0-5.525-3.406-8.324-9.308-8.324h-8.93V373.858z%27/%3E%3Cpath style=%27fill:%23FFFFFF;%27 d=%27M257.928,346.387c16.649,0,28.152,10.746,28.152,26.487c0,15.666-11.655,26.488-28.683,26.488 h-22.25v-52.975H257.928z M248.619,388.615h9.611c8.249,0,14.151-6.357,14.151-15.665c0-9.384-6.205-15.817-14.757-15.817h-9.006 V388.615z%27/%3E%3Cpath style=%27fill:%23FFFFFF;%27 d=%27M308.563,356.982v12.26h23.763v10.596h-23.763v19.525h-13.471v-52.975h39.277v10.595h-25.806 V356.982z%27/%3E%3C/g%3E%3C/svg%3E%0A");
1808 background-repeat: no-repeat;
1809 background-size: cover;
1810 width:60px;
1811 height:60px;
1812}
1813
1814.jeditor-toolbar {
1815 width: fit-content;
1816 max-width: 100%;
1817 box-sizing: border-box;
1818 margin: 10px;
1819}
1820
1821.toolbar-on-top .jeditor-toolbar {
1822 width: initial;
1823 margin: 0px;
1824 box-shadow: 1px 1px 2px rgb(0 0 0 / 10%);
1825 display: block;
1826}
1827
1828.toolbar-on-top .jeditor {
1829 padding: 15px;
1830}
1831
1832.toolbar-on-top .jtoolbar .material-icons {
1833 font-size: 24px;
1834 transform: initial;
1835 margin: 4px;
1836}
1837
1838.toolbar-on-top .jtoolbar .jpicker-header {
1839 font-size: 1em;
1840 margin-top: 4px;
1841 margin-bottom: 4px;
1842}
1843
1844.jeditor table {
1845 border-collapse: collapse;
1846}
1847
1848.jeditor table td {
1849 border: 1px solid #bbb;
1850 height: 2em;
1851}
1852
1853.jeditor table td:focus {
1854 border: 1px solid blue;
1855}
1856
1857.jeditor .line-break {
1858 border-top: 1px dashed #ccc;
1859 display: flex;
1860 justify-content: center;
1861 pointer-events: none;
1862}
1863
1864.jeditor .line-break:before {
1865 content: 'New page';
1866 background-color: #fff;
1867 color: #ccc;
1868 margin: -1em;
1869 padding: 6px;
1870 position: absolute;
1871}
1872.jfloating {
1873 position:fixed;
1874 bottom:0px;
1875 right:0px;
1876 margin-right:5px;
1877
1878 -webkit-box-shadow: 0 2px 10px rgba(0,0,0,.2);
1879 -moz-box-shadow: 0 2px 10px rgba(0,0,0,.2);
1880 border:1px solid #ccc;
1881 background-color:#fff;
1882 box-sizing: border-box;
1883 padding-top:50px !important;
1884 z-index:9002;
1885 border-radius: 8px;
1886}
1887
1888.jfloating.jfloating-big {
1889 width: 510px !important;
1890 height: 472px !important;
1891}
1892
1893.jfloating.jfloating-small {
1894 width: 300px !important;
1895 height: 320px !important;
1896}
1897
1898.jfloating.jfloating-large {
1899 width: 600px !important;
1900 height: 600px !important;
1901}
1902
1903.jfloating:before {
1904 position:absolute;
1905 top:0;
1906 left:0;
1907 width:100%;
1908 content:attr(title);
1909 padding:15px;
1910 box-sizing: border-box;
1911 font-size:1.2em;
1912 box-shadow: 1px 1px 3px rgba(0,0,0,.2);
1913 background-color: #fff;
1914 border-radius: 8px 8px 0px 0px;
1915 background-color: #404040;
1916 font-size: .93rem;
1917 font-weight: 600;
1918 color: white;
1919 letter-spacing: .5px;
1920}
1921
1922.jfloating:after {
1923 content:'';
1924 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath fill=%27%23FFF%27 d=%27M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z%27/%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3C/svg%3E");
1925 position:absolute;
1926 top:0;
1927 right:0;
1928 margin:14px;
1929 font-size:24px;
1930 width:24px;
1931 height:24px;
1932 cursor:pointer;
1933 text-shadow: 0px 0px 5px #fff;
1934}
1935
1936.jfloating_content {
1937 padding:20px;
1938 overflow-y:auto;
1939 max-height:100%;
1940 box-sizing: border-box;
1941 height: -webkit-fill-available;
1942}
1943
1944.jfloating.jfloating-minimized {
1945 height: 50px !important;
1946}
1947
1948.jfloating.jfloating-minimized .jfloating_content {
1949 display: none;
1950}
1951
1952.jmodal {
1953 position:fixed;
1954 top:50%;
1955 left:50%;
1956 width:60%;
1957 height:60%;
1958 -webkit-box-shadow: 0 2px 12px rgba(0,0,0,.2);
1959 -moz-box-shadow: 0 2px 12px rgba(0,0,0,.2);
1960 border:1px solid #ccc;
1961 background-color:#fff;
1962 transform: translate(-50%, -50%);
1963 box-sizing: border-box;
1964 z-index:9002;
1965 border-radius: 4px;
1966 display: flex;
1967 flex-direction: column;
1968}
1969
1970.jmodal_title {
1971 padding: 20px;
1972 height: 70px;
1973 box-sizing: border-box;
1974 font-size: 1.4em;
1975 background-color: #fff;
1976 border-radius: 8px 8px 0px 0px;
1977 pointer-events: none;
1978 display: flex;
1979 -webkit-align-items: center;
1980 -webkit-box-align: center;
1981 align-items: center;
1982 border-bottom: 1px solid #eee;
1983}
1984
1985.jmodal_title > div {
1986 font-size: 1.4em;
1987}
1988
1989.jmodal_title[data-icon]:before {
1990 content: attr(data-icon);
1991 font-family: 'Material Icons' !important;
1992 width: 24px;
1993 height: 24px;
1994 font-size: 24px;
1995 margin-right: 10px;
1996 line-height: 24px;
1997}
1998
1999.jmodal_content {
2000 padding: 20px;
2001 overflow-y: auto;
2002 height: 100%;
2003 box-sizing: border-box;
2004 scrollbar-width: thin;
2005 scrollbar-color: #333 transparent;
2006}
2007
2008.jmodal_title:empty {
2009 display: none;
2010}
2011
2012.jmodal_title:empty + .jmodal_content {
2013 height: 100%;
2014}
2015
2016.jmodal_content::-webkit-scrollbar {
2017 height: 12px;
2018}
2019
2020.jmodal_content::-webkit-scrollbar {
2021 width: 12px;
2022}
2023
2024.jmodal_content::-webkit-scrollbar-track {
2025 border: 1px solid #fff;
2026 background: #eee;
2027}
2028
2029.jmodal_content::-webkit-scrollbar-thumb {
2030 border: 1px solid #fff;
2031 background: #888;
2032}
2033
2034.jmodal:after {
2035 content: '';
2036 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath d=%27M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z%27/%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3C/svg%3E");
2037 position: absolute;
2038 top: 0;
2039 right: 0;
2040 margin: 25px;
2041 font-size: 24px;
2042 width: 24px;
2043 height: 24px;
2044 cursor: pointer;
2045 text-shadow: 0px 0px 5px #fff;
2046}
2047
2048.jmodal_fullscreen {
2049 width: 100% !important;
2050 height: 100% !important;
2051 top: 0px;
2052 left: 0px;
2053 transform: none;
2054 border: 0px;
2055 border-radius: 0px;
2056}
2057
2058.jmodal_backdrop {
2059 position: fixed;
2060 top: 0px;
2061 left: 0px;
2062 min-width: 100%;
2063 min-height: 100%;
2064 background-color: rgba(0,0,0,0.2);
2065 border: 0px;
2066 padding: 0px;
2067 z-index: 8000;
2068 display: none;
2069
2070 -webkit-touch-callout: none; /* iOS Safari */
2071 -webkit-user-select: none; /* Safari */
2072 -khtml-user-select: none; /* Konqueror HTML */
2073 -moz-user-select: none; /* Firefox */
2074 -ms-user-select: none; /* Internet Explorer/Edge */
2075 user-select: none; /* Non-prefixed version, currently
2076 supported by Chrome and Opera */
2077}
2078
2079.jmodal_content .jcalendar .jcalendar-content,
2080.jmodal_content .jdropdown-container {
2081 position: fixed;
2082}
2083
2084.jnotification {
2085 position: fixed;
2086 z-index: 10000;
2087 -webkit-box-sizing: border-box;
2088 box-sizing: border-box;
2089 padding: 10px;
2090 bottom: 0px;
2091}
2092
2093.jnotification-container {
2094 -webkit-box-shadow: 0px 2px 15px -5px rgba(0, 0, 0, 0.7);
2095 box-shadow: 0px 2px 15px -5px rgba(0, 0, 0, 0.7);
2096 padding: 12px;
2097 border-radius: 8px;
2098
2099 background-color: #000;
2100 background: rgba(92,92,92,1);
2101 background: linear-gradient(0deg, rgba(92,92,92,1) 0%, rgba(77,77,77,1) 100%);
2102 color: #fff;
2103 width: 320px;
2104 margin: 30px;
2105 padding: 20px;
2106}
2107
2108.jnotification-close {
2109 content: '';
2110 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2720%27 height=%2720%27 viewBox=%270 0 24 24%27 fill=%27white%27%3E%3Cpath d=%27M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z%27/%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3C/svg%3E");
2111 font-size: 20px;
2112 width: 20px;
2113 height: 20px;
2114 cursor: pointer;
2115}
2116
2117.jnotification-title {
2118 font-weight: bold;
2119}
2120
2121.jnotification-header {
2122 display: flex;
2123 padding-bottom: 5px;
2124}
2125
2126.jnotification-header:empty {
2127 display: none;
2128}
2129
2130.jnotification-image {
2131 margin-right: 5px;
2132}
2133
2134.jnotification-image:empty {
2135 display: none;
2136}
2137
2138.jnotification-image img {
2139 width: 24px;
2140}
2141
2142.jnotification-name {
2143 text-transform: uppercase;
2144 font-size: 0.9em;
2145 flex: 1;
2146 letter-spacing: 0.1em;
2147}
2148
2149.jnotification-error .jnotification-container {
2150 background: rgb(182,38,6);
2151 background: linear-gradient(0deg, rgba(170,41,13,1) 0%, rgba(149,11,11,1) 100%);
2152}
2153
2154@media (max-width: 800px) {
2155 .jnotification {
2156 top: calc(0px + var(--jsafe-area-top));
2157 width: 100%;
2158 }
2159 .jnotification-container {
2160 background: rgba(255,255,255,0.95);
2161 border: 1px solid #eee;
2162 color: #444;
2163 margin: 0px;
2164 width: initial;
2165 }
2166 .jnotification-error .jnotification-container {
2167 background: rgba(255,255,255,0.95);
2168 color: #790909;
2169 }
2170 .jnotification-close {
2171 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2720%27 height=%2720%27 viewBox=%270 0 24 24%27 fill=%27black%27%3E%3Cpath d=%27M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z%27/%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3C/svg%3E");
2172 }
2173}
2174
2175.jnotification-header {
2176 display: -webkit-box;
2177 display: -webkit-flex;
2178 display: -ms-flexbox;
2179 display: flex;
2180 -webkit-box-pack: start;
2181 -webkit-justify-content: flex-start;
2182 -ms-flex-pack: start;
2183 justify-content: flex-start;
2184 -webkit-box-align: center;
2185 -webkit-align-items: center;
2186 -ms-flex-align: center;
2187 align-items: center;
2188}
2189.jpicker {
2190 cursor: pointer;
2191 white-space: nowrap;
2192 display: inline-flex;
2193 -webkit-user-select: none;
2194 -moz-user-select: none;
2195 -ms-user-select: none;
2196 user-select: none;
2197 outline: none;
2198 position: relative;
2199 min-height: 26px;
2200}
2201
2202.jpicker-header {
2203 background-repeat: no-repeat;
2204 background-position: top 50% right 5px;
2205 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath fill=%27none%27 d=%27M0 0h24v24H0V0z%27/%3E%3Cpath d=%27M7 10l5 5 5-5H7z%27 fill=%27gray%27/%3E%3C/svg%3E");
2206 text-overflow: ellipsis;
2207 cursor: pointer;
2208 box-sizing: border-box;
2209 text-align: left;
2210 outline: none;
2211 line-height: 24px;
2212 padding: 2px 35px 2px 12px;
2213 border-radius: 4px;
2214}
2215
2216.jpicker-header:hover {
2217 background-color: #f2f2f2;
2218}
2219
2220.jpicker-content {
2221 position: absolute;
2222 top: 0;
2223 display: none;
2224 box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.2);
2225 border-radius: 4px;
2226 background-color: #fff;
2227 padding: 4px;
2228 z-index: 50;
2229 text-align: left;
2230 max-height: 250px;
2231 scrollbar-width: thin;
2232 scrollbar-color: #333 transparent;
2233}
2234
2235.jpicker-content::-webkit-scrollbar {
2236 width: 8px;
2237}
2238
2239.jpicker-content::-webkit-scrollbar-track {
2240 background: #eee;
2241}
2242
2243.jpicker-content::-webkit-scrollbar-thumb {
2244 background: #888;
2245}
2246
2247.jpicker-content > div {
2248 padding: 6px;
2249 padding-left: 15px;
2250 padding-right: 15px;
2251}
2252
2253.jpicker-focus > .jpicker-content {
2254 display: block;
2255}
2256
2257.jpicker-content > div:hover {
2258 background-color:#efefef;
2259}
2260
2261.jpicker-content > div:empty {
2262 opacity: 0;
2263}
2264
2265.jpicker-header > i, .jpicker-header > div {
2266 display: block;
2267}
2268
2269.jpicker-focus > .jpicker-content.jpicker-columns {
2270 display: flex !important ;
2271 justify-content: center;
2272 flex-wrap: wrap;
2273}
2274
2275.jpicker-focus .jpicker-content.jpicker-grid {
2276 display: inline-grid;
2277}
2278
2279
2280
2281.jprogressbar
2282{
2283 cursor:pointer;
2284 -webkit-touch-callout: none;
2285 -webkit-user-select: none;
2286 -khtml-user-select: none;
2287 -moz-user-select: none;
2288 -ms-user-select: none;
2289 user-select: none;
2290 box-sizing: border-box;
2291 background:#fff;
2292 -webkit-tap-highlight-color: transparent;
2293 display: inline-block;
2294 box-sizing: border-box;
2295 cursor:pointer;
2296 border:1px solid #ccc;
2297 position:relative;
2298}
2299
2300.jprogressbar::before {
2301 content:attr(data-value);
2302 position:absolute;
2303 margin:5px;
2304 margin-left:10px;
2305}
2306
2307.jprogressbar-header::placeholder
2308{
2309 color:#000;
2310}
2311
2312.jprogressbar:focus {
2313 outline: auto 5px -webkit-focus-ring-color;
2314}
2315
2316.jprogressbar > div {
2317 background-color: #eee;
2318 background-color: red;
2319 box-sizing: border-box;
2320 height:31px;
2321}
2322.jrating {
2323 display:flex;
2324}
2325.jrating > div {
2326 width:24px;
2327 height:24px;
2328 line-height:24px;
2329 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath d=%27M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z%27 fill=%27gray%27/%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3C/svg%3E");
2330}
2331
2332.jrating .jrating-over {
2333 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27 fill=%27black%27%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3Cpath d=%27M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z%27/%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3C/svg%3E");
2334 opacity: 0.7;
2335}
2336
2337.jrating .jrating-selected {
2338 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27 fill=%27red%27%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3Cpath d=%27M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z%27/%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3C/svg%3E");
2339}
2340
2341.jsearch {
2342 position: relative;
2343 display: none;
2344 -webkit-user-select: none;
2345 -moz-user-select: none;
2346 -ms-user-select: none;
2347 user-select: none;
2348}
2349
2350.jsearch_container {
2351 position: absolute;
2352 box-shadow: 0 1px 2px 0 rgba(60,64,67,0.302), 0 2px 6px 2px rgba(60,64,67,0.149);
2353 border: none;
2354 -webkit-border-radius: 4px;
2355 border-radius: 4px;
2356 width: 280px;
2357 padding: 8px 0;
2358 z-index: 1;
2359
2360 -webkit-box-shadow: 0 2px 4px rgba(0,0,0,0.2);
2361 box-shadow: 0 2px 4px rgba(0,0,0,0.2);
2362 -webkit-transition: opacity .218s;
2363 transition: opacity .218s;
2364 background: #fff;
2365 border: 1px solid rgba(0,0,0,.2);
2366 cursor: pointer;
2367 margin: 0;
2368 min-width: 300px;
2369 outline: none;
2370 width: auto;
2371 -webkit-user-select: none;
2372 -moz-user-select: none;
2373 -ms-user-select: none;
2374 user-select: none;
2375}
2376
2377.jsearch_container:empty:after {
2378 content: attr(data-placeholder);
2379}
2380
2381.jsearch_container > div {
2382 color: #333;
2383 cursor: pointer;
2384 display: -webkit-box;
2385 display: -webkit-flex;
2386 display: flex;
2387 padding: 5px 10px;
2388 user-select: none;
2389 -webkit-align-items: center;
2390 align-items: center;
2391
2392 -webkit-user-select: none;
2393 -moz-user-select: none;
2394 -ms-user-select: none;
2395 user-select: none;
2396}
2397
2398.jsearch_container > div:hover {
2399 background-color: #e8eaed;
2400}
2401
2402.jsearch_container > div > img {
2403 width: 32px;
2404 height: 32px;
2405 user-select: none;
2406 border-radius: 16px;
2407 margin-right: 2px;
2408}
2409
2410.jsearch_container > div > div {
2411 overflow: hidden;
2412 text-overflow: ellipsis;
2413 margin-left: 2px;
2414 max-width: 300px;
2415 white-space: nowrap;
2416 user-select: none;
2417}
2418
2419.jsearch_container .selected {
2420 background-color: #e8eaed;
2421}
2422.jslider {
2423 outline: none;
2424}
2425
2426.jslider-focus {
2427 width: 100% !important;
2428 height: 100% !important;
2429}
2430
2431.jslider-focus img {
2432 display: none;
2433}
2434
2435.jslider img {
2436 width: 100px;
2437}
2438
2439.jslider-left::before {
2440 position: fixed;
2441 left: 15px;
2442 top: 50%;
2443 content:'arrow_back_ios';
2444 color: #fff;
2445 width: 30px;
2446 height: 30px;
2447 font-family: 'Material Icons';
2448 font-size: 30px;
2449 /* before it was 0px 0px 0px #000 */
2450 text-shadow: 0px 0px 6px rgb(56,56,56);
2451 text-align: center;
2452 cursor: pointer;
2453}
2454
2455.jslider-right::after {
2456 position: fixed;
2457 right: 15px;
2458 top: 50%;
2459 content: 'arrow_forward_ios';
2460 color: #fff;
2461 width: 30px;
2462 height: 30px;
2463 font-family: 'Material Icons';
2464 font-size: 30px;
2465 /* before it was 0px 0px 0px #000 */
2466 text-shadow: 0px 0px 6px rgb(56,56,56);
2467 text-align: center;
2468 cursor: pointer;
2469}
2470
2471.jslider-close {
2472 width:24px;
2473 height:24px;
2474 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27 fill=%27white%27%3E%3Cpath d=%27M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z%27/%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3C/svg%3E");
2475 position:fixed;
2476 top:15px;
2477 right:15px;
2478 cursor:pointer;
2479 z-index:3000;
2480
2481 display: block !important;
2482}
2483
2484.jslider-counter {
2485 height:24px;
2486 background-color: transparent;
2487 position:fixed;
2488 left: 50%;
2489 transform: translateX(-50%);
2490 bottom: 15px;
2491 cursor:pointer;
2492 z-index:3000;
2493
2494 display: flex;
2495 display: -webkit-flex;
2496 -webkit-justify-content: center;
2497 -webkit-align-items: center;
2498 -webkit-flex-direction: row;
2499 justify-content: center;
2500 align-items: center;
2501 flex-direction: row;
2502}
2503
2504.jslider-caption {
2505 position: fixed;
2506 max-width: 90vw;
2507 text-overflow: ellipsis;
2508 white-space: nowrap;
2509 overflow: hidden;
2510 top:15px;
2511 left: 15px;
2512 z-index:3000;
2513 color: #FFF;
2514 font-size: 1rem;
2515
2516 display: block !important;
2517}
2518
2519.jslider-counter div {
2520 width: 10px;
2521 height: 10px;
2522 background: #fff;
2523 border-radius: 50%;
2524 margin: 0px 5px;
2525
2526 display: block !important;
2527}
2528
2529.jslider-counter .jslider-counter-focus {
2530 background-color: cornflowerblue;
2531 pointer-events: none;
2532}
2533
2534.jslider-focus {
2535 position:fixed;
2536 left:0;
2537 top:0;
2538 width: 100%;
2539 min-height:100%;
2540 max-height:100%;
2541 z-index:2000;
2542 margin:0px;
2543 box-sizing:border-box;
2544
2545 background-color:rgba(0,0,0,0.8);
2546 -webkit-transition-duration: .05s;
2547 transition-duration: .05s;
2548 display: flex;
2549 -ms-flex-align: center;
2550 -webkit-align-items: center;
2551 -webkit-box-align: center;
2552
2553 align-items: center;
2554}
2555
2556.jslider-focus img {
2557 width: 50vw;
2558 height: auto;
2559 box-sizing: border-box;
2560 margin:0 auto;
2561 vertical-align:middle;
2562 display:none;
2563}
2564
2565.jslider-focus img.jslider-vertical {
2566 width: auto;
2567 /* before it was 50vh */
2568 height: 80vh;
2569}
2570
2571@media only screen and (max-width: 576px) {
2572 .jslider-focus img.jslider-vertical {
2573 width: 99vw !important;
2574 height: auto !important;
2575 }
2576
2577 .jslider-focus img {
2578 width: 100vw !important;
2579 height: auto !important;
2580 }
2581}
2582
2583.jslider-grid {
2584 display: -ms-grid;
2585 display: grid;
2586 grid-gap: 1px;
2587 position: relative;
2588}
2589
2590.jslider-grid[data-number='2'] {
2591 -ms-grid-columns: 1fr 50%;
2592 grid-template-columns: 1fr 50%;
2593}
2594
2595.jslider-grid[data-number='3'] {
2596 -ms-grid-columns: 1fr 33%;
2597 grid-template-columns: 1fr 33%;
2598}
2599
2600.jslider-grid[data-number='4'] {
2601 -ms-grid-columns: 1fr 25%;
2602 grid-template-columns: 1fr 25%;
2603}
2604
2605.jslider-grid img {
2606 display: none;
2607 width: 100%;
2608 height: 100%;
2609 object-fit: cover;
2610}
2611
2612.jslider-grid[data-total]:after {
2613 content: attr(data-total) "+";
2614 font-size: 1.5em;
2615 position:absolute;
2616 color: #fff;
2617 right: 15px;
2618 bottom: 6px;
2619}
2620
2621.jslider-grid img:first-child {
2622 -ms-grid-column: 1;
2623 -ms-grid-row: 1;
2624 grid-column: 1;
2625 grid-row: 1;
2626 display: block;
2627}
2628
2629.jslider-grid[data-number='2'] img:nth-child(2) {
2630 -ms-grid-column: 2;
2631 -ms-grid-row: 1;
2632 grid-column: 2;
2633 grid-row: 1;
2634 display: block;
2635}
2636
2637.jslider-grid[data-number='3'] img:first-child {
2638 -ms-grid-column: 1 / 2;
2639 -ms-grid-row: 1 / 4;
2640 grid-column: 1 / 2;
2641 grid-row: 1 / 4;
2642}
2643
2644.jslider-grid[data-number='3'] img:nth-child(2) {
2645 -ms-grid-column: 2;
2646 -ms-grid-row: 1;
2647 grid-column: 2;
2648 grid-row: 1;
2649 display: block;
2650}
2651
2652.jslider-grid[data-number='3'] img:nth-child(3) {
2653 -ms-grid-column: 2;
2654 -ms-grid-row: 2;
2655 grid-column: 2;
2656 grid-row: 2;
2657 display: block;
2658}
2659
2660.jslider-grid[data-number='4'] img:first-child {
2661 -ms-grid-column: 1 / 2;
2662 -ms-grid-row: 1 / 4;
2663 grid-column: 1 / 2;
2664 grid-row: 1 / 4;
2665}
2666
2667.jslider-grid[data-number='4'] img:nth-child(2) {
2668 -ms-grid-column: 2;
2669 -ms-grid-row: 1;
2670 grid-column: 2;
2671 grid-row: 1;
2672 display: block;
2673}
2674
2675.jslider-grid[data-number='4'] img:nth-child(3) {
2676 -ms-grid-column: 2;
2677 -ms-grid-row: 2;
2678 grid-column: 2;
2679 grid-row: 2;
2680 display: block;
2681}
2682
2683.jslider-grid[data-number='4'] img:nth-child(4) {
2684 -ms-grid-column: 2;
2685 -ms-grid-row: 3;
2686 grid-column: 2;
2687 grid-row: 3;
2688 display: block;
2689}
2690
2691.jtabs {
2692 max-width: 100vw;
2693 position: relative;
2694}
2695
2696.jtabs .jtabs-headers-container {
2697 display: flex;
2698 align-items: center;
2699}
2700
2701.jtabs .jtabs-headers {
2702 display: flex;
2703 align-items: center;
2704 overflow: hidden;
2705 position: relative;
2706}
2707
2708.jtabs .jtabs-headers > div:not(.jtabs-border) {
2709 padding: 8px;
2710 padding-left: 20px;
2711 padding-right: 20px;
2712 margin-left: 1px;
2713 margin-right: 1px;
2714 background-color: #f1f1f1;
2715 cursor: pointer;
2716 white-space: nowrap;
2717 text-align: center;
2718}
2719
2720.jtabs .jtabs-headers > div.jtabs-selected {
2721 background-color: #e8e8e8;
2722 color: #000;
2723}
2724
2725.jtabs .jtabs-headers > div > div {
2726 color: #555;
2727 width: 100%;
2728 overflow: hidden;
2729}
2730
2731.jtabs .jtabs-headers i {
2732 display: block;
2733 margin: auto;
2734}
2735
2736.jtabs .jtabs-content {
2737 box-sizing: border-box;
2738}
2739
2740.jtabs .jtabs-content > div {
2741 display: none;
2742 box-sizing: border-box;
2743}
2744
2745.jtabs .jtabs-content > div.jtabs-selected {
2746 display: block;
2747}
2748
2749.jtabs .jtabs-border {
2750 position: absolute;
2751 height: 2px;
2752 background-color: #888;
2753 transform-origin: left;
2754 transition: all .2s cubic-bezier(0.4,0,0.2,1);
2755 transition-property: color,left,transform;
2756 display: none;
2757 pointer-events: none;
2758}
2759
2760.jtabs-animation .jtabs-border {
2761 display: initial;
2762}
2763
2764.jtabs .jtabs-controls {
2765 margin: 3px;
2766 margin-left: 10px;
2767 display: flex;
2768 min-width: 82px;
2769}
2770
2771.jtabs .jtabs-controls > div {
2772 cursor: pointer;
2773 background-position: center;
2774 background-repeat: no-repeat;
2775 width: 24px;
2776 height: 24px;
2777 line-height: 24px;
2778}
2779
2780.jtabs .jtabs-prev {
2781 margin-left: 10px;
2782 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27gray%27 width=%2718px%27 height=%2718px%27%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3Cpath d=%27M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z%27/%3E%3C/svg%3E");
2783}
2784
2785.jtabs .jtabs-prev.disabled {
2786 margin-left: 10px;
2787 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27lightgray%27 width=%2718px%27 height=%2718px%27%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3Cpath d=%27M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z%27/%3E%3C/svg%3E");
2788}
2789
2790.jtabs .jtabs-next {
2791 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27gray%27 width=%2718px%27 height=%2718px%27%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3Cpath d=%27M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z%27/%3E%3C/svg%3E");
2792}
2793
2794.jtabs .jtabs-next.disabled {
2795 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 24 24%27 fill=%27lightgray%27 width=%2718px%27 height=%2718px%27%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3Cpath d=%27M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z%27/%3E%3C/svg%3E");
2796}
2797
2798.jtabs .jtabs-add {
2799 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 height=%2724%27 viewBox=%270 0 24 24%27 width=%2724%27%3E%3Cpath d=%27M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-2 10h-4v4h-2v-4H7v-2h4V7h2v4h4v2z%27 fill=%27%23bbbbbb%27/%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3C/svg%3E");
2800}
2801
2802/** Modern skin **/
2803
2804.jtabs.jtabs-modern .jtabs-headers > div:not(.jtabs-border) {
2805 padding: 4px;
2806 padding-left: 10px;
2807 padding-right: 10px;
2808 background-color: #fff;
2809}
2810
2811.jtabs.jtabs-modern .jtabs-headers > .jtabs-selected {
2812 color: #000;
2813}
2814
2815.jtabs.jtabs-modern .jtabs-headers > .jtabs-selected .material-icons {
2816 color: #000;
2817}
2818
2819.jtabs.jtabs-modern .jtabs-headers {
2820 background: #EEEEEF !important;
2821 padding: 2px;
2822 border-radius: 4px;
2823}
2824
2825.jtabs.jtabs-modern .jtabs-headers .jtabs-border {
2826 border-color: #EEEEEF !important;
2827}
2828
2829.jtabs.jtabs-modern .jtabs-border {
2830 background-color: rgba(194, 197, 188, 0.884);
2831}
2832.jtags {
2833 display: flex;
2834 flex-wrap: wrap;
2835 -ms-flex-direction: row;
2836 -webkit-flex-direction: row;
2837 flex-direction: row;
2838 -ms-flex-pack: flex-start;
2839 -webkit-justify-content: space-between;
2840 justify-content: flex-start;
2841 padding: 1px;
2842 border: 1px solid #ccc;
2843 position: relative;
2844}
2845
2846.jtags.jtags-empty:not(.jtags-focus)::before {
2847 position: absolute;
2848 margin: 3px;
2849 color: #ccc;
2850 content: attr(data-placeholder);
2851 top: 0;
2852 margin-left: 6px;
2853}
2854
2855.jtags > div {
2856 padding: 3px 22px 3px 10px;
2857 font-size: 0.9em;
2858 position: relative;
2859 border-radius: 1px;
2860 margin: 2px;
2861 display: block;
2862 outline: none;
2863}
2864
2865.jtags > div:empty:before {
2866 content: " ";
2867 white-space: pre;
2868}
2869
2870.jtags > div::after {
2871 content: 'x';
2872 position: absolute;
2873 right: 4px;
2874 width: 12px;
2875 height: 12px;
2876 cursor: pointer;
2877 font-size: 0.9em;
2878 display: none;
2879}
2880
2881.jtags_label {
2882 background-color: #e4e4e4 !important;
2883}
2884
2885.jtags_label::after {
2886 display: inline-block !important;
2887}
2888
2889.jtags_error::after {
2890 color: #fff !important;
2891}
2892
2893.jtags_error {
2894 background-color: #d93025 !important;
2895 color: #fff;
2896}
2897
2898.jtoolbar-container {
2899 border-radius: 2px;
2900 box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.2);
2901 display: inline-flex !important;
2902}
2903
2904.jtoolbar {
2905 cursor: pointer;
2906 white-space: nowrap;
2907 display: flex;
2908 padding:4px;
2909 -webkit-user-select: none;
2910 -moz-user-select: none;
2911 -ms-user-select: none;
2912 user-select: none;
2913 font-size: 13px;
2914}
2915
2916.jtoolbar-disabled {
2917 pointer-events: none;
2918 opacity: 0.4;
2919}
2920
2921.jtoolbar-mobile {
2922 display: flex;
2923 position:fixed;
2924 bottom: 0;
2925 margin: 0;
2926 left: 0;
2927 width: 100%;
2928 background: #f7f7f8;
2929 z-index: 1;
2930 box-sizing: border-box;
2931 box-shadow: 0 -1px 2px rgba(0,0,0,.1);
2932 border-radius: 0px;
2933}
2934
2935.jtoolbar > div {
2936 display: inline-flex;
2937 align-items: center;
2938 box-sizing: border-box;
2939 vertical-align:middle;
2940 justify-content: space-evenly;
2941}
2942
2943.jtoolbar-mobile > div {
2944 display: flex;
2945 width: 100%;
2946}
2947
2948.jtoolbar .jtoolbar-item {
2949 text-align: center;
2950 margin: auto;
2951 padding: 2px;
2952 padding-left:4px;
2953 padding-right:4px;
2954}
2955
2956.jtoolbar-mobile .jtoolbar-item {
2957 position: relative;
2958 flex:1;
2959}
2960
2961.jtoolbar .jtoolbar-divisor {
2962 width: 2px;
2963 height: 18px;
2964 padding: 0;
2965 margin-left: 4px;
2966 margin-right: 4px;
2967 background-color: var(--jss-border-color, #ccc);
2968}
2969
2970.jtoolbar .jtoolbar-label {
2971 padding-left: 8px;
2972 padding-right: 8px;
2973}
2974
2975.jtoolbar-mobile a
2976{
2977 text-decoration:none;
2978 display:inline-block;
2979}
2980
2981.jtoolbar-mobile i {
2982 display: inline-flex !important;
2983 color:#929292;
2984}
2985
2986.jtoolbar-mobile span {
2987 font-size:0.7em;
2988 display:block;
2989 color:#929292;
2990}
2991
2992.jtoolbar-mobile .jtoolbar-selected a, .jtoolbar-mobile .jtoolbar-selected i, .jtoolbar-mobile .jtoolbar-selected span {
2993 color:var(--jactive-color) !important;
2994 background-color:transparent;
2995}
2996
2997.jtoolbar-item {
2998 -webkit-user-select: none;
2999 -moz-user-select: none;
3000 -ms-user-select: none;
3001 user-select: none;
3002}
3003
3004.jtoolbar-item i {
3005 display: block;
3006 color:#333;
3007}
3008
3009.jtoolbar-item:hover {
3010 background-color: var(--jss-background-color-highlight, #e8e8e8);
3011}
3012
3013.jtoolbar .jpicker {
3014 padding-left: 0;
3015 padding-right: 0;
3016}
3017
3018.jtoolbar .jpicker-header {
3019 padding: 0 20px 0 8px;
3020 background-position: top 50% right 0;
3021 display: flex;
3022 align-items: center;
3023}
3024
3025.jtoolbar .jpicker-content > div {
3026 padding: 6px;
3027}
3028
3029.jtoolbar-active {
3030 background-color:#eee;
3031}
3032
3033.jtoolbar .fa {
3034 width: 18px;
3035 height: 18px;
3036 display: block;
3037 line-height: 18px;
3038 font-size: 14px;
3039}
3040
3041.jtoolbar .material-icons {
3042 font-size: 18px;
3043 width: 24px;
3044 height: 24px;
3045 display: block;
3046 line-height: 24px;
3047 transform: rotate(0.03deg);
3048 text-align: center;
3049}
3050
3051.jtoolbar .jtoolbar-arrow {
3052 background-repeat: no-repeat;
3053 background-position: center;
3054 width: 24px;
3055 margin-left: 4px;
3056 border-left: 1px solid var(--jss-border-color, #ccc);
3057}
3058
3059.jtoolbar-floating {
3060 position: absolute;
3061 display: none;
3062 box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14), 0 1px 10px 0 rgba(0,0,0,0.12), 0 2px 4px -1px rgba(0,0,0,0.2);
3063 border-radius: 4px;
3064 background-color: var(--jss-background-color-header, #fff);
3065 padding: 4px;
3066 z-index: 50;
3067 text-align: left;
3068 margin-right: 20px;
3069}
3070
3071.jtoolbar-floating .jtoolbar-divisor {
3072 display: none;
3073}
3074
3075.jtoolbar-arrow-selected .jtoolbar-floating {
3076 display: flex;
3077 flex-wrap: wrap;
3078}
3079
3080:root {
3081 --lm-font-color: inherit;
3082 --lm-main-color: #2196f3;
3083 --lm-main-color-alpha: #2196f388;
3084 --lm-main-color-highlight: #1f64e1;
3085 --lm-secondary-color: #737373;
3086
3087 --lm-border-color: #ccc;
3088 --lm-border-color-light: #e9e9e9;
3089 --lm-border-color-highlight: #aaa;
3090 --lm-border-outline: #000;
3091 --lm-background-color: #fff;
3092 --lm-background-color-header: #f8f8f8;
3093 --lm-background-color-highlight: #ececec;
3094 --lm-background-color-active: #dcdcdc;
3095 --lm-background-color-input: initial;
3096 --lm-icon-color: #777;
3097
3098 --lm-font-grayout: #777;
3099 --lm-input-padding: 6px;
3100 --lm-border-radius: 2px;
3101 --lm-safe-area-top: 0;
3102 --lm-safe-area-bottom: 0;
3103 --lm-text-color: #000;
3104}
3105
3106.lm-dark-mode {
3107 --lm-font-color: #ddd;
3108 --lm-font-grayout: #777;
3109 --lm-border-color: #444;
3110 --lm-border-color-light: #222;
3111 --lm-border-color-highlight: #777;
3112 --lm-border-outline: #fff;
3113 --lm-background-color: #000;
3114 --lm-background-color-header: #181818;
3115 --lm-background-color-highlight: #282828;
3116 --lm-background-color-active: #858585;
3117 --lm-background-color-input: #181818;
3118 --lm-icon-color: #ccc;
3119}
3120
3121.lm-green {
3122 --lm-main-color: #39a33b;
3123 --lm-main-color-alpha: #39a33b88;
3124 --lm-main-color-highlight: #2f8431;
3125}
3126
3127@media (prefers-color-scheme: dark) {
3128}
3129
3130
3131body.lm-application {
3132 margin: 0;
3133 padding: 0;
3134 font-family: Montserrat, sans-serif;
3135 background: var(--lm-background-color);
3136 color: var(--lm-font-color);
3137}
3138
3139.lm-application input[type='text'],
3140.lm-application input[type='number'],
3141.lm-application input[type='password'],
3142.lm-application select,
3143.lm-application textarea,
3144.lm-application button,
3145.lm-input {
3146 padding: var(--lm-input-padding) var(--lm-input-padding) var(--lm-input-padding) 8px;
3147 box-sizing: border-box;
3148 border: 1px solid var(--lm-border-color, #ccc);
3149 background-color: var(--lm-background-color-input);
3150 line-height: initial;
3151 border-radius: 2px;
3152 color: var(--lm-font-color);
3153 font-family: inherit;
3154 font-size: inherit;
3155}
3156
3157.lm-application *:disabled {
3158 color: #888;
3159}
3160
3161[visible='false'] {
3162 display: none;
3163}
3164
3165[visible='true'] {
3166 display: block;
3167}
3168
3169.lm-container {
3170 width: 100%;
3171 margin: 0 auto;
3172 box-sizing: border-box;
3173}
3174
3175.lm-row {
3176 display: flex;
3177 flex-wrap: nowrap;
3178 flex-direction: row;
3179 justify-content: space-between;
3180 box-sizing: border-box;
3181}
3182
3183.lm-row.lm-container {
3184 flex-wrap: nowrap;
3185}
3186
3187.lm-row.lm-middle {
3188 align-items: center;
3189}
3190
3191.lm-row.lm-start {
3192 justify-content: start;
3193}
3194
3195.lm-column {
3196 box-sizing: border-box;
3197}
3198
3199.lm-column.lm-top {
3200 align-self: flex-start;
3201}
3202
3203.lm-column.lm-bottom {
3204 align-self: flex-end;
3205}
3206
3207.lm-form-group {
3208 width: 100%;
3209 padding-right: 8px;
3210 padding-bottom: 8px;
3211 box-sizing: border-box;
3212}
3213
3214.lm-form-group input[type='text'],
3215.lm-form-group input[type='time'],
3216.lm-form-group input[type='date'],
3217.lm-form-group input[type='password'],
3218.lm-form-group input[type='number'],
3219.lm-form-group select,
3220.lm-form-group textarea,
3221.lm-form-group {
3222 width: 100%;
3223}
3224
3225.lm-form-group label {
3226 display: block;
3227 margin-bottom: 4px;
3228}
3229
3230.lm-form-group label.lm-switch {
3231 display: inline-flex;
3232}
3233
3234.lm-f1 {
3235 flex: 1;
3236}
3237
3238.lm-f2 {
3239 flex: 2;
3240}
3241
3242.lm-f3 {
3243 flex: 3;
3244}
3245
3246.lm-f4 {
3247 flex: 4;
3248}
3249
3250.lm-f5 {
3251 flex: 5;
3252}
3253
3254.lm-f6 {
3255 flex: 6;
3256}
3257
3258.lm-f7 {
3259 flex: 7;
3260}
3261
3262.lm-f8 {
3263 flex: 8;
3264}
3265
3266.lm-p0 {
3267 padding: 0;
3268}
3269
3270.lm-p2 {
3271 padding: 2px;
3272}
3273
3274.lm-p4 {
3275 padding: 4px;
3276}
3277
3278.lm-p6 {
3279 padding: 6px;
3280}
3281
3282.lm-p8 {
3283 padding: 8px;
3284}
3285
3286.lm-p10 {
3287 padding: 10px;
3288}
3289
3290.lm-p15 {
3291 padding: 15px;
3292}
3293
3294.lm-p20 {
3295 padding: 20px;
3296}
3297
3298.lm-p25 {
3299 padding: 25px;
3300}
3301
3302.lm-p30 {
3303 padding: 30px;
3304}
3305
3306.lm-application .lm-button,
3307.lm-button {
3308 padding: var(--lm-input-padding) 20px;
3309 border-radius: 2px;
3310 cursor: pointer;
3311 outline: none;
3312
3313 background-color: var(--lm-secondary-color, #737373);
3314 border: 1px solid transparent;
3315 color: #fff;
3316}
3317
3318.lm-application .lm-button.red,
3319.lm-button.red {
3320 background-color: #a23131;
3321 border: 1px solid transparent;
3322 color: #fff;
3323}
3324
3325.lm-application .lm-button.blue,
3326.lm-button.blue {
3327 border: 1px solid transparent;
3328 color: #fff;
3329 background-color: #1a73e8;
3330}
3331
3332.lm-ripple {
3333 background-position: center;
3334 transition: background 0.8s;
3335}
3336
3337.lm-ripple:hover {
3338 background: var(--lm-background-color-highlight, #ebebeb) radial-gradient(circle, transparent 1%, var(--lm-background-color-highlight, #ebebeb) 1%) center/15000%;
3339}
3340
3341.lm-ripple:active {
3342 background-color: var(--lm-background-color-active, #e8e8e8);
3343 background-size: 100%;
3344 transition: background 0s;
3345}
3346
3347.lm-cursor {
3348 cursor: pointer;
3349}
3350
3351.lm-center {
3352 text-align: center;
3353}
3354
3355.lm-loading::before {
3356 content: '';
3357 position: fixed;
3358 top: 0;
3359 left: 0;
3360 right: 0;
3361 height: 3px;
3362 z-index: 9999;
3363 animation: lm-loading 2s linear infinite;
3364 background: #e0e0e0 repeating-linear-gradient(to right, var(--lm-main-color-highlight, #66b244), var(--lm-main-color-highlight, #66b244) 50%, #e0e0e0 50%, #e0e0e0);
3365 background-size: 200% 100%;
3366}
3367
3368.lm-icon {
3369 font-family: "Material Symbols Outlined", "Material Icons", "FontAwesome";
3370 font-size: 24px;
3371 width: 24px;
3372 height: 24px;
3373 line-height: 24px;
3374 font-style: normal;
3375}
3376
3377@keyframes lm-loading {
3378 from {
3379 background-position: 100% 0;
3380 }
3381 to {
3382 background-position: 0 0;
3383 }
3384}
3385
3386/** Dark mode */
3387
3388body.lm-dark-mode {
3389 background-color: var(--lm-background-color);
3390}
3391
3392.lm-dark-mode a {
3393 color: white;
3394}
3395
3396.lm-dark-mode .lm-button {
3397 background-color: #555;
3398 border: 1px solid transparent;
3399 color: white;
3400}
3401
3402@media (min-width: 320px) {
3403 .lm-container {
3404 padding: 0 2% 0 2%;
3405 }
3406}
3407
3408@media (min-width: 1200px) {
3409 .lm-container {
3410 padding: 0 5% 0 5%;
3411 }
3412}
3413
3414@media (max-width: 720px) {
3415 .lm-row {
3416 flex-wrap: wrap;
3417 }
3418
3419 .lm-column {
3420 min-width: 100%;
3421 }
3422
3423 .lm-column .lm-form-group {
3424 padding: 0;
3425 }
3426
3427 ::placeholder {
3428 text-transform: uppercase;
3429 }
3430
3431 ::-webkit-input-placeholder {
3432 text-transform: uppercase;
3433 }
3434
3435 :-moz-placeholder {
3436 text-transform: uppercase;
3437 }
3438
3439 :-ms-input-placeholder {
3440 text-transform: uppercase;
3441 }
3442}
3443
3444.lm-calendar {
3445 user-select: none;
3446 -moz-user-select: none;
3447 -webkit-user-drag: none;
3448 -webkit-touch-callout: none;
3449 -webkit-user-select: none;
3450 -ms-user-select: none;
3451 position: relative;
3452}
3453
3454.lm-calendar[data-disabled] .lm-calendar-container[data-view="days"] .lm-calendar-content,
3455.lm-calendar[data-disabled] .lm-calendar-footer {
3456 opacity: 0.5;
3457 pointer-events: none;
3458}
3459
3460.lm-calendar button {
3461 cursor: pointer;
3462}
3463
3464.lm-calendar .lm-modal {
3465 min-width: initial;
3466 min-height: initial;
3467}
3468
3469.lm-calendar-options {
3470 display: none;
3471}
3472
3473.lm-modal > div > .lm-calendar-options {
3474 display: flex;
3475 justify-content: space-between;
3476 border-bottom: 1px solid var(--lm-border-color, #ccc);
3477}
3478
3479.lm-modal > div > .lm-calendar-options button {
3480 border: 0;
3481 background-color: transparent;
3482 text-transform: uppercase;
3483 cursor: pointer;
3484 padding: 15px;
3485 font-weight: bold;
3486}
3487
3488.lm-calendar-header {
3489 display: flex;
3490 flex-direction: column;
3491}
3492
3493.lm-calendar-header > div:first-child {
3494 display: flex;
3495 align-items: center;
3496 padding: 10px;
3497 flex: 1;
3498 user-select: none;
3499}
3500
3501.lm-calendar-header .lm-calendar-labels {
3502 display: flex;
3503 flex: 1;
3504 cursor: pointer;
3505 padding: 5px;
3506 margin: 10px 0;
3507}
3508
3509.lm-calendar-header .lm-calendar-labels > button {
3510 font-size: 1.2em;
3511 border: 0;
3512 padding: 4px;
3513 background-color: transparent;
3514 font-weight: bold;
3515 color: var(--lm-font-color);
3516}
3517
3518.lm-calendar-navigation {
3519 display: grid;
3520 grid-template-columns: repeat(2, 1fr);
3521 gap: 1px;
3522}
3523
3524.lm-calendar-weekdays {
3525 display: none;
3526 grid-template-columns: repeat(7, 1fr);
3527 padding: 0 8px 0 8px;
3528 font-size: 0.8em;
3529 align-items: center;
3530 justify-content: center;
3531}
3532
3533.lm-calendar-container[data-view="days"] .lm-calendar-weekdays {
3534 display: grid;
3535 flex: 1;
3536}
3537
3538.lm-calendar-weekdays > div {
3539 display: inline-block;
3540 padding: 6px;
3541 box-sizing: border-box;
3542 text-align: center;
3543 font-weight: bold;
3544 line-height: 2em;
3545 justify-content: center;
3546}
3547
3548.lm-calendar-content {
3549 display: grid;
3550 grid-template-columns: repeat(7, 1fr);
3551 padding: 8px;
3552 font-size: 0.8em;
3553 outline: none;
3554}
3555
3556.lm-calendar-content > div {
3557 box-sizing: border-box;
3558 text-align: center;
3559 aspect-ratio: 1 / 1;
3560 display: flex;
3561 flex-direction: column;
3562 justify-content: center;
3563 align-items: center;
3564 padding: 6px;
3565 cursor: pointer;
3566 border-radius: 100px;
3567 background-origin: padding-box;
3568 min-width: 38px;
3569}
3570
3571.lm-calendar-content > div[data-disabled="true"] {
3572 pointer-events: none;
3573 opacity: 0.3;
3574}
3575
3576.lm-calendar-container[data-view="months"] .lm-calendar-content {
3577 grid-template-columns: repeat(4, 1fr);
3578}
3579
3580.lm-calendar-container[data-view="years"] .lm-calendar-content {
3581 grid-template-columns: repeat(4, 1fr);
3582}
3583
3584.lm-calendar-content > div[data-grey="true"] {
3585 color: #ccc;
3586}
3587
3588.lm-calendar-content > div[data-bold="true"] {
3589 font-weight: bold;
3590}
3591
3592.lm-calendar-content > div[data-event="true"]::before {
3593 content: '';
3594 position: absolute;
3595 margin-top: 22px;
3596 width: 3px;
3597 height: 3px;
3598 border-radius: 3px;
3599 background-color: red;
3600}
3601
3602.lm-calendar-content > div[data-selected="true"] {
3603 font-weight: bold;
3604 background-color: #eee;
3605 color: #000;
3606}
3607
3608.lm-calendar-content:focus > div[data-selected="true"] {
3609 outline: 2px solid black;
3610 outline-offset: -2px;
3611}
3612
3613.lm-calendar-content > div:hover {
3614 background-color: #eee;
3615 color: #000;
3616}
3617
3618.lm-calendar-content > div[data-range="true"] {
3619 position: relative;
3620}
3621
3622.lm-calendar-content > div[data-start="true"],
3623.lm-calendar-content > div[data-end="true"] {
3624 background-color: var(--lm-main-color, #2196f3);
3625 color: initial;
3626}
3627
3628.lm-calendar-content > div[data-range="true"]::before {
3629 content: "";
3630 position: absolute;
3631 left: 0;
3632 right: 0;
3633 top: calc(25%);
3634 height: 50%;
3635 background-color: var(--lm-main-color-alpha, #2196f388);
3636}
3637
3638.lm-calendar-content > div[data-start="true"]::before {
3639 left: 5px;
3640 border-top-left-radius: 20%;
3641 border-bottom-left-radius: 20%;
3642}
3643
3644.lm-calendar-content > div[data-end="true"]::before,
3645.lm-calendar-content > div[data-last="true"]::before {
3646 right: 5px;
3647 border-top-right-radius: 20%;
3648 border-bottom-right-radius: 20%;
3649}
3650
3651.lm-calendar-footer > div {
3652 flex: 1;
3653}
3654
3655.lm-calendar-footer {
3656 display: flex;
3657 margin: 0 10px 0 10px;
3658 padding: 8px 0 8px 0;
3659 line-height: 34px;
3660 border-top: 1px solid var(--lm-border-color-light, #e9e9e9);
3661}
3662
3663.lm-calendar-footer[data-visible="false"] {
3664 display: none;
3665}
3666
3667.lm-calendar-footer .lm-calendar-control {
3668 border: 0;
3669 background-color: transparent;
3670 padding: 6px;
3671 -moz-appearance: none;
3672 -webkit-appearance: none;
3673 margin: 2px;
3674 border-radius: 32px;
3675 font-size: 1.1em;
3676 width: initial;
3677}
3678
3679.lm-calendar-footer select:focus {
3680 background-color: #eee;
3681}
3682
3683.lm-calendar-footer input {
3684 width: 100%;
3685 cursor: pointer;
3686 background-color: var(--lm-border-color-light, #e9e9e9);
3687}
3688
3689.lm-calendar-input {
3690 padding-right: 24px !important;
3691 box-sizing: border-box;
3692 background: url("data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24\" viewBox=\"0 -960 960 960\" width=\"24\"><path d=\"M200-80q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v560q0 33-23.5 56.5T760-80H200Zm0-80h560v-400H200v400Zm0-480h560v-80H200v80Zm0 0v-80 80Zm280 240q-17 0-28.5-11.5T440-440q0-17 11.5-28.5T480-480q17 0 28.5 11.5T520-440q0 17-11.5 28.5T480-400Zm-160 0q-17 0-28.5-11.5T280-440q0-17 11.5-28.5T320-480q17 0 28.5 11.5T360-440q0 17-11.5 28.5T320-400Zm320 0q-17 0-28.5-11.5T600-440q0-17 11.5-28.5T640-480q17 0 28.5 11.5T680-440q0 17-11.5 28.5T640-400ZM480-240q-17 0-28.5-11.5T440-280q0-17 11.5-28.5T480-320q17 0 28.5 11.5T520-280q0 17-11.5 28.5T480-240Zm-160 0q-17 0-28.5-11.5T280-280q0-17 11.5-28.5T320-320q17 0 28.5 11.5T360-280q0 17-11.5 28.5T320-240Zm320 0q-17 0-28.5-11.5T600-280q0-17 11.5-28.5T640-320q17 0 28.5 11.5T680-280q0 17-11.5 28.5T640-240Z\" fill=\"gray\" /></svg>") top 50% right 5px no-repeat;
3693}
3694
3695.lm-calendar-time[data-visible="false"] {
3696 display: none;
3697}
3698
3699.lm-calendar .lm-calendar-icon {
3700 font-family: "Material Symbols Outlined", "Material Icons", "FontAwesome";
3701 font-size: 24px;
3702 width: 40px;
3703 height: 40px;
3704 line-height: 24px;
3705 box-sizing: border-box;
3706 border-radius: 20px;
3707 border: 0;
3708 padding: 0;
3709 margin: 0;
3710}
3711
3712.lm-calendar[data-type="picker"] .lm-modal {
3713 position: fixed;
3714 left: 0;
3715 bottom: 0;
3716 min-width: 100%;
3717 min-height: 40px;
3718}
3719
3720.lm-calendar[data-type="picker"] .lm-calendar-content > div {
3721 aspect-ratio: initial;
3722 min-height: 60px;
3723 border-radius: 4px;
3724}
3725
3726.lm-calendar[data-type="picker"] .lm-calendar-weekdays > div {
3727 min-height: 60px;
3728 line-height: 60px;
3729}
3730
3731
3732/** Calendar with grid lines */
3733
3734.lm-calendar[data-grid="true"] .lm-calendar-weekdays {
3735 padding: 0;
3736}
3737
3738.lm-calendar[data-grid="true"] .lm-calendar-content {
3739 border-top: 1px solid transparent;
3740 border-left: 1px solid transparent;
3741 border-right: 1px solid #ccc;
3742 border-bottom: 1px solid #ccc;
3743 padding: 0;
3744}
3745
3746.lm-calendar[data-grid="true"] .lm-calendar-content > div {
3747 border-top: 1px solid #ccc;
3748 border-left: 1px solid #ccc;
3749 border-right: 1px solid transparent;
3750 border-bottom: 1px solid transparent;
3751 border-radius: 0;
3752 justify-content: start;
3753 align-items: end;
3754}
3755
3756/** Other */
3757
3758.lm-ripple {
3759 background-position: center;
3760 transition: background 0.8s;
3761}
3762
3763.lm-ripple:hover {
3764 background: var(--lm-background-color-highlight, #ebebeb) radial-gradient(circle, transparent 1%, var(--lm-background-color-highlight, #ebebeb) 1%) center/15000%;
3765}
3766
3767.lm-ripple:active {
3768 background-color: var(--lm-background-color-active, #e8e8e8);
3769 background-size: 100%;
3770 transition: background 0s;
3771}
3772
3773/** Dark mode */
3774
3775.lm-dark-mode .lm-calendar-weekdays {
3776 color: #aaa;
3777}
3778
3779.lm-dark-mode .lm-calendar-labels > button {
3780 background-color: initial;
3781}
3782
3783.lm-dark-mode .lm-calendar-content:focus > div[data-selected="true"] {
3784 outline-color: white;
3785}
3786
3787.lm-dark-mode .lm-calendar-content > div[data-grey="true"] {
3788 color: var(--lm-font-grayout, #777);
3789}
3790
3791.lm-dark-mode .lm-calendar-footer select:focus {
3792 background-color: #3a3a45;
3793}
3794
3795.lm-color {
3796 background-color: #fff;
3797 line-height: initial;
3798 box-sizing: border-box;
3799 position: relative;
3800}
3801
3802.lm-color-options {
3803 display: none;
3804}
3805
3806.lm-modal > div > .lm-color-options {
3807 display: flex;
3808 justify-content: space-between;
3809 border-bottom: 1px solid var(--lm-border-color, #ccc);
3810}
3811
3812.lm-modal > div > .lm-color-options button {
3813 border: 0;
3814 background-color: transparent;
3815 text-transform: uppercase;
3816 cursor: pointer;
3817 padding: 15px;
3818 font-weight: bold;
3819}
3820
3821.lm-color-grid {
3822 width: 100%;
3823 height: 100%;
3824}
3825
3826.lm-color-grid table {
3827 width: 100%;
3828 height: 100%;
3829}
3830
3831.lm-color-grid tr:first-child>td:first-child {
3832 border-top-left-radius: 3px;
3833}
3834
3835.lm-color-grid tr:first-child>td:last-child {
3836 border-top-right-radius: 3px;
3837}
3838
3839.lm-color-grid tr:last-child>td:first-child {
3840 border-bottom-left-radius: 3px;
3841}
3842
3843.lm-color-grid tr:last-child>td:last-child {
3844 border-bottom-right-radius: 3px;
3845}
3846
3847.lm-color-selected {
3848 background-repeat: no-repeat;
3849 background-size: 16px;
3850 background-position: center;
3851 background-image: url("data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath d=%27M0 0h24v24H0z%27 fill=%27none%27/%3E%3Cpath d=%27M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z%27 fill=%27black%27/%3E%3C/svg%3E");
3852}
3853
3854.lm-color-hsl {
3855 width: 100%;
3856 height: 100%;
3857 box-sizing: border-box;
3858 position: relative;
3859 display: inline-block;
3860}
3861
3862.lm-color-hsl canvas {
3863 position: absolute;
3864 top: 0;
3865 left: 0;
3866 display: block;
3867 border-radius: 3px;
3868 -webkit-user-drag: none;
3869}
3870
3871.lm-color-point {
3872 height: 4px;
3873 width: 4px;
3874 background-color: #000;
3875 position: absolute;
3876 top: 50%;
3877 left: 50%;
3878 transform: translate(-50%, -50%);
3879 border-radius: 50%;
3880 outline: 1px solid white;
3881}
3882
3883.lm-color-input {
3884 padding-right: 24px !important;
3885 box-sizing: border-box;
3886 background: url("data:image/svg+xml,<svg xmlns=\"http://www.w3.org/2000/svg\" enable-background=\"new 0 0 24 24\" height=\"24px\" viewBox=\"0 0 24 24\" width=\"24px\" fill=\"gray\"><g><rect fill=\"none\" height=\"24\" width=\"24\"/></g><g><g><g><g><path d=\"M12,22C6.49,22,2,17.51,2,12S6.49,2,12,2s10,4.04,10,9c0,3.31-2.69,6-6,6h-1.77c-0.28,0-0.5,0.22-0.5,0.5 c0,0.12,0.05,0.23,0.13,0.33c0.41,0.47,0.64,1.06,0.64,1.67C14.5,20.88,13.38,22,12,22z M12,4c-4.41,0-8,3.59-8,8s3.59,8,8,8 c0.28,0,0.5-0.22,0.5-0.5c0-0.16-0.08-0.28-0.14-0.35c-0.41-0.46-0.63-1.05-0.63-1.65c0-1.38,1.12-2.5,2.5-2.5H16 c2.21,0,4-1.79,4-4C20,7.14,16.41,4,12,4z\"/><circle cx=\"6.5\" cy=\"11.5\" r=\"1.5\"/><circle cx=\"9.5\" cy=\"7.5\" r=\"1.5\"/><circle cx=\"14.5\" cy=\"7.5\" r=\"1.5\"/><circle cx=\"17.5\" cy=\"11.5\" r=\"1.5\"/></g></g></g></g></svg>") top 50% right 1px no-repeat;
3887}
3888
3889.lm-color .lm-modal {
3890 min-width: initial;
3891 min-height: initial;
3892}
3893
3894.lm-color .lm-tabs {
3895 flex-grow: 1;
3896 display: inline-flex;
3897 flex-direction: column;
3898 margin-top: 10px;
3899 min-width: 260px;
3900 min-height: 190px;
3901}
3902
3903.lm-color .lm-tabs-content {
3904 display: flex;
3905 flex-grow: 1;
3906 margin-top: 4px;
3907}
3908
3909.lm-color .lm-tabs .lm-tabs-content > div {
3910 flex-grow: 1;
3911 padding: 10px;
3912}
3913.lm-menu {
3914 display: none;
3915}
3916
3917.lm-menu-focus {
3918 display: unset;
3919}
3920
3921.lm-menu .lm-modal {
3922 color: #555;
3923 user-select: none;
3924 border: 1px solid var(--lm-border-color-light, #e9e9e9);
3925 border-radius: 4px;
3926 box-shadow: 0 2px 4px 2px rgba(60,64,67,.2);
3927 max-height: 600px;
3928 width: initial;
3929 height: initial;
3930 min-width: 250px;
3931 min-height: initial;
3932 padding-top: 4px;
3933 padding-bottom: 4px;
3934 z-index: 16;
3935 transition: initial;
3936}
3937
3938.lm-menu-submenu {
3939 padding-top: 1px;
3940 padding-bottom: 1px;
3941}
3942
3943.lm-menu-submenu > div.lm-menu-item {
3944 box-sizing: border-box;
3945 display: flex;
3946 padding: 1px 8px 1px 40px;
3947 width: 250px;
3948 font-size: 0.9em;
3949 font-family:sans-serif;
3950 text-align: left;
3951 align-items: center;
3952 position: relative;
3953}
3954
3955.lm-menu-submenu > div.lm-menu-item span {
3956 text-decoration: none;
3957 flex: 1;
3958 cursor: pointer;
3959 line-height: 30px;
3960}
3961
3962.lm-menu-submenu > div.lm-menu-item div {
3963 margin-right: 5px;
3964 color: #888;
3965}
3966
3967.lm-menu-submenu > div.lm-menu-item[data-submenu="true"]::after {
3968 content: 'arrow_right';
3969 font-family: "Material Symbols Outlined", "Material Icons", "FontAwesome";
3970 font-size: 18px;
3971 color: var(--lm-icon-color, #777);
3972}
3973
3974.lm-menu-submenu > div.lm-menu-item[data-disabled="true"] {
3975 opacity: 0.5;
3976 pointer-events: none;
3977}
3978
3979.lm-menu-submenu > div.lm-menu-item:hover,
3980.lm-menu-submenu > div.lm-menu-item[data-cursor="true"],
3981.lm-menu-submenu > div.lm-menu-item[aria-expanded="true"] {
3982 background-color: var(--lm-background-color-highlight, #ebebeb);
3983}
3984
3985.lm-menu-submenu hr {
3986 border: 1px solid var(--lm-border-color-light, #e9e9e9);
3987 border-bottom: 0;
3988 margin-top: 5px;
3989 margin-bottom: 5px;
3990}
3991
3992.lm-menu-submenu > div.lm-menu-item::before {
3993 content: attr(data-icon);
3994 font-family: "Material Symbols Outlined", "Material Icons", "FontAwesome";
3995 font-size: 18px;
3996 width: 24px;
3997 height: 24px;
3998 line-height: 24px;
3999 position: absolute;
4000 left: 11px;
4001 transform: rotate(0.03deg);
4002}
4003
4004.lm-dark-mode .lm-menu .lm-modal {
4005 color: #e8e7e9;
4006 background-color: #111;
4007 border: 1px solid #3c3c3c;
4008}
4009
4010.lm-dark-mode .lm-menu-submenu > div.lm-menu-item:hover,
4011.lm-dark-mode .lm-menu-submenu > div.lm-menu-item[data-cursor="true"],
4012.lm-dark-mode .lm-menu-submenu > div.lm-menu-item[aria-expanded="true"] {
4013 background-color: var(--lm-background-color-highlight, #2d2d2d);
4014}
4015
4016.lm-dropdown {
4017 user-select: none;
4018 cursor: pointer;
4019 box-sizing: border-box;
4020 outline-offset: 1px;
4021 vertical-align: top;
4022}
4023
4024.lm-dropdown[data-disabled="true"] {
4025 opacity: 0.5;
4026 pointer-events: none;
4027}
4028
4029.lm-dropdown-header {
4030 display: flex;
4031 align-items: center;
4032}
4033
4034.lm-dropdown-header-controls {
4035 display: none;
4036}
4037
4038.lm-application .lm-dropdown-header-controls button,
4039.lm-dropdown-header-controls button {
4040 background-color: transparent;
4041 text-transform: uppercase;
4042 cursor: pointer;
4043 padding: 15px;
4044 font-weight: bold;
4045 border: 0;
4046 color: var(--lm-font-color);
4047 margin: 1px;
4048}
4049
4050.lm-dropdown-content {
4051 position: relative;
4052 margin-top: 1px;
4053}
4054
4055.lm-dropdown .lm-modal {
4056 padding: 0;
4057 min-width: 100%;
4058 min-height: 5px;
4059 border: 1px solid var(--lm-border-color, #ccc);
4060 border-radius: 0;
4061}
4062
4063.lm-dropdown-input {
4064 padding: var(--lm-input-padding, 6px) 24px var(--lm-input-padding, 6px) 10px;
4065 white-space: nowrap;
4066 overflow: hidden;
4067 text-overflow: ellipsis;
4068 appearance: none;
4069 cursor: pointer;
4070 box-sizing: border-box;
4071 width: 100%;
4072 background: var(--lm-background-color-input, #fff);
4073 border: 1px solid var(--lm-border-color, #767676);
4074 border-radius: var(--lm-border-radius, 2px);
4075 position: relative;
4076 line-height: normal;
4077 display: flex;
4078 align-items: center;
4079 font: inherit;
4080}
4081
4082.lm-dropdown-input > br {
4083 display: none;
4084}
4085
4086.lm-dropdown-input::after {
4087 content: '';
4088 position: absolute;
4089 width: 24px;
4090 height: 24px;
4091 top: calc(50% - 12px);
4092 right: 0;
4093 background-repeat: no-repeat;
4094 background-image: url("data:image/svg+xml,%0A%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 width=%2724%27 height=%2724%27 viewBox=%270 0 24 24%27%3E%3Cpath fill=%27none%27 d=%27M0 0h24v24H0V0z%27/%3E%3Cpath d=%27M7 10l5 5 5-5H7z%27 fill=%27gray%27/%3E%3C/svg%3E");
4095 background-position: center;
4096 transition: transform .1s ease-in-out;
4097}
4098
4099.lm-application .lm-dropdown-add,
4100.lm-dropdown-add {
4101 position: absolute;
4102 padding: 0;
4103 margin: 0;
4104 border: 0;
4105 background: transparent;
4106 cursor: pointer;
4107 right: 30px;
4108 top: calc(50% - 8px);
4109 display: none;
4110}
4111
4112.lm-dropdown-add::after {
4113 content: '+';
4114 width: 16px;
4115 height: auto;
4116 display: block;
4117 color: var(--lm-font-color);
4118}
4119
4120.lm-dropdown[data-insert="true"] .lm-dropdown-input {
4121 padding-right: 35px;
4122}
4123
4124.lm-dropdown[data-state="true"][data-insert="true"] .lm-dropdown-add {
4125 display: initial;
4126}
4127
4128.lm-dropdown[data-state="true"] .lm-dropdown-input::after {
4129 transform: rotate(-180deg);
4130}
4131
4132.lm-dropdown-input:empty::before {
4133 content: "\00a0";
4134}
4135
4136.lm-dropdown[data-state="true"] .lm-dropdown-input[placeholder]:empty::before {
4137 content: "\00a0" attr(placeholder);
4138 color: #aaa;
4139}
4140
4141.lm-dropdown-options {
4142 width: 100%;
4143}
4144
4145.lm-dropdown-item {
4146 box-sizing: border-box;
4147}
4148
4149.lm-dropdown-item[data-disabled="true"] {
4150 opacity: 0.5;
4151 pointer-events: none;
4152}
4153
4154.lm-dropdown-item[data-group]::before {
4155 content: attr(data-group);
4156 display: block;
4157 padding: 8px;
4158 font-weight: bold;
4159 width: 100%;
4160 background-color: var(--lm-background-color-input, #fff);
4161 color: var(--lm-font-color, #000);
4162 box-sizing: border-box;
4163}
4164
4165.lm-dropdown-item > div {
4166 white-space: nowrap;
4167 text-align: left;
4168 text-overflow: ellipsis;
4169 overflow: hidden;
4170 color: var(--lm-font-color, #000);
4171 display: flex;
4172 align-items: center;
4173 padding: 4px 40px 4px 10px;
4174 position: relative;
4175 box-sizing: border-box;
4176}
4177
4178.lm-dropdown-item > div > span:empty::before {
4179 content: "\00a0";
4180}
4181
4182.lm-dropdown-item > div > img {
4183 width: 24px;
4184 height: 24px;
4185 margin-left: -6px;
4186 margin-right: 6px;
4187}
4188
4189.lm-dropdown-item > div > img:not([src]) {
4190 display: none;
4191}
4192
4193.lm-dropdown-item > div > img[src=""] {
4194 display: none;
4195}
4196
4197.lm-dropdown-item > div:hover {
4198 background-color: #1e90ff;
4199 color: white;
4200}
4201
4202.lm-dropdown-item[data-selected="true"] > div {
4203 background-color: #1e90ff;
4204 color: white;
4205}
4206
4207.lm-dropdown-item[data-selected="true"] > div::after {
4208 content: '✓';
4209 position: absolute;
4210 right: 10px;
4211 line-height: 24px;
4212}
4213
4214.lm-dropdown-item[data-cursor="true"] > div {
4215 background-color: var(--lm-background-color-highlight);
4216}
4217
4218.lm-dropdown-item[data-cursor="true"]:hover > div {
4219 background-color: var(--lm-background-color-active);
4220}
4221
4222.lm-dropdown-item[data-cursor="true"].lm-dropdown-item[data-selected="true"] > div {
4223 background-color: #1d86ed;
4224}
4225
4226/** Picker */
4227
4228.lm-dropdown[data-type="picker"][data-state="true"] .lm-dropdown-content .lm-modal {
4229 box-shadow: initial;
4230 border: initial;
4231}
4232
4233.lm-dropdown[data-type="picker"][data-state="true"] .lm-dropdown-content {
4234 position: initial;
4235}
4236
4237.lm-dropdown[data-type="picker"][data-state="true"] .lm-dropdown-header-controls {
4238 display: flex;
4239 position: fixed;
4240 bottom: 300px;
4241 left: 0;
4242 width: 100% !important;
4243 background-color: #fff;
4244 z-index: 1;
4245 box-sizing: border-box;
4246 border-top: 1px solid var(--lm-border-color);
4247 border-bottom: 1px solid var(--lm-border-color);
4248 box-shadow: 0 0 12px rgb(0 0 0 / 22%);
4249 justify-content: space-between;
4250}
4251
4252.lm-dropdown[data-type="picker"] .lm-modal {
4253 position: fixed;
4254 bottom: 0;
4255 left: 0;
4256 width: 100% !important;
4257 height: 300px !important;
4258}
4259
4260.lm-dropdown[data-type="picker"] .lm-lazy {
4261 width: 100% !important;
4262}
4263
4264.lm-dropdown[data-type="picker"] .lm-dropdown-item > div {
4265 border-bottom: solid 1px rgba(0, 0, 0, 0.2);
4266 text-transform: uppercase;
4267 font-size: 1.1em;
4268 padding: 16px;
4269}
4270
4271.lm-dropdown[data-type="picker"] .lm-dropdown-item[data-group]::before {
4272 text-align: center;
4273 border-bottom: solid 1px rgba(0, 0, 0, 0.2);
4274 padding: 16px;
4275}
4276
4277/** Searchbar */
4278
4279.lm-dropdown[data-type="searchbar"][data-state="true"] {
4280 position: fixed;
4281 top: 0;
4282 left: 0;
4283 width: 100% !important;
4284 height: 100% !important;
4285 display: flex;
4286 flex-direction: column;
4287 background-color: #fff;
4288 z-index: 1;
4289 box-sizing: border-box;
4290}
4291
4292.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-content .lm-modal {
4293 box-shadow: initial;
4294 border: initial;
4295 border-top: 1px solid var(--lm-border-color);
4296}
4297
4298.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-content {
4299 position: initial;
4300}
4301
4302.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-header {
4303 display: flex;
4304 background-color: #fff;
4305 box-sizing: border-box;
4306}
4307
4308.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-header-controls {
4309 display: flex;
4310}
4311
4312.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-input {
4313 font-size: 1.5em;
4314 border-radius: 0;
4315 border: 0;
4316 border-bottom: 1px solid #eee;
4317 outline: none;
4318 background-color: #fff;
4319 padding-top: 0;
4320 padding-bottom: 0;
4321 line-height: 60px;
4322 height: 60px;
4323 flex: 1;
4324}
4325
4326.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-input::after {
4327 background: initial;
4328}
4329
4330.lm-dropdown[data-type="searchbar"][data-state="true"] .lm-dropdown-add {
4331 right: 150px;
4332}
4333
4334.lm-dropdown[data-type="searchbar"][data-state="true"]:not(.lm-dropdown-loading) .lm-dropdown-add::after {
4335 content: 'add';
4336 font-family: "Material Symbols Outlined", "Material Icons";
4337 font-size: 24px;
4338 width: 24px;
4339 height: 24px;
4340}
4341
4342.lm-dropdown[data-type="searchbar"] .lm-modal {
4343 max-height: initial;
4344 bottom: 0;
4345 width: 100% !important;
4346 height: calc(100% - 60px) !important;
4347 border: 0;
4348}
4349
4350.lm-dropdown[data-type="searchbar"] .lm-dropdown-item > div {
4351 border-bottom: solid 1px rgba(0, 0, 0, 0.2);
4352 text-transform: uppercase;
4353 font-size: 1.1em;
4354 padding: 16px;
4355}
4356
4357.lm-dropdown[data-type="searchbar"] .lm-dropdown-item[data-group]::before {
4358 text-align: center;
4359 border-bottom: solid 1px rgba(0, 0, 0, 0.2);
4360 padding: 16px;
4361}
4362
4363.lm-dropdown[data-type="searchbar"] .lm-lazy {
4364 max-height: initial;
4365 width: 100% !important;
4366}
4367
4368
4369
4370
4371
4372.lm-dropdown .lm-lazy {
4373 max-height: 300px;
4374 scrollbar-width: thin;
4375}
4376
4377.lm-dropdown .lm-lazy::-webkit-scrollbar {
4378 height: 12px;
4379}
4380
4381.lm-dropdown .lm-lazy::-webkit-scrollbar {
4382 width: 12px;
4383}
4384
4385.lm-dropdown .lm-dropdown-loading::after {
4386 position: absolute;
4387 content: '';
4388 width: 12px;
4389 height: 12px;
4390 margin: 5px;
4391 border-style: solid;
4392 border-color: #888;
4393 border-top-color: transparent;
4394 border-width: 1px;
4395 border-radius: 50%;
4396 background-image: none;
4397 animation: lm-dropdown-spin .8s linear infinite;
4398}
4399
4400@keyframes lm-dropdown-spin {
4401 from {
4402 transform: rotate(0deg);
4403 }
4404 to {
4405 transform: rotate(360deg);
4406 }
4407}
4408
4409/** Lazyloading */
4410
4411.lm-lazy {
4412 position: relative;
4413 overflow-y: auto;
4414 overflow-x: hidden;
4415 display: flex;
4416 box-sizing: border-box;
4417 height: 100%;
4418}
4419
4420.lm-lazy-scroll {
4421 position: absolute;
4422 width: 1px;
4423}
4424
4425.lm-lazy-items {
4426 position: sticky;
4427 top: 0;
4428 box-sizing: border-box;
4429 width: 100%;
4430}
4431.lm-modal {
4432 position: fixed;
4433 min-width: 200px;
4434 min-height: 200px;
4435 border-radius: 5px;
4436 z-index: 15;
4437 background-color: var(--lm-background-color-input, #fff);
4438 box-sizing: border-box;
4439 box-shadow: 0 0 12px rgb(0 0 0 / 22%);
4440 opacity: 1;
4441 border: 1px solid var(--lm-border-color, #ccc);
4442 outline: none;
4443 margin: 0;
4444 display: flex;
4445 flex-direction: column;
4446 transition: opacity 0.4s ease, top 0.4s ease, left 0.4s ease, width 0.4s ease, height 0.4s ease;
4447 color: var(--lm-font-color, #000);
4448}
4449
4450.lm-modal[closed="true"] {
4451 display: none;
4452}
4453
4454.lm-modal.action {
4455 user-select: none;
4456}
4457
4458.lm-modal-title {
4459 width: 100%;
4460 border-bottom: 1px solid var(--lm-border-color, #ccc);
4461 padding: 12px;
4462 box-sizing: border-box;
4463 font-size: 1.3em;
4464 line-height: 24px;
4465 user-select: none;
4466 display: flex;
4467 border-radius: 5px 5px 0 0;
4468}
4469
4470.lm-modal-focus {
4471 z-index: 999;
4472}
4473
4474.lm-modal > .lm-modal-title {
4475 display: none;
4476}
4477
4478.lm-modal > .lm-modal-title[data-icon],
4479.lm-modal > .lm-modal-title[data-title],
4480.lm-modal[closable="true"] > .lm-modal-title,
4481.lm-modal[minimizable="true"] > .lm-modal-title {
4482 display: inherit;
4483}
4484
4485.lm-modal > .lm-modal-title > div:nth-child(2) {
4486 flex: 1;
4487}
4488
4489.lm-modal > .lm-modal-title > .lm-modal-icon {
4490 width: 24px;
4491 height: 24px;
4492 font-size: 24px;
4493 cursor: pointer;
4494 font-family: "Material Symbols Outlined", "Material Icons";
4495 text-align: center;
4496 margin-right: 8px;
4497 display: none;
4498}
4499
4500.lm-modal > .lm-modal-title > .lm-modal-icon:not(:empty) {
4501 display: inherit;
4502}
4503
4504.lm-modal > .lm-modal-title > .lm-modal-close::before {
4505 content: 'close';
4506}
4507
4508.lm-modal > .lm-modal-title > .lm-modal-minimize::before {
4509 content: '\2500';
4510}
4511
4512.lm-modal[minimized="true"] > .lm-modal-title > .lm-modal-minimize::before {
4513 content: '\e5d7';
4514}
4515
4516.lm-modal[minimizable="true"] > .lm-modal-title > .lm-modal-minimize {
4517 display: block;
4518}
4519
4520.lm-modal[closable="true"] > .lm-modal-title > .lm-modal-close {
4521 margin-right: 0;
4522 display: block;
4523}
4524
4525.lm-modal.hide {
4526 opacity: 0;
4527}
4528
4529.lm-modal[animation="false"] {
4530 transition: initial;
4531}
4532
4533.lm-modal.action {
4534 transition: initial;
4535}
4536
4537.lm-modal-backdrop {
4538 position: fixed;
4539 top: 0;
4540 left: 0;
4541 width: 100vw;
4542 height: 100vh;
4543 background-color: #00000020;
4544 z-index: 15;
4545}
4546
4547.lm-modal > div:last-child {
4548 width: 100%;
4549 height: 100%;
4550}
4551
4552.lm-modal[overflow="true"] > div:last-child {
4553 overflow: auto;
4554 scrollbar-width: thin;
4555 scrollbar-color: #333 transparent;
4556}
4557
4558.lm-modal > div:last-child::-webkit-scrollbar {
4559 width: 12px;
4560 height: 12px;
4561}
4562
4563.lm-modal > div:last-child::-webkit-scrollbar-track {
4564 background: #eee;
4565}
4566
4567.lm-modal > div:last-child::-webkit-scrollbar-thumb {
4568 background: #888;
4569}
4570
4571.lm-modal[position="absolute"] {
4572 position: absolute;
4573 transition: initial;
4574}
4575
4576.lm-modal[position="left"] {
4577 top: 0;
4578 left: 0;
4579 width: 280px;
4580 height: 100vh !important;
4581 border-width: 0;
4582 border-radius: initial;
4583}
4584
4585.lm-modal[position="right"] {
4586 top: 0;
4587 left: auto;
4588 right: 0;
4589 width: 280px;
4590 height: 100vh !important;
4591 border-width: 0;
4592 border-radius: initial;
4593}
4594
4595.lm-modal[position="bottom"] {
4596 top: initial;
4597 left: 0;
4598 bottom: 0;
4599 width: 100vw !important;
4600 height: 280px;
4601 border-width: 0;
4602 border-radius: initial;
4603}
4604
4605.lm-modal[minimized="true"] {
4606 position: fixed;
4607 width: 200px !important;
4608 height: 45px !important;
4609 min-width: initial;
4610 min-height: initial;
4611 overflow: hidden;
4612}
4613
4614.lm-rating i {
4615 color: lightgray;
4616 cursor: pointer;
4617 user-select: none;
4618 -webkit-user-drag: none;
4619}
4620
4621.lm-rating[data-size="small"] {
4622 height: 16px;
4623 line-height: 16px;
4624 font-size: 16px;
4625}
4626
4627.lm-rating[data-size="small"] i {
4628 font-size: 16px;
4629}
4630
4631.lm-rating i[data-hover="1"] {
4632 color: gray;
4633}
4634
4635.lm-rating i[data-selected="1"] {
4636 color: red;
4637}
4638
4639:root {
4640 --lm-switch-front-color: 127,127,127;
4641 --lm-switch-primary-color: 255,255,255;
4642 --lm-switch-main-color: var(--lm-main-color, #1565C0);
4643 --lm-switch-main-color-alpha: var(--lm-main-color-alpha, #1565C088);
4644}
4645
4646.lm-switch[data-color="green"] {
4647 --lm-switch-main-color: #2E7D32;
4648 --lm-switch-main-color-alpha: #2E7D3288;
4649}
4650
4651.lm-switch[data-color="orange"] {
4652 --lm-switch-main-color: #EF6C00;
4653 --lm-switch-main-color-alpha: #EF6C0088;
4654}
4655
4656.lm-switch[data-color="red"] {
4657 --lm-switch-main-color: #C62828;
4658 --lm-switch-main-color-alpha: #C6282888;
4659}
4660
4661.lm-switch[data-color="purple"] {
4662 --lm-switch-main-color: #6A1B9A;
4663 --lm-switch-main-color-alpha: #6A1B9A88;
4664}
4665
4666.lm-switch {
4667 position: relative;
4668 display: inline-flex;
4669 z-index: 0;
4670 align-items: center;
4671 min-width: 36px;
4672 min-height: 20px;
4673 cursor: pointer;
4674 user-select: none;
4675}
4676
4677.lm-switch:before {
4678 content: '';
4679 min-height: 1em;
4680}
4681
4682.lm-switch > input {
4683 appearance: none;
4684 position: absolute;
4685 left: 0;
4686 margin: 0;
4687 display: block;
4688 border-radius: 50%;
4689 width: 30px;
4690 height: 30px;
4691 max-width: 30px;
4692 max-height: 30px;
4693 outline: none;
4694 opacity: 0;
4695 transform: scale(1);
4696 pointer-events: none;
4697 transition: opacity 0.3s 0.1s, transform 0.2s 0.1s;
4698}
4699
4700.lm-switch > span {
4701 display: inline-flex;
4702 width: 100%;
4703 line-height: 24px;
4704 cursor: pointer;
4705 margin: 0 0 0 45px;
4706 align-items: center;
4707 box-sizing: border-box;
4708 max-width: -webkit-fill-available;
4709}
4710
4711.lm-switch > span:empty {
4712 margin: 0;
4713}
4714
4715.lm-switch > span::before {
4716 content: "";
4717 position: absolute;
4718 left: 0;
4719 border-radius: 7px;
4720 width: 36px;
4721 height: 14px;
4722 background-color: rgba(var(--lm-switch-front-color), 0.38);
4723 transition: background-color 0.2s, opacity 0.2s;
4724}
4725
4726.lm-switch > span::after {
4727 content: "";
4728 position: absolute;
4729 left: 0;
4730 border-radius: 50%;
4731 width: 20px;
4732 height: 20px;
4733 background-color: rgb(var(--lm-switch-primary-color));
4734 box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
4735 transition: background-color 0.2s, transform 0.2s;
4736}
4737
4738.lm-switch > input:checked {
4739 left: 11px;
4740 background-color: var(--lm-switch-main-color);
4741}
4742
4743.lm-switch > input:not(:checked) {
4744 left: -5px;
4745 background-color: var(--lm-secondary-color, #6A6A6A);
4746}
4747
4748.lm-switch > input:checked + span::before {
4749 background-color: var(--lm-switch-main-color-alpha);
4750}
4751
4752.lm-switch > input:checked + span::after {
4753 background-color: var(--lm-switch-main-color);
4754 transform: translateX(16px);
4755}
4756
4757/* Hover, Focus */
4758.lm-switch:hover > input {
4759 opacity: 0.04;
4760}
4761
4762.lm-switch > input:focus {
4763 opacity: 0.12;
4764}
4765
4766.lm-switch:hover > input:focus {
4767 opacity: 0.16;
4768}
4769
4770.lm-switch > input:active {
4771 opacity: 1;
4772 transform: scale(0);
4773 transition: transform 0s, opacity 0s;
4774}
4775
4776.lm-switch > input:active + span::before {
4777 background-color: var(--lm-switch-main-color-alpha);
4778}
4779
4780.lm-switch > input:checked:active + span::before {
4781 background-color: rgba(var(--lm-switch-front-color), 0.38);
4782}
4783
4784.lm-switch > input:disabled {
4785 opacity: 0;
4786}
4787
4788.lm-switch > input:disabled + span {
4789 color: rgb(var(--lm-switch-front-color));
4790 opacity: 0.50;
4791 cursor: default;
4792}
4793
4794.lm-switch > input:disabled + span::before {
4795 background-color: rgba(var(--lm-switch-front-color), 0.38);
4796}
4797
4798.lm-switch > input:checked:disabled + span::before {
4799 background-color: var(--lm-switch-main-color-alpha);
4800}
4801
4802.lm-switch[position="right"] > span {
4803 margin: 0 45px 0 0;
4804}
4805
4806.lm-switch[position="right"] > input {
4807 left: initial;
4808 right: 11px;
4809}
4810
4811.lm-switch[position="right"] > input:checked {
4812 left: initial;
4813 right: -5px;
4814}
4815
4816.lm-switch[position="right"] > span::before {
4817 left: initial;
4818 right: 0;
4819}
4820
4821.lm-switch[position="right"] > span::after {
4822 left: initial;
4823 right: 16px;
4824}
4825
4826.lm-tabs[data-position="bottom"] {
4827 display: flex;
4828 justify-content: center;
4829 flex-direction: column-reverse;
4830}
4831
4832.lm-tabs .lm-tabs-content > div {
4833 padding: 15px 5px;
4834}
4835
4836.lm-tabs .lm-tabs-headers {
4837 display: flex;
4838 align-items: center;
4839 width: 100%;
4840}
4841
4842.lm-tabs[data-position="center"] .lm-tabs-headers {
4843 margin: 0 auto;
4844 justify-content: center;
4845}
4846
4847.lm-tabs .lm-tabs-headers > ul {
4848 list-style-type: none;
4849 display: flex;
4850 margin: 0;
4851 padding: 0;
4852 align-items: center;
4853}
4854
4855.lm-tabs .lm-tabs-headers > ul > li {
4856 cursor: pointer;
4857 user-select: none;
4858 padding: 4px 24px;
4859 border: 1px solid #ccc;
4860 background-position: center;
4861 transition: background 0.8s;
4862 display: flex;
4863 flex-direction: column;
4864 align-items: center;
4865}
4866
4867.lm-tabs .lm-tabs-headers > ul > li.selected {
4868 background-color: #eee;
4869 color: #000;
4870}
4871
4872.lm-tabs .lm-tabs-headers > ul > li[data-icon]:before {
4873 content: attr(data-icon);
4874 font-family: "Material Symbols Outlined", "Material Icons", "FontAwesome";
4875 font-size: 24px;
4876 width: 24px;
4877 height: 24px;
4878 text-align: center;
4879 color: var(--lm-icon-color, #777);
4880 margin-bottom: 5px;
4881}
4882
4883.lm-tabs[data-round="true"] .lm-tabs-headers > ul > li:first-of-type {
4884 border-top-left-radius: 3px;
4885 border-bottom-left-radius: 3px;
4886}
4887
4888.lm-tabs[data-round="true"] .lm-tabs-headers > ul > li:last-of-type {
4889 border-top-right-radius: 3px;
4890 border-bottom-right-radius: 3px;
4891}
4892
4893.lm-tabs .lm-tabs-headers > ul > li:not(:first-child) {
4894 border-left: 1px solid transparent;
4895}
4896
4897.lm-tabs .lm-tabs-headers > ul > li:hover {
4898 background: #eee radial-gradient(circle, transparent 1%, #eee 1%) center/15000%;
4899}
4900
4901.lm-tabs .lm-tabs-headers > ul > li:active {
4902 background-color: #ddd;
4903 background-size: 100%;
4904 transition: background 0s;
4905}
4906
4907.lm-tabs .lm-tabs-content > div {
4908 display: none;
4909}
4910
4911.lm-tabs .lm-tabs-content > div.selected {
4912 display: block;
4913}
4914
4915.lm-tabs-insert-button {
4916 margin-left: 5px;
4917 color: #555;
4918 cursor: pointer;
4919 font-family: "Material Symbols Outlined", "Material Icons", "FontAwesome";
4920 font-size: 24px;
4921 width: 24px;
4922 height: 24px;
4923 text-align: center;
4924 line-height: 24px;
4925}
4926
4927.lm-tabs div[data-visible="false"] {
4928 display: none;
4929}
4930
4931.lm-topmenu {
4932 outline: none;
4933}
4934
4935.lm-topmenu-options {
4936 display: flex;
4937 font-size: 0.9em;
4938}
4939
4940.lm-topmenu-title {
4941 cursor: pointer;
4942 padding: 4px 12px 4px 12px;
4943 border-radius: 4px;
4944 user-select: none;
4945 margin: 8px 2px;
4946}
4947
4948.lm-topmenu-title:hover, .lm-topmenu-title:focus {
4949 background-color: var(--lm-background-color-highlight, #ebebeb);
4950}
4951
4952.lm-topmenu-title[data-disabled="true"] {
4953 opacity: 0.5;
4954 pointer-events: none;
4955}
4956
4957.lm-topmenu-title[data-selected="true"] {
4958 background-color: var(--lm-background-color-highlight, #ebebeb);
4959 outline: 2px solid var(--lm-border-outline, #000);
4960}
4961
4962.lm-topmenu lm-modal:first-of-type > .lm-modal {
4963 position: absolute;
4964 transition: initial;
4965}
web/vendor/jsuites.js +23974 -0
……@@ -0,0 +1,23974 @@
1
2;(function (global, factory) {
3 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4 typeof define === 'function' && define.amd ? define(factory) :
5 global.jSuites = factory();
6}(this, (function () {
7
8var jSuites;
9/******/ (function() { // webpackBootstrap
10/******/ var __webpack_modules__ = ({
11
12/***/ 791:
13/***/ (function(module) {
14
15/**
16 * (c) jSuites Javascript Plugins and Web Components (v6)
17 *
18 * Website: https://jsuites.net
19 * Description: Create amazing web based applications.
20 *
21 * MIT License
22 */
23
24;(function (global, factory) {
25 true ? module.exports = factory() :
26 0;
27}(this, (function () {
28
29 'use strict';
30
31 const Helpers = (function () {
32 const component = {};
33
34 // Excel like dates
35 const excelInitialTime = Date.UTC(1900, 0, 0);
36 const excelLeapYearBug = Date.UTC(1900, 1, 29);
37 const millisecondsPerDay = 86400000;
38
39 // Transform in two digits
40 component.two = function (value) {
41 value = '' + value;
42 if (value.length === 1) {
43 value = '0' + value;
44 }
45 return value;
46 };
47
48 component.isValidDate = function (d) {
49 return d instanceof Date && !isNaN(d.getTime());
50 };
51
52 component.isValidDateFormat = function(date) {
53 if (typeof date === 'string') {
54 // Check format: YYYY-MM-DD using regex
55 const match = date.substring(0, 10).match(/^(\d{4})-(\d{2})-(\d{2})$/);
56 if (match) {
57 const year = Number(match[1]);
58 const month = Number(match[2]) - 1;
59 const day = Number(match[3]);
60 const parsed = new Date(Date.UTC(year, month, day));
61 // Return
62 return parsed.getUTCFullYear() === year && parsed.getUTCMonth() === month && parsed.getUTCDate() === day;
63 }
64 }
65
66 return false;
67 }
68
69 component.toString = function (date, dateOnly) {
70 let y = null;
71 let m = null;
72 let d = null;
73 let h = null;
74 let i = null;
75 let s = null;
76
77 if (Array.isArray(date)) {
78 y = date[0];
79 m = date[1];
80 d = date[2];
81 h = date[3];
82 i = date[4];
83 s = date[5];
84 } else {
85 if (!date) {
86 date = new Date();
87 }
88 y = date.getUTCFullYear();
89 m = date.getUTCMonth() + 1;
90 d = date.getUTCDate();
91 h = date.getUTCHours();
92 i = date.getUTCMinutes();
93 s = date.getUTCSeconds();
94 }
95
96 if (dateOnly === true) {
97 return component.two(y) + '-' + component.two(m) + '-' + component.two(d);
98 } else {
99 return (
100 component.two(y) + '-' + component.two(m) + '-' + component.two(d) + ' ' + component.two(h) + ':' + component.two(i) + ':' + component.two(s)
101 );
102 }
103 };
104
105 component.toArray = function (value) {
106 let date = value.split(value.indexOf('T') !== -1 ? 'T' : ' ');
107 let time = date[1];
108
109 date = date[0].split('-');
110 let y = parseInt(date[0]);
111 let m = parseInt(date[1]);
112 let d = parseInt(date[2]);
113 let h = 0;
114 let i = 0;
115
116 if (time) {
117 time = time.split(':');
118 h = parseInt(time[0]);
119 i = parseInt(time[1]);
120 }
121 return [y, m, d, h, i, 0];
122 };
123
124 component.arrayToStringDate = function (arr) {
125 return component.toString(arr, false);
126 };
127
128 component.dateToNum = function (jsDate) {
129 if (typeof jsDate === 'string') {
130 jsDate = new Date(jsDate + ' GMT+0');
131 }
132 let jsDateInMilliseconds = jsDate.getTime();
133 if (jsDateInMilliseconds >= excelLeapYearBug) {
134 jsDateInMilliseconds += millisecondsPerDay;
135 }
136 jsDateInMilliseconds -= excelInitialTime;
137
138 return jsDateInMilliseconds / millisecondsPerDay;
139 };
140
141 component.numToDate = function (excelSerialNumber, asArray) {
142 // allow 0; only bail on null/undefined/empty
143 if (excelSerialNumber === null || excelSerialNumber === undefined || excelSerialNumber === '') {
144 return '';
145 }
146
147 const MS_PER_DAY = 86_400_000;
148 const SEC_PER_DAY = 86_400;
149
150 // Excel day 0 is 1899-12-31 (with the fake 1900-02-29 at serial 60)
151 const EXCEL_DAY0_UTC_MS = Date.UTC(1899, 11, 31);
152
153 let wholeDays = Math.floor(excelSerialNumber);
154 let fractionalDay = excelSerialNumber - wholeDays;
155
156 // Fix the 1900 leap-year bug: shift serials >= 60 back one day
157 if (wholeDays >= 60) wholeDays -= 1;
158
159 // Build midnight UTC of the day
160 let ms = EXCEL_DAY0_UTC_MS + wholeDays * MS_PER_DAY;
161
162 // Add time part using integer seconds to avoid FP jitter
163 const seconds = Math.round(fractionalDay * SEC_PER_DAY);
164 ms += seconds * 1000;
165
166 const d = new Date(ms);
167
168 const arr = [
169 d.getUTCFullYear(),
170 component.two(d.getUTCMonth() + 1),
171 component.two(d.getUTCDate()),
172 component.two(d.getUTCHours()),
173 component.two(d.getUTCMinutes()),
174 component.two(d.getUTCSeconds()),
175 ];
176
177 return asArray ? arr : component.toString(arr, false);
178 };
179
180 component.prettify = function (d, texts) {
181 if (!texts) {
182 texts = {
183 justNow: 'Just now',
184 xMinutesAgo: '{0}m ago',
185 xHoursAgo: '{0}h ago',
186 xDaysAgo: '{0}d ago',
187 xWeeksAgo: '{0}w ago',
188 xMonthsAgo: '{0} mon ago',
189 xYearsAgo: '{0}y ago',
190 };
191 }
192
193 if (d.indexOf('GMT') === -1 && d.indexOf('Z') === -1) {
194 d += ' GMT';
195 }
196
197 let d1 = new Date();
198 let d2 = new Date(d);
199 let total = parseInt((d1 - d2) / 1000 / 60);
200
201 const format = (t, o) => {
202 return t.replace('{0}', o);
203 };
204
205 if (!total) {
206 return texts.justNow;
207 } else if (total < 90) {
208 return format(texts.xMinutesAgo, total);
209 } else if (total < 1440) {
210 // One day
211 return format(texts.xHoursAgo, Math.round(total / 60));
212 } else if (total < 20160) {
213 // 14 days
214 return format(texts.xDaysAgo, Math.round(total / 1440));
215 } else if (total < 43200) {
216 // 30 days
217 return format(texts.xWeeksAgo, Math.round(total / 10080));
218 } else if (total < 1036800) {
219 // 24 months
220 return format(texts.xMonthsAgo, Math.round(total / 43200));
221 } else {
222 // 24 months+
223 return format(texts.xYearsAgo, Math.round(total / 525600));
224 }
225 };
226
227 component.prettifyAll = function () {
228 let elements = document.querySelectorAll('.prettydate');
229 for (let i = 0; i < elements.length; i++) {
230 if (elements[i].getAttribute('data-date')) {
231 elements[i].innerHTML = component.prettify(elements[i].getAttribute('data-date'));
232 } else {
233 if (elements[i].innerHTML) {
234 elements[i].setAttribute('title', elements[i].innerHTML);
235 elements[i].setAttribute('data-date', elements[i].innerHTML);
236 elements[i].innerHTML = component.prettify(elements[i].innerHTML);
237 }
238 }
239 }
240 };
241
242 // Compatibility with jSuites
243 component.now = component.toString;
244
245 const weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
246 const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
247
248 const translate = function (t) {
249 if (typeof document !== 'undefined' && document.dictionary) {
250 return document.dictionary[t] || t;
251 } else {
252 return t;
253 }
254 };
255
256 Object.defineProperty(component, 'weekdays', {
257 get: function () {
258 return weekdays.map(function (v) {
259 return translate(v);
260 });
261 },
262 });
263
264 Object.defineProperty(component, 'weekdaysShort', {
265 get: function () {
266 return weekdays.map(function (v) {
267 return translate(v).substring(0, 3);
268 });
269 },
270 });
271
272 Object.defineProperty(component, 'months', {
273 get: function () {
274 return months.map(function (v) {
275 return translate(v);
276 });
277 },
278 });
279
280 Object.defineProperty(component, 'monthsShort', {
281 get: function () {
282 return months.map(function (v) {
283 return translate(v).substring(0, 3);
284 });
285 },
286 });
287
288 return component;
289 })();
290
291 const Mask = (function() {
292 // Currency
293 const tokens = {
294 // Escape
295 escape: [ '\\\\[.\\s\\S]' ],
296 // Text
297 text: [ '@', '&' ],
298 // Number
299 fraction: [ '#{0,1}.*?\\?+\\/[0-9?]+' ],
300 // Currency tokens
301 currency: [ '#(.{1})##0?(.{1}[0#]+)?( ?;(.*)?)?' ],
302 // Scientific
303 scientific: [ '[0#]+([.,]{1}0*#*)?E{1}\\+0+' ],
304 // Percentage
305 percentage: [ '[0#]+([.,]{1}0*#*)?%' ],
306 // Number
307 numeric: [ '[0#]+([.,]{1}0*#*)?', '#+' ],
308 // Data tokens
309 datetime: [ 'YYYY', 'YYY', 'YY', 'MMMMM', 'MMMM', 'MMM', 'MM', 'DDDDD', 'DDDD', 'DDD', 'DD', 'DY', 'DAY', 'WD', 'D', 'Q', 'MONTH', 'MON', 'HH24', 'HH12', 'HH', '\\[H\\]', 'H', 'AM/PM', 'MI', 'SS', 'MS', 'S', 'Y', 'M', 'I' ],
310 // Other
311 general: [ 'A', '0', '\\?', '\\*', ',,M', ',,,B', '[a-zA-Z\\$]+', '_[.\\s\\S]', '\\(', '\\)', '.']
312 }
313
314 const countryCodes = {
315 "0409": [
316 "$",
317 ",",
318 "."
319 ],
320 "0809": [
321 "£",
322 ",",
323 "."
324 ],
325 "0C09": [
326 "$",
327 ",",
328 "."
329 ],
330 "1009": [
331 "$",
332 ",",
333 "."
334 ],
335 "1409": [
336 "$",
337 ",",
338 "."
339 ],
340 "1809": [
341 "€",
342 ",",
343 "."
344 ],
345 "1C09": [
346 "R",
347 " ",
348 "."
349 ],
350 "040C": [
351 "€",
352 " ",
353 ","
354 ],
355 "080C": [
356 "€",
357 " ",
358 ","
359 ],
360 "100C": [
361 "CHF",
362 "'",
363 "."
364 ],
365 "140C": [
366 "€",
367 " ",
368 ","
369 ],
370 "0C0C": [
371 "$",
372 " ",
373 ","
374 ],
375 "0407": [
376 "€",
377 ".",
378 ","
379 ],
380 "0C07": [
381 "€",
382 ".",
383 ","
384 ],
385 "0807": [
386 "CHF",
387 "'",
388 "."
389 ],
390 "1007": [
391 "€",
392 ".",
393 ","
394 ],
395 "0413": [
396 "€",
397 ".",
398 ","
399 ],
400 "0813": [
401 "€",
402 " ",
403 ","
404 ],
405 "0410": [
406 "€",
407 ".",
408 ","
409 ],
410 "0810": [
411 "CHF",
412 "'",
413 "."
414 ],
415 "0C0A": [
416 "€",
417 ".",
418 ","
419 ],
420 "080A": [
421 "$",
422 ",",
423 "."
424 ],
425 "2C0A": [
426 "$",
427 ".",
428 ","
429 ],
430 "340A": [
431 "$",
432 ".",
433 ","
434 ],
435 "240A": [
436 "$",
437 ".",
438 ","
439 ],
440 "300A": [
441 "$",
442 ",",
443 "."
444 ],
445 "280A": [
446 "S/",
447 ",",
448 "."
449 ],
450 "200A": [
451 "Bs.",
452 ".",
453 ","
454 ],
455 "140A": [
456 "₡",
457 ",",
458 "."
459 ],
460 "100A": [
461 "Q",
462 ",",
463 "."
464 ],
465 "1C0A": [
466 "RD$",
467 ",",
468 "."
469 ],
470 "3C0A": [
471 "$",
472 ",",
473 "."
474 ],
475 "440A": [
476 "C$",
477 ",",
478 "."
479 ],
480 "4C0A": [
481 "B/.",
482 ",",
483 "."
484 ],
485 "480A": [
486 "L",
487 ",",
488 "."
489 ],
490 "0816": [
491 "€",
492 ".",
493 ","
494 ],
495 "0416": [
496 "R$",
497 ".",
498 ","
499 ],
500 "0406": [
501 "kr",
502 ".",
503 ","
504 ],
505 "041D": [
506 "kr",
507 " ",
508 ","
509 ],
510 "0414": [
511 "kr",
512 " ",
513 ","
514 ],
515 "040B": [
516 "€",
517 " ",
518 ","
519 ],
520 "040F": [
521 "kr",
522 ".",
523 ","
524 ],
525 "0415": [
526 "zł",
527 " ",
528 ","
529 ],
530 "0405": [
531 "Kč",
532 " ",
533 ","
534 ],
535 "041B": [
536 "€",
537 " ",
538 ","
539 ],
540 "040E": [
541 "Ft",
542 " ",
543 ","
544 ],
545 "0424": [
546 "€",
547 ".",
548 ","
549 ],
550 "041A": [
551 "€",
552 ".",
553 ","
554 ],
555 "0418": [
556 "lei",
557 ".",
558 ","
559 ],
560 "0402": [
561 "лв.",
562 " ",
563 ","
564 ],
565 "0425": [
566 "€",
567 " ",
568 ","
569 ],
570 "0426": [
571 "€",
572 " ",
573 ","
574 ],
575 "0427": [
576 "€",
577 " ",
578 ","
579 ],
580 "0408": [
581 "€",
582 ".",
583 ","
584 ],
585 "043A": [
586 "€",
587 ",",
588 "."
589 ],
590 "043C": [
591 "€",
592 ",",
593 "."
594 ],
595 "0419": [
596 "₽",
597 " ",
598 ","
599 ],
600 "0422": [
601 "₴",
602 " ",
603 ","
604 ],
605 "0423": [
606 "Br",
607 " ",
608 ","
609 ],
610 "041F": [
611 "₺",
612 ".",
613 ","
614 ],
615 "042C": [
616 "₼",
617 " ",
618 ","
619 ],
620 "042F": [
621 "ден",
622 ".",
623 ","
624 ],
625 "0441": [
626 "Lek",
627 ".",
628 ","
629 ],
630 "141A": [
631 "KM",
632 ".",
633 ","
634 ],
635 "0401": [
636 "ر.س",
637 ",",
638 "."
639 ],
640 "0C01": [
641 "ج.م",
642 ",",
643 "."
644 ],
645 "1401": [
646 "دج",
647 " ",
648 ","
649 ],
650 "1801": [
651 "د.م.",
652 " ",
653 ","
654 ],
655 "1C01": [
656 "د.ت",
657 " ",
658 ","
659 ],
660 "2001": [
661 "﷼",
662 ",",
663 "."
664 ],
665 "3401": [
666 "KD",
667 ",",
668 "."
669 ],
670 "3801": [
671 "د.إ",
672 ",",
673 "."
674 ],
675 "3C01": [
676 "BD",
677 ",",
678 "."
679 ],
680 "4001": [
681 "ر.ق",
682 ",",
683 "."
684 ],
685 "2801": [
686 "£",
687 ",",
688 "."
689 ],
690 "2C01": [
691 "د.ا",
692 ",",
693 "."
694 ],
695 "3001": [
696 "ل.ل",
697 ",",
698 "."
699 ],
700 "2401": [
701 "﷼",
702 ",",
703 "."
704 ],
705 "1001": [
706 "ل.د",
707 ",",
708 "."
709 ],
710 "0429": [
711 "﷼",
712 ",",
713 "."
714 ],
715 "040D": [
716 "₪",
717 ",",
718 "."
719 ],
720 "0439": [
721 "₹",
722 ",",
723 "."
724 ],
725 "0445": [
726 "৳",
727 ",",
728 "."
729 ],
730 "0461": [
731 "रु",
732 ",",
733 "."
734 ],
735 "045B": [
736 "Rs",
737 ",",
738 "."
739 ],
740 "044E": [
741 "₹",
742 ",",
743 "."
744 ],
745 "0444": [
746 "₹",
747 ",",
748 "."
749 ],
750 "0449": [
751 "₹",
752 ",",
753 "."
754 ],
755 "044B": [
756 "₹",
757 ",",
758 "."
759 ],
760 "0421": [
761 "Rp",
762 ".",
763 ","
764 ],
765 "043E": [
766 "RM",
767 ",",
768 "."
769 ],
770 "0464": [
771 "₱",
772 ",",
773 "."
774 ],
775 "041E": [
776 "฿",
777 ",",
778 "."
779 ],
780 "042A": [
781 "₫",
782 ".",
783 ","
784 ],
785 "0453": [
786 "៛",
787 ",",
788 "."
789 ],
790 "0454": [
791 "₭",
792 ",",
793 "."
794 ],
795 "0455": [
796 "K",
797 ",",
798 "."
799 ],
800 "0404": [
801 "NT$",
802 ",",
803 "."
804 ],
805 "0C04": [
806 "HK$",
807 ",",
808 "."
809 ],
810 "0804": [
811 "¥",
812 ",",
813 "."
814 ],
815 "0411": [
816 "¥",
817 ",",
818 "."
819 ],
820 "0412": [
821 "₩",
822 ",",
823 "."
824 ],
825 "0437": [
826 "₾",
827 " ",
828 ","
829 ],
830 "042B": [
831 "֏",
832 " ",
833 ","
834 ],
835 "043F": [
836 "₸",
837 " ",
838 ","
839 ],
840 "0443": [
841 "so'm",
842 " ",
843 ","
844 ],
845 "0428": [
846 "ЅМ",
847 " ",
848 ","
849 ],
850 "0440": [
851 "сом",
852 " ",
853 ","
854 ],
855 "0466": [
856 "₦",
857 ",",
858 "."
859 ],
860 "0469": [
861 "₦",
862 ",",
863 "."
864 ],
865 "0468": [
866 "GH₵",
867 ",",
868 "."
869 ],
870 "180C": [
871 "F CFA",
872 " ",
873 ","
874 ]
875 }
876
877 /**
878 * Detect decimal and thousand separators in a mask pattern
879 */
880 const detectMaskSeparators = function(mask) {
881 // Decimal: separator in pattern 0[sep]0+ (can have trailing chars like _ )
882 // Look for the rightmost occurrence of this pattern
883 const decimalMatches = mask.match(/0([.,\s'])0+/g);
884 let decimal = null;
885 if (decimalMatches && decimalMatches.length > 0) {
886 // Get the last match (rightmost decimal pattern)
887 const lastMatch = decimalMatches[decimalMatches.length - 1];
888 const sepMatch = lastMatch.match(/0([.,\s'])0/);
889 decimal = sepMatch ? sepMatch[1] : null;
890 }
891
892 // Thousand: other separator that appears in #[sep]# or 0[sep]# patterns
893 let thousand = null;
894 for (const sep of [',', '.', ' ', "'"]) {
895 if (sep !== decimal) {
896 const escapedSep = sep === '.' ? '\\.' : sep;
897 const regex = new RegExp('[#0]' + escapedSep + '[#0]');
898 if (regex.test(mask)) {
899 thousand = sep;
900 break;
901 }
902 }
903 }
904
905 return { decimal, thousand };
906 }
907
908 /**
909 * Transform Excel currency locale patterns like [$$-409]#,##0.00
910 * countryCodes format: { "0409": ["$", ",", "."] } // [currency, thousand, decimal]
911 * [$$ = use locale's default currency, [$X = use literal X]
912 */
913 const transformExcelLocaleMask = function(mask) {
914 // Handle multiple patterns (e.g., positive;negative)
915 // Accept any alphanumeric for locale code to handle invalid codes gracefully
916 const pattern = /\[\$(.?)-([0-9A-Z]+)\]/gi;
917 let transformation = null;
918
919 // Find first pattern to determine locale
920 const firstMatch = mask.match(/\[\$(.?)-([0-9A-Z]+)\]/i);
921 if (!firstMatch) return mask;
922
923 const symbolChar = firstMatch[1] || '';
924 let localeCode = firstMatch[2].toUpperCase();
925
926 // Pad with leading zero if 3 digits (e.g., "409" → "0409")
927 if (localeCode.length === 3) {
928 localeCode = '0' + localeCode;
929 }
930
931 // Look up locale in countryCodes
932 const localeData = countryCodes[localeCode];
933
934 if (!localeData) {
935 // Unknown locale - fallback: strip ALL patterns, use literal symbol (or $)
936 const fallbackSymbol = symbolChar || '$';
937 // Replace all occurrences of the pattern with the symbol
938 return mask.replace(/\[\$(.?)-([0-9A-Z]+)\]/gi, fallbackSymbol);
939 }
940
941 // Extract from array: [currency, thousand, decimal]
942 const localeCurrency = localeData[0];
943 const localeThousand = localeData[1];
944 const localeDecimal = localeData[2];
945
946 // Determine currency symbol: $$ means use locale's default, else use literal
947 let currencySymbol;
948 if (symbolChar === '$') {
949 // $$ pattern - use locale's default currency
950 currencySymbol = localeCurrency;
951 } else {
952 // Literal symbol provided (e.g., [$€-407])
953 currencySymbol = symbolChar;
954 }
955
956 // Replace all locale patterns with currency symbol
957 let result = mask.replace(pattern, currencySymbol);
958
959 // Detect current separators in mask (after removing patterns)
960 const current = detectMaskSeparators(result);
961
962 // Transform separators to match locale using placeholders to avoid conflicts
963 const temp1 = '\uFFF0'; // Placeholder for thousand
964 const temp2 = '\uFFF1'; // Placeholder for decimal
965
966 // Step 1: Replace current separators with placeholders
967 if (current.thousand && current.thousand !== localeThousand) {
968 const from = current.thousand === '.' ? '\\.' : (current.thousand === ' ' ? ' ' : current.thousand);
969 result = result.replace(new RegExp(from, 'g'), temp1);
970 }
971 if (current.decimal && current.decimal !== localeDecimal) {
972 const from = current.decimal === '.' ? '\\.' : (current.decimal === ' ' ? ' ' : current.decimal);
973 result = result.replace(new RegExp(from, 'g'), temp2);
974 }
975
976 // Step 2: Replace placeholders with target separators
977 result = result.replace(new RegExp(temp1, 'g'), localeThousand);
978 result = result.replace(new RegExp(temp2, 'g'), localeDecimal);
979
980 return result;
981 }
982
983 // All expressions
984 const allExpressions = [].concat(tokens.escape, tokens.fraction, tokens.currency, tokens.datetime, tokens.percentage, tokens.scientific, tokens.numeric, tokens.text, tokens.general).join('|');
985
986 // Pre-compile all regexes once at initialization for better performance
987 const compiledTokens = {};
988 const tokenPriority = ['escape', 'fraction', 'currency', 'scientific', 'percentage', 'numeric', 'datetime', 'text', 'general'];
989
990 // Cache for getMethod results
991 const methodCache = {};
992 // Cache for getTokens results
993 const tokensCache = {};
994 // Cache for autoCasting results
995 const autoCastingCache = {};
996
997 // Initialize compiled regexes
998 for (const type of tokenPriority) {
999 compiledTokens[type] = tokens[type].map(pattern => ({
1000 regex: new RegExp('^' + pattern + '$', 'i'),
1001 method: pattern
1002 }));
1003 }
1004
1005 // Pre-compile regex for getTokens function
1006 const allExpressionsRegex = new RegExp(allExpressions, 'gi');
1007 const hiddenCaret = "\u200B";
1008 // Locale for date parsing
1009 const userLocale = (typeof navigator !== 'undefined' && navigator.language) || 'en-US';
1010
1011 // Helpers
1012 const focus = function(el) {
1013 if (el.textContent.length) {
1014 // Handle contenteditable elements
1015 const range = document.createRange();
1016 const sel = window.getSelection();
1017
1018 let node = el;
1019 // Go as deep as possible to the last text node
1020 while (node.lastChild) node = node.lastChild;
1021 // Ensure it's a text node
1022 if (node.nodeType === Node.TEXT_NODE) {
1023 range.setStart(node, node.length);
1024 } else {
1025 range.setStart(node, node.childNodes.length);
1026 }
1027 range.collapse(true);
1028 sel.removeAllRanges();
1029 sel.addRange(range);
1030
1031 el.scrollLeft = el.scrollWidth;
1032 }
1033 }
1034
1035 /**
1036 * Returns if the given value is considered blank
1037 */
1038 const isBlank = function(v) {
1039 return v === null || v === '' || typeof(v) === 'undefined';
1040 }
1041
1042 /**
1043 * Clean mask - extremely fast implementation using only char operations
1044 * Removes quotes, detects parenthesis for negative numbers, and removes brackets (except time format codes)
1045 * Sets control.parenthesisForNegativeNumbers and returns cleaned mask
1046 */
1047 const cleanMask = function(mask, control) {
1048 const len = mask.length;
1049 let result = '';
1050
1051 for (let i = 0; i < len; i++) {
1052 const char = mask[i];
1053
1054 // Remove quotes
1055 if (char === '"') {
1056 continue;
1057 }
1058
1059 // Handle brackets - remove them unless they're time format codes
1060 if (char === '[') {
1061 // Check if it's a time format code: [s], [ss], [h], [hh], [m], [mm]
1062 let isTimeFormat = false;
1063 if (i + 2 < len && mask[i + 2] === ']') {
1064 const c = mask[i + 1];
1065 if (c === 's' || c === 'h' || c === 'm') {
1066 isTimeFormat = true;
1067 }
1068 } else if (i + 3 < len && mask[i + 3] === ']') {
1069 const c1 = mask[i + 1];
1070 const c2 = mask[i + 2];
1071 if ((c1 === 's' && c2 === 's') || (c1 === 'h' && c2 === 'h') || (c1 === 'm' && c2 === 'm')) {
1072 isTimeFormat = true;
1073 }
1074 }
1075
1076 if (isTimeFormat) {
1077 result += char;
1078 } else {
1079 // Skip content and closing bracket
1080 while (i < len && mask[i] !== ']') {
1081 i++;
1082 }
1083 continue;
1084 }
1085 }
1086 // Check for parenthesis (not preceded by underscore and no underscore inside)
1087 else if (char === '(') {
1088 if (i === 0 || mask[i - 1] !== '_') {
1089 let hasUnderscore = false;
1090 let depth = 1;
1091 for (let j = i + 1; j < len && depth > 0; j++) {
1092 if (mask[j] === '(') depth++;
1093 if (mask[j] === ')') depth--;
1094 if (mask[j] === '_') {
1095 hasUnderscore = true;
1096 break;
1097 }
1098 }
1099 if (! hasUnderscore) {
1100 control.parenthesisForNegativeNumbers = true;
1101 }
1102 }
1103 result += char;
1104 } else {
1105 result += char;
1106 }
1107 }
1108
1109 return result;
1110 }
1111
1112 /**
1113 * Receives a string from a method type and returns if it's a numeric method
1114 */
1115 const isNumeric = function(t) {
1116 return t === 'currency' || t === 'percentage' || t === 'numeric' || t === 'scientific';
1117 }
1118
1119 const adjustPrecision = function(num) {
1120 if (typeof num === 'number' && ! Number.isInteger(num)) {
1121 const v = num.toString().split('.');
1122
1123 if (v[1] && v[1].length > 10) {
1124 let t0 = 0;
1125 const t1 = v[1][v[1].length - 2];
1126
1127 if (t1 == 0 || t1 == 9) {
1128 for (let i = v[1].length - 2; i > 0; i--) {
1129 if (t0 >= 0 && v[1][i] == t1) {
1130 t0++;
1131 if (t0 > 6) {
1132 break;
1133 }
1134 } else {
1135 t0 = 0;
1136 break;
1137 }
1138 }
1139
1140 if (t0) {
1141 return parseFloat(parseFloat(num).toFixed(v[1].length - 1));
1142 }
1143 }
1144 }
1145 }
1146
1147 return num;
1148 }
1149
1150 /**
1151 * Get the decimal defined in the mask configuration
1152 */
1153 const getDecimal = function(v) {
1154 let decimal;
1155 if (this.decimal) {
1156 decimal = this.decimal;
1157 } else {
1158 if (this.locale) {
1159 let t = Intl.NumberFormat(this.locale).format(1.1);
1160 decimal = t[1];
1161 } else {
1162 if (! v) {
1163 v = this.mask;
1164 }
1165
1166 // Fixed regex: 0* means zero or more 0s before decimal separator
1167 let e = new RegExp('0*([,.])0+', 'ig');
1168 let t = e.exec(v);
1169 if (t && t[1] && t[1].length === 1) {
1170 decimal = t[1];
1171 } else {
1172 // Try the second pattern for # formats
1173 e = new RegExp('#{1}(.{1})#+', 'ig');
1174 t = e.exec(v);
1175 if (t && t[1] && t[1].length === 1) {
1176 if (t[1] === ',') {
1177 decimal = '.';
1178 } else if (t[1] === "'" || t[1] === '.') {
1179 decimal = ',';
1180 }
1181 }
1182 }
1183
1184 if (! decimal) {
1185 decimal = '1.1'.toLocaleString().substring(1, 2);
1186 }
1187 }
1188 }
1189
1190 if (decimal) {
1191 return decimal;
1192 } else {
1193 return null;
1194 }
1195 }
1196
1197 /**
1198 * Caret position getter
1199 * `this` in this function should be the element with a caret
1200 */
1201 const getCaretPosition = function(editableDiv) {
1202 let caretPos = 0;
1203 let sel = window.getSelection();
1204 if (sel && sel.rangeCount > 0) {
1205 let range = sel.getRangeAt(0);
1206 let preRange = range.cloneRange();
1207 preRange.selectNodeContents(editableDiv);
1208 preRange.setEnd(range.endContainer, range.endOffset);
1209 caretPos = preRange.toString().length;
1210 }
1211 return caretPos;
1212 }
1213
1214 /**
1215 * Caret position getter
1216 * `this` in this function should be the element with a caret
1217 */
1218 const getCaret = function(el) {
1219 if (el.tagName === 'DIV') {
1220 return getCaretPosition(el);
1221 } else {
1222 return el.selectionStart;
1223 }
1224 }
1225
1226 /**
1227 * Caret position setter
1228 * `this` should be the element (input/textarea or contenteditable div)
1229 */
1230 const setCaret = function(index) {
1231 if (typeof index !== 'number') index = Number(index) || 0;
1232
1233 if (this.tagName !== 'DIV' || this.isContentEditable !== true) {
1234 const n = this.value ?? '';
1235 if (index < 0) index = 0;
1236 if (index > n.length) index = n.length;
1237 this.focus();
1238 this.selectionStart = index;
1239 this.selectionEnd = index;
1240 return;
1241 }
1242
1243 // Contenteditable DIV
1244 const el = /** @type {HTMLElement} */ (this);
1245 const totalLen = (el.textContent || '').length;
1246
1247 if (index < 0) index = 0;
1248 if (index > totalLen) index = totalLen;
1249
1250 const sel = window.getSelection();
1251 if (!sel) return;
1252
1253 const range = document.createRange();
1254 el.focus();
1255
1256 // Empty element → ensure a text node to place the caret into
1257 if (totalLen === 0) {
1258 if (!el.firstChild) el.appendChild(document.createTextNode(''));
1259 // place at start
1260 range.setStart(el.firstChild, 0);
1261 range.collapse(true);
1262 sel.removeAllRanges();
1263 sel.addRange(range);
1264 return;
1265 }
1266
1267 // If caret is at the very end, this is fastest/cleanest
1268 if (index === totalLen) {
1269 range.selectNodeContents(el);
1270 range.collapse(false);
1271 sel.removeAllRanges();
1272 sel.addRange(range);
1273 return;
1274 }
1275
1276 // Walk text nodes to find the node that contains the index-th character
1277 const walker = document.createTreeWalker(
1278 el,
1279 NodeFilter.SHOW_TEXT,
1280 {
1281 acceptNode(node) {
1282 // skip empty/whitespace-only nodes if you want; or just accept all text
1283 return node.nodeValue ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
1284 }
1285 }
1286 );
1287
1288 let pos = 0;
1289 let node = walker.nextNode();
1290 while (node) {
1291 const nextPos = pos + node.nodeValue.length;
1292 if (index <= nextPos) {
1293 const offset = index - pos; // char offset within this text node
1294 range.setStart(node, offset);
1295 range.collapse(true);
1296 sel.removeAllRanges();
1297 sel.addRange(range);
1298 return;
1299 }
1300 pos = nextPos;
1301 node = walker.nextNode();
1302 }
1303
1304 // Fallback: collapse at end if something unexpected happened
1305 range.selectNodeContents(el);
1306 range.collapse(false);
1307 sel.removeAllRanges();
1308 sel.addRange(range);
1309 };
1310
1311 /**
1312 * Methods to deal with different types of data
1313 */
1314 const parseMethods = {
1315 'FIND': function(v, a) {
1316 if (isBlank(this.values[this.index])) {
1317 this.values[this.index] = '';
1318 }
1319 // TODO: tratar eventos
1320 if (this.event && this.event.inputType && this.event.inputType.indexOf('delete') > -1) {
1321 this.values[this.index] += v;
1322 return;
1323 }
1324 let pos = 0;
1325 let count = 0;
1326 let value = (this.values[this.index] + v).toLowerCase();
1327 for (let i = 0; i < a.length; i++) {
1328 if (a[i].toLowerCase().indexOf(value) === 0) {
1329 pos = i;
1330 count++;
1331 }
1332 }
1333 if (count > 1) {
1334 this.values[this.index] += v;
1335 } else if (count === 1) {
1336 // Jump a number of chars
1337 let t = (a[pos].length - this.values[this.index].length) - 1;
1338 this.position += t;
1339 this.values[this.index] = a[pos];
1340 this.index++;
1341 return pos;
1342 }
1343 },
1344 'YEAR': function(v, s) {
1345 if (isBlank(this.values[this.index])) {
1346 this.values[this.index] = '';
1347 }
1348
1349 let number = parseInt(v);
1350
1351 if (number >= 0 && number <= 10) {
1352 if (this.values[this.index].length < s) {
1353 this.values[this.index] += v;
1354 }
1355 }
1356 if (this.values[this.index].length === s) {
1357 let y = new Date().getFullYear().toString();
1358 if (s === 2) {
1359 y = y.substring(0,2) + this.values[this.index];
1360 } else if (s === 3) {
1361 y = y.substring(0,1) + this.values[this.index];
1362 } else if (s === 4) {
1363 y = this.values[this.index];
1364 }
1365 this.date[0] = y;
1366 this.index++;
1367 }
1368 },
1369 'YYYY': function(v) {
1370 parseMethods.YEAR.call(this, v, 4);
1371 },
1372 'YYY': function(v) {
1373 parseMethods.YEAR.call(this, v, 3);
1374 },
1375 'YY': function(v) {
1376 parseMethods.YEAR.call(this, v, 2);
1377 },
1378 'MMMMM': function(v) {
1379 if (isBlank(this.values[this.index])) {
1380 this.values[this.index] = '';
1381 }
1382 let value = (this.values[this.index] + v).toLowerCase();
1383 for (var i = 0; i < Helpers.months.length; i++) {
1384 if (Helpers.months[i][0].toLowerCase().indexOf(value) === 0) {
1385 this.values[this.index] = Helpers.months[i][0];
1386 this.date[1] = i + 1;
1387 this.index++;
1388 break;
1389 }
1390 }
1391 },
1392 'MMMM': function(v) {
1393 let ret = parseMethods.FIND.call(this, v, Helpers.months);
1394 if (typeof(ret) !== 'undefined') {
1395 this.date[1] = ret + 1;
1396 }
1397 },
1398 'MMM': function(v) {
1399 let ret = parseMethods.FIND.call(this, v, Helpers.monthsShort);
1400 if (typeof(ret) !== 'undefined') {
1401 this.date[1] = ret + 1;
1402 }
1403 },
1404 'MM': function(v, single) {
1405 const commit = () => {
1406 this.date[1] = this.values[this.index];
1407 this.index++;
1408 }
1409
1410 let number = parseInt(v);
1411
1412 if (isBlank(this.values[this.index])) {
1413 if (number > 1 && number < 10) {
1414 if (! single) {
1415 v = '0' + v;
1416 }
1417 this.values[this.index] = v;
1418 commit();
1419 } else if (number < 2) {
1420 this.values[this.index] = v;
1421 }
1422 } else {
1423 if (this.values[this.index] == 1 && number < 3) {
1424 this.values[this.index] += v;
1425 commit();
1426 } else if (this.values[this.index] == 0 && number > 0 && number < 10) {
1427 this.values[this.index] += v;
1428 commit();
1429 } else {
1430 let test = parseInt(this.values[this.index]);
1431 if (test > 0 && test <= 12) {
1432 if (! single) {
1433 test = '0' + test;
1434 }
1435 this.values[this.index] = test;
1436 commit();
1437 return false;
1438 }
1439 }
1440 }
1441 },
1442 'M': function(v) {
1443 return parseMethods['MM'].call(this, v, true);
1444 },
1445 'MONTH': function(v) {
1446 return parseMethods['MMMM'].call(this, v);
1447 },
1448 'MON': function(v) {
1449 return parseMethods['MMM'].call(this, v);
1450 },
1451 'DDDD': function(v) {
1452 return parseMethods.FIND.call(this, v, Helpers.weekdays);
1453 },
1454 'DDD': function(v) {
1455 return parseMethods.FIND.call(this, v, Helpers.weekdaysShort);
1456 },
1457 'DD': function(v, single) {
1458 const commit = () => {
1459 this.date[2] = this.values[this.index];
1460 this.index++;
1461 }
1462
1463 let number = parseInt(v);
1464
1465 if (isBlank(this.values[this.index])) {
1466 if (number > 3 && number < 10) {
1467 if (! single) {
1468 v = '0' + v;
1469 }
1470 this.values[this.index] = v;
1471 commit();
1472 } else if (number < 10) {
1473 this.values[this.index] = v;
1474 }
1475 } else {
1476 if (this.values[this.index] == 3 && number < 2) {
1477 this.values[this.index] += v;
1478 commit();
1479 } else if ((this.values[this.index] == 1 || this.values[this.index] == 2) && number < 10) {
1480 this.values[this.index] += v;
1481 commit();
1482 } else if (this.values[this.index] == 0 && number > 0 && number < 10) {
1483 this.values[this.index] += v;
1484 commit();
1485 } else {
1486 let test = parseInt(this.values[this.index]);
1487 if (test > 0 && test <= 31) {
1488 if (! single) {
1489 test = '0' + test;
1490 }
1491 this.values[this.index] = test;
1492 commit();
1493 return false;
1494 }
1495 }
1496 }
1497 },
1498 'D': function(v) {
1499 return parseMethods['DD'].call(this, v, true);
1500 },
1501 'DY': function(v) {
1502 return parseMethods['DDD'].call(this, v);
1503 },
1504 'DAY': function(v) {
1505 return parseMethods['DDDD'].call(this, v);
1506 },
1507 'HH12': function(v, two) {
1508 let test = false;
1509
1510 let number = parseInt(v);
1511
1512 if (isBlank(this.values[this.index])) {
1513 if (number > 1 && number < 10) {
1514 if (two) {
1515 v = 0 + v;
1516 }
1517 this.date[3] = this.values[this.index] = v;
1518 this.index++;
1519 } else if (number < 10) {
1520 this.values[this.index] = v;
1521 }
1522 } else {
1523 if (this.values[this.index] == 1 && number < 3) {
1524 this.date[3] = this.values[this.index] += v;
1525 this.index++;
1526 } else if (this.values[this.index] < 1 && number < 10) {
1527 this.date[3] = this.values[this.index] += v;
1528 this.index++;
1529 } else {
1530 test = true;
1531 }
1532 }
1533
1534 // Re-test
1535 if (test === true) {
1536 var t = parseInt(this.values[this.index]);
1537 if (t >= 0 && t <= 12) {
1538 this.date[3] = this.values[this.index];
1539 this.index++;
1540 return false;
1541 }
1542 }
1543 },
1544 'HH24': function(v, two = true) {
1545 let test = false;
1546
1547 let number = parseInt(v)
1548
1549 if (number >= 0 && number < 10) {
1550 if (isBlank(this.values[this.index])) {
1551 if (number > 2 && number < 10) {
1552 if (two !== false) {
1553 v = 0 + v;
1554 }
1555 this.date[3] = this.values[this.index] = v;
1556 this.index++;
1557 } else if (number < 10) {
1558 this.values[this.index] = v;
1559 }
1560 } else {
1561 if (this.values[this.index] == 2 && number < 4) {
1562 if (two === false && this.values[this.index] === '0') {
1563 this.values[this.index] = '';
1564 }
1565 this.date[3] = this.values[this.index] += v;
1566 this.index++;
1567 } else if (this.values[this.index] < 2 && number < 10) {
1568 if (two === false && this.values[this.index] === '0') {
1569 this.values[this.index] = '';
1570 }
1571 this.date[3] = this.values[this.index] += v;
1572 this.index++;
1573 } else {
1574 test = true;
1575 }
1576 }
1577 } else {
1578 test = true;
1579 }
1580
1581 // Re-test
1582 if (test === true) {
1583 var t = parseInt(this.values[this.index]);
1584 if (t >= 0 && t < 24) {
1585 // Pad single digit with leading zero for HH24 format
1586 if (two !== false && this.values[this.index] && this.values[this.index].length === 1) {
1587 this.values[this.index] = '0' + this.values[this.index];
1588 }
1589 this.date[3] = this.values[this.index];
1590 this.index++;
1591 return false;
1592 }
1593 }
1594 },
1595 'HH': function(v) {
1596 parseMethods['HH24'].call(this, v, true);
1597 },
1598 'H': function(v) {
1599 parseMethods['HH24'].call(this, v, false);
1600 },
1601 '\\[H\\]': function(v) {
1602 if (this.values[this.index] == undefined) {
1603 this.values[this.index] = '';
1604 }
1605 if (v.match(/[0-9]/g)) {
1606 this.date[3] = this.values[this.index] += v;
1607 } else {
1608 if (this.values[this.index].match(/[0-9]/g)) {
1609 this.date[3] = this.values[this.index];
1610 this.index++;
1611 return false;
1612 }
1613 }
1614 },
1615 'N60': function(v, i, two) {
1616 let test = false;
1617
1618 let number = parseInt(v);
1619
1620 if (number >= 0 && number < 10) {
1621 if (isBlank(this.values[this.index])) {
1622 if (number > 5 && number < 10) {
1623 if (two) {
1624 v = '0' + v;
1625 }
1626 this.date[i] = this.values[this.index] = v;
1627 this.index++;
1628 } else if (number < 10) {
1629 this.values[this.index] = v;
1630 }
1631 } else {
1632 if (this.values[this.index] < 6 && number < 10) {
1633 if (! two && this.values[this.index] === '0') {
1634 this.values[this.index] = '';
1635 }
1636 this.date[i] = this.values[this.index] += v;
1637 this.index++;
1638 } else {
1639 test = true;
1640 }
1641 }
1642 } else {
1643 test = true;
1644 }
1645
1646 // Re-test
1647 if (test === true) {
1648 var t = parseInt(this.values[this.index]);
1649 if (t >= 0 && t < 60) {
1650 this.date[i] = this.values[this.index];
1651 this.index++;
1652 return false;
1653 }
1654 }
1655 },
1656 'MI': function(v) {
1657 parseMethods.N60.call(this, v, 4, true);
1658 },
1659 'SS': function(v) {
1660 parseMethods.N60.call(this, v, 5, true);
1661 },
1662 'I': function(v) {
1663 parseMethods.N60.call(this, v, 4, false);
1664 },
1665 'S': function(v) {
1666 parseMethods.N60.call(this, v, 5, false);
1667 },
1668 'AM/PM': function(v) {
1669 if (typeof(this.values[this.index]) === 'undefined') {
1670 this.values[this.index] = '';
1671 }
1672
1673 if (this.values[this.index] === '') {
1674 if (v.match(/a/i) && this.date[3] < 13) {
1675 this.values[this.index] += 'A';
1676 } else if (v.match(/p/i)) {
1677 this.values[this.index] += 'P';
1678 }
1679 } else if (this.values[this.index] === 'A' || this.values[this.index] === 'P') {
1680 this.values[this.index] += 'M';
1681 this.index++;
1682 }
1683 },
1684 'WD': function(v) {
1685 if (typeof(this.values[this.index]) === 'undefined') {
1686 this.values[this.index] = '';
1687 }
1688
1689 let number = parseInt(v);
1690
1691 if (number >= 0 && number < 7) {
1692 this.values[this.index] = v;
1693 }
1694 if (this.values[this.index].length == 1) {
1695 this.index++;
1696 }
1697 },
1698 // Numeric Methods
1699 '[0#]+([.,]{1}0*#*)?': function(v) {
1700 if (v === '.' && inputIsANumber(this.raw)) {
1701 v = this.decimal;
1702 }
1703
1704 if (isBlank(this.values[this.index])) {
1705 this.values[this.index] = '';
1706 }
1707
1708 if (v === '-') {
1709 // Transform the number into negative if it is not already
1710 if (this.values[this.index][0] != '-') {
1711 this.values[this.index] = '-' + this.values[this.index];
1712 }
1713 } else if (v === '+') {
1714 // Transform the number into positive if it is negative
1715 if (this.values[this.index][0] == '-') {
1716 this.values[this.index] = this.values[this.index].replace('-', '');
1717 }
1718 } else if (v == '0') {
1719 // Only adds zero if there's a non-zero number before
1720 if (this.values[this.index] != '0' && this.values[this.index] != '-0') {
1721 this.values[this.index] += v;
1722 }
1723 } else if (v > 0 && v < 10) {
1724 // Verify if there's a zero to remove it, avoiding left zeros
1725 if (this.values[this.index] == '0' || this.values[this.index] == '-0') {
1726 this.values[this.index] = this.values[this.index].replace('0', '');
1727 }
1728 this.values[this.index] += v;
1729 } else if (v === this.decimal) {
1730 // Only adds decimal when there's a number value on its left
1731 if (! this.values[this.index].includes(this.decimal)) {
1732 if (! this.values[this.index].replace('-', '').length) {
1733 this.values[this.index] += '0';
1734 }
1735 this.values[this.index] += this.decimal;
1736 }
1737 }
1738 },
1739 '[0#]+([.,]{1}0*#*)?%': function(v) {
1740 parseMethods['[0#]+([.,]{1}0*#*)?'].call(this, v);
1741
1742 // Adds the % only if it has a number value
1743 if (this.values[this.index].match(/[\-0-9]/g)) {
1744 if (this.values[this.index].indexOf('%') !== -1) {
1745 this.values[this.index] = this.values[this.index].replaceAll('%', '');
1746 }
1747 this.values[this.index] += '%';
1748 } else {
1749 this.values[this.index] = '';
1750 }
1751 },
1752 '#(.{1})##0?(.{1}[0#]+)?( ?;(.*)?)?': function(v) {
1753 // Process first the number
1754 parseMethods['[0#]+([.,]{1}0*#*)?'].call(this, v, true);
1755 // Create the separators
1756 let separator = this.tokens[this.index].substring(1,2);
1757
1758
1759 let currentValue = this.values[this.index];
1760 // Remove existing separators and negative sign
1761 currentValue = currentValue.replaceAll(separator, '');
1762 // Process separators
1763 let val = currentValue.split(this.decimal);
1764 if (val[0].length > 3) {
1765 let number = [];
1766 let count = 0;
1767 for (var j = val[0].length - 1; j >= 0 ; j--) {
1768 let c = val[0][j];
1769 if (c >= 0 && c <= 9) {
1770 if (count && ! (count % 3)) {
1771 number.unshift(separator);
1772 }
1773 count++;
1774 }
1775 number.unshift(c);
1776 }
1777 val[0] = number.join('');
1778 }
1779 // Reconstruct the value
1780 this.values[this.index] = val.join(this.decimal);
1781 },
1782 '[0#]+([.,]{1}0*#*)?E{1}\\+0+': function(v) {
1783 parseMethods['[0#]+([.,]{1}0*#*)?'].call(this, v);
1784 },
1785 '#{0,1}.*?\\?+\\/[0-9?]+': function (v) {
1786 if (isBlank(this.values[this.index])) {
1787 this.values[this.index] = '';
1788 }
1789
1790 const token = this.tokens[this.index]; // e.g. "# ?/?", "?/2", "# ??/16"
1791 let cur = this.values[this.index];
1792
1793 // Parse RHS of mask to decide denominator rule
1794 const rhsRaw = (token.split('/')[1] || '').replace(/\s+/g, '');
1795 const allowDen = /^\d+$/.test(rhsRaw) ? rhsRaw : /^\?+$/.test(rhsRaw) ? '?' : '?';
1796
1797 // ----- NEW: allow '-' as first char -----
1798 if (v === '-') {
1799 if (cur.length === 0) {
1800 this.values[this.index] = '-';
1801 }
1802 return; // never return false
1803 }
1804 // ----------------------------------------
1805
1806 // Only accept digits / space / slash; ignore everything else
1807 if (!(/[0-9\/ ]/.test(v))) {
1808 return;
1809 }
1810
1811 // If we already have a slash and denominator is fixed but not yet appended,
1812 // auto-complete immediately regardless of what the user typed now.
1813 const hasSlashNow = cur.includes('/');
1814 if (hasSlashNow && allowDen !== '?') {
1815 const afterSlash = cur.slice(cur.indexOf('/') + 1);
1816 if (afterSlash.length === 0) {
1817 this.values[this.index] = cur + allowDen;
1818 this.index++; // move to next token
1819 return;
1820 }
1821 }
1822
1823 // Empty -> only digits (or a leading '-' handled above)
1824 if (cur.length === 0) {
1825 if (/\d/.test(v)) this.values[this.index] = v;
1826 return;
1827 }
1828
1829 const hasSpace = cur.includes(' ');
1830 const hasSlash = cur.includes('/');
1831 const last = cur[cur.length - 1];
1832
1833 // Space rules: only one, must be before slash, must follow a digit
1834 if (v === ' ') {
1835 if (!hasSpace && !hasSlash && /\d/.test(last)) {
1836 this.values[this.index] = cur + ' ';
1837 }
1838 return;
1839 }
1840
1841 // Slash rules: only one slash, not right after a space, must follow a digit
1842 if (v === '/') {
1843 if (!hasSlash && last !== ' ' && /\d/.test(last)) {
1844 if (allowDen === '?') {
1845 this.values[this.index] = cur + '/';
1846 } else {
1847 this.values[this.index] = cur + '/' + allowDen;
1848 this.index++; // conclude this token
1849 }
1850 }
1851 return;
1852 }
1853
1854 // Digit rules
1855 if (/\d/.test(v)) {
1856 if (!hasSlash) {
1857 // Before slash: digits always fine
1858 this.values[this.index] = cur + v;
1859 return;
1860 }
1861
1862 // After slash
1863 if (allowDen === '?') {
1864 this.values[this.index] = cur + v;
1865 return;
1866 }
1867
1868 // Fixed denominator: enforce prefix and advance when complete
1869 const afterSlash = cur.slice(cur.indexOf('/') + 1);
1870 const nextDen = afterSlash + v;
1871 if (allowDen.startsWith(nextDen)) {
1872 this.values[this.index] = cur + v;
1873 if (nextDen.length === allowDen.length) {
1874 this.index++;
1875 }
1876 }
1877 }
1878 },
1879 '[a-zA-Z\\$]+': function(v) {
1880 // Token to be added to the value
1881 let word = this.tokens[this.index];
1882 // Value
1883 if (typeof(this.values[this.index]) === 'undefined') {
1884 this.values[this.index] = '';
1885 }
1886 if (v === null) {
1887 let size = this.values[this.index].length;
1888 v = word.substring(size, size+1);
1889 }
1890 // Add the value
1891 this.values[this.index] += v;
1892 // Only if caret is before the change
1893 let current = this.values[this.index];
1894 // Add token to the values
1895 if (current !== word.substring(0,current.length)) {
1896 this.values[this.index] = word;
1897 // Next token to process
1898 this.index++;
1899 return false;
1900 } else if (current === word) {
1901 // Next token to process
1902 this.index++;
1903 }
1904 },
1905 'A': function(v) {
1906 return parseMethods['[a-zA-Z\\$]+'].call(this, v);
1907 },
1908 'a': function(v) {
1909 return parseMethods['[a-zA-Z\\$]+'].call(this, v);
1910 },
1911 '.': function(v) {
1912 return parseMethods['[a-zA-Z\\$]+'].call(this, v);
1913 },
1914 '&': function(v) {
1915 if (v.match(/^[a-zA-Z ]+$/)) {
1916 this.values[this.index] = v;
1917 this.index++;
1918 }
1919 },
1920 '\\*': function() {
1921 this.values[this.index] = '';
1922 this.index++;
1923 return false;
1924 },
1925 'C': function(v) {
1926 parseMethods['&'].call(this, v);
1927 },
1928 // General Methods
1929 '0': function(v) {
1930 if (v.match(/[0-9]/g)) {
1931 this.values[this.index] = v;
1932 this.index++;
1933 }
1934 },
1935 '9': function(v) {
1936 parseMethods['0'].call(this, v);
1937 },
1938 '#': function(v) {
1939 parseMethods['0'].call(this, v);
1940 },
1941 'L': function(v) {
1942 if (v.match(/[a-zA-Z]/gi)) {
1943 this.values[this.index] = v;
1944 this.index++;
1945 }
1946 },
1947 '\\?': function(v) {
1948 if (v.match(/[1-9]/g)) {
1949 this.values[this.index] = v;
1950 this.index++;
1951 }
1952 },
1953 '@': function(v) {
1954 if (isBlank(this.values[this.index])) {
1955 this.values[this.index] = '';
1956 }
1957 this.values[this.index] += v;
1958 },
1959 '_[.\\s\\S]': function() {
1960 this.values[this.index] = ' ';
1961 this.index++;
1962 return false;
1963 },
1964 '\\(': function() {
1965 if (this.type === 'currency' && this.parenthesisForNegativeNumbers) {
1966 this.values[this.index] = '';
1967 } else {
1968 this.values[this.index] = '(';
1969 }
1970 this.index++;
1971 return false;
1972 },
1973 '\\)': function() {
1974 if (this.type === 'currency' && this.parenthesisForNegativeNumbers) {
1975 this.values[this.index] = '';
1976 } else {
1977 this.values[this.index] = ')';
1978 }
1979 this.index++;
1980 return false;
1981 },
1982 ',,M': function() {
1983 this.values[this.index] = 'M';
1984 this.index++;
1985 return false;
1986 },
1987 ',,,B': function() {
1988 this.values[this.index] = 'B';
1989 this.index++;
1990 return false;
1991 },
1992 '\\\\[.\\s\\S]': function(v) {
1993 this.values[this.index] = this.tokens[this.index].replace('\\', '');
1994 this.index++;
1995 return false;
1996 }
1997 }
1998
1999 const extractDate = function() {
2000 let v = '';
2001 if (! (this.date[0] && this.date[1] && this.date[2]) && (this.date[3] || this.date[4])) {
2002 if (this.mask.toLowerCase().indexOf('[h]') !== -1) {
2003 v = parseInt(this.date[3]);
2004 } else {
2005 let h = parseInt(this.date[3]);
2006 if (h < 13 && this.values.indexOf('PM') !== -1) {
2007 v = (h+12) % 24;
2008 } else {
2009 v = h % 24;
2010 }
2011 }
2012 if (this.date[4]) {
2013 v += parseFloat(this.date[4] / 60);
2014 }
2015 if (this.date[5]) {
2016 v += parseFloat(this.date[5] / 3600);
2017 }
2018 v /= 24;
2019 } else if (this.date[0] || this.date[1] || this.date[2] || this.date[3] || this.date[4] || this.date[5]) {
2020 if (this.date[0] && this.date[1] && ! this.date[2]) {
2021 this.date[2] = 1;
2022 }
2023 var t = Helpers.now(this.date);
2024 v = Helpers.dateToNum(t);
2025 }
2026
2027 if (isNaN(v)) {
2028 v = '';
2029 }
2030
2031 return v;
2032 }
2033
2034 // Types TODO: Generate types so we can garantee that text,scientific, numeric,percentage, current are not duplicates. If they are, it will be general or broken.
2035
2036 const getTokens = function(str) {
2037 // Check cache first - direct access, undefined check is fast
2038 let result = tokensCache[str];
2039 if (result !== undefined) {
2040 return result;
2041 }
2042
2043 allExpressionsRegex.lastIndex = 0; // Reset for global regex
2044 result = str.match(allExpressionsRegex);
2045 tokensCache[str] = result;
2046 return result;
2047 }
2048
2049 /**
2050 * Get the method of one given token
2051 */
2052 const getMethod = function(str, temporary) {
2053 str = str.toString().toUpperCase();
2054
2055 // Check cache first - direct access, undefined check is fast
2056 let cached = methodCache[str];
2057 if (cached !== undefined) {
2058 return cached;
2059 }
2060
2061 // Check for datetime mask
2062 const datetime = temporary.every(t => t.type === 'datetime' || t.type === 'general' || t.type === 'escape');
2063
2064 // Use priority order for faster matching with pre-compiled regexes
2065 for (const type of tokenPriority) {
2066 if (!datetime && type === 'datetime') continue;
2067
2068 for (const compiled of compiledTokens[type]) {
2069 if (compiled.regex.test(str)) {
2070 const result = { type: type, method: compiled.method };
2071 methodCache[str] = result;
2072 return result;
2073 }
2074 }
2075 }
2076 methodCache[str] = null;
2077 return null;
2078 }
2079
2080 const fixMinuteToken = function(t) {
2081 const len = t.length;
2082 for (let i = 0; i < len; i++) {
2083 const token = t[i];
2084 if (token === 'M' || token === 'MM') {
2085 // Check if this M is a minute (near H or S) rather than month
2086 let isMinute = false;
2087
2088 // Check previous 2 tokens for H (hour indicator)
2089 if (i > 0) {
2090 const prev1 = t[i - 1];
2091 // Use includes for fast check - covers H, HH, HH24, HH12, [H], etc
2092 if (prev1 && prev1.includes('H')) {
2093 isMinute = true;
2094 } else if (i > 1) {
2095 const prev2 = t[i - 2];
2096 if (prev2 && prev2.includes('H')) {
2097 isMinute = true;
2098 }
2099 }
2100 }
2101
2102 // Check next 2 tokens for S (seconds indicator) if not already determined
2103 if (!isMinute && i < len - 1) {
2104 const next1 = t[i + 1];
2105 // Use includes for fast check - covers S, SS, MS, etc
2106 if (next1 && next1.includes('S')) {
2107 isMinute = true;
2108 } else if (i < len - 2) {
2109 const next2 = t[i + 2];
2110 if (next2 && next2.includes('S')) {
2111 isMinute = true;
2112 }
2113 }
2114 }
2115
2116 if (isMinute) {
2117 t[i] = token === 'M' ? 'I' : 'MI';
2118 }
2119 }
2120 }
2121 }
2122
2123 /**
2124 * Identify each method for each token
2125 */
2126 const getMethodsFromTokens = function(t) {
2127 // Uppercase
2128 t = t.map(v => {
2129 return v.toString().toUpperCase();
2130 });
2131
2132 // Compatibility with Excel
2133 fixMinuteToken(t);
2134
2135 let result = [];
2136 for (let i = 0; i < t.length; i++) {
2137 var m = getMethod(t[i], result);
2138 if (m) {
2139 result.push(m);
2140 } else {
2141 result.push(null);
2142 }
2143 }
2144 return result;
2145 }
2146
2147 const getMethodByPosition = function(control) {
2148 let methodName;
2149 if (control.methods[control.index] && typeof(control.value[control.position]) !== 'undefined') {
2150 methodName = control.methods[control.index].method;
2151 }
2152
2153 let m = parseMethods[methodName];
2154 if (typeof(m) === 'function') {
2155 return m;
2156 }
2157
2158 return false;
2159 }
2160
2161 const processPaddingZeros = function(token, value, decimal) {
2162 if (! value) {
2163 return value;
2164 }
2165 let m = token.split(decimal);
2166 let desiredNumOfPaddingZeros = m[0].match(/[0]+/g);
2167 if (desiredNumOfPaddingZeros && desiredNumOfPaddingZeros[0]) {
2168 desiredNumOfPaddingZeros = desiredNumOfPaddingZeros[0].length
2169 let v = value.toString().split(decimal);
2170 let len = v[0].length;
2171 if (desiredNumOfPaddingZeros > len) {
2172 v[0] = v[0].padStart(desiredNumOfPaddingZeros, '0');
2173 return v.join(decimal);
2174 }
2175 }
2176 }
2177
2178 const processNumOfPaddingZeros = function(control) {
2179 let negativeSignal = false;
2180 control.methods.forEach((method, k) => {
2181 if (method) {
2182 if (method.type === 'numeric' || method.type === 'percentage' || method.type === 'scientific') {
2183 let ret = processPaddingZeros(control.tokens[k], control.values[k], control.decimal);
2184 if (ret) {
2185 control.values[k] = ret;
2186 }
2187 }
2188
2189 if (isNumeric(control.type) && control.parenthesisForNegativeNumbers === true) {
2190 if (isNumeric(method.type)) {
2191 if (control.values[k] && control.values[k].toString().includes('-')) {
2192 control.values[k] = control.values[k].replace('-', '');
2193
2194 negativeSignal = true;
2195 }
2196 }
2197 }
2198 }
2199 });
2200
2201
2202 if (isNumeric(control.type) && control.parenthesisForNegativeNumbers === true && negativeSignal) {
2203 control.methods.forEach((method, k) => {
2204 if (! control.values[k] && control.tokens[k] === '(') {
2205 control.values[k] = '(';
2206 } else if (! control.values[k] && control.tokens[k] === ')') {
2207 control.values[k] = ')';
2208 }
2209 });
2210 }
2211 }
2212
2213 const getValue = function(control) {
2214 let value = control.values.join('');
2215 if (isNumeric(control.type)) {
2216 if (value.indexOf('--') !== false) {
2217 value = value.replace('--', '-');
2218 }
2219 if (Number(control.raw) < 0 && value.includes('-')) {
2220 value = '-' + value.replace('-', '');
2221 }
2222 }
2223 return value;
2224 }
2225
2226 const inputIsANumber = function(num) {
2227 if (typeof(num) === 'string') {
2228 num = num.trim();
2229 }
2230 return !isNaN(num) && num !== null && num !== '';
2231 }
2232
2233 const getType = function(control) {
2234 // Mask type
2235 let type = 'general';
2236 // Process other types
2237 for (var i = 0; i < control.methods.length; i++) {
2238 let m = control.methods[i];
2239 if (m) {
2240 let t = m.type;
2241 if (t !== 'general' && t !== 'escape' && t !== type) {
2242 if (type === 'general') {
2243 type = t;
2244 } else {
2245 type = 'general';
2246 break;
2247 }
2248 }
2249 }
2250 }
2251 return type;
2252 }
2253
2254 const isNumber = function(num) {
2255 if (typeof(num) === 'string') {
2256 num = num.trim();
2257 }
2258 return !isNaN(num) && num !== null && num !== '';
2259 }
2260
2261 // TODO, get negative mask automatically based on the input sign?
2262
2263 const getConfig = function(config, value) {
2264 // Internal default control of the mask system
2265 const control = {
2266 // Mask options
2267 options: {},
2268 // New values for each token found
2269 values: [],
2270 // Token position
2271 index: 0,
2272 // Character position
2273 position: 0,
2274 // Date raw values
2275 date: [0,0,0,0,0,0],
2276 // Raw number for the numeric values
2277 number: 0,
2278 }
2279
2280 if (typeof(value) === 'undefined' || value === null) {
2281 value = '';
2282 }
2283
2284 // Value to be masked
2285 control.value = value.toString();
2286 control.raw = value;
2287
2288
2289 // Options defined by the user
2290 if (typeof(config) == 'string') {
2291 // Mask
2292 control.mask = config;
2293 } else if (config) {
2294 // Mask
2295 let k = Object.keys(config);
2296 for (var i = 0; i < k.length; i++) {
2297 control[k[i]] = config[k[i]];
2298 }
2299 }
2300
2301 // Controls of Excel that should be ignored
2302 let mask = control.mask;
2303 if (mask) {
2304 if (mask.indexOf(';') !== -1) {
2305 let d = mask.split(';');
2306
2307 // Mask
2308 mask = d[0];
2309
2310 if (typeof (value) === 'number' || isNumber(value)) {
2311 if (Number(value) < 0 && d[1]) {
2312 mask = d[1];
2313 } else if (Number(value) === 0 && d[2]) {
2314 mask = d[2];
2315 } else {
2316 mask = d[0];
2317 }
2318 } else {
2319 if (typeof(d[3]) !== 'undefined') {
2320 mask = d[3];
2321 }
2322 }
2323 }
2324
2325 // Transform Excel locale patterns (e.g., [$$-409]#,##0.00) - only if pattern exists
2326 if (mask.indexOf('[$') !== -1) {
2327 mask = transformExcelLocaleMask(mask);
2328 }
2329
2330 // Cleaning the mask
2331 mask = cleanMask(mask, control);
2332 // Get only the first mask for now and remove
2333 control.mask = mask;
2334 // Get tokens which are the methods for parsing
2335 let tokens = control.tokens = getTokens(mask);
2336 // Get methods from the tokens
2337 control.methods = getMethodsFromTokens(tokens);
2338 // Type
2339 control.type = getType(control);
2340 }
2341
2342 // Decimal only for numbers
2343 if (isNumeric(control.type) || control.locale) {
2344 control.decimal = getDecimal.call(control);
2345 }
2346
2347 return control;
2348 }
2349
2350 const toPlainString = function(num) {
2351 // Convert number to string if it isn't already
2352 num = String(num);
2353
2354 // If it's not in exponential form, return as-is
2355 if (!/e/i.test(num)) return num;
2356
2357 // Decompose scientific notation
2358 const [coefficient, exponent] = num.toLowerCase().split('e');
2359 const exp = parseInt(exponent, 10);
2360
2361 // Handle sign
2362 const sign = coefficient[0] === '-' ? '-' : '';
2363 const [intPart, fracPart = ''] = coefficient.replace('-', '').split('.');
2364
2365 const digits = intPart + fracPart;
2366 const decimalPos = intPart.length;
2367
2368 let newPos = decimalPos + exp;
2369
2370 if (newPos <= 0) {
2371 // Decimal point moves left
2372 return sign + '0.' + '0'.repeat(-newPos) + digits;
2373 } else if (newPos >= digits.length) {
2374 // Decimal point moves right, add trailing zeros
2375 return sign + digits + '0'.repeat(newPos - digits.length);
2376 } else {
2377 // Decimal point moves into the number
2378 return sign + digits.slice(0, newPos) + '.' + digits.slice(newPos);
2379 }
2380 };
2381
2382 const adjustNumberOfDecimalPlaces = function(config, value) {
2383 let temp = value;
2384 let mask = config.mask;
2385
2386 if (config.type === 'scientific') {
2387 // Scientific notation handling
2388 mask = config.mask.toUpperCase().split('E')[0];
2389
2390 let numOfDecimalPlaces = mask.split(config.decimal);
2391 // Handle masks without decimal (e.g., '0E+00')
2392 if (numOfDecimalPlaces[1]) {
2393 numOfDecimalPlaces = numOfDecimalPlaces[1].match(/[0#]+/g);
2394 numOfDecimalPlaces = numOfDecimalPlaces[0]?.length ?? 0;
2395 } else {
2396 numOfDecimalPlaces = 0;
2397 }
2398 temp = temp.toExponential(numOfDecimalPlaces);
2399 // Split by 'e' to handle both positive (e+) and negative (e-) exponents
2400 let expo = temp.toString().split('e');
2401 // Keep coefficient as string to preserve decimal places (e.g., '1.00' not 1)
2402 temp = expo[0];
2403
2404 // Process padding zeros for coefficient
2405 let ret = processPaddingZeros(mask, temp, config.decimal);
2406 if (ret) {
2407 temp = ret;
2408 }
2409 expo[0] = temp;
2410
2411 // Handle both E+ and E- in mask for exponent
2412 mask = config.mask.toUpperCase().split(/E[+-]?/)[1];
2413 ret = processPaddingZeros(mask, expo[1]?.replace(/^[+-]/, ''), config.decimal);
2414 if (ret) {
2415 // Preserve the sign from the original exponent
2416 let sign = expo[1]?.charAt(0);
2417 expo[1] = (sign === '-' ? '-' : '+') + ret;
2418 }
2419
2420 temp = expo.join('e');
2421 } else {
2422 // Non-scientific decimal adjustment
2423 if (mask.indexOf(config.decimal) === -1) {
2424 // No decimal places
2425 if (! Number.isInteger(temp)) {
2426 temp = temp.toFixed(0);
2427 }
2428 } else {
2429 // Length of the decimal
2430 let mandatoryDecimalPlaces = mask.split(config.decimal);
2431 mandatoryDecimalPlaces = mandatoryDecimalPlaces[1].match(/0+/g);
2432 if (mandatoryDecimalPlaces) {
2433 mandatoryDecimalPlaces = mandatoryDecimalPlaces[0].length;
2434 } else {
2435 mandatoryDecimalPlaces = 0;
2436 }
2437
2438 // Amount of decimal (use original value to check decimal separator)
2439 let valueStr = value.toString();
2440 let numOfDecimalPlaces = valueStr.split(valueStr.includes('.') ? '.' : (config.decimal || '.'))
2441 numOfDecimalPlaces = numOfDecimalPlaces[1]?.length ?? 0;
2442 // Necessary adjustment
2443 let necessaryAdjustment = 0;
2444 if (numOfDecimalPlaces < mandatoryDecimalPlaces) {
2445 necessaryAdjustment = mandatoryDecimalPlaces;
2446 } else {
2447 // Optional
2448 let optionalDecimalPlaces = mask.split(config.decimal);
2449 optionalDecimalPlaces = optionalDecimalPlaces[1].match(/[0#]+/g);
2450 if (optionalDecimalPlaces) {
2451 optionalDecimalPlaces = optionalDecimalPlaces[0].length;
2452 if (numOfDecimalPlaces > optionalDecimalPlaces) {
2453 necessaryAdjustment = optionalDecimalPlaces;
2454 }
2455 }
2456 }
2457 // Adjust decimal numbers if applicable
2458 if (necessaryAdjustment) {
2459 let t = temp.toFixed(necessaryAdjustment);
2460 let n = temp.toString().split('.');
2461 let fraction = n[1];
2462 if (fraction && fraction.length > necessaryAdjustment && fraction[fraction.length - 1] === '5') {
2463 t = parseFloat(n[0] + '.' + fraction + '1').toFixed(necessaryAdjustment);
2464 }
2465 temp = t;
2466 }
2467 }
2468 }
2469
2470 return temp;
2471 }
2472
2473 const formatFraction = function(value, mask) {
2474 let maxDenominator;
2475 let fixedDenominator = null;
2476 let allowWholeNumber = true;
2477
2478 // Check for fixed denominator like # ?/8 or ?/8
2479 const fixed = mask.match(/\/(\d+)/);
2480 if (fixed) {
2481 fixedDenominator = parseInt(fixed[1], 10);
2482 maxDenominator = fixedDenominator;
2483 } else {
2484 // Determine based on question marks in mask
2485 const match = mask.match(/\?\/(\?+)/);
2486 if (match) {
2487 maxDenominator = Math.pow(10, match[1].length) - 1;
2488 } else {
2489 maxDenominator = 9; // Default for # ?/? or ?/?
2490 }
2491 }
2492 // Check if mask allows whole number (e.g., ?/? or ?/8 implies no whole number)
2493 allowWholeNumber = mask.includes('#');
2494
2495 // If we have a fixed denominator, use it exactly (don't simplify)
2496 if (fixedDenominator) {
2497 const isNegative = value < 0;
2498 const absValue = Math.abs(value);
2499 const numerator = Math.round(absValue * fixedDenominator);
2500
2501 // For masks like ?/8, always output as pure fraction (no whole number)
2502 if (!allowWholeNumber) {
2503 return isNegative ? `-${numerator}/${fixedDenominator}` : `${numerator}/${fixedDenominator}`;
2504 }
2505
2506 // For masks like # ?/8, allow whole number
2507 const whole = Math.floor(numerator / fixedDenominator);
2508 const remainder = numerator % fixedDenominator;
2509 if (remainder === 0) {
2510 return isNegative ? `-${whole}` : `${whole}`;
2511 }
2512 if (whole === 0) {
2513 return isNegative ? `-${numerator}/${fixedDenominator}` : `${numerator}/${fixedDenominator}`;
2514 }
2515 return isNegative ? `-${whole} ${remainder}/${fixedDenominator}` : `${whole} ${remainder}/${fixedDenominator}`;
2516 }
2517
2518 // Use continued fractions algorithm for better approximation
2519 function continuedFraction(value, maxDenom) {
2520 if (value === 0) return [0, 1];
2521 let sign = value < 0 ? -1 : 1;
2522 value = Math.abs(value);
2523 let whole = Math.floor(value);
2524 let frac = value - whole;
2525 if (frac === 0) return [sign * whole, 1];
2526
2527 let h1 = 1, h2 = 0;
2528 let k1 = 0, k2 = 1;
2529 let x = frac;
2530 while (k1 <= maxDenom) {
2531 let a = Math.floor(x);
2532 let h0 = a * h1 + h2;
2533 let k0 = a * k1 + k2;
2534 if (k0 > maxDenom) break;
2535 h2 = h1; h1 = h0;
2536 k2 = k1; k1 = k0;
2537 if (Math.abs(x - a) < 1e-10) break;
2538 x = 1 / (x - a);
2539 }
2540
2541 // Add the whole part back only if allowed
2542 let finalNum = sign * (allowWholeNumber ? whole * k1 + h1 : Math.round(value * k1));
2543 let finalDen = k1;
2544 return [finalNum, finalDen];
2545 }
2546
2547 const [numerator, denominator] = continuedFraction(value, maxDenominator);
2548
2549 // Handle the result
2550 const isNegative = numerator < 0;
2551 const absNumerator = Math.abs(numerator);
2552 const whole = allowWholeNumber ? Math.floor(absNumerator / denominator) : 0;
2553 const remainder = absNumerator % denominator;
2554 const sign = isNegative ? '-' : '';
2555
2556 if (remainder === 0) {
2557 return `${sign}${whole || 0}`;
2558 }
2559 if (whole === 0 || !allowWholeNumber) {
2560 return `${sign}${absNumerator}/${denominator}`;
2561 }
2562 return `${sign}${whole} ${remainder}/${denominator}`;
2563 }
2564
2565 const extractDateAndTime = function(value) {
2566 value = value.toString().substring(0,19);
2567 let splitStr = (value.indexOf('T') !== -1) ? 'T' : ' ';
2568 value = value.split(splitStr);
2569
2570 let y = null;
2571 let m = null;
2572 let d = null;
2573 let h = '0';
2574 let i = '0';
2575 let s = '0';
2576
2577 if (! value[1]) {
2578 if (value[0].indexOf(':') !== -1) {
2579 value[0] = value[0].split(':');
2580 h = value[0][0];
2581 i = value[0][1];
2582 s = value[0][2];
2583 } else {
2584 value[0] = value[0].split('-');
2585 y = value[0][0];
2586 m = value[0][1];
2587 d = value[0][2];
2588 }
2589 } else {
2590 value[0] = value[0].split('-');
2591 y = value[0][0];
2592 m = value[0][1];
2593 d = value[0][2];
2594
2595 value[1] = value[1].split(':');
2596 h = value[1][0];
2597 i = value[1][1];
2598 s = value[1][2];
2599 }
2600
2601 return [y,m,d,h,i,s];
2602 }
2603
2604 const format = function(str, config) {
2605 // Extract numeric value from formatted or unformatted string (e.g., "₹3.00" -> 3)
2606 // Using same logic as ParseValue to handle already-formatted strings
2607 let numericValue;
2608 const decimal = config.decimal || '.';
2609 let v = String(str).split(decimal);
2610
2611 // Detect negative sign
2612 let signal = v[0].includes('-');
2613
2614 // Extract digits only
2615 v[0] = v[0].match(/[0-9]+/g);
2616 if (v[0]) {
2617 if (signal) v[0].unshift('-');
2618 v[0] = v[0].join('');
2619 } else {
2620 v[0] = signal ? '-0' : '0';
2621 }
2622
2623 if (v[1] !== undefined) {
2624 v[1] = v[1].match(/[0-9]+/g);
2625 v[1] = v[1] ? v[1].join('') : '';
2626 }
2627
2628 // Convert to number
2629 numericValue = v[0] || v[1] ? parseFloat(v.join('.')) : 0;
2630
2631 let ret = new Intl.NumberFormat(config.locale, config.options || {}).format(numericValue);
2632
2633 config.values.push(ret);
2634 }
2635
2636 const Component = function(str, config, returnObject) {
2637 // Get configuration
2638 const control = getConfig(config, str);
2639
2640 if (control.locale) {
2641 format(str, control);
2642 } else if (control.mask) {
2643 // Walk every character on the value
2644 let method;
2645 while (method = getMethodByPosition(control)) {
2646 let char = control.value[control.position];
2647 if (char === hiddenCaret) {
2648 control.caret = {
2649 index: control.index,
2650 position: control.values[control.index]?.length ?? 0,
2651 }
2652 control.position++;
2653 } else {
2654 // Get the method name to handle the current token
2655 let ret = method.call(control, char);
2656 // Next position
2657 if (ret !== false) {
2658 control.position++;
2659 }
2660 }
2661 }
2662
2663 // Move index
2664 if (control.methods[control.index]) {
2665 let type = control.methods[control.index].type;
2666 if (isNumeric(type) && control.methods[++control.index]) {
2667 let next;
2668 while (next = control.methods[control.index]) {
2669 if (control.methods[control.index].type === 'general') {
2670 let method = control.methods[control.index].method;
2671 if (method && typeof(parseMethods[method]) === 'function') {
2672 parseMethods[method].call(control, null);
2673 }
2674 } else {
2675 break;
2676 }
2677 }
2678 }
2679 }
2680 }
2681 if (control.caret) {
2682 let index = control.caret.index;
2683 let position = control.caret.position;
2684 let value = control.values[index] ?? '';
2685 // Re-apply the caret to the original position
2686 control.values[index] = value.substring(0, position) + hiddenCaret + value.substring(position);
2687 }
2688
2689 control.value = getValue(control);
2690
2691 if (returnObject) {
2692 return control;
2693 } else {
2694 return control.value;
2695 }
2696 }
2697
2698 // Helper: Compare rendered value to original input
2699 const testMask = function(mask, value, original) {
2700 const rendered = Component.render(value, { mask }, true);
2701 return rendered.replace(/\s/g, '') === original.replace(/\s/g, '');
2702 }
2703
2704 const autoCastingFractions = function(value) {
2705 const fractionPattern = /^\s*(-?\d+\s+)?(-?\d+)\/(\d+)\s*$/;
2706 const fractionMatch = value.match(fractionPattern);
2707 if (fractionMatch) {
2708 const sign = value.trim().startsWith('-') ? -1 : 1;
2709 const whole = fractionMatch[1] ? Math.abs(parseInt(fractionMatch[1])) : 0;
2710 const numerator = Math.abs(parseInt(fractionMatch[2]));
2711 const denominator = parseInt(fractionMatch[3]);
2712
2713 if (denominator === 0) return null;
2714
2715 const decimalValue = sign * (whole + (numerator / denominator));
2716
2717 // Determine the mask
2718 let mask;
2719 if ([2, 4, 8, 16, 32].includes(denominator)) {
2720 mask = whole !== 0 ? `# ?/${denominator}` : `?/${denominator}`;
2721 } else if (denominator <= 9) {
2722 mask = whole !== 0 ? '# ?/?' : '?/?';
2723 } else {
2724 mask = whole !== 0 ? '# ??/??' : '??/??';
2725 }
2726
2727 if (testMask(mask, decimalValue, value.trim())) {
2728 return { mask, value: decimalValue, type: 'fraction', category: 'fraction' };
2729 }
2730 }
2731 return null;
2732 }
2733
2734 const autoCastingPercent = function(value) {
2735 const percentPattern = /^\s*([+-]?\d+(?:[.,]\d+)?)%\s*$/;
2736 const percentMatch = value.match(percentPattern);
2737 if (percentMatch) {
2738 const rawNumber = percentMatch[1].replace(',', '.');
2739 const decimalValue = parseFloat(rawNumber) / 100;
2740
2741 const decimalPart = rawNumber.split('.')[1];
2742 const decimalPlaces = decimalPart ? decimalPart.length : 0;
2743 const mask = decimalPlaces > 0 ? `0.${'0'.repeat(decimalPlaces)}%` : '0%';
2744
2745 if (testMask(mask, decimalValue, value.trim())) {
2746 return { mask: mask, value: decimalValue, type: 'percent', category: 'numeric' };
2747 }
2748 }
2749 return null;
2750 }
2751
2752 const autoCastingDates = function(value) {
2753 if (!value || typeof value !== 'string') {
2754 return null;
2755 }
2756
2757 // Smart pattern detection based on the structure of the string
2758
2759 // 1. Analyze the structure to determine possible formats
2760 const analyzeStructure = function(str) {
2761 const patterns = [];
2762
2763 // Check for date with forward slashes: XX/XX/XXXX or XX/XX/XX
2764 if (str.match(/^\d{1,2}\/\d{1,2}\/\d{2,4}$/)) {
2765 const parts = str.split('/');
2766 const p1 = parseInt(parts[0]);
2767 const p2 = parseInt(parts[1]);
2768 const p3 = parseInt(parts[2]);
2769
2770 // Determine likely format based on values
2771 if (p1 <= 12 && p2 <= 31 && p2 > 12) {
2772 // Likely mm/dd/yyyy
2773 patterns.push('mm/dd/yyyy', 'mm/dd/yy', 'm/d/yyyy', 'm/d/yy');
2774 } else if (p1 <= 31 && p2 <= 12 && p1 > 12) {
2775 // Likely dd/mm/yyyy
2776 patterns.push('dd/mm/yyyy', 'dd/mm/yy', 'd/m/yyyy', 'd/m/yy');
2777 } else if (p1 <= 12 && p2 <= 12) {
2778 // Ambiguous - could be either, use locale preference
2779 if (userLocale.startsWith('en-US')) {
2780 patterns.push('mm/dd/yyyy', 'dd/mm/yyyy', 'mm/dd/yy', 'dd/mm/yy');
2781 } else {
2782 patterns.push('dd/mm/yyyy', 'mm/dd/yyyy', 'dd/mm/yy', 'mm/dd/yy');
2783 }
2784 }
2785
2786 // Add variations
2787 if (p3 < 100) {
2788 patterns.push('dd/mm/yy', 'mm/dd/yy', 'd/m/yy', 'm/d/yy');
2789 } else {
2790 patterns.push('dd/mm/yyyy', 'mm/dd/yyyy', 'd/m/yyyy', 'm/d/yyyy');
2791 }
2792 }
2793
2794 // Check for date with dashes: XX-XX-XXXX
2795 else if (str.match(/^\d{1,2}-\d{1,2}-\d{2,4}$/)) {
2796 const parts = str.split('-');
2797 const p1 = parseInt(parts[0]);
2798 const p2 = parseInt(parts[1]);
2799
2800 if (p1 <= 12 && p2 <= 31 && p2 > 12) {
2801 patterns.push('mm-dd-yyyy', 'mm-dd-yy', 'm-d-yyyy', 'm-d-yy');
2802 } else if (p1 <= 31 && p2 <= 12 && p1 > 12) {
2803 patterns.push('dd-mm-yyyy', 'dd-mm-yy', 'd-m-yyyy', 'd-m-yy');
2804 } else {
2805 patterns.push('dd-mm-yyyy', 'mm-dd-yyyy', 'dd-mm-yy', 'mm-dd-yy');
2806 }
2807 }
2808
2809 // Check for ISO format: YYYY-MM-DD
2810 else if (str.match(/^\d{4}-\d{1,2}-\d{1,2}$/)) {
2811 patterns.push('yyyy-mm-dd', 'yyyy-m-d');
2812 }
2813
2814 // Check for format: YYYY/MM/DD
2815 else if (str.match(/^\d{4}\/\d{1,2}\/\d{1,2}$/)) {
2816 patterns.push('yyyy/mm/dd', 'yyyy/m/d');
2817 }
2818
2819 // Check for dates with month names
2820 else if (str.match(/\b(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i)) {
2821 // DD Mon YYYY or DD Month YYYY
2822 if (str.match(/^\d{1,2}\s+\w+\s+\d{2,4}$/i)) {
2823 patterns.push('dd mmm yyyy', 'dd mmmm yyyy', 'd mmm yyyy', 'd mmmm yyyy',
2824 'dd mmm yy', 'dd mmmm yy', 'd mmm yy', 'd mmmm yy');
2825 }
2826 // Mon DD, YYYY or Month DD, YYYY
2827 else if (str.match(/^\w+\s+\d{1,2},?\s+\d{2,4}$/i)) {
2828 patterns.push('mmm dd, yyyy', 'mmmm dd, yyyy', 'mmm d, yyyy', 'mmmm d, yyyy',
2829 'mmm dd yyyy', 'mmmm dd yyyy', 'mmm d yyyy', 'mmmm d yyyy');
2830 }
2831 // DD-Mon-YYYY
2832 else if (str.match(/^\d{1,2}-\w+-\d{2,4}$/i)) {
2833 patterns.push('dd-mmm-yyyy', 'dd-mmmm-yyyy', 'd-mmm-yyyy', 'd-mmmm-yyyy',
2834 'dd-mmm-yy', 'dd-mmmm-yy', 'd-mmm-yy', 'd-mmmm-yy');
2835 }
2836 }
2837
2838 // Check for weekday formats
2839 else if (str.match(/^(mon|tue|wed|thu|fri|sat|sun)/i)) {
2840 if (str.match(/^\w+,\s+\d{1,2}\s+\w+\s+\d{4}$/i)) {
2841 patterns.push('ddd, dd mmm yyyy', 'ddd, d mmm yyyy',
2842 'dddd, dd mmmm yyyy', 'dddd, d mmmm yyyy');
2843 }
2844 }
2845
2846 // Check for datetime formats
2847 else if (str.includes(' ') && str.match(/\d{1,2}:\d{2}/)) {
2848 const parts = str.split(' ');
2849 if (parts.length >= 2) {
2850 const datePart = parts[0];
2851 const timePart = parts.slice(1).join(' ');
2852
2853 // Determine date format
2854 let dateMasks = [];
2855 if (datePart.includes('/')) {
2856 dateMasks = ['dd/mm/yyyy', 'mm/dd/yyyy', 'd/m/yyyy', 'm/d/yyyy'];
2857 } else if (datePart.includes('-')) {
2858 if (datePart.match(/^\d{4}-/)) {
2859 dateMasks = ['yyyy-mm-dd', 'yyyy-m-d'];
2860 } else {
2861 dateMasks = ['dd-mm-yyyy', 'mm-dd-yyyy', 'd-m-yyyy', 'm-d-yyyy'];
2862 }
2863 }
2864
2865 // Determine time format
2866 let timeMasks = [];
2867 if (timePart.match(/\d{1,2}:\d{2}:\d{2}/)) {
2868 timeMasks = ['hh:mm:ss', 'h:mm:ss'];
2869 } else {
2870 timeMasks = ['hh:mm', 'h:mm'];
2871 }
2872
2873 // Add AM/PM variants if present
2874 if (timePart.match(/[ap]m/i)) {
2875 timeMasks = timeMasks.map(t => t + ' am/pm');
2876 }
2877
2878 // Combine date and time masks
2879 for (const dateMask of dateMasks) {
2880 for (const timeMask of timeMasks) {
2881 patterns.push(`${dateMask} ${timeMask}`);
2882 }
2883 }
2884 }
2885 }
2886
2887 // Check for time-only formats
2888 else if (str.match(/^\d{1,2}:\d{2}(:\d{2})?(\s*(am|pm))?$/i)) {
2889 if (str.match(/:\d{2}:\d{2}/)) {
2890 patterns.push('hh:mm:ss', 'h:mm:ss');
2891 if (str.match(/[ap]m/i)) {
2892 patterns.push('hh:mm:ss am/pm', 'h:mm:ss am/pm');
2893 }
2894 } else {
2895 patterns.push('hh:mm', 'h:mm');
2896 if (str.match(/[ap]m/i)) {
2897 patterns.push('hh:mm am/pm', 'h:mm am/pm');
2898 }
2899 }
2900 }
2901
2902 // Check for extended hour format [h]:mm:ss
2903 else if (str.match(/^\[?\d+\]?:\d{2}:\d{2}$/)) {
2904 patterns.push('[h]:mm:ss');
2905 }
2906
2907 return [...new Set(patterns)]; // Remove duplicates
2908 };
2909
2910 // Get candidate masks based on the string structure
2911 const candidateMasks = analyzeStructure(value);
2912
2913 // If no patterns detected, try some common formats as fallback
2914 if (candidateMasks.length === 0) {
2915 if (userLocale.startsWith('en-US')) {
2916 candidateMasks.push(
2917 'mm/dd/yyyy', 'mm-dd-yyyy', 'yyyy-mm-dd',
2918 'mm/dd/yy', 'mm-dd-yy',
2919 'hh:mm:ss', 'hh:mm', 'h:mm am/pm'
2920 );
2921 } else {
2922 candidateMasks.push(
2923 'dd/mm/yyyy', 'dd-mm-yyyy', 'yyyy-mm-dd',
2924 'dd/mm/yy', 'dd-mm-yy',
2925 'hh:mm:ss', 'hh:mm', 'h:mm'
2926 );
2927 }
2928 }
2929
2930 // Try each candidate mask
2931 for (const mask of candidateMasks) {
2932 try {
2933 // Use Component.extractDateFromString to parse the date
2934 const isoDate = Component.extractDateFromString(value, mask);
2935
2936 if (isoDate && isoDate !== '') {
2937 // Parse the ISO date string to components
2938 const parts = isoDate.split(' ');
2939 const dateParts = parts[0].split('-');
2940 const timeParts = parts[1] ? parts[1].split(':') : ['0', '0', '0'];
2941
2942 const year = parseInt(dateParts[0]);
2943 const month = parseInt(dateParts[1]);
2944 const day = parseInt(dateParts[2]);
2945 const hour = parseInt(timeParts[0]);
2946 const minute = parseInt(timeParts[1]);
2947 const second = parseInt(timeParts[2]);
2948
2949 // Validate the date components
2950 if (year > 0 && month >= 1 && month <= 12 && day >= 1 && day <= 31 &&
2951 hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60) {
2952
2953 // Convert to Excel serial number
2954 const excelNumber = Helpers.dateToNum(isoDate);
2955
2956 // Verify by rendering back
2957 const rendered = Component.render(excelNumber, { mask: mask }, true);
2958
2959 // Case-insensitive comparison for month names
2960 if (rendered.toLowerCase() === value.toLowerCase()) {
2961 return {
2962 mask: mask,
2963 value: excelNumber,
2964 type: 'date',
2965 category: 'datetime'
2966 };
2967 }
2968 }
2969 }
2970 } catch (e) {
2971 }
2972 }
2973
2974 // No matching format found
2975 return null;
2976 };
2977
2978 const autoCastingCurrency = function (input, filterDecimal) {
2979 if (typeof input !== 'string') return null;
2980
2981 const str = input.trim();
2982 if (!str) return null;
2983
2984 const len = str.length;
2985 let isNegative = false;
2986 let hasParens = false;
2987 let symbol = '';
2988 let numericPart = '';
2989 let letterBuffer = '';
2990 let firstCommaPos = -1;
2991 let lastCommaPos = -1;
2992 let firstDotPos = -1;
2993 let lastDotPos = -1;
2994 let commaCount = 0;
2995 let dotCount = 0;
2996 let hasInvalidChars = false;
2997 let hasCurrencySymbol = false;
2998
2999 // Single pass through the string
3000 for (let i = 0; i < len; i++) {
3001 const char = str[i];
3002
3003 // Check for negative signs and parentheses
3004 if (char === '-' && !numericPart) {
3005 isNegative = true;
3006 continue;
3007 }
3008 if (char === '(') {
3009 hasParens = true;
3010 isNegative = true;
3011 continue;
3012 }
3013 if (char === ')') continue;
3014
3015 // Skip whitespace
3016 if (char === ' ' || char === '\t') {
3017 if (letterBuffer) {
3018 letterBuffer += char;
3019 }
3020 continue;
3021 }
3022
3023 // Currency symbols
3024 if (char === '$' || char === '€' || char === '£' || char === '¥' ||
3025 char === '₹' || char === '₽' || char === '₩' || char === '₫' || char === '¢') {
3026 hasCurrencySymbol = true;
3027 // Validate letter buffer: max 2 letters before symbol
3028 const trimmedBuffer = letterBuffer.trim();
3029 if (trimmedBuffer.length > 2) {
3030 return null;
3031 }
3032 if (letterBuffer) {
3033 symbol = letterBuffer + char;
3034 letterBuffer = '';
3035 } else {
3036 symbol = char;
3037 }
3038 // Check if next char is a space to include it in symbol
3039 if (i + 1 < len && (str[i + 1] === ' ' || str[i + 1] === '\t')) {
3040 symbol += ' ';
3041 i++; // Skip the space
3042 }
3043 continue;
3044 }
3045
3046 // Letters (only valid BEFORE currency symbol, max 2 letters)
3047 if ((char >= 'A' && char <= 'Z') || (char >= 'a' && char <= 'z')) {
3048 // Letters after symbol or numeric part are invalid
3049 if (hasCurrencySymbol || numericPart) {
3050 return null;
3051 }
3052 letterBuffer += char;
3053 continue;
3054 }
3055
3056 // Digits
3057 if (char >= '0' && char <= '9') {
3058 // Reject if we have letters but no currency symbol
3059 if (letterBuffer && !hasCurrencySymbol) {
3060 return null;
3061 }
3062 letterBuffer = '';
3063 numericPart += char;
3064 continue;
3065 }
3066
3067 // Comma and dot separators
3068 if (char === ',') {
3069 if (firstCommaPos === -1) firstCommaPos = numericPart.length;
3070 lastCommaPos = numericPart.length;
3071 commaCount++;
3072 numericPart += char;
3073 continue;
3074 }
3075 if (char === '.') {
3076 if (firstDotPos === -1) firstDotPos = numericPart.length;
3077 lastDotPos = numericPart.length;
3078 dotCount++;
3079 numericPart += char;
3080 continue;
3081 }
3082
3083 // Invalid character
3084 hasInvalidChars = true;
3085 }
3086
3087 // Reject if no currency symbol was found
3088 if (!hasCurrencySymbol) {
3089 return null;
3090 }
3091
3092 // Reject if there are any invalid characters
3093 if (hasInvalidChars) {
3094 return null;
3095 }
3096
3097 // If no numeric part, reject
3098 if (!numericPart) return null;
3099
3100 // Ensure numeric part contains at least one digit (not just separators)
3101 if (!/\d/.test(numericPart)) return null;
3102
3103 // Infer decimal and group separators
3104 let decimal = '.';
3105 let group = ',';
3106
3107 // If filterDecimal is provided, use it to determine separators
3108 if (filterDecimal) {
3109 decimal = filterDecimal;
3110 group = filterDecimal === ',' ? '.' : ',';
3111
3112 // Validate that the input matches this interpretation
3113 if (commaCount > 0 && dotCount > 0) {
3114 // Both present: check if filterDecimal matches the last one (which should be decimal)
3115 const lastIsComma = lastCommaPos > lastDotPos;
3116 if ((filterDecimal === ',' && !lastIsComma) || (filterDecimal === '.' && lastIsComma)) {
3117 return null;
3118 }
3119 } else if (dotCount === 1 && commaCount === 0) {
3120 // Only one dot: if NOT followed by exactly 3 digits, it's a decimal separator
3121 const afterDot = numericPart.substring(lastDotPos + 1);
3122 if (afterDot.length !== 3) {
3123 // It's a decimal separator, must match filterDecimal
3124 if (filterDecimal !== '.') {
3125 return null;
3126 }
3127 }
3128 } else if (commaCount === 1 && dotCount === 0) {
3129 // Only one comma: if NOT followed by exactly 3 digits, it's a decimal separator
3130 const afterComma = numericPart.substring(lastCommaPos + 1);
3131 if (afterComma.length !== 3) {
3132 // It's a decimal separator, must match filterDecimal
3133 if (filterDecimal !== ',') {
3134 return null;
3135 }
3136 }
3137 }
3138 } else {
3139 // Infer from the input pattern
3140 if (commaCount > 0 && dotCount > 0) {
3141 // Both present: the one that appears last is decimal
3142 if (lastCommaPos > lastDotPos) {
3143 decimal = ',';
3144 group = '.';
3145 }
3146 } else if (dotCount === 1 && commaCount === 0) {
3147 // Only one dot: check if it's followed by exactly 3 digits
3148 const afterDot = numericPart.substring(lastDotPos + 1);
3149 if (afterDot.length === 3) {
3150 // Likely a thousands separator
3151 decimal = ',';
3152 group = '.';
3153 }
3154 } else if (commaCount === 1 && dotCount === 0) {
3155 // Only one comma: check if it's followed by exactly 3 digits
3156 const afterComma = numericPart.substring(lastCommaPos + 1);
3157 if (afterComma.length !== 3) {
3158 // Likely a decimal separator
3159 decimal = ',';
3160 group = '.';
3161 }
3162 }
3163 }
3164
3165 // Normalize: remove group separator, convert decimal to '.'
3166 let normalized = '';
3167 for (let i = 0; i < numericPart.length; i++) {
3168 const char = numericPart[i];
3169 if (char === group) continue;
3170 if (char === decimal) {
3171 normalized += '.';
3172 } else {
3173 normalized += char;
3174 }
3175 }
3176
3177 const parsed = parseFloat(normalized);
3178 if (isNaN(parsed)) return null;
3179
3180 const finalValue = isNegative ? -parsed : parsed;
3181
3182 // Build mask
3183 const dotPos = normalized.indexOf('.');
3184 const decimalPlaces = dotPos !== -1 ? normalized.length - dotPos - 1 : 0;
3185 const maskDecimal = decimalPlaces ? decimal + '0'.repeat(decimalPlaces) : '';
3186 const groupMask = '#' + group + '##0';
3187 const needsSpace = symbol && !symbol.endsWith(' ') && !symbol.endsWith('\t') && !hasParens;
3188 let mask = symbol + (needsSpace ? ' ' : '') + groupMask + maskDecimal;
3189
3190 if (hasParens) {
3191 mask = `(${mask})`;
3192 }
3193
3194 return {
3195 mask,
3196 value: finalValue,
3197 type: 'currency',
3198 category: 'numeric'
3199 };
3200 }
3201
3202 const autoCastingNumber = function (input, filterDecimal) {
3203 // If you currently support numeric inputs directly, keep this:
3204 if (typeof input === 'number' && Number.isFinite(input)) {
3205 return { mask: '0', value: input, type: 'number', category: 'numeric' };
3206 }
3207
3208 if (typeof input !== 'string') {
3209 return null;
3210 }
3211
3212 const sRaw = input.trim();
3213
3214 // Check for simple integers first (with optional sign)
3215 if (/^[+-]?\d+$/.test(sRaw)) {
3216 const sign = /^[+-]/.test(sRaw) ? sRaw[0] : '';
3217 const digitsClean = (sign ? sRaw.slice(1) : sRaw);
3218 const rawDigits = sign ? sRaw.slice(1) : sRaw;
3219 const m = rawDigits.match(/^0+/);
3220 const leadingZeros = m ? m[0].length : 0;
3221 const mask = leadingZeros > 0 ? '0'.repeat(rawDigits.length) : '0';
3222 const value = Number(sign + digitsClean);
3223 return { mask, value, type: 'number', category: 'numeric' };
3224 }
3225
3226 // Check for formatted numbers with thousand separators (no letters, no symbols)
3227 // Examples: "1,000.25", "1.000,25", "-1,234.56"
3228 if (/^[+-]?[\d,.]+$/.test(sRaw)) {
3229 let isNegative = sRaw[0] === '-';
3230 let numStr = isNegative ? sRaw.slice(1) : sRaw;
3231
3232 // Count separators
3233 const commaCount = (numStr.match(/,/g) || []).length;
3234 const dotCount = (numStr.match(/\./g) || []).length;
3235
3236 // Must have at least one digit
3237 if (!/\d/.test(numStr)) return null;
3238
3239 // Infer decimal and group separators
3240 let decimal = '.';
3241 let group = ',';
3242
3243 const lastCommaPos = numStr.lastIndexOf(',');
3244 const lastDotPos = numStr.lastIndexOf('.');
3245
3246 // If filterDecimal is provided, use it to determine separators
3247 if (filterDecimal) {
3248 decimal = filterDecimal;
3249 group = filterDecimal === ',' ? '.' : ',';
3250
3251 // Validate that the input matches this interpretation
3252 if (commaCount > 0 && dotCount > 0) {
3253 // Both present: check if filterDecimal matches the last one (which should be decimal)
3254 const lastIsComma = lastCommaPos > lastDotPos;
3255 if ((filterDecimal === ',' && !lastIsComma) || (filterDecimal === '.' && lastIsComma)) {
3256 return null;
3257 }
3258 } else if (dotCount === 1 && commaCount === 0) {
3259 // Only one dot: if NOT followed by exactly 3 digits, it's a decimal separator
3260 const afterDot = numStr.substring(lastDotPos + 1);
3261 if (afterDot.length !== 3 || /[,.]/.test(afterDot)) {
3262 // It's a decimal separator, must match filterDecimal
3263 if (filterDecimal !== '.') {
3264 return null;
3265 }
3266 }
3267 } else if (commaCount === 1 && dotCount === 0) {
3268 // Only one comma: if NOT followed by exactly 3 digits, it's a decimal separator
3269 const afterComma = numStr.substring(lastCommaPos + 1);
3270 if (afterComma.length !== 3 || /[,.]/.test(afterComma)) {
3271 // It's a decimal separator, must match filterDecimal
3272 if (filterDecimal !== ',') {
3273 return null;
3274 }
3275 }
3276 }
3277 } else {
3278 // Infer from the input pattern
3279 if (commaCount > 0 && dotCount > 0) {
3280 // Both present: the one that appears last is decimal
3281 if (lastCommaPos > lastDotPos) {
3282 decimal = ',';
3283 group = '.';
3284 }
3285 } else if (dotCount === 1 && commaCount === 0) {
3286 // Only one dot: check if it's followed by exactly 3 digits (thousands separator)
3287 const afterDot = numStr.substring(lastDotPos + 1);
3288 if (afterDot.length === 3 && !/[,.]/.test(afterDot)) {
3289 decimal = ',';
3290 group = '.';
3291 }
3292 } else if (commaCount === 1 && dotCount === 0) {
3293 // Only one comma: check if it's NOT followed by exactly 3 digits (decimal separator)
3294 const afterComma = numStr.substring(lastCommaPos + 1);
3295 if (afterComma.length !== 3 || /[,.]/.test(afterComma)) {
3296 decimal = ',';
3297 group = '.';
3298 }
3299 }
3300 }
3301
3302 // Check if group separator is actually used in the input
3303 const hasGroupSeparator = (group === ',' && commaCount > 1) || (group === '.' && dotCount > 1) ||
3304 (group === ',' && decimal === '.' && commaCount > 0) ||
3305 (group === '.' && decimal === ',' && dotCount > 0);
3306
3307 // Normalize: remove group separator, convert decimal to '.'
3308 let normalized = numStr.replace(new RegExp('\\' + group, 'g'), '').replace(decimal, '.');
3309 const parsed = parseFloat(normalized);
3310 if (isNaN(parsed)) return null;
3311
3312 const value = isNegative ? -parsed : parsed;
3313
3314 // Build mask
3315 const dotPos = normalized.indexOf('.');
3316 const decimalPlaces = dotPos !== -1 ? normalized.length - dotPos - 1 : 0;
3317 const maskDecimal = decimalPlaces ? decimal + '0'.repeat(decimalPlaces) : '';
3318 const mask = (hasGroupSeparator ? '#' + group + '##0' : '0') + maskDecimal;
3319
3320 return { mask, value, type: 'number', category: 'numeric' };
3321 }
3322
3323 return null;
3324 };
3325
3326 const autoCastingScientific = function(input) {
3327 if (typeof input !== 'string') return null;
3328
3329 const original = input.trim();
3330
3331 // Match scientific notation: 1e3, -2.5E-4, etc.
3332 const sciPattern = /^[-+]?\d*\.?\d+[eE][-+]?\d+$/;
3333 if (!sciPattern.test(original)) return null;
3334
3335 const parsed = parseFloat(original);
3336 if (isNaN(parsed)) return null;
3337
3338 // Extract parts to determine mask
3339 const [coefficient, exponent] = original.toLowerCase().split('e');
3340 const decimalPlaces = coefficient.includes('.') ? coefficient.split('.')[1].length : 0;
3341 const mask = `0${decimalPlaces ? '.' + '0'.repeat(decimalPlaces) : ''}E+00`;
3342
3343 return {
3344 mask,
3345 value: parsed,
3346 type: 'scientific',
3347 category: 'scientific'
3348 };
3349 }
3350
3351 const autoCastingTime = function (input) {
3352 if (typeof input !== 'string') return null;
3353 const original = input.trim();
3354
3355 // hh:mm[:ss][ am/pm]
3356 const m = original.match(/^(\d{1,2}):(\d{2})(?::(\d{2}))?(?:\s*(am|pm))?$/i);
3357 if (!m) return null;
3358
3359 let h = parseInt(m[1], 10);
3360 const i = parseInt(m[2], 10);
3361 const s = m[3] ? parseInt(m[3], 10) : 0;
3362 const mer = m[4] && m[4].toLowerCase();
3363
3364 // basic range checks
3365 if (i > 59 || s > 59) return null;
3366 if (mer) {
3367 if (h < 1 || h > 12) return null;
3368 if (mer === 'pm' && h < 12) h += 12;
3369 if (mer === 'am' && h === 12) h = 0;
3370 } else {
3371 if (h > 23) return null;
3372 }
3373
3374 // Excel serial for time-of-day = hours/24 + minutes/1440 + seconds/86400
3375 const excel = (h + i / 60 + s / 3600) / 24;
3376
3377 // Build mask according to how user typed it
3378 const hourToken = m[1].length === 1 ? 'h' : 'hh';
3379 const base = s !== 0 || m[3] ? `${hourToken}:mm:ss` : `${hourToken}:mm`;
3380 const mask = mer ? `${base} am/pm` : base;
3381
3382 // Verify we can render back exactly what the user typed
3383 if (testMask(mask, excel, original)) { // uses Component.render under the hood
3384 return { mask: mask, value: excel, type: 'time', category: 'datetime' };
3385 }
3386
3387 // Try alternate hour width if needed
3388 const altHour = hourToken === 'hh' ? 'h' : 'hh';
3389 const alt = mer
3390 ? `${altHour}${base.slice(hourToken.length)} am/pm`
3391 : `${altHour}${base.slice(hourToken.length)}`;
3392
3393 if (testMask(alt, excel, original)) {
3394 return { mask: alt, value: excel, type: 'time', category: 'datetime' };
3395 }
3396
3397 return null;
3398 };
3399
3400 const ParseValue = function(v, config) {
3401 if (v === '') return '';
3402
3403 const originalInput = '' + v;
3404 const decimal = config.decimal || '.';
3405
3406 // Validate that the input looks like a reasonable number format before extracting digits
3407 // Reject strings that are clearly not intended to be numbers (e.g., "test123", "abc", etc.)
3408 const hasLetters = /[a-zA-Z]/.test(originalInput);
3409 const hasDigits = /[0-9]/.test(originalInput);
3410
3411 if (hasLetters && hasDigits) {
3412 // Mixed letters and digits - check if it's a valid numeric format
3413 // Allow currency symbols, currency codes (3 letters), percentage, and separators
3414
3415 // Remove all valid numeric characters and symbols
3416 let cleaned = originalInput.replace(/[\d\s.,\-+()]/g, ''); // Remove digits, spaces, separators, signs, parentheses
3417 cleaned = cleaned.replace(/[A-Z]{1,2}[€$£¥₹₽₩₫¢]/gi, ''); // Remove 1-2 letter prefix + currency symbol (R$, U$, etc.)
3418 cleaned = cleaned.replace(/[€$£¥₹₽₩₫¢]/g, ''); // Remove remaining currency symbols
3419 cleaned = cleaned.replace(/%/g, ''); // Remove percentage
3420 cleaned = cleaned.replace(/\b[A-Z]{3}\b/g, ''); // Remove 3-letter currency codes (USD, BRL, etc.)
3421
3422 // If anything remains, it's likely invalid (like "test" in "test123")
3423 if (cleaned.trim().length > 0) {
3424 return null; // Reject patterns like "test123", "abc123", etc.
3425 }
3426 }
3427
3428 v = originalInput.split(decimal);
3429
3430 // Detect negative sign
3431 let signal = v[0].includes('-');
3432
3433 v[0] = v[0].match(/[0-9]+/g);
3434 if (v[0]) {
3435 if (signal) v[0].unshift('-');
3436 v[0] = v[0].join('');
3437 } else {
3438 v[0] = signal ? '-' : '';
3439 }
3440
3441 if (v[1] !== undefined) {
3442 v[1] = v[1].match(/[0-9]+/g);
3443 v[1] = v[1] ? v[1].join('') : '';
3444 }
3445
3446 return v[0] || v[1] ? v : '';
3447 }
3448
3449 const Extract = function(v, config) {
3450 const parsed = ParseValue(v, config);
3451 if (parsed) {
3452 if (parsed[0] === '-') {
3453 parsed[0] = '-0';
3454 }
3455 return parseFloat(parsed.join('.'));
3456 }
3457 return null;
3458 }
3459
3460 /**
3461 * Try to get which mask that can transform the number in that format
3462 * @param {string|number} value - The value to detect the mask for
3463 * @param {string} [decimal] - Optional decimal separator filter ('.' or ',')
3464 */
3465 Component.autoCasting = function(value, decimal) {
3466 // Check cache first - use string value and decimal as key
3467 const cacheKey = decimal ? String(value) + '|' + decimal : String(value);
3468 let cached = autoCastingCache[cacheKey];
3469 if (cached !== undefined) {
3470 return cached;
3471 }
3472
3473 const methods = [
3474 autoCastingDates, // Most structured, the least ambiguous
3475 autoCastingTime,
3476 autoCastingFractions, // Specific pattern with slashes
3477 autoCastingPercent, // Recognizable with "%"
3478 autoCastingScientific,
3479 (v) => autoCastingNumber(v, decimal), // Only picks up basic digits, decimals, leading 0s
3480 (v) => autoCastingCurrency(v, decimal), // Complex formats, but recognizable
3481 ];
3482
3483 let result = null;
3484 for (let method of methods) {
3485 const test = method(value);
3486 if (test) {
3487 result = test;
3488 break;
3489 }
3490 }
3491
3492 // Cache the result (even if null)
3493 autoCastingCache[cacheKey] = result;
3494 return result;
3495 }
3496
3497 Component.extract = function(value, options, returnObject) {
3498 if (! value || typeof options !== 'object') {
3499 return value;
3500 }
3501
3502 if (options.locale) {
3503 const config = getConfig(options, value);
3504 config.value = Extract(value, config);
3505 if (value.toString().indexOf('%') !== -1) {
3506 config.value /= 100;
3507 }
3508 return returnObject ? config : config.value;
3509 } else if (options.mask) {
3510 let mask = options.mask.split(';')[0];
3511 if (mask) {
3512 options.mask = mask;
3513 }
3514
3515 // Get decimal, group, type, etc.
3516 const config = getConfig(options, value);
3517 const type = config.type;
3518
3519 let result;
3520 let o = options;
3521
3522 if (type === 'text') {
3523 result = value;
3524 } else if (type === 'general') {
3525 result = Component(value, options);
3526 } else if (type === 'datetime') {
3527 if (value instanceof Date) {
3528 value = Component.getDateString(value, config.mask);
3529 }
3530
3531 o = Component(value, options, true);
3532
3533 result = typeof o.value === 'number' ? o.value : extractDate.call(o);
3534 } else if (type === 'scientific') {
3535 result = typeof value === 'string' ? Number(value) : value;
3536 } else if (type === 'fraction') {
3537 // Parse a fraction string according to the mask (supports mixed "# ?/d" or simple "?/d")
3538 const mask = config.mask;
3539
3540 // Detect fixed denominator (e.g. "# ?/16" or "?/8")
3541 const fixedDenMatch = mask.match(/\/\s*(\d+)\s*$/);
3542 const fixedDen = fixedDenMatch ? parseInt(fixedDenMatch[1], 10) : null;
3543
3544 // Whether a mask allows a whole part (e.g. "# ?/?")
3545 const allowWhole = mask.includes('#');
3546
3547 let s = ('' + value).trim();
3548 if (!s) {
3549 result = null;
3550 } else {
3551 // Allow leading parentheses or '-' for negatives
3552 let sign = 1;
3553 if (/^\(.*\)$/.test(s)) {
3554 sign = -1;
3555 s = s.slice(1, -1).trim();
3556 }
3557 if (/^\s*-/.test(s)) {
3558 sign = -1;
3559 s = s.replace(/^\s*-/, '').trim();
3560 }
3561
3562 let out = null;
3563
3564 if (s.includes('/')) {
3565 // sign? (whole )? numerator / denominator
3566 // Examples:
3567 // "1 1/2" => whole=1, num=1, den=2
3568 // "1/2" => whole=undefined, num=1, den=2
3569 const m = s.match(/^\s*(?:(\d+)\s+)?(\d+)\s*\/\s*(\d+)\s*$/);
3570 if (m) {
3571 const whole = allowWhole && m[1] ? parseInt(m[1], 10) : 0;
3572 const num = parseInt(m[2], 10);
3573 let den = parseInt(m[3], 10);
3574
3575 // If mask fixes the denominator, enforce it
3576 if (fixedDen) den = fixedDen;
3577
3578 if (den !== 0) {
3579 out = sign * (whole + num / den);
3580 }
3581 }
3582 } else {
3583 // No slash → treats as a plain number (e.g., whole only)
3584 const plain = Number(s.replace(',', '.'));
3585 if (!Number.isNaN(plain)) {
3586 out = sign * Math.abs(plain);
3587 }
3588 }
3589
3590 result = out;
3591 }
3592 } else {
3593 // Default fallback — numeric/currency/percent/etc.
3594 result = Extract(value, config);
3595 // Adjust percent
3596 if (type === 'percentage' && ('' + value).indexOf('%') !== -1) {
3597 result = result / 100;
3598 }
3599 }
3600
3601 o.value = result;
3602
3603 if (!o.type && type) {
3604 o.type = type;
3605 }
3606
3607 return returnObject ? o : result;
3608 }
3609
3610 return value;
3611 };
3612
3613 Component.render = function(value, options, fullMask, strict) {
3614 // Nothing to render
3615 if (value === '' || value === undefined || value === null) {
3616 return '';
3617 }
3618
3619 // Store original value for strict mode
3620 const originalValue = value;
3621
3622 // Config
3623 const config = getConfig(options, value);
3624
3625 if (config.locale) {
3626 value = Component(value, options);
3627 } else if (config.mask) {
3628 // Percentage
3629 if (config.type === 'datetime') {
3630 var t = Component.getDateString(value, config.mask);
3631 if (t) {
3632 value = t;
3633 } else {
3634 return '';
3635 }
3636 } else if (config.type === 'text') {
3637 // Parse number
3638 if (typeof (value) === 'number') {
3639 value = value.toString();
3640 }
3641 } else {
3642 // Strict mode: for numeric masks, if string input is not a valid number,
3643 // return original value unchanged (Excel-like behavior)
3644 if (strict && typeof(originalValue) === 'string' && !isNumber(originalValue)) {
3645 return originalValue;
3646 }
3647 if (config.type === 'percentage') {
3648 if (typeof (value) === 'string' && value.indexOf('%') !== -1) {
3649 value = value.replace('%', '');
3650 } else {
3651 value = adjustPrecision(Number(value) * 100);
3652 }
3653 } else {
3654 if (config.mask.includes(',,M')) {
3655 if (typeof (value) === 'string' && value.indexOf('M') !== -1) {
3656 value = value.replace('M', '');
3657 } else {
3658 value = Number(value) / 1000000;
3659 }
3660 } else if (config.mask.includes(',,,B')) {
3661 if (typeof (value) === 'string' && value.indexOf('B') !== -1) {
3662 value = value.replace('B', '');
3663 } else {
3664 value = Number(value) / 1000000000;
3665 }
3666 }
3667 }
3668
3669 if (typeof (value) === 'string' && isNumber(value)) {
3670 value = Number(value);
3671 }
3672
3673 if (typeof value === 'number') {
3674 // Temporary value
3675 let temp = value;
3676
3677 if (config.type === 'fraction') {
3678 temp = formatFraction(value, config.mask);
3679 } else {
3680 if (fullMask) {
3681 temp = adjustNumberOfDecimalPlaces(config, value);
3682
3683 if (config.type === 'scientific') {
3684 return temp;
3685 }
3686 }
3687 }
3688
3689 value = toPlainString(temp);
3690
3691 if (config.decimal === ',') {
3692 value = value.replace('.', config.decimal);
3693 }
3694 }
3695 }
3696
3697 // Process mask
3698 let control = Component(value, options, true);
3699 // Complement render
3700 if (fullMask) {
3701 processNumOfPaddingZeros(control);
3702 }
3703
3704 value = getValue(control);
3705
3706 // If numeric mask but no numbers in input, return empty
3707 if (isNumeric(control.type)) {
3708 // Check if any numeric digit was actually extracted
3709 const hasNumericValue = control.values.some(v => v && /\d/.test(v));
3710 if (! hasNumericValue) {
3711 value = '';
3712 }
3713 }
3714
3715 if (options.input && options.input.tagName) {
3716 if (options.input.contentEditable) {
3717 options.input.textContent = value;
3718 } else {
3719 options.input.value = value;
3720 }
3721 focus(options.input);
3722 }
3723 }
3724
3725 return value;
3726 }
3727
3728 // Helper to extract date from a string
3729 Component.extractDateFromString = function (date, format) {
3730 let o = Component(date, { mask: format }, true);
3731
3732 // Check if in format Excel (Need difference with format date or type detected is numeric)
3733 if (date > 0 && Number(date) == date && (o.values.join("") !== o.value || o.type == "numeric")) {
3734 var d = new Date(Math.round((date - 25569) * 86400 * 1000));
3735 return d.getFullYear() + "-" + Helpers.two(d.getMonth()) + "-" + Helpers.two(d.getDate()) + ' 00:00:00';
3736 }
3737
3738 let complete = false;
3739
3740 if (o.values && o.values.length === o.tokens.length && o.values[o.values.length - 1].length >= o.tokens[o.tokens.length - 1].length) {
3741 complete = true;
3742 }
3743
3744 if (o.date[0] && o.date[1] && (o.date[2] || complete)) {
3745 if (!o.date[2]) {
3746 o.date[2] = 1;
3747 }
3748
3749 return o.date[0] + '-' + Helpers.two(o.date[1]) + '-' + Helpers.two(o.date[2]) + ' ' + Helpers.two(o.date[3]) + ':' + Helpers.two(o.date[4]) + ':' + Helpers.two(o.date[5]);
3750 }
3751
3752 return '';
3753 }
3754
3755 // Tokens
3756 const dateTokens = ['DAY', 'WD', 'DDDD', 'DDD', 'DD', 'D', 'Q', 'HH24', 'HH12', 'HH', '\\[H\\]', 'H', 'AM/PM', 'MI', 'SS', 'MS', 'YYYY', 'YYY', 'YY', 'Y', 'MONTH', 'MON', 'MMMMM', 'MMMM', 'MMM', 'MM', 'M', '.'];
3757 // All date tokens
3758 const allDateTokens = dateTokens.join('|')
3759
3760 Component.getDateString = function(value, options) {
3761 if (! options) {
3762 options = {};
3763 }
3764
3765 // Labels
3766 let format;
3767
3768 if (options && typeof(options) == 'object') {
3769 if (options.format) {
3770 format = options.format;
3771 } else if (options.mask) {
3772 format = options.mask;
3773 }
3774 } else {
3775 format = options;
3776 }
3777
3778 if (! format) {
3779 format = 'YYYY-MM-DD';
3780 }
3781
3782 format = format.toUpperCase();
3783
3784 // Date instance
3785 if (value instanceof Date) {
3786 value = Helpers.now(value);
3787 } else if (isNumber(value)) {
3788 value = Helpers.numToDate(value);
3789 }
3790
3791
3792 // Expression to extract all tokens from the string
3793 let e = new RegExp(allDateTokens, 'gi');
3794 // Extract
3795 let t = format.match(e);
3796
3797 // Compatibility with Excel
3798 fixMinuteToken(t);
3799
3800 // Object
3801 const o = {
3802 tokens: t
3803 }
3804
3805 // Value
3806 if (value) {
3807 try {
3808 // Data
3809 o.data = extractDateAndTime(value);
3810
3811 if (o.data[1] && o.data[1] > 12) {
3812 throw new Error('Invalid date');
3813 } else if (o.data[4] && o.data[4] > 59) {
3814 throw new Error('Invalid date');
3815 } else if (o.data[5] && o.data[5] > 59) {
3816 throw new Error('Invalid date');
3817 } else if (o.data[0] != null && o.data[1] != null) {
3818 let day = new Date(o.data[0], o.data[1], 0).getDate();
3819 if (o.data[2] > day) {
3820 throw new Error('Invalid date');
3821 }
3822 }
3823
3824 // Value
3825 o.value = [];
3826
3827 // Calendar instance
3828 let calendar = new Date(o.data[0], o.data[1] - 1, o.data[2], o.data[3], o.data[4], o.data[5]);
3829
3830 if (o.data[0] === null && o.data[1] === null && o.data[2] === null) {
3831 // Do nothing
3832 } else {
3833 if (isNaN(calendar.getTime())) {
3834 throw new Error('Invalid date');
3835 }
3836 }
3837
3838 // Get method
3839 const get = function (i) {
3840 // Token
3841 let t = this.tokens[i];
3842
3843 // Case token
3844 let s = t.toUpperCase();
3845 let v = null;
3846
3847 if (s === 'YYYY') {
3848 v = this.data[0];
3849 } else if (s === 'YYY') {
3850 v = this.data[0];
3851 if (v) {
3852 v = v.substring(1, 4);
3853 }
3854 } else if (s === 'YY') {
3855 v = this.data[0];
3856 if (v) {
3857 v = v.substring(2, 4);
3858 }
3859 } else if (s === 'Y') {
3860 v = this.data[0];
3861 if (v) {
3862 v = v.substring(3, 4);
3863 }
3864 } else if (t === 'MON') {
3865 v = Helpers.months[calendar.getMonth()];
3866 if (v) {
3867 v = v.substr(0, 3).toUpperCase();
3868 }
3869 } else if (t === 'mon') {
3870 v = Helpers.months[calendar.getMonth()];
3871 if (v) {
3872 v = v.substr(0, 3).toLowerCase();
3873 }
3874 } else if (t === 'MONTH') {
3875 v = Helpers.months[calendar.getMonth()];
3876 if (v) {
3877 v = v.toUpperCase();
3878 }
3879 } else if (t === 'month') {
3880 v = Helpers.months[calendar.getMonth()];
3881 if (v) {
3882 v = v.toLowerCase();
3883 }
3884 } else if (s === 'MMMMM') {
3885 v = Helpers.months[calendar.getMonth()];
3886 if (v) {
3887 v = v.substr(0, 1);
3888 }
3889 } else if (s === 'MMMM' || t === 'Month') {
3890 v = Helpers.months[calendar.getMonth()];
3891 } else if (s === 'MMM' || t == 'Mon') {
3892 v = Helpers.months[calendar.getMonth()];
3893 if (v) {
3894 v = v.substr(0, 3);
3895 }
3896 } else if (s === 'MM') {
3897 v = Helpers.two(this.data[1]);
3898 } else if (s === 'M') {
3899 v = calendar.getMonth() + 1;
3900 } else if (t === 'DAY') {
3901 v = Helpers.weekdays[calendar.getDay()];
3902 if (v) {
3903 v = v.toUpperCase();
3904 }
3905 } else if (t === 'day') {
3906 v = Helpers.weekdays[calendar.getDay()];
3907 if (v) {
3908 v = v.toLowerCase();
3909 }
3910 } else if (s === 'DDDD' || t == 'Day') {
3911 v = Helpers.weekdays[calendar.getDay()];
3912 } else if (s === 'DDD') {
3913 v = Helpers.weekdays[calendar.getDay()];
3914 if (v) {
3915 v = v.substr(0, 3);
3916 }
3917 } else if (s === 'DD') {
3918 v = Helpers.two(this.data[2]);
3919 } else if (s === 'D') {
3920 v = parseInt(this.data[2]);
3921 } else if (s === 'Q') {
3922 v = Math.floor((calendar.getMonth() + 3) / 3);
3923 } else if (s === 'HH24' || s === 'HH') {
3924 v = this.data[3]%24;
3925 if (this.tokens.indexOf('AM/PM') !== -1) {
3926 if (v > 12) {
3927 v -= 12;
3928 } else if (v == '0' || v == '00') {
3929 v = 12;
3930 }
3931 }
3932 v = Helpers.two(v);
3933 } else if (s === 'HH12') {
3934 v = this.data[3]%24;
3935 if (v > 12) {
3936 v = Helpers.two(v - 12);
3937 } else {
3938 v = Helpers.two(v);
3939 }
3940 } else if (s === 'H') {
3941 v = this.data[3]%24;
3942 if (this.tokens.indexOf('AM/PM') !== -1) {
3943 if (v > 12) {
3944 v -= 12;
3945 } else if (v == '0' || v == '00') {
3946 v = 12;
3947 }
3948 }
3949 } else if (s === '[H]') {
3950 v = this.data[3];
3951 } else if (s === 'MI') {
3952 v = Helpers.two(this.data[4]);
3953 } else if (s === 'I') {
3954 v = parseInt(this.data[4]);
3955 } else if (s === 'SS') {
3956 v = Helpers.two(this.data[5]);
3957 } else if (s === 'S') {
3958 v = parseInt(this.data[5]);
3959 } else if (s === 'MS') {
3960 v = calendar.getMilliseconds();
3961 } else if (s === 'AM/PM') {
3962 if (this.data[3] >= 12) {
3963 v = 'PM';
3964 } else {
3965 v = 'AM';
3966 }
3967 } else if (s === 'WD') {
3968 v = Helpers.weekdays[calendar.getDay()];
3969 }
3970
3971 if (v === null) {
3972 this.value[i] = this.tokens[i];
3973 } else {
3974 this.value[i] = v;
3975 }
3976 }
3977
3978 for (let i = 0; i < o.tokens.length; i++) {
3979 get.call(o, i);
3980 }
3981
3982 value = o.value.join('');
3983 } catch (e) {
3984 value = '';
3985 }
3986 }
3987
3988 return value;
3989 }
3990
3991 Component.getDate = function(value, format) {
3992 if (! format) {
3993 format = 'YYYY-MM-DD';
3994 }
3995
3996 let ret = value;
3997 if (ret && Number(ret) == ret) {
3998 ret = Helpers.numToDate(ret);
3999 }
4000
4001 // Try a formatted date
4002 if (! Helpers.isValidDateFormat(ret)) {
4003 let tmp = Component.extractDateFromString(ret, format);
4004 if (tmp) {
4005 ret = tmp;
4006 }
4007 }
4008
4009 return Component.getDateString(ret, format);
4010 }
4011
4012 Component.oninput = function(e, mask) {
4013 // Element
4014 let element = e.target;
4015 // Property
4016 let property = 'value';
4017 // Get the value of the input
4018 if (element.tagName !== 'INPUT') {
4019 property = 'textContent';
4020 }
4021 // Value
4022 let value = element[property];
4023 // Get the mask
4024 if (! mask) {
4025 mask = element.getAttribute('data-mask') || element.mask;
4026 }
4027 // Keep the current caret position
4028 let caret = getCaret(element);
4029 if (caret) {
4030 value = value.substring(0, caret) + hiddenCaret + value.substring(caret);
4031 }
4032
4033 if (typeof mask === 'string') {
4034 mask = { mask: mask };
4035 }
4036
4037 if (mask.locale) {
4038 return;
4039 }
4040
4041 // Run mask
4042 let result = Component(value, mask, true);
4043
4044 // New value
4045 let newValue = result.values.join('');
4046 // Apply the result back to the element
4047 if (newValue !== value && ! e.inputType.includes('delete')) {
4048 // Set the caret to the position before transformation
4049 let caret = newValue.indexOf(hiddenCaret);
4050 if (caret !== -1) {
4051 // Apply value
4052 element[property] = newValue.replace(hiddenCaret, "");
4053 // Set caret
4054 setCaret.call(element, caret);
4055 } else {
4056 // Apply value
4057 element[property] = newValue;
4058 // Make sure the caret is positioned in the end
4059 focus(element);
4060 }
4061 }
4062 }
4063
4064 Component.getType = function(config) {
4065 // Get configuration
4066 const control = getConfig(config, null);
4067
4068 return control.type;
4069 };
4070
4071 Component.adjustPrecision = adjustPrecision;
4072
4073 return Component;
4074 })();
4075
4076 return { Mask: Mask, Helpers: Helpers };
4077})));
4078
4079/***/ }),
4080
4081/***/ 763:
4082/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
4083
4084if (! lemonade && "function" === 'function') {
4085 var lemonade = __webpack_require__(966);
4086}
4087
4088if (! Modal && "function" === 'function') {
4089 var Modal = __webpack_require__(72);
4090}
4091
4092if (! utils && "function" === 'function') {
4093 var utils = __webpack_require__(791);
4094}
4095
4096const Helpers = utils.Helpers;
4097const Mask = utils.Mask;
4098
4099; (function (global, factory) {
4100 true ? module.exports = factory() :
4101 0;
4102}(this, (function () {
4103
4104 class CustomEvents extends Event {
4105 constructor(type, props, options) {
4106 super(type, {
4107 bubbles: true,
4108 composed: true,
4109 ...options,
4110 });
4111
4112 if (props) {
4113 for (const key in props) {
4114 // Avoid assigning if property already exists anywhere on `this`
4115 if (! (key in this)) {
4116 this[key] = props[key];
4117 }
4118 }
4119 }
4120 }
4121 }
4122
4123 // Dispatcher
4124 const Dispatch = function(method, type, options) {
4125 // Try calling the method directly if provided
4126 if (typeof method === 'function') {
4127 let a = Object.values(options);
4128 return method(...a);
4129 } else if (this.tagName) {
4130 this.dispatchEvent(new CustomEvents(type, options));
4131 }
4132 }
4133
4134 // Translations
4135 const T = function(t) {
4136 if (typeof(document) !== "undefined" && document.dictionary) {
4137 return document.dictionary[t] || t;
4138 } else {
4139 return t;
4140 }
4141 }
4142
4143 const filterData = function(year, month) {
4144 // Data for the month
4145 let data = {};
4146 if (Array.isArray(this.data)) {
4147 this.data.map(function (v) {
4148 let d = year + '-' + Helpers.two(month + 1);
4149 if (v.date.substring(0, 7) === d) {
4150 if (!data[v.date]) {
4151 data[v.date] = [];
4152 }
4153 data[v.date].push(v);
4154 }
4155 });
4156 }
4157 return data;
4158 }
4159
4160 // Get the short weekdays name
4161 const getWeekdays = function(firstDayOfWeek) {
4162 const reorderedWeekdays = [];
4163 for (let i = 0; i < 7; i++) {
4164 const dayIndex = (firstDayOfWeek + i) % 7;
4165 reorderedWeekdays.push(Helpers.weekdays[dayIndex]);
4166 }
4167
4168 return reorderedWeekdays.map(w => {
4169 return { title: w.substring(0, 1) };
4170 });
4171 }
4172
4173 const Views = function(self) {
4174 const view = {};
4175
4176 // Create years container
4177 view.years = [];
4178 view.months = [];
4179 view.days = [];
4180 view.hours = [];
4181 view.minutes = [];
4182
4183 for (let i = 0; i < 16; i++) {
4184 view.years.push({
4185 title: null,
4186 value: null,
4187 selected: false,
4188 });
4189 }
4190
4191 for (let i = 0; i < 12; i++) {
4192 view.months.push({
4193 title: null,
4194 value: null,
4195 selected: false,
4196 });
4197 }
4198
4199 for (let i = 0; i < 42; i++) {
4200 view.days.push({
4201 title: null,
4202 value: null,
4203 selected: false,
4204 });
4205 }
4206
4207 for (let i = 0; i < 24; i++) {
4208 view.hours.push({
4209 title: Helpers.two(i),
4210 value: i
4211 });
4212 }
4213
4214 for (let i = 0; i < 60; i++) {
4215 view.minutes.push({
4216 title: Helpers.two(i),
4217 value: i
4218 });
4219 }
4220
4221 view.years.update = function(date) {
4222 let year = date.getUTCFullYear();
4223 let start = year - (year % 16);
4224
4225 for (let i = 0; i < 16; i++) {
4226 let item = view.years[i];
4227 let value = start + i;
4228
4229 item.title = value
4230 item.value = value;
4231
4232 if (self.cursor.y === value) {
4233 item.selected = true;
4234 // Current item
4235 self.cursor.current = item;
4236 } else {
4237 item.selected = false;
4238 }
4239 }
4240 }
4241
4242 view.months.update = function(date) {
4243 let year = date.getUTCFullYear();
4244
4245 for (let i = 0; i < 12; i++) {
4246 let item = view.months[i];
4247
4248 item.title = Helpers.months[i].substring(0,3);
4249 item.value = i;
4250
4251 if (self.cursor.y === year && self.cursor.m === i) {
4252 item.selected = true;
4253 // Current item
4254 self.cursor.current = item;
4255 } else {
4256 item.selected = false;
4257 }
4258 }
4259 }
4260
4261 view.days.update = function(date) {
4262 let year = date.getUTCFullYear();
4263 let month = date.getUTCMonth();
4264 let data = filterData.call(self, year, month);
4265
4266 // First day
4267 let tmp = new Date(Date.UTC(year, month, 1, 0, 0, 0));
4268 let firstDayOfMonth = tmp.getUTCDay();
4269 let firstDayOfWeek = self.startingDay ?? 0;
4270
4271 // Calculate offset based on desired first day of week. firstDayOfWeek: 0 = Sunday, 1 = Monday, 2 = Tuesday, etc.
4272 let offset = (firstDayOfMonth - firstDayOfWeek + 7) % 7;
4273
4274 let index = -1 * offset;
4275
4276 for (let i = 0; i < 42; i++) {
4277 index++;
4278 // Item
4279 let item = view.days[i];
4280 // Get the day
4281 tmp = new Date(Date.UTC(year, month, index, 0, 0, 0));
4282 // Day
4283 let day = tmp.getUTCDate();
4284
4285 // Create the item
4286 item.title = day;
4287 item.value = index;
4288 item.number = Helpers.dateToNum(tmp.toISOString().substring(0, 10));
4289
4290 // Reset range properties for each item
4291 item.start = false;
4292 item.end = false;
4293 item.range = false;
4294 item.last = false;
4295 item.disabled = false;
4296 item.data = null;
4297
4298 // Check selections
4299 if (tmp.getUTCMonth() !== month) {
4300 // Days are not in the current month
4301 item.grey = true;
4302 } else {
4303 // Check for data
4304 let d = [ year, Helpers.two(month+1), Helpers.two(day) ].join('-');
4305
4306 if (data && data[d]) {
4307 item.data = data[d];
4308 }
4309
4310 item.grey = false;
4311 }
4312 // Month
4313 let m = tmp.getUTCMonth();
4314
4315 // Select cursor
4316 if (self.cursor.y === year && self.cursor.m === m && self.cursor.d === day) {
4317 item.selected = true;
4318 // Current item
4319 self.cursor.current = item;
4320 } else {
4321 item.selected = false;
4322 }
4323
4324
4325 // Valid ranges
4326 if (self.validRange) {
4327 if (typeof self.validRange === 'function') {
4328 let ret = self.validRange(day,m,year,item);
4329 if (typeof ret !== 'undefined') {
4330 item.disabled = ret;
4331 }
4332 } else {
4333 let current = year + '-' + Helpers.two(m+1) + '-' + Helpers.two(day);
4334
4335 let test1 = !self.validRange[0] || current >= self.validRange[0].substr(0, 10);
4336 let test2 = !self.validRange[1] || current <= self.validRange[1].substr(0, 10);
4337
4338 if (! (test1 && test2)) {
4339 item.disabled = true;
4340 }
4341 }
4342 }
4343
4344 // Select range
4345 if (self.range && self.rangeValues) {
4346 // Only mark start/end if the number matches
4347 item.start = self.rangeValues[0] === item.number;
4348 item.end = self.rangeValues[1] === item.number;
4349 // Mark as part of range if between start and end
4350 item.range = self.rangeValues[0] && self.rangeValues[1] && self.rangeValues[0] <= item.number && self.rangeValues[1] >= item.number;
4351 }
4352 }
4353 }
4354
4355 return view;
4356 }
4357
4358 const isTrue = function(v) {
4359 return v === true || v === 'true';
4360 }
4361
4362 const isNumber = function (num) {
4363 if (typeof(num) === 'string') {
4364 num = num.trim();
4365 }
4366 return !isNaN(num) && num !== null && num !== '';
4367 }
4368
4369 const Calendar = function(children, { onchange, onload, track }) {
4370 let self = this;
4371
4372 // Event
4373 let change = self.onchange;
4374 self.onchange = null;
4375
4376 // Weekdays
4377 self.weekdays = getWeekdays(self.startingDay ?? 0);
4378
4379 // Cursor
4380 self.cursor = {};
4381
4382 // Time
4383 self.time = !! self.time;
4384
4385 // Range values
4386 self.rangeValues = null;
4387
4388 // Calendar date
4389 let date = new Date();
4390
4391 // Views
4392 const views = Views(self);
4393 const hours = views.hours;
4394 const minutes = views.minutes;
4395
4396 // Initial view
4397 self.view = 'days';
4398
4399 // Auto Input
4400 if (self.input === 'auto') {
4401 self.input = document.createElement('input');
4402 self.input.type = 'text';
4403 }
4404
4405
4406 // Get the position of the data based on the view
4407 const getPosition = function() {
4408 let position = 2;
4409 if (self.view === 'years') {
4410 position = 0;
4411 } else if (self.view === 'months') {
4412 position = 1;
4413 }
4414 return position;
4415 }
4416
4417 const setView = function(e) {
4418 if (typeof e === 'object') {
4419 e = this.getAttribute('data-view');
4420 }
4421
4422 // Valid views
4423 const validViews = ['days', 'months', 'years'];
4424
4425 // Define new view
4426 if (validViews.includes(e) && self.view !== e) {
4427 self.view = e;
4428 }
4429 }
4430
4431 const reloadView = function(reset) {
4432 if (reset) {
4433 // Update options to the view
4434 self.options = views[self.view];
4435 }
4436 // Update the values of hte options of hte view
4437 views[self.view]?.update.call(self, date);
4438 }
4439
4440 const getValue = function() {
4441 let value = null;
4442 if (isTrue(self.range)) {
4443 if (Array.isArray(self.rangeValues)) {
4444 if (isTrue(self.numeric)) {
4445 value = self.rangeValues;
4446 } else {
4447 value = [
4448 Helpers.numToDate(self.rangeValues[0]).substring(0, 10),
4449 Helpers.numToDate(self.rangeValues[1]).substring(0, 10)
4450 ];
4451 }
4452 }
4453 } else {
4454 value = getDate();
4455 if (isTrue(self.numeric)) {
4456 value = Helpers.dateToNum(value);
4457 }
4458 }
4459 return value;
4460 }
4461
4462 const setValue = function(v) {
4463 let d = new Date();
4464 if (v) {
4465 if (isTrue(self.range)) {
4466 if (v) {
4467 if (! Array.isArray(v)) {
4468 v = v.toString().split(',');
4469 }
4470 self.rangeValues = [...v];
4471
4472 if (v[0] && typeof (v[0]) === 'string' && v[0].indexOf('-')) {
4473 self.rangeValues[0] = Helpers.dateToNum(v[0]);
4474 }
4475 if (v[1] && typeof (v[1]) === 'string' && v[1].indexOf('-')) {
4476 self.rangeValues[1] = Helpers.dateToNum(v[1]);
4477 }
4478
4479 v = v[0];
4480 }
4481 } else if (typeof v === 'string' && v.includes(',')) {
4482 v = v.split(',')[0];
4483 }
4484
4485 if (v) {
4486 v = isNumber(v) ? Helpers.numToDate(v) : v;
4487 d = new Date(v + ' GMT+0');
4488 }
4489
4490 // if no date is defined
4491 if (! Helpers.isValidDate(d)) {
4492 d = new Date();
4493 }
4494 }
4495
4496 // Update the internal calendar date
4497 setDate(d, true);
4498 // Update the view
4499 reloadView();
4500 }
4501
4502 const getDate = function() {
4503 let v = [ self.cursor.y, self.cursor.m, self.cursor.d, self.hour, self.minute ];
4504 let d = new Date(Date.UTC(...v));
4505 // Update the headers of the calendar
4506 if (self.time) {
4507 return d.toISOString().substring(0, 19).replace('T', ' ');
4508 } else {
4509 return d.toISOString().substring(0, 10);
4510 }
4511 }
4512
4513 const setDate = function(d, update) {
4514 if (Array.isArray(d)) {
4515 d = new Date(Date.UTC(...d));
4516 } else if (typeof(d) === 'string') {
4517 d = new Date(d);
4518 }
4519
4520 // Update the date
4521 let value = d.toISOString().substring(0,10).split('-');
4522 let month = Helpers.months[parseInt(value[1])-1];
4523 let year = parseInt(value[0]);
4524
4525 if (self.month !== month) {
4526 self.month = month;
4527 }
4528 if (self.year !== year) {
4529 self.year = year;
4530 }
4531
4532 // Update the time
4533 let time = d.toISOString().substring(11,19).split(':');
4534 let hour = parseInt(time[0]);
4535 let minute = parseInt(time[1]);
4536
4537 if (self.hour !== hour) {
4538 self.hour = hour;
4539 }
4540 if (self.minute !== minute) {
4541 self.minute = minute;
4542 }
4543
4544 // Update internal date
4545 date = d;
4546
4547 // Update cursor information
4548 if (update) {
4549 updateCursor();
4550 }
4551 }
4552
4553 const updateCursor = function() {
4554 self.cursor.y = date.getUTCFullYear();
4555 self.cursor.m = date.getUTCMonth();
4556 self.cursor.d = date.getUTCDate();
4557 }
4558
4559 const resetCursor = function() {
4560 // Remove selection from the current object
4561 let current = self.cursor.current;
4562 // Current item
4563 if (typeof current !== 'undefined') {
4564 current.selected = false;
4565 }
4566 }
4567
4568 const setCursor = function(s) {
4569 // Reset current visual cursor
4570 resetCursor();
4571 // Update cursor based on the object position
4572 if (s) {
4573 // Update current
4574 self.cursor.current = s;
4575 // Update selected property
4576 s.selected = true;
4577 }
4578
4579 updateCursor();
4580
4581 // Update range
4582 if (isTrue(self.range)) {
4583 updateRange(s)
4584 }
4585
4586 Dispatch.call(self, self.onupdate, 'update', {
4587 instance: self,
4588 value: date.toISOString(),
4589 });
4590 }
4591
4592 const select = function(e, s) {
4593 // Get new date content
4594 let d = updateDate(s.value, getPosition());
4595 // New date
4596 setDate(new Date(Date.UTC(...d)))
4597 // Based where was the click
4598 if (self.view !== 'days') {
4599 // Back to the days
4600 self.view = 'days';
4601 } else if (! s.disabled) {
4602 if (isTrue(self.range)) {
4603 // Start a new range
4604 if (self.rangeValues && (self.rangeValues[0] >= s.number || self.rangeValues[1])) {
4605 destroyRange();
4606 }
4607 // Range
4608 s.range = true;
4609 // Update range
4610 if (! self.rangeValues) {
4611 s.start = true;
4612 self.rangeValues = [s.number, null];
4613 } else {
4614 s.end = true;
4615 self.rangeValues[1] = s.number;
4616 }
4617 setCursor(s);
4618 } else {
4619 setCursor(s);
4620
4621 update(e);
4622 }
4623 }
4624 }
4625
4626 // Update Calendar
4627 const update = function(e) {
4628 self.setValue(getValue());
4629
4630 if (! (e && e.type === 'click' && e.target.tagName === 'DIV' && self.time === true)) {
4631 self.close({ origin: 'button' });
4632 }
4633 }
4634
4635 const reset = function() {
4636 self.setValue('');
4637 self.close({ origin: 'button' });
4638 }
4639
4640 const updateDate = function(v, position) {
4641 // Current internal date
4642 let value = [date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), self.hour, self.minute, 0];
4643 // Update internal date
4644 value[position] = v;
4645 // Return new value
4646 return value;
4647 }
4648
4649 const move = function(direction) {
4650 // Reset visual cursor
4651 resetCursor();
4652
4653 // Value
4654 let value;
4655
4656 // Update the new internal date
4657 if (self.view === 'days') {
4658 // Select the new internal date
4659 value = updateDate(date.getUTCMonth()+direction, 1);
4660 } else if (self.view === 'months') {
4661 // Select the new internal date
4662 value = updateDate(date.getUTCFullYear()+direction, 0);
4663 } else if (self.view === 'years') {
4664 // Select the new internal date
4665 value = updateDate(date.getUTCFullYear()+(direction*16), 0);
4666 }
4667
4668 // Update view
4669 setDate(value);
4670
4671 // Reload content of the view
4672 reloadView();
4673 }
4674
4675 const getJump = function(e) {
4676 if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
4677 return self.view === 'days' ? 7 : 4;
4678 }
4679
4680 return 1;
4681 }
4682
4683 const prev = function(e) {
4684 if (e && e.type === 'keydown') {
4685 // Current index
4686 let total = self.options.length;
4687 let position = self.options.indexOf(self.cursor.current) - getJump(e);
4688 if (position < 0) {
4689 // Next month
4690 move(-1);
4691 // New position
4692 position = total + position;
4693 }
4694 // Update cursor
4695 setCursor(self.options[position])
4696 } else {
4697 move(-1);
4698 }
4699 }
4700
4701 const next = function(e) {
4702 if (e && e.type === 'keydown') {
4703 // Current index
4704 let total = self.options.length;
4705 let position = self.options.indexOf(self.cursor.current) + getJump(e);
4706 if (position >= total) {
4707 // Next month
4708 move(1);
4709 // New position
4710 position = position - total;
4711 }
4712 // Update cursor
4713 setCursor(self.options[position])
4714 } else {
4715 move(1);
4716 }
4717 }
4718
4719 const getInput = function() {
4720 let input = self.input;
4721 if (input && input.current) {
4722 input = input.current;
4723 } else {
4724 if (self.input) {
4725 input = self.input;
4726 }
4727 }
4728
4729 return input;
4730 }
4731
4732 const updateRange = function(s) {
4733 if (self.range && self.view === 'days' && self.rangeValues) {
4734 // Creating a range
4735 if (self.rangeValues[0] && ! self.rangeValues[1]) {
4736 let number = s.number;
4737 if (number) {
4738 // Update range properties
4739 for (let i = 0; i < self.options.length; i++) {
4740 let v = self.options[i].number;
4741 // Update property condition
4742 self.options[i].range = v >= self.rangeValues[0] && v <= number;
4743 self.options[i].last = (v === number);
4744 }
4745 }
4746 }
4747 }
4748 }
4749
4750 const destroyRange = function() {
4751 if (self.range) {
4752 for (let i = 0; i < self.options.length; i++) {
4753 if (self.options[i].range !== false) {
4754 self.options[i].range = false;
4755 }
4756 if (self.options[i].start !== false) {
4757 self.options[i].start = false;
4758 }
4759 if (self.options[i].end !== false) {
4760 self.options[i].end = false;
4761 }
4762 if (self.options[i].last !== false) {
4763 self.options[i].last = false;
4764 }
4765 }
4766 self.rangeValues = null;
4767 }
4768 }
4769
4770 const render = function(v) {
4771 if (v) {
4772 if (! Array.isArray(v)) {
4773 v = v.toString().split(',');
4774 }
4775
4776 v = v.map(entry => {
4777 return Mask.render(entry, self.format || 'YYYY-MM-DD');
4778 }).join(',');
4779 }
4780 return v;
4781 }
4782
4783 const normalize = function(v) {
4784 if (! Array.isArray(v)) {
4785 v = v.toString().split(',');
4786 }
4787
4788 return v.map(item => {
4789 if (Number(item) == item) {
4790 return Helpers.numToDate(item);
4791 } else {
4792 if (Helpers.isValidDateFormat(item)) {
4793 return item;
4794 } else if (self.format) {
4795 let tmp = Mask.extractDateFromString(item, self.format);
4796 if (tmp) {
4797 return tmp;
4798 }
4799 }
4800 }
4801 })
4802 }
4803
4804 const extractValueFromInput = function() {
4805 let input = getInput();
4806 if (input) {
4807 let v;
4808 if (input.tagName === 'INPUT' || input.tagName === 'TEXTAREA') {
4809 v = input.value;
4810 } else if (input.isContentEditable) {
4811 v = input.textContent;
4812 }
4813 if (v) {
4814 return normalize(v).join(',');
4815 }
4816 return v;
4817 }
4818 }
4819
4820 const onopen = function() {
4821 let isEditable = false;
4822 let value = self.value;
4823
4824 let input = getInput();
4825 if (input) {
4826 if (input.tagName === 'INPUT' || input.tagName === 'TEXTAREA') {
4827 isEditable = !input.hasAttribute('readonly') && !input.hasAttribute('disabled');
4828 } else if (input.isContentEditable) {
4829 isEditable = true;
4830 }
4831
4832 let ret = extractValueFromInput();
4833 if (ret && ret !== value) {
4834 value = ret;
4835 }
4836 }
4837
4838 if (! isEditable) {
4839 self.content.focus();
4840 }
4841
4842 // Update the internal date values
4843 setValue(value);
4844
4845 // Open event
4846 Dispatch.call(self, self.onopen, 'open', {
4847 instance: self
4848 });
4849 }
4850
4851 const onclose = function(modal, origin) {
4852 // Cancel range events
4853 destroyRange();
4854 // Close event
4855 Dispatch.call(self, self.onclose, 'close', {
4856 instance: self,
4857 origin: origin,
4858 });
4859 }
4860
4861 const dispatchOnChangeEvent = function() {
4862 // Destroy range
4863 destroyRange();
4864 // Update the internal controllers
4865 setValue(self.value);
4866 // Events
4867 Dispatch.call(self, change, 'change', {
4868 instance: self,
4869 value: self.value,
4870 });
4871 // Update input
4872 let input = getInput();
4873 if (input) {
4874 // Update input value
4875 input.value = render(self.value);
4876 // Dispatch event
4877 Dispatch.call(input, null, 'change', {
4878 instance: self,
4879 value: self.value,
4880 });
4881 }
4882 }
4883
4884 const events = {
4885 focusin: (e) => {
4886 if (self.modal && self.isClosed()) {
4887 self.open();
4888 }
4889 },
4890 focusout: (e) => {
4891 if (self.modal && ! self.isClosed()) {
4892 if (! (e.relatedTarget && self.modal.el.contains(e.relatedTarget))) {
4893 self.modal.close({ origin: 'focusout' });
4894 }
4895 }
4896 },
4897 click: (e) => {
4898 if (e.target.classList.contains('lm-calendar-input')) {
4899 self.open();
4900 }
4901 },
4902 keydown: (e) => {
4903 if (self.modal) {
4904 if (e.code === 'ArrowUp' || e.code === 'ArrowDown') {
4905 if (! self.isClosed()) {
4906 self.content.focus();
4907 } else {
4908 self.open();
4909 }
4910 } else if (e.code === 'Enter') {
4911 if (! self.isClosed()) {
4912 update(e);
4913 } else {
4914 self.open();
4915 }
4916 } else if (e.code === 'Escape') {
4917 if (! self.isClosed()) {
4918 self.modal.close({origin: 'escape'});
4919 }
4920 }
4921 }
4922 },
4923 input: (e) => {
4924 let input = e.target;
4925 if (input.classList.contains('lm-calendar-input')) {
4926 if (! isTrue(self.range)) {
4927 // TODO: process with range
4928 // Apply mask
4929 if (self.format) {
4930 Mask.oninput(e, self.format);
4931 }
4932 let value = null;
4933 // Content
4934 let content = (input.tagName === 'INPUT' || input.tagName === 'TEXTAREA') ? input.value : input.textContent;
4935 // Check if that is a valid date
4936 if (Helpers.isValidDateFormat(content)) {
4937 value = content;
4938 } else if (self.format) {
4939 let tmp = Mask.extractDateFromString(content, self.format);
4940 if (tmp) {
4941 value = tmp;
4942 }
4943 }
4944 // Change the calendar view
4945 if (value) {
4946 setValue(value);
4947 }
4948 }
4949 }
4950 }
4951 }
4952
4953 // Onload
4954 onload(() => {
4955 if (self.type !== "inline") {
4956 // Create modal instance
4957 self.modal = {
4958 width: 300,
4959 closed: true,
4960 focus: false,
4961 onopen: onopen,
4962 onclose: onclose,
4963 position: 'absolute',
4964 'auto-close': false,
4965 'auto-adjust': true,
4966 };
4967 // Generate modal
4968 Modal(self.el, self.modal);
4969 }
4970
4971 let ret;
4972
4973 // Create input controls
4974 if (self.input && self.initInput !== false) {
4975 if (! self.input.parentNode) {
4976 self.el.parentNode.insertBefore(self.input, self.el);
4977 }
4978
4979 let input = getInput();
4980 if (input && input.tagName) {
4981 input.classList.add('lm-input');
4982 input.classList.add('lm-calendar-input');
4983 input.addEventListener('click', events.click);
4984 input.addEventListener('input', events.input);
4985 input.addEventListener('keydown', events.keydown);
4986 input.addEventListener('focusin', events.focusin);
4987 input.addEventListener('focusout', events.focusout);
4988 if (self.placeholder) {
4989 input.setAttribute('placeholder', self.placeholder);
4990 }
4991 if (self.onChange) {
4992 input.addEventListener('change', self.onChange);
4993 }
4994
4995 // Retrieve the value
4996 if (self.value) {
4997 input.value = render(self.value);
4998 } else {
4999 let value = extractValueFromInput();
5000 if (value && value !== self.value) {
5001 ret = value;
5002 }
5003 }
5004 }
5005 }
5006
5007 // Update the internal date values
5008 if (ret) {
5009 self.setValue(ret);
5010 } else {
5011 setValue(self.value);
5012 }
5013
5014 // Reload view
5015 reloadView(true);
5016
5017 /**
5018 * Handler keyboard
5019 * @param {object} e - event
5020 */
5021 self.el.addEventListener('keydown', function(e) {
5022 let prevent = false;
5023 if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
5024 if (e.target !== self.content) {
5025 self.content.focus();
5026 }
5027 prev(e);
5028 prevent = true;
5029 } else if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
5030 if (e.target !== self.content) {
5031 self.content.focus();
5032 }
5033 next(e);
5034 prevent = true;
5035 } else if (e.key === 'Enter') {
5036 if (e.target === self.content) {
5037 // Item
5038 if (self.cursor.current) {
5039 // Select
5040 select(e, self.cursor.current);
5041 prevent = true;
5042 }
5043 }
5044 } else if (e.key === 'Escape') {
5045 if (! self.isClosed()) {
5046 self.close({ origin: 'escape' });
5047 prevent = true;
5048 }
5049 }
5050
5051 if (prevent) {
5052 e.preventDefault();
5053 e.stopImmediatePropagation();
5054 }
5055 });
5056
5057 /**
5058 * Mouse wheel handler
5059 * @param {object} e - mouse event
5060 */
5061 self.content.addEventListener('wheel', function(e){
5062 if (self.wheel !== false) {
5063 if (e.deltaY < 0) {
5064 prev(e);
5065 } else {
5066 next(e);
5067 }
5068 e.preventDefault();
5069 }
5070 }, { passive: false });
5071
5072 /**
5073 * Range handler
5074 * @param {object} e - mouse event
5075 */
5076 self.content.addEventListener('mouseover', function(e){
5077 let parent = e.target.parentNode
5078 if (parent === self.content) {
5079 let index = Array.prototype.indexOf.call(parent.children, e.target);
5080 updateRange(self.options[index]);
5081 }
5082 });
5083
5084 // Create event for focus out
5085 self.el.addEventListener("focusout", (e) => {
5086 let input = getInput();
5087 if (e.relatedTarget !== input && ! self.el.contains(e.relatedTarget)) {
5088 self.close({ origin: 'focusout' });
5089 }
5090 });
5091 });
5092
5093 onchange((prop) => {
5094 if (prop === 'view') {
5095 reloadView(true);
5096 } else if (prop === 'startingDay') {
5097 self.weekdays = getWeekdays(self.startingDay ?? 0);
5098 } else if (prop === 'value') {
5099 dispatchOnChangeEvent();
5100 }
5101 })
5102
5103 // Tracking variables
5104 track('value');
5105
5106 // Public methods
5107
5108 self.open = function(e) {
5109 if (self.modal) {
5110 if (self.type === 'auto') {
5111 self.type = window.innerWidth > 640 ? self.type = 'default' : 'picker';
5112 }
5113 self.modal.open();
5114 }
5115 }
5116
5117 self.close = function(options) {
5118 if (self.modal) {
5119 if (options && options.origin) {
5120 self.modal.close(options)
5121 } else {
5122 self.modal.close({ origin: 'button' })
5123 }
5124 }
5125 }
5126
5127 self.isClosed = function() {
5128 if (self.modal) {
5129 return self.modal.isClosed();
5130 }
5131 }
5132
5133 self.getValue = function() {
5134 return self.value;
5135 }
5136
5137 self.setValue = function(v) {
5138 // Update value
5139 if (v) {
5140 let ret = normalize(v);
5141 if (isTrue(self.numeric)) {
5142 ret = ret.map(entry => {
5143 return Helpers.dateToNum(entry);
5144 })
5145 }
5146
5147 if (! Array.isArray(v)) {
5148 ret = ret.join(',');
5149 }
5150
5151 if (ret == Number(ret)) {
5152 ret = Number(ret);
5153 }
5154
5155 v = ret;
5156 }
5157
5158 // Events
5159 if (v !== self.value) {
5160 self.value = v;
5161 }
5162 }
5163
5164 self.onevent = function(e) {
5165 if (events[e.type]) {
5166 events[e.type](e);
5167 }
5168 }
5169
5170 self.update = update;
5171 self.next = next;
5172 self.prev = prev;
5173 self.reset = reset;
5174 self.setView = setView;
5175 self.helpers = Helpers;
5176 self.helpers.getDate = Mask.getDate;
5177
5178 return render => render`<div class="lm-calendar" data-grid="{{self.grid}}" data-type="{{self.type}}" data-disabled="{{self.disabled}}" data-starting-day="{{self.startingDay}}">
5179 <div class="lm-calendar-options">
5180 <button type="button" onclick="${reset}">${T('Reset')}</button>
5181 <button type="button" onclick="${update}">${T('Done')}</button>
5182 </div>
5183 <div class="lm-calendar-container" data-view="{{self.view}}">
5184 <div class="lm-calendar-header">
5185 <div>
5186 <div class="lm-calendar-labels"><button type="button" onclick="${setView}" data-view="months">{{self.month}}</button> <button type="button" onclick="${setView}" data-view="years">{{self.year}}</button></div>
5187 <div class="lm-calendar-navigation">
5188 <button type="button" class="lm-calendar-icon lm-ripple" onclick="${prev}" tabindex="0">expand_less</button>
5189 <button type="button" class="lm-calendar-icon lm-ripple" onclick="${next}" tabindex="0">expand_more</button>
5190 </div>
5191 </div>
5192 <div class="lm-calendar-weekdays" :loop="self.weekdays"><div>{{self.title}}</div></div>
5193 </div>
5194 <div class="lm-calendar-content" :loop="self.options" tabindex="0" :ref="self.content">
5195 <div data-start="{{self.start}}" data-end="{{self.end}}" data-last="{{self.last}}" data-range="{{self.range}}" data-event="{{self.data}}" data-grey="{{self.grey}}" data-bold="{{self.bold}}" data-selected="{{self.selected}}" data-disabled="{{self.disabled}}" onclick="${select}">{{self.title}}</div>
5196 </div>
5197 <div class="lm-calendar-footer" data-visible="{{self.footer}}">
5198 <div class="lm-calendar-time" data-visible="{{self.time}}"><select :loop="${hours}" :bind="self.hour" class="lm-calendar-control"><option value="{{self.value}}">{{self.title}}</option></select>:<select :loop="${minutes}" :bind="self.minute" class="lm-calendar-control"><option value="{{self.value}}">{{self.title}}</option></select></div>
5199 <div class="lm-calendar-update"><input type="button" value="${T('Update')}" onclick="${update}" class="lm-ripple lm-input"></div>
5200 </div>
5201 </div>
5202 </div>`
5203 }
5204
5205 // Register the LemonadeJS Component
5206 lemonade.setComponents({ Calendar: Calendar });
5207 // Register the web component
5208 lemonade.createWebComponent('calendar', Calendar);
5209
5210 return function (root, options) {
5211 if (typeof (root) === 'object') {
5212 lemonade.render(Calendar, root, options)
5213 return options;
5214 } else {
5215 return Calendar.call(this, root)
5216 }
5217 }
5218})));
5219
5220/***/ }),
5221
5222/***/ 541:
5223/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
5224
5225if (! lemonade && "function" === 'function') {
5226 var lemonade = __webpack_require__(966);
5227}
5228
5229if (! Modal && "function" === 'function') {
5230 var Modal = __webpack_require__(72);
5231}
5232
5233if (! Tabs && "function" === 'function') {
5234 var Tabs = __webpack_require__(560);
5235}
5236
5237; (function (global, factory) {
5238 true ? module.exports = factory() :
5239 0;
5240}(this, (function () {
5241
5242 // Dispatcher
5243 const Dispatch = function(method, type, options) {
5244 // Try calling the method directly if provided
5245 if (typeof method === 'function') {
5246 let a = Object.values(options);
5247 method(...a);
5248 } else if (this.tagName) {
5249 // Fallback: dispatch a custom event
5250 const event = new CustomEvent(type, {
5251 bubbles: true,
5252 cancelable: true,
5253 detail: options,
5254 });
5255 this.dispatchEvent(event);
5256 }
5257 }
5258
5259 const defaultPalette = [
5260 ["#ffebee", "#fce4ec", "#f3e5f5", "#e8eaf6", "#e3f2fd", "#e0f7fa", "#e0f2f1", "#e8f5e9", "#f1f8e9", "#f9fbe7", "#fffde7", "#fff8e1", "#fff3e0", "#fbe9e7", "#efebe9", "#fafafa", "#eceff1"],
5261 ["#ffcdd2", "#f8bbd0", "#e1bee7", "#c5cae9", "#bbdefb", "#b2ebf2", "#b2dfdb", "#c8e6c9", "#dcedc8", "#f0f4c3", "#fff9c4", "#ffecb3", "#ffe0b2", "#ffccbc", "#d7ccc8", "#f5f5f5", "#cfd8dc"],
5262 ["#ef9a9a", "#f48fb1", "#ce93d8", "#9fa8da", "#90caf9", "#80deea", "#80cbc4", "#a5d6a7", "#c5e1a5", "#e6ee9c", "#fff59d", "#ffe082", "#ffcc80", "#ffab91", "#bcaaa4", "#eeeeee", "#b0bec5"],
5263 ["#e57373", "#f06292", "#ba68c8", "#7986cb", "#64b5f6", "#4dd0e1", "#4db6ac", "#81c784", "#aed581", "#dce775", "#fff176", "#ffd54f", "#ffb74d", "#ff8a65", "#a1887f", "#e0e0e0", "#90a4ae"],
5264 ["#ef5350", "#ec407a", "#ab47bc", "#5c6bc0", "#42a5f5", "#26c6da", "#26a69a", "#66bb6a", "#9ccc65", "#d4e157", "#ffee58", "#ffca28", "#ffa726", "#ff7043", "#8d6e63", "#bdbdbd", "#78909c"],
5265 ["#f44336", "#e91e63", "#9c27b0", "#3f51b5", "#2196f3", "#00bcd4", "#009688", "#4caf50", "#8bc34a", "#cddc39", "#ffeb3b", "#ffc107", "#ff9800", "#ff5722", "#795548", "#9e9e9e", "#607d8b"],
5266 ["#e53935", "#d81b60", "#8e24aa", "#3949ab", "#1e88e5", "#00acc1", "#00897b", "#43a047", "#7cb342", "#c0ca33", "#fdd835", "#ffb300", "#fb8c00", "#f4511e", "#6d4c41", "#757575", "#546e7a"],
5267 ["#d32f2f", "#c2185b", "#7b1fa2", "#303f9f", "#1976d2", "#0097a7", "#00796b", "#388e3c", "#689f38", "#afb42b", "#fbc02d", "#ffa000", "#f57c00", "#e64a19", "#5d4037", "#616161", "#455a64"],
5268 ["#c62828", "#ad1457", "#6a1b9a", "#283593", "#1565c0", "#00838f", "#00695c", "#2e7d32", "#558b2f", "#9e9d24", "#f9a825", "#ff8f00", "#ef6c00", "#d84315", "#4e342e", "#424242", "#37474f"],
5269 ["#b71c1c", "#880e4f", "#4a148c", "#1a237e", "#0d47a1", "#006064", "#004d40", "#1b5e20", "#33691e", "#827717", "#f57f17", "#ff6f00", "#e65100", "#bf360c", "#3e2723", "#212121", "#263238"],
5270 ]
5271
5272 const Grid = function(children, { onchange }) {
5273 const self = this;
5274
5275 if (! self.palette) {
5276 self.palette = defaultPalette;
5277 }
5278
5279 const select = (event) => {
5280 if (event.target.tagName === 'TD') {
5281 let color = event.target.getAttribute('data-value')
5282
5283 // Remove current selected mark
5284 let selected = self.el.querySelector('.lm-color-selected');
5285 if (selected) {
5286 selected.classList.remove('lm-color-selected');
5287 }
5288
5289 // Mark cell as selected
5290 if (color) {
5291 event.target.classList.add('lm-color-selected');
5292 self.set(color);
5293 }
5294 }
5295 }
5296
5297 self.constructRows = function (e) {
5298 let tbody = [];
5299 e.textContent = '';
5300 for (let j = 0; j < self.palette.length; j++) {
5301 let tr = document.createElement('tr');
5302 e.appendChild(tr);
5303
5304 for (let i = 0; i < self.palette[j].length; i++) {
5305 let color = self.palette[j][i];
5306 let td = document.createElement('td');
5307 td.setAttribute('data-value', color);
5308 td.style.backgroundColor = color;
5309 tr.appendChild(td);
5310 }
5311 }
5312 }
5313
5314 onchange(property => {
5315 if (property === 'palette') {
5316 self.constructRows()
5317 }
5318 });
5319
5320 return render => render`<div class="lm-color-grid" :palette="self.palette">
5321 <table cellpadding="7" cellspacing="0" onclick="${select}" :ref="self.table" :ready="self.constructRows"></table>
5322 </div>`
5323 }
5324
5325 const Spectrum = function(children, { onload }) {
5326 let self = this;
5327 let context = null;
5328
5329 let decToHex = function(num) {
5330 let hex = num.toString(16);
5331 return hex.length === 1 ? "0" + hex : hex;
5332 }
5333 let rgbToHex = function(r, g, b) {
5334 return "#" + decToHex(r) + decToHex(g) + decToHex(b);
5335 }
5336
5337 onload(() => {
5338 context = self.canvas.getContext("2d", { willReadFrequently: true });
5339 draw();
5340 })
5341
5342 // Drsaw
5343 const draw = function() {
5344 let g = context.createLinearGradient(0, 0, self.canvas.width, 0);
5345 // Create color gradient
5346 g.addColorStop(0, "rgb(255,0,0)");
5347 g.addColorStop(0.15, "rgb(255,0,255)");
5348 g.addColorStop(0.33, "rgb(0,0,255)");
5349 g.addColorStop(0.49, "rgb(0,255,255)");
5350 g.addColorStop(0.67, "rgb(0,255,0)");
5351 g.addColorStop(0.84, "rgb(255,255,0)");
5352 g.addColorStop(1, "rgb(255,0,0)");
5353 context.fillStyle = g;
5354 context.fillRect(0, 0, self.canvas.width, self.canvas.height);
5355 g = context.createLinearGradient(0, 0, 0, self.canvas.height);
5356 g.addColorStop(0, "rgba(255,255,255,1)");
5357 g.addColorStop(0.5, "rgba(255,255,255,0)");
5358 g.addColorStop(0.5, "rgba(0,0,0,0)");
5359 g.addColorStop(1, "rgba(0,0,0,1)");
5360 context.fillStyle = g;
5361 context.fillRect(0, 0, self.canvas.width, self.canvas.height);
5362 }
5363
5364 // Moves the marquee point to the specified position
5365 const update = (e) => {
5366 let x;
5367 let y;
5368 let buttons = 1;
5369 if (e.type === 'touchmove') {
5370 x = e.changedTouches[0].clientX;
5371 y = e.changedTouches[0].clientY;
5372 } else {
5373 buttons = e.buttons;
5374 x = e.clientX;
5375 y = e.clientY;
5376 }
5377
5378 if (buttons === 1) {
5379 let rect = self.el.getBoundingClientRect();
5380 let left = x - rect.left;
5381 let top = y - rect.top;
5382 // Get the color in this pixel
5383 let pixel = context.getImageData(left, top, 1, 1).data;
5384 // Position pointer
5385 self.point.style.left = left + 'px';
5386 self.point.style.top = top + 'px';
5387 // Return color
5388 self.set(rgbToHex(pixel[0], pixel[1], pixel[2]));
5389 }
5390 }
5391
5392 return render => render`<div class="lm-color-hsl">
5393 <canvas width="240" height="140" :ref="self.canvas" onmousedown="${update}" onmousemove="${update}" ontouchmove="${update}"></canvas>
5394 <div class="lm-color-point" :ref="self.point"></div>
5395 </div>`;
5396 }
5397
5398 const Color = function(children, { onchange, onload }) {
5399 let self = this;
5400 let value = null;
5401
5402 const change = self.onchange;
5403 self.onchange = null;
5404
5405 // Decide the type based on the size of the screen
5406 let autoType = self.type === 'auto';
5407
5408 const applyValue = function(v) {
5409 if (self.value !== v) {
5410 self.value = v;
5411 }
5412 }
5413
5414 const onopen = function(e) {
5415 self.open();
5416 // Open event
5417 Dispatch.call(self, self.onopen, 'open', {
5418 instance: self
5419 });
5420 }
5421
5422 const onclose = function(modal, origin) {
5423 // Close event
5424 Dispatch.call(self, self.onclose, 'close', {
5425 instance: self,
5426 origin: origin,
5427 });
5428 }
5429
5430 const update = function() {
5431 applyValue(value);
5432 self.close({ origin: 'button' });
5433 }
5434
5435 const getInput = function() {
5436 let input = self.input;
5437 if (input && input.current) {
5438 input = input.current;
5439 } else {
5440 if (self.input) {
5441 input = self.input;
5442 }
5443 }
5444
5445 return input;
5446 }
5447
5448 const events = {
5449 focusin: (e) => {
5450 if (self.modal && self.isClosed()) {
5451 self.open();
5452 }
5453 },
5454 focusout: (e) => {
5455 if (self.modal && ! self.isClosed()) {
5456 if (! (e.relatedTarget && self.modal.el.contains(e.relatedTarget))) {
5457 self.modal.close({ origin: 'focusout' });
5458 }
5459 }
5460 },
5461 click: (e) => {
5462 if (e.target.classList.contains('lm-color-input')) {
5463 self.open();
5464 }
5465 },
5466 keydown: (e) => {
5467 if (self.modal) {
5468 if (e.code === 'ArrowUp' || e.code === 'ArrowDown') {
5469 if (self.isClosed()) {
5470 self.open();
5471 }
5472 } else if (e.code === 'Enter') {
5473 if (! self.isClosed()) {
5474 update();
5475 } else {
5476 self.open();
5477 }
5478 } else if (e.code === 'Escape') {
5479 if (! self.isClosed()) {
5480 self.modal.close({origin: 'escape'});
5481 }
5482 }
5483 }
5484 }
5485 }
5486
5487 const set = function(v) {
5488 value = v;
5489 // Close
5490 if (self.closeOnChange === true) {
5491 // Update value
5492 self.setValue(v);
5493 // Close modal
5494 self.close({ origin: 'select' });
5495 }
5496 }
5497
5498 self.open = function(e) {
5499 if (self.modal) {
5500 if (autoType) {
5501 self.type = window.innerWidth > 640 ? self.type = 'default' : 'picker';
5502 }
5503 value = self.value;
5504 // Table
5505 let table = self.grid.table;
5506 // Remove any selection
5507 let o = table.querySelector('.lm-color-selected');
5508 if (o) {
5509 o.classList.remove('lm-color-selected');
5510 }
5511 // Selected
5512 o = table.querySelector('[data-value="'+self.value+'"]');
5513 if (o) {
5514 o.classList.add('lm-color-selected');
5515 }
5516 // Open modal
5517 self.modal.open();
5518 }
5519 }
5520
5521 /**
5522 * Close the modal
5523 */
5524 self.close = function(options) {
5525 if (self.modal) {
5526 if (options && options.origin) {
5527 self.modal.close(options)
5528 } else {
5529 self.modal.close({ origin: 'button' })
5530 }
5531 }
5532 }
5533
5534 self.isClosed = function() {
5535 if (self.modal) {
5536 return self.modal.isClosed();
5537 }
5538 }
5539
5540 self.reset = function() {
5541 self.setValue('');
5542 self.close({ origin: 'button' });
5543 }
5544
5545 self.setValue = function(v) {
5546 self.value = value = v;
5547 }
5548
5549 self.getValue = function() {
5550 return self.value;
5551 }
5552
5553 self.onevent = function(e) {
5554 if (events[e.type]) {
5555 events[e.type](e);
5556 }
5557 }
5558
5559 onchange(prop => {
5560 if (prop === 'value') {
5561 let input = getInput();
5562 if (input) {
5563 input.value = self.value;
5564 if (self.value) {
5565 input.style.color = self.value;
5566 } else {
5567 input.style.color = '';
5568 }
5569 }
5570
5571 Dispatch.call(self, change, 'change', {
5572 instance: self,
5573 value: self.value,
5574 });
5575 }
5576 });
5577
5578 // Input
5579 if (self.input === 'auto') {
5580 self.input = document.createElement('input');
5581 self.input.type = 'text';
5582 }
5583
5584 onload(() => {
5585 if (self.type !== "inline") {
5586 // Create modal instance
5587 self.modal = {
5588 closed: true,
5589 onopen: onopen,
5590 onclose: onclose,
5591 focus: false,
5592 position: 'absolute',
5593 'auto-close': false,
5594 'auto-adjust': true,
5595 };
5596 // Generate modal
5597 Modal(self.el, self.modal);
5598 }
5599
5600 // Create input controls
5601 if (self.input && self.initInput !== false) {
5602 if (! self.input.parentNode) {
5603 self.el.parentNode.insertBefore(self.input, self.el);
5604 }
5605
5606 let input = getInput();
5607 if (input && input.tagName) {
5608 input.classList.add('lm-input');
5609 input.classList.add('lm-color-input');
5610 input.addEventListener('click', events.click);
5611 input.addEventListener('focusin', events.focusin);
5612 input.addEventListener('focusout', events.focusout);
5613 if (self.placeholder) {
5614 input.setAttribute('placeholder', self.placeholder);
5615 }
5616 if (self.onChange) {
5617 input.addEventListener('change', self.onChange);
5618 }
5619
5620 // Retrieve the value
5621 if (self.value) {
5622 input.value = self.value;
5623 } else if (input.value && input.value !== self.value) {
5624 self.value = input.value;
5625 }
5626 }
5627 }
5628
5629 // Create event for focus out
5630 self.el.addEventListener("focusout", (e) => {
5631 let input = getInput();
5632 if (e.relatedTarget !== input && ! self.el.contains(e.relatedTarget)) {
5633 self.close({ origin: 'focusout' });
5634 }
5635 });
5636 });
5637
5638 return render => render`<div class="lm-color" :value="self.value">
5639 <div class="lm-color-options">
5640 <button type="button" onclick="${self.reset}">Reset</button>
5641 <button type="button" onclick="${update}">Done</button>
5642 </div>
5643 <lm-tabs selected="0" position="center" :ref="self.tabs">
5644 <div title="Grid"><${Grid} :palette="self.palette" :ref="self.grid" :set="${set}" /></div>
5645 <div title="Spectrum"><${Spectrum} :ref="self.spectrum" :set="${set}" /></div>
5646 </lm-tabs>
5647 </div>`;
5648 }
5649
5650 lemonade.setComponents({ Color: Color });
5651 // Register the web component
5652 lemonade.createWebComponent('color', Color);
5653
5654 return function (root, options) {
5655 if (typeof (root) === 'object') {
5656 lemonade.render(Color, root, options)
5657 return options;
5658 } else {
5659 return Color.call(this, root)
5660 }
5661 }
5662})));
5663
5664/***/ }),
5665
5666/***/ 238:
5667/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
5668
5669if (! lemonade && "function" === 'function') {
5670 var lemonade = __webpack_require__(966);
5671}
5672
5673if (! Modal && "function" === 'function') {
5674 var Modal = __webpack_require__(72);
5675}
5676
5677; (function (global, factory) {
5678 true ? module.exports = factory() :
5679 0;
5680}(this, (function () {
5681
5682 class CustomEvents extends Event {
5683 constructor(type, props, options) {
5684 super(type, {
5685 bubbles: true,
5686 composed: true,
5687 ...options,
5688 });
5689
5690 if (props) {
5691 for (const key in props) {
5692 // Avoid assigning if property already exists anywhere on `this`
5693 if (! (key in this)) {
5694 this[key] = props[key];
5695 }
5696 }
5697 }
5698 }
5699 }
5700
5701 // Dispatcher
5702 const Dispatch = function(method, type, options) {
5703 // Try calling the method directly if provided
5704 if (typeof method === 'function') {
5705 let a = Object.values(options);
5706 return method(...a);
5707 } else if (this.tagName) {
5708 this.dispatchEvent(new CustomEvents(type, options));
5709 }
5710 }
5711
5712 // Get the coordinates of the action
5713 const getCoords = function(e) {
5714 let x;
5715 let y;
5716
5717 if (e.changedTouches && e.changedTouches[0]) {
5718 x = e.changedTouches[0].clientX;
5719 y = e.changedTouches[0].clientY;
5720 } else {
5721 x = e.clientX;
5722 y = e.clientY;
5723 }
5724
5725 return [x,y];
5726 }
5727
5728 const Item = function() {
5729 let self = this;
5730
5731 self.onload = function() {
5732 if (typeof(self.render) === 'function') {
5733 self.render.call(self, self.el);
5734 }
5735 }
5736
5737 // Initialize expanded state
5738 self.expanded = false;
5739
5740 if (self.type === 'line' || self.type === 'divisor') {
5741 return `<hr role="separator" />`;
5742 } else if (self.type === 'inline') {
5743 return `<div></div>`;
5744 } else {
5745 return `<div class="lm-menu-item" role="menuitem" data-disabled="{{self.disabled}}" data-cursor="{{self.cursor}}" data-icon="{{self.icon}}" title="{{self.tooltip}}" data-submenu="${!!self.submenu}" aria-haspopup="${!!self.submenu}" aria-expanded="{{self.expanded}}" aria-label="{{self.title}}" tabindex="-1" onmouseup="self.parent.mouseUp" onmouseenter="self.parent.mouseEnter" onmouseleave="self.parent.mouseLeave">
5746 <span>{{self.title}}</span> <div>{{self.shortcut}}</div>
5747 </div>`;
5748 }
5749 }
5750
5751 const Create = function() {
5752 let self = this;
5753
5754 // Delay on open
5755 let delayTimer;
5756 // Save the position of this modal
5757 let index = self.parent.modals.length;
5758
5759 // Blank options
5760 self.options = [];
5761
5762 // Close handler
5763 self.onclose = function() {
5764 // Reset any cursor
5765 resetCursor.call(self);
5766 // Parent
5767 if (typeof(self.parent.onclose) === 'function') {
5768 self.parent.onclose(self.parent, self);
5769 }
5770 }
5771
5772 self.onopen = function() {
5773 // Parent
5774 if (typeof(self.parent.onopen) === 'function') {
5775 self.parent.onopen(self.parent, self);
5776 }
5777 }
5778
5779 /**
5780 * Close the modal
5781 */
5782 self.close = function() {
5783 // Close modals with higher level
5784 self.parent.close(index);
5785 }
5786
5787 /**
5788 * Open submenu handler
5789 * @param {object} s
5790 * @param {boolean} cursor - Activate the first item
5791 */
5792 self.open = function(s, cursor) {
5793 if (s.submenu) {
5794 // Get the modal in the container of modals
5795 let current = self.parent.modals[index+1];
5796 // Do not exist yet, create it.
5797 if (! current) {
5798 // Modal needs to be created
5799 current = self.parent.create();
5800 }
5801 // Get the parent from this one
5802 let parent = self.parent.modals[index];
5803 // Update modal content
5804 if (current.options !== s.submenu) {
5805 // Close modals with higher level
5806 current.options = s.submenu;
5807 // Close other modals
5808 self.parent.close(index+1);
5809 }
5810 // Update the selected modal
5811 self.parent.modalIndex = index+1;
5812 let rect = parent.modal.el.getBoundingClientRect();
5813 // Update modal
5814 current.modal.open();
5815
5816 // Calculate initial position using item's actual screen position (accounts for scroll)
5817 let itemRect = s.el.getBoundingClientRect();
5818 let submenuWidth = 250;
5819 let submenuTop = itemRect.y;
5820 let submenuLeft = rect.x + rect.width - 2; // Position to the right of parent
5821
5822 // Check if parent was positioned to the left (has negative margin or is on left side)
5823 let parentOpenedLeft = parent.openedLeft || false;
5824
5825 // Check horizontal space
5826 let spaceOnRight = window.innerWidth - (rect.x + rect.width);
5827 let spaceOnLeft = rect.x;
5828
5829 // Determine which side to open the submenu
5830 let openLeft = parentOpenedLeft; // Follow parent's direction by default
5831
5832 // If parent opened to right, check if we still have space
5833 if (!parentOpenedLeft && spaceOnRight < submenuWidth + 10) {
5834 // Not enough space on right, switch to left
5835 openLeft = true;
5836 }
5837 // If parent opened to left, check if we still have space on left
5838 if (parentOpenedLeft && spaceOnLeft < submenuWidth + 10) {
5839 // Not enough space on left, switch to right if possible
5840 if (spaceOnRight >= submenuWidth + 10) {
5841 openLeft = false;
5842 }
5843 }
5844
5845 if (openLeft) {
5846 // Position to the left of parent menu
5847 submenuLeft = rect.x - submenuWidth + 2;
5848 // Ensure it doesn't go off the left edge
5849 if (submenuLeft < 10) {
5850 submenuLeft = 10;
5851 }
5852 current.openedLeft = true;
5853 } else {
5854 current.openedLeft = false;
5855 }
5856
5857 // Set position
5858 current.modal.top = submenuTop;
5859 current.modal.left = submenuLeft;
5860
5861 // Adjust vertical position after render
5862 queueMicrotask(() => {
5863 let submenuEl = current.modal.el;
5864 let submenuRect = submenuEl.getBoundingClientRect();
5865
5866 // Check if submenu goes off the bottom
5867 if (submenuRect.bottom > window.innerHeight - 10) {
5868 let overflow = submenuRect.bottom - (window.innerHeight - 10);
5869 let newTop = submenuTop - overflow;
5870 // Don't go above the top of the screen
5871 if (newTop < 10) {
5872 newTop = 10;
5873 }
5874 current.modal.top = newTop;
5875 }
5876 });
5877
5878 // Keep current item for each modal
5879 current.item = s;
5880 s.expanded = true;
5881
5882 // Activate the cursor
5883 if (cursor === true) {
5884 // Place cursor in the first position
5885 current.options[0].cursor = true;
5886 // Position cursor
5887 current.cursor = 0;
5888 }
5889
5890 onopen(current, s.submenu)
5891 } else {
5892 // Close modals with higher level
5893 self.parent.close(index+1);
5894 }
5895 }
5896
5897 // Mouse open
5898 self.mouseUp = function(e, s) {
5899 if (typeof(s.onclick) === 'function') {
5900 s.onclick.call(s, e, s.el);
5901 }
5902 if (! s.submenu) {
5903 self.close();
5904 }
5905 }
5906
5907 self.mouseEnter = function(e, s) {
5908 if (delayTimer) {
5909 clearTimeout(delayTimer);
5910 }
5911 delayTimer = setTimeout(function() {
5912 self.open(s);
5913 }, 200);
5914 }
5915
5916 self.mouseLeave = function(e, s) {
5917 if (delayTimer) {
5918 clearTimeout(delayTimer);
5919 }
5920 }
5921
5922 let template = `<lm-modal :overflow="true" :closed="true" :ref="self.modal" :responsive="false" :auto-adjust="true" :focus="false" :layers="false" :onopen="self.onopen" :onclose="self.onclose">
5923 <div class="lm-menu-submenu" role="menu" aria-orientation="vertical">
5924 <Item :loop="self.options" />
5925 </div>
5926 </lm-modal>`;
5927
5928 return lemonade.element(template, self, { Item: Item });
5929 }
5930
5931 const findNextEnabledCursor = function(startIndex, direction) {
5932 if (!this.options || this.options.length === 0) {
5933 return null;
5934 }
5935
5936 let cursor = startIndex;
5937 let attempts = 0;
5938 const maxAttempts = this.options.length;
5939
5940 while (attempts < maxAttempts) {
5941 if (direction) {
5942 // Down
5943 if (cursor >= this.options.length) {
5944 cursor = 0;
5945 }
5946 } else {
5947 // Up
5948 if (cursor < 0) {
5949 cursor = this.options.length - 1;
5950 }
5951 }
5952
5953 let item = this.options[cursor];
5954 if (item && !item.disabled && item.type !== 'line') {
5955 return cursor;
5956 }
5957
5958 cursor = direction ? cursor + 1 : cursor - 1;
5959 attempts++;
5960 }
5961 return null;
5962 };
5963
5964 const setCursor = function(direction) {
5965 let cursor = null;
5966
5967 if (typeof(this.cursor) !== 'undefined') {
5968 if (! direction) {
5969 // Up
5970 cursor = findNextEnabledCursor.call(this, this.cursor - 1, false);
5971 } else {
5972 // Down
5973 cursor = findNextEnabledCursor.call(this, this.cursor + 1, true);
5974 }
5975 }
5976
5977 // Remove the cursor
5978 if (cursor === null) {
5979 if (direction) {
5980 cursor = findNextEnabledCursor.call(this, 0, true);
5981 } else {
5982 cursor = findNextEnabledCursor.call(this, this.options.length - 1, false);
5983 }
5984 } else if (typeof(this.cursor) !== 'undefined') {
5985 this.options[this.cursor].cursor = false;
5986 }
5987
5988 // Add the cursor if found
5989 if (cursor !== null) {
5990 this.options[cursor].cursor = true;
5991 this.cursor = cursor;
5992 return true;
5993 }
5994
5995 return false;
5996 }
5997
5998 /**
5999 * Reset the cursor for a contextmenu
6000 */
6001 const resetCursor = function() {
6002 // Contextmenu modal
6003 let item = this.options[this.cursor];
6004 // Cursor is found so reset it
6005 if (typeof(item) !== 'undefined') {
6006 // Remove the cursor style
6007 item.cursor = false;
6008 // Delete reference index
6009 delete this.cursor;
6010 }
6011 }
6012
6013 /**
6014 * Go through all items of a menu
6015 * @param s
6016 * @param options
6017 */
6018 const onopen = function(s, options) {
6019 // Onopen
6020 for (let i = 0; i < options.length; i++) {
6021 if (typeof(options[i].onopen) === 'function') {
6022 options[i].onopen(s);
6023 }
6024 }
6025 }
6026
6027 const Contextmenu = function(children, { onload }) {
6028 let self = this;
6029
6030 // Container for all modals
6031 self.modals = [];
6032 self.modalIndex = 0;
6033
6034 self.create = function() {
6035 // Create a new self for each modal
6036 let s = {
6037 parent: self,
6038 };
6039 // Render the modal inside the main container
6040 lemonade.render(Create, self.el, s);
6041 // Add the reference of the modal in a container#
6042 self.modals.push(s);
6043 // Return self
6044 return s;
6045 }
6046
6047 self.isClosed = function() {
6048 return self.modals[0].modal.closed === true;
6049 }
6050
6051 self.openAt = function(a, b) {
6052 let x, y;
6053 if (a instanceof Event || (a && a.clientX !== undefined)) {
6054 // openAt(event)
6055 x = a.clientX;
6056 y = a.clientY;
6057 } else {
6058 // openAt(x, y)
6059 x = a;
6060 y = b;
6061 }
6062 self.open(self.options, x, y, true);
6063 };
6064
6065 self.open = function(options, x, y, adjust) {
6066 // Get the main modal
6067 let menu = self.modals[0];
6068 // Reset cursor
6069 resetCursor.call(menu);
6070 // Define new position
6071 menu.modal.top = y;
6072 menu.modal.left = x;
6073 // Open
6074 menu.modal.open();
6075 // If the modal is open and the content is different from what is shown. Close modals with higher level
6076 self.close(1);
6077 // Update the data
6078 if (options && menu.options !== options) {
6079 // Refresh content
6080 menu.options = options;
6081 }
6082 onopen(self, options);
6083
6084 // Adjust position to respect mouse cursor after auto-adjust
6085 // Use queueMicrotask to ensure it runs after the modal's auto-adjust
6086 if (adjust === true) {
6087 queueMicrotask(() => {
6088 let modalEl = menu.modal.el;
6089 let rect = modalEl.getBoundingClientRect();
6090 let marginLeft = parseFloat(modalEl.style.marginLeft) || 0;
6091 let marginTop = parseFloat(modalEl.style.marginTop) || 0;
6092
6093 // Check if horizontal adjustment was applied (margin is non-zero)
6094 if (marginLeft !== 0) {
6095 // Position modal so its right edge is at x - 1 (cursor 1px to the right of modal)
6096 // Formula: left + margin + width = x - 1, where left = x
6097 // Therefore: margin = -width - 1
6098 let newMarginLeft = -rect.width - 1;
6099 // Check if this would push modal off the left edge
6100 let newLeft = x + newMarginLeft;
6101 if (newLeft < 10) {
6102 // Keep a 10px margin from the left edge
6103 newMarginLeft = 10 - x;
6104 }
6105 modalEl.style.marginLeft = newMarginLeft + 'px';
6106 }
6107
6108 // Check if vertical adjustment was applied (margin is non-zero)
6109 if (marginTop !== 0) {
6110 // Position modal so its bottom edge is at y - 1 (cursor 1px below modal)
6111 // Formula: top + margin + height = y - 1, where top = y
6112 // Therefore: margin = -height - 1
6113 let newMarginTop = -rect.height - 1;
6114 // Check if this would push modal off the top edge
6115 let newTop = y + newMarginTop;
6116 if (newTop < 10) {
6117 // Keep a 10px margin from the top edge
6118 newMarginTop = 10 - y;
6119 }
6120 modalEl.style.marginTop = newMarginTop + 'px';
6121 }
6122 });
6123 }
6124 // Focus
6125 self.el.classList.add('lm-menu-focus');
6126 // Focus on the contextmenu
6127 self.el.focus();
6128 }
6129
6130 self.close = function(level) {
6131 // Close all modals from the level specified
6132 self.modals.forEach(function(menu, k) {
6133 if (k >= level) {
6134 if (menu.item) {
6135 menu.item.expanded = false;
6136 menu.item = null;
6137 }
6138 menu.openedLeft = false;
6139 menu.modal.close();
6140 }
6141 });
6142 // Keep the index of the modal that is opened
6143 self.modalIndex = level ? level - 1 : 0;
6144
6145 // Close event
6146 if (level === 0) {
6147 self.el.classList.remove('lm-menu-focus');
6148
6149 Dispatch.call(self, self.onclose, 'close', {
6150 instance: self,
6151 });
6152 }
6153 }
6154
6155 onload(() => {
6156 // Create first menu
6157 self.create();
6158
6159 // Create event for focus out
6160 self.el.addEventListener("focusout", (e) => {
6161 if (! (e.relatedTarget && (self.el.contains(e.relatedTarget) || self.root?.contains(e.relatedTarget)))) {
6162 self.close(0);
6163 }
6164 });
6165
6166 // Keyboard event
6167 self.el.addEventListener("keydown", function(e) {
6168 // Menu object
6169 let menu = self.modals[self.modalIndex];
6170 // Modal must be opened
6171 if (! menu.modal.closed) {
6172 // Something happens
6173 let ret = false;
6174 // Control
6175 if (e.key === 'ArrowLeft') {
6176 if (self.modalIndex > 0) {
6177 // Close modal
6178 menu.close();
6179 // Action happened
6180 ret = true;
6181 }
6182 } else if (e.key === 'ArrowRight') {
6183 // Get the selected cursor
6184 let item = menu.options[menu.cursor];
6185 // Open submenu
6186 if (typeof (item) !== 'undefined') {
6187 // Open submenu in case that exists
6188 if (item.submenu && !item.disabled) {
6189 // Open modal
6190 menu.open(item, true);
6191 // Action happened
6192 ret = true;
6193 }
6194 }
6195 } else if (e.key === 'ArrowUp') {
6196 ret = setCursor.call(menu, 0);
6197 } else if (e.key === 'ArrowDown') {
6198 ret = setCursor.call(menu, 1);
6199 } else if (e.key === 'Enter') {
6200 // Contextmenu modal
6201 let item = menu.options[menu.cursor];
6202 // Cursor is found so reset it
6203 if (typeof(item) !== 'undefined') {
6204 // Execute action
6205 if (typeof (item.onclick) === 'function') {
6206 item.onclick.call(item, e, item.el);
6207 }
6208 // Open sub menu in case exists
6209 if (item.submenu) {
6210 // Open menu
6211 menu.open(item, true);
6212 // Action happened
6213 ret = true;
6214 } else {
6215 // Close all menu
6216 self.close(0);
6217 // Action happened
6218 ret = true;
6219 }
6220 }
6221 } else if (e.key === 'Escape') {
6222 self.close(0);
6223 }
6224
6225 // Something important happen so block any progression
6226 if (ret === true) {
6227 e.preventDefault();
6228 e.stopImmediatePropagation();
6229 }
6230 }
6231 });
6232
6233 if (! self.root) {
6234 if (self.tagName) {
6235 self.root = self.el.parentNode.parentNode;
6236 } else {
6237 self.root = self.el.parentNode;
6238 }
6239 }
6240
6241 // Parent
6242 self.root.addEventListener("contextmenu", function(e) {
6243 if (Array.isArray(self.options) && self.options.length) {
6244 let [x, y] = getCoords(e);
6245 self.open(self.options, x, y, true);
6246 e.preventDefault();
6247 e.stopImmediatePropagation();
6248 }
6249 });
6250 });
6251
6252 return `<div class="lm-menu" role="menu" aria-orientation="vertical" tabindex="0"></div>`;
6253 }
6254
6255 lemonade.setComponents({ Contextmenu: Contextmenu });
6256
6257 lemonade.createWebComponent('contextmenu', Contextmenu);
6258
6259 return function (root, options) {
6260 if (typeof (root) === 'object') {
6261 lemonade.render(Contextmenu, root, options)
6262 return options;
6263 } else {
6264 return Contextmenu.call(this, root)
6265 }
6266 }
6267})));
6268
6269/***/ }),
6270
6271/***/ 692:
6272/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
6273
6274/**
6275 * Implement page up and down navigation
6276 * Implement color attribute for items
6277 */
6278
6279if (!lemonade && "function" === 'function') {
6280 var lemonade = __webpack_require__(966);
6281}
6282
6283if (!Modal && "function" === 'function') {
6284 var Modal = __webpack_require__(72);
6285}
6286
6287; (function (global, factory) {
6288 true ? module.exports = factory() :
6289 0;
6290}(this, (function () {
6291
6292 class CustomEvents extends Event {
6293 constructor(type, props, options) {
6294 super(type, {
6295 bubbles: true,
6296 composed: true,
6297 ...options,
6298 });
6299
6300 if (props) {
6301 for (const key in props) {
6302 // Avoid assigning if property already exists anywhere on `this`
6303 if (! (key in this)) {
6304 this[key] = props[key];
6305 }
6306 }
6307 }
6308 }
6309 }
6310
6311 // Dispatcher
6312 const Dispatch = function(method, type, options) {
6313 // Try calling the method directly if provided
6314 if (typeof method === 'function') {
6315 let a = Object.values(options);
6316 return method(...a);
6317 } else if (this.tagName) {
6318 return this.dispatchEvent(new CustomEvents(type, options));
6319 }
6320 }
6321
6322 // Default row height
6323 let defaultRowHeight = 24;
6324
6325 // Translations
6326 const T = function(t) {
6327 if (typeof(document) !== "undefined" && document.dictionary) {
6328 return document.dictionary[t] || t;
6329 } else {
6330 return t;
6331 }
6332 }
6333
6334 const isEmpty = function(v) {
6335 return v === '' || v === null || v === undefined || (Array.isArray(v) && v.length === 0);
6336 }
6337
6338 /**
6339 * Compare two values (arrays, strings, numbers, etc.)
6340 * Returns true if both are equal or empty
6341 * @param {*} a1
6342 * @param {*} a2
6343 */
6344 const compareValues = function(a1, a2) {
6345 if (a1 === a2 || (isEmpty(a1) && isEmpty(a2))) {
6346 return true;
6347 }
6348
6349 if (!a1 || !a2) {
6350 return false;
6351 }
6352
6353 if (Array.isArray(a1) && Array.isArray(a2)) {
6354 if (a1.length !== a2.length) {
6355 return false;
6356 }
6357 for (let i = 0; i < a1.length; i++) {
6358 if (a1[i] !== a2[i]) {
6359 return false;
6360 }
6361 }
6362 return true;
6363 }
6364
6365 return a1 === a2;
6366 }
6367
6368 const lazyLoading = function (self) {
6369 /**
6370 * Get the position from top of a row by its index
6371 * @param item
6372 * @returns {number}
6373 */
6374 const getRowPosition = function (item) {
6375 // Position from top
6376 let top = 0;
6377 if (item) {
6378 let items = self.rows;
6379 if (items && items.length) {
6380 let index = self.rows.indexOf(item);
6381 // Go through the items
6382 for (let j = 0; j < index; j++) {
6383 top += items[j].height || defaultRowHeight;
6384 }
6385 }
6386 }
6387 return top;
6388 }
6389
6390 const updateScroll = function () {
6391 let items = self.rows;
6392 if (items) {
6393 // Before control
6394 let before = true;
6395 // Total of items in the container
6396 let numOfItems = items.length;
6397 // Position from top
6398 let height = 0;
6399 // Size of the adjustment
6400 let size = 0;
6401 // Go through the items
6402 for (let j = 0; j < numOfItems; j++) {
6403 let h = items[j].height || defaultRowHeight;
6404 // Height
6405 height += h;
6406 // Start tracking all items as before
6407 if (items[j] === self.result[0]) {
6408 before = false;
6409 }
6410 // Adjustment
6411 if (before) {
6412 size += h;
6413 }
6414 }
6415 // Update height
6416 scroll.style.height = height + 'px';
6417 // Adjust scroll position
6418 return size;
6419 }
6420 return false;
6421 }
6422
6423 const getVisibleRows = function (reset) {
6424 let items = self.rows;
6425 if (items) {
6426 let adjust;
6427 // Total of items in the container
6428 let numOfItems = items.length;
6429 // Get the position from top
6430 let y = el.scrollTop;
6431 // Get the height
6432 let h = null;
6433 if (self.type === 'searchbar' || self.type === 'picker') {
6434 // Priority should be the size used on the viewport
6435 h = y + (el.offsetHeight || self.height);
6436 } else {
6437 // Priority is the height define during initialization
6438 h = y + (self.height || el.offsetHeight);
6439 }
6440 // Go through the items
6441 let rows = [];
6442 // Height
6443 let height = 0;
6444 // Go through all items
6445 for (let j = 0; j < numOfItems; j++) {
6446 if (items[j].visible !== false) {
6447 // Height
6448 let rowHeight = items[j].height || defaultRowHeight;
6449 // Return on partial width
6450 if (height + rowHeight > y && height < h) {
6451 rows.push(items[j]);
6452 }
6453 height += rowHeight;
6454 }
6455 }
6456
6457 // Update visible rows
6458 if (reset || !compareValues(rows, self.result)) {
6459 // Render the items
6460 self.result = rows;
6461 // Adjust scroll height
6462 let adjustScroll = reset;
6463 // Adjust scrolling
6464 for (let i = 0; i < rows.length; i++) {
6465 // Item
6466 let item = rows[i];
6467 // Item height
6468 let h = item.el.offsetHeight;
6469 // Update row height
6470 if (!item.height || h !== item.height) {
6471 // Keep item height
6472 item.height = h;
6473 // Adjust total height
6474 adjustScroll = true;
6475 }
6476 }
6477
6478 // Update scroll if the height of one element has been changed
6479 if (adjustScroll) {
6480 // Adjust the scroll height
6481 adjust = updateScroll();
6482 }
6483 }
6484
6485 // Adjust position of the first element
6486 let position = getRowPosition(self.result[0]);
6487 let diff = position - el.scrollTop;
6488 if (diff > 0) {
6489 diff = 0;
6490 }
6491 self.container.style.top = diff + 'px';
6492
6493 return adjust;
6494 }
6495 }
6496
6497 /**
6498 * Move the position to the top and re-render based on the scroll
6499 * @param reset
6500 */
6501 const render = function (reset) {
6502 // Move scroll to the top
6503 el.scrollTop = 0;
6504 // Reset scroll
6505 updateScroll();
6506 // Append first batch
6507 getVisibleRows(reset);
6508 }
6509
6510 /**
6511 * Will adjust the items based on the scroll position offset
6512 */
6513 self.adjustPosition = function (item) {
6514 if (item.el) {
6515 let h = item.el.offsetHeight;
6516 let calc = item.el.offsetTop + h;
6517 if (calc > el.offsetHeight) {
6518 let size = calc - el.offsetHeight;
6519 if (size < h) {
6520 size = h;
6521 }
6522 el.scrollTop -= -1 * size;
6523 }
6524 }
6525 }
6526
6527 // Controls
6528 const scrollControls = function () {
6529 getVisibleRows(false);
6530 }
6531
6532 // Element for scrolling
6533 let el = self.container.parentNode;
6534 el.classList.add('lm-lazy');
6535 // Div to represent the height of the content
6536 const scroll = document.createElement('div');
6537 scroll.classList.add('lm-lazy-scroll');
6538 // Force the height and add scrolling
6539 el.appendChild(scroll);
6540 el.addEventListener('scroll', scrollControls, { passive: true });
6541 el.addEventListener('wheel', scrollControls, { passive: true });
6542 self.container.classList.add('lm-lazy-items');
6543
6544 self.goto = function (item) {
6545 el.scrollTop = getRowPosition(item);
6546 let adjust = getVisibleRows(false);
6547 if (adjust) {
6548 el.scrollTop = adjust;
6549 // Last adjust on the visible rows
6550 getVisibleRows(false);
6551 }
6552 }
6553
6554 return (prop) => {
6555 if (prop === 'rows') {
6556 render(true);
6557 }
6558 }
6559 }
6560
6561 const getAttributeName = function(prop) {
6562 if (prop.substring(0,1) === ':') {
6563 prop = prop.substring(1);
6564 } else if (prop.substring(0,3) === 'lm-') {
6565 prop = prop.substring(3);
6566 }
6567 return prop.toLowerCase();
6568 }
6569
6570 const extractFromHtml = function(element) {
6571 let data = [];
6572 // Content
6573 for (let i = 0; i < element.children.length; i++) {
6574 let e = element.children[i];
6575 let item = {
6576 text: e.textContent || e.getAttribute('title'),
6577 value: e.getAttribute('value'),
6578 }
6579 if (item.value == null) {
6580 item.value = item.text;
6581 }
6582 data.push(item);
6583 }
6584
6585 return data;
6586 }
6587
6588 const extract = function(children) {
6589 let data = [];
6590
6591 if (this.tagName) {
6592 data = extractFromHtml(this);
6593 // Remove all elements
6594 this.textContent = '';
6595 } else {
6596 // Get data
6597 if (typeof(children) === 'string') {
6598 // Version 4
6599 let d = document.createElement('div');
6600 d.innerHTML = children;
6601 data = extractFromHtml(d);
6602 } else if (children && children.length) {
6603 // Version 5
6604 children.forEach((v) => {
6605 let item = {}
6606 v.props.forEach((prop) => {
6607 item[getAttributeName(prop.name)] = prop.value;
6608 });
6609 if (! item.text) {
6610 item.text = v.children[0]?.props[0]?.value || '';
6611 }
6612 data.push(item);
6613 });
6614 // Block children
6615 children.length = 0;
6616 }
6617 }
6618
6619 return data;
6620 }
6621
6622 const isDOM = function(o) {
6623 return (o instanceof Element || o instanceof HTMLDocument || o instanceof DocumentFragment);
6624 }
6625
6626 const Dropdown = function (children, { onchange, onload }) {
6627 let self = this;
6628 // Data
6629 let data = [];
6630 // Internal value controllers
6631 let value = [];
6632 // Cursor
6633 let cursor = null;
6634 // Control events
6635 let ignoreEvents = false;
6636 // Lazy loading global instance
6637 let lazyloading = null;
6638 // Tracking changes
6639 let changesDetected = false;
6640 // Debounce timer for search
6641 let searchTimeout = null;
6642
6643 // Data
6644 if (! Array.isArray(self.data)) {
6645 self.data = [];
6646 }
6647
6648 let d = extract.call(this, children);
6649 if (d) {
6650 d.forEach((v) => {
6651 self.data.push(v)
6652 })
6653 }
6654
6655 // Decide the type based on the size of the screen
6656 let autoType = self.type === 'auto';
6657
6658 // Custom events defined by the user
6659 let load = self.onload;
6660 self.onload = null;
6661 let change = self.onchange;
6662 self.onchange = null;
6663
6664 // Compatibility
6665 if (typeof self.newOptions !== 'undefined') {
6666 self.insert = self.newOptions;
6667 }
6668
6669 // Cursor controllers
6670 const setCursor = function (index, force) {
6671 let item = self.rows[index];
6672 if (typeof (item) !== 'undefined') {
6673 // Set the cursor number
6674 cursor = index;
6675 // Set visual indication
6676 item.cursor = true;
6677 // Go to the item on the scroll in case the item is not on the viewport
6678 if (!(item.el && item.el.parentNode) || force === true) {
6679 // Goto method
6680 self.goto(item);
6681 }
6682 // Adjust cursor position
6683 setTimeout(function () {
6684 self.adjustPosition(item);
6685 });
6686 }
6687 }
6688
6689 const removeCursor = function (reset) {
6690 if (cursor !== null) {
6691 if (typeof (self.rows[cursor]) !== 'undefined') {
6692 self.rows[cursor].cursor = false;
6693 }
6694 if (reset) {
6695 // Cursor is null
6696 cursor = null;
6697 }
6698 }
6699 }
6700
6701 const moveCursor = function (direction, jump) {
6702 // Remove cursor
6703 removeCursor();
6704 // Last item
6705 let last = self.rows.length - 1;
6706 if (jump) {
6707 if (direction < 0) {
6708 cursor = 0;
6709 } else {
6710 cursor = last;
6711 }
6712 } else {
6713 // Position
6714 if (cursor === null) {
6715 cursor = 0;
6716 } else {
6717 // Move previous
6718 cursor = cursor + direction;
6719 }
6720 // Reach the boundaries
6721 if (direction < 0) {
6722 // Back to the last one
6723 if (cursor < 0) {
6724 cursor = last;
6725 }
6726 } else {
6727 // Back to the first one
6728 if (cursor > last) {
6729 cursor = 0;
6730 }
6731 }
6732 }
6733 // Add cursor
6734 setCursor(cursor);
6735 }
6736
6737 const adjustDimensions = function(data) {
6738 // Estimate width
6739 let width = self.width ?? 0;
6740 // Adjust the width
6741 let w = getInput().offsetWidth;
6742 if (width < w) {
6743 width = w;
6744 }
6745 // Width && values
6746 data.map(function (s) {
6747 // Estimated width of the element
6748 if (s.text) {
6749 let w = Math.max(width, s.text.length * 7.5);
6750 if (width < w) {
6751 width = w;
6752 }
6753 }
6754 });
6755 // Min width for the container
6756 self.container.parentNode.style.width = (width - 2) + 'px';
6757 }
6758
6759 const setData = function () {
6760 // Data
6761 data = JSON.parse(JSON.stringify(self.data));
6762 // Re-order to make sure groups are in sequence
6763 if (data && data.length) {
6764 // Adjust width and height
6765 adjustDimensions(data);
6766 // Groups
6767 data.sort((a, b) => {
6768 // Compare groups
6769 if (a.group && b.group) {
6770 return a.group.localeCompare(b.group);
6771 }
6772 return 0;
6773 });
6774 let group = '';
6775 // Define group headers
6776 data.map((v) => {
6777 // Compare groups
6778 if (v && v.group && v.group !== group) {
6779 v.header = v.group;
6780 group = v.group;
6781 }
6782 });
6783 }
6784 // Data to be listed
6785 self.rows = data;
6786 }
6787
6788 const updateLabel = function () {
6789 if (value && value.length) {
6790 getInput().textContent = value.filter(v => v.selected).map(i => i.text).join('; ');
6791 } else {
6792 getInput().textContent = '';
6793 }
6794 }
6795
6796 const setValue = function (v, ignoreEvent) {
6797 // Values
6798 let newValue;
6799 if (! Array.isArray(v)) {
6800 if (typeof(v) === 'string') {
6801 newValue = v.split(self.divisor ?? ';');
6802 } else {
6803 newValue = [v];
6804 }
6805 } else {
6806 newValue = v;
6807 }
6808
6809 // Width && values
6810 value = [];
6811
6812 if (Array.isArray(data)) {
6813 data.map(function (s) {
6814 s.selected = newValue.some(v => {
6815 // Use strict equality when either value is empty string to avoid '' == 0 being true
6816 if (v === '' || s.value === '') {
6817 return v === s.value;
6818 }
6819 return v == s.value;
6820 });
6821 if (s.selected) {
6822 value.push(s);
6823 }
6824 });
6825 }
6826
6827 // Update label
6828 if (self.isClosed()) {
6829 updateLabel();
6830 }
6831
6832 // Component onchange
6833 if (! ignoreEvent) {
6834 Dispatch.call(self, change, 'change', {
6835 instance: self,
6836 value: getValue(),
6837 });
6838 }
6839 }
6840
6841 const getValue = function () {
6842 if (self.multiple) {
6843 if (value && value.length) {
6844 return value.filter(v => v.selected).map(i => i.value);
6845 }
6846 } else {
6847 if (value && value.length) {
6848 return value[0].value;
6849 }
6850 }
6851
6852 return null;
6853 }
6854
6855 const getText = function () {
6856 if (self.multiple) {
6857 if (value && value.length) {
6858 return value.filter(v => v.selected).map(i => i.text);
6859 }
6860 } else {
6861 if (value && value.length) {
6862 return value[0].text;
6863 }
6864 }
6865
6866 return null;
6867 }
6868
6869 const onopen = function () {
6870 self.state = true;
6871 // Value
6872 let v = value[value.length - 1];
6873 // Make sure goes back to the top of the scroll
6874 if (self.container.parentNode.scrollTop > 0) {
6875 self.container.parentNode.scrollTop = 0;
6876 }
6877 // Move to the correct position
6878 if (v) {
6879 // Mark the position of the cursor to the same element
6880 setCursor(self.rows.indexOf(v), true);
6881 }
6882 // Prepare search field
6883 if (self.autocomplete) {
6884 // Get the input
6885 let input = getInput();
6886 // Editable
6887 input.setAttribute('contenteditable', true);
6888 // Clear input
6889 input.textContent = '';
6890 // Focus on the item
6891 input.focus();
6892 }
6893 // Adjust width and height
6894 adjustDimensions(self.data);
6895 // Open event
6896 Dispatch.call(self, self.onopen, 'open', {
6897 instance: self
6898 });
6899 }
6900
6901 const onclose = function (options, origin) {
6902 // Cursor
6903 removeCursor(true);
6904 // Reset search
6905 if (self.autocomplete) {
6906 // Go to begin of the data
6907 self.rows = data;
6908 // Get the input
6909 let input = getInput();
6910 if (input) {
6911 // Remove editable attribute
6912 input.removeAttribute('contenteditable');
6913 // Clear input
6914 input.textContent = '';
6915 }
6916 }
6917
6918 if (origin === 'escape') {
6919 // Cancel operation and keep the same previous value
6920 setValue(self.value, true);
6921 } else {
6922 // Current value
6923 let newValue = getValue();
6924
6925 // If that is different from the component value
6926 if (changesDetected === true && ! compareValues(newValue, self.value)) {
6927 self.value = newValue;
6928 } else {
6929 // Update label
6930 updateLabel();
6931 }
6932 }
6933
6934 // Identify the new state of the dropdown
6935 self.state = false;
6936
6937 // Close event
6938 Dispatch.call(self, self.onclose, 'close', {
6939 instance: self,
6940 ...options
6941 });
6942 }
6943
6944 const normalizeData = function(result) {
6945 if (result && result.length) {
6946 return result.map((v) => {
6947 if (typeof v === 'string' || typeof v === 'number') {
6948 return { value: v, text: v };
6949 } else if (typeof v === 'object' && v.hasOwnProperty('name')) {
6950 return { value: v.id, text: v.name };
6951 } else {
6952 return v;
6953 }
6954 });
6955 }
6956 }
6957
6958 const loadData = function(result) {
6959 result = normalizeData(result);
6960 // Loading controls
6961 lazyloading = lazyLoading(self);
6962 // Loading new data from a remote source
6963 if (result) {
6964 result.forEach((v) => {
6965 self.data.push(v);
6966 });
6967 }
6968 // Process the data
6969 setData();
6970 // Set value
6971 if (typeof(self.value) !== 'undefined') {
6972 setValue(self.value, true);
6973 }
6974 // Onload method
6975 Dispatch.call(self, load, 'load', {
6976 instance: self
6977 });
6978 // Remove loading spin
6979 self.input.classList.remove('lm-dropdown-loading');
6980 }
6981
6982 const resetData = function(result) {
6983 result = normalizeData(result);
6984 // Reset cursor
6985 removeCursor(true);
6986 let r = data.filter(item => {
6987 return item.selected === true;
6988 });
6989 // Loading new data from a remote source
6990 if (result) {
6991 result.forEach((v) => {
6992 r.push(v);
6993 });
6994 }
6995 self.rows = r;
6996 // Remove loading spin
6997 self.input.classList.remove('lm-dropdown-loading');
6998
6999 // Event
7000 Dispatch.call(self, self.onsearch, 'search', {
7001 instance: self,
7002 result: result,
7003 });
7004 }
7005
7006 const getInput = function() {
7007 return self.input;
7008 }
7009
7010 const search = function(query) {
7011 if (! self.isClosed() && self.autocomplete) {
7012
7013 // Remote or normal search
7014 if (self.remote === true && self.url) {
7015 // Clear existing timeout
7016 if (searchTimeout) {
7017 clearTimeout(searchTimeout);
7018 }
7019 // Loading spin
7020 self.input.classList.add('lm-dropdown-loading');
7021 // Headers
7022 let http = {
7023 headers: {
7024 'Content-Type': 'text/json',
7025 }
7026 }
7027 let ret = Dispatch.call(self, self.onbeforesearch, 'beforesearch', {
7028 instance: self,
7029 http: http,
7030 query: query,
7031 });
7032
7033 if (ret === false) {
7034 return;
7035 }
7036
7037 // Debounce the search with 300ms delay
7038 searchTimeout = setTimeout(() => {
7039 let url = self.url;
7040 url += url.indexOf('?') === -1 ? '?' : '&';
7041 url += `q=${query}`;
7042
7043 fetch(url, http).then(r => r.json()).then(resetData).catch((error) => {
7044 resetData([]);
7045 });
7046 }, 300);
7047 } else {
7048 // Filter options
7049 let temp;
7050
7051 const find = (prop) => {
7052 if (prop) {
7053 if (Array.isArray(prop)) {
7054 // match if ANY element contains the query (case-insensitive)
7055 return prop.some(v => v != null && v.toString().toLowerCase().includes(query));
7056 }
7057 // handle strings/numbers/others
7058 return prop.toString().toLowerCase().includes(query);
7059 }
7060 return false;
7061 };
7062
7063 if (! query) {
7064 temp = data;
7065 } else {
7066 temp = data.filter(item => {
7067 return item.selected === true || find(item.text) || find(item.group) || find(item.keywords) || find(item.synonym);
7068 });
7069 }
7070
7071 // Cursor
7072 removeCursor(true);
7073 // Update the data from the dropdown
7074 self.rows = temp;
7075 }
7076 }
7077 }
7078
7079 const events = {
7080 focusout: (e) => {
7081 if (self.modal) {
7082 if (! (e.relatedTarget && self.el.contains(e.relatedTarget))) {
7083 if (! self.isClosed()) {
7084 self.close({ origin: 'focusout '});
7085 }
7086 }
7087 }
7088 },
7089 keydown: (e) => {
7090 if (! self.isClosed()) {
7091 let prevent = false;
7092 if (e.code === 'ArrowUp') {
7093 moveCursor(-1);
7094 prevent = true;
7095 } else if (e.code === 'ArrowDown') {
7096 moveCursor(1);
7097 prevent = true;
7098 } else if (e.code === 'Home') {
7099 moveCursor(-1, true);
7100 if (!self.autocomplete) {
7101 prevent = true;
7102 }
7103 } else if (e.code === 'End') {
7104 moveCursor(1, true);
7105 if (!self.autocomplete) {
7106 prevent = true;
7107 }
7108 } else if (e.code === 'Enter') {
7109 if (e.target.tagName === 'BUTTON') {
7110 e.target.click();
7111 let input = getInput();
7112 input.focus();
7113 } else {
7114 select(e, self.rows[cursor]);
7115 }
7116 prevent = true;
7117 } else if (e.code === 'Escape') {
7118 self.close({ origin: 'escape'});
7119 prevent = true;
7120 } else {
7121 if (e.keyCode === 32 && !self.autocomplete) {
7122 select(e, self.rows[cursor]);
7123 }
7124 }
7125
7126 if (prevent) {
7127 e.preventDefault();
7128 e.stopImmediatePropagation();
7129 }
7130 } else {
7131 if (e.code === 'ArrowUp' || e.code === 'ArrowDown' || e.code === 'Enter') {
7132 self.open();
7133 e.preventDefault();
7134 e.stopImmediatePropagation();
7135 }
7136 }
7137 },
7138 mousedown: (e) => {
7139 if (e.target.classList.contains('lm-dropdown-input')) {
7140 if (self.autocomplete) {
7141 let x;
7142 if (e.changedTouches && e.changedTouches[0]) {
7143 x = e.changedTouches[0].clientX;
7144 } else {
7145 x = e.clientX;
7146 }
7147 if (e.target.offsetWidth - (x - e.target.offsetLeft) < 20) {
7148 toggle();
7149 } else {
7150 self.open();
7151 }
7152 } else {
7153 toggle();
7154 }
7155 }
7156 },
7157 paste: (e) => {
7158 if (e.target.classList.contains('lm-dropdown-input')) {
7159 let text;
7160 if (e.clipboardData || e.originalEvent.clipboardData) {
7161 text = (e.originalEvent || e).clipboardData.getData('text/plain');
7162 } else if (window.clipboardData) {
7163 text = window.clipboardData.getData('Text');
7164 }
7165 text = text.replace(/(\r\n|\n|\r)/gm, "");
7166 document.execCommand('insertText', false, text)
7167 e.preventDefault();
7168 }
7169 },
7170 input: (e) => {
7171 if (e.target.classList.contains('lm-dropdown-input')) {
7172 search(e.target.textContent.toLowerCase());
7173 }
7174 },
7175 }
7176
7177 const selectItem = function(s) {
7178 if (self.remote === true) {
7179 if (data.indexOf(s) === -1) {
7180 self.data.push(s);
7181 data.push(s);
7182 }
7183 }
7184
7185 if (self.multiple === true) {
7186 let position = value.indexOf(s);
7187 if (position === -1) {
7188 value.push(s);
7189 s.selected = true;
7190 } else {
7191 value.splice(position, 1);
7192 s.selected = false;
7193 }
7194 } else {
7195 if (value[0] === s) {
7196 if (self.allowEmpty === false) {
7197 s.selected = true;
7198 } else {
7199 s.selected = !s.selected;
7200 }
7201 } else {
7202 if (value[0]) {
7203 value[0].selected = false;
7204 }
7205 s.selected = true;
7206 }
7207 if (s.selected) {
7208 value = [s];
7209 } else {
7210 value = [];
7211 }
7212 }
7213
7214 changesDetected = true;
7215 }
7216
7217 const add = async function (e) {
7218 let input = getInput();
7219 let text = input.textContent;
7220 if (! text) {
7221 return false;
7222 }
7223
7224 // New item
7225 let s = {
7226 text: text,
7227 value: text,
7228 }
7229
7230 self.add(s);
7231
7232 e.preventDefault();
7233 }
7234
7235 const select = function (e, s) {
7236 if (s && s.disabled !== true) {
7237 selectItem(s);
7238 // Close the modal
7239 if (self.multiple !== true) {
7240 self.close({ origin: 'button' });
7241 }
7242 }
7243 }
7244
7245 const toggle = function () {
7246 if (self.modal) {
7247 if (self.isClosed()) {
7248 self.open();
7249 } else {
7250 self.close({ origin: 'button' });
7251 }
7252 }
7253 }
7254
7255 self.add = async function (newItem) {
7256 // Event
7257 if (typeof(self.onbeforeinsert) === 'function') {
7258 self.input.classList.add('lm-dropdown-loading');
7259 let ret = await self.onbeforeinsert(self, newItem);
7260 self.input.classList.remove('lm-dropdown-loading');
7261 if (ret === false) {
7262 return;
7263 } else if (ret) {
7264 newItem = ret;
7265 }
7266 }
7267 // Process the data
7268 data.push(newItem);
7269 self.data.push(newItem);
7270 // Refresh screen
7271 self.result.unshift(newItem);
7272 self.rows.unshift(newItem);
7273 self.refresh('result');
7274
7275 Dispatch.call(self, self.oninsert, 'insert', {
7276 instance: self,
7277 item: newItem,
7278 });
7279 }
7280
7281 self.open = function () {
7282 if (self.modal && ! self.disabled) {
7283 if (self.isClosed()) {
7284 if (autoType) {
7285 self.type = window.innerWidth > 640 ? self.type = 'default' : (self.autocomplete ? 'searchbar' : 'picker');
7286 }
7287 // Track
7288 changesDetected = false;
7289 // Open the modal
7290 self.modal.open();
7291 }
7292 }
7293 }
7294
7295 self.close = function (options) {
7296 if (self.modal) {
7297 if (options?.origin) {
7298 self.modal.close(options)
7299 } else {
7300 self.modal.close({ origin: 'button' })
7301 }
7302 }
7303 }
7304
7305 self.isClosed = function() {
7306 if (self.modal) {
7307 return self.modal.isClosed();
7308 }
7309 }
7310
7311 self.setData = function(data) {
7312 self.data = data;
7313 }
7314
7315 self.getData = function() {
7316 return self.data;
7317 }
7318
7319 self.getValue = function() {
7320 return self.value;
7321 }
7322
7323 self.getText = function() {
7324 return getText();
7325 }
7326
7327 self.setValue = function(v) {
7328 self.value = v;
7329 }
7330
7331 self.reset = function() {
7332 self.value = null;
7333 self.close({ origin: 'button' });
7334 }
7335
7336 self.onevent = function(e) {
7337 if (events[e.type]) {
7338 events[e.type](e);
7339 }
7340 }
7341
7342 // Init with a
7343 let input = self.input;
7344
7345 onload(() => {
7346 if (self.type === "inline") {
7347 // For inline dropdown
7348 self.el.setAttribute('tabindex', 0);
7349 // Remove search
7350 self.input.remove();
7351 } else {
7352 // Create modal instance
7353 self.modal = {
7354 closed: true,
7355 focus: false,
7356 onopen: onopen,
7357 onclose: onclose,
7358 position: 'absolute',
7359 'auto-adjust': true,
7360 'auto-close': false,
7361 };
7362 // Generate modal
7363 Modal(self.el.children[1], self.modal);
7364 }
7365
7366 if (self.remote === 'true') {
7367 self.remote = true;
7368 }
7369
7370 if (self.autocomplete === 'true') {
7371 self.autocomplete = true;
7372 }
7373
7374 if (self.multiple === 'true') {
7375 self.multiple = true;
7376 }
7377
7378 if (self.insert === 'true') {
7379 self.insert = true;
7380 }
7381
7382 // Autocomplete will be forced to be true when insert action is active
7383 if ((self.insert === true || self.type === 'searchbar' || self.remote === true) && ! self.autocomplete) {
7384 self.autocomplete = true;
7385 }
7386
7387 if (typeof(input) !== 'undefined') {
7388 // Remove the native element
7389 if (isDOM(input)) {
7390 input.classList.add('lm-dropdown-input');
7391 }
7392 // Remove search
7393 self.input.remove();
7394 // New input
7395 self.input = input;
7396 } else {
7397 self.el.children[0].style.position = 'relative';
7398 }
7399
7400 // Default width
7401 if (self.width) {
7402 // Dropdown
7403 self.el.style.width = self.width + 'px';
7404 }
7405
7406 // Height
7407 self.height = 400;
7408
7409 // Animation for mobile
7410 if (document.documentElement.clientWidth < 800) {
7411 self.animation = true;
7412 }
7413
7414 // Events
7415 self.el.addEventListener('focusout', events.focusout);
7416 self.el.addEventListener('keydown', events.keydown);
7417 self.el.addEventListener('mousedown', events.mousedown);
7418 self.el.addEventListener('paste', events.paste);
7419 self.el.addEventListener('input', events.input);
7420
7421 // Load remote data
7422 if (self.url) {
7423 if (self.remote === true) {
7424 loadData();
7425 } else {
7426 // Loading spin
7427 self.input.classList.add('lm-dropdown-loading');
7428 // Load remote data
7429 fetch(self.url, {
7430 headers: {
7431 'Content-Type': 'text/json',
7432 }
7433 }).then(r => r.json()).then(loadData).catch(() => {
7434 loadData();
7435 });
7436 }
7437 } else {
7438 loadData();
7439 }
7440 });
7441
7442 onchange(prop => {
7443 if (prop === 'value') {
7444 setValue(self.value);
7445 } else if (prop === 'data') {
7446 // Store current value before resetting data
7447 let currentValue = self.value;
7448 setData();
7449
7450 // Only reset value if it's not in the new data
7451 if (currentValue !== null && currentValue !== undefined && currentValue !== '') {
7452 let valuesToCheck = Array.isArray(currentValue) ? currentValue : [currentValue];
7453
7454 // Filter to keep only values that exist in the new data
7455 let validValues = valuesToCheck.filter(v => {
7456 return self.data.some(item => {
7457 if (v === '' || item.value === '') {
7458 return v === item.value;
7459 }
7460 return v == item.value;
7461 });
7462 });
7463
7464 if (validValues.length === 0) {
7465 // No valid values remain, reset to null
7466 self.value = null;
7467 } else if (self.multiple) {
7468 // Multi-select: keep only valid values
7469 self.value = validValues;
7470 } else {
7471 // Single select: re-apply the value
7472 self.value = validValues[0];
7473 }
7474 }
7475 }
7476
7477 if (typeof (lazyloading) === 'function') {
7478 lazyloading(prop);
7479 }
7480 });
7481
7482 return render => render`<div class="lm-dropdown" data-state="{{self.state}}" data-insert="{{self.insert}}" data-type="{{self.type}}" data-disabled="{{self.disabled}}" :value="self.value" :data="self.data">
7483 <div class="lm-dropdown-header">
7484 <div class="lm-dropdown-input" placeholder="{{self.placeholder}}" :ref="self.input" tabindex="0"></div>
7485 <button class="lm-dropdown-add" onclick="${add}" tabindex="0"></button>
7486 <div class="lm-dropdown-header-controls">
7487 <button onclick="self.reset" class="lm-dropdown-done">${T('Reset')}</button>
7488 <button onclick="self.close" class="lm-dropdown-done">${T('Done')}</button>
7489 </div>
7490 </div>
7491 <div class="lm-dropdown-content">
7492 <div>
7493 <div :loop="self.result" :ref="self.container" :rows="self.rows">
7494 <div class="lm-dropdown-item" onclick="${select}" data-cursor="{{self.cursor}}" data-disabled="{{self.disabled}}" data-selected="{{self.selected}}" data-group="{{self.header}}">
7495 <div><img :src="self.image" /> <div>{{self.text}}</div></div>
7496 </div>
7497 </div>
7498 </div>
7499 </div>
7500 </div>`;
7501 }
7502
7503 lemonade.setComponents({ Dropdown: Dropdown });
7504
7505 lemonade.createWebComponent('dropdown', Dropdown);
7506
7507 return function (root, options) {
7508 if (typeof (root) === 'object') {
7509 lemonade.render(Dropdown, root, options)
7510 return options;
7511 } else {
7512 return Dropdown.call(this, root)
7513 }
7514 }
7515})));
7516
7517/***/ }),
7518
7519/***/ 72:
7520/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
7521
7522/**
7523 * pin the modal to the left panel
7524 */
7525if (!lemonade && "function" === 'function') {
7526 var lemonade = __webpack_require__(966);
7527}
7528
7529;(function (global, factory) {
7530 true ? module.exports = factory() :
7531 0;
7532}(this, (function () {
7533
7534 class CustomEvents extends Event {
7535 constructor(type, props, options) {
7536 super(type, {
7537 bubbles: true,
7538 composed: true,
7539 ...options,
7540 });
7541
7542 if (props) {
7543 for (const key in props) {
7544 // Avoid assigning if property already exists anywhere on `this`
7545 if (! (key in this)) {
7546 this[key] = props[key];
7547 }
7548 }
7549 }
7550 }
7551 }
7552
7553 // Dispatcher
7554 const Dispatch = function(method, type, options) {
7555 // Try calling the method directly if provided
7556 if (typeof method === 'function') {
7557 let a = Object.values(options);
7558 return method(...a);
7559 } else if (this.tagName) {
7560 this.dispatchEvent(new CustomEvents(type, options));
7561 }
7562 }
7563
7564 // References
7565 const modals = [];
7566 // State of the resize and move modal
7567 let state = {};
7568 // Internal controls of the action of resize and move
7569 let controls = {};
7570 // Width of the border
7571 let cornerSize = 10;
7572 // Container with minimized modals
7573 const minimizedModals = [];
7574 // Default z-index for the modals
7575 const defaultZIndex = 20;
7576
7577 /**
7578 * Send the modal to the front
7579 * @param container
7580 */
7581 const sendToFront = function(container) {
7582 let highestXIndex = defaultZIndex;
7583 for (let i = 0; i < modals.length; i++) {
7584 const zIndex = parseInt(modals[i].el.style.zIndex);
7585 if (zIndex > highestXIndex) {
7586 highestXIndex = zIndex;
7587 }
7588 }
7589 container.style.zIndex = highestXIndex + 1;
7590 }
7591
7592 /**
7593 * Send modal to the back
7594 * @param container
7595 */
7596 const sendToBack = function(container) {
7597 container.style.zIndex = defaultZIndex;
7598 }
7599
7600 // Get the coordinates of the action
7601 const getCoords = function(e) {
7602 let x;
7603 let y;
7604
7605 if (e.changedTouches && e.changedTouches[0]) {
7606 x = e.changedTouches[0].clientX;
7607 y = e.changedTouches[0].clientY;
7608 } else {
7609 x = e.clientX;
7610 y = e.clientY;
7611 }
7612
7613 return [x,y];
7614 }
7615
7616 // Get the button status
7617 const getButton = function(e) {
7618 e = e || window.event;
7619 if (e.buttons) {
7620 return e.buttons;
7621 } else if (e.button) {
7622 return e.button;
7623 } else {
7624 return e.which;
7625 }
7626 }
7627
7628 // Finalize any potential action
7629 const mouseUp = function(e) {
7630 // Finalize all actions
7631 if (typeof(controls.action) === 'function') {
7632 controls.action();
7633 }
7634 setTimeout(function() {
7635 // Remove cursor
7636 if (controls.e) {
7637 controls.e.style.cursor = '';
7638 }
7639 // Reset controls
7640 controls = {};
7641 // Reset state controls
7642 state = {
7643 x: null,
7644 y: null,
7645 }
7646 }, 0)
7647 }
7648
7649 const mouseMove = function(e) {
7650 if (! getButton(e)) {
7651 return false;
7652 }
7653 // Get mouse coordinates
7654 let [x,y] = getCoords(e);
7655
7656 // Move modal
7657 if (controls.type === 'move') {
7658 if (state && state.x == null && state.y == null) {
7659 state.x = x;
7660 state.y = y;
7661 }
7662
7663 let dx = x - state.x;
7664 let dy = y - state.y;
7665 let top = controls.e.offsetTop + dy;
7666 let left = controls.e.offsetLeft + dx;
7667
7668 // Update position
7669 controls.top = top;
7670 controls.left = left;
7671 controls.e.style.top = top + 'px';
7672 controls.e.style.left = left + 'px';
7673
7674 state.x = x;
7675 state.y = y;
7676 state.top = top;
7677 state.left = left;
7678 } else if (controls.type === 'resize') {
7679 let top = null;
7680 let left = null;
7681 let width = null;
7682 let height = null;
7683
7684 if (controls.d === 'e-resize' || controls.d === 'ne-resize' || controls.d === 'se-resize') {
7685 width = controls.w + (x - controls.x);
7686
7687 if (e.shiftKey) {
7688 height = controls.h + (x - controls.x) * (controls.h / controls.w);
7689 }
7690 } else if (controls.d === 'w-resize' || controls.d === 'nw-resize'|| controls.d === 'sw-resize') {
7691 left = controls.l + (x - controls.x);
7692 // Do not move further
7693 if (left >= controls.l) {
7694 left = controls.l;
7695 }
7696 // Update width
7697 width = controls.l + controls.w - left;
7698 // Consider shift to update height
7699 if (e.shiftKey) {
7700 height = controls.h - (x - controls.x) * (controls.h / controls.w);
7701 }
7702 }
7703
7704 if (controls.d === 's-resize' || controls.d === 'se-resize' || controls.d === 'sw-resize') {
7705 if (! height) {
7706 height = controls.h + (y - controls.y);
7707 }
7708 } else if (controls.d === 'n-resize' || controls.d === 'ne-resize' || controls.d === 'nw-resize') {
7709 top = controls.t + (y - controls.y);
7710 // Do not move further
7711 if (top >= controls.t) {
7712 top = controls.t;
7713 }
7714 // Update height
7715 height = controls.t + controls.h - top;
7716 }
7717
7718 if (top) {
7719 controls.e.style.top = top + 'px';
7720 }
7721 if (left) {
7722 controls.e.style.left = left + 'px';
7723 }
7724 if (width) {
7725 controls.e.style.width = width + 'px';
7726 }
7727 if (height) {
7728 controls.e.style.height = height + 'px';
7729 }
7730 }
7731 }
7732
7733 if (typeof(document) !== "undefined") {
7734 document.addEventListener('mouseup', mouseUp);
7735 document.addEventListener('mousemove', mouseMove);
7736 }
7737
7738 const isTrue = function(e) {
7739 return e === true || e === 1 || e === 'true';
7740 }
7741
7742 const refreshMinimized = function() {
7743 let items = minimizedModals;
7744 let numOfItems = items.length;
7745 let width = 10;
7746 let height = 55;
7747 let offsetWidth = window.innerWidth;
7748 let offsetHeight = window.innerHeight;
7749 for (let i = 0; i < numOfItems; i++) {
7750 let item = items[i];
7751 item.el.style.left = width + 'px';
7752 item.el.style.top = offsetHeight - height + 'px';
7753 width += 205;
7754
7755 if (offsetWidth - width < 205) {
7756 width = 10;
7757 height += 50;
7758 }
7759 }
7760 }
7761
7762 const delayAction = function(self, action) {
7763 // Make sure to remove the transformation before minimize to preserve the animation
7764 if (self.el.style.marginLeft || self.el.style.marginTop) {
7765 // Make sure no animation during this process
7766 self.el.classList.add('action');
7767 // Remove adjustment
7768 removeMargin(self);
7769 // Make sure to continue with minimize
7770 setTimeout(function() {
7771 // Remove class
7772 self.el.classList.remove('action');
7773 // Call action
7774 action(self);
7775 },0)
7776
7777 return true;
7778 }
7779 }
7780
7781 const setMini = function(self) {
7782 if (delayAction(self, setMini)) {
7783 return;
7784 }
7785
7786 // Minimize modals
7787 minimizedModals.push(self);
7788
7789 self.el.top = self.el.offsetTop;
7790 self.el.left = self.el.offsetLeft;
7791
7792 if (! self.el.style.top) {
7793 self.el.style.top = self.el.top + 'px';
7794 }
7795 if (! self.el.style.left) {
7796 self.el.style.left = self.el.left + 'px';
7797 }
7798
7799 self.el.translateY = 0;
7800 self.el.translateX = 0;
7801
7802 // Refresh positions
7803 setTimeout(function() {
7804 refreshMinimized();
7805 self.minimized = true;
7806 },10)
7807 }
7808
7809 const removeMini = function(self) {
7810 minimizedModals.splice(minimizedModals.indexOf(self), 1);
7811 self.minimized = false;
7812 self.el.style.top = self.el.top + 'px';
7813 self.el.style.left = self.el.left + 'px';
7814 // Refresh positions
7815 setTimeout(() => {
7816 refreshMinimized();
7817 }, 10);
7818 // Refresh positions
7819 setTimeout(() => {
7820 if (self.top === '') {
7821 self.el.style.top = '';
7822 }
7823 if (self.left === '') {
7824 self.el.style.left = '';
7825 }
7826 }, 400);
7827 }
7828
7829 const removeMargin = function(self) {
7830 if (self.el.style.marginLeft) {
7831 let y = self.el.offsetLeft;
7832 self.el.style.marginLeft = '';
7833 self.left = y;
7834 }
7835
7836 if (self.el.style.marginTop) {
7837 let x = self.el.offsetTop;
7838 self.el.style.marginTop = '';
7839 self.top = x;
7840 }
7841 }
7842
7843 const adjustHorizontal = function(self) {
7844 if (! isTrue(self['auto-adjust'])) {
7845 return false;
7846 }
7847
7848 self.el.style.marginLeft = '';
7849 let viewportWidth = window.innerWidth;
7850 let margin = 10;
7851
7852 if (self.position) {
7853 if (self.position === 'absolute') {
7854 let w = document.documentElement.offsetWidth;
7855 if (w > viewportWidth) {
7856 //viewportWidth = w;
7857 }
7858 } else if (self.position !== 'center') {
7859 margin = 0;
7860 }
7861 }
7862
7863 let el = self.el.getBoundingClientRect();
7864
7865 let rightEdgeDistance = viewportWidth - (el.left + el.width);
7866 let transformX = 0;
7867
7868 if (self.position === 'absolute') {
7869 if (rightEdgeDistance < 0) {
7870 transformX = rightEdgeDistance - margin - 10; // 10 is the scroll width
7871 }
7872 } else {
7873 if (rightEdgeDistance < 0) {
7874 transformX = rightEdgeDistance - margin;
7875 }
7876 }
7877
7878 if (el.left < 0) {
7879 transformX = margin - el.left;
7880 }
7881 if (transformX !== 0) {
7882 self.el.style.marginLeft = transformX + 'px';
7883 }
7884 }
7885
7886 const adjustVertical = function(self) {
7887 if (! isTrue(self['auto-adjust'])) {
7888 return false;
7889 }
7890
7891 self.el.style.marginTop = '';
7892 let viewportHeight = window.innerHeight;
7893 let margin = 10;
7894
7895 if (self.position) {
7896 if (self.position === 'absolute') {
7897 let h = document.documentElement.offsetHeight;
7898 if (h > viewportHeight) {
7899 //viewportHeight = h;
7900 }
7901 } else if (self.position !== 'center') {
7902 margin = 0;
7903 }
7904 }
7905
7906 let el = self.el.getBoundingClientRect();
7907
7908 let bottomEdgeDistance = viewportHeight - (el.top + el.height);
7909 let transformY = 0;
7910
7911 if (self.position === 'absolute') {
7912 if (bottomEdgeDistance < 5) {
7913 transformY = (-1 * el.height) - margin - 12;
7914 if (el.top + transformY < 0) {
7915 transformY = -el.top + 10;
7916 }
7917 }
7918 } else {
7919 if (bottomEdgeDistance < 0) {
7920 transformY = bottomEdgeDistance - margin;
7921 }
7922 }
7923
7924 if (el.top < 0) {
7925 transformY = margin - el.top;
7926 }
7927 if (transformY !== 0) {
7928 self.el.style.marginTop = transformY + 'px';
7929 }
7930 }
7931
7932 const removeElements = function(root) {
7933 // Keep the DOM elements
7934 let elements = [];
7935 if (root) {
7936 while (root.firstChild) {
7937 elements.push(root.firstChild);
7938 root.firstChild.remove();
7939 }
7940 }
7941 return elements;
7942 }
7943
7944 const appendElements = function(root, elements) {
7945 if (elements && elements.length) {
7946 while (elements[0]) {
7947 root.appendChild(elements.shift());
7948 }
7949 }
7950 }
7951
7952 const Modal = function (template, { onchange, onload, track }) {
7953 let self = this;
7954 let backdrop = null;
7955 let elements = null;
7956
7957 if (this.tagName) {
7958 // Remove elements from the DOM
7959 elements = removeElements(this);
7960
7961 this.addEventListener('dragstart', (e) => {
7962 e.preventDefault();
7963 });
7964 }
7965
7966 // Make sure keep the state as boolean
7967 self.closed = !! self.closed;
7968
7969 // Keep all modals references
7970 modals.push(self);
7971
7972 // External onload remove from the lifecycle
7973 let change = self.onchange;
7974 self.onchange = null;
7975
7976 let load = self.onload;
7977 self.onload = null;
7978
7979 let ignoreEvents = false;
7980
7981 const click = function(e) {
7982 if (e.target.classList.contains('lm-modal-close')) {
7983 self.close({ origin: 'button' });
7984 }
7985
7986 if (e.target.classList.contains('lm-modal-minimize')) {
7987 // Handles minimized modal positioning
7988 if (self.minimized === true) {
7989 removeMini(self);
7990 } else {
7991 setMini(self);
7992 }
7993 }
7994 }
7995
7996 const mousemove = function(e) {
7997 if (getButton(e)) {
7998 return;
7999 }
8000
8001 // Get mouse coordinates
8002 let [x,y] = getCoords(e);
8003 // Root element of the component
8004 let item = self.el;
8005 // Get the position and dimensions
8006 let rect = item.getBoundingClientRect();
8007
8008 controls.type = null;
8009 controls.d = null;
8010 controls.e = item;
8011 controls.w = rect.width;
8012 controls.h = rect.height;
8013 controls.t = rect.top;
8014 controls.l = rect.left;
8015
8016 // When resizable
8017 if (isTrue(self.resizable)) {
8018 if (e.clientY - rect.top < cornerSize) {
8019 if (rect.width - (e.clientX - rect.left) < cornerSize) {
8020 item.style.cursor = 'ne-resize';
8021 } else if (e.clientX - rect.left < cornerSize) {
8022 item.style.cursor = 'nw-resize';
8023 } else {
8024 item.style.cursor = 'n-resize';
8025 }
8026 } else if (rect.height - (e.clientY - rect.top) < cornerSize) {
8027 if (rect.width - (e.clientX - rect.left) < cornerSize) {
8028 item.style.cursor = 'se-resize';
8029 } else if (e.clientX - rect.left < cornerSize) {
8030 item.style.cursor = 'sw-resize';
8031 } else {
8032 item.style.cursor = 's-resize';
8033 }
8034 } else if (rect.width - (e.clientX - rect.left) < cornerSize) {
8035 item.style.cursor = 'e-resize';
8036 } else if (e.clientX - rect.left < cornerSize) {
8037 item.style.cursor = 'w-resize';
8038 } else {
8039 item.style.cursor = '';
8040 }
8041
8042 if (item.style.cursor) {
8043 controls.type = 'resize';
8044 controls.d = item.style.cursor;
8045 } else {
8046 controls.type = null;
8047 controls.d = null;
8048 }
8049 }
8050
8051 if (controls.type == null && isTrue(self.draggable)) {
8052 if (y - rect.top < 40) {
8053 item.style.cursor = 'move';
8054 } else {
8055 item.style.cursor = '';
8056 }
8057
8058 if (item.style.cursor) {
8059 controls.type = 'move';
8060 controls.d = item.style.cursor;
8061 } else {
8062 controls.type = null;
8063 controls.d = null;
8064 }
8065 }
8066 }
8067
8068 const mousedown = function(e) {
8069 if (! self.minimized) {
8070 // Get mouse coordinates
8071 let [x,y] = getCoords(e);
8072 controls.x = x;
8073 controls.y = y;
8074 // Root element of the component
8075 let item = self.el;
8076 // Get the position and dimensions
8077 let rect = item.getBoundingClientRect();
8078 controls.e = item;
8079 controls.w = rect.width;
8080 controls.h = rect.height;
8081 controls.t = rect.top;
8082 controls.l = rect.left;
8083 // If is not minimized
8084 if (controls.type === 'resize') {
8085 // Make sure the width and height is defined for the modal
8086 if (! item.style.width) {
8087 item.style.width = controls.w + 'px';
8088 }
8089 if (! item.style.height) {
8090 item.style.height = controls.h + 'px';
8091 }
8092 // This will be the callback when finalize the resize
8093 controls.action = function () {
8094 self.width = parseInt(item.style.width);
8095 self.height = parseInt(item.style.height);
8096 controls.e.classList.remove('action');
8097 // Event
8098 Dispatch.call(self, self.onresize, 'resize', {
8099 instance: self,
8100 width: self.width,
8101 height: self.height,
8102 });
8103 }
8104 controls.e.classList.add('action');
8105 } else if (isTrue(self.draggable) && y - rect.top < 40) {
8106 // Callback
8107 controls.action = function () {
8108 self.top = parseInt(item.style.top);
8109 self.left = parseInt(item.style.left);
8110 controls.e.classList.remove('action');
8111 // Open event
8112 Dispatch.call(self, self.onmove, 'move', {
8113 instance: self,
8114 top: self.top,
8115 left: self.left,
8116 });
8117 }
8118 controls.e.classList.add('action');
8119 // Remove transform
8120 removeMargin(self);
8121 }
8122 }
8123 }
8124
8125 self.back = function() {
8126 sendToBack(self.el);
8127 }
8128
8129 self.front = function() {
8130 sendToFront(self.el);
8131 }
8132
8133 self.open = function() {
8134 if (self.closed === true) {
8135 self.closed = false;
8136 // Close event
8137 Dispatch.call(self, self.onopen, 'open', {
8138 instance: self
8139 });
8140 }
8141 }
8142
8143 self.close = function(options) {
8144 if (self.closed === false) {
8145 self.closed = true;
8146 // Close event
8147 Dispatch.call(self, self.onclose, 'close', {
8148 instance: self,
8149 ...options
8150 });
8151 }
8152 }
8153
8154 self.isClosed = function() {
8155 return self.closed;
8156 }
8157
8158 if (! template || typeof(template) !== 'string') {
8159 template = '';
8160 }
8161
8162 // Custom Root Configuration
8163 self.settings = {
8164 getRoot: function() {
8165 return self.root;
8166 }
8167 }
8168
8169 // Native lemonade
8170 onload(() => {
8171 // Dimensions
8172 if (self.width) {
8173 self.el.style.width = self.width + 'px';
8174 }
8175 if (self.height) {
8176 self.el.style.height = self.height + 'px';
8177 }
8178 // Position
8179 if (self.top) {
8180 self.el.style.top = self.top + 'px';
8181 }
8182 if (self.left) {
8183 self.el.style.left = self.left + 'px';
8184 }
8185
8186 if (self.position === 'absolute' || self.position === 'right' || self.position === 'bottom' || self.position === 'left') {
8187
8188 } else {
8189 if (!self.width && self.el.offsetWidth) {
8190 self.width = self.el.offsetWidth;
8191 }
8192 if (!self.height && self.el.offsetHeight) {
8193 self.height = self.el.offsetHeight;
8194 }
8195
8196 // Initial centralize
8197 if (self.position === 'center' || !self.top) {
8198 self.top = (window.innerHeight - self.height) / 2;
8199 }
8200 if (self.position === 'center' || !self.left) {
8201 self.left = (window.innerWidth - self.width) / 2;
8202 }
8203
8204 // Responsive
8205 if (document.documentElement.clientWidth < 800) {
8206 // Full screen
8207 if (self.height > 300) {
8208 self.el.classList.add('fullscreen');
8209 }
8210 }
8211 }
8212
8213 // Auto adjust
8214 adjustHorizontal(self);
8215 adjustVertical(self);
8216
8217 // Backdrop
8218 if (self.backdrop === true) {
8219 backdrop = document.createElement('div');
8220 backdrop.classList.add('lm-modal-backdrop');
8221 backdrop.addEventListener('click', () => {
8222 self.close({ origin: 'backdrop' });
8223 });
8224
8225 if (self.closed === false) {
8226 self.el.parentNode.insertBefore(backdrop, self.el);
8227 }
8228 }
8229
8230 // Import content from DOM
8231 if (self.content) {
8232 if (typeof(self.content) === 'string') {
8233 template = self.content;
8234 } else if (typeof(self.content) === 'object' && self.content.tagName) {
8235 self.root.appendChild(self.content);
8236 }
8237 }
8238
8239 // Focus out of the component
8240 self.el.addEventListener('focusout', function(e) {
8241 if (! self.el.contains(e.relatedTarget)) {
8242 if (isTrue(self['auto-close'])) {
8243 self.close({ origin: 'focusout' });
8244 }
8245 // Remove focus
8246 self.el.classList.remove('lm-modal-focus');
8247 }
8248 });
8249
8250 // Focus out of the component
8251 self.el.addEventListener('focusin', function(e) {
8252 self.el.classList.add('lm-modal-focus');
8253 });
8254
8255 // Close and stop propagation
8256 self.el.addEventListener('keydown', (e) => {
8257 if (e.key === 'Escape') {
8258 if (self.closed === false) {
8259 self.close({ origin: 'escape' });
8260 e.preventDefault();
8261 e.stopImmediatePropagation();
8262 }
8263 } else if (e.key === 'Enter') {
8264 click(e);
8265 }
8266 });
8267
8268 // Append elements to the container
8269 appendElements(self.el.children[1], elements);
8270
8271 if (self.url) {
8272 fetch(self.url)
8273 .then(response => response.clone().body)
8274 .then(body => {
8275 let reader = body.getReader();
8276 reader.read().then(({ done, value }) => {
8277 // Add HTML to the modal
8278 self.root.innerHTML = new TextDecoder().decode(value.buffer);
8279 // Call onload event
8280 Dispatch.call(self, load, 'load', {
8281 instance: self
8282 });
8283 });
8284 });
8285 } else {
8286 // Call onload event
8287 Dispatch.call(self, load, 'load', {
8288 instance: self
8289 });
8290 }
8291 });
8292
8293 onchange((property) => {
8294 if (ignoreEvents) {
8295 return false;
8296 }
8297
8298 if (property === 'closed') {
8299 if (self.closed === false) {
8300 // Focus on the modal
8301 if (self.focus !== false) {
8302 self.el.focus();
8303 }
8304 // Show backdrop
8305 if (backdrop) {
8306 self.el.parentNode.insertBefore(backdrop, self.el);
8307 }
8308
8309 // Auto adjust
8310 queueMicrotask(() => {
8311 adjustHorizontal(self);
8312 adjustVertical(self);
8313 });
8314 } else {
8315 // Hide backdrop
8316 if (backdrop) {
8317 backdrop.remove();
8318 }
8319 }
8320 } else if (property === 'top' || property === 'left' || property === 'width' || property === 'height') {
8321 if (self[property] !== '') {
8322 self.el.style[property] = self[property] + 'px';
8323 } else {
8324 self.el.style[property] = '';
8325 }
8326
8327 if (self.closed === false) {
8328 queueMicrotask(() => {
8329 if (property === 'top') {
8330 adjustVertical(self);
8331 }
8332 if (property === 'left') {
8333 adjustHorizontal(self);
8334 }
8335 });
8336 }
8337 } else if (property === 'position') {
8338 if (self.position) {
8339 if (self.position === 'center') {
8340 self.top = (window.innerHeight - self.el.offsetHeight) / 2;
8341 self.left = (window.innerWidth - self.el.offsetWidth) / 2;
8342 } else {
8343 self.top = '';
8344 self.left = '';
8345 }
8346 } else {
8347 if (! self.top) {
8348 self.top = (window.innerHeight - self.el.offsetHeight) / 2;
8349 }
8350 if (! self.left) {
8351 self.left = (window.innerWidth - self.el.offsetWidth) / 2;
8352 }
8353 }
8354 }
8355 });
8356
8357 track('top');
8358 track('left');
8359 track('width');
8360 track('height');
8361
8362 return render => render`<div class="lm-modal" animation="{{self.animation}}" position="{{self.position}}" closed="{{self.closed}}" closable="{{self.closable}}" minimizable="{{self.minimizable}}" minimized="{{self.minimized}}" overflow="{{self.overflow}}" tabindex="-1" role="modal" onmousedown="${mousedown}" onmousemove="${mousemove}" onclick="${click}">
8363 <div class="lm-modal-title" data-title="{{self.title}}" data-icon="{{self.icon}}"><div class="lm-modal-icon">{{self.icon}}</div><div>{{self.title}}</div><div class="lm-modal-icon lm-modal-minimize" tabindex="0"></div><div class="lm-modal-icon lm-modal-close" tabindex="0"></div></div>
8364 <div :ref="self.root">${template}</div>
8365 </div>`
8366 }
8367
8368 const Component = function (root, options) {
8369 if (typeof(root) === 'object') {
8370 // Remove elements from the DOM
8371 let elements = removeElements(root);
8372 // Create the modal
8373 let e = lemonade.render(Modal, root, options);
8374 // Add elements to the container
8375 appendElements(e.children[1], elements);
8376
8377 return options;
8378 } else {
8379 return Modal.call(this);
8380 }
8381 }
8382
8383 // Create LemonadeJS Component
8384 lemonade.setComponents({ Modal: Modal });
8385 // Create Web Component
8386 lemonade.createWebComponent('modal', Modal)
8387
8388 return Component;
8389})));
8390
8391/***/ }),
8392
8393/***/ 867:
8394/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
8395
8396if (!lemonade && "function" === 'function') {
8397 var lemonade = __webpack_require__(966);
8398}
8399
8400;(function (global, factory) {
8401 true ? module.exports = factory() :
8402 0;
8403}(this, (function () {
8404
8405 class CustomEvents extends Event {
8406 constructor(type, props, options) {
8407 super(type, {
8408 bubbles: true,
8409 composed: true,
8410 ...options,
8411 });
8412
8413 if (props) {
8414 for (const key in props) {
8415 // Avoid assigning if property already exists anywhere on `this`
8416 if (! (key in this)) {
8417 this[key] = props[key];
8418 }
8419 }
8420 }
8421 }
8422 }
8423
8424 // Dispatcher
8425 const Dispatch = function(method, type, options) {
8426 // Try calling the method directly if provided
8427 if (typeof method === 'function') {
8428 let a = Object.values(options);
8429 return method(...a);
8430 } else if (this.tagName) {
8431 this.dispatchEvent(new CustomEvents(type, options));
8432 }
8433 }
8434
8435 const Rating = function(children, { onchange, onload }) {
8436 let self = this;
8437
8438 // Event
8439 let change = self.onchange;
8440 self.onchange = null;
8441
8442 if (! self.number) {
8443 self.number = 5;
8444 }
8445
8446 self.stars = [];
8447
8448 // Current self star
8449 let current = null;
8450
8451 /**
8452 * Update the number of stars
8453 */
8454 const len = function () {
8455 // Remove stars
8456 if (self.number < self.stars.length) {
8457 self.stars.splice(self.number, self.stars.length);
8458 if (self.value > self.number) {
8459 self.value = self.number;
8460 }
8461 }
8462 // Add missing stars
8463 for (let i = 0; i < self.number; i++) {
8464 if (! self.stars[i]) {
8465 self.stars[i] = {
8466 icon: 'star',
8467 };
8468 if (self.tooltip[i]) {
8469 self.stars[i].title = self.tooltip[i];
8470 }
8471 }
8472 }
8473 // Refresh
8474 self.refresh('stars');
8475 }
8476
8477 const val = function (index, events) {
8478 if (typeof(index) === 'string') {
8479 index = Number(index);
8480 }
8481 // Apply value to the selected property in each star
8482 for (let i = 0; i < self.number; i++) {
8483 self.stars[i].selected = i <= index - 1 ? 1 : 0;
8484 }
8485 // Keep current value
8486 current = index;
8487 // Dispatch method
8488 if (events !== false) {
8489 Dispatch.call(self, change, 'change', {
8490 instance: self,
8491 value: index,
8492 });
8493 }
8494 }
8495
8496 const getElementPosition = function(child) {
8497 if (child.tagName === 'I') {
8498 let root = self.el;
8499 for (let i = 0; i < root.children.length; i++) {
8500 let c = root.children[i];
8501 if (c === child) {
8502 return i;
8503 }
8504 }
8505 }
8506 return -1;
8507 }
8508
8509 const click = function(e, s) {
8510 let ret = getElementPosition(e.target);
8511 if (ret !== -1) {
8512 let index = ret + 1;
8513 if (index === current) {
8514 index = 0;
8515 }
8516 self.value = index;
8517 }
8518 }
8519
8520 const mouseover = function(e, s) {
8521 let index = getElementPosition(e.target);
8522 if (index !== -1) {
8523 for (let i = 0; i < self.number; i++) {
8524 if (i <= index) {
8525 self.stars[i].hover = 1;
8526 } else {
8527 self.stars[i].hover = 0;
8528 }
8529 }
8530 }
8531 }
8532
8533 const mouseout = function(e, s) {
8534 for (let i = 0; i < self.number; i++) {
8535 self.stars[i].hover = 0;
8536 }
8537 }
8538
8539 onchange((prop) => {
8540 if (prop === 'number') {
8541 len();
8542 } else if (prop === 'value') {
8543 val(self.value);
8544 } else if (prop === 'tooltip') {
8545 if (typeof(self.tooltip) === 'string') {
8546 self.tooltip = self.tooltip.split(',')
8547 }
8548 len();
8549 }
8550 })
8551
8552 onload(() => {
8553 // Bind global method to be compatible with LemonadeJS forms
8554 self.el.val = function (v) {
8555 if (typeof (v) === 'undefined') {
8556 return self.value;
8557 } else {
8558 self.value = v;
8559 }
8560 }
8561
8562 if (self.tooltip && typeof(self.tooltip) === 'string') {
8563 self.tooltip = self.tooltip.split(',')
8564 } else {
8565 self.tooltip = '';
8566 }
8567 len();
8568 // Ignore events
8569 val(self.value, false);
8570
8571 self.el.addEventListener('click', click);
8572 self.el.addEventListener('mouseout', mouseout);
8573 self.el.addEventListener('mouseover', mouseover);
8574 });
8575
8576 self.getValue = function () {
8577 return Number(self.value);
8578 }
8579
8580 self.setValue = function (index) {
8581 self.value = index;
8582 }
8583
8584 return `<div class="lm-rating" value="{{self.value}}" number="{{self.number}}" name="{{self.name}}" data-size="{{self.size}}" :loop="self.stars">
8585 <i class="material-symbols-outlined material-icons" data-selected="{{self.selected}}" data-hover="{{self.hover}}" title="{{self.title}}">star</i>
8586 </div>`;
8587 }
8588
8589 // Register the LemonadeJS Component
8590 lemonade.setComponents({ Rating: Rating });
8591 // Register the web component
8592 lemonade.createWebComponent('rating', Rating);
8593
8594 return function (root, options) {
8595 if (typeof (root) === 'object') {
8596 lemonade.render(Rating, root, options)
8597 return options;
8598 } else {
8599 return Rating.call(this, root)
8600 }
8601 }
8602
8603})));
8604
8605/***/ }),
8606
8607/***/ 539:
8608/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
8609
8610if (!lemonade && "function" === 'function') {
8611 var lemonade = __webpack_require__(966);
8612}
8613
8614; (function (global, factory) {
8615 true ? module.exports = factory() :
8616 0;
8617}(this, (function () {
8618
8619 class CustomEvents extends Event {
8620 constructor(type, props, options) {
8621 super(type, {
8622 bubbles: true,
8623 composed: true,
8624 ...options,
8625 });
8626
8627 if (props) {
8628 for (const key in props) {
8629 // Avoid assigning if property already exists anywhere on `this`
8630 if (! (key in this)) {
8631 this[key] = props[key];
8632 }
8633 }
8634 }
8635 }
8636 }
8637
8638 // Dispatcher
8639 const Dispatch = function(method, type, options) {
8640 // Try calling the method directly if provided
8641 if (typeof method === 'function') {
8642 let a = Object.values(options);
8643 return method(...a);
8644 } else if (this.tagName) {
8645 this.dispatchEvent(new CustomEvents(type, options));
8646 }
8647 }
8648
8649 const Switch = function (children, { onchange, onload }) {
8650 let self = this;
8651
8652 // Event
8653 let change = self.onchange;
8654 self.onchange = null;
8655
8656 const state = () => {
8657 let s = self.el.firstChild.checked;
8658 if (s !== self.checked) {
8659 self.checked = s;
8660 }
8661 }
8662
8663 onchange((prop, a, b, c, d) => {
8664 if (a !== b) {
8665 Dispatch.call(self, change, 'change', {
8666 instance: self,
8667 value: self.value,
8668 });
8669 }
8670
8671 state();
8672 })
8673
8674 onload(state);
8675
8676 return render => render`<label class="lm-switch" position="{{self.position}}" data-color="{{self.color}}">
8677 <input type="checkbox" name="{{self.name}}" disabled="{{self.disabled}}" checked="{{self.checked}}" :bind="self.value" /> <span>{{self.text}}</span>
8678 </label>`
8679 }
8680
8681 // Create LemonadeJS references
8682 lemonade.setComponents({ Switch: Switch });
8683 // Create web-component
8684 lemonade.createWebComponent('switch', Switch);
8685
8686 return function (root, options) {
8687 if (typeof (root) === 'object') {
8688 lemonade.render(Switch, root, options)
8689 return options;
8690 } else {
8691 return Switch.call(this, root);
8692 }
8693 }
8694
8695})));
8696
8697/***/ }),
8698
8699/***/ 560:
8700/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
8701
8702if (! lemonade && "function" === 'function') {
8703 var lemonade = __webpack_require__(966);
8704}
8705
8706; (function (global, factory) {
8707 true ? module.exports = factory() :
8708 0;
8709}(this, (function () {
8710
8711 class CustomEvents extends Event {
8712 constructor(type, props, options) {
8713 super(type, {
8714 bubbles: true,
8715 composed: true,
8716 ...options,
8717 });
8718
8719 if (props) {
8720 for (const key in props) {
8721 // Avoid assigning if property already exists anywhere on `this`
8722 if (! (key in this)) {
8723 this[key] = props[key];
8724 }
8725 }
8726 }
8727 }
8728 }
8729
8730 // Dispatcher
8731 const Dispatch = function(method, type, options) {
8732 // Try calling the method directly if provided
8733 if (typeof method === 'function') {
8734 let a = Object.values(options);
8735 return method(...a);
8736 } else if (this.tagName) {
8737 this.dispatchEvent(new CustomEvents(type, options));
8738 }
8739 }
8740
8741 const extract = function(root, self) {
8742 if (! Array.isArray(self.data)) {
8743 self.data = [];
8744 }
8745
8746 if (root.tagName) {
8747 for (let i = 0; i < root.children.length; i++) {
8748 self.data.push({
8749 el: root.children[i],
8750 })
8751 }
8752 } else {
8753 root.forEach((child) => {
8754 self.data.push({
8755 el: child.element,
8756 })
8757 });
8758 }
8759 }
8760
8761 const sorting = function(el, options) {
8762 const obj = {};
8763
8764 let dragElement = null;
8765
8766 el.addEventListener('dragstart', function(e) {
8767 let target = e.target;
8768 if (target.nodeType === 3) {
8769 if (target.parentNode.getAttribute('draggable') === 'true') {
8770 target = target.parentNode;
8771 } else {
8772 e.preventDefault();
8773 e.stopPropagation();
8774 return;
8775 }
8776 }
8777
8778 if (target.getAttribute('draggable') === 'true') {
8779 let position = Array.prototype.indexOf.call(target.parentNode.children, target);
8780 dragElement = {
8781 element: target,
8782 o: position,
8783 d: position
8784 }
8785 target.style.opacity = '0.25';
8786 e.dataTransfer.setDragImage(target,0,0);
8787 }
8788 });
8789
8790 el.addEventListener('dragover', function(e) {
8791 e.preventDefault();
8792
8793 if (dragElement && getElement(e.target) && e.target.getAttribute('draggable') == 'true' && dragElement.element != e.target) {
8794 let element = e.target.clientWidth / 2 > e.offsetX ? e.target : e.target.nextSibling;
8795 e.target.parentNode.insertBefore(dragElement.element, element);
8796 dragElement.d = Array.prototype.indexOf.call(e.target.parentNode.children, dragElement.element);
8797 }
8798 });
8799
8800 el.addEventListener('dragleave', function(e) {
8801 e.preventDefault();
8802 });
8803
8804 el.addEventListener('dragend', function(e) {
8805 e.preventDefault();
8806
8807 if (dragElement) {
8808 let element = dragElement.o < dragElement.d ? e.target.parentNode.children[dragElement.o] : e.target.parentNode.children[dragElement.o].nextSibling
8809 e.target.parentNode.insertBefore(dragElement.element, element);
8810 dragElement.element.style.opacity = '';
8811 dragElement = null;
8812 }
8813 });
8814
8815 el.addEventListener('drop', function(e) {
8816 e.preventDefault();
8817
8818 if (dragElement) {
8819 if (dragElement.o !== dragElement.d) {
8820 if (typeof(options.ondrop) == 'function') {
8821 options.ondrop(el, dragElement.o, dragElement.d, dragElement.element, e.target, e);
8822 }
8823 }
8824
8825 dragElement.element.style.opacity = '';
8826 dragElement = null;
8827 }
8828 });
8829
8830 const getElement = function(element) {
8831 var sorting = false;
8832
8833 function path (element) {
8834 if (element === el) {
8835 sorting = true;
8836 }
8837
8838 if (! sorting) {
8839 path(element.parentNode);
8840 }
8841 }
8842
8843 path(element);
8844
8845 return sorting;
8846 }
8847
8848 for (let i = 0; i < el.children.length; i++) {
8849 if (! el.children[i].hasAttribute('draggable')) {
8850 el.children[i].setAttribute('draggable', 'true');
8851 }
8852 }
8853
8854 return el;
8855 }
8856
8857 const Tabs = function(children, { onchange, onload }) {
8858 let self = this
8859
8860 // Event
8861 let change = self.onchange;
8862 self.onchange = null;
8863
8864 // Add new tab
8865 let createButton;
8866
8867 // Get the references from the root web component
8868 let root;
8869 let template = '';
8870 if (this.tagName) {
8871 root = this;
8872 } else {
8873 // References from LemonadeJS
8874 if (typeof(children) === 'string') {
8875 // Version 4
8876 template = children;
8877 } else if (children && children.length) {
8878 // Version 5
8879 root = children;
8880 }
8881 }
8882
8883 if (root) {
8884 extract(root, self);
8885 }
8886
8887 // Process the data
8888 if (self.data) {
8889 for (let i = 0; i < self.data.length; i++) {
8890 if (! self.data[i].el) {
8891 // Create element
8892 self.data[i].el = document.createElement('div');
8893 // Create from content
8894 if (self.data[i].content) {
8895 self.data[i].el.innerHTML = self.data[i].content;
8896 }
8897 }
8898 }
8899 }
8900
8901 let props = ['title', 'selected', 'data-icon'];
8902
8903 const select = function(index) {
8904 // Make sure the index is a number
8905 index = parseInt(index);
8906 // Do not select tabs that does not exist
8907 if (index >= 0 && index < self.data.length) {
8908 for (let i = 0; i < self.root.children.length; i++) {
8909 self.headers.children[i].classList.remove('selected');
8910 self.root.children[i].classList.remove('selected');
8911 }
8912 self.headers.children[index].classList.add('selected');
8913 self.root.children[index].classList.add('selected');
8914 }
8915 }
8916
8917 const init = function(selected) {
8918 let tabs = [];
8919
8920 for (let i = 0; i < self.data.length; i++) {
8921 // Extract meta information from the DOM
8922 if (props) {
8923 props.forEach((prop) => {
8924 let short = prop.replace('data-', '');
8925 if (! self.data[i][short]) {
8926 let ret = self.data[i].el.getAttribute(prop);
8927 if (ret != null) {
8928 self.data[i][short] = ret;
8929 }
8930 }
8931 });
8932 }
8933 // Create tabs object
8934 tabs[i] = {
8935 title: self.data[i].title,
8936 }
8937 // Which one is selected by default
8938 if (self.data[i].selected) {
8939 selected = i;
8940 }
8941 if (self.data[i].icon) {
8942 tabs[i].icon = self.data[i].icon;
8943 }
8944
8945 self.root.appendChild(self.data[i].el);
8946 }
8947
8948 // Create headers
8949 self.tabs = tabs;
8950
8951 // Default selected
8952 if (typeof(selected) !== 'undefined') {
8953 self.selected = selected;
8954 }
8955
8956 if (props) {
8957 // Add create new tab button
8958 if (createButton) {
8959 self.headers.appendChild(createButton);
8960 }
8961 // Add sorting
8962 sorting(self.el.firstChild.firstChild, {
8963 ondrop: (el, fromIndex, toIndex) => {
8964 // Remove the item from its original position
8965 const [movedItem] = self.data.splice(fromIndex, 1);
8966 // Insert it into the new position
8967 self.data.splice(toIndex, 0, movedItem);
8968 // Make sure correct order
8969 for (let i = 0; i < self.data.length; i++) {
8970 self.root.appendChild(self.data[i].el);
8971 }
8972 // Select new position
8973 self.selected = toIndex;
8974 // Dispatch event
8975 Dispatch.call(self, self.onchangeposition, 'changeposition', {
8976 instance: self,
8977 fromIndex: fromIndex,
8978 toIndex: toIndex,
8979 });
8980 }
8981 })
8982 }
8983
8984 props = null;
8985 }
8986
8987 const create = function() {
8988 // Create a new item
8989 self.create({ title: 'Untitled' }, null, true);
8990 }
8991
8992 const open = function(e) {
8993 if (e.target.tagName === 'LI') {
8994 // Avoid select something already selected
8995 let index = Array.prototype.indexOf.call(e.target.parentNode.children, e.target);
8996 if (index !== self.selected) {
8997 self.selected = index;
8998 }
8999 }
9000 }
9001
9002 const keydown = function(e, s) {
9003 let index = null;
9004 if (e.key === 'Enter') {
9005 self.click(e, s);
9006 } else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
9007 index = self.selected - 1;
9008 if (index < 0) {
9009 index = 0;
9010 }
9011 } else if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
9012 index = self.selected + 1;
9013 if (index > self.tabs.length-1) {
9014 index = self.tabs.length-1;
9015 }
9016 }
9017
9018 // Make selection
9019 if (index !== null) {
9020 self.tabs[index].el.focus();
9021 }
9022 }
9023
9024 onload(() => {
9025 if (template) {
9026 extract(self.root, self);
9027 }
9028
9029 init(self.selected || 0);
9030 })
9031
9032 onchange((property) => {
9033 if (property === 'selected') {
9034 select(self.selected);
9035
9036 Dispatch.call(self, self.onopen, 'open', {
9037 instance: self,
9038 selected: self.selected,
9039 });
9040
9041 Dispatch.call(self, change, 'change', {
9042 instance: self,
9043 value: self.selected,
9044 });
9045 }
9046 })
9047
9048 self.open = function (index) {
9049 self.selected = index;
9050 }
9051
9052 self.create = function(item, position, select) {
9053 // Create element
9054 if (typeof(item) !== 'object') {
9055 console.error('Item must be an object');
9056 } else {
9057
9058 let ret = Dispatch.call(self, self.onbeforecreate, 'beforecreate', {
9059 instance: self,
9060 item: item,
9061 position: position,
9062 });
9063
9064 if (ret === false) {
9065 return false;
9066 }
9067
9068 // Create DOM
9069 item.el = document.createElement('div');
9070 // Create from content
9071 if (item.content) {
9072 item.el.innerHTML = item.content;
9073 }
9074
9075 // Add the new item in the end
9076 if (typeof(position) === 'undefined' || position === null) {
9077 // Mew item
9078 position = self.data.length;
9079 // Add in the end
9080 self.data.push(item);
9081 } else {
9082 self.data.splice(position, 0, item);
9083 }
9084 // New position
9085 if (select) {
9086 // Refresh
9087 init(self.data.indexOf(item));
9088 } else {
9089 init(self.selected);
9090 }
9091
9092 self.tabs.forEach(item => {
9093 item.el.setAttribute('draggable', 'true');
9094 })
9095
9096 Dispatch.call(self, self.oncreate, 'create', {
9097 instance: self,
9098 item: item,
9099 position: position,
9100 });
9101 }
9102 }
9103
9104 self.allowCreate = !! self.allowCreate;
9105
9106 return render => render`<div class="lm-tabs" data-position="{{self.position}}" data-round="{{self.round}}">
9107 <div role="tabs" class="lm-tabs-headers">
9108 <ul :ref="self.headers" :loop="self.tabs" :selected="self.selected" onclick="${open}" onkeydown="${keydown}" onfocusin="${open}"><li class="lm-tab" tabindex="0" role="tab" data-icon="{{self.icon}}">{{self.title}}</li></ul>
9109 <div data-visible="{{self.allowCreate}}" class="lm-tabs-insert-button" role="insert-tab" onclick="${create}">add</div>
9110 </div>
9111 <div :ref="self.root" class="lm-tabs-content">${template}</div>
9112 </div>`
9113 }
9114
9115 lemonade.setComponents({ Tabs: Tabs });
9116
9117 lemonade.createWebComponent('tabs', Tabs);
9118
9119 return function (root, options) {
9120 if (typeof (root) === 'object') {
9121 if (typeof(options) !== 'object') {
9122 options = {};
9123 }
9124 // Extract DOM references
9125 extract(root, options);
9126 // Create the modal
9127 lemonade.render(Tabs, root, options);
9128 // Return self
9129 return options;
9130 } else {
9131 return Tabs.call(this);
9132 }
9133 };
9134})));
9135
9136/***/ }),
9137
9138/***/ 330:
9139/***/ (function(module, __unused_webpack_exports, __webpack_require__) {
9140
9141if (!lemonade && "function" === 'function') {
9142 var lemonade = __webpack_require__(966);
9143}
9144
9145if (! Contextmenu && "function" === 'function') {
9146 var Contextmenu = __webpack_require__(238);
9147}
9148
9149; (function (global, factory) {
9150 true ? module.exports = factory() :
9151 0;
9152}(this, (function () {
9153
9154 const Topmenu = function(children, { onload, onchange }) {
9155 let self = this;
9156
9157 // Current selection
9158 let currentIndex = null;
9159
9160 const getElementPosition = function(child) {
9161 let root = self.el.children[0];
9162 for (let i = 0; i < root.children.length; i++) {
9163 let c = root.children[i];
9164 if (c === child) {
9165 return i;
9166 }
9167 }
9168 return -1;
9169 }
9170
9171 const select = function(e, s) {
9172 if (! self.menu.isClosed()) {
9173 let index = self.options.indexOf(s);
9174 if (index !== currentIndex) {
9175 open(index);
9176 }
9177 }
9178 }
9179
9180 const deselect = function() {
9181 if (self.options) {
9182 self.options.forEach(v => v.selected = false);
9183 }
9184 }
9185
9186 const selectIndex = function(newIndex) {
9187 if (self.options) {
9188 let s = self.options[newIndex];
9189 if (s && ! s.disabled) {
9190 deselect();
9191 // Make it selected
9192 s.selected = true;
9193 // New index
9194 currentIndex = newIndex;
9195 // Focus
9196 s.el.focus();
9197 }
9198 }
9199 }
9200
9201 const open = function(index) {
9202 // Update cursor position
9203 selectIndex(index);
9204 let s = self.options[currentIndex];
9205 if (s && s.submenu) {
9206 let x = s.el.offsetLeft;
9207 let y = s.el.offsetTop + s.el.offsetHeight + 2;
9208 self.menu.open(s.submenu, x, y);
9209 s.expanded = true;
9210 }
9211 }
9212
9213 const close = function() {
9214 self.menu.close(0);
9215 let s = self.options[currentIndex];
9216 if (s) {
9217 s.el.focus();
9218 s.expanded = false;
9219 }
9220 }
9221
9222 const toggle = function(e, s) {
9223 if (s.submenu && ! s.disabled) {
9224 let index = self.options.indexOf(s);
9225 if (index === currentIndex && ! self.menu.isClosed()) {
9226 close();
9227 } else {
9228 open(index);
9229 }
9230 cancel(e);
9231 }
9232 }
9233
9234 const findNextEnabledIndex = function(startIndex) {
9235 if (!self.options || self.options.length === 0) {
9236 return null;
9237 }
9238
9239 let index = startIndex;
9240 let attempts = 0;
9241 const maxAttempts = self.options.length;
9242
9243 while (attempts < maxAttempts) {
9244 if (index >= self.options.length) {
9245 index = 0;
9246 }
9247 if (!self.options[index].disabled) {
9248 return index;
9249 }
9250 index++;
9251 attempts++;
9252 }
9253 return null;
9254 };
9255
9256 const findPreviousEnabledIndex = function(startIndex) {
9257 if (!self.options || self.options.length === 0) {
9258 return null;
9259 }
9260
9261 let index = startIndex;
9262 let attempts = 0;
9263 const maxAttempts = self.options.length;
9264
9265 while (attempts < maxAttempts) {
9266 if (index < 0) {
9267 index = self.options.length - 1;
9268 }
9269 if (!self.options[index].disabled) {
9270 return index;
9271 }
9272 index--;
9273 attempts++;
9274 }
9275 return null;
9276 };
9277
9278 const adjustOptionProperties = function() {
9279 if (self.options) {
9280 self.options.forEach(v => {
9281 v.haspopup = !!v.submenu;
9282 v.expanded = false;
9283
9284 if (v.disabled) {
9285 v.el.removeAttribute('tabindex');
9286 } else {
9287 v.el.setAttribute('tabindex', '0');
9288 }
9289 })
9290 }
9291 };
9292
9293 /**
9294 * Open a submenu programaticaly. Default 0
9295 * @param {number} index
9296 */
9297 self.open = function(index) {
9298 if (typeof index === 'undefined') {
9299 index = currentIndex;
9300 }
9301 if (! index) {
9302 index = 0;
9303 }
9304
9305 let s = self.options[index];
9306 if (s) {
9307 open(index);
9308 }
9309 }
9310
9311 onchange((prop) => {
9312 if (prop === 'options') {
9313 adjustOptionProperties();
9314 }
9315 });
9316
9317 // Keyboard event
9318 onload(() => {
9319 self.el.addEventListener("focusin", function(e) {
9320 let index = getElementPosition(e.target);
9321 if (index !== -1) {
9322 if (e.relatedTarget === self.menu.el) {
9323 close();
9324 } else {
9325 selectIndex(index);
9326 }
9327 }
9328 });
9329
9330 self.el.addEventListener("focusout", function(e) {
9331 if (! (e.relatedTarget && self.el.contains(e.relatedTarget))) {
9332 if (self.options[currentIndex]) {
9333 self.options[currentIndex].selected = false;
9334 }
9335 }
9336 });
9337
9338 self.el.addEventListener("keydown", function(e) {
9339 let o = self.options;
9340 // Select top menu
9341 let select = null;
9342
9343 if (e.key === 'Enter') {
9344 toggle(e, o[currentIndex])
9345 } else if (e.key === 'ArrowLeft') {
9346 select = findPreviousEnabledIndex(currentIndex - 1);
9347 } else if (e.key === 'ArrowRight') {
9348 select = findNextEnabledIndex(currentIndex + 1);
9349 }
9350
9351 if (select !== null) {
9352 if (self.menu.isClosed()) {
9353 selectIndex(select);
9354 } else {
9355 open(select);
9356 }
9357 }
9358 });
9359
9360 adjustOptionProperties();
9361 });
9362
9363 const cancel = function(e) {
9364 e.preventDefault();
9365 e.stopImmediatePropagation();
9366 }
9367
9368 return render => render`<div class="lm-topmenu" role="menubar" aria-orientation="horizontal" oncontextmenu="${cancel}">
9369 <div class="lm-topmenu-options" :loop="self.options">
9370 <div class="lm-topmenu-title" role="menuitem" data-disabled="{{self.disabled}}" data-selected="{{self.selected}}" tabindex="0" aria-haspopup="{{self.haspopup}}" aria-expanded="{{self.expanded}}" aria-label="{{self.title}}" onmousedown="${toggle}" onmouseenter="${select}">{{self.title}}</div>
9371 </div>
9372 <Contextmenu :ref="self.menu" :root="self.el" />
9373 </div>`
9374 }
9375
9376 lemonade.setComponents({ Topmenu: Topmenu });
9377
9378 // Register the web component
9379 lemonade.createWebComponent('topmenu', Topmenu);
9380
9381 return function (root, options) {
9382 if (typeof (root) === 'object') {
9383 lemonade.render(Topmenu, root, options)
9384 return options;
9385 } else {
9386 return Topmenu.call(this, root)
9387 }
9388 }
9389})));
9390
9391/***/ }),
9392
9393/***/ 966:
9394/***/ (function(module) {
9395
9396/**
9397 * LemonadeJS v5
9398 *
9399 * Website: https://lemonadejs.com
9400 * Description: Create amazing web based reusable components.
9401 *
9402 * This software is distributed under MIT License
9403 * @Roadmap
9404 * Accept interpolated values on properties `<div test="test: ${state}"></div>
9405 */
9406
9407;(function (global, factory) {
9408 true ? module.exports = factory() :
9409 0;
9410}(this, (function () {
9411
9412 'use strict';
9413
9414 /**
9415 * Global control element
9416 */
9417 let R = {
9418 queue: [],
9419 container: {},
9420 tracking: new Map,
9421 components: {},
9422 version: 5,
9423 };
9424
9425 // Global LemonadeJS controllers
9426 if (typeof(document) !== "undefined") {
9427 if (! document.lemonadejs) {
9428 document.lemonadejs = R;
9429 } else {
9430 R = document.lemonadejs;
9431 }
9432 }
9433
9434 // Get any conflict of versions
9435 if (! R.version) {
9436 console.error('This project seems to be using version 4 and version 5 causing a conflict of versions.');
9437 }
9438
9439 // Script expression inside LemonadeJS templates
9440 let isScript = /{{(.*?)}}/g;
9441
9442 /**
9443 * Apply value in a object based on the address
9444 */
9445 const Path = function(str, val, remove) {
9446 str = str.split('.');
9447 if (str.length) {
9448 let o = this;
9449 let p = null;
9450 while (str.length > 1) {
9451 // Get the property
9452 p = str.shift();
9453 // Check if the property exists
9454 if (o.hasOwnProperty(p)) {
9455 o = o[p];
9456 } else {
9457 // Property does not exist
9458 if (typeof(val) === 'undefined') {
9459 return undefined;
9460 } else {
9461 // Create the property
9462 o[p] = {};
9463 // Next property
9464 o = o[p];
9465 }
9466 }
9467 }
9468 // Get the property
9469 p = str.shift();
9470 // Set or get the value
9471 if (typeof(val) !== 'undefined') {
9472 if (remove === true) {
9473 delete o[p];
9474 } else {
9475 o[p] = val;
9476 }
9477 // Success
9478 return true;
9479 } else {
9480 // Return the value
9481 if (o) {
9482 return o[p];
9483 }
9484 }
9485 }
9486 // Something went wrong
9487 return false;
9488 }
9489
9490 /**
9491 * Show a better error developers
9492 */
9493 const createError = function() {
9494 throw new Error('LemonadeJS ' + Array.from(arguments).join(' '));
9495 }
9496
9497 /**
9498 * Reference token is a string that define a token and not an expression
9499 * @param {string} token
9500 * @param {boolean?} topLevelOnly
9501 * @returns {boolean}
9502 */
9503 function isReferenceToken(token, topLevelOnly) {
9504 if (topLevelOnly) {
9505 return /^(this|self)(\.\w+)$/gm.test(token);
9506 } else {
9507 return /^(this|self)(\.\w+|\[\d+])*$/gm.test(token);
9508 }
9509 }
9510
9511 /**
9512 * Extract all valid tokens from a string
9513 * @param {string} content
9514 * @returns {string[]}
9515 */
9516 function extractTokens(content) {
9517 // Input validation
9518 if (typeof content !== 'string') {
9519 throw new TypeError('Content must be a string');
9520 }
9521 // Single regex pattern to match both 'self.' and 'this.' prefixed identifiers Negative lookahead (?!\.\w) prevents matching nested properties
9522 //const pattern = /(?:self|this)\.\w+\b(?!\.\w)/g;
9523 const pattern = /(?<=(?:this|self)\.)[a-zA-Z_]\w*/gm
9524
9525 // If no matches found, return empty array early
9526 const matches = content.match(pattern);
9527 if (!matches) {
9528 return [];
9529 }
9530 // Create Set directly from matches array with map transform This is more efficient than adding items one by one
9531 return [...new Set(matches.map(match => match.slice(match.indexOf('.') + 1)))];
9532 }
9533
9534 /**
9535 * Bind a property to one action and start tracking
9536 * @param {object} lemon
9537 * @param {string} prop
9538 */
9539 const trackProperty = function(lemon, prop) {
9540 // Lemon handler
9541 let s = lemon.self;
9542 if (typeof(s) === 'object') {
9543 // Change
9544 let change = lemon.change;
9545 // Events
9546 let events = lemon.events[prop];
9547 // Current value
9548 let value = s[prop];
9549 // Do not allow undefined
9550 if (typeof(value) === 'undefined') {
9551 value = '';
9552 }
9553 // Create the observer
9554 Object.defineProperty(s, prop, {
9555 set: function(v) {
9556 // Old value
9557 let oldValue = value;
9558 // New value
9559 value = v;
9560 // Dispatch reactions
9561 if (events) {
9562 events.forEach((action) => {
9563 action();
9564 });
9565 }
9566 // Refresh bound elements
9567 if (change && change.length) {
9568 change.forEach((action) => {
9569 if (typeof (action) === 'function') {
9570 action.call(s, prop, oldValue, v);
9571 }
9572 })
9573 }
9574 },
9575 get: function () {
9576 // Get value
9577 return value;
9578 },
9579 configurable: true,
9580 enumerable: true,
9581 });
9582 }
9583 }
9584
9585 /**
9586 * Check if an element is appended to the DOM or a shadowRoot
9587 * @param {HTMLElement} node
9588 * @return {boolean}
9589 */
9590 const isAppended = function(node) {
9591 while (node) {
9592 if (node === document.body) {
9593 return true; // Node is in main document
9594 }
9595
9596 if (node.parentNode === null) {
9597 if (node.host) {
9598 node = node.host; // Traverse up through ShadowRoot
9599 } else {
9600 return false; // Detached node
9601 }
9602 } else {
9603 node = node.parentNode; // Traverse up through parentNode
9604 }
9605 }
9606 return false;
9607 }
9608
9609 const elementNotReady = new Set;
9610
9611 /**
9612 * Execute all pending events from onload
9613 * @param lemon
9614 */
9615 const executeOnload = function(lemon) {
9616 let s = lemon.self;
9617 // Ready event
9618 while (lemon.ready.length) {
9619 lemon.ready.shift()();
9620 }
9621 // Native onload
9622 if (typeof(s.onload) === 'function') {
9623 s.onload.call(s, s.el);
9624 }
9625 // Current self
9626 if (typeof(lemon.load) === 'function') {
9627 lemon.load.call(s, s.el);
9628 }
9629 }
9630
9631 /**
9632 * Process the onload methods
9633 */
9634 const processOnload = function(lemon) {
9635 let root = lemon.tree.element;
9636 if (root.tagName === 'ROOT' && lemon.elements) {
9637 root = lemon.elements[0];
9638 }
9639 // Add to the queue
9640 elementNotReady.add(lemon);
9641 // Check if the element is appended to the DOM
9642 if (isAppended(root)) {
9643 elementNotReady.forEach((item) => {
9644 // Remove from the list
9645 elementNotReady.delete(item);
9646 // Run onload and ready events
9647 executeOnload(item);
9648 })
9649 }
9650 }
9651
9652 /**
9653 * Return the element based on the type
9654 * @param item
9655 * @returns {*}
9656 */
9657 const getElement = function(item) {
9658 return typeof(item.type) === 'function' ? item.self : item.element;
9659 }
9660
9661 const HTMLParser = function(html, values) {
9662 /**
9663 * process the scape chars
9664 * @param char
9665 * @returns {*|string}
9666 */
9667 function escape(char) {
9668 const escapeMap = {
9669 'n': String.fromCharCode(0x0A),
9670 'r': String.fromCharCode(0x0D),
9671 't': String.fromCharCode(0x09),
9672 'b': String.fromCharCode(0x08),
9673 'f': String.fromCharCode(0x0C),
9674 'v': String.fromCharCode(0x0B),
9675 '0': String.fromCharCode(0x00)
9676 };
9677
9678 return escapeMap[char] || char;
9679 }
9680
9681 /**
9682 * Check if is a self-closing tag
9683 * @param {string|function} type - Tag name or component function
9684 * @returns {boolean}
9685 */
9686 function isSelfClosing(type) {
9687 if (! type) {
9688 return false;
9689 } else {
9690 // List of self-closing or void HTML elements
9691 const selfClosingTags = [
9692 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'source', 'track', 'wbr'
9693 ];
9694 // Convert tagName to lowercase to ensure case-insensitive comparison
9695 return typeof(type) === 'function' || selfClosingTags.includes(type.toLowerCase());
9696 }
9697 }
9698
9699 /**
9700 * Create a text node and add it to current node's children
9701 * @param {Object} tag - Text node properties
9702 */
9703 const createTextNode = function(tag) {
9704 if (! this.current.children) {
9705 this.current.children = [];
9706 }
9707
9708 this.current.children.push({
9709 type: '#text',
9710 parent: this.current,
9711 props: [tag],
9712 });
9713 }
9714
9715 /**
9716 * Find the parent node by tag name
9717 * @param {Object} node - Current node
9718 * @param {string} type - Tag name to find
9719 * @returns {Object|undefined}
9720 */
9721 const findParentByTagName = function(node, type) {
9722 if (node && type) {
9723 if (node.type === type) {
9724 return node;
9725 } else {
9726 return findParentByTagName(node.parent, type);
9727 }
9728 }
9729
9730 return undefined;
9731 }
9732
9733 /**
9734 * Get expression value and update tag metadata
9735 * @param {Object} tag - Tag to update
9736 * @returns {*} Expression value
9737 */
9738 const getExpression = function(tag) {
9739 // Get value
9740 const v = values && values[this.index] !== undefined ? values[this.index] : '';
9741 if (tag) {
9742 // Keep the reference
9743 tag.expression = this.reference;
9744 // Keep the index
9745 tag.index = this.index;
9746 }
9747 // Move the value index
9748 this.index++;
9749 // Delete reference
9750 delete this.reference;
9751 // Return value
9752 return v;
9753 }
9754
9755 /**
9756 * Handle the text node creation
9757 */
9758 const commitText = function() {
9759 if (typeof(this.text) !== 'undefined') {
9760 const text = this.text.replace(/\r?\n\s+/g, '');
9761 if (text) {
9762 createTextNode.call(this, { name: 'textContent', value: text });
9763 }
9764 delete this.text;
9765 }
9766 }
9767
9768 const commitComments = function() {
9769 if (typeof(this.comments) !== 'undefined') {
9770 let comments = this.comments;
9771 if (comments) {
9772 comments = comments
9773 .replace('<!--', '')
9774 .replace('-->', '')
9775
9776 if (! this.current.children) {
9777 this.current.children = [];
9778 }
9779
9780 this.current.children.push({
9781 type: '#comments',
9782 parent: this.current,
9783 props: [{ name: 'text', value: comments }],
9784 });
9785 }
9786 delete this.comments;
9787 }
9788 }
9789
9790 /**
9791 * Save the attribute to the tag
9792 */
9793 const commitAttribute = function() {
9794 if (this.tag.attributeName) {
9795 // Commit any current attribute
9796 if (! this.tag.props) {
9797 this.tag.props = [];
9798 }
9799
9800 let k = this.tag.attributeName;
9801 let v = this.tag.attributeValue;
9802
9803 if (typeof(v) === 'undefined') {
9804 v = k;
9805 }
9806
9807 let tag = {
9808 name: k,
9809 value: v,
9810 };
9811
9812 if (typeof(this.tag.expression) !== 'undefined') {
9813 tag.index = this.tag.index;
9814 tag.expression = this.tag.expression;
9815 }
9816
9817 this.tag.props.push(tag);
9818
9819 // Clean up temporary properties
9820 delete this.tag.attributeName;
9821 delete this.tag.attributeValue;
9822 delete this.tag.index;
9823 delete this.tag.expression;
9824
9825 if (this.tag.attributeIsReadyToClose) {
9826 delete this.tag.attributeIsReadyToClose;
9827 }
9828 }
9829 }
9830
9831 /**
9832 * Actions controller
9833 * @param {Object} control - Parser control object
9834 * @param {string} char - Current character
9835 */
9836 const actions = function(control, char) {
9837 const method = control.action || 'text';
9838 if (typeof actions[method] === 'function') {
9839 actions[method].call(control, char);
9840 }
9841 }
9842
9843 /**
9844 * Extract content between expression markers, handling quoted content
9845 * @param {string} html - Full HTML string
9846 * @param {number} startIndex - Starting index (position after ${})
9847 * @returns {Object} Expression content and ending position
9848 */
9849 function extractExpressionContent(html, startIndex) {
9850 let text = '';
9851 let i = startIndex;
9852 let insideQuotes = null;
9853
9854 while (i < html.length) {
9855 const char = html[i];
9856
9857 // Handle quotes
9858 if ((char === '"' || char === "'" || char === '`')) {
9859 if (!insideQuotes) {
9860 insideQuotes = char;
9861 } else if (char === insideQuotes) {
9862 insideQuotes = null;
9863 }
9864 }
9865
9866 // Found closing brace outside quotes
9867 if (char === '}' && !insideQuotes) {
9868 return {
9869 content: text,
9870 position: i
9871 };
9872 }
9873
9874 text += char;
9875 i++;
9876 }
9877
9878 return {
9879 content: text,
9880 position: i
9881 };
9882 }
9883
9884 /**
9885 * Process a new tag
9886 * @param char
9887 */
9888 actions.processTag = function(char) {
9889 // Just to check if there are any text to commit
9890 commitText.call(this);
9891
9892 // Process the tag
9893 if (char === '<') {
9894 // Create new tag
9895 this.tag = {
9896 type: '',
9897 parent: this.current
9898 };
9899 } else if (char.match(/[a-zA-Z0-9-]/)) {
9900 // Tag name
9901 this.tag.type += char;
9902 } else {
9903 if (char === '$' && this.reference) {
9904 // Custom tags
9905 this.tag.type = getExpression.call(this);
9906 }
9907 // Finished with tag name, move to attribute handling
9908 this.action = 'attributeName';
9909 }
9910 }
9911
9912 /**
9913 * Handle tag closing
9914 * @param char
9915 */
9916 actions.closeTag = function(char) {
9917 // Make sure to commit attribute
9918 commitAttribute.call(this);
9919 // Close the tag
9920 if (char === '>') {
9921 // Get the new parent
9922 if (isSelfClosing(this.tag.type)) {
9923 // Push new tag to the parent
9924 if (! this.tag.parent.children) {
9925 this.tag.parent.children = [];
9926 }
9927 this.tag.parent.children.push(this.tag);
9928 } else if (this.tag.closingTag) {
9929 // Need to find the parent on the chain
9930 const parentNode = findParentByTagName(this.tag.parent, this.tag.type);
9931 if (parentNode) {
9932 this.current = parentNode.parent;
9933 }
9934 } else {
9935 if (this.tag.closing) {
9936 // Current is the parent
9937 this.current = this.tag.parent;
9938 } else {
9939 this.current = this.tag;
9940 }
9941
9942 // Push new tag to the parent
9943 if (! this.tag.parent.children) {
9944 this.tag.parent.children = [];
9945 }
9946 this.tag.parent.children.push(this.tag);
9947 }
9948
9949 // Remote temporary properties
9950 delete this.tag.insideQuote;
9951 delete this.tag.closingTag;
9952 delete this.tag.closing;
9953 // Finalize tag
9954 this.tag = null;
9955 // New action
9956 this.action = 'text';
9957 } else if (! this.tag.locked) {
9958 if (char === '/') {
9959 if (! this.tag.type) {
9960 // This is a closing tag
9961 this.tag.closingTag = true;
9962 }
9963 // Closing character is found
9964 this.tag.closing = true;
9965 } else if (char.match(/[a-zA-Z0-9-]/)) {
9966 // If is a closing tag, get the tag name
9967 if (this.tag.closingTag) {
9968 this.tag.type += char;
9969 }
9970 } else {
9971 // Wait to the closing sign
9972 if (this.tag.type) {
9973 this.locked = true;
9974 }
9975 }
9976 }
9977 }
9978
9979 actions.attributeName = function(char) {
9980 // There is another attribute to commit
9981 if (this.tag.attributeIsReadyToClose) {
9982 commitAttribute.call(this);
9983 }
9984
9985 // Build attribute name
9986 if (char.match(/[a-zA-Z0-9-:]/)) {
9987 if (! this.tag.attributeName) {
9988 this.tag.attributeName = '';
9989 }
9990 this.tag.attributeName += char;
9991 } else if (char === '=') {
9992 // Move to attribute value
9993 if (this.tag.attributeName) {
9994 this.action = 'attributeValue';
9995 delete this.tag.attributeIsReadyToClose;
9996 }
9997 } else if (char.match(/\s/)) {
9998 if (this.tag.attributeName) {
9999 this.tag.attributeIsReadyToClose = true;
10000 }
10001 }
10002 };
10003
10004 actions.attributeValue = function(char) {
10005 if (! this.tag.attributeValue) {
10006 this.tag.attributeValue = '';
10007 }
10008
10009 if (char === '"' || char === "'") {
10010 if (this.tag.insideQuote) {
10011 if (this.tag.insideQuote === char) {
10012 this.tag.insideQuote = false;
10013 } else {
10014 this.tag.attributeValue += char;
10015 }
10016 } else {
10017 this.tag.insideQuote = char;
10018 }
10019 } else {
10020 if (char === '$' && this.reference) {
10021 // Custom tags
10022 char = getExpression.call(this, this.tag);
10023 }
10024 // Inside quotes, keep appending to the attribute value
10025 if (this.tag.insideQuote) {
10026 if (this.tag.attributeValue) {
10027 this.tag.attributeValue += char;
10028 } else {
10029 this.tag.attributeValue = char;
10030 }
10031 } else if (typeof(char) === 'string' && char.match(/\s/)) {
10032 if (this.tag.attributeValue) {
10033 this.action = 'attributeName';
10034 }
10035 this.tag.attributeIsReadyToClose = true;
10036 } else {
10037 if (this.tag.attributeIsReadyToClose) {
10038 this.action = 'attributeName';
10039 actions.attributeName.call(this, char);
10040 } else {
10041 if (this.tag.attributeValue) {
10042 this.tag.attributeValue += char;
10043 } else {
10044 this.tag.attributeValue = char;
10045 }
10046 }
10047 }
10048 }
10049 }
10050
10051 actions.text = function(char) {
10052 if (char === '$' && this.reference) {
10053 // Just to check if there are any text to commit
10054 commitText.call(this);
10055 // Custom tags
10056 let tag = { name: 'textContent' }
10057 tag.value = getExpression.call(this, tag);
10058 // Add node tag
10059 createTextNode.call(this, tag);
10060 } else {
10061 if (referenceControl === 1) {
10062 // Just to check if there are any text to commit
10063 commitText.call(this);
10064 }
10065
10066 // Normal text processing
10067 if (! this.text) {
10068 this.text = '';
10069 }
10070 this.text += char; // Keep appending to text content
10071
10072 if (referenceControl === 2) {
10073 // Just to check if there are any text to commit
10074 commitText.call(this);
10075 }
10076 }
10077 }
10078
10079 actions.comments = function(char) {
10080 if (! this.comments) {
10081 this.comments = '';
10082 }
10083 this.comments += char;
10084
10085 if (this.comments.endsWith('-->')) {
10086 commitComments.call(this);
10087 this.action = 'text';
10088 }
10089 }
10090
10091 // Control the LemonadeJS native references
10092 let referenceControl = null;
10093
10094 const result = { type: 'template' };
10095 const control = {
10096 current: result,
10097 action: 'text',
10098 index: 0,
10099 };
10100
10101 // Input validation
10102 if (typeof html !== 'string') {
10103 throw new TypeError('HTML input must be a string');
10104 }
10105
10106 // Main loop to process the HTML string
10107 for (let i = 0; i < html.length; i++) {
10108 // Current char
10109 let char = html[i];
10110
10111 if (control.action === 'text' && char === '<' && html[i+1] === '!' && html[i+2] === '-' && html[i+3] === '-') {
10112 control.action = 'comments';
10113 }
10114
10115 if (control.action !== 'comments') {
10116 let escaped = false;
10117
10118 if (values !== null) {
10119 // Handle scape
10120 if (char === '\\') {
10121 // This is a escaped char
10122 escaped = true;
10123 // Parse escape char
10124 char = escape(html[i+1]);
10125 // Move to the next char
10126 i++;
10127 }
10128 }
10129
10130 // Global control logic
10131 if (control.tag) {
10132 if (char === '>' || char === '/') {
10133 // End of tag, commit any attributes and go back to text parsing
10134 if (!control.tag.insideQuote) {
10135 control.action = 'closeTag';
10136 }
10137 }
10138 } else {
10139 if (char === '<') {
10140 control.action = 'processTag';
10141 }
10142 }
10143
10144 // Register references for a dynamic template
10145 if (!escaped && char === '$' && html[i + 1] === '{') {
10146 const result = extractExpressionContent(html, i + 2);
10147 control.reference = result.content;
10148 i = result.position;
10149 }
10150
10151 // Control node references
10152 if (char === '{' && html[i + 1] === '{') {
10153 referenceControl = 1;
10154 } else if (char === '}' && html[i - 1] === '}') {
10155 referenceControl = 2;
10156 }
10157 }
10158
10159 // Execute action
10160 actions(control, char);
10161
10162 // Reference control
10163 referenceControl = null;
10164 }
10165
10166 // Handle any remaining text
10167 commitText.call(control);
10168
10169 return result.children && result.children[0];
10170 }
10171
10172 const generateHTML = function(lemon) {
10173
10174 const appendEvent = function(token, event, exec) {
10175 if (! lemon.events[token]) {
10176 lemon.events[token] = []
10177 }
10178 // Push the event
10179 lemon.events[token].push(event);
10180 // Execute
10181 if (exec) {
10182 event();
10183 }
10184 }
10185
10186 const createEventsFromExpression = function(expression, event, exec) {
10187 // Get the tokens should be updated to populate this attribute
10188 let tokens = extractTokens(expression);
10189 if (tokens.length) {
10190 // Process all the tokens
10191 for (let i = 0; i < tokens.length; i++) {
10192 appendEvent(tokens[i], event);
10193 }
10194 }
10195 // Execute method
10196 if (exec) {
10197 event();
10198 }
10199 }
10200
10201 const setDynamicValue = function(item, prop, attributeName) {
10202 // Create a reference to the DOM element
10203 let property = prop.expression || prop.value;
10204
10205 if (isReferenceToken(property)) {
10206 // Event
10207 let event = function() {
10208 // Reference
10209 let value = extractFromPath.call(lemon.self, property);
10210 // Update reference
10211 setAttribute(getElement(item), attributeName, value);
10212 }
10213 // Append event only for the top level properties in the self
10214 if (isReferenceToken(property, true)) {
10215 let p = extractFromPath.call(lemon.self, property, true);
10216 if (p) {
10217 // Append event to the token change
10218 let token = p[1]
10219 // Append event
10220 appendEvent(token, event);
10221 }
10222 }
10223 // Execute the event in the first time
10224 event();
10225 } else {
10226 setAttribute(getElement(item), attributeName, castProperty(prop.value));
10227 }
10228 }
10229
10230 const dynamicContent = function(text) {
10231 try {
10232 // Cast value
10233 let cast = null;
10234 // Replace the text
10235 text = text.replace(isScript, function (a, b) {
10236 let s = lemon.self;
10237 // Try to find the property
10238 let result = extractFromPath.call(s, b);
10239 // Evaluation for legacy purposes
10240 if (typeof(result) === 'undefined') {
10241 // This is deprecated and will be dropped on LemonadeJS 6
10242 result = run.call(s, b);
10243 if (typeof (result) === 'undefined') {
10244 result = '';
10245 }
10246 } else if (result === null) {
10247 result = '';
10248 }
10249 // Parse correct type
10250 if (typeof(result) !== 'string' && a === text) {
10251 cast = result;
10252 }
10253 // Return
10254 return result;
10255 });
10256
10257 if (cast !== null) {
10258 return cast;
10259 }
10260
10261 return text;
10262 } catch (e) {
10263 }
10264 }
10265
10266 const isHTML = function(str) {
10267 return /<[^>]*>/.test(str);
10268 }
10269
10270 const appendHTMLBeforeNode = function(item, value) {
10271 // Remove previous elements
10272 if (item.current) {
10273 item.current.forEach(e => e?.remove());
10274 }
10275 item.current = [];
10276 // Node container
10277 let node = getElement(item);
10278 // Append content
10279 if (! isHTML(value)) {
10280 node.textContent = value;
10281 } else {
10282 // TODO: improve that
10283 queueMicrotask(() => {
10284 // Create a temporary container
10285 const t = document.createElement('div');
10286 t.innerHTML = value;
10287 // Insert elements and store references
10288 while (t.firstChild) {
10289 item.current.push(t.firstChild);
10290 node.parentNode.insertBefore(t.firstChild, node);
10291 }
10292 });
10293 }
10294 }
10295
10296 const applyElementAttribute = function(item, prop) {
10297 if (typeof(prop.expression) !== 'undefined') {
10298 // Event to update the designed position
10299 let event = function() {
10300 // Extra value from the template
10301 let value = lemon.view(parseTemplate)[prop.index];
10302 // Process the NODE
10303 if (item.type === '#text') {
10304 appendHTMLBeforeNode(item, value);
10305 } else {
10306 // Set attribute
10307 setAttribute(getElement(item), prop.name, value);
10308 }
10309 }
10310 // Bind event to any tokens change
10311 createEventsFromExpression(prop.expression, event, true);
10312 // Register event for state changes
10313 lemon.events[prop.index] = event;
10314 } else {
10315 // Get the tokens should be updated to populate this attribute
10316 let tokens = extractTokens(prop.value);
10317 if (tokens.length) {
10318 // Dynamic
10319 createEventsFromExpression(prop.value, function() {
10320 // Dynamic text
10321 let value = dynamicContent(prop.value);
10322 // Get the dynamic value
10323 setAttribute(getElement(item), prop.name, value);
10324 }, true)
10325 } else {
10326 let value = prop.value;
10327 if (value.match(isScript)) {
10328 value = dynamicContent(value);
10329 }
10330
10331 setAttribute(getElement(item), prop.name, value, true);
10332 }
10333 }
10334 }
10335
10336 /**
10337 * Create a LemonadeJS self bind
10338 * @param item
10339 * @param prop
10340 */
10341 const applyBindHandler = function(item, prop) {
10342 // Create a reference to the DOM element
10343 let property = prop.expression || prop.value;
10344
10345 if (isReferenceToken(property, true)) {
10346 let prop = property.split('.')[1];
10347
10348 // Event from component to the property
10349 let event = function () {
10350 let value = getAttribute(getElement(item), 'value');
10351 if (lemon.self[prop] !== value) {
10352 lemon.self[prop] = value;
10353 }
10354 }
10355
10356 if (typeof (item.type) === 'function') {
10357 item.bind = event;
10358 } else {
10359 item.element.addEventListener('input', event);
10360 }
10361
10362 // Event property to the element
10363 event = () => {
10364 setAttribute(getElement(item), 'value', lemon.self[prop]);
10365 }
10366 // Append event
10367 appendEvent(prop, event, true);
10368 } else if (prop.value instanceof state) {
10369 // TODO: implement :bind states
10370 }
10371 }
10372
10373 /**
10374 * Create a LemonadeJS self render
10375 * @param item
10376 * @param prop
10377 */
10378 const applyRenderHandler = function(item, prop) {
10379 // Create a reference to the DOM element
10380 let property = prop.expression || prop.value;
10381 let getValue = null;
10382 let token = null;
10383
10384 if (isReferenceToken(property, true)) {
10385 token = property.split('.')[1];
10386 // Get value
10387 getValue = () => {
10388 return lemon.self[token];
10389 }
10390 } else {
10391 if (typeof(prop.expression) !== 'undefined') {
10392 getValue = () => {
10393 // Extra value from the template
10394 let data = lemon.view(parseTemplate)[prop.index];
10395 if (data instanceof state) {
10396 data = data.value;
10397 }
10398 return data;
10399 }
10400 }
10401 }
10402
10403 if (getValue) {
10404 // Create container to keep the elements
10405 item.container = [];
10406
10407 // Event property to the element
10408 let event = () => {
10409 // Root element
10410 let root = typeof(item.type) === 'function' ? item.self.el : item.element;
10411 // Curren value
10412 let value = getValue();
10413 if (value) {
10414 item.container.forEach(e => {
10415 root.appendChild(e);
10416 });
10417 } else {
10418 while (root.firstChild) {
10419 item.container.push(root.firstChild);
10420 root.firstChild.remove();
10421 }
10422 }
10423 }
10424
10425 if (token) {
10426 // Append event
10427 appendEvent(token, event);
10428 } else {
10429 if (typeof(prop.expression) !== 'undefined') {
10430 lemon.events[prop.index] = event;
10431 createEventsFromExpression(prop.expression, event);
10432 }
10433 }
10434
10435 // Execute event
10436 let root = typeof(item.type) === 'function' ? item.self.el : item.element;
10437 if (root) {
10438 event();
10439 } else {
10440 lemon.ready.push(event);
10441 }
10442 }
10443 }
10444
10445 /**
10446 * Create a dynamic reference
10447 * @param item
10448 * @param prop
10449 */
10450 const createReference = function(item, prop) {
10451 let ref = getElement(item);
10452 if (typeof(prop.value) === 'function') {
10453 prop.value(ref);
10454 } else {
10455 // Create a reference to the DOM element
10456 let property = prop.expression || prop.value;
10457 // Reference
10458 if (isReferenceToken(property)) {
10459 let p = extractFromPath.call(lemon.self, property, true);
10460 if (p) {
10461 lemon.self[p[1]] = ref;
10462 }
10463 }
10464 }
10465 }
10466
10467 /**
10468 * Process the :ready. Call when DOM is ready
10469 * @param item
10470 * @param prop
10471 */
10472 const whenIsReady = function(item, prop) {
10473 let value = prop.value;
10474 // If not a method, should be converted to a method
10475 if (typeof(value) !== 'function') {
10476 let t = extractFromPath.call(lemon.self, value);
10477 if (t) {
10478 value = t;
10479 }
10480 }
10481 // Must be a function
10482 if (typeof(value) === 'function') {
10483 lemon.ready.push(function() {
10484 value(getElement(item), lemon.self);
10485 });
10486 } else {
10487 createError(`:ready ${value} is not a function`)
10488 }
10489 }
10490
10491 const getRoot = function(item) {
10492 if (typeof(item.type) === 'function') {
10493 if (item.parent.type === 'template') {
10494 return lemon.root;
10495 } else {
10496 return item.parent.element;
10497 }
10498 }
10499
10500 return item.element;
10501 }
10502
10503 const registerLoop = function(item, prop) {
10504 // Create a reference to the DOM element
10505 let property = prop.expression || prop.value;
10506
10507 // Append the template back to the correct position
10508 if (lemon.self.settings?.loop) {
10509 lemon.self.settings.loop(item)
10510 }
10511
10512 // Event
10513 let updateLoop = function(data) {
10514 // Component
10515 let method = typeof(item.type) === 'function' ? item.type : Basic;
10516 // Remove all DOM
10517 let root = getRoot(item);
10518 if (root) {
10519 while (root.firstChild) {
10520 root.firstChild.remove();
10521 }
10522 }
10523 // Process the data
10524 if (data && Array.isArray(data)) {
10525 // Process data
10526 data.forEach(function(self) {
10527 let el = self.el;
10528 if (el) {
10529 root.appendChild(el);
10530 } else {
10531 // Register parent
10532 register(self, 'parent', lemon.self);
10533 // Pass parent view for expressions in loop templates
10534 item.parentView = lemon.view;
10535 // Render
10536 L.render(method, root, self, item);
10537 }
10538
10539 if (root?.getAttribute('unique') === 'false') {
10540 delete self.el;
10541 }
10542 })
10543 }
10544 }
10545
10546 // Event
10547 let event;
10548
10549 // Type of property
10550 if (isReferenceToken(property)) {
10551 // Event
10552 event = function() {
10553 // Reference
10554 let data = extractFromPath.call(lemon.self, property);
10555 // Update reference
10556 updateLoop(data);
10557 }
10558
10559 // Append event only for the top level properties in the self
10560 if (isReferenceToken(property, true)) {
10561 let p = extractFromPath.call(lemon.self, property, true);
10562 if (p) {
10563 // Append event to the token change
10564 appendEvent(p[1], event);
10565 }
10566 }
10567 } else {
10568 if (typeof(prop.expression) !== 'undefined') {
10569 event = function() {
10570 // Extra value from the template
10571 let data = lemon.view(parseTemplate)[prop.index];
10572 if (data instanceof state) {
10573 data = data.value;
10574 }
10575 // Update the data
10576 updateLoop(data);
10577 }
10578 // Register event for state changes
10579 lemon.events[prop.index] = event;
10580 }
10581 }
10582
10583 // Defer event since the dom is not ready
10584 if (event) {
10585 if (getRoot(item)) {
10586 event();
10587 } else {
10588 lemon.ready.push(event);
10589 }
10590 }
10591 }
10592
10593 const isLoopAttribute = function(props) {
10594 let test = false;
10595 props.forEach(function(prop) {
10596 if (prop.name === ':loop' || prop.name === 'lm-loop' || prop.name === '@loop') {
10597 test = true;
10598 }
10599 });
10600 return test;
10601 }
10602
10603 const registerPath = function(item, prop) {
10604 if (! lemon.path.elements) {
10605 lemon.path.elements = [];
10606 }
10607
10608 let element = getElement(item);
10609
10610 lemon.path.elements.push({
10611 element: element,
10612 path: prop.value
10613 });
10614
10615 // Event from component to the property
10616 let event = function () {
10617 // Get the current value of my HTML form element or component
10618 let value = getAttribute(element, 'value');
10619 // Apply the new value on the path on the object
10620 if (lemon.path.value) {
10621 Path.call(lemon.path.value, prop.value, value);
10622 // Call the callback when exist
10623 if (typeof(lemon.path.change) === 'function') {
10624 lemon.path.change(value, prop.value, element);
10625 }
10626 } else {
10627 console.log('Use setPath to define the form container before using lm-path');
10628 }
10629 }
10630
10631 if (typeof(item.type) === 'function') {
10632 item.path = event;
10633 } else {
10634 item.element.addEventListener('input', event);
10635 }
10636 }
10637
10638 const appendChildren = function(container, children) {
10639 if (container && children) {
10640 for (let i = 0; i < children.length; i++) {
10641 let child = children[i];
10642 if (typeof(child) === 'string') {
10643 container.appendChild(document.createTextNode(child));
10644 } else if (child.element) {
10645 if (child.element.tagName === 'ROOT') {
10646 while (child.element.firstChild) {
10647 container.appendChild(child.element.firstChild);
10648 }
10649 } else {
10650 container.appendChild(child.element);
10651 }
10652 }
10653 }
10654 }
10655 }
10656
10657 const getAttributeName = function(prop) {
10658 return prop[0] === ':' || prop[0] === '@' ? prop.substring(1) : prop.substring(3);
10659 }
10660
10661 const getAttributeEvent = function(event) {
10662 event = event.toLowerCase();
10663 if (event.startsWith('on')) {
10664 return event.toLowerCase();
10665 } else if (event.startsWith(':on')) {
10666 return getAttributeName(event);
10667 }
10668 }
10669
10670 /**
10671 * CHeck if the event name is a valid DOM event name
10672 * @param element
10673 * @param eventName
10674 * @returns {boolean}
10675 */
10676 const isValidEventName = function(element, eventName) {
10677 const validEventPattern = /^on[a-z]+$/;
10678 return validEventPattern.test(eventName);
10679 }
10680
10681 /**
10682 * Create element from the string tagname
10683 * @param tagName
10684 * @returns {*}
10685 */
10686 const createElementFromString = function(tagName) {
10687 // List of SVG tags (you can expand this list if needed)
10688 const svgTags = [
10689 "svg", "path", "circle", "rect", "line", "polygon", "polyline", "text"
10690 ];
10691
10692 if (svgTags.includes(tagName)) {
10693 // For SVG elements, use createElementNS with the correct namespace
10694 return document.createElementNS("http://www.w3.org/2000/svg", tagName);
10695 } else {
10696 // For regular HTML elements, use createElement
10697 return document.createElement(tagName);
10698 }
10699 }
10700
10701 const reorderProps = function(arr) {
10702 // Define the desired order of names
10703 const orderPriority = ['ref', 'bind', 'loop', 'ready'];
10704
10705 // Separate items into prioritized and non-prioritized
10706 const prioritized = [];
10707 const others = [];
10708
10709 // Sort items into respective arrays
10710 arr.forEach(item => {
10711 if (orderPriority.includes(item.name.substring(1)) || orderPriority.includes(item.name.substring(3))) {
10712 prioritized.push(item);
10713 } else {
10714 others.push(item);
10715 }
10716 });
10717
10718 // Return combined array with prioritized items at the end
10719 return [...others, ...prioritized];
10720 }
10721
10722
10723 const createElements = function(item) {
10724 if (typeof(item) === 'object') {
10725 // Create an element
10726 if (item.type === '#comments') {
10727 item.element = document.createComment(item.props[0].value);
10728 } else if (item.type === '#text') {
10729 // Text node
10730 item.element = document.createTextNode('');
10731 // Check for dynamic content
10732 applyElementAttribute(item, item.props[0]);
10733 } else {
10734 // Apply attributes if they exist
10735 if (item.props && ! Array.isArray(item.props)) {
10736 let props = [];
10737 let keys = Object.keys(item.props);
10738 for (let i = 0; i < keys.length; i++) {
10739 props.push({ name: keys[i], value: item.props[keys[i]] });
10740 }
10741 item.props = props;
10742 } else if (! item.props) {
10743 item.props = [];
10744 }
10745
10746 // This item is a parent for a loop
10747 if (isLoopAttribute(item.props)) {
10748 // Mark this item as a loop
10749 item.loop = true;
10750 }
10751
10752 if (! item.type) {
10753 item.type = 'root';
10754 }
10755
10756 if (typeof(item.type) === 'string') {
10757 if (item.type.match(/^[A-Z][a-zA-Z0-9\-]*$/g)) {
10758 let controller = item.type.toUpperCase();
10759 if (typeof(R.components[controller]) === 'function') {
10760 item.type = R.components[controller];
10761 } else if (typeof (lemon.components[controller]) === 'function') {
10762 item.type = lemon.components[controller];
10763 } else {
10764 }
10765 }
10766 }
10767
10768 if (typeof(item.type) === 'string') {
10769 item.element = createElementFromString(item.type);
10770 } else if (typeof(item.type) === 'function') {
10771 // Create instance without calling constructor
10772 if (isClass(item.type)) {
10773 item.self = new item.type;
10774 } else {
10775 item.self = {};
10776 }
10777 }
10778
10779 // Create all children
10780 if (! item.loop) {
10781 if (item.children && Array.isArray(item.children)) {
10782 item.children.forEach(child => {
10783 createElements(child);
10784 });
10785 }
10786 if (item.element) {
10787 appendChildren(item.element, item.children);
10788 }
10789 }
10790
10791 // Process attributes
10792 if (item.props.length) {
10793 // Reorder props
10794 item.props = reorderProps(item.props);
10795 // Order by priority
10796 item.props.forEach(function(prop) {
10797 try {
10798 // If the property is an event
10799 let event = getAttributeEvent(prop.name);
10800 // When event for a DOM
10801 if (event) {
10802 // Element
10803 let element = item.element;
10804 // Value
10805 let value = prop.value;
10806 if (value) {
10807 let handler = null; // Reset handler for each iteration
10808 if (typeof (value) === 'function') {
10809 handler = value;
10810 } else {
10811 let t = extractFromPath.call(lemon.self, value);
10812 if (t) {
10813 if (typeof (t) === 'function') {
10814 prop.value = handler = t;
10815 }
10816 }
10817 }
10818 // When the element is a DOM
10819 if (isDOM(element)) {
10820 // Create the event handler
10821 let eventHandler;
10822 // Bind event
10823 if (typeof(handler) === 'function') {
10824 eventHandler = function(e, a, b) {
10825 return handler.call(element, e, lemon.self, a, b);
10826 }
10827 } else {
10828 // Legacy compatibility. Inline scripting is non-Compliance with Content Security Policy (CSP).
10829 eventHandler = function (e) {
10830 return Function('e', 'self', value).call(element, e, lemon.self); // TODO, quebra tudo se mudar
10831 }
10832 }
10833
10834 if (isValidEventName(element, prop.name)) {
10835 element.addEventListener(event.substring(2), eventHandler);
10836 } else {
10837 if (element.tagName?.includes('-')) {
10838 element[event] = handler;
10839 } else {
10840 element[event] = eventHandler;
10841 }
10842 }
10843 } else {
10844 item.self[event] = handler || value;
10845 }
10846 }
10847 } else if (prop.name.startsWith(':') || prop.name.startsWith('@') || prop.name.startsWith('lm-')) {
10848 // Special lemonade attribute name
10849 let attrName = getAttributeName(prop.name);
10850 // Special properties bound to the self
10851 if (attrName === 'ready') {
10852 whenIsReady(item, prop);
10853 } else if (attrName === 'ref') {
10854 createReference(item, prop);
10855 } else if (attrName === 'loop') {
10856 registerLoop(item, prop);
10857 } else if (attrName === 'bind') {
10858 applyBindHandler(item, prop);
10859 } else if (attrName === 'path') {
10860 registerPath(item, prop);
10861 } else if (attrName === 'render') {
10862 applyRenderHandler(item, prop);
10863 } else {
10864 setDynamicValue(item, prop, attrName);
10865 }
10866 } else {
10867 applyElementAttribute(item, prop);
10868 }
10869 } catch (e) {
10870 let propValue = prop.expression || prop.value;
10871 console.error(`${prop.name}="${propValue}" - ${e.message}`, item);
10872 }
10873 })
10874 }
10875
10876 // Do not create elements at this state if this is a loop
10877 if (! item.loop) {
10878 if (typeof(item.type) === 'function') {
10879 // Execute component
10880 item.element = L.render(item.type, null, item.self, item);
10881
10882 // Create all children
10883 if (item.children) {
10884 let root = item.element;
10885 if (typeof(item.self?.settings?.getRoot) === 'function') {
10886 root = item.self.settings.getRoot();
10887 }
10888 appendChildren(root, item.children);
10889 }
10890 }
10891 }
10892 }
10893 }
10894 }
10895
10896 // Create DOM elements
10897 createElements(lemon.tree);
10898
10899 return lemon.tree.element;
10900 }
10901
10902 /**
10903 * Extract a property from a nested object using a string address
10904 * @param {string} str address inside the nested object
10905 * @param {boolean} config get the configuration obj => property
10906 */
10907 const extractFromPath = function(str, config) {
10908 try {
10909 let t = str.toString().replace(/[\[\]]/g, '.').split('.');
10910 if (t[0] === 'self' || t[0] === 'this') {
10911 t.shift();
10912 }
10913 // Remove blanks
10914 t = t.filter(item => item !== '');
10915 // Object
10916 let o = this;
10917 let lastObject;
10918 while (t.length) {
10919 // Get the property
10920 let p = t.shift();
10921 // Process config
10922 if (config) {
10923 if (typeof(o) === 'object' && ! Array.isArray(o)) {
10924 lastObject = [o,p];
10925 }
10926 if (t.length === 0) {
10927 return lastObject;
10928 }
10929 }
10930 // Check if the property exists
10931 if (o.hasOwnProperty(p) || typeof(o[p]) !== 'undefined') {
10932 o = o[p];
10933 } else {
10934 return undefined;
10935 }
10936 }
10937
10938 if (typeof(o) !== 'undefined') {
10939 return o;
10940 }
10941 } catch (e) {}
10942
10943 // Something went wrong
10944 return undefined;
10945 }
10946
10947 /**
10948 * Cast the value of an attribute
10949 */
10950 const castProperty = function(attr) {
10951 // Parse type
10952 try {
10953 if (typeof(attr) === 'string' && attr) {
10954 // Remove any white spaces
10955 attr = attr.trim();
10956 if (attr === 'true') {
10957 return true;
10958 } else if (attr === 'false') {
10959 return false;
10960 } else if (! isNaN(attr)) {
10961 return Number(attr);
10962 } else {
10963 let firstChar = attr[0];
10964 if (firstChar === '{' || firstChar === '[') {
10965 if (attr.slice(-1) === '}' || attr.slice(-1) === ']') {
10966 return JSON.parse(attr);
10967 }
10968 } else if (attr.startsWith('self.') || attr.startsWith('this.')) {
10969 let v = extractFromPath.call(this, attr);
10970 if (typeof(v) !== 'undefined') {
10971 return v;
10972 }
10973 }
10974 }
10975 }
10976 } catch (e) {}
10977
10978 return attr;
10979 }
10980
10981 /**
10982 * This allows to run inline script on LEGACY system. Inline script can lead to security issues so use carefully.
10983 * @param {string} s string to function
10984 */
10985 const run = function(s) {
10986 return Function('self', '"use strict";return (' + s + ')')(this);
10987 }
10988
10989 /**
10990 * Check if the content {o} is a valid DOM Element
10991 * @param {HTMLElement|DocumentFragment|object} o - is this a valid dom?
10992 * @return {boolean}
10993 */
10994 const isDOM = function(o) {
10995 return (o instanceof HTMLElement || o instanceof Element || o instanceof DocumentFragment);
10996 }
10997
10998 /**
10999 * Check if the method is a method or a class
11000 * @param {function} f
11001 * @return {boolean}
11002 */
11003 const isClass = function(f) {
11004 return typeof f === 'function' && /^class\s/.test(Function.prototype.toString.call(f));
11005 }
11006
11007 /**
11008 * Basic handler
11009 * @param {string|object} t - HTML template
11010 * @return {string|object}
11011 */
11012 const Basic = function(t) {
11013 return t;
11014 }
11015
11016 /**
11017 * Get the attribute helper
11018 * @param {object} e Element
11019 * @param {string} attribute
11020 */
11021 const getAttribute = function(e, attribute) {
11022 let value;
11023 if (attribute === 'value') {
11024 if (typeof(e.val) === 'function') {
11025 value = e.val();
11026 } else {
11027 if (e.getAttribute) {
11028 if (e.tagName === 'SELECT' && e.getAttribute('multiple') !== null) {
11029 value = [];
11030 for (let i = 0; i < e.options.length; i++) {
11031 if (e.options[i].selected) {
11032 value.push(e.options[i].value);
11033 }
11034 }
11035 } else if (e.type === 'checkbox') {
11036 value = e.checked && e.getAttribute('value') ? e.value : e.checked;
11037 } else if (e.getAttribute('contenteditable')) {
11038 value = e.innerHTML;
11039 } else {
11040 value = e.value;
11041 }
11042 } else {
11043 value = e.value;
11044 }
11045 }
11046 }
11047 return value;
11048 }
11049
11050 /**
11051 * Set attribute value helper
11052 * @param {object} e Element
11053 * @param {string} attribute
11054 * @param {any} value
11055 * @param {boolean?} propertyValue
11056 */
11057 const setAttribute = function(e, attribute, value, propertyValue) {
11058 // Handle state
11059 if (value instanceof state) {
11060 value = value.value;
11061 } else if (typeof(value) === 'undefined') {
11062 value = '';
11063 }
11064
11065 if (attribute === 'value' && ! propertyValue) {
11066 // Update HTML form element
11067 if (typeof (e.val) === 'function') {
11068 if (e.val() != value) {
11069 e.val(value);
11070 }
11071 } else if (e.tagName === 'SELECT' && e.getAttribute('multiple') !== null) {
11072 for (let j = 0; j < e.children.length; j++) {
11073 e.children[j].selected = value.indexOf(e.children[j].value) >= 0;
11074 }
11075 } else if (e.type === 'checkbox') {
11076 e.checked = !(!value || value === '0' || value === 'false');
11077 } else if (e.type === 'radio') {
11078 e.checked = e.value == value;
11079 } else if (e.getAttribute && e.getAttribute('contenteditable')) {
11080 if (e.innerHTML != value) {
11081 e.innerHTML = value;
11082 }
11083 } else {
11084 // Make sure apply that to the value
11085 e.value = value;
11086 // Update attribute if exists
11087 if (e.getAttribute && e.getAttribute('value') !== null) {
11088 e.setAttribute('value', value);
11089 }
11090 }
11091 } else if (typeof(value) === 'object' || typeof(value) === 'function') {
11092 e[attribute] = value;
11093 } else {
11094 if (isDOM(e)) {
11095 if (typeof (e[attribute]) !== 'undefined' && !(e.namespaceURI && e.namespaceURI.includes('svg'))) {
11096 e[attribute] = value;
11097 } else {
11098 if (value === '') {
11099 e.removeAttribute(attribute);
11100 } else {
11101 e.setAttribute(attribute, value);
11102 }
11103 }
11104 } else {
11105 e[attribute] = value;
11106 }
11107 }
11108 }
11109
11110 /**
11111 * Get attributes as an object
11112 * @param {boolean} props - all attributes that are not undefined
11113 * @return {object}
11114 */
11115 const getAttributes = function(props) {
11116 let o = {};
11117 let k = null;
11118 let a = this.attributes;
11119 if (a && a.length) {
11120 for (let i = 0; i < a.length; i++) {
11121 k = a[i].name;
11122 if (props && typeof(this[k]) !== 'undefined') {
11123 o[k] = this[k];
11124 } else {
11125 o[k] = a[i].value;
11126 }
11127 }
11128 }
11129 return o;
11130 }
11131
11132 /**
11133 * Register a getter without setter for a self object
11134 * @param {object} s - self object
11135 * @param {string} p - self property
11136 * @param {string|object|number} v - value
11137 */
11138 const register = function(s, p, v) {
11139 if (typeof(s) === 'object') {
11140 Object.defineProperty(s, p, {
11141 enumerable: false,
11142 configurable: true,
11143 get: function () {
11144 return v;
11145 }
11146 });
11147 }
11148 }
11149
11150 /**
11151 * Extract variables from the dynamic and append to the self
11152 * @return {[string, array]} grab the literal injection
11153 */
11154 const parseTemplate = function() {
11155 let args = Array.from(arguments);
11156 // Remove first
11157 args.shift()
11158 // Return the final template
11159 return args;
11160 }
11161
11162 function cloneChildren(element) {
11163 // Base case: if an element is null/undefined or not an object, return as is
11164 if (!element || typeof element !== 'object') {
11165 return element;
11166 }
11167
11168 // Handle arrays
11169 if (Array.isArray(element)) {
11170 return element.map(item => cloneChildren(item));
11171 }
11172
11173 // Create a new object
11174 const cloned = {};
11175
11176 // Clone each property
11177 for (const key in element) {
11178 if (key === 'children') {
11179 // Handle children especially as before
11180 cloned.children = element.children ? cloneChildren(element.children) : undefined;
11181 } else if (key === 'props') {
11182 // Deep clone props array
11183 cloned.props = element.props.map(prop => ({
11184 ...prop,
11185 value: prop.value // If value is a function, it will maintain the reference which is what we want
11186 }));
11187 } else {
11188 // Clone other properties
11189 cloned[key] = element[key];
11190 }
11191 }
11192
11193 return cloned;
11194 }
11195
11196 // LemonadeJS object
11197 const L = {};
11198
11199 /**
11200 * Render a lemonade DOM element, method or class into a root DOM element
11201 * @param {function} component - LemonadeJS component or DOM created
11202 * @param {HTMLElement} root - root DOM element to receive the new HTML
11203 * @param {object?} self - self to be used
11204 * @param {object?} item - item
11205 * @return {HTMLElement|boolean} o
11206 */
11207 L.render = function(component, root, self, item) {
11208 if (typeof(component) !== 'function') {
11209 console.error('Component is not a function');
11210 return false;
11211 }
11212
11213 // In case the self has not initial definition by the developer
11214 if (typeof(self) === 'undefined') {
11215 self = {};
11216 }
11217
11218 // Web component
11219 if (self.tagName && self.tagName.includes('-')) {
11220 let props = getAttributes.call(self, true);
11221 // Copy all values to the object
11222 L.setProperties.call(self, props, true);
11223 }
11224
11225 // Arguments
11226 let args = Array.from(arguments);
11227
11228 // Lemonade component object
11229 let lemon = {
11230 self: self,
11231 ready: [],
11232 change: [],
11233 events: {},
11234 components: {},
11235 elements: [],
11236 root: root,
11237 path: {},
11238 }
11239
11240 // Current onchange
11241 let externalOnchange = self.onchange;
11242 let externalOnload = self.onload;
11243
11244 if (! item) {
11245 item = {};
11246 } else if (typeof(item) === 'string') {
11247 item = {
11248 children: item,
11249 }
11250 }
11251
11252 let view;
11253 let result;
11254
11255 // New self
11256 if (component === Basic) {
11257 view = cloneChildren(item.children[0]);
11258
11259 if (item.parentView) {
11260 lemon.view = item.parentView;
11261 }
11262 } else {
11263 R.currentLemon = lemon;
11264
11265 const tools = {
11266 onload: (...args) => setOnload(lemon, ...args),
11267 onchange: (...args) => setOnchange(lemon, ...args),
11268 track: (...args) => setTrack(lemon, ...args),
11269 state: (...args) => setState(lemon, ...args),
11270 setPath: (...args) => setPath(lemon, ...args),
11271 };
11272
11273 if (isClass(component)) {
11274 if (! (self instanceof component)) {
11275 lemon.self = self = new component(self);
11276 }
11277 view = self.render(item.children, tools);
11278 } else {
11279 // Execute component
11280 view = component.call(self, item.children, tools);
11281 }
11282
11283 // Resolve onchange scope conflict
11284 if (typeof(self.onchange) === 'function' && externalOnchange !== self.onchange) {
11285 // Keep onchange event in the new onchange format
11286 lemon.change.push(self.onchange);
11287 // Keep the external onchange
11288 self.onchange = externalOnchange;
11289 }
11290
11291 R.currentLemon = null;
11292 }
11293
11294 // Values
11295 let values = null;
11296 // Process return
11297 if (typeof(view) === 'function') {
11298 values = view(parseTemplate);
11299 // Curren values
11300 lemon.values = values;
11301 // A render template to be executed
11302 lemon.view = view;
11303 // Template from the method
11304 result = view.toString().split('`');
11305 // Get the original template
11306 if (result) {
11307 // Remove the last element
11308 result.shift();
11309 result.pop();
11310 // Join everything else
11311 result = result.join('`').trim();
11312 }
11313 } else {
11314 result = view;
11315 }
11316
11317 // Virtual DOM tree
11318 if (typeof(result) === 'string') {
11319 result = HTMLParser(result.trim(), values);
11320 }
11321
11322 let element;
11323
11324 // Process the result
11325 if (result) {
11326 // Get the HTML virtual DOM representation
11327 lemon.tree = result;
11328
11329 // Create real DOM and append to the root
11330 element = generateHTML(lemon);
11331
11332 if (element) {
11333 // Parents
11334 lemon.elements = [];
11335 // Append parents
11336 if (element.tagName === 'ROOT') {
11337 element.childNodes.forEach((e) => {
11338 lemon.elements.push(e);
11339 });
11340 } else {
11341 lemon.elements.push(element);
11342 }
11343
11344 // Register element when is not registered inside the component
11345 register(lemon.self, 'el', element);
11346
11347 const destroy = () => {
11348 // Do not add in the same root
11349 let div = document.createElement('div');
11350 // Append temporary DIV to the same position
11351 lemon.elements[0].parentNode.insertBefore(div, lemon.elements[0]);
11352 // Remove the old elements
11353 lemon.elements.forEach((e) => {
11354 e.remove();
11355 });
11356 // Root element
11357 args[1] = div;
11358 // Create a new component
11359 L.render(...args);
11360 // Append elements in the same position in the DOM tree
11361 while (div.firstChild) {
11362 div.parentNode.insertBefore(div.firstChild, div);
11363 }
11364 // Remove DIV
11365 div.remove();
11366 // Object not in use
11367 lemon = null;
11368 }
11369
11370 // Refresh
11371 register(lemon.self, 'refresh', (prop) => {
11372 if (prop) {
11373 if (prop === true) {
11374 destroy();
11375 } else {
11376 lemon.self[prop] = lemon.self[prop];
11377 }
11378 } else {
11379 if (lemon.view) {
11380 runViewValues(lemon);
11381 } else {
11382 destroy();
11383 }
11384 }
11385 });
11386
11387 // Append element to the DOM
11388 if (root) {
11389 lemon.elements.forEach((e) => {
11390 root.appendChild(e);
11391 });
11392 }
11393 } else {
11394 // Refresh
11395 register(lemon.self, 'refresh', (prop) => {
11396 if (prop) {
11397 if (prop === true) {
11398 runViewValues(lemon);
11399 } else {
11400 lemon.self[prop] = lemon.self[prop];
11401 }
11402 }
11403 });
11404 }
11405 }
11406
11407 // Bind to custom component
11408 if (item.bind || item.path) {
11409 let token = 'value';
11410 if (! lemon.events[token]) {
11411 lemon.events[token] = []
11412 }
11413 // Push the event
11414 if (item.bind) {
11415 lemon.events[token].push(item.bind);
11416 }
11417 if (item.path) {
11418 lemon.events[token].push(item.path);
11419 }
11420 }
11421
11422 // In case initial exists
11423 if (typeof(lemon.path.initial) === 'object') {
11424 // Get the value of the draft
11425 let newValue = lemon.path.initial;
11426 // Delete draft
11427 delete lemon.path.initial;
11428 // Apply new values
11429 lemon.path.setValue(newValue);
11430
11431 }
11432
11433 // Apply events
11434 if (lemon.events) {
11435 let props = Object.keys(lemon.events);
11436 if (props.length) {
11437 for (let i = 0; i <props.length; i++) {
11438 let prop = props[i];
11439 if (prop != Number(prop)) {
11440 trackProperty(lemon, prop);
11441 }
11442 }
11443 }
11444 }
11445
11446 // Process the onload
11447 if (element) {
11448 processOnload(lemon);
11449 }
11450
11451 return element;
11452 }
11453
11454 const registerComponents = function(components) {
11455 if (components && R.currentLemon) {
11456 for (const key in components) {
11457 R.currentLemon.components[key.toUpperCase()] = components[key];
11458 }
11459 }
11460 }
11461
11462 /**
11463 * Deprecated
11464 * @param {string} template
11465 * @param {object?} s (self)
11466 * @param {object?} components
11467 */
11468 L.element = function(template, s, components) {
11469 if (R.currentLemon && s && typeof(s) === 'object') {
11470 if (s !== R.currentLemon.self) {
11471 R.currentLemon.self = s;
11472 }
11473 }
11474 registerComponents(components);
11475 return template;
11476 }
11477
11478 /**
11479 * Apply self to an existing appended DOM element
11480 * @param {HTMLElement} el - element root
11481 * @param {object} s - self to associate to the template
11482 * @param {object?} components - object with component declarations
11483 */
11484 L.apply = function(el, s, components) {
11485 let template = el.innerHTML;
11486 el.textContent = '';
11487 let Component = function() {
11488 registerComponents(components);
11489 return `<>${template}</>`;
11490 }
11491 return L.render(Component,el,s);
11492 }
11493
11494 /**
11495 * Get all properties existing in {o} and create a new object with the values from {this};
11496 * @param {object} o - reference object with the properties relevant to the new object
11497 * @return {object} n - the new object with all new values
11498 */
11499 L.getProperties = function(o) {
11500 // The new object with all properties found in {o} with values from {this}
11501 let n = {};
11502 for (let p in o) {
11503 n[p] = this[p];
11504 }
11505 return n;
11506 }
11507
11508 /**
11509 * Set the values from {o} to {this}
11510 * @param {object} o set the values of {this} when the `this[property]` is found in {o}, or when flag force is true
11511 * @param {boolean} f create a new property when that does not exist yet, but is found in {o}
11512 * @return {object} this is redundant since object {this} is a reference and is already available in the caller
11513 */
11514 L.setProperties = function(o, f) {
11515 for (let p in o) {
11516 if (this.hasOwnProperty(p) || f) {
11517 this[p] = o[p];
11518 }
11519 }
11520 return this;
11521 }
11522
11523 /**
11524 * Reset the values of any common property name between this and a given object
11525 * @param {object} o - all properties names in the object {o} found in {this} will be reset.
11526 */
11527 L.resetProperties = function(o) {
11528 for (let p in o) {
11529 this[p] = '';
11530 }
11531 }
11532
11533 /**
11534 * Lemonade CC (common container) helps you share a self or function through the whole application
11535 * @param {string} name alias for your declared object(self) or function
11536 * @returns {Object | Function} - registered element
11537 */
11538 L.get = function(name) {
11539 return R.container[name];
11540 }
11541
11542 /**
11543 * Register something to the Lemonade CC (common container)
11544 * @param {string} name - alias for your declared object(self) or function
11545 * @param {object|function} e - the element to be added to the common container. Can be an object(self) or function.
11546 * @param {boolean} persistence - optional the persistence flag. Only applicable for functions.
11547 */
11548 L.set = function(name, e, persistence) {
11549 // Applicable only when the o is a function
11550 if (typeof(e) === 'function' && persistence === true) {
11551 // Keep the flag
11552 e.storage = true;
11553 // Any existing values
11554 let t = window.localStorage.getItem(name);
11555 if (t) {
11556 // Parse JSON
11557 t = JSON.parse(t);
11558 // Execute method with the existing values
11559 e(t);
11560 }
11561 }
11562 // Save to the sugar container
11563 R.container[name] = e;
11564 }
11565
11566 /**
11567 * Dispatch the new values to the function
11568 * @param {string} name - alias to the element saved on the Lemonade CC (common container)
11569 * @param {object?} data - data to be dispatched
11570 */
11571 L.dispatch = function(name, data) {
11572 // Get from the container
11573 let e = R.container[name];
11574 // Confirm that the alias is a function
11575 if (typeof(e) === 'function') {
11576 // Save the data to the local storage
11577 if (e.storage === true) {
11578 window.localStorage.setItem(name, JSON.stringify(data));
11579 }
11580 // Dispatch the data to the function
11581 return e(data);
11582 }
11583 }
11584
11585 /**
11586 * Register components
11587 * @param {object} components - register components
11588 */
11589 L.setComponents = function(components) {
11590 if (typeof(components) === 'object') {
11591 // Component names
11592 let k = Object.keys(components);
11593 // Make sure they follow the standard
11594 for (let i = 0; i < k.length; i++) {
11595 R.components[k[i].toUpperCase()] = components[k[i]];
11596 }
11597 }
11598 }
11599
11600 L.component = class {}
11601
11602 /**
11603 * Create a Web Component
11604 * @param {string} name - web component name
11605 * @param {function} handler - lemonadejs component
11606 * @param {object} options - options to create the web components
11607 */
11608 L.createWebComponent = function(name, handler, options) {
11609 if (typeof(window) === 'undefined') {
11610 return;
11611 }
11612
11613 if (typeof(handler) !== 'function') {
11614 return 'Handler should be an function';
11615 }
11616 // Prefix
11617 let prefix = options && options.prefix ? options.prefix : 'lm';
11618
11619 // Component name
11620 const componentName = prefix + '-' + name;
11621
11622 // Check if the component is already defined
11623 if (! window.customElements.get(componentName)) {
11624 class Component extends HTMLElement {
11625 constructor() {
11626 super();
11627 }
11628
11629 connectedCallback() {
11630 // LemonadeJS self
11631 let self = this;
11632 // First call
11633 let state = typeof(this.el) === 'undefined';
11634 // LemonadeJS is already rendered
11635 if (state === true) {
11636 // Render
11637 if (options && options.applyOnly === true) {
11638 // Merge component
11639 handler.call(this);
11640 // Apply
11641 L.apply(this, self);
11642 } else {
11643 let root = this;
11644 if (options && options.shadowRoot === true) {
11645 this.attachShadow({ mode: 'open' });
11646 root = document.createElement('div');
11647 this.shadowRoot.appendChild(root);
11648 }
11649 // Give the browser time to calculate all width and heights
11650 L.render(handler, root, self);
11651 }
11652 }
11653
11654 queueMicrotask(() => {
11655 // Event
11656 if (typeof(self.onconnect) === 'function') {
11657 self.onconnect(self, state);
11658 }
11659 });
11660 }
11661
11662 disconnectedCallback() {
11663 if (typeof(this.ondisconnect) === 'function') {
11664 this.ondisconnect(this);
11665 }
11666 }
11667 }
11668
11669 if (! window.customElements.get(componentName)) {
11670 window.customElements.define(componentName, Component);
11671 }
11672 }
11673 }
11674
11675 L.h = function(type, props, ...children) {
11676 return { type, props: props || {}, children };
11677 }
11678
11679 L.Fragment = function(props) {
11680 return props.children;
11681 }
11682
11683 const wrongLevel = 'Hooks must be called at the top level of your component';
11684
11685 const setOnload = function(lemon, event) {
11686 lemon.load = event;
11687 }
11688
11689 const setOnchange = function(lemon, event) {
11690 lemon.change.push(event);
11691 }
11692
11693 const setTrack = function(lemon, prop) {
11694 if (! lemon.events[prop]) {
11695 lemon.events[prop] = [];
11696 }
11697 }
11698
11699 const setPath = function(lemon, initialValues, change) {
11700 // My value object
11701 let value = {};
11702 // Create a method to update the state
11703 const setValue = (newValue) => {
11704 if (typeof(lemon.path.initial) === 'undefined') {
11705 if (typeof (newValue) === 'object') {
11706 // If my has been declared
11707 let elements = lemon.path.elements;
11708 if (elements) {
11709 for (let i = 0; i < elements.length; i++) {
11710 let v = Path.call(newValue, elements[i].path)
11711 setAttribute(elements[i].element, 'value', v);
11712 // Also sync value to the data object (use '' for undefined to match form behavior)
11713 Path.call(lemon.path.value, elements[i].path, v !== undefined ? v : '');
11714 }
11715 }
11716 }
11717 } else {
11718 lemon.path.initial = newValue;
11719 }
11720 }
11721
11722 const getValue = () => {
11723 let ret = {};
11724 // If my has been declared
11725 let elements = lemon.path.elements;
11726 if (elements) {
11727 for (let i = 0; i < elements.length; i++) {
11728 let v = getAttribute(elements[i].element, 'value');
11729 Path.call(ret, elements[i].path, v);
11730 }
11731 }
11732 return ret;
11733 }
11734
11735 lemon.path = {
11736 setValue: setValue,
11737 value: value,
11738 change: change,
11739 initial: initialValues || {}
11740 };
11741
11742 return [value, setValue, getValue];
11743 }
11744
11745 const setState = function(lemon, value, callback) {
11746 // Create a state container
11747 const s = new state();
11748 // Create a method to update the state
11749 const setValue = (newValue) => {
11750 let oldValue = value;
11751 // Update original value
11752 value = typeof newValue === 'function' ? newValue(value) : newValue;
11753 // Values from the view
11754 runViewValues(lemon, s);
11755 // Call back
11756 callback?.(value, oldValue);
11757 }
11758 // Make the value attribute dynamic
11759 Object.defineProperty(s, 'value', {
11760 set: setValue,
11761 get: () => value
11762 });
11763
11764 return s;
11765 }
11766
11767 L.onload = function(event) {
11768 if (! R.currentLemon) {
11769 createError(wrongLevel);
11770 }
11771 return setOnload(R.currentLemon, event);
11772 }
11773
11774 L.onchange = function(event) {
11775 if (! R.currentLemon) {
11776 createError(wrongLevel);
11777 }
11778 return setOnchange(R.currentLemon, event);
11779 }
11780
11781 L.track = function(prop) {
11782 if (! R.currentLemon) {
11783 createError(wrongLevel);
11784 }
11785 return setTrack(R.currentLemon, prop);
11786 }
11787
11788 L.setPath = function(initialValues, change) {
11789 if (! R.currentLemon) {
11790 createError(wrongLevel);
11791 }
11792 return setPath(R.currentLemon, initialValues, change);
11793 }
11794
11795 /**
11796 * Run view values
11797 * @param lemon
11798 * @param s - refresh from state
11799 */
11800 const runViewValues = function(lemon, s) {
11801 let values = lemon.view(parseTemplate);
11802 if (values && values.length) {
11803 values.forEach((v, k) => {
11804 let current = lemon.values[k];
11805 // Compare if the previous value
11806 if (s && s === v || v !== current) {
11807 // Update current value
11808 lemon.values[k] = v;
11809 // Trigger state events
11810 if (typeof(lemon.events[k]) === 'function') {
11811 lemon.events[k]();
11812 }
11813 }
11814 });
11815 }
11816 }
11817
11818 const state = function() {}
11819
11820 state.prototype.toString = function() {
11821 return this.value.toString();
11822 }
11823
11824 state.prototype.valueOf = function() {
11825 return this.value;
11826 }
11827
11828 state.prototype[Symbol.toPrimitive] = function(hint) {
11829 if (hint === 'string') {
11830 return this.value.toString();
11831 }
11832 return this.value;
11833 }
11834
11835 // TODO: Proxy for Objects and Arrays
11836 L.state = function(value, callback) {
11837 if (! R.currentLemon) {
11838 createError(wrongLevel);
11839 }
11840
11841 return setState(R.currentLemon, value, callback);
11842 }
11843
11844 L.helpers = {
11845 path: extractFromPath,
11846 properties: {
11847 get: L.getProperties,
11848 set: L.setProperties,
11849 reset: L.resetProperties,
11850 }
11851 }
11852
11853 L.events = (function() {
11854 class CustomEvents extends Event {
11855 constructor(type, props, options) {
11856 super(type, {
11857 bubbles: true,
11858 composed: true,
11859 ...options,
11860 });
11861
11862 if (props) {
11863 for (const key in props) {
11864 // Avoid assigning if property already exists anywhere on `this`
11865 if (! (key in this)) {
11866 this[key] = props[key];
11867 }
11868 }
11869 }
11870 }
11871 }
11872
11873 const create = function(type, props, options) {
11874 return new CustomEvents(type, props, options);
11875 };
11876
11877 return {
11878 create: create,
11879 dispatch(element, event, options) {
11880 if (typeof event === 'string') {
11881 event = create(event, options);
11882 }
11883 element.dispatchEvent(event);
11884 }
11885 };
11886 })();
11887
11888 return L;
11889})));
11890
11891/***/ }),
11892
11893/***/ 195:
11894/***/ (function(module) {
11895
11896/**
11897 * (c) jSuites Javascript Plugins and Web Components (v4)
11898 *
11899 * Website: https://jsuites.net
11900 * Description: Create amazing web based applications.
11901 * Plugin: Organogram
11902 *
11903 * MIT License
11904 */
11905
11906;(function (global, factory) {
11907 true ? module.exports = factory() :
11908 0;
11909}(this, (function () {
11910
11911 return (function(str) {
11912 function int64(msint_32, lsint_32) {
11913 this.highOrder = msint_32;
11914 this.lowOrder = lsint_32;
11915 }
11916
11917 var H = [new int64(0x6a09e667, 0xf3bcc908), new int64(0xbb67ae85, 0x84caa73b),
11918 new int64(0x3c6ef372, 0xfe94f82b), new int64(0xa54ff53a, 0x5f1d36f1),
11919 new int64(0x510e527f, 0xade682d1), new int64(0x9b05688c, 0x2b3e6c1f),
11920 new int64(0x1f83d9ab, 0xfb41bd6b), new int64(0x5be0cd19, 0x137e2179)];
11921
11922 var K = [new int64(0x428a2f98, 0xd728ae22), new int64(0x71374491, 0x23ef65cd),
11923 new int64(0xb5c0fbcf, 0xec4d3b2f), new int64(0xe9b5dba5, 0x8189dbbc),
11924 new int64(0x3956c25b, 0xf348b538), new int64(0x59f111f1, 0xb605d019),
11925 new int64(0x923f82a4, 0xaf194f9b), new int64(0xab1c5ed5, 0xda6d8118),
11926 new int64(0xd807aa98, 0xa3030242), new int64(0x12835b01, 0x45706fbe),
11927 new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, 0xd5ffb4e2),
11928 new int64(0x72be5d74, 0xf27b896f), new int64(0x80deb1fe, 0x3b1696b1),
11929 new int64(0x9bdc06a7, 0x25c71235), new int64(0xc19bf174, 0xcf692694),
11930 new int64(0xe49b69c1, 0x9ef14ad2), new int64(0xefbe4786, 0x384f25e3),
11931 new int64(0x0fc19dc6, 0x8b8cd5b5), new int64(0x240ca1cc, 0x77ac9c65),
11932 new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
11933 new int64(0x5cb0a9dc, 0xbd41fbd4), new int64(0x76f988da, 0x831153b5),
11934 new int64(0x983e5152, 0xee66dfab), new int64(0xa831c66d, 0x2db43210),
11935 new int64(0xb00327c8, 0x98fb213f), new int64(0xbf597fc7, 0xbeef0ee4),
11936 new int64(0xc6e00bf3, 0x3da88fc2), new int64(0xd5a79147, 0x930aa725),
11937 new int64(0x06ca6351, 0xe003826f), new int64(0x14292967, 0x0a0e6e70),
11938 new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
11939 new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, 0x9d95b3df),
11940 new int64(0x650a7354, 0x8baf63de), new int64(0x766a0abb, 0x3c77b2a8),
11941 new int64(0x81c2c92e, 0x47edaee6), new int64(0x92722c85, 0x1482353b),
11942 new int64(0xa2bfe8a1, 0x4cf10364), new int64(0xa81a664b, 0xbc423001),
11943 new int64(0xc24b8b70, 0xd0f89791), new int64(0xc76c51a3, 0x0654be30),
11944 new int64(0xd192e819, 0xd6ef5218), new int64(0xd6990624, 0x5565a910),
11945 new int64(0xf40e3585, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
11946 new int64(0x19a4c116, 0xb8d2d0c8), new int64(0x1e376c08, 0x5141ab53),
11947 new int64(0x2748774c, 0xdf8eeb99), new int64(0x34b0bcb5, 0xe19b48a8),
11948 new int64(0x391c0cb3, 0xc5c95a63), new int64(0x4ed8aa4a, 0xe3418acb),
11949 new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, 0xd6b2b8a3),
11950 new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
11951 new int64(0x84c87814, 0xa1f0ab72), new int64(0x8cc70208, 0x1a6439ec),
11952 new int64(0x90befffa, 0x23631e28), new int64(0xa4506ceb, 0xde82bde9),
11953 new int64(0xbef9a3f7, 0xb2c67915), new int64(0xc67178f2, 0xe372532b),
11954 new int64(0xca273ece, 0xea26619c), new int64(0xd186b8c7, 0x21c0c207),
11955 new int64(0xeada7dd6, 0xcde0eb1e), new int64(0xf57d4f7f, 0xee6ed178),
11956 new int64(0x06f067aa, 0x72176fba), new int64(0x0a637dc5, 0xa2c898a6),
11957 new int64(0x113f9804, 0xbef90dae), new int64(0x1b710b35, 0x131c471b),
11958 new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
11959 new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, 0x9c100d4c),
11960 new int64(0x4cc5d4be, 0xcb3e42b6), new int64(0x597f299c, 0xfc657e2a),
11961 new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)];
11962
11963 var W = new Array(64);
11964 var a, b, c, d, e, f, g, h, i, j;
11965 var T1, T2;
11966 var charsize = 8;
11967
11968 function utf8_encode(str) {
11969 return unescape(encodeURIComponent(str));
11970 }
11971
11972 function str2binb(str) {
11973 var bin = [];
11974 var mask = (1 << charsize) - 1;
11975 var len = str.length * charsize;
11976
11977 for (var i = 0; i < len; i += charsize) {
11978 bin[i >> 5] |= (str.charCodeAt(i / charsize) & mask) << (32 - charsize - (i % 32));
11979 }
11980
11981 return bin;
11982 }
11983
11984 function binb2hex(binarray) {
11985 var hex_tab = "0123456789abcdef";
11986 var str = "";
11987 var length = binarray.length * 4;
11988 var srcByte;
11989
11990 for (var i = 0; i < length; i += 1) {
11991 srcByte = binarray[i >> 2] >> ((3 - (i % 4)) * 8);
11992 str += hex_tab.charAt((srcByte >> 4) & 0xF) + hex_tab.charAt(srcByte & 0xF);
11993 }
11994
11995 return str;
11996 }
11997
11998 function safe_add_2(x, y) {
11999 var lsw, msw, lowOrder, highOrder;
12000
12001 lsw = (x.lowOrder & 0xFFFF) + (y.lowOrder & 0xFFFF);
12002 msw = (x.lowOrder >>> 16) + (y.lowOrder >>> 16) + (lsw >>> 16);
12003 lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
12004
12005 lsw = (x.highOrder & 0xFFFF) + (y.highOrder & 0xFFFF) + (msw >>> 16);
12006 msw = (x.highOrder >>> 16) + (y.highOrder >>> 16) + (lsw >>> 16);
12007 highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
12008
12009 return new int64(highOrder, lowOrder);
12010 }
12011
12012 function safe_add_4(a, b, c, d) {
12013 var lsw, msw, lowOrder, highOrder;
12014
12015 lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF);
12016 msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (lsw >>> 16);
12017 lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
12018
12019 lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (msw >>> 16);
12020 msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (lsw >>> 16);
12021 highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
12022
12023 return new int64(highOrder, lowOrder);
12024 }
12025
12026 function safe_add_5(a, b, c, d, e) {
12027 var lsw, msw, lowOrder, highOrder;
12028
12029 lsw = (a.lowOrder & 0xFFFF) + (b.lowOrder & 0xFFFF) + (c.lowOrder & 0xFFFF) + (d.lowOrder & 0xFFFF) + (e.lowOrder & 0xFFFF);
12030 msw = (a.lowOrder >>> 16) + (b.lowOrder >>> 16) + (c.lowOrder >>> 16) + (d.lowOrder >>> 16) + (e.lowOrder >>> 16) + (lsw >>> 16);
12031 lowOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
12032
12033 lsw = (a.highOrder & 0xFFFF) + (b.highOrder & 0xFFFF) + (c.highOrder & 0xFFFF) + (d.highOrder & 0xFFFF) + (e.highOrder & 0xFFFF) + (msw >>> 16);
12034 msw = (a.highOrder >>> 16) + (b.highOrder >>> 16) + (c.highOrder >>> 16) + (d.highOrder >>> 16) + (e.highOrder >>> 16) + (lsw >>> 16);
12035 highOrder = ((msw & 0xFFFF) << 16) | (lsw & 0xFFFF);
12036
12037 return new int64(highOrder, lowOrder);
12038 }
12039
12040 function maj(x, y, z) {
12041 return new int64(
12042 (x.highOrder & y.highOrder) ^ (x.highOrder & z.highOrder) ^ (y.highOrder & z.highOrder),
12043 (x.lowOrder & y.lowOrder) ^ (x.lowOrder & z.lowOrder) ^ (y.lowOrder & z.lowOrder)
12044 );
12045 }
12046
12047 function ch(x, y, z) {
12048 return new int64(
12049 (x.highOrder & y.highOrder) ^ (~x.highOrder & z.highOrder),
12050 (x.lowOrder & y.lowOrder) ^ (~x.lowOrder & z.lowOrder)
12051 );
12052 }
12053
12054 function rotr(x, n) {
12055 if (n <= 32) {
12056 return new int64(
12057 (x.highOrder >>> n) | (x.lowOrder << (32 - n)),
12058 (x.lowOrder >>> n) | (x.highOrder << (32 - n))
12059 );
12060 } else {
12061 return new int64(
12062 (x.lowOrder >>> n) | (x.highOrder << (32 - n)),
12063 (x.highOrder >>> n) | (x.lowOrder << (32 - n))
12064 );
12065 }
12066 }
12067
12068 function sigma0(x) {
12069 var rotr28 = rotr(x, 28);
12070 var rotr34 = rotr(x, 34);
12071 var rotr39 = rotr(x, 39);
12072
12073 return new int64(
12074 rotr28.highOrder ^ rotr34.highOrder ^ rotr39.highOrder,
12075 rotr28.lowOrder ^ rotr34.lowOrder ^ rotr39.lowOrder
12076 );
12077 }
12078
12079 function sigma1(x) {
12080 var rotr14 = rotr(x, 14);
12081 var rotr18 = rotr(x, 18);
12082 var rotr41 = rotr(x, 41);
12083
12084 return new int64(
12085 rotr14.highOrder ^ rotr18.highOrder ^ rotr41.highOrder,
12086 rotr14.lowOrder ^ rotr18.lowOrder ^ rotr41.lowOrder
12087 );
12088 }
12089
12090 function gamma0(x) {
12091 var rotr1 = rotr(x, 1), rotr8 = rotr(x, 8), shr7 = shr(x, 7);
12092
12093 return new int64(
12094 rotr1.highOrder ^ rotr8.highOrder ^ shr7.highOrder,
12095 rotr1.lowOrder ^ rotr8.lowOrder ^ shr7.lowOrder
12096 );
12097 }
12098
12099 function gamma1(x) {
12100 var rotr19 = rotr(x, 19);
12101 var rotr61 = rotr(x, 61);
12102 var shr6 = shr(x, 6);
12103
12104 return new int64(
12105 rotr19.highOrder ^ rotr61.highOrder ^ shr6.highOrder,
12106 rotr19.lowOrder ^ rotr61.lowOrder ^ shr6.lowOrder
12107 );
12108 }
12109
12110 function shr(x, n) {
12111 if (n <= 32) {
12112 return new int64(
12113 x.highOrder >>> n,
12114 x.lowOrder >>> n | (x.highOrder << (32 - n))
12115 );
12116 } else {
12117 return new int64(
12118 0,
12119 x.highOrder << (32 - n)
12120 );
12121 }
12122 }
12123
12124 var str = utf8_encode(str);
12125 var strlen = str.length*charsize;
12126 str = str2binb(str);
12127
12128 str[strlen >> 5] |= 0x80 << (24 - strlen % 32);
12129 str[(((strlen + 128) >> 10) << 5) + 31] = strlen;
12130
12131 for (var i = 0; i < str.length; i += 32) {
12132 a = H[0];
12133 b = H[1];
12134 c = H[2];
12135 d = H[3];
12136 e = H[4];
12137 f = H[5];
12138 g = H[6];
12139 h = H[7];
12140
12141 for (var j = 0; j < 80; j++) {
12142 if (j < 16) {
12143 W[j] = new int64(str[j*2 + i], str[j*2 + i + 1]);
12144 } else {
12145 W[j] = safe_add_4(gamma1(W[j - 2]), W[j - 7], gamma0(W[j - 15]), W[j - 16]);
12146 }
12147
12148 T1 = safe_add_5(h, sigma1(e), ch(e, f, g), K[j], W[j]);
12149 T2 = safe_add_2(sigma0(a), maj(a, b, c));
12150 h = g;
12151 g = f;
12152 f = e;
12153 e = safe_add_2(d, T1);
12154 d = c;
12155 c = b;
12156 b = a;
12157 a = safe_add_2(T1, T2);
12158 }
12159
12160 H[0] = safe_add_2(a, H[0]);
12161 H[1] = safe_add_2(b, H[1]);
12162 H[2] = safe_add_2(c, H[2]);
12163 H[3] = safe_add_2(d, H[3]);
12164 H[4] = safe_add_2(e, H[4]);
12165 H[5] = safe_add_2(f, H[5]);
12166 H[6] = safe_add_2(g, H[6]);
12167 H[7] = safe_add_2(h, H[7]);
12168 }
12169
12170 var binarray = [];
12171 for (var i = 0; i < H.length; i++) {
12172 binarray.push(H[i].highOrder);
12173 binarray.push(H[i].lowOrder);
12174 }
12175
12176 return binb2hex(binarray);
12177 });
12178
12179})));
12180
12181
12182/***/ })
12183
12184/******/ });
12185/************************************************************************/
12186/******/ // The module cache
12187/******/ var __webpack_module_cache__ = {};
12188/******/
12189/******/ // The require function
12190/******/ function __webpack_require__(moduleId) {
12191/******/ // Check if module is in cache
12192/******/ var cachedModule = __webpack_module_cache__[moduleId];
12193/******/ if (cachedModule !== undefined) {
12194/******/ return cachedModule.exports;
12195/******/ }
12196/******/ // Create a new module (and put it into the cache)
12197/******/ var module = __webpack_module_cache__[moduleId] = {
12198/******/ // no module.id needed
12199/******/ // no module.loaded needed
12200/******/ exports: {}
12201/******/ };
12202/******/
12203/******/ // Execute the module function
12204/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
12205/******/
12206/******/ // Return the exports of the module
12207/******/ return module.exports;
12208/******/ }
12209/******/
12210/************************************************************************/
12211/******/ /* webpack/runtime/compat get default export */
12212/******/ !function() {
12213/******/ // getDefaultExport function for compatibility with non-harmony modules
12214/******/ __webpack_require__.n = function(module) {
12215/******/ var getter = module && module.__esModule ?
12216/******/ function() { return module['default']; } :
12217/******/ function() { return module; };
12218/******/ __webpack_require__.d(getter, { a: getter });
12219/******/ return getter;
12220/******/ };
12221/******/ }();
12222/******/
12223/******/ /* webpack/runtime/define property getters */
12224/******/ !function() {
12225/******/ // define getter functions for harmony exports
12226/******/ __webpack_require__.d = function(exports, definition) {
12227/******/ for(var key in definition) {
12228/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
12229/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
12230/******/ }
12231/******/ }
12232/******/ };
12233/******/ }();
12234/******/
12235/******/ /* webpack/runtime/hasOwnProperty shorthand */
12236/******/ !function() {
12237/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
12238/******/ }();
12239/******/
12240/************************************************************************/
12241var __webpack_exports__ = {};
12242// This entry need to be wrapped in an IIFE because it need to be in strict mode.
12243!function() {
12244"use strict";
12245
12246// EXPORTS
12247__webpack_require__.d(__webpack_exports__, {
12248 "default": function() { return /* binding */ jsuites; }
12249});
12250
12251;// CONCATENATED MODULE: ./src/utils/dictionary.js
12252// Update dictionary
12253const setDictionary = function(d) {
12254 if (! document.dictionary) {
12255 document.dictionary = {}
12256 }
12257 // Replace the key into the dictionary and append the new ones
12258 let k = Object.keys(d);
12259 for (let i = 0; i < k.length; i++) {
12260 document.dictionary[k[i]] = d[k[i]];
12261 }
12262}
12263
12264// Translate
12265const translate = function(t) {
12266 if (typeof(document) !== "undefined" && document.dictionary) {
12267 return document.dictionary[t] || t;
12268 } else {
12269 return t;
12270 }
12271}
12272
12273
12274/* harmony default export */ var dictionary = ({ setDictionary, translate });
12275;// CONCATENATED MODULE: ./src/utils/tracking.js
12276 const Tracking = function(component, state) {
12277 if (state === true) {
12278 window['jSuitesStateControl'] = window['jSuitesStateControl'].filter(function(v) {
12279 return v !== null;
12280 });
12281
12282 // Start after all events
12283 setTimeout(function() {
12284 window['jSuitesStateControl'].push(component);
12285 }, 0);
12286
12287 } else {
12288 var index = window['jSuitesStateControl'].indexOf(component);
12289 if (index >= 0) {
12290 window['jSuitesStateControl'].splice(index, 1);
12291 }
12292 }
12293}
12294
12295/* harmony default export */ var tracking = (Tracking);
12296;// CONCATENATED MODULE: ./src/utils/helpers.js
12297const Helpers = {};
12298
12299// Two digits
12300Helpers.two = function(value) {
12301 value = '' + value;
12302 if (value.length == 1) {
12303 value = '0' + value;
12304 }
12305 return value;
12306}
12307
12308Helpers.focus = function(el) {
12309 if (el.textContent.length) {
12310 // Handle contenteditable elements
12311 const range = document.createRange();
12312 const sel = window.getSelection();
12313
12314 let node = el;
12315 // Go as deep as possible to the last text node
12316 while (node.lastChild) node = node.lastChild;
12317 // Ensure it's a text node
12318 if (node.nodeType === Node.TEXT_NODE) {
12319 range.setStart(node, node.length);
12320 } else {
12321 range.setStart(node, node.childNodes.length);
12322 }
12323 range.collapse(true);
12324 sel.removeAllRanges();
12325 sel.addRange(range);
12326
12327 el.scrollLeft = el.scrollWidth;
12328 }
12329}
12330
12331Helpers.isNumeric = (function (num) {
12332 if (typeof(num) === 'string') {
12333 num = num.trim();
12334 }
12335 return !isNaN(num) && num !== null && num !== '';
12336});
12337
12338Helpers.guid = function() {
12339 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
12340 let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
12341 return v.toString(16);
12342 });
12343}
12344
12345Helpers.getNode = function() {
12346 let node = document.getSelection().anchorNode;
12347 if (node) {
12348 return (node.nodeType == 3 ? node.parentNode : node);
12349 } else {
12350 return null;
12351 }
12352}
12353/**
12354 * Generate hash from a string
12355 */
12356Helpers.hash = function(str) {
12357 let hash = 0, i, chr;
12358
12359 if (str.length === 0) {
12360 return hash;
12361 } else {
12362 for (i = 0; i < str.length; i++) {
12363 chr = str.charCodeAt(i);
12364 if (chr > 32) {
12365 hash = ((hash << 5) - hash) + chr;
12366 hash |= 0;
12367 }
12368 }
12369 }
12370 return hash;
12371}
12372
12373/**
12374 * Generate a random color
12375 */
12376Helpers.randomColor = function(h) {
12377 let lum = -0.25;
12378 let hex = String('#' + Math.random().toString(16).slice(2, 8).toUpperCase()).replace(/[^0-9a-f]/gi, '');
12379 if (hex.length < 6) {
12380 hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
12381 }
12382 let rgb = [], c;
12383 for (let i = 0; i < 3; i++) {
12384 c = parseInt(hex.substr(i * 2, 2), 16);
12385 c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
12386 rgb.push(("00" + c).substr(c.length));
12387 }
12388
12389 // Return hex
12390 if (h === true) {
12391 return '#' + Helpers.two(rgb[0].toString(16)) + Helpers.two(rgb[1].toString(16)) + Helpers.two(rgb[2].toString(16));
12392 }
12393
12394 return rgb;
12395}
12396
12397Helpers.getWindowWidth = function() {
12398 let w = window,
12399 d = document,
12400 e = d.documentElement,
12401 g = d.getElementsByTagName('body')[0],
12402 x = w.innerWidth || e.clientWidth || g.clientWidth;
12403 return x;
12404}
12405
12406Helpers.getWindowHeight = function() {
12407 let w = window,
12408 d = document,
12409 e = d.documentElement,
12410 g = d.getElementsByTagName('body')[0],
12411 y = w.innerHeight|| e.clientHeight|| g.clientHeight;
12412 return y;
12413}
12414
12415Helpers.getPosition = function(e) {
12416 let x;
12417 let y;
12418 if (e.changedTouches && e.changedTouches[0]) {
12419 x = e.changedTouches[0].pageX;
12420 y = e.changedTouches[0].pageY;
12421 } else {
12422 x = (window.Event) ? e.pageX : e.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
12423 y = (window.Event) ? e.pageY : e.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
12424 }
12425
12426 return [ x, y ];
12427}
12428
12429Helpers.click = function(el) {
12430 if (el.click) {
12431 el.click();
12432 } else {
12433 let evt = new MouseEvent('click', {
12434 bubbles: true,
12435 cancelable: true,
12436 view: window
12437 });
12438 el.dispatchEvent(evt);
12439 }
12440}
12441
12442Helpers.findElement = function(element, condition) {
12443 let foundElement = false;
12444
12445 function path (element) {
12446 if (element && ! foundElement) {
12447 if (typeof(condition) == 'function') {
12448 foundElement = condition(element)
12449 } else if (typeof(condition) == 'string') {
12450 if (element.classList && element.classList.contains(condition)) {
12451 foundElement = element;
12452 }
12453 }
12454 }
12455
12456 if (element.parentNode && ! foundElement) {
12457 path(element.parentNode);
12458 }
12459 }
12460
12461 path(element);
12462
12463 return foundElement;
12464}
12465
12466/* harmony default export */ var helpers = (Helpers);
12467;// CONCATENATED MODULE: ./src/utils/path.js
12468const isValidPathObj = function(o) {
12469 return o !== null && (typeof o === 'object' || typeof o === 'function');
12470}
12471
12472function Path(pathString, value, remove) {
12473 // Ensure the path is a valid, non-empty string
12474 if (typeof pathString !== 'string' || pathString.length === 0) {
12475 return undefined;
12476 }
12477
12478 // Split the path into individual keys and filter out empty keys
12479 const keys = pathString.split('.');
12480 if (keys.length === 0) {
12481 return undefined;
12482 }
12483
12484 // Start with the root object
12485 let currentObject = this;
12486
12487 // Read mode: retrieve a value
12488 if (typeof value === 'undefined' && typeof remove === 'undefined') {
12489 // Traverse all keys
12490 for (let i = 0; i < keys.length; i++) {
12491 const key = keys[i];
12492 // Check if the current object is valid and has the key
12493 if (currentObject != null && isValidPathObj(currentObject) && key in currentObject) {
12494 currentObject = currentObject[key];
12495 } else {
12496 // Return undefined if the path is invalid or currentObject is null/undefined
12497 return undefined;
12498 }
12499 }
12500 // Return the final value
12501 return currentObject;
12502 }
12503
12504 // Write mode: set or delete a value
12505 // Traverse all keys except the last one
12506 for (let i = 0; i < keys.length - 1; i++) {
12507 const key = keys[i];
12508
12509 // Check if the current object is invalid (null/undefined or non-object)
12510 if (currentObject == null || ! isValidPathObj(currentObject)) {
12511 console.warn(`Cannot set value: path '${pathString}' blocked by invalid object at '${key}'`);
12512 return false;
12513 }
12514
12515 // If the key exists but is null/undefined or a non-object, replace it with an empty object
12516 if (
12517 key in currentObject &&
12518 (currentObject[key] == null || ! isValidPathObj(currentObject[key]))
12519 ) {
12520 currentObject[key] = {};
12521 } else if (!(key in currentObject)) {
12522 // If the key doesn't exist, create an empty object
12523 currentObject[key] = {};
12524 }
12525
12526 // Move to the next level
12527 currentObject = currentObject[key];
12528 }
12529
12530 // Handle the final key
12531 const finalKey = keys[keys.length - 1];
12532
12533 // Check if the current object is valid for setting/deleting
12534 if (currentObject == null || ! isValidPathObj(currentObject)) {
12535 return false;
12536 }
12537
12538 // Delete the property if remove is true
12539 if (remove === true) {
12540 if (finalKey in currentObject) {
12541 delete currentObject[finalKey];
12542 return true;
12543 }
12544 return false; // Nothing to delete
12545 }
12546
12547 // Set the value
12548 currentObject[finalKey] = value;
12549 return true;
12550}
12551;// CONCATENATED MODULE: ./src/utils/sorting.js
12552function Sorting(el, options) {
12553 var obj = {};
12554 obj.options = {};
12555
12556 var defaults = {
12557 pointer: null,
12558 direction: null,
12559 ondragstart: null,
12560 ondragend: null,
12561 ondrop: null,
12562 }
12563
12564 var dragElement = null;
12565
12566 // Loop through the initial configuration
12567 for (var property in defaults) {
12568 if (options && options.hasOwnProperty(property)) {
12569 obj.options[property] = options[property];
12570 } else {
12571 obj.options[property] = defaults[property];
12572 }
12573 }
12574
12575 el.classList.add('jsorting');
12576
12577 el.addEventListener('dragstart', function(e) {
12578 let target = e.target;
12579 if (target.nodeType === 3) {
12580 if (target.parentNode.getAttribute('draggable') === 'true') {
12581 target = target.parentNode;
12582 } else {
12583 e.preventDefault();
12584 e.stopPropagation();
12585 return;
12586 }
12587 }
12588
12589 if (target.getAttribute('draggable') === 'true') {
12590 let position = Array.prototype.indexOf.call(target.parentNode.children, target);
12591 dragElement = {
12592 element: target,
12593 o: position,
12594 d: position
12595 }
12596 target.style.opacity = '0.25';
12597
12598 if (typeof (obj.options.ondragstart) == 'function') {
12599 obj.options.ondragstart(el, target, e);
12600 }
12601
12602 e.dataTransfer.setDragImage(target,0,0);
12603 }
12604 });
12605
12606 el.addEventListener('dragover', function(e) {
12607 e.preventDefault();
12608
12609 if (dragElement) {
12610 if (getElement(e.target)) {
12611 if (e.target.getAttribute('draggable') == 'true' && dragElement.element != e.target) {
12612 if (!obj.options.direction) {
12613 var condition = e.target.clientHeight / 2 > e.offsetY;
12614 } else {
12615 var condition = e.target.clientWidth / 2 > e.offsetX;
12616 }
12617
12618 if (condition) {
12619 e.target.parentNode.insertBefore(dragElement.element, e.target);
12620 } else {
12621 e.target.parentNode.insertBefore(dragElement.element, e.target.nextSibling);
12622 }
12623
12624 dragElement.d = Array.prototype.indexOf.call(e.target.parentNode.children, dragElement.element);
12625 }
12626 }
12627 }
12628 });
12629
12630 el.addEventListener('dragleave', function(e) {
12631 e.preventDefault();
12632 });
12633
12634 el.addEventListener('dragend', function(e) {
12635 e.preventDefault();
12636
12637 if (dragElement) {
12638 if (typeof(obj.options.ondragend) == 'function') {
12639 obj.options.ondragend(el, dragElement.element, e);
12640 }
12641
12642 // Cancelled put element to the original position
12643 if (dragElement.o < dragElement.d) {
12644 e.target.parentNode.insertBefore(dragElement.element, e.target.parentNode.children[dragElement.o]);
12645 } else {
12646 e.target.parentNode.insertBefore(dragElement.element, e.target.parentNode.children[dragElement.o].nextSibling);
12647 }
12648
12649 dragElement.element.style.opacity = '';
12650 dragElement = null;
12651 }
12652 });
12653
12654 el.addEventListener('drop', function(e) {
12655 e.preventDefault();
12656
12657 if (dragElement) {
12658 if (dragElement.o !== dragElement.d) {
12659 if (typeof (obj.options.ondrop) == 'function') {
12660 obj.options.ondrop(el, dragElement.o, dragElement.d, dragElement.element, e.target, e);
12661 }
12662 }
12663
12664 dragElement.element.style.opacity = '';
12665 dragElement = null;
12666 }
12667 });
12668
12669 var getElement = function(element) {
12670 var sorting = false;
12671
12672 function path (element) {
12673 if (element.className) {
12674 if (element.classList.contains('jsorting')) {
12675 sorting = true;
12676 }
12677 }
12678
12679 if (! sorting) {
12680 path(element.parentNode);
12681 }
12682 }
12683
12684 path(element);
12685
12686 return sorting;
12687 }
12688
12689 for (var i = 0; i < el.children.length; i++) {
12690 if (! el.children[i].hasAttribute('draggable')) {
12691 el.children[i].setAttribute('draggable', 'true');
12692 }
12693 }
12694
12695 el.val = function() {
12696 var id = null;
12697 var data = [];
12698 for (var i = 0; i < el.children.length; i++) {
12699 if (id = el.children[i].getAttribute('data-id')) {
12700 data.push(id);
12701 }
12702 }
12703 return data;
12704 }
12705
12706 return el;
12707}
12708;// CONCATENATED MODULE: ./src/utils/lazyloading.js
12709function LazyLoading(el, options) {
12710 var obj = {}
12711
12712 // Mandatory options
12713 if (! options.loadUp || typeof(options.loadUp) != 'function') {
12714 options.loadUp = function() {
12715 return false;
12716 }
12717 }
12718 if (! options.loadDown || typeof(options.loadDown) != 'function') {
12719 options.loadDown = function() {
12720 return false;
12721 }
12722 }
12723 // Timer ms
12724 if (! options.timer) {
12725 options.timer = 100;
12726 }
12727
12728 // Timer
12729 var timeControlLoading = null;
12730
12731 // Controls
12732 var scrollControls = function(e) {
12733 if (timeControlLoading == null) {
12734 var event = false;
12735 var scrollTop = el.scrollTop;
12736 if (el.scrollTop + (el.clientHeight * 2) >= el.scrollHeight) {
12737 if (options.loadDown()) {
12738 if (scrollTop == el.scrollTop) {
12739 el.scrollTop = el.scrollTop - (el.clientHeight);
12740 }
12741 event = true;
12742 }
12743 } else if (el.scrollTop <= el.clientHeight) {
12744 if (options.loadUp()) {
12745 if (scrollTop == el.scrollTop) {
12746 el.scrollTop = el.scrollTop + (el.clientHeight);
12747 }
12748 event = true;
12749 }
12750 }
12751
12752 timeControlLoading = setTimeout(function() {
12753 timeControlLoading = null;
12754 }, options.timer);
12755
12756 if (event) {
12757 if (typeof(options.onupdate) == 'function') {
12758 options.onupdate();
12759 }
12760 }
12761 }
12762 }
12763
12764 // Onscroll
12765 el.onscroll = function(e) {
12766 scrollControls(e);
12767 }
12768
12769 el.onwheel = function(e) {
12770 scrollControls(e);
12771 }
12772
12773 return obj;
12774}
12775;// CONCATENATED MODULE: ./src/plugins/ajax.js
12776function Ajax() {
12777 var Component = (function(options, complete) {
12778 if (Array.isArray(options)) {
12779 // Create multiple request controller
12780 var multiple = {
12781 instance: [],
12782 complete: complete,
12783 }
12784
12785 if (options.length > 0) {
12786 for (var i = 0; i < options.length; i++) {
12787 options[i].multiple = multiple;
12788 multiple.instance.push(Component(options[i]));
12789 }
12790 }
12791
12792 return multiple;
12793 }
12794
12795 if (! options.data) {
12796 options.data = {};
12797 }
12798
12799 if (options.type) {
12800 options.method = options.type;
12801 }
12802
12803 // Default method
12804 if (! options.method) {
12805 options.method = 'GET';
12806 }
12807
12808 // Default type
12809 if (! options.dataType) {
12810 options.dataType = 'json';
12811 }
12812
12813 if (options.data) {
12814 // Parse object to variables format
12815 var parseData = function (value, key) {
12816 var vars = [];
12817 if (value) {
12818 var keys = Object.keys(value);
12819 if (keys.length) {
12820 for (var i = 0; i < keys.length; i++) {
12821 if (key) {
12822 var k = key + '[' + keys[i] + ']';
12823 } else {
12824 var k = keys[i];
12825 }
12826
12827 if (value[k] instanceof FileList) {
12828 vars[k] = value[keys[i]];
12829 } else if (value[keys[i]] === null || value[keys[i]] === undefined) {
12830 vars[k] = '';
12831 } else if (typeof(value[keys[i]]) == 'object') {
12832 var r = parseData(value[keys[i]], k);
12833 var o = Object.keys(r);
12834 for (var j = 0; j < o.length; j++) {
12835 vars[o[j]] = r[o[j]];
12836 }
12837 } else {
12838 vars[k] = value[keys[i]];
12839 }
12840 }
12841 }
12842 }
12843
12844 return vars;
12845 }
12846
12847 var d = parseData(options.data);
12848 var k = Object.keys(d);
12849
12850 // Data form
12851 if (options.method == 'GET') {
12852 if (k.length) {
12853 var data = [];
12854 for (var i = 0; i < k.length; i++) {
12855 data.push(k[i] + '=' + encodeURIComponent(d[k[i]]));
12856 }
12857
12858 if (options.url.indexOf('?') < 0) {
12859 options.url += '?';
12860 }
12861 options.url += data.join('&');
12862 }
12863 } else {
12864 var data = new FormData();
12865 for (var i = 0; i < k.length; i++) {
12866 if (d[k[i]] instanceof FileList) {
12867 if (d[k[i]].length) {
12868 for (var j = 0; j < d[k[i]].length; j++) {
12869 data.append(k[i], d[k[i]][j], d[k[i]][j].name);
12870 }
12871 }
12872 } else {
12873 data.append(k[i], d[k[i]]);
12874 }
12875 }
12876 }
12877 }
12878
12879 var httpRequest = new XMLHttpRequest();
12880 httpRequest.open(options.method, options.url, true);
12881
12882 if (options.requestedWith) {
12883 httpRequest.setRequestHeader('X-Requested-With', options.requestedWith);
12884 } else {
12885 if (options.requestedWith !== false) {
12886 httpRequest.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
12887 }
12888 }
12889
12890 // Content type
12891 if (options.contentType) {
12892 httpRequest.setRequestHeader('Content-Type', options.contentType);
12893 }
12894
12895 // Headers
12896 if (options.method === 'POST') {
12897 httpRequest.setRequestHeader('Accept', 'application/json');
12898 } else {
12899 if (options.dataType === 'blob') {
12900 httpRequest.responseType = "blob";
12901 } else {
12902 if (! options.contentType) {
12903 if (options.dataType === 'json') {
12904 httpRequest.setRequestHeader('Content-Type', 'text/json');
12905 } else if (options.dataType === 'html') {
12906 httpRequest.setRequestHeader('Content-Type', 'text/html');
12907 }
12908 }
12909 }
12910 }
12911
12912 // No cache
12913 if (options.cache !== true) {
12914 httpRequest.setRequestHeader('pragma', 'no-cache');
12915 httpRequest.setRequestHeader('cache-control', 'no-cache');
12916 }
12917
12918 // Authentication
12919 if (options.withCredentials === true) {
12920 httpRequest.withCredentials = true
12921 }
12922
12923 // Before send
12924 if (typeof(options.beforeSend) == 'function') {
12925 options.beforeSend(httpRequest);
12926 }
12927
12928 // Before send
12929 if (typeof(Component.beforeSend) == 'function') {
12930 Component.beforeSend(httpRequest);
12931 }
12932
12933 if (document.ajax && typeof(document.ajax.beforeSend) == 'function') {
12934 document.ajax.beforeSend(httpRequest);
12935 }
12936
12937 httpRequest.onerror = function() {
12938 if (options.error && typeof(options.error) == 'function') {
12939 options.error({
12940 message: 'Network error: Unable to reach the server.',
12941 status: 0
12942 });
12943 }
12944 }
12945
12946 httpRequest.ontimeout = function() {
12947 if (options.error && typeof(options.error) == 'function') {
12948 options.error({
12949 message: 'Request timed out after ' + httpRequest.timeout + 'ms.',
12950 status: 0
12951 });
12952 }
12953 }
12954
12955 httpRequest.onload = function() {
12956 if (httpRequest.status >= 200 && httpRequest.status < 300) {
12957 if (options.dataType === 'json') {
12958 try {
12959 var result = JSON.parse(httpRequest.responseText);
12960
12961 if (options.success && typeof(options.success) == 'function') {
12962 options.success(result);
12963 }
12964 } catch(err) {
12965 if (options.error && typeof(options.error) == 'function') {
12966 options.error(err, result);
12967 }
12968 }
12969 } else {
12970 if (options.dataType === 'blob') {
12971 var result = httpRequest.response;
12972 } else {
12973 var result = httpRequest.responseText;
12974 }
12975
12976 if (options.success && typeof(options.success) == 'function') {
12977 options.success(result);
12978 }
12979 }
12980 } else {
12981 if (options.error && typeof(options.error) == 'function') {
12982 options.error(httpRequest.responseText, httpRequest.status);
12983 }
12984 }
12985
12986 // Global queue
12987 if (Component.queue && Component.queue.length > 0) {
12988 Component.send(Component.queue.shift());
12989 }
12990
12991 // Global complete method
12992 if (Component.requests && Component.requests.length) {
12993 // Get index of this request in the container
12994 var index = Component.requests.indexOf(httpRequest);
12995 // Remove from the ajax requests container
12996 Component.requests.splice(index, 1);
12997 // Deprecated: Last one?
12998 if (! Component.requests.length) {
12999 // Object event
13000 if (options.complete && typeof(options.complete) == 'function') {
13001 options.complete(result);
13002 }
13003 }
13004 // Group requests
13005 if (options.group) {
13006 if (Component.oncomplete && typeof(Component.oncomplete[options.group]) == 'function') {
13007 if (! Component.pending(options.group)) {
13008 Component.oncomplete[options.group]();
13009 Component.oncomplete[options.group] = null;
13010 }
13011 }
13012 }
13013 // Multiple requests controller
13014 if (options.multiple && options.multiple.instance) {
13015 // Get index of this request in the container
13016 var index = options.multiple.instance.indexOf(httpRequest);
13017 // Remove from the ajax requests container
13018 options.multiple.instance.splice(index, 1);
13019 // If this is the last one call method complete
13020 if (! options.multiple.instance.length) {
13021 if (options.multiple.complete && typeof(options.multiple.complete) == 'function') {
13022 options.multiple.complete(result);
13023 }
13024 }
13025 }
13026 }
13027 }
13028
13029 // Keep the options
13030 httpRequest.options = options;
13031 // Data
13032 httpRequest.data = data;
13033
13034 // Queue
13035 if (options.queue === true && Component.requests.length > 0) {
13036 Component.queue.push(httpRequest);
13037 } else {
13038 Component.send(httpRequest)
13039 }
13040
13041 return httpRequest;
13042 });
13043
13044 Component.send = function(httpRequest) {
13045 if (httpRequest.data) {
13046 if (Array.isArray(httpRequest.data)) {
13047 httpRequest.send(httpRequest.data.join('&'));
13048 } else {
13049 httpRequest.send(httpRequest.data);
13050 }
13051 } else {
13052 httpRequest.send();
13053 }
13054
13055 Component.requests.push(httpRequest);
13056 }
13057
13058 Component.exists = function(url, __callback) {
13059 var http = new XMLHttpRequest();
13060 http.open('HEAD', url, false);
13061 http.send();
13062 if (http.status) {
13063 __callback(http.status);
13064 }
13065 }
13066
13067 Component.pending = function(group) {
13068 var n = 0;
13069 var o = Component.requests;
13070 if (o && o.length) {
13071 for (var i = 0; i < o.length; i++) {
13072 if (! group || group == o[i].options.group) {
13073 n++
13074 }
13075 }
13076 }
13077 return n;
13078 }
13079
13080 Component.oncomplete = {};
13081 Component.requests = [];
13082 Component.queue = [];
13083
13084 return Component
13085}
13086
13087/* harmony default export */ var ajax = (Ajax());
13088;// CONCATENATED MODULE: ./src/plugins/animation.js
13089function Animation() {
13090 const Component = {
13091 loading: {}
13092 }
13093
13094 Component.loading.show = function(timeout) {
13095 if (! Component.loading.element) {
13096 Component.loading.element = document.createElement('div');
13097 Component.loading.element.className = 'jloading';
13098 }
13099 document.body.appendChild(Component.loading.element);
13100
13101 // Max timeout in seconds
13102 if (timeout > 0) {
13103 setTimeout(function() {
13104 Component.loading.hide();
13105 }, timeout * 1000)
13106 }
13107 }
13108
13109 Component.loading.hide = function() {
13110 if (Component.loading.element && Component.loading.element.parentNode) {
13111 document.body.removeChild(Component.loading.element);
13112 }
13113 }
13114
13115 Component.slideLeft = function (element, direction, done) {
13116 if (direction == true) {
13117 element.classList.add('jslide-left-in');
13118 setTimeout(function () {
13119 element.classList.remove('jslide-left-in');
13120 if (typeof (done) == 'function') {
13121 done();
13122 }
13123 }, 400);
13124 } else {
13125 element.classList.add('jslide-left-out');
13126 setTimeout(function () {
13127 element.classList.remove('jslide-left-out');
13128 if (typeof (done) == 'function') {
13129 done();
13130 }
13131 }, 400);
13132 }
13133 }
13134
13135 Component.slideRight = function (element, direction, done) {
13136 if (direction === true) {
13137 element.classList.add('jslide-right-in');
13138 setTimeout(function () {
13139 element.classList.remove('jslide-right-in');
13140 if (typeof (done) == 'function') {
13141 done();
13142 }
13143 }, 400);
13144 } else {
13145 element.classList.add('jslide-right-out');
13146 setTimeout(function () {
13147 element.classList.remove('jslide-right-out');
13148 if (typeof (done) == 'function') {
13149 done();
13150 }
13151 }, 400);
13152 }
13153 }
13154
13155 Component.slideTop = function (element, direction, done) {
13156 if (direction === true) {
13157 element.classList.add('jslide-top-in');
13158 setTimeout(function () {
13159 element.classList.remove('jslide-top-in');
13160 if (typeof (done) == 'function') {
13161 done();
13162 }
13163 }, 400);
13164 } else {
13165 element.classList.add('jslide-top-out');
13166 setTimeout(function () {
13167 element.classList.remove('jslide-top-out');
13168 if (typeof (done) == 'function') {
13169 done();
13170 }
13171 }, 400);
13172 }
13173 }
13174
13175 Component.slideBottom = function (element, direction, done) {
13176 if (direction === true) {
13177 element.classList.add('jslide-bottom-in');
13178 setTimeout(function () {
13179 element.classList.remove('jslide-bottom-in');
13180 if (typeof (done) == 'function') {
13181 done();
13182 }
13183 }, 400);
13184 } else {
13185 element.classList.add('jslide-bottom-out');
13186 setTimeout(function () {
13187 element.classList.remove('jslide-bottom-out');
13188 if (typeof (done) == 'function') {
13189 done();
13190 }
13191 }, 100);
13192 }
13193 }
13194
13195 Component.fadeIn = function (element, done) {
13196 element.style.display = '';
13197 element.classList.add('jfade-in');
13198 setTimeout(function () {
13199 element.classList.remove('jfade-in');
13200 if (typeof (done) == 'function') {
13201 done();
13202 }
13203 }, 2000);
13204 }
13205
13206 Component.fadeOut = function (element, done) {
13207 element.classList.add('jfade-out');
13208 setTimeout(function () {
13209 element.style.display = 'none';
13210 element.classList.remove('jfade-out');
13211 if (typeof (done) == 'function') {
13212 done();
13213 }
13214 }, 1000);
13215 }
13216
13217 return Component;
13218}
13219
13220/* harmony default export */ var animation = (Animation());
13221// EXTERNAL MODULE: ./node_modules/@jsuites/utils/dist/index.js
13222var dist = __webpack_require__(791);
13223var dist_default = /*#__PURE__*/__webpack_require__.n(dist);
13224;// CONCATENATED MODULE: ./src/plugins/calendar.js
13225
13226
13227
13228
13229
13230
13231const Mask = (dist_default()).Mask;
13232const HelpersDate = (dist_default()).Helpers;
13233
13234function Calendar() {
13235 var Component = (function (el, options) {
13236 // Already created, update options
13237 if (el.calendar) {
13238 return el.calendar.setOptions(options, true);
13239 }
13240
13241 // New instance
13242 var obj = {type: 'calendar'};
13243 obj.options = {};
13244
13245 // Date
13246 obj.date = null;
13247
13248 /**
13249 * Update options
13250 */
13251 obj.setOptions = function (options, reset) {
13252 // Default configuration
13253 var defaults = {
13254 // Render type: [ default | year-month-picker ]
13255 type: 'default',
13256 // Restrictions
13257 validRange: null,
13258 // Starting weekday - 0 for sunday, 6 for saturday
13259 startingDay: null,
13260 // Date format
13261 format: 'DD/MM/YYYY',
13262 // Allow keyboard date entry
13263 readonly: true,
13264 // Today is default
13265 today: false,
13266 // Show timepicker
13267 time: false,
13268 // Show the reset button
13269 resetButton: true,
13270 // Placeholder
13271 placeholder: '',
13272 // Translations can be done here
13273 months: HelpersDate.monthsShort,
13274 monthsFull: HelpersDate.months,
13275 weekdays: HelpersDate.weekdays,
13276 textDone: dictionary.translate('Done'),
13277 textReset: dictionary.translate('Reset'),
13278 textUpdate: dictionary.translate('Update'),
13279 // Value
13280 value: null,
13281 // Fullscreen (this is automatic set for screensize < 800)
13282 fullscreen: false,
13283 // Create the calendar closed as default
13284 opened: false,
13285 // Events
13286 onopen: null,
13287 onclose: null,
13288 onchange: null,
13289 onupdate: null,
13290 // Internal mode controller
13291 mode: null,
13292 position: null,
13293 // Data type
13294 dataType: null,
13295 // Controls
13296 controls: true,
13297 // Auto select
13298 autoSelect: true,
13299 }
13300
13301 // Loop through our object
13302 for (var property in defaults) {
13303 if (options && options.hasOwnProperty(property)) {
13304 obj.options[property] = options[property];
13305 } else {
13306 if (typeof (obj.options[property]) == 'undefined' || reset === true) {
13307 obj.options[property] = defaults[property];
13308 }
13309 }
13310 }
13311
13312 // Register custom months and weekdays with the dictionary for translation
13313 if (obj.options.monthsFull && obj.options.monthsFull !== defaults.monthsFull) {
13314 const englishMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
13315 const translations = {};
13316 for (let i = 0; i < 12; i++) {
13317 if (obj.options.monthsFull[i]) {
13318 translations[englishMonths[i]] = obj.options.monthsFull[i];
13319 }
13320 }
13321 dictionary.setDictionary(translations);
13322 }
13323
13324 if (obj.options.weekdays && obj.options.weekdays !== defaults.weekdays) {
13325 const englishWeekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
13326 const translations = {};
13327 for (let i = 0; i < 7; i++) {
13328 if (obj.options.weekdays[i]) {
13329 translations[englishWeekdays[i]] = obj.options.weekdays[i];
13330 }
13331 }
13332 dictionary.setDictionary(translations);
13333 }
13334
13335 // Reset button
13336 if (obj.options.resetButton == false) {
13337 calendarReset.style.display = 'none';
13338 } else {
13339 calendarReset.style.display = '';
13340 }
13341
13342 // Readonly
13343 if (obj.options.readonly) {
13344 el.setAttribute('readonly', 'readonly');
13345 } else {
13346 el.removeAttribute('readonly');
13347 }
13348
13349 // Placeholder
13350 if (obj.options.placeholder) {
13351 el.setAttribute('placeholder', obj.options.placeholder);
13352 } else {
13353 el.removeAttribute('placeholder');
13354 }
13355
13356 if (helpers.isNumeric(obj.options.value) && obj.options.value > 0) {
13357 obj.options.value = Component.numToDate(obj.options.value);
13358 // Data type numeric
13359 obj.options.dataType = 'numeric';
13360 }
13361
13362 // Texts
13363 calendarReset.innerHTML = obj.options.textReset;
13364 calendarConfirm.innerHTML = obj.options.textDone;
13365 calendarControlsUpdateButton.innerHTML = obj.options.textUpdate;
13366
13367 // Define mask
13368 if (obj.options.format) {
13369 el.setAttribute('data-mask', obj.options.format.toLowerCase());
13370 }
13371
13372 // Value
13373 if (!obj.options.value && obj.options.today) {
13374 var value = Component.now();
13375 } else {
13376 var value = obj.options.value;
13377 }
13378
13379 // Set internal date
13380 if (value) {
13381 // Force the update
13382 obj.options.value = null;
13383 // New value
13384 obj.setValue(value);
13385 }
13386
13387 return obj;
13388 }
13389
13390 /**
13391 * Open the calendar
13392 */
13393 obj.open = function (value) {
13394 if (!calendar.classList.contains('jcalendar-focus')) {
13395 if (!calendar.classList.contains('jcalendar-inline')) {
13396 // Current
13397 Component.current = obj;
13398 // Start tracking
13399 tracking(obj, true);
13400 // Create the days
13401 obj.getDays();
13402 // Render months
13403 if (obj.options.type == 'year-month-picker') {
13404 obj.getMonths();
13405 }
13406 // Get time
13407 if (obj.options.time) {
13408 calendarSelectHour.value = obj.date[3];
13409 calendarSelectMin.value = obj.date[4];
13410 }
13411
13412 // Show calendar
13413 calendar.classList.add('jcalendar-focus');
13414
13415 // Get the position of the corner helper
13416 if (helpers.getWindowWidth() < 800 || obj.options.fullscreen) {
13417 calendar.classList.add('jcalendar-fullsize');
13418 // Animation
13419 animation.slideBottom(calendarContent, 1);
13420 } else {
13421 calendar.classList.remove('jcalendar-fullsize');
13422
13423 var rect = el.getBoundingClientRect();
13424 var rectContent = calendarContent.getBoundingClientRect();
13425
13426 if (obj.options.position) {
13427 calendarContainer.style.position = 'fixed';
13428 if (window.innerHeight < rect.bottom + rectContent.height) {
13429 calendarContainer.style.top = (rect.top - (rectContent.height + 2)) + 'px';
13430 } else {
13431 calendarContainer.style.top = (rect.top + rect.height + 2) + 'px';
13432 }
13433 calendarContainer.style.left = rect.left + 'px';
13434 } else {
13435 if (window.innerHeight < rect.bottom + rectContent.height) {
13436 var d = -1 * (rect.height + rectContent.height + 2);
13437 if (d + rect.top < 0) {
13438 d = -1 * (rect.top + rect.height);
13439 }
13440 calendarContainer.style.top = d + 'px';
13441 } else {
13442 calendarContainer.style.top = 2 + 'px';
13443 }
13444
13445 if (window.innerWidth < rect.left + rectContent.width) {
13446 var d = window.innerWidth - (rect.left + rectContent.width + 20);
13447 calendarContainer.style.left = d + 'px';
13448 } else {
13449 calendarContainer.style.left = '0px';
13450 }
13451 }
13452 }
13453
13454 // Events
13455 if (typeof (obj.options.onopen) == 'function') {
13456 obj.options.onopen(el);
13457 }
13458 }
13459 }
13460 }
13461
13462 obj.close = function (ignoreEvents, update) {
13463 if (obj.options.autoSelect !== true && typeof(update) === 'undefined') {
13464 update = false;
13465 }
13466 if (calendar.classList.contains('jcalendar-focus')) {
13467 if (update !== false) {
13468 var element = calendar.querySelector('.jcalendar-selected');
13469
13470 if (typeof (update) == 'string') {
13471 var value = update;
13472 } else if (!element || element.classList.contains('jcalendar-disabled')) {
13473 var value = obj.options.value
13474 } else {
13475 var value = obj.getValue();
13476 }
13477
13478 obj.setValue(value);
13479 } else {
13480 let value = obj.options.value || '';
13481 obj.options.value = null;
13482 obj.setValue(value)
13483 }
13484
13485 // Events
13486 if (!ignoreEvents && typeof (obj.options.onclose) == 'function') {
13487 obj.options.onclose(el);
13488 }
13489 // Hide
13490 calendar.classList.remove('jcalendar-focus');
13491 // Stop tracking
13492 tracking(obj, false);
13493 // Current
13494 Component.current = null;
13495 }
13496
13497 return obj.options.value;
13498 }
13499
13500 obj.prev = function () {
13501 // Check if the visualization is the days picker or years picker
13502 if (obj.options.mode == 'years') {
13503 obj.date[0] = obj.date[0] - 12;
13504
13505 // Update picker table of days
13506 obj.getYears();
13507 } else if (obj.options.mode == 'months') {
13508 obj.date[0] = parseInt(obj.date[0]) - 1;
13509 // Update picker table of months
13510 obj.getMonths();
13511 } else {
13512 // Go to the previous month
13513 if (obj.date[1] < 2) {
13514 obj.date[0] = obj.date[0] - 1;
13515 obj.date[1] = 12;
13516 } else {
13517 obj.date[1] = obj.date[1] - 1;
13518 }
13519
13520 // Update picker table of days
13521 obj.getDays();
13522 }
13523 }
13524
13525 obj.next = function () {
13526 // Check if the visualization is the days picker or years picker
13527 if (obj.options.mode == 'years') {
13528 obj.date[0] = parseInt(obj.date[0]) + 12;
13529
13530 // Update picker table of days
13531 obj.getYears();
13532 } else if (obj.options.mode == 'months') {
13533 obj.date[0] = parseInt(obj.date[0]) + 1;
13534 // Update picker table of months
13535 obj.getMonths();
13536 } else {
13537 // Go to the previous month
13538 if (obj.date[1] > 11) {
13539 obj.date[0] = parseInt(obj.date[0]) + 1;
13540 obj.date[1] = 1;
13541 } else {
13542 obj.date[1] = parseInt(obj.date[1]) + 1;
13543 }
13544
13545 // Update picker table of days
13546 obj.getDays();
13547 }
13548 }
13549
13550 /**
13551 * Set today
13552 */
13553 obj.setToday = function () {
13554 // Today
13555 var value = new Date().toISOString().substr(0, 10);
13556 // Change value
13557 obj.setValue(value);
13558 // Value
13559 return value;
13560 }
13561
13562 obj.setValue = function (val) {
13563 if (!val) {
13564 val = '' + val;
13565 }
13566 // Values
13567 var newValue = val;
13568 var oldValue = obj.options.value;
13569
13570 if (oldValue != newValue) {
13571 // Set label
13572 if (!newValue) {
13573 obj.date = null;
13574 var val = '';
13575 el.classList.remove('jcalendar_warning');
13576 el.title = '';
13577 } else {
13578 var value = obj.setLabel(newValue, obj.options);
13579 var date = newValue.split(' ');
13580 if (!date[1]) {
13581 date[1] = '00:00:00';
13582 }
13583 var time = date[1].split(':')
13584 var date = date[0].split('-');
13585 var y = parseInt(date[0]);
13586 var m = parseInt(date[1]);
13587 var d = parseInt(date[2]);
13588 var h = parseInt(time[0]);
13589 var i = parseInt(time[1]);
13590 obj.date = [y, m, d, h, i, 0];
13591 var val = obj.setLabel(newValue, obj.options);
13592
13593 // Current selection day
13594 var current = Component.now(new Date(y, m - 1, d), true);
13595
13596 // Available ranges
13597 if (obj.options.validRange) {
13598 if (!obj.options.validRange[0] || current >= obj.options.validRange[0]) {
13599 var test1 = true;
13600 } else {
13601 var test1 = false;
13602 }
13603
13604 if (!obj.options.validRange[1] || current <= obj.options.validRange[1]) {
13605 var test2 = true;
13606 } else {
13607 var test2 = false;
13608 }
13609
13610 if (!(test1 && test2)) {
13611 el.classList.add('jcalendar_warning');
13612 el.title = dictionary.translate('Date outside the valid range');
13613 } else {
13614 el.classList.remove('jcalendar_warning');
13615 el.title = '';
13616 }
13617 } else {
13618 el.classList.remove('jcalendar_warning');
13619 el.title = '';
13620 }
13621 }
13622
13623 // New value
13624 obj.options.value = newValue;
13625
13626 if (typeof (obj.options.onchange) == 'function') {
13627 obj.options.onchange(el, newValue, oldValue);
13628 }
13629
13630 // Lemonade JS
13631 if (el.value != val) {
13632 el.value = val;
13633 if (typeof (el.oninput) == 'function') {
13634 el.oninput({
13635 type: 'input',
13636 target: el,
13637 value: el.value
13638 });
13639 }
13640 }
13641 }
13642
13643 if (obj.date) {
13644 obj.getDays();
13645 // Render months
13646 if (obj.options.type == 'year-month-picker') {
13647 obj.getMonths();
13648 }
13649 }
13650 }
13651
13652 obj.getValue = function () {
13653 if (obj.date) {
13654 if (obj.options.time) {
13655 return helpers.two(obj.date[0]) + '-' + helpers.two(obj.date[1]) + '-' + helpers.two(obj.date[2]) + ' ' + helpers.two(obj.date[3]) + ':' + helpers.two(obj.date[4]) + ':' + helpers.two(0);
13656 } else {
13657 return helpers.two(obj.date[0]) + '-' + helpers.two(obj.date[1]) + '-' + helpers.two(obj.date[2]) + ' ' + helpers.two(0) + ':' + helpers.two(0) + ':' + helpers.two(0);
13658 }
13659 } else {
13660 return "";
13661 }
13662 }
13663
13664 /**
13665 * Calendar
13666 */
13667 obj.update = function (element, v) {
13668 if (element.classList.contains('jcalendar-disabled')) {
13669 // Do nothing
13670 } else {
13671 var elements = calendar.querySelector('.jcalendar-selected');
13672 if (elements) {
13673 elements.classList.remove('jcalendar-selected');
13674 }
13675 element.classList.add('jcalendar-selected');
13676
13677 if (element.classList.contains('jcalendar-set-month')) {
13678 obj.date[1] = v;
13679 obj.date[2] = 1; // first day of the month
13680 } else {
13681 obj.date[2] = element.innerText;
13682 }
13683
13684 if (!obj.options.time) {
13685 obj.close(null, true);
13686 } else {
13687 obj.date[3] = calendarSelectHour.value;
13688 obj.date[4] = calendarSelectMin.value;
13689 }
13690 }
13691
13692 // Update
13693 updateActions();
13694 }
13695
13696 /**
13697 * Set to blank
13698 */
13699 obj.reset = function () {
13700 // Close calendar
13701 obj.setValue('');
13702 obj.date = null;
13703 obj.close(false, false);
13704 }
13705
13706 /**
13707 * Get calendar days
13708 */
13709 obj.getDays = function () {
13710 // Mode
13711 obj.options.mode = 'days';
13712
13713 // Setting current values in case of NULLs
13714 var date = new Date();
13715
13716 // Current selection
13717 var year = obj.date && helpers.isNumeric(obj.date[0]) ? obj.date[0] : parseInt(date.getFullYear());
13718 var month = obj.date && helpers.isNumeric(obj.date[1]) ? obj.date[1] : parseInt(date.getMonth()) + 1;
13719 var day = obj.date && helpers.isNumeric(obj.date[2]) ? obj.date[2] : parseInt(date.getDate());
13720 var hour = obj.date && helpers.isNumeric(obj.date[3]) ? obj.date[3] : parseInt(date.getHours());
13721 var min = obj.date && helpers.isNumeric(obj.date[4]) ? obj.date[4] : parseInt(date.getMinutes());
13722
13723 // Selection container
13724 obj.date = [year, month, day, hour, min, 0];
13725
13726 // Update title
13727 calendarLabelYear.innerHTML = year;
13728 calendarLabelMonth.innerHTML = obj.options.months[month - 1];
13729
13730 // Current month and Year
13731 var isCurrentMonthAndYear = (date.getMonth() == month - 1) && (date.getFullYear() == year) ? true : false;
13732 var currentDay = date.getDate();
13733
13734 // Number of days in the month
13735 var date = new Date(year, month, 0, 0, 0);
13736 var numberOfDays = date.getDate();
13737
13738 // First day
13739 var date = new Date(year, month - 1, 0, 0, 0);
13740 var firstDay = date.getDay() + 1;
13741
13742 // Index value
13743 var index = obj.options.startingDay || 0;
13744
13745 // First of day relative to the starting calendar weekday
13746 firstDay = firstDay - index;
13747
13748 // Reset table
13749 calendarBody.innerHTML = '';
13750
13751 // Weekdays Row
13752 var row = document.createElement('tr');
13753 row.setAttribute('align', 'center');
13754 calendarBody.appendChild(row);
13755
13756 // Create weekdays row
13757 for (var i = 0; i < 7; i++) {
13758 var cell = document.createElement('td');
13759 cell.classList.add('jcalendar-weekday')
13760 cell.innerHTML = obj.options.weekdays[index].substr(0, 1);
13761 row.appendChild(cell);
13762 // Next week day
13763 index++;
13764 // Restart index
13765 if (index > 6) {
13766 index = 0;
13767 }
13768 }
13769
13770 // Index of days
13771 var index = 0;
13772 var d = 0;
13773
13774 // Calendar table
13775 for (var j = 0; j < 6; j++) {
13776 // Reset cells container
13777 var row = document.createElement('tr');
13778 row.setAttribute('align', 'center');
13779 row.style.height = '34px';
13780
13781 // Create cells
13782 for (var i = 0; i < 7; i++) {
13783 // Create cell
13784 var cell = document.createElement('td');
13785 cell.classList.add('jcalendar-set-day');
13786
13787 if (index >= firstDay && index < (firstDay + numberOfDays)) {
13788 // Day cell
13789 d++;
13790 cell.innerHTML = d;
13791
13792 // Selected
13793 if (d == day) {
13794 cell.classList.add('jcalendar-selected');
13795 }
13796
13797 // Current selection day is today
13798 if (isCurrentMonthAndYear && currentDay == d) {
13799 cell.style.fontWeight = 'bold';
13800 }
13801
13802 // Current selection day
13803 var current = Component.now(new Date(year, month - 1, d), true);
13804
13805 // Available ranges
13806 if (obj.options.validRange) {
13807 if (!obj.options.validRange[0] || current >= obj.options.validRange[0]) {
13808 var test1 = true;
13809 } else {
13810 var test1 = false;
13811 }
13812
13813 if (!obj.options.validRange[1] || current <= obj.options.validRange[1]) {
13814 var test2 = true;
13815 } else {
13816 var test2 = false;
13817 }
13818
13819 if (!(test1 && test2)) {
13820 cell.classList.add('jcalendar-disabled');
13821 }
13822 }
13823 }
13824 // Day cell
13825 row.appendChild(cell);
13826 // Index
13827 index++;
13828 }
13829
13830 // Add cell to the calendar body
13831 calendarBody.appendChild(row);
13832 }
13833
13834 // Show time controls
13835 if (obj.options.time) {
13836 calendarControlsTime.style.display = '';
13837 } else {
13838 calendarControlsTime.style.display = 'none';
13839 }
13840
13841 // Update
13842 updateActions();
13843 }
13844
13845 obj.getMonths = function () {
13846 // Mode
13847 obj.options.mode = 'months';
13848
13849 // Loading month labels
13850 var months = obj.options.months;
13851
13852 // Value
13853 var value = obj.options.value;
13854
13855 // Current date
13856 var date = new Date();
13857 var currentYear = parseInt(date.getFullYear());
13858 var currentMonth = parseInt(date.getMonth()) + 1;
13859 var selectedYear = obj.date && helpers.isNumeric(obj.date[0]) ? obj.date[0] : currentYear;
13860 var selectedMonth = obj.date && helpers.isNumeric(obj.date[1]) ? obj.date[1] : currentMonth;
13861
13862 // Update title
13863 calendarLabelYear.innerHTML = obj.date[0];
13864 calendarLabelMonth.innerHTML = months[selectedMonth - 1];
13865
13866 // Table
13867 var table = document.createElement('table');
13868 table.setAttribute('width', '100%');
13869
13870 // Row
13871 var row = null;
13872
13873 // Calendar table
13874 for (var i = 0; i < 12; i++) {
13875 if (!(i % 4)) {
13876 // Reset cells container
13877 var row = document.createElement('tr');
13878 row.setAttribute('align', 'center');
13879 table.appendChild(row);
13880 }
13881
13882 // Create cell
13883 var cell = document.createElement('td');
13884 cell.classList.add('jcalendar-set-month');
13885 cell.setAttribute('data-value', i + 1);
13886 cell.innerText = months[i];
13887
13888 if (obj.options.validRange) {
13889 var current = selectedYear + '-' + helpers.two(i + 1);
13890 if (!obj.options.validRange[0] || current >= obj.options.validRange[0].substr(0, 7)) {
13891 var test1 = true;
13892 } else {
13893 var test1 = false;
13894 }
13895
13896 if (!obj.options.validRange[1] || current <= obj.options.validRange[1].substr(0, 7)) {
13897 var test2 = true;
13898 } else {
13899 var test2 = false;
13900 }
13901
13902 if (!(test1 && test2)) {
13903 cell.classList.add('jcalendar-disabled');
13904 }
13905 }
13906
13907 if (i + 1 == selectedMonth) {
13908 cell.classList.add('jcalendar-selected');
13909 }
13910
13911 if (currentYear == selectedYear && i + 1 == currentMonth) {
13912 cell.style.fontWeight = 'bold';
13913 }
13914
13915 row.appendChild(cell);
13916 }
13917
13918 calendarBody.innerHTML = '<tr><td colspan="7"></td></tr>';
13919 calendarBody.children[0].children[0].appendChild(table);
13920
13921 // Update
13922 updateActions();
13923 }
13924
13925 obj.getYears = function () {
13926 // Mode
13927 obj.options.mode = 'years';
13928
13929 // Current date
13930 var date = new Date();
13931 var currentYear = date.getFullYear();
13932 var selectedYear = obj.date && helpers.isNumeric(obj.date[0]) ? obj.date[0] : parseInt(date.getFullYear());
13933
13934 // Array of years
13935 var y = [];
13936 for (var i = 0; i < 25; i++) {
13937 y[i] = parseInt(obj.date[0]) + (i - 12);
13938 }
13939
13940 // Assembling the year tables
13941 var table = document.createElement('table');
13942 table.setAttribute('width', '100%');
13943
13944 for (var i = 0; i < 25; i++) {
13945 if (!(i % 5)) {
13946 // Reset cells container
13947 var row = document.createElement('tr');
13948 row.setAttribute('align', 'center');
13949 table.appendChild(row);
13950 }
13951
13952 // Create cell
13953 var cell = document.createElement('td');
13954 cell.classList.add('jcalendar-set-year');
13955 cell.innerText = y[i];
13956
13957 if (selectedYear == y[i]) {
13958 cell.classList.add('jcalendar-selected');
13959 }
13960
13961 if (currentYear == y[i]) {
13962 cell.style.fontWeight = 'bold';
13963 }
13964
13965 row.appendChild(cell);
13966 }
13967
13968 calendarBody.innerHTML = '<tr><td colspan="7"></td></tr>';
13969 calendarBody.firstChild.firstChild.appendChild(table);
13970
13971 // Update
13972 updateActions();
13973 }
13974
13975 obj.setLabel = function (value, mixed) {
13976 return Component.getDateString(value, mixed);
13977 }
13978
13979 obj.fromFormatted = function (value, format) {
13980 return Component.extractDateFromString(value, format);
13981 }
13982
13983 var mouseUpControls = function (e) {
13984 var element = helpers.findElement(e.target, 'jcalendar-container');
13985 if (element) {
13986 var action = e.target.className;
13987
13988 // Object id
13989 if (action == 'jcalendar-prev') {
13990 obj.prev();
13991 } else if (action == 'jcalendar-next') {
13992 obj.next();
13993 } else if (action == 'jcalendar-month') {
13994 obj.getMonths();
13995 } else if (action == 'jcalendar-year') {
13996 obj.getYears();
13997 } else if (action == 'jcalendar-set-year') {
13998 obj.date[0] = e.target.innerText;
13999 if (obj.options.type == 'year-month-picker') {
14000 obj.getMonths();
14001 } else {
14002 obj.getDays();
14003 }
14004 } else if (e.target.classList.contains('jcalendar-set-month')) {
14005 var month = parseInt(e.target.getAttribute('data-value'));
14006 if (obj.options.type == 'year-month-picker') {
14007 obj.update(e.target, month);
14008 } else {
14009 obj.date[1] = month;
14010 obj.getDays();
14011 }
14012 } else if (action == 'jcalendar-confirm' || action == 'jcalendar-update' || action == 'jcalendar-close') {
14013 obj.close(null, true);
14014 } else if (action == 'jcalendar-backdrop') {
14015 obj.close(false, false);
14016 } else if (action == 'jcalendar-reset') {
14017 obj.reset();
14018 } else if (e.target.classList.contains('jcalendar-set-day') && e.target.innerText) {
14019 obj.update(e.target);
14020 }
14021 } else {
14022 obj.close(false, false);
14023 }
14024 }
14025
14026 var keyUpControls = function (e) {
14027 if (e.target.value && e.target.value.length > 3) {
14028 var test = Component.extractDateFromString(e.target.value, obj.options.format);
14029 if (test) {
14030 obj.setValue(test);
14031 }
14032 }
14033 }
14034
14035 // Update actions button
14036 var updateActions = function () {
14037 var currentDay = calendar.querySelector('.jcalendar-selected');
14038
14039 if (currentDay && currentDay.classList.contains('jcalendar-disabled')) {
14040 calendarControlsUpdateButton.setAttribute('disabled', 'disabled');
14041 calendarSelectHour.setAttribute('disabled', 'disabled');
14042 calendarSelectMin.setAttribute('disabled', 'disabled');
14043 } else {
14044 calendarControlsUpdateButton.removeAttribute('disabled');
14045 calendarSelectHour.removeAttribute('disabled');
14046 calendarSelectMin.removeAttribute('disabled');
14047 }
14048
14049 // Event
14050 if (typeof (obj.options.onupdate) == 'function') {
14051 obj.options.onupdate(el, obj.getValue());
14052 }
14053 }
14054
14055 var calendar = null;
14056 var calendarReset = null;
14057 var calendarConfirm = null;
14058 var calendarContainer = null;
14059 var calendarContent = null;
14060 var calendarLabelYear = null;
14061 var calendarLabelMonth = null;
14062 var calendarTable = null;
14063 var calendarBody = null;
14064
14065 var calendarControls = null;
14066 var calendarControlsTime = null;
14067 var calendarControlsUpdate = null;
14068 var calendarControlsUpdateButton = null;
14069 var calendarSelectHour = null;
14070 var calendarSelectMin = null;
14071
14072 var init = function () {
14073 // Get value from initial element if that is an input
14074 if (el.tagName == 'INPUT' && el.value) {
14075 options.value = el.value;
14076 }
14077
14078 // Calendar DOM elements
14079 calendarReset = document.createElement('div');
14080 calendarReset.className = 'jcalendar-reset';
14081
14082 calendarConfirm = document.createElement('div');
14083 calendarConfirm.className = 'jcalendar-confirm';
14084
14085 calendarControls = document.createElement('div');
14086 calendarControls.className = 'jcalendar-controls'
14087 calendarControls.style.borderBottom = '1px solid #ddd';
14088 calendarControls.appendChild(calendarReset);
14089 calendarControls.appendChild(calendarConfirm);
14090
14091 calendarContainer = document.createElement('div');
14092 calendarContainer.className = 'jcalendar-container';
14093 calendarContent = document.createElement('div');
14094 calendarContent.className = 'jcalendar-content';
14095 calendarContainer.appendChild(calendarContent);
14096
14097 // Main element
14098 if (el.tagName == 'DIV') {
14099 calendar = el;
14100 calendar.classList.add('jcalendar-inline');
14101 } else {
14102 // Add controls to the screen
14103 calendarContent.appendChild(calendarControls);
14104
14105 calendar = document.createElement('div');
14106 calendar.className = 'jcalendar';
14107 }
14108 calendar.classList.add('jcalendar-container');
14109 calendar.appendChild(calendarContainer);
14110
14111 // Table container
14112 var calendarTableContainer = document.createElement('div');
14113 calendarTableContainer.className = 'jcalendar-table';
14114 calendarContent.appendChild(calendarTableContainer);
14115
14116 // Previous button
14117 var calendarHeaderPrev = document.createElement('td');
14118 calendarHeaderPrev.setAttribute('colspan', '2');
14119 calendarHeaderPrev.className = 'jcalendar-prev';
14120
14121 // Header with year and month
14122 calendarLabelYear = document.createElement('span');
14123 calendarLabelYear.className = 'jcalendar-year';
14124 calendarLabelMonth = document.createElement('span');
14125 calendarLabelMonth.className = 'jcalendar-month';
14126
14127 var calendarHeaderTitle = document.createElement('td');
14128 calendarHeaderTitle.className = 'jcalendar-header';
14129 calendarHeaderTitle.setAttribute('colspan', '3');
14130 calendarHeaderTitle.appendChild(calendarLabelMonth);
14131 calendarHeaderTitle.appendChild(calendarLabelYear);
14132
14133 var calendarHeaderNext = document.createElement('td');
14134 calendarHeaderNext.setAttribute('colspan', '2');
14135 calendarHeaderNext.className = 'jcalendar-next';
14136
14137 var calendarHeader = document.createElement('thead');
14138 var calendarHeaderRow = document.createElement('tr');
14139 calendarHeaderRow.appendChild(calendarHeaderPrev);
14140 calendarHeaderRow.appendChild(calendarHeaderTitle);
14141 calendarHeaderRow.appendChild(calendarHeaderNext);
14142 calendarHeader.appendChild(calendarHeaderRow);
14143
14144 calendarTable = document.createElement('table');
14145 calendarBody = document.createElement('tbody');
14146 calendarTable.setAttribute('cellpadding', '0');
14147 calendarTable.setAttribute('cellspacing', '0');
14148 calendarTable.appendChild(calendarHeader);
14149 calendarTable.appendChild(calendarBody);
14150 calendarTableContainer.appendChild(calendarTable);
14151
14152 calendarSelectHour = document.createElement('select');
14153 calendarSelectHour.className = 'jcalendar-select';
14154 calendarSelectHour.onchange = function () {
14155 obj.date[3] = this.value;
14156
14157 // Event
14158 if (typeof (obj.options.onupdate) == 'function') {
14159 obj.options.onupdate(el, obj.getValue());
14160 }
14161 }
14162
14163 for (var i = 0; i < 24; i++) {
14164 var element = document.createElement('option');
14165 element.value = i;
14166 element.innerHTML = helpers.two(i);
14167 calendarSelectHour.appendChild(element);
14168 }
14169
14170 calendarSelectMin = document.createElement('select');
14171 calendarSelectMin.className = 'jcalendar-select';
14172 calendarSelectMin.onchange = function () {
14173 obj.date[4] = this.value;
14174
14175 // Event
14176 if (typeof (obj.options.onupdate) == 'function') {
14177 obj.options.onupdate(el, obj.getValue());
14178 }
14179 }
14180
14181 for (var i = 0; i < 60; i++) {
14182 var element = document.createElement('option');
14183 element.value = i;
14184 element.innerHTML = helpers.two(i);
14185 calendarSelectMin.appendChild(element);
14186 }
14187
14188 // Footer controls
14189 var calendarControlsFooter = document.createElement('div');
14190 calendarControlsFooter.className = 'jcalendar-controls';
14191
14192 calendarControlsTime = document.createElement('div');
14193 calendarControlsTime.className = 'jcalendar-time';
14194 calendarControlsTime.style.maxWidth = '140px';
14195 calendarControlsTime.appendChild(calendarSelectHour);
14196 calendarControlsTime.appendChild(calendarSelectMin);
14197
14198 calendarControlsUpdateButton = document.createElement('button');
14199 calendarControlsUpdateButton.setAttribute('type', 'button');
14200 calendarControlsUpdateButton.className = 'jcalendar-update';
14201
14202 calendarControlsUpdate = document.createElement('div');
14203 calendarControlsUpdate.style.flexGrow = '10';
14204 calendarControlsUpdate.appendChild(calendarControlsUpdateButton);
14205 calendarControlsFooter.appendChild(calendarControlsTime);
14206
14207 // Only show the update button for input elements
14208 if (el.tagName == 'INPUT') {
14209 calendarControlsFooter.appendChild(calendarControlsUpdate);
14210 }
14211
14212 calendarContent.appendChild(calendarControlsFooter);
14213
14214 var calendarBackdrop = document.createElement('div');
14215 calendarBackdrop.className = 'jcalendar-backdrop';
14216 calendar.appendChild(calendarBackdrop);
14217
14218 // Handle events
14219 el.addEventListener("keyup", keyUpControls);
14220
14221 // Add global events
14222 calendar.addEventListener("swipeleft", function (e) {
14223 animation.slideLeft(calendarTable, 0, function () {
14224 obj.next();
14225 animation.slideRight(calendarTable, 1);
14226 });
14227 e.preventDefault();
14228 e.stopPropagation();
14229 });
14230
14231 calendar.addEventListener("swiperight", function (e) {
14232 animation.slideRight(calendarTable, 0, function () {
14233 obj.prev();
14234 animation.slideLeft(calendarTable, 1);
14235 });
14236 e.preventDefault();
14237 e.stopPropagation();
14238 });
14239
14240 if ('ontouchend' in document.documentElement === true) {
14241 calendar.addEventListener("touchend", mouseUpControls);
14242 el.addEventListener("touchend", obj.open);
14243 } else {
14244 calendar.addEventListener("mouseup", mouseUpControls);
14245 el.addEventListener("mouseup", obj.open);
14246 }
14247
14248 // Global controls
14249 if (!Component.hasEvents) {
14250 // Execute only one time
14251 Component.hasEvents = true;
14252 // Enter and Esc
14253 document.addEventListener("keydown", Component.keydown);
14254 }
14255
14256 // Set configuration
14257 obj.setOptions(options);
14258
14259 // Append element to the DOM
14260 if (el.tagName == 'INPUT') {
14261 el.parentNode.insertBefore(calendar, el.nextSibling);
14262 // Add properties
14263 el.setAttribute('autocomplete', 'off');
14264 // Element
14265 el.classList.add('jcalendar-input');
14266 // Value
14267 el.value = obj.setLabel(obj.getValue(), obj.options);
14268 } else {
14269 // Get days
14270 obj.getDays();
14271 // Hour
14272 if (obj.options.time) {
14273 calendarSelectHour.value = obj.date[3];
14274 calendarSelectMin.value = obj.date[4];
14275 }
14276 }
14277
14278 // Controls - must be set before open() for correct height calculations
14279 if (obj.options.controls == false) {
14280 calendarContainer.classList.add('jcalendar-hide-controls');
14281 }
14282
14283 // Default opened
14284 if (obj.options.opened == true) {
14285 obj.open();
14286 }
14287
14288 // Change method
14289 el.change = obj.setValue;
14290
14291 // Global generic value handler
14292 el.val = function (val) {
14293 if (val === undefined) {
14294 return obj.getValue();
14295 } else {
14296 obj.setValue(val);
14297 }
14298 }
14299
14300 // Keep object available from the node
14301 el.calendar = calendar.calendar = obj;
14302 }
14303
14304 init();
14305
14306 return obj;
14307 });
14308
14309 Component.keydown = function (e) {
14310 var calendar = null;
14311 if (calendar = Component.current) {
14312 if (e.which == 13) {
14313 // ENTER
14314 calendar.close(false, true);
14315 } else if (e.which == 27) {
14316 // ESC
14317 calendar.close(false, false);
14318 }
14319 }
14320 }
14321
14322 Component.prettify = function (d, texts) {
14323 if (!texts) {
14324 var texts = {
14325 justNow: 'Just now',
14326 xMinutesAgo: '{0}m ago',
14327 xHoursAgo: '{0}h ago',
14328 xDaysAgo: '{0}d ago',
14329 xWeeksAgo: '{0}w ago',
14330 xMonthsAgo: '{0} mon ago',
14331 xYearsAgo: '{0}y ago',
14332 }
14333 }
14334
14335 if (d.indexOf('GMT') === -1 && d.indexOf('Z') === -1) {
14336 d += ' GMT';
14337 }
14338
14339 var d1 = new Date();
14340 var d2 = new Date(d);
14341 var total = parseInt((d1 - d2) / 1000 / 60);
14342
14343 String.prototype.format = function (o) {
14344 return this.replace('{0}', o);
14345 }
14346
14347 if (total == 0) {
14348 var text = texts.justNow;
14349 } else if (total < 90) {
14350 var text = texts.xMinutesAgo.format(total);
14351 } else if (total < 1440) { // One day
14352 var text = texts.xHoursAgo.format(Math.round(total / 60));
14353 } else if (total < 20160) { // 14 days
14354 var text = texts.xDaysAgo.format(Math.round(total / 1440));
14355 } else if (total < 43200) { // 30 days
14356 var text = texts.xWeeksAgo.format(Math.round(total / 10080));
14357 } else if (total < 1036800) { // 24 months
14358 var text = texts.xMonthsAgo.format(Math.round(total / 43200));
14359 } else { // 24 months+
14360 var text = texts.xYearsAgo.format(Math.round(total / 525600));
14361 }
14362
14363 return text;
14364 }
14365
14366 Component.prettifyAll = function () {
14367 var elements = document.querySelectorAll('.prettydate');
14368 for (var i = 0; i < elements.length; i++) {
14369 if (elements[i].getAttribute('data-date')) {
14370 elements[i].innerHTML = Component.prettify(elements[i].getAttribute('data-date'));
14371 } else {
14372 if (elements[i].innerHTML) {
14373 elements[i].setAttribute('title', elements[i].innerHTML);
14374 elements[i].setAttribute('data-date', elements[i].innerHTML);
14375 elements[i].innerHTML = Component.prettify(elements[i].innerHTML);
14376 }
14377 }
14378 }
14379 }
14380
14381 Component.now = HelpersDate.now;
14382 Component.toArray = HelpersDate.toArray;
14383 Component.dateToNum = HelpersDate.dateToNum
14384 Component.numToDate = HelpersDate.numToDate;
14385 Component.weekdays = HelpersDate.weekdays;
14386 Component.months = HelpersDate.months;
14387 Component.weekdaysShort = HelpersDate.weekdaysShort;
14388 Component.monthsShort = HelpersDate.monthsShort;
14389
14390 // Legacy shortcut
14391 Component.extractDateFromString = Mask.extractDateFromString;
14392 Component.getDateString = Mask.getDateString;
14393
14394 return Component;
14395}
14396
14397/* harmony default export */ var calendar = (Calendar());
14398;// CONCATENATED MODULE: ./src/plugins/palette.js
14399// More palettes https://coolors.co/ or https://gka.github.io/palettes/#/10|s|003790,005647,ffffe0|ffffe0,ff005e,93003a|1|1
14400
14401function Palette() {
14402
14403 var palette = {
14404 material: [
14405 ["#ffebee", "#fce4ec", "#f3e5f5", "#e8eaf6", "#e3f2fd", "#e0f7fa", "#e0f2f1", "#e8f5e9", "#f1f8e9", "#f9fbe7", "#fffde7", "#fff8e1", "#fff3e0", "#fbe9e7", "#efebe9", "#fafafa", "#eceff1"],
14406 ["#ffcdd2", "#f8bbd0", "#e1bee7", "#c5cae9", "#bbdefb", "#b2ebf2", "#b2dfdb", "#c8e6c9", "#dcedc8", "#f0f4c3", "#fff9c4", "#ffecb3", "#ffe0b2", "#ffccbc", "#d7ccc8", "#f5f5f5", "#cfd8dc"],
14407 ["#ef9a9a", "#f48fb1", "#ce93d8", "#9fa8da", "#90caf9", "#80deea", "#80cbc4", "#a5d6a7", "#c5e1a5", "#e6ee9c", "#fff59d", "#ffe082", "#ffcc80", "#ffab91", "#bcaaa4", "#eeeeee", "#b0bec5"],
14408 ["#e57373", "#f06292", "#ba68c8", "#7986cb", "#64b5f6", "#4dd0e1", "#4db6ac", "#81c784", "#aed581", "#dce775", "#fff176", "#ffd54f", "#ffb74d", "#ff8a65", "#a1887f", "#e0e0e0", "#90a4ae"],
14409 ["#ef5350", "#ec407a", "#ab47bc", "#5c6bc0", "#42a5f5", "#26c6da", "#26a69a", "#66bb6a", "#9ccc65", "#d4e157", "#ffee58", "#ffca28", "#ffa726", "#ff7043", "#8d6e63", "#bdbdbd", "#78909c"],
14410 ["#f44336", "#e91e63", "#9c27b0", "#3f51b5", "#2196f3", "#00bcd4", "#009688", "#4caf50", "#8bc34a", "#cddc39", "#ffeb3b", "#ffc107", "#ff9800", "#ff5722", "#795548", "#9e9e9e", "#607d8b"],
14411 ["#e53935", "#d81b60", "#8e24aa", "#3949ab", "#1e88e5", "#00acc1", "#00897b", "#43a047", "#7cb342", "#c0ca33", "#fdd835", "#ffb300", "#fb8c00", "#f4511e", "#6d4c41", "#757575", "#546e7a"],
14412 ["#d32f2f", "#c2185b", "#7b1fa2", "#303f9f", "#1976d2", "#0097a7", "#00796b", "#388e3c", "#689f38", "#afb42b", "#fbc02d", "#ffa000", "#f57c00", "#e64a19", "#5d4037", "#616161", "#455a64"],
14413 ["#c62828", "#ad1457", "#6a1b9a", "#283593", "#1565c0", "#00838f", "#00695c", "#2e7d32", "#558b2f", "#9e9d24", "#f9a825", "#ff8f00", "#ef6c00", "#d84315", "#4e342e", "#424242", "#37474f"],
14414 ["#b71c1c", "#880e4f", "#4a148c", "#1a237e", "#0d47a1", "#006064", "#004d40", "#1b5e20", "#33691e", "#827717", "#f57f17", "#ff6f00", "#e65100", "#bf360c", "#3e2723", "#212121", "#263238"],
14415 ],
14416 fire: [
14417 ["0b1a6d", "840f38", "b60718", "de030b", "ff0c0c", "fd491c", "fc7521", "faa331", "fbb535", "ffc73a"],
14418 ["071147", "5f0b28", "930513", "be0309", "ef0000", "fa3403", "fb670b", "f9991b", "faad1e", "ffc123"],
14419 ["03071e", "370617", "6a040f", "9d0208", "d00000", "dc2f02", "e85d04", "f48c06", "faa307", "ffba08"],
14420 ["020619", "320615", "61040d", "8c0207", "bc0000", "c82a02", "d05203", "db7f06", "e19405", "efab00"],
14421 ["020515", "2d0513", "58040c", "7f0206", "aa0000", "b62602", "b94903", "c57205", "ca8504", "d89b00"],
14422 ],
14423 baby: [
14424 ["eddcd2", "fff1e6", "fde2e4", "fad2e1", "c5dedd", "dbe7e4", "f0efeb", "d6e2e9", "bcd4e6", "99c1de"],
14425 ["e1c4b3", "ffd5b5", "fab6ba", "f5a8c4", "aacecd", "bfd5cf", "dbd9d0", "baceda", "9dc0db", "7eb1d5"],
14426 ["daa990", "ffb787", "f88e95", "f282a9", "8fc4c3", "a3c8be", "cec9b3", "9dbcce", "82acd2", "649dcb"],
14427 ["d69070", "ff9c5e", "f66770", "f05f8f", "74bbb9", "87bfae", "c5b993", "83aac3", "699bca", "4d89c2"],
14428 ["c97d5d", "f58443", "eb4d57", "e54a7b", "66a9a7", "78ae9c", "b5a67e", "7599b1", "5c88b7", "4978aa"],
14429 ],
14430 chart: [
14431 ['#C1D37F', '#4C5454', '#FFD275', '#66586F', '#D05D5B', '#C96480', '#95BF8F', '#6EA240', '#0F0F0E', '#EB8258', '#95A3B3', '#995D81'],
14432 ],
14433 }
14434
14435 var Component = function (o) {
14436 // Otherwise get palette value
14437 if (palette[o]) {
14438 return palette[o];
14439 } else {
14440 return palette.material;
14441 }
14442 }
14443
14444 Component.get = function (o) {
14445 // Otherwise get palette value
14446 if (palette[o]) {
14447 return palette[o];
14448 } else {
14449 return palette;
14450 }
14451 }
14452
14453 Component.set = function (o, v) {
14454 palette[o] = v;
14455 }
14456
14457 return Component;
14458}
14459
14460/* harmony default export */ var palette = (Palette());
14461;// CONCATENATED MODULE: ./src/plugins/tabs.js
14462
14463
14464
14465
14466function Tabs(el, options) {
14467 var obj = {};
14468 obj.options = {};
14469
14470 // Default configuration
14471 var defaults = {
14472 data: [],
14473 position: null,
14474 allowCreate: false,
14475 allowChangePosition: false,
14476 onclick: null,
14477 onload: null,
14478 onchange: null,
14479 oncreate: null,
14480 ondelete: null,
14481 onbeforecreate: null,
14482 onchangeposition: null,
14483 animation: false,
14484 hideHeaders: false,
14485 padding: null,
14486 palette: null,
14487 maxWidth: null,
14488 }
14489
14490 // Loop through the initial configuration
14491 for (var property in defaults) {
14492 if (options && options.hasOwnProperty(property)) {
14493 obj.options[property] = options[property];
14494 } else {
14495 obj.options[property] = defaults[property];
14496 }
14497 }
14498
14499 // Class
14500 el.classList.add('jtabs');
14501
14502 var prev = null;
14503 var next = null;
14504 var border = null;
14505 var header = null;
14506 var controls = null;
14507 var add = null;
14508
14509 // Event handler references for cleanup
14510 var headersClickHandler = null;
14511 var headersContextMenuHandler = null;
14512
14513 // Helpers
14514 const setBorder = function(index) {
14515 if (obj.options.animation) {
14516 setTimeout(function() {
14517 // Guard against destroyed state
14518 if (!obj.headers || !obj.headers.children[index]) {
14519 return;
14520 }
14521 let rect = obj.headers.children[index].getBoundingClientRect();
14522
14523 if (obj.options.palette === 'modern') {
14524 border.style.width = rect.width - 4 + 'px';
14525 border.style.left = obj.headers.children[index].offsetLeft + 2 + 'px';
14526 } else {
14527 border.style.width = rect.width + 'px';
14528 border.style.left = obj.headers.children[index].offsetLeft + 'px';
14529 }
14530
14531 if (obj.options.position === 'bottom') {
14532 border.style.top = '0px';
14533 } else {
14534 border.style.bottom = '0px';
14535 }
14536 }, 50);
14537 }
14538 }
14539
14540 var updateControls = function(x) {
14541 // Guard against destroyed state
14542 if (!obj.headers) {
14543 return;
14544 }
14545 if (typeof(obj.headers.scrollTo) == 'function') {
14546 obj.headers.scrollTo({
14547 left: x,
14548 behavior: 'smooth',
14549 });
14550 } else {
14551 obj.headers.scrollLeft = x;
14552 }
14553
14554 if (x <= 1) {
14555 prev.classList.add('disabled');
14556 } else {
14557 prev.classList.remove('disabled');
14558 }
14559
14560 if (x >= obj.headers.scrollWidth - obj.headers.offsetWidth) {
14561 next.classList.add('disabled');
14562 } else {
14563 next.classList.remove('disabled');
14564 }
14565
14566 if (obj.headers.scrollWidth <= obj.headers.offsetWidth) {
14567 prev.style.display = 'none';
14568 next.style.display = 'none';
14569 } else {
14570 prev.style.display = '';
14571 next.style.display = '';
14572 }
14573 }
14574
14575 obj.setBorder = setBorder;
14576
14577 // Set value
14578 obj.open = function(index) {
14579 // This is to force safari to update the children
14580 const items = Array.from(obj.content.children);
14581 if (! obj.content.children[index]) {
14582 return;
14583 }
14584
14585 var previous = null;
14586 for (var i = 0; i < obj.headers.children.length; i++) {
14587 if (obj.headers.children[i].classList.contains('jtabs-selected')) {
14588 // Current one
14589 previous = i;
14590 }
14591 // Remote selected
14592 obj.headers.children[i].classList.remove('jtabs-selected');
14593 obj.headers.children[i].removeAttribute('aria-selected')
14594 if (obj.content.children[i]) {
14595 obj.content.children[i].classList.remove('jtabs-selected');
14596 }
14597 }
14598
14599 obj.headers.children[index].classList.add('jtabs-selected');
14600 obj.headers.children[index].setAttribute('aria-selected', 'true')
14601
14602 if (obj.content.children[index]) {
14603 obj.content.children[index].classList.add('jtabs-selected');
14604 }
14605
14606 if (previous != index && typeof(obj.options.onchange) == 'function') {
14607 if (obj.content.children[index]) {
14608 obj.options.onchange(el, obj, index, obj.headers.children[index], obj.content.children[index]);
14609 }
14610 }
14611
14612 // Hide
14613 if (obj.options.hideHeaders == true && (obj.headers.children.length < 3 && obj.options.allowCreate == false)) {
14614 obj.headers.parentNode.style.display = 'none';
14615 } else {
14616 obj.headers.parentNode.style.display = '';
14617
14618 var x1 = obj.headers.children[index].offsetLeft;
14619 var x2 = x1 + obj.headers.children[index].offsetWidth;
14620 var r1 = obj.headers.scrollLeft;
14621 var r2 = r1 + obj.headers.offsetWidth;
14622
14623 if (! (r1 <= x1 && r2 >= x2)) {
14624 // Out of the viewport
14625 updateControls(x1 - 1);
14626 }
14627
14628 // Set border
14629 setBorder(index);
14630 }
14631 }
14632
14633 obj.selectIndex = function(a) {
14634 var index = Array.prototype.indexOf.call(obj.headers.children, a);
14635 if (index >= 0) {
14636 obj.open(index);
14637 }
14638
14639 return index;
14640 }
14641
14642 obj.rename = function(i, title) {
14643 if (! title) {
14644 title = prompt('New title', obj.headers.children[i].innerText);
14645 }
14646 obj.headers.children[i].innerText = title;
14647 setBorder(obj.getActive());
14648 }
14649
14650 obj.create = function(title, url) {
14651 if (typeof(obj.options.onbeforecreate) == 'function') {
14652 var ret = obj.options.onbeforecreate(el, title);
14653 if (ret === false) {
14654 return false;
14655 } else {
14656 title = ret;
14657 }
14658 }
14659
14660 var div = obj.appendElement(title);
14661
14662 if (typeof(obj.options.oncreate) == 'function') {
14663 obj.options.oncreate(el, div)
14664 }
14665
14666 setBorder(obj.getActive());
14667
14668 return div;
14669 }
14670
14671 obj.remove = function(index) {
14672 return obj.deleteElement(index);
14673 }
14674
14675 obj.nextNumber = function() {
14676 var num = 0;
14677 for (var i = 0; i < obj.headers.children.length; i++) {
14678 var tmp = obj.headers.children[i].innerText.match(/[0-9].*/);
14679 if (tmp > num) {
14680 num = parseInt(tmp);
14681 }
14682 }
14683 if (! num) {
14684 num = 1;
14685 } else {
14686 num++;
14687 }
14688
14689 return num;
14690 }
14691
14692 obj.deleteElement = function(index) {
14693 let current = obj.getActive();
14694
14695 if (! obj.headers.children[index]) {
14696 return false;
14697 } else {
14698 obj.headers.removeChild(obj.headers.children[index]);
14699 obj.content.removeChild(obj.content.children[index]);
14700 }
14701
14702 if (current === index) {
14703 obj.open(0);
14704 } else {
14705 let current = obj.getActive() || 0;
14706 setBorder(current);
14707 }
14708
14709 if (typeof(obj.options.ondelete) == 'function') {
14710 obj.options.ondelete(el, index)
14711 }
14712 }
14713
14714 obj.appendElement = function(title, cb, openTab, position) {
14715 if (! title) {
14716 var title = prompt('Title?', '');
14717 }
14718
14719 if (title) {
14720 let headerId = helpers.guid();
14721 let contentId = helpers.guid();
14722 // Add content
14723 var div = document.createElement('div');
14724 div.setAttribute('id', contentId);
14725 div.setAttribute('role', 'tabpanel');
14726 div.setAttribute('aria-labelledby', headerId);
14727
14728 // Add headers
14729 var h = document.createElement('div');
14730 h.setAttribute('id', headerId);
14731 h.setAttribute('role', 'tab');
14732 h.setAttribute('aria-controls', contentId);
14733
14734 h.textContent = title;
14735 h.content = div;
14736
14737 if (typeof(position) === 'undefined') {
14738 obj.content.appendChild(div);
14739 obj.headers.insertBefore(h, obj.headers.lastChild);
14740 } else {
14741 let r = obj.content.children[position];
14742 if (r) {
14743 obj.content.insertBefore(div, r);
14744 } else {
14745 obj.content.appendChild(div);
14746 }
14747 r = obj.headers.children[position] || obj.headers.lastChild;
14748 obj.headers.insertBefore(h, r);
14749 }
14750
14751 // Sortable
14752 if (obj.options.allowChangePosition) {
14753 h.setAttribute('draggable', 'true');
14754 }
14755
14756 // Open new tab
14757 if (openTab !== false) {
14758 // Open new tab
14759 obj.selectIndex(h);
14760 }
14761
14762 // Callback
14763 if (typeof(cb) == 'function') {
14764 cb(div, h);
14765 }
14766
14767 // Return element
14768 return div;
14769 }
14770 }
14771
14772 obj.getActive = function() {
14773 for (var i = 0; i < obj.headers.children.length; i++) {
14774 if (obj.headers.children[i].classList.contains('jtabs-selected')) {
14775 return i;
14776 }
14777 }
14778 return false;
14779 }
14780
14781 obj.updateContent = function(position, newContent) {
14782 if (typeof newContent !== 'string') {
14783 var contentItem = newContent;
14784 } else {
14785 var contentItem = document.createElement('div');
14786 contentItem.innerHTML = newContent;
14787 }
14788
14789 if (obj.content.children[position].classList.contains('jtabs-selected')) {
14790 newContent.classList.add('jtabs-selected');
14791 }
14792
14793 obj.content.replaceChild(newContent, obj.content.children[position]);
14794
14795 setBorder();
14796 }
14797
14798 obj.updatePosition = function(f, t, ignoreEvents, openTab) {
14799 // Ondrop update position of content
14800 if (f > t) {
14801 obj.content.insertBefore(obj.content.children[f], obj.content.children[t]);
14802 } else {
14803 obj.content.insertBefore(obj.content.children[f], obj.content.children[t].nextSibling);
14804 }
14805
14806 // Open destination tab
14807 if (openTab !== false) {
14808 obj.open(t);
14809 } else {
14810 const activeIndex = obj.getActive();
14811
14812 if (t < activeIndex) {
14813 obj.setBorder(activeIndex);
14814 }
14815 }
14816
14817 // Call event
14818 if (! ignoreEvents && typeof(obj.options.onchangeposition) == 'function') {
14819 obj.options.onchangeposition(obj.headers, f, t);
14820 }
14821 }
14822
14823 obj.move = function(f, t, ignoreEvents, openTab) {
14824 if (f > t) {
14825 obj.headers.insertBefore(obj.headers.children[f], obj.headers.children[t]);
14826 } else {
14827 obj.headers.insertBefore(obj.headers.children[f], obj.headers.children[t].nextSibling);
14828 }
14829
14830 obj.updatePosition(f, t, ignoreEvents, openTab);
14831 }
14832
14833 obj.setBorder = setBorder;
14834
14835 obj.init = function() {
14836 el.textContent = '';
14837
14838 // Make sure the component is blank
14839 obj.headers = document.createElement('div');
14840 obj.content = document.createElement('div');
14841 obj.headers.classList.add('jtabs-headers');
14842 obj.headers.setAttribute('role', 'tablist');
14843 obj.content.classList.add('jtabs-content');
14844 obj.content.setAttribute('role', 'region');
14845 obj.content.setAttribute('aria-label', 'Tab Panels');
14846
14847 if (obj.options.palette) {
14848 el.classList.add('jtabs-modern');
14849 } else {
14850 el.classList.remove('jtabs-modern');
14851 }
14852
14853 // Padding
14854 if (obj.options.padding) {
14855 obj.content.style.padding = parseInt(obj.options.padding) + 'px';
14856 }
14857
14858 // Header
14859 header = document.createElement('div');
14860 header.className = 'jtabs-headers-container';
14861 header.appendChild(obj.headers);
14862 if (obj.options.maxWidth) {
14863 header.style.maxWidth = parseInt(obj.options.maxWidth) + 'px';
14864 }
14865
14866 // Controls
14867 controls = document.createElement('div');
14868 controls.className = 'jtabs-controls';
14869 controls.setAttribute('draggable', 'false');
14870 header.appendChild(controls);
14871
14872 // Append DOM elements
14873 if (obj.options.position == 'bottom') {
14874 el.appendChild(obj.content);
14875 el.appendChild(header);
14876 } else {
14877 el.appendChild(header);
14878 el.appendChild(obj.content);
14879 }
14880
14881 // New button
14882 if (obj.options.allowCreate == true) {
14883 add = document.createElement('div');
14884 add.className = 'jtabs-add';
14885 add.onclick = function() {
14886 obj.create();
14887 }
14888 controls.appendChild(add);
14889 }
14890
14891 prev = document.createElement('div');
14892 prev.className = 'jtabs-prev';
14893 prev.onclick = function() {
14894 updateControls(obj.headers.scrollLeft - obj.headers.offsetWidth);
14895 }
14896 controls.appendChild(prev);
14897
14898 next = document.createElement('div');
14899 next.className = 'jtabs-next';
14900 next.onclick = function() {
14901 updateControls(obj.headers.scrollLeft + obj.headers.offsetWidth);
14902 }
14903 controls.appendChild(next);
14904
14905 // Data
14906 for (var i = 0; i < obj.options.data.length; i++) {
14907 // Title
14908 if (obj.options.data[i].titleElement) {
14909 var headerItem = obj.options.data[i].titleElement;
14910 } else {
14911 var headerItem = document.createElement('div');
14912 }
14913 // Icon
14914 if (obj.options.data[i].icon) {
14915 var iconContainer = document.createElement('div');
14916 var icon = document.createElement('i');
14917 icon.classList.add('material-icons');
14918 icon.textContent = obj.options.data[i].icon;
14919 iconContainer.appendChild(icon);
14920 headerItem.appendChild(iconContainer);
14921 }
14922 // Title
14923 if (obj.options.data[i].title) {
14924 var title = document.createTextNode(obj.options.data[i].title);
14925 headerItem.appendChild(title);
14926 }
14927 // Width
14928 if (obj.options.data[i].width) {
14929 headerItem.style.width = obj.options.data[i].width;
14930 }
14931 // Content
14932 if (obj.options.data[i].contentElement) {
14933 var contentItem = obj.options.data[i].contentElement;
14934 } else {
14935 var contentItem = document.createElement('div');
14936 contentItem.innerHTML = obj.options.data[i].content;
14937 }
14938 obj.headers.appendChild(headerItem);
14939 obj.content.appendChild(contentItem);
14940 }
14941
14942 // Animation
14943 border = document.createElement('div');
14944 border.className = 'jtabs-border';
14945 obj.headers.appendChild(border);
14946
14947 if (obj.options.animation) {
14948 el.classList.add('jtabs-animation');
14949 }
14950
14951 // Events
14952 headersClickHandler = function(e) {
14953 if (e.target.parentNode.classList.contains('jtabs-headers')) {
14954 var target = e.target;
14955 } else {
14956 if (e.target.tagName == 'I') {
14957 var target = e.target.parentNode.parentNode;
14958 } else {
14959 var target = e.target.parentNode;
14960 }
14961 }
14962
14963 var index = obj.selectIndex(target);
14964
14965 if (typeof(obj.options.onclick) == 'function') {
14966 obj.options.onclick(el, obj, index, obj.headers.children[index], obj.content.children[index]);
14967 }
14968 };
14969 obj.headers.addEventListener("click", headersClickHandler);
14970
14971 headersContextMenuHandler = function(e) {
14972 obj.selectIndex(e.target);
14973 };
14974 obj.headers.addEventListener("contextmenu", headersContextMenuHandler);
14975
14976 if (obj.headers.children.length) {
14977 // Open first tab
14978 obj.open(0);
14979 }
14980
14981 // Update controls
14982 setTimeout(() => {
14983 updateControls(0);
14984 })
14985
14986 if (obj.options.allowChangePosition == true) {
14987 Sorting(obj.headers, {
14988 direction: 1,
14989 ondrop: function(a,b,c) {
14990 obj.updatePosition(b,c);
14991 },
14992 });
14993 }
14994
14995 if (typeof(obj.options.onload) == 'function') {
14996 obj.options.onload(el, obj);
14997 }
14998 }
14999
15000 // Loading existing nodes as the data
15001 if (el.children[0] && el.children[0].children.length) {
15002 // Create from existing elements
15003 for (var i = 0; i < el.children[0].children.length; i++) {
15004 var item = obj.options.data && obj.options.data[i] ? obj.options.data[i] : {};
15005
15006 if (el.children[1] && el.children[1].children[i]) {
15007 item.titleElement = el.children[0].children[i];
15008 item.contentElement = el.children[1].children[i];
15009 } else {
15010 item.contentElement = el.children[0].children[i];
15011 }
15012
15013 obj.options.data[i] = item;
15014 }
15015 }
15016
15017 // Remote controller flag
15018 var loadingRemoteData = false;
15019
15020 // Create from data
15021 if (obj.options.data) {
15022 // Append children
15023 for (var i = 0; i < obj.options.data.length; i++) {
15024 if (obj.options.data[i].url) {
15025 ajax({
15026 url: obj.options.data[i].url,
15027 type: 'GET',
15028 dataType: 'text/html',
15029 index: i,
15030 success: function(result) {
15031 obj.options.data[this.index].content = result;
15032 },
15033 complete: function() {
15034 obj.init();
15035 }
15036 });
15037
15038 // Flag loading
15039 loadingRemoteData = true;
15040 }
15041 }
15042 }
15043
15044 if (! loadingRemoteData) {
15045 obj.init();
15046 }
15047
15048 /**
15049 * Destroy the tabs instance and release all resources
15050 */
15051 obj.destroy = function() {
15052 // Remove event listeners from headers
15053 if (obj.headers) {
15054 if (headersClickHandler) {
15055 obj.headers.removeEventListener('click', headersClickHandler);
15056 }
15057 if (headersContextMenuHandler) {
15058 obj.headers.removeEventListener('contextmenu', headersContextMenuHandler);
15059 }
15060 }
15061
15062 // Clear onclick handlers
15063 if (prev) {
15064 prev.onclick = null;
15065 }
15066 if (next) {
15067 next.onclick = null;
15068 }
15069 if (add) {
15070 add.onclick = null;
15071 }
15072
15073 // Remove DOM elements
15074 if (header && header.parentNode) {
15075 header.parentNode.removeChild(header);
15076 }
15077 if (obj.content && obj.content.parentNode) {
15078 obj.content.parentNode.removeChild(obj.content);
15079 }
15080
15081 // Remove class from element
15082 el.classList.remove('jtabs');
15083 el.classList.remove('jtabs-animation');
15084 el.classList.remove('jtabs-modern');
15085
15086 // Remove instance reference
15087 delete el.tabs;
15088
15089 // Clear options callbacks to release closures
15090 if (obj.options) {
15091 obj.options.onclick = null;
15092 obj.options.onload = null;
15093 obj.options.onchange = null;
15094 obj.options.oncreate = null;
15095 obj.options.ondelete = null;
15096 obj.options.onbeforecreate = null;
15097 obj.options.onchangeposition = null;
15098 }
15099
15100 // Clear references
15101 obj.headers = null;
15102 obj.content = null;
15103 header = null;
15104 controls = null;
15105 prev = null;
15106 next = null;
15107 border = null;
15108 add = null;
15109 headersClickHandler = null;
15110 headersContextMenuHandler = null;
15111 }
15112
15113 el.tabs = obj;
15114
15115 return obj;
15116}
15117;// CONCATENATED MODULE: ./src/plugins/color.js
15118
15119
15120
15121
15122
15123
15124function Color(el, options) {
15125 // Already created, update options
15126 if (el.color) {
15127 return el.color.setOptions(options, true);
15128 }
15129
15130 // New instance
15131 var obj = { type: 'color' };
15132 obj.options = {};
15133
15134 var container = null;
15135 var backdrop = null;
15136 var content = null;
15137 var resetButton = null;
15138 var closeButton = null;
15139 var tabs = null;
15140 var jsuitesTabs = null;
15141
15142 /**
15143 * Update options
15144 */
15145 obj.setOptions = function(options, reset) {
15146 /**
15147 * @typedef {Object} defaults
15148 * @property {(string|Array)} value - Initial value of the compontent
15149 * @property {string} placeholder - The default instruction text on the element
15150 * @property {requestCallback} onchange - Method to be execute after any changes on the element
15151 * @property {requestCallback} onclose - Method to be execute when the element is closed
15152 * @property {string} doneLabel - Label for button done
15153 * @property {string} resetLabel - Label for button reset
15154 * @property {string} resetValue - Value for button reset
15155 * @property {Bool} showResetButton - Active or note for button reset - default false
15156 */
15157 var defaults = {
15158 placeholder: '',
15159 value: null,
15160 onopen: null,
15161 onclose: null,
15162 onchange: null,
15163 closeOnChange: true,
15164 palette: null,
15165 position: null,
15166 doneLabel: 'Done',
15167 resetLabel: 'Reset',
15168 fullscreen: false,
15169 opened: false,
15170 }
15171
15172 if (! options) {
15173 options = {};
15174 }
15175
15176 if (options && ! options.palette) {
15177 // Default palette
15178 options.palette = palette();
15179 }
15180
15181 // Loop through our object
15182 for (var property in defaults) {
15183 if (options && options.hasOwnProperty(property)) {
15184 obj.options[property] = options[property];
15185 } else {
15186 if (typeof(obj.options[property]) == 'undefined' || reset === true) {
15187 obj.options[property] = defaults[property];
15188 }
15189 }
15190 }
15191
15192 // Update the text of the controls, if they have already been created
15193 if (resetButton) {
15194 resetButton.innerHTML = obj.options.resetLabel;
15195 }
15196 if (closeButton) {
15197 closeButton.innerHTML = obj.options.doneLabel;
15198 }
15199
15200 // Update the pallete
15201 if (obj.options.palette && jsuitesTabs) {
15202 jsuitesTabs.updateContent(0, table());
15203 }
15204
15205 // Value
15206 if (typeof obj.options.value === 'string') {
15207 el.value = obj.options.value;
15208 if (el.tagName === 'INPUT') {
15209 el.style.color = el.value;
15210 el.style.backgroundColor = el.value;
15211 }
15212 }
15213
15214 // Placeholder
15215 if (obj.options.placeholder) {
15216 el.setAttribute('placeholder', obj.options.placeholder);
15217 } else {
15218 if (el.getAttribute('placeholder')) {
15219 el.removeAttribute('placeholder');
15220 }
15221 }
15222
15223 return obj;
15224 }
15225
15226 obj.select = function(color) {
15227 // Remove current selected mark
15228 var selected = container.querySelector('.jcolor-selected');
15229 if (selected) {
15230 selected.classList.remove('jcolor-selected');
15231 }
15232
15233 // Mark cell as selected
15234 if (obj.values[color]) {
15235 obj.values[color].classList.add('jcolor-selected');
15236 }
15237
15238 obj.options.value = color;
15239 }
15240
15241 /**
15242 * Open color pallete
15243 */
15244 obj.open = function() {
15245 if (! container.classList.contains('jcolor-focus')) {
15246 // Start tracking
15247 tracking(obj, true);
15248
15249 // Show color picker
15250 container.classList.add('jcolor-focus');
15251
15252 // Select current color
15253 if (obj.options.value) {
15254 obj.select(obj.options.value);
15255 }
15256
15257 // Reset margin
15258 content.style.marginTop = '';
15259 content.style.marginLeft = '';
15260
15261 var rectContent = content.getBoundingClientRect();
15262 var availableWidth = helpers.getWindowWidth();
15263 var availableHeight = helpers.getWindowHeight();
15264
15265 if (availableWidth < 800 || obj.options.fullscreen == true) {
15266 content.classList.add('jcolor-fullscreen');
15267 animation.slideBottom(content, 1);
15268 backdrop.style.display = 'block';
15269 } else {
15270 if (content.classList.contains('jcolor-fullscreen')) {
15271 content.classList.remove('jcolor-fullscreen');
15272 backdrop.style.display = '';
15273 }
15274
15275 if (obj.options.position) {
15276 content.style.position = 'fixed';
15277 } else {
15278 content.style.position = '';
15279 }
15280
15281 if (rectContent.left + rectContent.width > availableWidth) {
15282 content.style.marginLeft = -1 * (rectContent.left + rectContent.width - (availableWidth - 20)) + 'px';
15283 }
15284 if (rectContent.top + rectContent.height > availableHeight) {
15285 content.style.marginTop = -1 * (rectContent.top + rectContent.height - (availableHeight - 20)) + 'px';
15286 }
15287 }
15288
15289
15290 if (typeof(obj.options.onopen) == 'function') {
15291 obj.options.onopen(el, obj);
15292 }
15293
15294 jsuitesTabs.setBorder(jsuitesTabs.getActive());
15295
15296 // Update sliders
15297 if (obj.options.value) {
15298 var rgb = HexToRgb(obj.options.value);
15299
15300 rgbInputs.forEach(function(rgbInput, index) {
15301 rgbInput.value = rgb[index];
15302 rgbInput.dispatchEvent(new Event('input'));
15303 });
15304 }
15305 }
15306 }
15307
15308 /**
15309 * Close color pallete
15310 */
15311 obj.close = function(ignoreEvents) {
15312 if (container && container.classList.contains('jcolor-focus')) {
15313 // Remove focus
15314 container.classList.remove('jcolor-focus');
15315 // Make sure backdrop is hidden
15316 if (backdrop) {
15317 backdrop.style.display = '';
15318 }
15319 // Call related events
15320 if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
15321 obj.options.onclose(el, obj);
15322 }
15323 // Stop the object
15324 tracking(obj, false);
15325 }
15326
15327 return obj.options.value ? obj.options.value : null;
15328 }
15329
15330 /**
15331 * Set value
15332 */
15333 obj.setValue = function(color) {
15334 if (! color) {
15335 color = '';
15336 }
15337
15338 if (color != obj.options.value) {
15339 obj.options.value = color;
15340 slidersResult = color;
15341
15342 // Remove current selecded mark
15343 obj.select(color);
15344
15345 // Onchange
15346 if (typeof(obj.options.onchange) == 'function') {
15347 obj.options.onchange(el, color, obj);
15348 }
15349
15350 // Changes
15351 if (el.value != obj.options.value) {
15352 // Set input value
15353 el.value = obj.options.value;
15354 if (el.tagName === 'INPUT') {
15355 el.style.color = el.value;
15356 el.style.backgroundColor = el.value;
15357 }
15358
15359 // Element onchange native
15360 if (typeof(el.oninput) == 'function') {
15361 el.oninput({
15362 type: 'input',
15363 target: el,
15364 value: el.value
15365 });
15366 }
15367 }
15368
15369 if (obj.options.closeOnChange == true) {
15370 obj.close();
15371 }
15372 }
15373 }
15374
15375 /**
15376 * Get value
15377 */
15378 obj.getValue = function() {
15379 return obj.options.value;
15380 }
15381
15382 var backdropClickControl = false;
15383
15384 // Converts a number in decimal to hexadecimal
15385 var decToHex = function(num) {
15386 var hex = num.toString(16);
15387 return hex.length === 1 ? "0" + hex : hex;
15388 }
15389
15390 // Converts a color in rgb to hexadecimal
15391 var rgbToHex = function(r, g, b) {
15392 return "#" + decToHex(r) + decToHex(g) + decToHex(b);
15393 }
15394
15395 // Converts a number in hexadecimal to decimal
15396 var hexToDec = function(hex) {
15397 return parseInt('0x' + hex);
15398 }
15399
15400 // Converts a color in hexadecimal to rgb
15401 var HexToRgb = function(hex) {
15402 return [hexToDec(hex.substr(1, 2)), hexToDec(hex.substr(3, 2)), hexToDec(hex.substr(5, 2))]
15403 }
15404
15405 var table = function() {
15406 // Content of the first tab
15407 var tableContainer = document.createElement('div');
15408 tableContainer.className = 'jcolor-grid';
15409
15410 // Cells
15411 obj.values = [];
15412
15413 // Table pallete
15414 var t = document.createElement('table');
15415 t.setAttribute('cellpadding', '7');
15416 t.setAttribute('cellspacing', '0');
15417
15418 for (var j = 0; j < obj.options.palette.length; j++) {
15419 var tr = document.createElement('tr');
15420 for (var i = 0; i < obj.options.palette[j].length; i++) {
15421 var td = document.createElement('td');
15422 var color = obj.options.palette[j][i];
15423 if (color.length < 7 && color.substr(0,1) !== '#') {
15424 color = '#' + color;
15425 }
15426 td.style.backgroundColor = color;
15427 td.setAttribute('data-value', color);
15428 td.innerHTML = '';
15429 tr.appendChild(td);
15430
15431 // Selected color
15432 if (obj.options.value == color) {
15433 td.classList.add('jcolor-selected');
15434 }
15435
15436 // Possible values
15437 obj.values[color] = td;
15438 }
15439 t.appendChild(tr);
15440 }
15441
15442 // Append to the table
15443 tableContainer.appendChild(t);
15444
15445 return tableContainer;
15446 }
15447
15448 // Canvas where the image will be rendered
15449 var canvas = document.createElement('canvas');
15450 canvas.width = 200;
15451 canvas.height = 160;
15452 var context = canvas.getContext("2d");
15453
15454 var resizeCanvas = function() {
15455 // Specifications necessary to correctly obtain colors later in certain positions
15456 var m = tabs.firstChild.getBoundingClientRect();
15457 canvas.width = m.width - 14;
15458 gradient()
15459 }
15460
15461 var gradient = function() {
15462 var g = context.createLinearGradient(0, 0, canvas.width, 0);
15463 // Create color gradient
15464 g.addColorStop(0, "rgb(255,0,0)");
15465 g.addColorStop(0.15, "rgb(255,0,255)");
15466 g.addColorStop(0.33, "rgb(0,0,255)");
15467 g.addColorStop(0.49, "rgb(0,255,255)");
15468 g.addColorStop(0.67, "rgb(0,255,0)");
15469 g.addColorStop(0.84, "rgb(255,255,0)");
15470 g.addColorStop(1, "rgb(255,0,0)");
15471 context.fillStyle = g;
15472 context.fillRect(0, 0, canvas.width, canvas.height);
15473 g = context.createLinearGradient(0, 0, 0, canvas.height);
15474 g.addColorStop(0, "rgba(255,255,255,1)");
15475 g.addColorStop(0.5, "rgba(255,255,255,0)");
15476 g.addColorStop(0.5, "rgba(0,0,0,0)");
15477 g.addColorStop(1, "rgba(0,0,0,1)");
15478 context.fillStyle = g;
15479 context.fillRect(0, 0, canvas.width, canvas.height);
15480 }
15481
15482 var hsl = function() {
15483 var element = document.createElement('div');
15484 element.className = "jcolor-hsl";
15485
15486 var point = document.createElement('div');
15487 point.className = 'jcolor-point';
15488
15489 var div = document.createElement('div');
15490 div.appendChild(canvas);
15491 div.appendChild(point);
15492 element.appendChild(div);
15493
15494 // Moves the marquee point to the specified position
15495 var update = function(buttons, x, y) {
15496 if (buttons === 1) {
15497 var rect = element.getBoundingClientRect();
15498 var left = x - rect.left;
15499 var top = y - rect.top;
15500 if (left < 0) {
15501 left = 0;
15502 }
15503 if (top < 0) {
15504 top = 0;
15505 }
15506 if (left > rect.width) {
15507 left = rect.width;
15508 }
15509 if (top > rect.height) {
15510 top = rect.height;
15511 }
15512 point.style.left = left + 'px';
15513 point.style.top = top + 'px';
15514 var pixel = context.getImageData(left, top, 1, 1).data;
15515 slidersResult = rgbToHex(pixel[0], pixel[1], pixel[2]);
15516 }
15517 }
15518
15519 // Applies the point's motion function to the div that contains it
15520 element.addEventListener('mousedown', function(e) {
15521 update(e.buttons, e.clientX, e.clientY);
15522 });
15523
15524 element.addEventListener('mousemove', function(e) {
15525 update(e.buttons, e.clientX, e.clientY);
15526 });
15527
15528 element.addEventListener('touchmove', function(e) {
15529 update(1, e.changedTouches[0].clientX, e.changedTouches[0].clientY);
15530 });
15531
15532 return element;
15533 }
15534
15535 var slidersResult = '';
15536
15537 var rgbInputs = [];
15538
15539 var changeInputColors = function() {
15540 if (slidersResult !== '') {
15541 for (var j = 0; j < rgbInputs.length; j++) {
15542 var currentColor = HexToRgb(slidersResult);
15543
15544 currentColor[j] = 0;
15545
15546 var newGradient = 'linear-gradient(90deg, rgb(';
15547 newGradient += currentColor.join(', ');
15548 newGradient += '), rgb(';
15549
15550 currentColor[j] = 255;
15551
15552 newGradient += currentColor.join(', ');
15553 newGradient += '))';
15554
15555 rgbInputs[j].style.backgroundImage = newGradient;
15556 }
15557 }
15558 }
15559
15560 var sliders = function() {
15561 // Content of the third tab
15562 var slidersElement = document.createElement('div');
15563 slidersElement.className = 'jcolor-sliders';
15564
15565 var slidersBody = document.createElement('div');
15566
15567 // Creates a range-type input with the specified name
15568 var createSliderInput = function(name) {
15569 var inputContainer = document.createElement('div');
15570 inputContainer.className = 'jcolor-sliders-input-container';
15571
15572 var label = document.createElement('label');
15573 label.innerText = name;
15574
15575 var subContainer = document.createElement('div');
15576 subContainer.className = 'jcolor-sliders-input-subcontainer';
15577
15578 var input = document.createElement('input');
15579 input.type = 'range';
15580 input.min = 0;
15581 input.max = 255;
15582 input.value = 0;
15583
15584 input.setAttribute('aria-label', "Color value");
15585 input.setAttribute('aria-valuemin', "0");
15586 input.setAttribute('aria-valuemax', "255");
15587 input.setAttribute('aria-valuenow', "0");
15588
15589 inputContainer.appendChild(label);
15590 subContainer.appendChild(input);
15591
15592 var value = document.createElement('div');
15593 value.innerText = input.value;
15594
15595 input.addEventListener('input', function() {
15596 value.innerText = input.value;
15597 });
15598
15599 subContainer.appendChild(value);
15600 inputContainer.appendChild(subContainer);
15601
15602 slidersBody.appendChild(inputContainer);
15603
15604 return input;
15605 }
15606
15607 // Creates red, green and blue inputs
15608 rgbInputs = [
15609 createSliderInput('Red'),
15610 createSliderInput('Green'),
15611 createSliderInput('Blue'),
15612 ];
15613
15614 slidersElement.appendChild(slidersBody);
15615
15616 // Element that prints the current color
15617 var slidersResultColor = document.createElement('div');
15618 slidersResultColor.className = 'jcolor-sliders-final-color';
15619
15620 var resultElement = document.createElement('div');
15621 resultElement.style.visibility = 'hidden';
15622 resultElement.innerText = 'a';
15623 slidersResultColor.appendChild(resultElement)
15624
15625 // Update the element that prints the current color
15626 var updateResult = function() {
15627 var resultColor = rgbToHex(parseInt(rgbInputs[0].value), parseInt(rgbInputs[1].value), parseInt(rgbInputs[2].value));
15628
15629 resultElement.innerText = resultColor;
15630 resultElement.style.color = resultColor;
15631 resultElement.style.removeProperty('visibility');
15632
15633 slidersResult = resultColor;
15634 }
15635
15636 // Apply the update function to color inputs
15637 rgbInputs.forEach(function(rgbInput) {
15638 rgbInput.addEventListener('input', function() {
15639 updateResult();
15640 changeInputColors();
15641 });
15642 });
15643
15644 slidersElement.appendChild(slidersResultColor);
15645
15646 return slidersElement;
15647 }
15648
15649 var init = function() {
15650 // Initial options
15651 obj.setOptions(options);
15652
15653 // Add a proper input tag when the element is an input
15654 if (el.tagName == 'INPUT') {
15655 el.classList.add('jcolor-input');
15656 el.readOnly = true;
15657 }
15658
15659 // Table container
15660 container = document.createElement('div');
15661 container.className = 'jcolor';
15662
15663 // Table container
15664 backdrop = document.createElement('div');
15665 backdrop.className = 'jcolor-backdrop';
15666 container.appendChild(backdrop);
15667
15668 // Content
15669 content = document.createElement('div');
15670 content.className = 'jcolor-content';
15671
15672 // Controls
15673 var controls = document.createElement('div');
15674 controls.className = 'jcolor-controls';
15675 content.appendChild(controls);
15676
15677 // Reset button
15678 resetButton = document.createElement('div');
15679 resetButton.className = 'jcolor-reset';
15680 resetButton.innerHTML = obj.options.resetLabel;
15681 controls.appendChild(resetButton);
15682
15683 // Close button
15684 closeButton = document.createElement('div');
15685 closeButton.className = 'jcolor-close';
15686 closeButton.innerHTML = obj.options.doneLabel;
15687 controls.appendChild(closeButton);
15688
15689 // Element that will be used to create the tabs
15690 tabs = document.createElement('div');
15691 content.appendChild(tabs);
15692
15693 // Starts the jSuites tabs component
15694 jsuitesTabs = Tabs(tabs, {
15695 animation: true,
15696 data: [
15697 {
15698 title: 'Grid',
15699 contentElement: table(),
15700 },
15701 {
15702 title: 'Spectrum',
15703 contentElement: hsl(),
15704 },
15705 {
15706 title: 'Sliders',
15707 contentElement: sliders(),
15708 }
15709 ],
15710 onchange: function(element, instance, index) {
15711 if (index === 1) {
15712 resizeCanvas();
15713 } else {
15714 var color = slidersResult !== '' ? slidersResult : obj.getValue();
15715
15716 if (index === 2 && color) {
15717 var rgb = HexToRgb(color);
15718
15719 rgbInputs.forEach(function(rgbInput, index) {
15720 rgbInput.value = rgb[index];
15721 rgbInput.dispatchEvent(new Event('input'));
15722 });
15723 }
15724 }
15725 },
15726 palette: 'modern',
15727 });
15728
15729 container.appendChild(content);
15730
15731 // Insert picker after the element
15732 if (el.tagName == 'INPUT') {
15733 el.parentNode.insertBefore(container, el.nextSibling);
15734 } else {
15735 el.appendChild(container);
15736 }
15737
15738 containerClickHandler = function(e) {
15739 if (e.target.tagName == 'TD') {
15740 var value = e.target.getAttribute('data-value');
15741 if (value) {
15742 obj.setValue(value);
15743 }
15744 } else if (e.target.classList.contains('jcolor-reset')) {
15745 obj.setValue('');
15746 obj.close();
15747 } else if (e.target.classList.contains('jcolor-close')) {
15748 if (jsuitesTabs.getActive() > 0) {
15749 obj.setValue(slidersResult);
15750 }
15751 obj.close();
15752 } else if (e.target.classList.contains('jcolor-backdrop')) {
15753 obj.close();
15754 } else {
15755 obj.open();
15756 }
15757 };
15758 container.addEventListener("click", containerClickHandler);
15759
15760 /**
15761 * If element is focus open the picker
15762 */
15763 elMouseupHandler = function(e) {
15764 obj.open();
15765 };
15766 el.addEventListener("mouseup", elMouseupHandler);
15767
15768 // If the picker is open on the spectrum tab, it changes the canvas size when the window size is changed
15769 windowResizeHandler = function() {
15770 if (container.classList.contains('jcolor-focus') && jsuitesTabs.getActive() == 1) {
15771 resizeCanvas();
15772 }
15773 };
15774 window.addEventListener('resize', windowResizeHandler);
15775
15776 // Default opened
15777 if (obj.options.opened == true) {
15778 obj.open();
15779 }
15780
15781 // Change
15782 el.change = obj.setValue;
15783
15784 // Global generic value handler
15785 el.val = function(val) {
15786 if (val === undefined) {
15787 return obj.getValue();
15788 } else {
15789 obj.setValue(val);
15790 }
15791 }
15792
15793 // Keep object available from the node
15794 el.color = obj;
15795
15796 // Container shortcut
15797 container.color = obj;
15798 }
15799
15800 obj.toHex = function(rgb) {
15801 var hex = function(x) {
15802 return ("0" + parseInt(x).toString(16)).slice(-2);
15803 }
15804 if (rgb) {
15805 if (/^#[0-9A-F]{6}$/i.test(rgb)) {
15806 return rgb;
15807 } else {
15808 rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
15809 if (rgb && rgb.length) {
15810 return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
15811 } else {
15812 return "";
15813 }
15814 }
15815 }
15816 }
15817
15818 // Store event handler references for cleanup
15819 var containerClickHandler = null;
15820 var elMouseupHandler = null;
15821 var windowResizeHandler = null;
15822
15823 /**
15824 * Destroy the color picker instance and release all resources
15825 */
15826 obj.destroy = function() {
15827 // Close if open (removes from tracking)
15828 obj.close(true);
15829
15830 // Remove event listeners
15831 if (container && containerClickHandler) {
15832 container.removeEventListener('click', containerClickHandler);
15833 }
15834 if (el && elMouseupHandler) {
15835 el.removeEventListener('mouseup', elMouseupHandler);
15836 }
15837 if (windowResizeHandler) {
15838 window.removeEventListener('resize', windowResizeHandler);
15839 }
15840
15841 // Destroy the tabs component if it has destroy method
15842 if (jsuitesTabs && typeof jsuitesTabs.destroy === 'function') {
15843 jsuitesTabs.destroy();
15844 }
15845
15846 // Clear rgbInputs references
15847 rgbInputs = [];
15848
15849 // Remove container from DOM
15850 if (container && container.parentNode) {
15851 container.parentNode.removeChild(container);
15852 }
15853
15854 // Clean up element
15855 if (el.tagName === 'INPUT') {
15856 el.classList.remove('jcolor-input');
15857 el.readOnly = false;
15858 el.style.color = '';
15859 el.style.backgroundColor = '';
15860 }
15861
15862 // Remove instance properties from el
15863 delete el.color;
15864 delete el.change;
15865 delete el.val;
15866
15867 // Clear options callbacks to release closures
15868 if (obj.options) {
15869 obj.options.onchange = null;
15870 obj.options.onclose = null;
15871 obj.options.onopen = null;
15872 obj.options.onload = null;
15873 }
15874
15875 // Clear references
15876 container = null;
15877 backdrop = null;
15878 content = null;
15879 resetButton = null;
15880 closeButton = null;
15881 tabs = null;
15882 jsuitesTabs = null;
15883 }
15884
15885 init();
15886
15887 return obj;
15888}
15889;// CONCATENATED MODULE: ./src/plugins/contextmenu.js
15890
15891
15892
15893function Contextmenu() {
15894
15895 var Component = function(el, options) {
15896 // New instance
15897 var obj = {type: 'contextmenu'};
15898 obj.options = {};
15899
15900 // Default configuration
15901 var defaults = {
15902 items: null,
15903 onclick: null,
15904 };
15905
15906 // Loop through our object
15907 for (var property in defaults) {
15908 if (options && options.hasOwnProperty(property)) {
15909 obj.options[property] = options[property];
15910 } else {
15911 obj.options[property] = defaults[property];
15912 }
15913 }
15914
15915 // Class definition
15916 el.classList.add('jcontextmenu');
15917
15918 /**
15919 * Open contextmenu
15920 */
15921 obj.open = function (e, items) {
15922 if (items) {
15923 // Update content
15924 obj.options.items = items;
15925 // Create items
15926 obj.create(items);
15927 }
15928
15929 // Close current contextmenu
15930 if (Component.current) {
15931 Component.current.close();
15932 }
15933
15934 // Add to the opened components monitor
15935 tracking(obj, true);
15936
15937 // Show context menu
15938 el.classList.add('jcontextmenu-focus');
15939
15940 // Current
15941 Component.current = obj;
15942
15943 // Coordinates
15944 if ((obj.options.items && obj.options.items.length > 0) || el.children.length) {
15945 if (e.target) {
15946 if (e.changedTouches && e.changedTouches[0]) {
15947 x = e.changedTouches[0].clientX;
15948 y = e.changedTouches[0].clientY;
15949 } else {
15950 var x = e.clientX;
15951 var y = e.clientY;
15952 }
15953 } else {
15954 var x = e.x;
15955 var y = e.y;
15956 }
15957
15958 var rect = el.getBoundingClientRect();
15959
15960 if (window.innerHeight < y + rect.height) {
15961 var h = y - rect.height;
15962 if (h < 0) {
15963 h = 0;
15964 }
15965 el.style.top = h + 'px';
15966 } else {
15967 el.style.top = y + 'px';
15968 }
15969
15970 if (window.innerWidth < x + rect.width) {
15971 if (x - rect.width > 0) {
15972 el.style.left = (x - rect.width) + 'px';
15973 } else {
15974 el.style.left = '10px';
15975 }
15976 } else {
15977 el.style.left = x + 'px';
15978 }
15979 }
15980 }
15981
15982 obj.isOpened = function () {
15983 return el.classList.contains('jcontextmenu-focus') ? true : false;
15984 }
15985
15986 /**
15987 * Close menu
15988 */
15989 obj.close = function () {
15990 if (el.classList.contains('jcontextmenu-focus')) {
15991 el.classList.remove('jcontextmenu-focus');
15992 }
15993 tracking(obj, false);
15994 }
15995
15996 /**
15997 * Create items based on the declared objectd
15998 * @param {object} items - List of object
15999 */
16000 obj.create = function (items) {
16001 // Update content
16002 el.innerHTML = '';
16003
16004 // Add header contextmenu
16005 var itemHeader = createHeader();
16006 el.appendChild(itemHeader);
16007
16008 // Append items
16009 for (var i = 0; i < items.length; i++) {
16010 var itemContainer = createItemElement(items[i]);
16011 el.appendChild(itemContainer);
16012 }
16013 }
16014
16015 /**
16016 * createHeader for context menu
16017 * @private
16018 * @returns {HTMLElement}
16019 */
16020 function createHeader() {
16021 var header = document.createElement('div');
16022 header.classList.add("header");
16023 header.addEventListener("click", function (e) {
16024 e.preventDefault();
16025 e.stopPropagation();
16026 });
16027 var title = document.createElement('a');
16028 title.classList.add("title");
16029 title.innerHTML = dictionary.translate("Menu");
16030
16031 header.appendChild(title);
16032
16033 var closeButton = document.createElement('a');
16034 closeButton.classList.add("close");
16035 closeButton.innerHTML = dictionary.translate("close");
16036 closeButton.addEventListener("click", function (e) {
16037 obj.close();
16038 });
16039
16040 header.appendChild(closeButton);
16041
16042 return header;
16043 }
16044
16045 /**
16046 * Private function for create a new Item element
16047 * @param {type} item
16048 * @returns {jsuitesL#15.jSuites.contextmenu.createItemElement.itemContainer}
16049 */
16050 function createItemElement(item) {
16051 if (item.type && (item.type == 'line' || item.type == 'divisor')) {
16052 var itemContainer = document.createElement('hr');
16053 } else {
16054 var itemContainer = document.createElement('div');
16055 var itemText = document.createElement('a');
16056 itemText.innerHTML = item.title;
16057
16058 if (item.tooltip) {
16059 itemContainer.setAttribute('title', item.tooltip);
16060 }
16061
16062 if (item.icon) {
16063 itemContainer.setAttribute('data-icon', item.icon);
16064 }
16065
16066 if (item.id) {
16067 itemContainer.id = item.id;
16068 }
16069
16070 if (item.disabled) {
16071 itemContainer.className = 'jcontextmenu-disabled';
16072 } else if (item.onclick) {
16073 let method = item.onclick;
16074 itemContainer.addEventListener("mousedown", function (e) {
16075 e.preventDefault();
16076 });
16077 itemContainer.addEventListener("mouseup", function (e) {
16078 method(this, e);
16079 });
16080 }
16081 itemContainer.appendChild(itemText);
16082
16083 if (item.submenu) {
16084 var itemIconSubmenu = document.createElement('span');
16085 itemIconSubmenu.innerHTML = "&#9658;";
16086 itemContainer.appendChild(itemIconSubmenu);
16087 itemContainer.classList.add('jcontexthassubmenu');
16088 var el_submenu = document.createElement('div');
16089 // Class definition
16090 el_submenu.classList.add('jcontextmenu');
16091 // Focusable
16092 el_submenu.setAttribute('tabindex', '900');
16093
16094 // Append items
16095 var submenu = item.submenu;
16096 for (var i = 0; i < submenu.length; i++) {
16097 var itemContainerSubMenu = createItemElement(submenu[i]);
16098 el_submenu.appendChild(itemContainerSubMenu);
16099 }
16100
16101 itemContainer.appendChild(el_submenu);
16102
16103 // Submenu positioning logic:
16104 // Case 1: Default (enough space to the right) - submenu opens to the right of the parent menu item.
16105 // Case 2: Not enough space to the right, but enough to the left - submenu opens to the left of the parent menu item.
16106 // Case 3: Not enough space on either side (e.g., very narrow viewport) - submenu opens below the parent menu item.
16107 itemContainer.addEventListener('mouseenter', function () {
16108 // Reset to default
16109 el_submenu.style.left = '';
16110 el_submenu.style.right = '';
16111 el_submenu.style.minWidth = itemContainer.offsetWidth + 'px';
16112
16113 // Temporarily show submenu to measure
16114 el_submenu.style.display = 'block';
16115 el_submenu.style.opacity = '0';
16116 el_submenu.style.pointerEvents = 'none';
16117
16118 // Use getBoundingClientRect to determine position
16119 var parentRect = itemContainer.getBoundingClientRect();
16120 var submenuRect = el_submenu.getBoundingClientRect();
16121 var viewportWidth = window.innerWidth || document.documentElement.clientWidth;
16122
16123 // Calculate the right edge if rendered to the right
16124 var rightEdge = parentRect.right + submenuRect.width;
16125 var leftEdge = parentRect.left - submenuRect.width;
16126
16127 // If rendering to the right would overflow, render to the left
16128 if (rightEdge > viewportWidth && leftEdge >= 0) {
16129 el_submenu.style.left = 'auto';
16130 el_submenu.style.right = '99%';
16131 }
16132 // If both right and left would overflow, render to the right of the left border (worst case)
16133 else if (rightEdge > viewportWidth && leftEdge < 0) {
16134 el_submenu.style.left = '32px';
16135 el_submenu.style.right = 'auto';
16136 el_submenu.style.top = '100%';
16137 }
16138 // Default: render to the right
16139 else {
16140 el_submenu.style.left = '99%';
16141 el_submenu.style.right = 'auto';
16142 }
16143
16144 // Restore visibility
16145 el_submenu.style.opacity = '';
16146 el_submenu.style.pointerEvents = '';
16147 el_submenu.style.display = '';
16148 });
16149
16150 // Also reset submenu position on mouseleave to avoid stale styles
16151 itemContainer.addEventListener('mouseleave', function () {
16152 el_submenu.style.left = '';
16153 el_submenu.style.right = '';
16154 el_submenu.style.minWidth = '';
16155 });
16156 } else if (item.shortcut) {
16157 var itemShortCut = document.createElement('span');
16158 itemShortCut.innerHTML = item.shortcut;
16159 itemContainer.appendChild(itemShortCut);
16160 }
16161 }
16162 return itemContainer;
16163 }
16164
16165 if (typeof (obj.options.onclick) == 'function') {
16166 el.addEventListener('click', function (e) {
16167 obj.options.onclick(obj, e);
16168 });
16169 }
16170
16171 // Create items
16172 if (obj.options.items) {
16173 obj.create(obj.options.items);
16174 }
16175
16176 window.addEventListener("mousewheel", function () {
16177 obj.close();
16178 });
16179
16180 el.contextmenu = obj;
16181
16182 return obj;
16183 }
16184
16185 return Component;
16186}
16187
16188/* harmony default export */ var contextmenu = (Contextmenu());
16189;// CONCATENATED MODULE: ./src/plugins/dropdown.js
16190
16191
16192
16193
16194
16195
16196
16197function Dropdown() {
16198
16199 var Component = (function (el, options) {
16200 // Already created, update options
16201 if (el.dropdown) {
16202 return el.dropdown.setOptions(options, true);
16203 }
16204
16205 // New instance
16206 var obj = {type: 'dropdown'};
16207 obj.options = {};
16208
16209 // Success
16210 var success = function (data, val) {
16211 // Set data
16212 if (data && data.length) {
16213 // Sort
16214 if (obj.options.sortResults !== false) {
16215 if (typeof obj.options.sortResults == "function") {
16216 data.sort(obj.options.sortResults);
16217 } else {
16218 data.sort(sortData);
16219 }
16220 }
16221
16222 obj.setData(data);
16223 }
16224
16225 // Onload method
16226 if (typeof (obj.options.onload) == 'function') {
16227 obj.options.onload(el, obj, data, val);
16228 }
16229
16230 // Set value
16231 if (val) {
16232 applyValue(val);
16233 }
16234
16235 // Component value
16236 if (val === undefined || val === null) {
16237 obj.options.value = '';
16238 }
16239 el.value = obj.options.value;
16240
16241 // Open dropdown
16242 if (obj.options.opened == true) {
16243 obj.open();
16244 }
16245 }
16246
16247
16248 // Default sort
16249 var sortData = function (itemA, itemB) {
16250 var testA, testB;
16251 if (typeof itemA == "string") {
16252 testA = itemA;
16253 } else {
16254 if (itemA.text) {
16255 testA = itemA.text;
16256 } else if (itemA.name) {
16257 testA = itemA.name;
16258 }
16259 }
16260
16261 if (typeof itemB == "string") {
16262 testB = itemB;
16263 } else {
16264 if (itemB.text) {
16265 testB = itemB.text;
16266 } else if (itemB.name) {
16267 testB = itemB.name;
16268 }
16269 }
16270
16271 if (typeof testA == "string" || typeof testB == "string") {
16272 if (typeof testA != "string") {
16273 testA = "" + testA;
16274 }
16275 if (typeof testB != "string") {
16276 testB = "" + testB;
16277 }
16278 return testA.localeCompare(testB);
16279 } else {
16280 return testA - testB;
16281 }
16282 }
16283
16284 /**
16285 * Reset the options for the dropdown
16286 */
16287 var resetValue = function () {
16288 // Reset value container
16289 obj.value = {};
16290 // Remove selected
16291 for (var i = 0; i < obj.items.length; i++) {
16292 if (obj.items[i].selected == true) {
16293 if (obj.items[i].element) {
16294 obj.items[i].element.classList.remove('jdropdown-selected')
16295 }
16296 obj.items[i].selected = null;
16297 }
16298 }
16299 // Reset options
16300 obj.options.value = '';
16301 // Reset value
16302 el.value = '';
16303 }
16304
16305 /**
16306 * Apply values to the dropdown
16307 */
16308 var applyValue = function (values) {
16309 // Reset the current values
16310 resetValue();
16311
16312 // Read values
16313 if (values !== null) {
16314 if (!values) {
16315 if (typeof (obj.value['']) !== 'undefined') {
16316 obj.value[''] = '';
16317 }
16318 } else {
16319 if (!Array.isArray(values)) {
16320 values = ('' + values).split(';');
16321 }
16322 for (var i = 0; i < values.length; i++) {
16323 obj.value[values[i]] = '';
16324 }
16325 }
16326 }
16327
16328 // Update the DOM
16329 for (var i = 0; i < obj.items.length; i++) {
16330 if (typeof (obj.value[Value(i)]) !== 'undefined') {
16331 if (obj.items[i].element) {
16332 obj.items[i].element.classList.add('jdropdown-selected')
16333 }
16334 obj.items[i].selected = true;
16335
16336 // Keep label
16337 obj.value[Value(i)] = Text(i);
16338 }
16339 }
16340
16341 // Global value
16342 obj.options.value = Object.keys(obj.value).join(';');
16343
16344 // Update labels
16345 obj.header.value = obj.getText();
16346 }
16347
16348 // Get the value of one item
16349 var Value = function (k, v) {
16350 // Legacy purposes
16351 if (!obj.options.format) {
16352 var property = 'value';
16353 } else {
16354 var property = 'id';
16355 }
16356
16357 if (obj.items[k]) {
16358 if (v !== undefined) {
16359 return obj.items[k].data[property] = v;
16360 } else {
16361 return obj.items[k].data[property];
16362 }
16363 }
16364
16365 return '';
16366 }
16367
16368 // Get the label of one item
16369 var Text = function (k, v) {
16370 // Legacy purposes
16371 if (!obj.options.format) {
16372 var property = 'text';
16373 } else {
16374 var property = 'name';
16375 }
16376
16377 if (obj.items[k]) {
16378 if (v !== undefined) {
16379 return obj.items[k].data[property] = v;
16380 } else {
16381 return obj.items[k].data[property];
16382 }
16383 }
16384
16385 return '';
16386 }
16387
16388 var getValue = function () {
16389 return Object.keys(obj.value);
16390 }
16391
16392 var getText = function () {
16393 var data = [];
16394 var k = Object.keys(obj.value);
16395 for (var i = 0; i < k.length; i++) {
16396 data.push(obj.value[k[i]]);
16397 }
16398 return data;
16399 }
16400
16401 obj.setOptions = function (options, reset) {
16402 if (!options) {
16403 options = {};
16404 }
16405
16406 // Default configuration
16407 var defaults = {
16408 url: null,
16409 data: [],
16410 format: 0,
16411 multiple: false,
16412 autocomplete: false,
16413 remoteSearch: false,
16414 lazyLoading: false,
16415 type: null,
16416 width: null,
16417 maxWidth: null,
16418 opened: false,
16419 value: null,
16420 placeholder: '',
16421 newOptions: false,
16422 position: false,
16423 onchange: null,
16424 onload: null,
16425 onopen: null,
16426 onclose: null,
16427 onfocus: null,
16428 onblur: null,
16429 oninsert: null,
16430 onbeforeinsert: null,
16431 onsearch: null,
16432 onbeforesearch: null,
16433 sortResults: false,
16434 autofocus: false,
16435 prompt: null,
16436 allowEmpty: true,
16437 }
16438
16439 // Loop through our object
16440 for (var property in defaults) {
16441 if (options && options.hasOwnProperty(property)) {
16442 obj.options[property] = options[property];
16443 } else {
16444 if (typeof (obj.options[property]) == 'undefined' || reset === true) {
16445 obj.options[property] = defaults[property];
16446 }
16447 }
16448 }
16449
16450 // Force autocomplete search
16451 if (obj.options.remoteSearch == true || obj.options.type === 'searchbar') {
16452 obj.options.autocomplete = true;
16453 }
16454
16455 // New options
16456 if (obj.options.newOptions == true) {
16457 obj.header.classList.add('jdropdown-add');
16458 } else {
16459 obj.header.classList.remove('jdropdown-add');
16460 }
16461
16462 // Autocomplete
16463 if (obj.options.autocomplete == true) {
16464 obj.header.removeAttribute('readonly');
16465 } else {
16466 obj.header.setAttribute('readonly', 'readonly');
16467 }
16468
16469 // Place holder
16470 if (obj.options.placeholder) {
16471 obj.header.setAttribute('placeholder', obj.options.placeholder);
16472 } else {
16473 obj.header.removeAttribute('placeholder');
16474 }
16475
16476 // Remove specific dropdown typing to add again
16477 el.classList.remove('jdropdown-searchbar');
16478 el.classList.remove('jdropdown-picker');
16479 el.classList.remove('jdropdown-list');
16480
16481 if (obj.options.type == 'searchbar') {
16482 el.classList.add('jdropdown-searchbar');
16483 } else if (obj.options.type == 'list') {
16484 el.classList.add('jdropdown-list');
16485 } else if (obj.options.type == 'picker') {
16486 el.classList.add('jdropdown-picker');
16487 } else {
16488 if (helpers.getWindowWidth() < 800) {
16489 if (obj.options.autocomplete) {
16490 el.classList.add('jdropdown-searchbar');
16491 obj.options.type = 'searchbar';
16492 } else {
16493 el.classList.add('jdropdown-picker');
16494 obj.options.type = 'picker';
16495 }
16496 } else {
16497 if (obj.options.width) {
16498 el.style.width = obj.options.width;
16499 el.style.minWidth = obj.options.width;
16500 } else {
16501 el.style.removeProperty('width');
16502 el.style.removeProperty('min-width');
16503 }
16504
16505 el.classList.add('jdropdown-default');
16506 obj.options.type = 'default';
16507 }
16508 }
16509
16510 // Close button
16511 if (obj.options.type == 'searchbar') {
16512 containerHeader.appendChild(closeButton);
16513 } else {
16514 container.insertBefore(closeButton, container.firstChild);
16515 }
16516
16517 // Load the content
16518 if (obj.options.url && !options.data) {
16519 ajax({
16520 url: obj.options.url,
16521 method: 'GET',
16522 dataType: 'json',
16523 success: function (data) {
16524 if (data) {
16525 success(data, obj.options.value);
16526 }
16527 }
16528 });
16529 } else {
16530 success(obj.options.data, obj.options.value);
16531 }
16532
16533 // Return the instance
16534 return obj;
16535 }
16536
16537 // Helpers
16538 var containerHeader = null;
16539 var container = null;
16540 var content = null;
16541 var closeButton = null;
16542 var resetButton = null;
16543 var backdrop = null;
16544
16545 var keyTimer = null;
16546
16547 /**
16548 * Init dropdown
16549 */
16550 var init = function () {
16551 // Do not accept null
16552 if (!options) {
16553 options = {};
16554 }
16555
16556 // If the element is a SELECT tag, create a configuration object
16557 if (el.tagName == 'SELECT') {
16558 var ret = Component.extractFromDom(el, options);
16559 el = ret.el;
16560 options = ret.options;
16561 }
16562
16563 // Place holder
16564 if (!options.placeholder && el.getAttribute('placeholder')) {
16565 options.placeholder = el.getAttribute('placeholder');
16566 }
16567
16568 // Value container
16569 obj.value = {};
16570 // Containers
16571 obj.items = [];
16572 obj.groups = [];
16573 // Search options
16574 obj.search = '';
16575 obj.results = null;
16576
16577 // Create dropdown
16578 el.classList.add('jdropdown');
16579
16580 // Header container
16581 containerHeader = document.createElement('div');
16582 containerHeader.className = 'jdropdown-container-header';
16583
16584 // Header
16585 obj.header = document.createElement('input');
16586 obj.header.className = 'jdropdown-header jss_object';
16587 obj.header.type = 'text';
16588 obj.header.setAttribute('autocomplete', 'off');
16589 obj.header.onfocus = function () {
16590 if (typeof (obj.options.onfocus) == 'function') {
16591 obj.options.onfocus(el);
16592 }
16593 }
16594
16595 obj.header.onblur = function () {
16596 if (typeof (obj.options.onblur) == 'function') {
16597 obj.options.onblur(el);
16598 }
16599 }
16600
16601 obj.header.onkeyup = function (e) {
16602 if (obj.options.autocomplete == true && !keyTimer) {
16603 if (obj.search != obj.header.value.trim()) {
16604 keyTimer = setTimeout(function () {
16605 obj.find(obj.header.value.trim());
16606 keyTimer = null;
16607 }, 400);
16608 }
16609
16610 if (!el.classList.contains('jdropdown-focus')) {
16611 obj.open();
16612 }
16613 } else {
16614 if (!obj.options.autocomplete) {
16615 obj.next(e.key);
16616 }
16617 }
16618 }
16619
16620 // Global controls
16621 if (!Component.hasEvents) {
16622 // Execute only one time
16623 Component.hasEvents = true;
16624 // Enter and Esc
16625 document.addEventListener("keydown", Component.keydown);
16626 }
16627
16628 // Container
16629 container = document.createElement('div');
16630 container.className = 'jdropdown-container';
16631
16632 // Dropdown content
16633 content = document.createElement('div');
16634 content.className = 'jdropdown-content';
16635
16636 // Close button
16637 closeButton = document.createElement('div');
16638 closeButton.className = 'jdropdown-close';
16639 closeButton.textContent = 'Done';
16640
16641 // Reset button
16642 resetButton = document.createElement('div');
16643 resetButton.className = 'jdropdown-reset';
16644 resetButton.textContent = 'x';
16645 resetButton.onclick = function () {
16646 obj.reset();
16647 obj.close();
16648 }
16649
16650 // Create backdrop
16651 backdrop = document.createElement('div');
16652 backdrop.className = 'jdropdown-backdrop';
16653
16654 // Append elements
16655 containerHeader.appendChild(obj.header);
16656
16657 container.appendChild(content);
16658 el.appendChild(containerHeader);
16659 el.appendChild(container);
16660 el.appendChild(backdrop);
16661
16662 // Set the otiptions
16663 obj.setOptions(options);
16664
16665 if ('ontouchsend' in document.documentElement === true) {
16666 el.addEventListener('touchsend', Component.mouseup);
16667 } else {
16668 el.addEventListener('mouseup', Component.mouseup);
16669 }
16670
16671 // Lazyloading
16672 if (obj.options.lazyLoading == true) {
16673 LazyLoading(content, {
16674 loadUp: obj.loadUp,
16675 loadDown: obj.loadDown,
16676 });
16677 }
16678
16679 content.onwheel = function (e) {
16680 e.stopPropagation();
16681 }
16682
16683 // Change method
16684 el.change = obj.setValue;
16685
16686 // Global generic value handler
16687 el.val = function (val) {
16688 if (val === undefined) {
16689 return obj.getValue(obj.options.multiple ? true : false);
16690 } else {
16691 obj.setValue(val);
16692 }
16693 }
16694
16695 // Keep object available from the node
16696 el.dropdown = obj;
16697 }
16698
16699 /**
16700 * Get the current remote source of data URL
16701 */
16702 obj.getUrl = function () {
16703 return obj.options.url;
16704 }
16705
16706 /**
16707 * Set the new data from a remote source
16708 * @param {string} url - url from the remote source
16709 * @param {function} callback - callback when the data is loaded
16710 */
16711 obj.setUrl = function (url, callback) {
16712 obj.options.url = url;
16713
16714 ajax({
16715 url: obj.options.url,
16716 method: 'GET',
16717 dataType: 'json',
16718 success: function (data) {
16719 obj.setData(data);
16720 // Callback
16721 if (typeof (callback) == 'function') {
16722 callback(obj);
16723 }
16724 }
16725 });
16726 }
16727
16728 /**
16729 * Set ID for one item
16730 */
16731 obj.setId = function (item, v) {
16732 // Legacy purposes
16733 if (!obj.options.format) {
16734 var property = 'value';
16735 } else {
16736 var property = 'id';
16737 }
16738
16739 if (typeof (item) == 'object') {
16740 item[property] = v;
16741 } else {
16742 obj.items[item].data[property] = v;
16743 }
16744 }
16745
16746 const add = function(title, id) {
16747 if (! title) {
16748 let current = obj.options.autocomplete == true ? obj.header.value : '';
16749 title = prompt(dictionary.translate('Add A New Option'), current);
16750 if (! title) {
16751 return false;
16752 }
16753 }
16754
16755 // Id
16756 if (! id) {
16757 id = helpers.guid();
16758 }
16759
16760 // Create new item
16761 if (!obj.options.format) {
16762 var item = {
16763 value: id,
16764 text: title,
16765 }
16766 } else {
16767 var item = {
16768 id: id,
16769 name: title,
16770 }
16771 }
16772
16773 // Callback
16774 if (typeof (obj.options.onbeforeinsert) == 'function') {
16775 let ret = obj.options.onbeforeinsert(obj, item);
16776 if (ret === false) {
16777 return false;
16778 } else if (ret) {
16779 item = ret;
16780 }
16781 }
16782
16783 // Add item to the main list
16784 obj.options.data.push(item);
16785
16786 // Create DOM
16787 var newItem = obj.createItem(item);
16788
16789 // Append DOM to the list
16790 content.appendChild(newItem.element);
16791
16792 // Callback
16793 if (typeof (obj.options.oninsert) == 'function') {
16794 obj.options.oninsert(obj, item, newItem);
16795 }
16796
16797 // Show content
16798 if (content.style.display == 'none') {
16799 content.style.display = '';
16800 }
16801
16802 // Search?
16803 if (obj.results) {
16804 obj.results.push(newItem);
16805 }
16806
16807 return item;
16808 }
16809
16810 /**
16811 * Add a new item
16812 * @param {string} title - title of the new item
16813 * @param {string} id - value/id of the new item
16814 */
16815 obj.add = function (title, id) {
16816 if (typeof (obj.options.prompt) == 'function') {
16817 return obj.options.prompt.call(obj, add);
16818 }
16819 return add(title, id);
16820 }
16821
16822 /**
16823 * Create a new item
16824 */
16825 obj.createItem = function (data, group, groupName) {
16826 // Keep the correct source of data
16827 if (!obj.options.format) {
16828 if (!data.value && data.id !== undefined) {
16829 data.value = data.id;
16830 //delete data.id;
16831 }
16832 if (!data.text && data.name !== undefined) {
16833 data.text = data.name;
16834 //delete data.name;
16835 }
16836 } else {
16837 if (!data.id && data.value !== undefined) {
16838 data.id = data.value;
16839 //delete data.value;
16840 }
16841 if (!data.name && data.text !== undefined) {
16842 data.name = data.text
16843 //delete data.text;
16844 }
16845 }
16846
16847 // Create item
16848 var item = {};
16849 item.element = document.createElement('div');
16850 item.element.className = 'jdropdown-item';
16851 item.element.indexValue = obj.items.length;
16852 item.data = data;
16853
16854 // Groupd DOM
16855 if (group) {
16856 item.group = group;
16857 }
16858
16859 // Id
16860 if (data.id) {
16861 item.element.setAttribute('id', data.id);
16862 }
16863
16864 // Disabled
16865 if (data.disabled == true) {
16866 item.element.setAttribute('data-disabled', true);
16867 }
16868
16869 // Tooltip
16870 if (data.tooltip) {
16871 item.element.setAttribute('title', data.tooltip);
16872 }
16873
16874 // Image
16875 if (data.image) {
16876 var image = document.createElement('img');
16877 image.className = 'jdropdown-image';
16878 image.src = data.image;
16879 if (!data.title) {
16880 image.classList.add('jdropdown-image-small');
16881 }
16882 item.element.appendChild(image);
16883 } else if (data.icon) {
16884 var icon = document.createElement('span');
16885 icon.className = "jdropdown-icon material-icons";
16886 icon.innerText = data.icon;
16887 if (!data.title) {
16888 icon.classList.add('jdropdown-icon-small');
16889 }
16890 if (data.color) {
16891 icon.style.color = data.color;
16892 }
16893 item.element.appendChild(icon);
16894 } else if (data.color) {
16895 var color = document.createElement('div');
16896 color.className = 'jdropdown-color';
16897 color.style.backgroundColor = data.color;
16898 item.element.appendChild(color);
16899 }
16900
16901 // Set content
16902 if (!obj.options.format) {
16903 var text = data.text;
16904 } else {
16905 var text = data.name;
16906 }
16907
16908 var node = document.createElement('div');
16909 node.className = 'jdropdown-description';
16910 node.textContent = text || '&nbsp;';
16911
16912 // Title
16913 if (data.title) {
16914 var title = document.createElement('div');
16915 title.className = 'jdropdown-title';
16916 title.innerText = data.title;
16917 node.appendChild(title);
16918 }
16919
16920 // Set content
16921 if (!obj.options.format) {
16922 var val = data.value;
16923 } else {
16924 var val = data.id;
16925 }
16926
16927 // Value
16928 if (obj.value[val]) {
16929 item.element.classList.add('jdropdown-selected');
16930 item.selected = true;
16931 }
16932
16933 // Keep DOM accessible
16934 obj.items.push(item);
16935
16936 // Add node to item
16937 item.element.appendChild(node);
16938
16939 return item;
16940 }
16941
16942 obj.appendData = function (data) {
16943 // Create elements
16944 if (data.length) {
16945 // Helpers
16946 var items = [];
16947 var groups = [];
16948
16949 // Prepare data
16950 for (var i = 0; i < data.length; i++) {
16951 // Process groups
16952 if (data[i].group) {
16953 if (!groups[data[i].group]) {
16954 groups[data[i].group] = [];
16955 }
16956 groups[data[i].group].push(i);
16957 } else {
16958 items.push(i);
16959 }
16960 }
16961
16962 // Number of items counter
16963 var counter = 0;
16964
16965 // Groups
16966 var groupNames = Object.keys(groups);
16967
16968 // Append groups in case exists
16969 if (groupNames.length > 0) {
16970 for (var i = 0; i < groupNames.length; i++) {
16971 // Group container
16972 var group = document.createElement('div');
16973 group.className = 'jdropdown-group';
16974 // Group name
16975 var groupName = document.createElement('div');
16976 groupName.className = 'jdropdown-group-name';
16977 groupName.textContent = groupNames[i];
16978 // Group arrow
16979 var groupArrow = document.createElement('i');
16980 groupArrow.className = 'jdropdown-group-arrow jdropdown-group-arrow-down';
16981 groupName.appendChild(groupArrow);
16982 // Group items
16983 var groupContent = document.createElement('div');
16984 groupContent.className = 'jdropdown-group-items';
16985 for (var j = 0; j < groups[groupNames[i]].length; j++) {
16986 var item = obj.createItem(data[groups[groupNames[i]][j]], group, groupNames[i]);
16987
16988 if (obj.options.lazyLoading == false || counter < 200) {
16989 groupContent.appendChild(item.element);
16990 counter++;
16991 }
16992 }
16993 // Group itens
16994 group.appendChild(groupName);
16995 group.appendChild(groupContent);
16996 // Keep group DOM
16997 obj.groups.push(group);
16998 // Only add to the screen if children on the group
16999 if (groupContent.children.length > 0) {
17000 // Add DOM to the content
17001 content.appendChild(group);
17002 }
17003 }
17004 }
17005
17006 if (items.length) {
17007 for (var i = 0; i < items.length; i++) {
17008 var item = obj.createItem(data[items[i]]);
17009 if (obj.options.lazyLoading == false || counter < 200) {
17010 content.appendChild(item.element);
17011 counter++;
17012 }
17013 }
17014 }
17015 }
17016 }
17017
17018 obj.setData = function (data) {
17019 // Reset current value
17020 resetValue();
17021
17022 // Make sure the content container is blank
17023 content.textContent = '';
17024
17025 // Reset
17026 obj.header.value = '';
17027
17028 // Reset items and values
17029 obj.items = [];
17030
17031 // Prepare data
17032 if (data && data.length) {
17033 for (var i = 0; i < data.length; i++) {
17034 // Compatibility
17035 if (typeof (data[i]) != 'object') {
17036 // Correct format
17037 if (!obj.options.format) {
17038 data[i] = {
17039 value: data[i],
17040 text: data[i]
17041 }
17042 } else {
17043 data[i] = {
17044 id: data[i],
17045 name: data[i]
17046 }
17047 }
17048 }
17049 }
17050
17051 // Append data
17052 obj.appendData(data);
17053
17054 // Update data
17055 obj.options.data = data;
17056 } else {
17057 // Update data
17058 obj.options.data = [];
17059 }
17060
17061 obj.close();
17062 }
17063
17064 obj.getData = function () {
17065 return obj.options.data;
17066 }
17067
17068 /**
17069 * Get position of the item
17070 */
17071 obj.getPosition = function (val) {
17072 for (var i = 0; i < obj.items.length; i++) {
17073 if (Value(i) == val) {
17074 return i;
17075 }
17076 }
17077 return false;
17078 }
17079
17080 /**
17081 * Get dropdown current text
17082 */
17083 obj.getText = function (asArray) {
17084 // Get value
17085 var v = getText();
17086 // Return value
17087 if (asArray) {
17088 return v;
17089 } else {
17090 return v.join('; ');
17091 }
17092 }
17093
17094 /**
17095 * Get dropdown current value
17096 */
17097 obj.getValue = function (asArray) {
17098 // Get value
17099 var v = getValue();
17100 // Return value
17101 if (asArray) {
17102 return v;
17103 } else {
17104 return v.join(';');
17105 }
17106 }
17107
17108 /**
17109 * Change event
17110 */
17111 var change = function (oldValue) {
17112 // Lemonade JS
17113 if (el.value != obj.options.value) {
17114 el.value = obj.options.value;
17115 if (typeof (el.oninput) == 'function') {
17116 el.oninput({
17117 type: 'input',
17118 target: el,
17119 value: el.value
17120 });
17121 }
17122 }
17123
17124 // Events
17125 if (typeof (obj.options.onchange) == 'function') {
17126 obj.options.onchange(el, obj, oldValue, obj.options.value);
17127 }
17128 }
17129
17130 /**
17131 * Set value
17132 */
17133 obj.setValue = function (newValue) {
17134 // Current value
17135 var oldValue = obj.getValue();
17136 // New value
17137 if (Array.isArray(newValue)) {
17138 newValue = newValue.join(';')
17139 }
17140
17141 if (oldValue !== newValue) {
17142 // Set value
17143 applyValue(newValue);
17144
17145 // Change
17146 change(oldValue);
17147 }
17148 }
17149
17150 obj.resetSelected = function () {
17151 obj.setValue(null);
17152 }
17153
17154 obj.selectIndex = function (index, force) {
17155 // Make sure is a number
17156 var index = parseInt(index);
17157
17158 // Only select those existing elements
17159 if (obj.items && obj.items[index] && (force === true || obj.items[index].data.disabled !== true)) {
17160 // Reset cursor to a new position
17161 obj.setCursor(index, false);
17162
17163 // Behaviour
17164 if (!obj.options.multiple) {
17165 // Update value
17166 if (obj.items[index].selected) {
17167 if (obj.options.allowEmpty !== false) {
17168 obj.setValue(null);
17169 }
17170 } else {
17171 obj.setValue(Value(index));
17172 }
17173
17174 // Close component
17175 obj.close();
17176 } else {
17177 // Old value
17178 var oldValue = obj.options.value;
17179
17180 // Toggle option
17181 if (obj.items[index].selected) {
17182 obj.items[index].element.classList.remove('jdropdown-selected');
17183 obj.items[index].selected = false;
17184
17185 delete obj.value[Value(index)];
17186 } else {
17187 // Select element
17188 obj.items[index].element.classList.add('jdropdown-selected');
17189 obj.items[index].selected = true;
17190
17191 // Set value
17192 obj.value[Value(index)] = Text(index);
17193 }
17194
17195 // Global value
17196 obj.options.value = Object.keys(obj.value).join(';');
17197
17198 // Update labels for multiple dropdown
17199 if (obj.options.autocomplete == false) {
17200 obj.header.value = getText().join('; ');
17201 }
17202
17203 // Events
17204 change(oldValue);
17205 }
17206 }
17207 }
17208
17209 obj.selectItem = function (item) {
17210 obj.selectIndex(item.indexValue);
17211 }
17212
17213 var exists = function (k, result) {
17214 for (var j = 0; j < result.length; j++) {
17215 if (!obj.options.format) {
17216 if (result[j].value == k) {
17217 return true;
17218 }
17219 } else {
17220 if (result[j].id == k) {
17221 return true;
17222 }
17223 }
17224 }
17225 return false;
17226 }
17227
17228 obj.find = function (str) {
17229 if (obj.search == str.trim()) {
17230 return false;
17231 }
17232
17233 // Search term
17234 obj.search = str;
17235
17236 // Reset index
17237 obj.setCursor();
17238
17239 // Remove nodes from all groups
17240 if (obj.groups.length) {
17241 for (var i = 0; i < obj.groups.length; i++) {
17242 obj.groups[i].lastChild.textContent = '';
17243 }
17244 }
17245
17246 // Remove all nodes
17247 content.textContent = '';
17248
17249 // Remove current items in the remote search
17250 if (obj.options.remoteSearch == true) {
17251 // Reset results
17252 obj.results = null;
17253 // URL
17254 var url = obj.options.url;
17255
17256 // Ajax call
17257 let o = {
17258 url: url,
17259 method: 'GET',
17260 data: { q: str },
17261 dataType: 'json',
17262 success: function (result) {
17263 // Reset items
17264 obj.items = [];
17265
17266 // Add the current selected items to the results in case they are not there
17267 var current = Object.keys(obj.value);
17268 if (current.length) {
17269 for (var i = 0; i < current.length; i++) {
17270 if (!exists(current[i], result)) {
17271 if (!obj.options.format) {
17272 result.unshift({value: current[i], text: obj.value[current[i]]});
17273 } else {
17274 result.unshift({id: current[i], name: obj.value[current[i]]});
17275 }
17276 }
17277 }
17278 }
17279 // Append data
17280 obj.appendData(result);
17281 // Show or hide results
17282 if (!result.length) {
17283 content.style.display = 'none';
17284 } else {
17285 content.style.display = '';
17286 }
17287
17288 if (typeof(obj.options.onsearch) === 'function') {
17289 obj.options.onsearch(obj, result);
17290 }
17291 }
17292 }
17293
17294 if (typeof(obj.options.onbeforesearch) === 'function') {
17295 let ret = obj.options.onbeforesearch(obj, o);
17296 if (ret === false) {
17297 return;
17298 } else if (typeof(ret) === 'object') {
17299 o = ret;
17300 }
17301 }
17302
17303 // Remote search
17304 ajax(o);
17305 } else {
17306 // Search terms
17307 str = new RegExp(str, 'gi');
17308
17309 // Reset search
17310 var results = [];
17311
17312 // Append options
17313 for (var i = 0; i < obj.items.length; i++) {
17314 // Item label
17315 var label = Text(i);
17316 // Item title
17317 var title = obj.items[i].data.title || '';
17318 // Group name
17319 var groupName = obj.items[i].data.group || '';
17320 // Synonym
17321 var synonym = obj.items[i].data.synonym || '';
17322 if (synonym) {
17323 synonym = synonym.join(' ');
17324 }
17325
17326 if (str == null || obj.items[i].selected == true || label.toString().match(str) || title.match(str) || groupName.match(str) || synonym.match(str)) {
17327 results.push(obj.items[i]);
17328 }
17329 }
17330
17331 if (!results.length) {
17332 content.style.display = 'none';
17333
17334 // Results
17335 obj.results = null;
17336 } else {
17337 content.style.display = '';
17338
17339 // Results
17340 obj.results = results;
17341
17342 // Show 200 items at once
17343 var number = results.length || 0;
17344
17345 // Lazyloading
17346 if (obj.options.lazyLoading == true && number > 200) {
17347 number = 200;
17348 }
17349
17350 for (var i = 0; i < number; i++) {
17351 if (obj.results[i].group) {
17352 if (!obj.results[i].group.parentNode) {
17353 content.appendChild(obj.results[i].group);
17354 }
17355 obj.results[i].group.lastChild.appendChild(obj.results[i].element);
17356 } else {
17357 content.appendChild(obj.results[i].element);
17358 }
17359 }
17360 }
17361 }
17362
17363 // Auto focus
17364 if (obj.options.autofocus == true) {
17365 obj.first();
17366 }
17367 }
17368
17369 obj.open = function () {
17370 // Focus
17371 if (!el.classList.contains('jdropdown-focus')) {
17372 // Current dropdown
17373 Component.current = obj;
17374
17375 // Start tracking
17376 tracking(obj, true);
17377
17378 // Add focus
17379 el.classList.add('jdropdown-focus');
17380
17381 // Animation
17382 if (helpers.getWindowWidth() < 800) {
17383 if (obj.options.type == null || obj.options.type == 'picker') {
17384 animation.slideBottom(container, 1);
17385 }
17386 }
17387
17388 // Filter
17389 if (obj.options.autocomplete == true) {
17390 obj.header.value = obj.search;
17391 obj.header.focus();
17392 }
17393
17394 // Set cursor for the first or first selected element
17395 var k = getValue();
17396 if (k[0]) {
17397 var cursor = obj.getPosition(k[0]);
17398 if (cursor !== false) {
17399 obj.setCursor(cursor);
17400 }
17401 }
17402
17403 // Container Size
17404 if (!obj.options.type || obj.options.type == 'default') {
17405 var rect = el.getBoundingClientRect();
17406 var rectContainer = container.getBoundingClientRect();
17407
17408 if (obj.options.position) {
17409 container.style.position = 'fixed';
17410 if (window.innerHeight < rect.bottom + rectContainer.height) {
17411 container.style.top = '';
17412 container.style.bottom = (window.innerHeight - rect.top) + 1 + 'px';
17413 } else {
17414 container.style.top = rect.bottom + 'px';
17415 container.style.bottom = '';
17416 }
17417 container.style.left = rect.left + 'px';
17418 } else {
17419 if (window.innerHeight < rect.bottom + rectContainer.height) {
17420 container.style.top = '';
17421 container.style.bottom = rect.height + 1 + 'px';
17422 } else {
17423 container.style.top = '';
17424 container.style.bottom = '';
17425 }
17426 }
17427
17428 container.style.minWidth = rect.width + 'px';
17429
17430 if (obj.options.maxWidth) {
17431 container.style.maxWidth = obj.options.maxWidth;
17432 }
17433
17434 if (!obj.items.length && obj.options.autocomplete == true) {
17435 content.style.display = 'none';
17436 } else {
17437 content.style.display = '';
17438 }
17439 }
17440 }
17441
17442 // Events
17443 if (typeof (obj.options.onopen) == 'function') {
17444 obj.options.onopen(el);
17445 }
17446 }
17447
17448 obj.close = function (ignoreEvents) {
17449 if (el.classList.contains('jdropdown-focus')) {
17450 // Update labels
17451 obj.header.value = obj.getText();
17452 // Remove cursor
17453 obj.setCursor();
17454 // Events
17455 if (!ignoreEvents && typeof (obj.options.onclose) == 'function') {
17456 obj.options.onclose(el);
17457 }
17458 // Blur
17459 if (obj.header.blur) {
17460 obj.header.blur();
17461 }
17462 // Remove focus
17463 el.classList.remove('jdropdown-focus');
17464 // Start tracking
17465 tracking(obj, false);
17466 // Current dropdown
17467 Component.current = null;
17468 }
17469
17470 return obj.getValue();
17471 }
17472
17473 /**
17474 * Set cursor
17475 */
17476 obj.setCursor = function (index, setPosition) {
17477 // Remove current cursor
17478 if (obj.currentIndex != null) {
17479 // Remove visual cursor
17480 if (obj.items && obj.items[obj.currentIndex]) {
17481 obj.items[obj.currentIndex].element.classList.remove('jdropdown-cursor');
17482 }
17483 }
17484
17485 if (index == undefined) {
17486 obj.currentIndex = null;
17487 } else {
17488 index = parseInt(index);
17489
17490 // Cursor only for visible items
17491 if (obj.items[index].element.parentNode) {
17492 obj.items[index].element.classList.add('jdropdown-cursor');
17493 obj.currentIndex = index;
17494
17495 // Update scroll to the cursor element
17496 if (setPosition !== false && obj.items[obj.currentIndex].element) {
17497 var container = content.scrollTop;
17498 var element = obj.items[obj.currentIndex].element;
17499 content.scrollTop = element.offsetTop - element.scrollTop + element.clientTop - 95;
17500 }
17501 }
17502 }
17503 }
17504
17505 // Compatibility
17506 obj.resetCursor = obj.setCursor;
17507 obj.updateCursor = obj.setCursor;
17508
17509 /**
17510 * Reset cursor and selected items
17511 */
17512 obj.reset = function () {
17513 // Reset cursor
17514 obj.setCursor();
17515
17516 // Reset selected
17517 obj.setValue(null);
17518 }
17519
17520 /**
17521 * First available item
17522 */
17523 obj.first = function () {
17524 if (obj.options.lazyLoading === true) {
17525 obj.loadFirst();
17526 }
17527
17528 var items = content.querySelectorAll('.jdropdown-item');
17529 if (items.length) {
17530 var newIndex = items[0].indexValue;
17531 obj.setCursor(newIndex);
17532 }
17533 }
17534
17535 /**
17536 * Last available item
17537 */
17538 obj.last = function () {
17539 if (obj.options.lazyLoading === true) {
17540 obj.loadLast();
17541 }
17542
17543 var items = content.querySelectorAll('.jdropdown-item');
17544 if (items.length) {
17545 var newIndex = items[items.length - 1].indexValue;
17546 obj.setCursor(newIndex);
17547 }
17548 }
17549
17550 obj.next = function (letter) {
17551 var newIndex = null;
17552
17553 if (letter) {
17554 if (letter.length == 1) {
17555 // Current index
17556 var current = obj.currentIndex || -1;
17557 // Letter
17558 letter = letter.toLowerCase();
17559
17560 var e = null;
17561 var l = null;
17562 var items = content.querySelectorAll('.jdropdown-item');
17563 if (items.length) {
17564 for (var i = 0; i < items.length; i++) {
17565 if (items[i].indexValue > current) {
17566 if (e = obj.items[items[i].indexValue]) {
17567 if (l = e.element.innerText[0]) {
17568 l = l.toLowerCase();
17569 if (letter == l) {
17570 newIndex = items[i].indexValue;
17571 break;
17572 }
17573 }
17574 }
17575 }
17576 }
17577 obj.setCursor(newIndex);
17578 }
17579 }
17580 } else {
17581 if (obj.currentIndex == undefined || obj.currentIndex == null) {
17582 obj.first();
17583 } else {
17584 var element = obj.items[obj.currentIndex].element;
17585
17586 var next = element.nextElementSibling;
17587 if (next) {
17588 if (next.classList.contains('jdropdown-group')) {
17589 next = next.lastChild.firstChild;
17590 }
17591 newIndex = next.indexValue;
17592 } else {
17593 if (element.parentNode.classList.contains('jdropdown-group-items')) {
17594 if (next = element.parentNode.parentNode.nextElementSibling) {
17595 if (next.classList.contains('jdropdown-group')) {
17596 next = next.lastChild.firstChild;
17597 } else if (next.classList.contains('jdropdown-item')) {
17598 newIndex = next.indexValue;
17599 } else {
17600 next = null;
17601 }
17602 }
17603
17604 if (next) {
17605 newIndex = next.indexValue;
17606 }
17607 }
17608 }
17609
17610 if (newIndex !== null) {
17611 obj.setCursor(newIndex);
17612 }
17613 }
17614 }
17615 }
17616
17617 obj.prev = function () {
17618 var newIndex = null;
17619
17620 if (obj.currentIndex === null) {
17621 obj.first();
17622 } else {
17623 var element = obj.items[obj.currentIndex].element;
17624
17625 var prev = element.previousElementSibling;
17626 if (prev) {
17627 if (prev.classList.contains('jdropdown-group')) {
17628 prev = prev.lastChild.lastChild;
17629 }
17630 newIndex = prev.indexValue;
17631 } else {
17632 if (element.parentNode.classList.contains('jdropdown-group-items')) {
17633 if (prev = element.parentNode.parentNode.previousElementSibling) {
17634 if (prev.classList.contains('jdropdown-group')) {
17635 prev = prev.lastChild.lastChild;
17636 } else if (prev.classList.contains('jdropdown-item')) {
17637 newIndex = prev.indexValue;
17638 } else {
17639 prev = null
17640 }
17641 }
17642
17643 if (prev) {
17644 newIndex = prev.indexValue;
17645 }
17646 }
17647 }
17648 }
17649
17650 if (newIndex !== null) {
17651 obj.setCursor(newIndex);
17652 }
17653 }
17654
17655 obj.loadFirst = function () {
17656 // Search
17657 if (obj.results) {
17658 var results = obj.results;
17659 } else {
17660 var results = obj.items;
17661 }
17662
17663 // Show 200 items at once
17664 var number = results.length || 0;
17665
17666 // Lazyloading
17667 if (obj.options.lazyLoading == true && number > 200) {
17668 number = 200;
17669 }
17670
17671 // Reset container
17672 content.textContent = '';
17673
17674 // First 200 items
17675 for (var i = 0; i < number; i++) {
17676 if (results[i].group) {
17677 if (!results[i].group.parentNode) {
17678 content.appendChild(results[i].group);
17679 }
17680 results[i].group.lastChild.appendChild(results[i].element);
17681 } else {
17682 content.appendChild(results[i].element);
17683 }
17684 }
17685
17686 // Scroll go to the begin
17687 content.scrollTop = 0;
17688 }
17689
17690 obj.loadLast = function () {
17691 // Search
17692 if (obj.results) {
17693 var results = obj.results;
17694 } else {
17695 var results = obj.items;
17696 }
17697
17698 // Show first page
17699 var number = results.length;
17700
17701 // Max 200 items
17702 if (number > 200) {
17703 number = number - 200;
17704
17705 // Reset container
17706 content.textContent = '';
17707
17708 // First 200 items
17709 for (var i = number; i < results.length; i++) {
17710 if (results[i].group) {
17711 if (!results[i].group.parentNode) {
17712 content.appendChild(results[i].group);
17713 }
17714 results[i].group.lastChild.appendChild(results[i].element);
17715 } else {
17716 content.appendChild(results[i].element);
17717 }
17718 }
17719
17720 // Scroll go to the begin
17721 content.scrollTop = content.scrollHeight;
17722 }
17723 }
17724
17725 obj.loadUp = function () {
17726 var test = false;
17727
17728 // Search
17729 if (obj.results) {
17730 var results = obj.results;
17731 } else {
17732 var results = obj.items;
17733 }
17734
17735 var items = content.querySelectorAll('.jdropdown-item');
17736 var fistItem = items[0].indexValue;
17737 fistItem = obj.items[fistItem];
17738 var index = results.indexOf(fistItem) - 1;
17739
17740 if (index > 0) {
17741 var number = 0;
17742
17743 while (index > 0 && results[index] && number < 200) {
17744 if (results[index].group) {
17745 if (!results[index].group.parentNode) {
17746 content.insertBefore(results[index].group, content.firstChild);
17747 }
17748 results[index].group.lastChild.insertBefore(results[index].element, results[index].group.lastChild.firstChild);
17749 } else {
17750 content.insertBefore(results[index].element, content.firstChild);
17751 }
17752
17753 index--;
17754 number++;
17755 }
17756
17757 // New item added
17758 test = true;
17759 }
17760
17761 return test;
17762 }
17763
17764 obj.loadDown = function () {
17765 var test = false;
17766
17767 // Search
17768 if (obj.results) {
17769 var results = obj.results;
17770 } else {
17771 var results = obj.items;
17772 }
17773
17774 var items = content.querySelectorAll('.jdropdown-item');
17775 var lastItem = items[items.length - 1].indexValue;
17776 lastItem = obj.items[lastItem];
17777 var index = results.indexOf(lastItem) + 1;
17778
17779 if (index < results.length) {
17780 var number = 0;
17781 while (index < results.length && results[index] && number < 200) {
17782 if (results[index].group) {
17783 if (!results[index].group.parentNode) {
17784 content.appendChild(results[index].group);
17785 }
17786 results[index].group.lastChild.appendChild(results[index].element);
17787 } else {
17788 content.appendChild(results[index].element);
17789 }
17790
17791 index++;
17792 number++;
17793 }
17794
17795 // New item added
17796 test = true;
17797 }
17798
17799 return test;
17800 }
17801
17802 init();
17803
17804 return obj;
17805 });
17806
17807 Component.keydown = function (e) {
17808 var dropdown = null;
17809 if (dropdown = Component.current) {
17810 if (e.which == 13 || e.which == 9) { // enter or tab
17811 if (dropdown.header.value && dropdown.currentIndex == null && dropdown.options.newOptions) {
17812 // if they typed something in, but it matched nothing, and newOptions are allowed, start that flow
17813 dropdown.add();
17814 } else {
17815 // Quick Select/Filter
17816 if (dropdown.currentIndex == null && dropdown.options.autocomplete == true && dropdown.header.value != "") {
17817 dropdown.find(dropdown.header.value);
17818 }
17819 dropdown.selectIndex(dropdown.currentIndex);
17820 }
17821 } else if (e.which == 38) { // up arrow
17822 if (dropdown.currentIndex == null) {
17823 dropdown.first();
17824 } else if (dropdown.currentIndex > 0) {
17825 dropdown.prev();
17826 }
17827 e.preventDefault();
17828 } else if (e.which == 40) { // down arrow
17829 if (dropdown.currentIndex == null) {
17830 dropdown.first();
17831 } else if (dropdown.currentIndex + 1 < dropdown.items.length) {
17832 dropdown.next();
17833 }
17834 e.preventDefault();
17835 } else if (e.which == 36) {
17836 dropdown.first();
17837 if (!e.target.classList.contains('jdropdown-header')) {
17838 e.preventDefault();
17839 }
17840 } else if (e.which == 35) {
17841 dropdown.last();
17842 if (!e.target.classList.contains('jdropdown-header')) {
17843 e.preventDefault();
17844 }
17845 } else if (e.which == 27) {
17846 dropdown.close();
17847 } else if (e.which == 33) { // page up
17848 if (dropdown.currentIndex == null) {
17849 dropdown.first();
17850 } else if (dropdown.currentIndex > 0) {
17851 for (var i = 0; i < 7; i++) {
17852 dropdown.prev()
17853 }
17854 }
17855 e.preventDefault();
17856 } else if (e.which == 34) { // page down
17857 if (dropdown.currentIndex == null) {
17858 dropdown.first();
17859 } else if (dropdown.currentIndex + 1 < dropdown.items.length) {
17860 for (var i = 0; i < 7; i++) {
17861 dropdown.next()
17862 }
17863 }
17864 e.preventDefault();
17865 }
17866 }
17867 }
17868
17869 Component.mouseup = function (e) {
17870 var element = helpers.findElement(e.target, 'jdropdown');
17871 if (element) {
17872 var dropdown = element.dropdown;
17873 if (e.target.classList.contains('jdropdown-header')) {
17874 if (element.classList.contains('jdropdown-focus') && element.classList.contains('jdropdown-default')) {
17875 var rect = element.getBoundingClientRect();
17876
17877 if (e.changedTouches && e.changedTouches[0]) {
17878 var x = e.changedTouches[0].clientX;
17879 var y = e.changedTouches[0].clientY;
17880 } else {
17881 var x = e.clientX;
17882 var y = e.clientY;
17883 }
17884
17885 if (rect.width - (x - rect.left) < 30) {
17886 if (e.target.classList.contains('jdropdown-add')) {
17887 dropdown.add();
17888 } else {
17889 dropdown.close();
17890 }
17891 } else {
17892 if (dropdown.options.autocomplete == false) {
17893 dropdown.close();
17894 }
17895 }
17896 } else {
17897 dropdown.open();
17898 }
17899 } else if (e.target.classList.contains('jdropdown-group-name')) {
17900 var items = e.target.nextSibling.children;
17901 if (e.target.nextSibling.style.display != 'none') {
17902 for (var i = 0; i < items.length; i++) {
17903 if (items[i].style.display != 'none') {
17904 dropdown.selectItem(items[i]);
17905 }
17906 }
17907 }
17908 } else if (e.target.classList.contains('jdropdown-group-arrow')) {
17909 if (e.target.classList.contains('jdropdown-group-arrow-down')) {
17910 e.target.classList.remove('jdropdown-group-arrow-down');
17911 e.target.classList.add('jdropdown-group-arrow-up');
17912 e.target.parentNode.nextSibling.style.display = 'none';
17913 } else {
17914 e.target.classList.remove('jdropdown-group-arrow-up');
17915 e.target.classList.add('jdropdown-group-arrow-down');
17916 e.target.parentNode.nextSibling.style.display = '';
17917 }
17918 } else if (e.target.classList.contains('jdropdown-item')) {
17919 dropdown.selectItem(e.target);
17920 } else if (e.target.classList.contains('jdropdown-image')) {
17921 dropdown.selectItem(e.target.parentNode);
17922 } else if (e.target.classList.contains('jdropdown-description')) {
17923 dropdown.selectItem(e.target.parentNode);
17924 } else if (e.target.classList.contains('jdropdown-title')) {
17925 dropdown.selectItem(e.target.parentNode.parentNode);
17926 } else if (e.target.classList.contains('jdropdown-close') || e.target.classList.contains('jdropdown-backdrop')) {
17927 dropdown.close();
17928 }
17929 }
17930 }
17931
17932 Component.extractFromDom = function (el, options) {
17933 // Keep reference
17934 var select = el;
17935 if (!options) {
17936 options = {};
17937 }
17938 // Prepare configuration
17939 if (el.getAttribute('multiple') && (!options || options.multiple == undefined)) {
17940 options.multiple = true;
17941 }
17942 if (el.getAttribute('placeholder') && (!options || options.placeholder == undefined)) {
17943 options.placeholder = el.getAttribute('placeholder');
17944 }
17945 if (el.getAttribute('data-autocomplete') && (!options || options.autocomplete == undefined)) {
17946 options.autocomplete = true;
17947 }
17948 if (!options || options.width == undefined) {
17949 options.width = el.offsetWidth;
17950 }
17951 if (el.value && (!options || options.value == undefined)) {
17952 options.value = el.value;
17953 }
17954 if (!options || options.data == undefined) {
17955 options.data = [];
17956 for (var j = 0; j < el.children.length; j++) {
17957 if (el.children[j].tagName == 'OPTGROUP') {
17958 for (var i = 0; i < el.children[j].children.length; i++) {
17959 options.data.push({
17960 value: el.children[j].children[i].value,
17961 text: el.children[j].children[i].textContent,
17962 group: el.children[j].getAttribute('label'),
17963 });
17964 }
17965 } else {
17966 options.data.push({
17967 value: el.children[j].value,
17968 text: el.children[j].textContent,
17969 });
17970 }
17971 }
17972 }
17973 if (!options || options.onchange == undefined) {
17974 options.onchange = function (a, b, c, d) {
17975 if (options.multiple == true) {
17976 if (obj.items[b].classList.contains('jdropdown-selected')) {
17977 select.options[b].setAttribute('selected', 'selected');
17978 } else {
17979 select.options[b].removeAttribute('selected');
17980 }
17981 } else {
17982 select.value = d;
17983 }
17984 }
17985 }
17986 // Create DIV
17987 var div = document.createElement('div');
17988 el.parentNode.insertBefore(div, el);
17989 el.style.display = 'none';
17990 el = div;
17991
17992 return {el: el, options: options};
17993 }
17994
17995 return Component;
17996}
17997
17998/* harmony default export */ var dropdown = (Dropdown());
17999;// CONCATENATED MODULE: ./src/plugins/picker.js
18000
18001
18002
18003function Picker(el, options) {
18004 // Already created, update options
18005 if (el.picker) {
18006 return el.picker.setOptions(options, true);
18007 }
18008
18009 // New instance
18010 var obj = { type: 'picker' };
18011 obj.options = {};
18012
18013 var dropdownHeader = null;
18014 var dropdownContent = null;
18015
18016 /**
18017 * The element passed is a DOM element
18018 */
18019 var isDOM = function(o) {
18020 return (o instanceof Element || o instanceof HTMLDocument);
18021 }
18022
18023 /**
18024 * Create the content options
18025 */
18026 var createContent = function() {
18027 dropdownContent.innerHTML = '';
18028
18029 // Create items
18030 var keys = Object.keys(obj.options.data);
18031
18032 // Go though all options
18033 for (var i = 0; i < keys.length; i++) {
18034 // Item
18035 var dropdownItem = document.createElement('div');
18036 dropdownItem.classList.add('jpicker-item');
18037 dropdownItem.setAttribute('role', 'option');
18038 dropdownItem.k = keys[i];
18039 dropdownItem.v = obj.options.data[keys[i]];
18040 // Label
18041 var item = obj.getLabel(keys[i], dropdownItem);
18042 if (isDOM(item)) {
18043 dropdownItem.appendChild(item);
18044 } else {
18045 dropdownItem.innerHTML = item;
18046 }
18047 // Append
18048 dropdownContent.appendChild(dropdownItem);
18049 }
18050 }
18051
18052 /**
18053 * Set or reset the options for the picker
18054 */
18055 obj.setOptions = function(options, reset) {
18056 // Default configuration
18057 var defaults = {
18058 value: 0,
18059 data: null,
18060 render: null,
18061 onchange: null,
18062 onmouseover: null,
18063 onselect: null,
18064 onopen: null,
18065 onclose: null,
18066 onload: null,
18067 width: null,
18068 header: true,
18069 right: false,
18070 bottom: false,
18071 content: false,
18072 columns: null,
18073 grid: null,
18074 height: null,
18075 }
18076
18077 // Legacy purpose only
18078 if (options && options.options) {
18079 options.data = options.options;
18080 }
18081
18082 // Loop through the initial configuration
18083 for (var property in defaults) {
18084 if (options && options.hasOwnProperty(property)) {
18085 obj.options[property] = options[property];
18086 } else {
18087 if (typeof(obj.options[property]) == 'undefined' || reset === true) {
18088 obj.options[property] = defaults[property];
18089 }
18090 }
18091 }
18092
18093 // Start using the options
18094 if (obj.options.header === false) {
18095 dropdownHeader.style.display = 'none';
18096 } else {
18097 dropdownHeader.style.display = '';
18098 }
18099
18100 // Width
18101 if (obj.options.width) {
18102 dropdownHeader.style.width = parseInt(obj.options.width) + 'px';
18103 } else {
18104 dropdownHeader.style.width = '';
18105 }
18106
18107 // Height
18108 if (obj.options.height) {
18109 dropdownContent.style.maxHeight = obj.options.height + 'px';
18110 dropdownContent.style.overflow = 'scroll';
18111 } else {
18112 dropdownContent.style.overflow = '';
18113 }
18114
18115 if (obj.options.columns > 0) {
18116 if (! obj.options.grid) {
18117 dropdownContent.classList.add('jpicker-columns');
18118 dropdownContent.style.width = obj.options.width ? obj.options.width : 36 * obj.options.columns + 'px';
18119 } else {
18120 dropdownContent.classList.add('jpicker-grid');
18121 dropdownContent.style.gridTemplateColumns = 'repeat(' + obj.options.grid + ', 1fr)';
18122 }
18123 }
18124
18125 if (isNaN(parseInt(obj.options.value))) {
18126 obj.options.value = 0;
18127 }
18128
18129 // Create list from data
18130 createContent();
18131
18132 // Set value
18133 obj.setValue(obj.options.value);
18134
18135 // Set options all returns the own instance
18136 return obj;
18137 }
18138
18139 obj.getValue = function() {
18140 return obj.options.value;
18141 }
18142
18143 obj.setValue = function(k, e) {
18144 // Set label
18145 obj.setLabel(k);
18146
18147 // Update value
18148 obj.options.value = String(k);
18149
18150 // Lemonade JS
18151 if (el.value != obj.options.value) {
18152 el.value = obj.options.value;
18153 if (typeof(el.oninput) == 'function') {
18154 el.oninput({
18155 type: 'input',
18156 target: el,
18157 value: el.value
18158 });
18159 }
18160 }
18161
18162 if (dropdownContent.children[k] && dropdownContent.children[k].getAttribute('type') !== 'generic') {
18163 obj.close();
18164 }
18165
18166 // Call method
18167 if (e) {
18168 if (typeof (obj.options.onchange) == 'function') {
18169 var v = obj.options.data[k];
18170
18171 obj.options.onchange(el, obj, v, v, k, e);
18172 }
18173 }
18174 }
18175
18176 obj.getLabel = function(v, item) {
18177 var label = obj.options.data[v] || null;
18178 if (typeof(obj.options.render) == 'function') {
18179 label = obj.options.render(label, item);
18180 }
18181 return label;
18182 }
18183
18184 obj.setLabel = function(v) {
18185 var item;
18186
18187 if (obj.options.content) {
18188 item = document.createElement('i');
18189 item.textContent = obj.options.content;
18190 item.classList.add('material-icons');
18191 } else {
18192 item = obj.getLabel(v, null);
18193 }
18194
18195 // Label
18196 if (isDOM(item)) {
18197 dropdownHeader.textContent = '';
18198 dropdownHeader.appendChild(item);
18199 } else {
18200 dropdownHeader.innerHTML = item;
18201 }
18202 }
18203
18204 obj.open = function() {
18205 if (! el.classList.contains('jpicker-focus')) {
18206 // Start tracking the element
18207 tracking(obj, true);
18208
18209 // Open picker
18210 el.classList.add('jpicker-focus');
18211 el.focus();
18212
18213 var top = 0;
18214 var left = 0;
18215
18216 dropdownContent.style.marginLeft = '';
18217
18218 var rectHeader = dropdownHeader.getBoundingClientRect();
18219 var rectContent = dropdownContent.getBoundingClientRect();
18220
18221 if (window.innerHeight < rectHeader.bottom + rectContent.height || obj.options.bottom) {
18222 top = -1 * (rectContent.height + 4);
18223 } else {
18224 top = rectHeader.height + 4;
18225 }
18226
18227 if (obj.options.right === true) {
18228 left = -1 * rectContent.width + rectHeader.width;
18229 }
18230
18231 if (rectContent.left + left < 0) {
18232 left = left + rectContent.left + 10;
18233 }
18234 if (rectContent.left + rectContent.width > window.innerWidth) {
18235 left = -1 * (10 + rectContent.left + rectContent.width - window.innerWidth);
18236 }
18237
18238 dropdownContent.style.marginTop = parseInt(top) + 'px';
18239 dropdownContent.style.marginLeft = parseInt(left) + 'px';
18240
18241 //dropdownContent.style.marginTop
18242 if (typeof obj.options.onopen == 'function') {
18243 obj.options.onopen(el, obj);
18244 }
18245 }
18246 }
18247
18248 obj.close = function() {
18249 if (el.classList.contains('jpicker-focus')) {
18250 el.classList.remove('jpicker-focus');
18251
18252 // Start tracking the element
18253 tracking(obj, false);
18254
18255 if (typeof obj.options.onclose == 'function') {
18256 obj.options.onclose(el, obj);
18257 }
18258 }
18259 }
18260
18261 /**
18262 * Destroy the picker instance and release all resources
18263 */
18264 obj.destroy = function() {
18265 // Close if open (removes from tracking)
18266 obj.close();
18267
18268 // Remove event listeners
18269 el.onmousedown = null;
18270 if (dropdownContent) {
18271 dropdownContent.onclick = null;
18272 }
18273
18274 // Remove created DOM elements
18275 if (dropdownHeader && dropdownHeader.parentNode) {
18276 dropdownHeader.parentNode.removeChild(dropdownHeader);
18277 }
18278 if (dropdownContent && dropdownContent.parentNode) {
18279 dropdownContent.parentNode.removeChild(dropdownContent);
18280 }
18281
18282 // Remove classes and attributes from el
18283 el.classList.remove('jpicker');
18284 el.classList.remove('jpicker-focus');
18285 el.removeAttribute('role');
18286 el.removeAttribute('aria-haspopup');
18287 el.removeAttribute('aria-expanded');
18288 el.removeAttribute('aria-controls');
18289 el.removeAttribute('tabindex');
18290
18291 // Remove instance properties from el
18292 delete el.picker;
18293 delete el.value;
18294 delete el.change;
18295 delete el.val;
18296
18297 // Clear options callbacks to release closures
18298 if (obj.options) {
18299 obj.options.onchange = null;
18300 obj.options.onclose = null;
18301 obj.options.onopen = null;
18302 obj.options.onload = null;
18303 obj.options.onselect = null;
18304 obj.options.onmouseover = null;
18305 obj.options.render = null;
18306 }
18307
18308 // Clear references
18309 dropdownHeader = null;
18310 dropdownContent = null;
18311 }
18312
18313 /**
18314 * Create floating picker
18315 */
18316 var init = function() {
18317 let id = helpers.guid();
18318
18319 // Class
18320 el.classList.add('jpicker');
18321 el.setAttribute('role', 'combobox');
18322 el.setAttribute('aria-haspopup', 'listbox');
18323 el.setAttribute('aria-expanded', 'false');
18324 el.setAttribute('aria-controls', id);
18325 el.setAttribute('tabindex', '0');
18326 el.onmousedown = function(e) {
18327 if (! el.classList.contains('jpicker-focus')) {
18328 obj.open();
18329 }
18330 }
18331
18332 // Dropdown Header
18333 dropdownHeader = document.createElement('div');
18334 dropdownHeader.classList.add('jpicker-header');
18335
18336 // Dropdown content
18337 dropdownContent = document.createElement('div');
18338 dropdownContent.setAttribute('id', id);
18339 dropdownContent.setAttribute('role', 'listbox');
18340 dropdownContent.classList.add('jpicker-content');
18341 dropdownContent.onclick = function(e) {
18342 var item = helpers.findElement(e.target, 'jpicker-item');
18343 if (item) {
18344 if (item.parentNode === dropdownContent) {
18345 // Update label
18346 obj.setValue(item.k, e);
18347 }
18348 }
18349 }
18350 // Append content and header
18351 el.appendChild(dropdownHeader);
18352 el.appendChild(dropdownContent);
18353
18354 // Default value
18355 el.value = options.value || 0;
18356
18357 // Set options
18358 obj.setOptions(options);
18359
18360 if (typeof(obj.options.onload) == 'function') {
18361 obj.options.onload(el, obj);
18362 }
18363
18364 // Change
18365 el.change = obj.setValue;
18366
18367 // Global generic value handler
18368 el.val = function(val) {
18369 if (val === undefined) {
18370 return obj.getValue();
18371 } else {
18372 obj.setValue(val);
18373 }
18374 }
18375
18376 // Reference
18377 el.picker = obj;
18378 }
18379
18380 init();
18381
18382 return obj;
18383}
18384;// CONCATENATED MODULE: ./src/plugins/toolbar.js
18385
18386
18387
18388
18389
18390function Toolbar(el, options) {
18391 // New instance
18392 var obj = { type:'toolbar' };
18393 obj.options = {};
18394
18395 // Track internal components for cleanup
18396 var internalComponents = [];
18397
18398 // Event handler references for cleanup
18399 var elClickHandler = null;
18400 var windowResizeHandler = null;
18401
18402 // Default configuration
18403 var defaults = {
18404 app: null,
18405 container: false,
18406 badge: false,
18407 title: false,
18408 responsive: false,
18409 maxWidth: null,
18410 bottom: true,
18411 items: [],
18412 }
18413
18414 // Loop through our object
18415 for (var property in defaults) {
18416 if (options && options.hasOwnProperty(property)) {
18417 obj.options[property] = options[property];
18418 } else {
18419 obj.options[property] = defaults[property];
18420 }
18421 }
18422
18423 if (! el && options.app && options.app.el) {
18424 el = document.createElement('div');
18425 options.app.el.appendChild(el);
18426 }
18427
18428 // Arrow
18429 var toolbarArrow = document.createElement('div');
18430 toolbarArrow.classList.add('jtoolbar-item');
18431 toolbarArrow.classList.add('jtoolbar-arrow');
18432
18433 let arrow = document.createElement('i');
18434 arrow.classList.add('material-icons');
18435 arrow.textContent = 'more_vert';
18436 toolbarArrow.appendChild(arrow);
18437
18438 var toolbarFloating = document.createElement('div');
18439 toolbarFloating.classList.add('jtoolbar-floating');
18440 toolbarArrow.appendChild(toolbarFloating);
18441
18442 obj.selectItem = function(element) {
18443 var elements = toolbarContent.children;
18444 for (var i = 0; i < elements.length; i++) {
18445 if (element != elements[i]) {
18446 elements[i].classList.remove('jtoolbar-selected');
18447 }
18448 }
18449 element.classList.add('jtoolbar-selected');
18450 }
18451
18452 obj.hide = function() {
18453 animation.slideBottom(el, 0, function() {
18454 el.style.display = 'none';
18455 });
18456 }
18457
18458 obj.show = function() {
18459 el.style.display = '';
18460 animation.slideBottom(el, 1);
18461 }
18462
18463 obj.get = function() {
18464 return el;
18465 }
18466
18467 obj.setBadge = function(index, value) {
18468 toolbarContent.children[index].children[1].firstChild.innerHTML = value;
18469 }
18470
18471 obj.destroy = function() {
18472 // Close if open (removes from tracking)
18473 obj.close();
18474
18475 // Destroy all internal components (pickers, etc.)
18476 for (var i = 0; i < internalComponents.length; i++) {
18477 var comp = internalComponents[i];
18478 if (comp) {
18479 // First destroy any nested components created in onload (stored on the picker instance)
18480 if (comp.components && comp.components.length) {
18481 for (var j = 0; j < comp.components.length; j++) {
18482 if (comp.components[j] && typeof comp.components[j].destroy === 'function') {
18483 comp.components[j].destroy();
18484 }
18485 }
18486 comp.components = null;
18487 }
18488 // Then destroy the picker/component itself
18489 if (typeof comp.destroy === 'function') {
18490 comp.destroy();
18491 }
18492 }
18493 }
18494 internalComponents = [];
18495
18496 // Clear onclick handlers from DOM elements (releases bound function references)
18497 if (toolbarContent) {
18498 var items = toolbarContent.querySelectorAll('.jtoolbar-item');
18499 for (var i = 0; i < items.length; i++) {
18500 items[i].onclick = null;
18501 items[i].updateState = null;
18502 }
18503 }
18504 if (toolbarFloating) {
18505 var items = toolbarFloating.querySelectorAll('.jtoolbar-item');
18506 for (var i = 0; i < items.length; i++) {
18507 items[i].onclick = null;
18508 items[i].updateState = null;
18509 }
18510 }
18511
18512 // Clear options items callbacks to release closures
18513 if (obj.options && obj.options.items) {
18514 for (var i = 0; i < obj.options.items.length; i++) {
18515 var item = obj.options.items[i];
18516 // Clear all callback references
18517 item.onclick = null;
18518 item.onchange = null;
18519 item.onload = null;
18520 item.render = null;
18521 item.updateState = null;
18522 item.onopen = null;
18523 item.onclose = null;
18524 }
18525 obj.options.items = null;
18526 }
18527
18528 // Remove event listeners
18529 if (elClickHandler) {
18530 el.removeEventListener('click', elClickHandler);
18531 elClickHandler = null;
18532 }
18533 if (windowResizeHandler) {
18534 window.removeEventListener('resize', windowResizeHandler);
18535 windowResizeHandler = null;
18536 }
18537
18538 // Clear DOM
18539 el.innerHTML = '';
18540
18541 // Clear references
18542 toolbarContent = null;
18543 toolbarFloating = null;
18544 toolbarArrow = null;
18545
18546 // Remove classes
18547 el.classList.remove('jtoolbar');
18548 el.classList.remove('jtoolbar-container');
18549 el.classList.remove('jtoolbar-mobile');
18550 el.classList.remove('jtoolbar-disabled');
18551
18552 // Remove instance reference
18553 delete el.toolbar;
18554 }
18555
18556 obj.update = function(a, b) {
18557 for (var i = 0; i < toolbarContent.children.length; i++) {
18558 // Toolbar element
18559 var toolbarItem = toolbarContent.children[i];
18560 // State management
18561 if (typeof(toolbarItem.updateState) == 'function') {
18562 toolbarItem.updateState(el, obj, toolbarItem, a, b);
18563 }
18564 }
18565 for (var i = 0; i < toolbarFloating.children.length; i++) {
18566 // Toolbar element
18567 var toolbarItem = toolbarFloating.children[i];
18568 // State management
18569 if (typeof(toolbarItem.updateState) == 'function') {
18570 toolbarItem.updateState(el, obj, toolbarItem, a, b);
18571 }
18572 }
18573 }
18574
18575 obj.create = function(items) {
18576 // Reset anything in the toolbar
18577 toolbarContent.innerHTML = '';
18578 // Create elements in the toolbar
18579 for (var i = 0; i < items.length; i++) {
18580 var toolbarItem = document.createElement('div');
18581 toolbarItem.classList.add('jtoolbar-item');
18582
18583 if (items[i].width) {
18584 toolbarItem.style.width = parseInt(items[i].width) + 'px';
18585 }
18586
18587 if (items[i].k) {
18588 toolbarItem.k = items[i].k;
18589 }
18590
18591 if (items[i].tooltip) {
18592 toolbarItem.setAttribute('title', items[i].tooltip);
18593 toolbarItem.setAttribute('aria-label', items[i].tooltip);
18594 }
18595
18596 // Id
18597 if (items[i].id) {
18598 toolbarItem.setAttribute('id', items[i].id);
18599 }
18600
18601 // Selected
18602 if (items[i].updateState) {
18603 toolbarItem.updateState = items[i].updateState;
18604 }
18605
18606 if (items[i].active) {
18607 toolbarItem.classList.add('jtoolbar-active');
18608 }
18609
18610 if (items[i].disabled) {
18611 toolbarItem.classList.add('jtoolbar-disabled');
18612 }
18613
18614 if (items[i].type == 'select' || items[i].type == 'dropdown') {
18615 var picker = Picker(toolbarItem, items[i]);
18616 internalComponents.push(picker);
18617 } else if (items[i].type == 'divisor') {
18618 toolbarItem.classList.add('jtoolbar-divisor');
18619 } else if (items[i].type == 'label') {
18620 toolbarItem.classList.add('jtoolbar-label');
18621 toolbarItem.innerHTML = items[i].content;
18622 } else {
18623 // Material icons
18624 var toolbarIcon = document.createElement('i');
18625 if (typeof(items[i].class) === 'undefined') {
18626 toolbarIcon.classList.add('material-icons');
18627 } else {
18628 var c = items[i].class.split(' ');
18629 for (var j = 0; j < c.length; j++) {
18630 toolbarIcon.classList.add(c[j]);
18631 }
18632 }
18633 toolbarIcon.innerHTML = items[i].content ? items[i].content : '';
18634 toolbarItem.setAttribute('role', 'button');
18635 toolbarItem.appendChild(toolbarIcon);
18636
18637 // Badge options
18638 if (obj.options.badge == true) {
18639 var toolbarBadge = document.createElement('div');
18640 toolbarBadge.classList.add('jbadge');
18641 var toolbarBadgeContent = document.createElement('div');
18642 toolbarBadgeContent.innerHTML = items[i].badge ? items[i].badge : '';
18643 toolbarBadge.appendChild(toolbarBadgeContent);
18644 toolbarItem.appendChild(toolbarBadge);
18645 }
18646
18647 // Title
18648 if (items[i].title) {
18649 if (obj.options.title == true) {
18650 var toolbarTitle = document.createElement('span');
18651 toolbarTitle.innerHTML = items[i].title;
18652 toolbarItem.appendChild(toolbarTitle);
18653 } else {
18654 toolbarItem.setAttribute('title', items[i].title);
18655 }
18656 }
18657
18658 if (obj.options.app && items[i].route) {
18659 // Route
18660 toolbarItem.route = items[i].route;
18661 // Onclick for route
18662 toolbarItem.onclick = function() {
18663 obj.options.app.pages(this.route);
18664 }
18665 // Create pages
18666 obj.options.app.pages(items[i].route, {
18667 toolbarItem: toolbarItem,
18668 closed: true
18669 });
18670 }
18671
18672 // Render
18673 if (typeof(items[i].render) === 'function') {
18674 items[i].render(toolbarItem, items[i]);
18675 }
18676 }
18677
18678 if (items[i].onclick) {
18679 toolbarItem.onclick = items[i].onclick.bind(items[i], el, obj, toolbarItem);
18680 }
18681
18682 toolbarContent.appendChild(toolbarItem);
18683 }
18684
18685 // Fits to the page
18686 setTimeout(function() {
18687 obj.refresh();
18688 }, 0);
18689 }
18690
18691 obj.open = function() {
18692 toolbarArrow.classList.add('jtoolbar-arrow-selected');
18693
18694 var rectElement = el.getBoundingClientRect();
18695 var rect = toolbarFloating.getBoundingClientRect();
18696 if (rect.bottom > window.innerHeight || obj.options.bottom) {
18697 toolbarFloating.style.bottom = '0';
18698 } else {
18699 toolbarFloating.style.removeProperty('bottom');
18700 }
18701
18702 toolbarFloating.style.right = '0';
18703
18704 toolbarArrow.children[1].focus();
18705 // Start tracking
18706 tracking(obj, true);
18707 }
18708
18709 obj.close = function() {
18710 if (toolbarArrow) {
18711 toolbarArrow.classList.remove('jtoolbar-arrow-selected')
18712 }
18713 // End tracking
18714 tracking(obj, false);
18715 }
18716
18717 obj.refresh = function() {
18718 if (obj.options.responsive == true) {
18719 // Width of the c
18720 var rect = el.parentNode.getBoundingClientRect();
18721 if (! obj.options.maxWidth) {
18722 obj.options.maxWidth = rect.width;
18723 }
18724 // Available parent space
18725 var available = parseInt(obj.options.maxWidth);
18726 // Remove arrow
18727 if (toolbarArrow.parentNode) {
18728 toolbarArrow.parentNode.removeChild(toolbarArrow);
18729 }
18730 // Move all items to the toolbar
18731 while (toolbarFloating.firstChild) {
18732 toolbarContent.appendChild(toolbarFloating.firstChild);
18733 }
18734 // Toolbar is larger than the parent, move elements to the floating element
18735 if (available < toolbarContent.offsetWidth) {
18736 // Give space to the floating element
18737 available -= 50;
18738 // Move to the floating option
18739 while (toolbarContent.lastChild && available < toolbarContent.offsetWidth) {
18740 toolbarFloating.insertBefore(toolbarContent.lastChild, toolbarFloating.firstChild);
18741 }
18742 }
18743 // Show arrow
18744 if (toolbarFloating.children.length > 0) {
18745 toolbarContent.appendChild(toolbarArrow);
18746 }
18747 }
18748 }
18749
18750 obj.setReadonly = function(state) {
18751 state = state ? 'add' : 'remove';
18752 el.classList[state]('jtoolbar-disabled');
18753 }
18754
18755 elClickHandler = function(e) {
18756 var element = helpers.findElement(e.target, 'jtoolbar-item');
18757 if (element) {
18758 obj.selectItem(element);
18759 }
18760
18761 if (e.target.classList.contains('jtoolbar-arrow') || e.target.parentNode.classList.contains('jtoolbar-arrow')) {
18762 obj.open();
18763 }
18764 };
18765 el.addEventListener('click', elClickHandler);
18766
18767 windowResizeHandler = function() {
18768 obj.refresh();
18769 };
18770 window.addEventListener('resize', windowResizeHandler);
18771
18772 // Toolbar
18773 el.classList.add('jtoolbar');
18774 // Reset content
18775 el.innerHTML = '';
18776 // Container
18777 if (obj.options.container == true) {
18778 el.classList.add('jtoolbar-container');
18779 }
18780 // Content
18781 var toolbarContent = document.createElement('div');
18782 el.appendChild(toolbarContent);
18783 // Special toolbar for mobile applications
18784 if (obj.options.app) {
18785 el.classList.add('jtoolbar-mobile');
18786 }
18787 // Create toolbar
18788 obj.create(obj.options.items);
18789 // Shortcut
18790 el.toolbar = obj;
18791
18792 return obj;
18793}
18794;// CONCATENATED MODULE: ./src/utils/filter.js
18795
18796// Valid tags (removed iframe for security)
18797const validTags = [
18798 'html','body','address','span', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'b', 'i', 'blockquote',
18799 'strong', 'em', 'ul', 'ol', 'li', 'a', 'code', 'pre', 'hr', 'br', 'img',
18800 'figure', 'picture', 'figcaption', 'table', 'thead', 'tbody', 'tfoot', 'tr',
18801 'th', 'td', 'caption', 'u', 'del', 'ins', 'sub', 'sup', 'small', 'mark',
18802 'input', 'textarea', 'select', 'option', 'button', 'label', 'fieldset',
18803 'legend', 'audio', 'video', 'abbr', 'cite', 'kbd', 'section', 'article',
18804 'nav', 'aside', 'header', 'footer', 'main', 'details', 'summary', 'svg', 'line', 'source'
18805];
18806
18807// Dangerous tags that should be completely removed
18808const dangerousTags = ['script', 'object', 'embed', 'applet', 'meta', 'base', 'link', 'iframe'];
18809
18810// Valid properties (added id, class, title, alt for better editor support)
18811const validProperty = ['width', 'height', 'align', 'border', 'src', 'href', 'tabindex', 'id', 'class', 'title', 'alt'];
18812
18813// Tags that are allowed to have src attribute
18814const tagsAllowedSrc = ['img', 'audio', 'video', 'source'];
18815
18816// Tags that are allowed to have href attribute
18817const tagsAllowedHref = ['a'];
18818
18819// Valid CSS attributes
18820const validStyle = ['color', 'font-weight', 'font-size', 'background', 'background-color', 'margin', 'padding', 'text-align', 'text-decoration'];
18821
18822// Function to decode HTML entities (prevents bypassing with &#106;avascript:)
18823function decodeHTMLEntities(text) {
18824 if (!text) return '';
18825 const textArea = document.createElement('textarea');
18826 textArea.innerHTML = text;
18827 return textArea.value;
18828}
18829
18830// Function to check if a URL scheme is dangerous
18831function isDangerousURL(url) {
18832 if (!url) return false;
18833 const decoded = decodeHTMLEntities(url).toLowerCase().trim();
18834 // Remove whitespace and null bytes that can be used to bypass filters
18835 const cleaned = decoded.replace(/[\s\0]/g, '');
18836
18837 return cleaned.startsWith('javascript:') ||
18838 cleaned.startsWith('data:text/') ||
18839 cleaned.startsWith('data:application/') ||
18840 cleaned.startsWith('vbscript:') ||
18841 cleaned.includes('<script');
18842}
18843
18844// Function to sanitize CSS value
18845function sanitizeStyleValue(value) {
18846 if (!value) return '';
18847 const decoded = decodeHTMLEntities(value).toLowerCase();
18848
18849 // Block dangerous CSS content
18850 if (decoded.includes('javascript:') ||
18851 decoded.includes('expression(') ||
18852 decoded.includes('behavior:') ||
18853 decoded.includes('-moz-binding') ||
18854 decoded.includes('binding:') ||
18855 decoded.includes('@import') ||
18856 decoded.includes('url(') && (decoded.includes('javascript:') || decoded.includes('data:'))) {
18857 return '';
18858 }
18859
18860 return value;
18861}
18862
18863const parse = function(element, img) {
18864 if (!element || !element.tagName) {
18865 return;
18866 }
18867
18868 const tagName = element.tagName.toLowerCase();
18869
18870 // Remove dangerous tags completely
18871 if (dangerousTags.indexOf(tagName) !== -1) {
18872 if (element.parentNode) {
18873 element.parentNode.removeChild(element);
18874 }
18875 return;
18876 }
18877
18878 // Remove elements that are not white-listed
18879 if (validTags.indexOf(tagName) === -1) {
18880 if (element.innerText) {
18881 element.innerHTML = element.innerText;
18882 }
18883 }
18884
18885 // Remove attributes
18886 if (element.attributes && element.attributes.length) {
18887 let style = null;
18888 // Process style attribute
18889 let elementStyle = element.getAttribute('style');
18890 if (elementStyle) {
18891 style = [];
18892 let t = elementStyle.split(';');
18893 for (let j = 0; j < t.length; j++) {
18894 let v = t[j].trim().split(':');
18895 const property = v[0].trim();
18896 if (validStyle.indexOf(property) >= 0) {
18897 let k = v.shift();
18898 v = v.join(':');
18899 // Sanitize the CSS value
18900 const sanitizedValue = sanitizeStyleValue(v);
18901 if (sanitizedValue) {
18902 style.push(k + ':' + sanitizedValue);
18903 }
18904 }
18905 }
18906 }
18907
18908 // Process image
18909 if (tagName === 'img') {
18910 const src = element.getAttribute('src');
18911 if (!src || isDangerousURL(src)) {
18912 if (element.parentNode) {
18913 element.parentNode.removeChild(element);
18914 }
18915 return;
18916 } else {
18917 element.setAttribute('tabindex', '900');
18918 // Check attributes for persistence
18919 img.push(src);
18920 }
18921 }
18922
18923 // Collect all attribute names first
18924 let attr = [];
18925 for (let i = 0; i < element.attributes.length; i++) {
18926 attr.push(element.attributes[i].name);
18927 }
18928
18929 // Process attributes
18930 if (attr.length) {
18931 attr.forEach(function (v) {
18932 const attrName = v.toLowerCase();
18933
18934 // Remove all event handlers (onclick, onerror, onload, etc.)
18935 if (attrName.startsWith('on')) {
18936 element.removeAttribute(v);
18937 return;
18938 }
18939
18940 // Check if attribute is in whitelist
18941 if (validProperty.indexOf(attrName) === -1) {
18942 element.removeAttribute(v);
18943 } else {
18944 // Validate whitelisted attributes
18945 let attrValue = element.getAttribute(v);
18946
18947 // Special handling for src attribute
18948 if (attrName === 'src') {
18949 if (tagsAllowedSrc.indexOf(tagName) === -1) {
18950 // src not allowed on this tag
18951 element.removeAttribute(v);
18952 return;
18953 }
18954 if (isDangerousURL(attrValue)) {
18955 element.removeAttribute(v);
18956 return;
18957 }
18958 }
18959
18960 // Special handling for href attribute
18961 if (attrName === 'href') {
18962 if (tagsAllowedHref.indexOf(tagName) === -1) {
18963 // href not allowed on this tag
18964 element.removeAttribute(v);
18965 return;
18966 }
18967 if (isDangerousURL(attrValue)) {
18968 element.removeAttribute(v);
18969 return;
18970 }
18971 }
18972
18973 // Protection XSS - check for dangerous characters
18974 if (attrValue && attrValue.indexOf('<') !== -1) {
18975 element.setAttribute(v, attrValue.replace(/</g, '&#60;'));
18976 }
18977 }
18978 });
18979 }
18980
18981 element.style = '';
18982 // Add valid style
18983 if (style && style.length) {
18984 element.setAttribute('style', style.join(';'));
18985 }
18986 }
18987
18988 // Parse children recursively
18989 if (element.children.length) {
18990 for (let i = element.children.length; i > 0; i--) {
18991 parse(element.children[i - 1], img);
18992 }
18993 }
18994}
18995
18996const filter = function(data, img) {
18997 if (data) {
18998 data = data.replace(new RegExp('<!--(.*?)-->', 'gsi'), '');
18999 }
19000 let parser = new DOMParser();
19001 let d = parser.parseFromString(data, "text/html");
19002 parse(d.body, img);
19003 let div = document.createElement('div');
19004 div.innerHTML = d.body.innerHTML;
19005 return div;
19006}
19007
19008/* harmony default export */ var utils_filter = (filter);
19009;// CONCATENATED MODULE: ./src/plugins/editor.js
19010
19011
19012
19013
19014
19015
19016function Editor() {
19017 var Component = (function(el, options) {
19018 // New instance
19019 var obj = { type:'editor' };
19020 obj.options = {};
19021
19022 // Default configuration
19023 var defaults = {
19024 // Load data from a remove location
19025 url: null,
19026 // Initial HTML content
19027 value: '',
19028 // Initial snippet
19029 snippet: null,
19030 // Add toolbar
19031 toolbar: true,
19032 toolbarOnTop: false,
19033 // Website parser is to read websites and images from cross domain
19034 remoteParser: null,
19035 // Placeholder
19036 placeholder: null,
19037 // Parse URL
19038 filterPaste: true,
19039 // Accept drop files
19040 dropZone: true,
19041 dropAsSnippet: false,
19042 acceptImages: true,
19043 acceptFiles: false,
19044 maxFileSize: 5000000,
19045 allowImageResize: true,
19046 // Style
19047 maxHeight: null,
19048 height: null,
19049 focus: false,
19050 // Events
19051 onclick: null,
19052 onfocus: null,
19053 onblur: null,
19054 onload: null,
19055 onkeyup: null,
19056 onkeydown: null,
19057 onchange: null,
19058 extensions: null,
19059 type: null,
19060 };
19061
19062 // Loop through our object
19063 for (var property in defaults) {
19064 if (options && options.hasOwnProperty(property)) {
19065 obj.options[property] = options[property];
19066 } else {
19067 obj.options[property] = defaults[property];
19068 }
19069 }
19070
19071 // Private controllers
19072 var editorTimer = null;
19073 var editorAction = null;
19074 var files = [];
19075
19076 // Keep the reference for the container
19077 obj.el = el;
19078
19079 if (typeof(obj.options.onclick) == 'function') {
19080 el.onclick = function(e) {
19081 obj.options.onclick(el, obj, e);
19082 }
19083 }
19084
19085 // Prepare container
19086 el.classList.add('jeditor-container');
19087
19088 // Snippet
19089 var snippet = document.createElement('div');
19090 snippet.className = 'jsnippet';
19091 snippet.setAttribute('contenteditable', false);
19092
19093 // Toolbar
19094 var toolbar = document.createElement('div');
19095 toolbar.className = 'jeditor-toolbar';
19096
19097 obj.editor = document.createElement('div');
19098 obj.editor.setAttribute('contenteditable', true);
19099 obj.editor.setAttribute('spellcheck', false);
19100 obj.editor.classList.add('jeditor');
19101
19102 // Placeholder
19103 if (obj.options.placeholder) {
19104 obj.editor.setAttribute('data-placeholder', obj.options.placeholder);
19105 }
19106
19107 // Max height
19108 if (obj.options.maxHeight || obj.options.height) {
19109 obj.editor.style.overflowY = 'auto';
19110
19111 if (obj.options.maxHeight) {
19112 obj.editor.style.maxHeight = obj.options.maxHeight;
19113 }
19114 if (obj.options.height) {
19115 obj.editor.style.height = obj.options.height;
19116 }
19117 }
19118
19119 // Set editor initial value
19120 if (obj.options.url) {
19121 ajax({
19122 url: obj.options.url,
19123 dataType: 'html',
19124 success: function(result) {
19125 obj.editor.innerHTML = result;
19126
19127 Component.setCursor(obj.editor, obj.options.focus == 'initial' ? true : false);
19128 }
19129 })
19130 } else {
19131 if (obj.options.value) {
19132 obj.editor.innerHTML = obj.options.value;
19133 } else {
19134 // Create from existing elements
19135 for (var i = 0; i < el.children.length; i++) {
19136 obj.editor.appendChild(el.children[i]);
19137 }
19138 }
19139 }
19140
19141 // Make sure element is empty
19142 el.innerHTML = '';
19143
19144 /**
19145 * Onchange event controllers
19146 */
19147 var change = function(e) {
19148 if (typeof(obj.options.onchange) == 'function') {
19149 obj.options.onchange(el, obj, e);
19150 }
19151
19152 // Update value
19153 obj.options.value = obj.getData();
19154
19155 // Lemonade JS
19156 if (el.value != obj.options.value) {
19157 el.value = obj.options.value;
19158 if (typeof(el.oninput) == 'function') {
19159 el.oninput({
19160 type: 'input',
19161 target: el,
19162 value: el.value
19163 });
19164 }
19165 }
19166 }
19167
19168 /**
19169 * Extract images from a HTML string
19170 */
19171 var extractImageFromHtml = function(html) {
19172 let img = [];
19173 // Create temp element
19174 var div = document.createElement('div');
19175 utils_filter(html, img);
19176 if (img.length) {
19177 for (var i = 0; i < img.length; i++) {
19178 obj.addImage(img[i]);
19179 }
19180 }
19181 }
19182
19183 /**
19184 * Insert node at caret
19185 */
19186 var insertNodeAtCaret = function(newNode) {
19187 var sel, range;
19188
19189 if (window.getSelection) {
19190 sel = window.getSelection();
19191 if (sel.rangeCount) {
19192 range = sel.getRangeAt(0);
19193 var selectedText = range.toString();
19194 range.deleteContents();
19195 range.insertNode(newNode);
19196 // move the cursor after element
19197 range.setStartAfter(newNode);
19198 range.setEndAfter(newNode);
19199 sel.removeAllRanges();
19200 sel.addRange(range);
19201 }
19202 }
19203 }
19204
19205 var updateTotalImages = function() {
19206 var o = null;
19207 if (o = snippet.children[0]) {
19208 // Make sure is a grid
19209 if (! o.classList.contains('jslider-grid')) {
19210 o.classList.add('jslider-grid');
19211 }
19212 // Quantify of images
19213 var number = o.children.length;
19214 // Set the configuration of the grid
19215 o.setAttribute('data-number', number > 4 ? 4 : number);
19216 // Total of images inside the grid
19217 if (number > 4) {
19218 o.setAttribute('data-total', number - 4);
19219 } else {
19220 o.removeAttribute('data-total');
19221 }
19222 }
19223 }
19224
19225 /**
19226 * Append image to the snippet
19227 */
19228 var appendImage = function(image) {
19229 if (! snippet.innerHTML) {
19230 obj.appendSnippet({});
19231 }
19232 snippet.children[0].appendChild(image);
19233 updateTotalImages();
19234 }
19235
19236 /**
19237 * Append snippet
19238 * @Param object data
19239 */
19240 obj.appendSnippet = function(data) {
19241 // Reset snippet
19242 snippet.innerHTML = '';
19243
19244 // Attributes
19245 var a = [ 'image', 'title', 'description', 'host', 'url' ];
19246
19247 for (var i = 0; i < a.length; i++) {
19248 var div = document.createElement('div');
19249 div.className = 'jsnippet-' + a[i];
19250 div.setAttribute('data-k', a[i]);
19251 snippet.appendChild(div);
19252 if (data[a[i]]) {
19253 if (a[i] == 'image') {
19254 if (! Array.isArray(data.image)) {
19255 data.image = [ data.image ];
19256 }
19257 for (var j = 0; j < data.image.length; j++) {
19258 var img = document.createElement('img');
19259 img.src = data.image[j];
19260 div.appendChild(img);
19261 }
19262 } else {
19263 div.innerHTML = data[a[i]];
19264 }
19265 }
19266 }
19267
19268 obj.editor.appendChild(document.createElement('br'));
19269 obj.editor.appendChild(snippet);
19270 }
19271
19272 /**
19273 * Set editor value
19274 */
19275 obj.setData = function(o) {
19276 if (typeof(o) == 'object') {
19277 obj.editor.innerHTML = o.content;
19278 } else {
19279 obj.editor.innerHTML = o;
19280 }
19281
19282 if (obj.options.focus) {
19283 Component.setCursor(obj.editor, true);
19284 }
19285
19286 // Reset files container
19287 files = [];
19288 }
19289
19290 obj.getFiles = function() {
19291 var f = obj.editor.querySelectorAll('.jfile');
19292 var d = [];
19293 for (var i = 0; i < f.length; i++) {
19294 if (files[f[i].src]) {
19295 d.push(files[f[i].src]);
19296 }
19297 }
19298 return d;
19299 }
19300
19301 obj.getText = function() {
19302 return obj.editor.innerText;
19303 }
19304
19305 /**
19306 * Get editor data
19307 */
19308 obj.getData = function(json) {
19309 if (! json) {
19310 var data = obj.editor.innerHTML;
19311 } else {
19312 var data = {
19313 content : '',
19314 }
19315
19316 // Get snippet
19317 if (snippet.innerHTML) {
19318 var index = 0;
19319 data.snippet = {};
19320 for (var i = 0; i < snippet.children.length; i++) {
19321 // Get key from element
19322 var key = snippet.children[i].getAttribute('data-k');
19323 if (key) {
19324 if (key == 'image') {
19325 if (! data.snippet.image) {
19326 data.snippet.image = [];
19327 }
19328 // Get all images
19329 for (var j = 0; j < snippet.children[i].children.length; j++) {
19330 data.snippet.image.push(snippet.children[i].children[j].getAttribute('src'))
19331 }
19332 } else {
19333 data.snippet[key] = snippet.children[i].innerHTML;
19334 }
19335 }
19336 }
19337 }
19338
19339 // Get files
19340 var f = Object.keys(files);
19341 if (f.length) {
19342 data.files = [];
19343 for (var i = 0; i < f.length; i++) {
19344 data.files.push(files[f[i]]);
19345 }
19346 }
19347
19348 // Get content
19349 var d = document.createElement('div');
19350 d.innerHTML = obj.editor.innerHTML;
19351 var s = d.querySelector('.jsnippet');
19352 if (s) {
19353 s.remove();
19354 }
19355
19356 var text = d.innerHTML;
19357 text = text.replace(/<br>/g, "\n");
19358 text = text.replace(/<\/div>/g, "<\/div>\n");
19359 text = text.replace(/<(?:.|\n)*?>/gm, "");
19360 data.content = text.trim();
19361
19362 // Process extensions
19363 processExtensions('getData', data);
19364 }
19365
19366 return data;
19367 }
19368
19369 // Reset
19370 obj.reset = function() {
19371 obj.editor.innerHTML = '';
19372 snippet.innerHTML = '';
19373 files = [];
19374 }
19375
19376 obj.addPdf = function(data) {
19377 if (data.result.substr(0,4) != 'data') {
19378 console.error('Invalid source');
19379 } else {
19380 var canvas = document.createElement('canvas');
19381 canvas.width = 60;
19382 canvas.height = 60;
19383
19384 var img = new Image();
19385 var ctx = canvas.getContext('2d');
19386 ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
19387
19388 canvas.toBlob(function(blob) {
19389 var newImage = document.createElement('img');
19390 newImage.src = window.URL.createObjectURL(blob);
19391 newImage.title = data.name;
19392 newImage.className = 'jfile pdf';
19393
19394 files[newImage.src] = {
19395 file: newImage.src,
19396 extension: 'pdf',
19397 content: data.result,
19398 }
19399
19400 //insertNodeAtCaret(newImage);
19401 document.execCommand('insertHtml', false, newImage.outerHTML);
19402 });
19403 }
19404 }
19405
19406 obj.addImage = function(src, asSnippet) {
19407 if (! obj.options.acceptImages) {
19408 return;
19409 }
19410
19411 if (! src) {
19412 src = '';
19413 }
19414
19415 if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) {
19416 console.error('remoteParser not defined in your initialization');
19417 } else {
19418 // This is to process cross domain images
19419 if (src.substr(0,4) == 'data') {
19420 var extension = src.split(';')
19421 extension = extension[0].split('/');
19422 extension = extension[1];
19423 } else {
19424 var extension = src.substr(src.lastIndexOf('.') + 1);
19425 // Work for cross browsers
19426 src = obj.options.remoteParser + src;
19427 }
19428
19429 var img = new Image();
19430
19431 img.onload = function onload() {
19432 var canvas = document.createElement('canvas');
19433 canvas.width = img.width;
19434 canvas.height = img.height;
19435
19436 var ctx = canvas.getContext('2d');
19437 ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
19438
19439 canvas.toBlob(function(blob) {
19440 var newImage = document.createElement('img');
19441 newImage.src = window.URL.createObjectURL(blob);
19442 newImage.classList.add('jfile');
19443 newImage.setAttribute('tabindex', '900');
19444 newImage.setAttribute('width', img.width);
19445 newImage.setAttribute('height', img.height);
19446 files[newImage.src] = {
19447 file: newImage.src,
19448 extension: extension,
19449 content: canvas.toDataURL(),
19450 }
19451
19452 if (obj.options.dropAsSnippet || asSnippet) {
19453 appendImage(newImage);
19454 // Just to understand the attachment is part of a snippet
19455 files[newImage.src].snippet = true;
19456 } else {
19457 //insertNodeAtCaret(newImage);
19458 document.execCommand('insertHtml', false, newImage.outerHTML);
19459 }
19460
19461 change();
19462 });
19463 };
19464
19465 img.src = src;
19466 }
19467 }
19468
19469 obj.addFile = function(files) {
19470 var reader = [];
19471
19472 for (var i = 0; i < files.length; i++) {
19473 if (files[i].size > obj.options.maxFileSize) {
19474 alert('The file is too big');
19475 } else {
19476 // Only PDF or Images
19477 var type = files[i].type.split('/');
19478
19479 if (type[0] == 'image') {
19480 type = 1;
19481 } else if (type[1] == 'pdf') {
19482 type = 2;
19483 } else {
19484 type = 0;
19485 }
19486
19487 if (type) {
19488 // Create file
19489 reader[i] = new FileReader();
19490 reader[i].index = i;
19491 reader[i].type = type;
19492 reader[i].name = files[i].name;
19493 reader[i].date = files[i].lastModified;
19494 reader[i].size = files[i].size;
19495 reader[i].addEventListener("load", function (data) {
19496 // Get result
19497 if (data.target.type == 2) {
19498 if (obj.options.acceptFiles == true) {
19499 obj.addPdf(data.target);
19500 }
19501 } else {
19502 obj.addImage(data.target.result);
19503 }
19504 }, false);
19505
19506 reader[i].readAsDataURL(files[i])
19507 } else {
19508 alert('The extension is not allowed');
19509 }
19510 }
19511 }
19512 }
19513
19514 // Destroy
19515 obj.destroy = function() {
19516 obj.editor.removeEventListener('mouseup', editorMouseUp);
19517 obj.editor.removeEventListener('mousedown', editorMouseDown);
19518 obj.editor.removeEventListener('mousemove', editorMouseMove);
19519 obj.editor.removeEventListener('keyup', editorKeyUp);
19520 obj.editor.removeEventListener('keydown', editorKeyDown);
19521 obj.editor.removeEventListener('dragstart', editorDragStart);
19522 obj.editor.removeEventListener('dragenter', editorDragEnter);
19523 obj.editor.removeEventListener('dragover', editorDragOver);
19524 obj.editor.removeEventListener('drop', editorDrop);
19525 obj.editor.removeEventListener('paste', editorPaste);
19526 obj.editor.removeEventListener('blur', editorBlur);
19527 obj.editor.removeEventListener('focus', editorFocus);
19528
19529 el.editor = null;
19530 el.classList.remove('jeditor-container');
19531
19532 toolbar.remove();
19533 snippet.remove();
19534 obj.editor.remove();
19535 }
19536
19537 obj.upload = function() {
19538 helpers.click(obj.file);
19539 }
19540
19541 var select = function(e) {
19542 var s = window.getSelection()
19543 var r = document.createRange();
19544 r.selectNode(e);
19545 s.addRange(r)
19546 }
19547
19548 var editorPaste = function(e) {
19549 if (obj.options.filterPaste == true) {
19550 if (e.clipboardData || e.originalEvent.clipboardData) {
19551 var html = (e.originalEvent || e).clipboardData.getData('text/html');
19552 var text = (e.originalEvent || e).clipboardData.getData('text/plain');
19553 var file = (e.originalEvent || e).clipboardData.files
19554 } else if (window.clipboardData) {
19555 var html = window.clipboardData.getData('Html');
19556 var text = window.clipboardData.getData('Text');
19557 var file = window.clipboardData.files
19558 }
19559
19560 if (file.length) {
19561 // Paste a image from the clipboard
19562 obj.addFile(file);
19563 } else {
19564 if (! html) {
19565 html = text.split('\r\n');
19566 if (! e.target.innerText) {
19567 html.map(function(v) {
19568 var d = document.createElement('div');
19569 d.innerText = v;
19570 obj.editor.appendChild(d);
19571 });
19572 } else {
19573 html = html.map(function(v) {
19574 return '<div>' + v + '</div>';
19575 });
19576 document.execCommand('insertText', false, html.join(''));
19577 }
19578 } else {
19579 let img = [];
19580 var d = utils_filter(html, img);
19581 if (img.length) {
19582 for (var i = 0; i < img.length; i++) {
19583 obj.addImage(img[i]);
19584 }
19585 }
19586 // Paste to the editor
19587 //insertNodeAtCaret(d);
19588 document.execCommand('insertHtml', false, d.innerHTML);
19589 }
19590 }
19591
19592 e.preventDefault();
19593 }
19594 }
19595
19596 var editorDragStart = function(e) {
19597 if (editorAction && editorAction.e) {
19598 e.preventDefault();
19599 }
19600 }
19601
19602 var editorDragEnter = function(e) {
19603 if (editorAction || obj.options.dropZone == false) {
19604 // Do nothing
19605 } else {
19606 el.classList.add('jeditor-dragging');
19607 e.preventDefault();
19608 }
19609 }
19610
19611 var editorDragOver = function(e) {
19612 if (editorAction || obj.options.dropZone == false) {
19613 // Do nothing
19614 } else {
19615 if (editorTimer) {
19616 clearTimeout(editorTimer);
19617 }
19618
19619 editorTimer = setTimeout(function() {
19620 el.classList.remove('jeditor-dragging');
19621 }, 100);
19622 e.preventDefault();
19623 }
19624 }
19625
19626 var editorDrop = function(e) {
19627 if (editorAction || obj.options.dropZone === false) {
19628 // Do nothing
19629 } else {
19630 // Position caret on the drop
19631 let range = null;
19632 if (document.caretRangeFromPoint) {
19633 range=document.caretRangeFromPoint(e.clientX, e.clientY);
19634 } else if (e.rangeParent) {
19635 range=document.createRange();
19636 range.setStart(e.rangeParent,e.rangeOffset);
19637 }
19638 let sel = window.getSelection();
19639 sel.removeAllRanges();
19640 sel.addRange(range);
19641 sel.anchorNode.parentNode.focus();
19642
19643 let html = (e.originalEvent || e).dataTransfer.getData('text/html');
19644 let text = (e.originalEvent || e).dataTransfer.getData('text/plain');
19645 let file = (e.originalEvent || e).dataTransfer.files;
19646
19647 if (file.length) {
19648 obj.addFile(file);
19649 } else if (text) {
19650 extractImageFromHtml(html);
19651 }
19652
19653 el.classList.remove('jeditor-dragging');
19654 e.preventDefault();
19655 }
19656 }
19657
19658 var editorBlur = function(e) {
19659 // Process extensions
19660 processExtensions('onevent', e);
19661 // Apply changes
19662 change(e);
19663 // Blur
19664 if (typeof(obj.options.onblur) == 'function') {
19665 obj.options.onblur(el, obj, e);
19666 }
19667 }
19668
19669 var editorFocus = function(e) {
19670 // Focus
19671 if (typeof(obj.options.onfocus) == 'function') {
19672 obj.options.onfocus(el, obj, e);
19673 }
19674 }
19675
19676 var editorKeyUp = function(e) {
19677 if (! obj.editor.innerHTML) {
19678 obj.editor.innerHTML = '<div><br></div>';
19679 }
19680 if (typeof(obj.options.onkeyup) == 'function') {
19681 obj.options.onkeyup(el, obj, e);
19682 }
19683 }
19684
19685 var editorKeyDown = function(e) {
19686 // Process extensions
19687 processExtensions('onevent', e);
19688
19689 if (e.key == 'Delete') {
19690 if (e.target.tagName == 'IMG') {
19691 var parent = e.target.parentNode;
19692 select(e.target);
19693 if (parent.classList.contains('jsnippet-image')) {
19694 updateTotalImages();
19695 }
19696 }
19697 }
19698
19699 if (typeof(obj.options.onkeydown) == 'function') {
19700 obj.options.onkeydown(el, obj, e);
19701 }
19702 }
19703
19704 var editorMouseUp = function(e) {
19705 if (editorAction && editorAction.e) {
19706 editorAction.e.classList.remove('resizing');
19707
19708 if (editorAction.e.changed == true) {
19709 var image = editorAction.e.cloneNode()
19710 image.width = parseInt(editorAction.e.style.width) || editorAction.e.getAttribute('width');
19711 image.height = parseInt(editorAction.e.style.height) || editorAction.e.getAttribute('height');
19712 editorAction.e.style.width = '';
19713 editorAction.e.style.height = '';
19714 select(editorAction.e);
19715 document.execCommand('insertHtml', false, image.outerHTML);
19716 }
19717 }
19718
19719 editorAction = false;
19720 }
19721
19722 var editorMouseDown = function(e) {
19723 var close = function(snippet) {
19724 var rect = snippet.getBoundingClientRect();
19725 if (rect.width - (e.clientX - rect.left) < 40 && e.clientY - rect.top < 40) {
19726 snippet.innerHTML = '';
19727 snippet.remove();
19728 }
19729 }
19730
19731 if (e.target.tagName == 'IMG') {
19732 if (e.target.style.cursor) {
19733 var rect = e.target.getBoundingClientRect();
19734 editorAction = {
19735 e: e.target,
19736 x: e.clientX,
19737 y: e.clientY,
19738 w: rect.width,
19739 h: rect.height,
19740 d: e.target.style.cursor,
19741 }
19742
19743 if (! e.target.getAttribute('width')) {
19744 e.target.setAttribute('width', rect.width)
19745 }
19746
19747 if (! e.target.getAttribute('height')) {
19748 e.target.setAttribute('height', rect.height)
19749 }
19750
19751 var s = window.getSelection();
19752 if (s.rangeCount) {
19753 for (var i = 0; i < s.rangeCount; i++) {
19754 s.removeRange(s.getRangeAt(i));
19755 }
19756 }
19757
19758 e.target.classList.add('resizing');
19759 } else {
19760 editorAction = true;
19761 }
19762 } else {
19763 if (e.target.classList.contains('jsnippet')) {
19764 close(e.target);
19765 } else if (e.target.parentNode.classList.contains('jsnippet')) {
19766 close(e.target.parentNode);
19767 }
19768
19769 editorAction = true;
19770 }
19771 }
19772
19773 var editorMouseMove = function(e) {
19774 if (e.target.tagName == 'IMG' && ! e.target.parentNode.classList.contains('jsnippet-image') && obj.options.allowImageResize == true) {
19775 if (e.target.getAttribute('tabindex')) {
19776 var rect = e.target.getBoundingClientRect();
19777 if (e.clientY - rect.top < 5) {
19778 if (rect.width - (e.clientX - rect.left) < 5) {
19779 e.target.style.cursor = 'ne-resize';
19780 } else if (e.clientX - rect.left < 5) {
19781 e.target.style.cursor = 'nw-resize';
19782 } else {
19783 e.target.style.cursor = 'n-resize';
19784 }
19785 } else if (rect.height - (e.clientY - rect.top) < 5) {
19786 if (rect.width - (e.clientX - rect.left) < 5) {
19787 e.target.style.cursor = 'se-resize';
19788 } else if (e.clientX - rect.left < 5) {
19789 e.target.style.cursor = 'sw-resize';
19790 } else {
19791 e.target.style.cursor = 's-resize';
19792 }
19793 } else if (rect.width - (e.clientX - rect.left) < 5) {
19794 e.target.style.cursor = 'e-resize';
19795 } else if (e.clientX - rect.left < 5) {
19796 e.target.style.cursor = 'w-resize';
19797 } else {
19798 e.target.style.cursor = '';
19799 }
19800 }
19801 }
19802
19803 // Move
19804 if (e.which == 1 && editorAction && editorAction.d) {
19805 if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') {
19806 editorAction.e.style.width = (editorAction.w + (e.clientX - editorAction.x));
19807
19808 if (e.shiftKey) {
19809 var newHeight = (e.clientX - editorAction.x) * (editorAction.h / editorAction.w);
19810 editorAction.e.style.height = editorAction.h + newHeight;
19811 } else {
19812 var newHeight = null;
19813 }
19814 }
19815
19816 if (! newHeight) {
19817 if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') {
19818 if (! e.shiftKey) {
19819 editorAction.e.style.height = editorAction.h + (e.clientY - editorAction.y);
19820 }
19821 }
19822 }
19823
19824 editorAction.e.changed = true;
19825 }
19826 }
19827
19828 var processExtensions = function(method, data) {
19829 if (obj.options.extensions) {
19830 var ext = Object.keys(obj.options.extensions);
19831 if (ext.length) {
19832 for (var i = 0; i < ext.length; i++)
19833 if (obj.options.extensions[ext[i]] && typeof(obj.options.extensions[ext[i]][method]) == 'function') {
19834 obj.options.extensions[ext[i]][method].call(obj, data);
19835 }
19836 }
19837 }
19838 }
19839
19840 var loadExtensions = function() {
19841 if (obj.options.extensions) {
19842 var ext = Object.keys(obj.options.extensions);
19843 if (ext.length) {
19844 for (var i = 0; i < ext.length; i++) {
19845 if (obj.options.extensions[ext[i]] && typeof (obj.options.extensions[ext[i]]) == 'function') {
19846 obj.options.extensions[ext[i]] = obj.options.extensions[ext[i]](el, obj);
19847 }
19848 }
19849 }
19850 }
19851 }
19852
19853 document.addEventListener('mouseup', editorMouseUp);
19854 document.addEventListener('mousemove', editorMouseMove);
19855 obj.editor.addEventListener('mousedown', editorMouseDown);
19856 obj.editor.addEventListener('keyup', editorKeyUp);
19857 obj.editor.addEventListener('keydown', editorKeyDown);
19858 obj.editor.addEventListener('dragstart', editorDragStart);
19859 obj.editor.addEventListener('dragenter', editorDragEnter);
19860 obj.editor.addEventListener('dragover', editorDragOver);
19861 obj.editor.addEventListener('drop', editorDrop);
19862 obj.editor.addEventListener('paste', editorPaste);
19863 obj.editor.addEventListener('focus', editorFocus);
19864 obj.editor.addEventListener('blur', editorBlur);
19865
19866 // Append editor to the container
19867 el.appendChild(obj.editor);
19868 // Snippet
19869 if (obj.options.snippet) {
19870 obj.appendSnippet(obj.options.snippet);
19871 }
19872
19873 // Add toolbar
19874 if (obj.options.toolbar) {
19875 // Default toolbar configuration
19876 if (Array.isArray(obj.options.toolbar)) {
19877 var toolbarOptions = {
19878 container: true,
19879 responsive: true,
19880 items: obj.options.toolbar
19881 }
19882 } else if (obj.options.toolbar === true) {
19883 var toolbarOptions = {
19884 container: true,
19885 responsive: true,
19886 items: [],
19887 }
19888 } else {
19889 var toolbarOptions = obj.options.toolbar;
19890 }
19891
19892 // Default items
19893 if (! (toolbarOptions.items && toolbarOptions.items.length)) {
19894 toolbarOptions.items = Component.getDefaultToolbar(obj);
19895 }
19896
19897 if (obj.options.toolbarOnTop) {
19898 // Add class
19899 el.classList.add('toolbar-on-top');
19900 // Append to the DOM
19901 el.insertBefore(toolbar, el.firstChild);
19902 } else {
19903 // Add padding to the editor
19904 obj.editor.style.padding = '15px';
19905 // Append to the DOM
19906 el.appendChild(toolbar);
19907 }
19908
19909 // Create toolbar
19910 Toolbar(toolbar, toolbarOptions);
19911
19912 toolbar.addEventListener('click', function() {
19913 obj.editor.focus();
19914 })
19915 }
19916
19917 // Upload file
19918 obj.file = document.createElement('input');
19919 obj.file.style.display = 'none';
19920 obj.file.type = 'file';
19921 obj.file.setAttribute('accept', 'image/*');
19922 obj.file.onchange = function() {
19923 obj.addFile(this.files);
19924 }
19925 el.appendChild(obj.file);
19926
19927 // Focus to the editor
19928 if (obj.options.focus) {
19929 Component.setCursor(obj.editor, obj.options.focus == 'initial' ? true : false);
19930 }
19931
19932 // Change method
19933 el.change = obj.setData;
19934
19935 // Global generic value handler
19936 el.val = function(val) {
19937 if (val === undefined) {
19938 // Data type
19939 var o = el.getAttribute('data-html') === 'true' ? false : true;
19940 return obj.getData(o);
19941 } else {
19942 obj.setData(val);
19943 }
19944 }
19945
19946 loadExtensions();
19947
19948 el.editor = obj;
19949
19950 // Onload
19951 if (typeof(obj.options.onload) == 'function') {
19952 obj.options.onload(el, obj, obj.editor);
19953 }
19954
19955 return obj;
19956 });
19957
19958 Component.setCursor = function(element, first) {
19959 element.focus();
19960 document.execCommand('selectAll');
19961 var sel = window.getSelection();
19962 var range = sel.getRangeAt(0);
19963 if (first == true) {
19964 var node = range.startContainer;
19965 var size = 0;
19966 } else {
19967 var node = range.endContainer;
19968 var size = node.length;
19969 }
19970 range.setStart(node, size);
19971 range.setEnd(node, size);
19972 sel.removeAllRanges();
19973 sel.addRange(range);
19974 }
19975
19976 Component.getDefaultToolbar = function(obj) {
19977
19978 var color = function(a,b,c) {
19979 if (! c.color) {
19980 var t = null;
19981 var colorPicker = Color(c, {
19982 onchange: function(o, v) {
19983 if (c.k === 'color') {
19984 document.execCommand('foreColor', false, v);
19985 } else {
19986 document.execCommand('backColor', false, v);
19987 }
19988 }
19989 });
19990 c.color.open();
19991 }
19992 }
19993
19994 var items = [];
19995
19996 items.push({
19997 content: 'undo',
19998 onclick: function() {
19999 document.execCommand('undo');
20000 }
20001 });
20002
20003 items.push({
20004 content: 'redo',
20005 onclick: function() {
20006 document.execCommand('redo');
20007 }
20008 });
20009
20010 items.push({
20011 type: 'divisor'
20012 });
20013
20014 if (obj.options.toolbarOnTop) {
20015 items.push({
20016 type: 'select',
20017 width: '140px',
20018 options: ['Default', 'Verdana', 'Arial', 'Courier New'],
20019 render: function (e) {
20020 return '<span style="font-family:' + e + '">' + e + '</span>';
20021 },
20022 onchange: function (a,b,c,d,e) {
20023 document.execCommand("fontName", false, d);
20024 }
20025 });
20026
20027 items.push({
20028 type: 'select',
20029 content: 'format_size',
20030 options: ['x-small', 'small', 'medium', 'large', 'x-large'],
20031 render: function (e) {
20032 return '<span style="font-size:' + e + '">' + e + '</span>';
20033 },
20034 onchange: function (a,b,c,d,e) {
20035 //var html = `<span style="font-size: ${c}">${text}</span>`;
20036 //document.execCommand('insertHtml', false, html);
20037 document.execCommand("fontSize", false, parseInt(e)+1);
20038 //var f = window.getSelection().anchorNode.parentNode
20039 //f.removeAttribute("size");
20040 //f.style.fontSize = d;
20041 }
20042 });
20043
20044 items.push({
20045 type: 'select',
20046 options: ['format_align_left', 'format_align_center', 'format_align_right', 'format_align_justify'],
20047 render: function (e) {
20048 return '<i class="material-icons">' + e + '</i>';
20049 },
20050 onchange: function (a,b,c,d,e) {
20051 var options = ['JustifyLeft','justifyCenter','justifyRight','justifyFull'];
20052 document.execCommand(options[e]);
20053 }
20054 });
20055
20056 items.push({
20057 type: 'divisor'
20058 });
20059
20060 items.push({
20061 content: 'format_color_text',
20062 k: 'color',
20063 onclick: color,
20064 });
20065
20066 items.push({
20067 content: 'format_color_fill',
20068 k: 'background-color',
20069 onclick: color,
20070 });
20071 }
20072
20073 items.push({
20074 content: 'format_bold',
20075 onclick: function(a,b,c) {
20076 document.execCommand('bold');
20077
20078 if (document.queryCommandState("bold")) {
20079 c.classList.add('selected');
20080 } else {
20081 c.classList.remove('selected');
20082 }
20083 }
20084 });
20085
20086 items.push({
20087 content: 'format_italic',
20088 onclick: function(a,b,c) {
20089 document.execCommand('italic');
20090
20091 if (document.queryCommandState("italic")) {
20092 c.classList.add('selected');
20093 } else {
20094 c.classList.remove('selected');
20095 }
20096 }
20097 });
20098
20099 items.push({
20100 content: 'format_underline',
20101 onclick: function(a,b,c) {
20102 document.execCommand('underline');
20103
20104 if (document.queryCommandState("underline")) {
20105 c.classList.add('selected');
20106 } else {
20107 c.classList.remove('selected');
20108 }
20109 }
20110 });
20111
20112 items.push({
20113 type:'divisor'
20114 });
20115
20116 items.push({
20117 content: 'format_list_bulleted',
20118 onclick: function(a,b,c) {
20119 document.execCommand('insertUnorderedList');
20120
20121 if (document.queryCommandState("insertUnorderedList")) {
20122 c.classList.add('selected');
20123 } else {
20124 c.classList.remove('selected');
20125 }
20126 }
20127 });
20128
20129 items.push({
20130 content: 'format_list_numbered',
20131 onclick: function(a,b,c) {
20132 document.execCommand('insertOrderedList');
20133
20134 if (document.queryCommandState("insertOrderedList")) {
20135 c.classList.add('selected');
20136 } else {
20137 c.classList.remove('selected');
20138 }
20139 }
20140 });
20141
20142 items.push({
20143 content: 'format_indent_increase',
20144 onclick: function(a,b,c) {
20145 document.execCommand('indent', true, null);
20146
20147 if (document.queryCommandState("indent")) {
20148 c.classList.add('selected');
20149 } else {
20150 c.classList.remove('selected');
20151 }
20152 }
20153 });
20154
20155 items.push({
20156 content: 'format_indent_decrease',
20157 onclick: function(a,b,c) {
20158 document.execCommand('outdent');
20159
20160 if (document.queryCommandState("outdent")) {
20161 c.classList.add('selected');
20162 } else {
20163 c.classList.remove('selected');
20164 }
20165 }
20166 });
20167
20168 if (obj.options.toolbarOnTop) {
20169 items.push({
20170 type: 'divisor'
20171 });
20172
20173 items.push({
20174 content: 'photo',
20175 onclick: function () {
20176 obj.upload();
20177 }
20178 });
20179
20180 items.push({
20181 type: 'select',
20182 content: 'table_view',
20183 columns: 8,
20184 grid: 8,
20185 right: true,
20186 options: [
20187 '0x0', '1x0', '2x0', '3x0', '4x0', '5x0', '6x0', '7x0',
20188 '0x1', '1x1', '2x1', '3x1', '4x1', '5x1', '6x1', '7x1',
20189 '0x2', '1x2', '2x2', '3x2', '4x2', '5x2', '6x2', '7x2',
20190 '0x3', '1x3', '2x3', '3x3', '4x3', '5x3', '6x3', '7x3',
20191 '0x4', '1x4', '2x4', '3x4', '4x4', '5x4', '6x4', '7x4',
20192 '0x5', '1x5', '2x5', '3x5', '4x5', '5x5', '6x5', '7x5',
20193 '0x6', '1x6', '2x6', '3x6', '4x6', '5x6', '6x6', '7x6',
20194 '0x7', '1x7', '2x7', '3x7', '4x7', '5x7', '6x7', '7x7',
20195 ],
20196 render: function (e, item) {
20197 if (item) {
20198 item.onmouseover = this.onmouseover;
20199 e = e.split('x');
20200 item.setAttribute('data-x', e[0]);
20201 item.setAttribute('data-y', e[1]);
20202 }
20203 var element = document.createElement('div');
20204 item.style.margin = '1px';
20205 item.style.border = '1px solid #ddd';
20206 return element;
20207 },
20208 onmouseover: function (e) {
20209 var x = parseInt(e.target.getAttribute('data-x'));
20210 var y = parseInt(e.target.getAttribute('data-y'));
20211 for (var i = 0; i < e.target.parentNode.children.length; i++) {
20212 var element = e.target.parentNode.children[i];
20213 var ex = parseInt(element.getAttribute('data-x'));
20214 var ey = parseInt(element.getAttribute('data-y'));
20215 if (ex <= x && ey <= y) {
20216 element.style.backgroundColor = '#cae1fc';
20217 element.style.borderColor = '#2977ff';
20218 } else {
20219 element.style.backgroundColor = '';
20220 element.style.borderColor = '#ddd';
20221 }
20222 }
20223 },
20224 onchange: function (a, b, c) {
20225 c = c.split('x');
20226 var table = document.createElement('table');
20227 var tbody = document.createElement('tbody');
20228 for (var y = 0; y <= c[1]; y++) {
20229 var tr = document.createElement('tr');
20230 for (var x = 0; x <= c[0]; x++) {
20231 var td = document.createElement('td');
20232 td.innerHTML = '';
20233 tr.appendChild(td);
20234 }
20235 tbody.appendChild(tr);
20236 }
20237 table.appendChild(tbody);
20238 table.setAttribute('width', '100%');
20239 table.setAttribute('cellpadding', '6');
20240 table.setAttribute('cellspacing', '0');
20241 document.execCommand('insertHTML', false, table.outerHTML);
20242 }
20243 });
20244 }
20245
20246 return items;
20247 }
20248
20249 return Component;
20250}
20251
20252/* harmony default export */ var editor = (Editor());
20253
20254;// CONCATENATED MODULE: ./src/plugins/floating.js
20255function Floating() {
20256 var Component = (function (el, options) {
20257 var obj = {};
20258 obj.options = {};
20259
20260 // Default configuration
20261 var defaults = {
20262 type: 'big',
20263 title: 'Untitled',
20264 width: 510,
20265 height: 472,
20266 }
20267
20268 // Loop through our object
20269 for (var property in defaults) {
20270 if (options && options.hasOwnProperty(property)) {
20271 obj.options[property] = options[property];
20272 } else {
20273 obj.options[property] = defaults[property];
20274 }
20275 }
20276
20277 // Private methods
20278
20279 var setContent = function () {
20280 var temp = document.createElement('div');
20281 while (el.children[0]) {
20282 temp.appendChild(el.children[0]);
20283 }
20284
20285 obj.content = document.createElement('div');
20286 obj.content.className = 'jfloating_content';
20287 obj.content.innerHTML = el.innerHTML;
20288
20289 while (temp.children[0]) {
20290 obj.content.appendChild(temp.children[0]);
20291 }
20292
20293 obj.container = document.createElement('div');
20294 obj.container.className = 'jfloating';
20295 obj.container.appendChild(obj.content);
20296
20297 if (obj.options.title) {
20298 obj.container.setAttribute('title', obj.options.title);
20299 } else {
20300 obj.container.classList.add('no-title');
20301 }
20302
20303 // validate element dimensions
20304 if (obj.options.width) {
20305 obj.container.style.width = parseInt(obj.options.width) + 'px';
20306 }
20307
20308 if (obj.options.height) {
20309 obj.container.style.height = parseInt(obj.options.height) + 'px';
20310 }
20311
20312 el.innerHTML = '';
20313 el.appendChild(obj.container);
20314 }
20315
20316 var setEvents = function () {
20317 if (obj.container) {
20318 obj.container.addEventListener('click', function (e) {
20319 var rect = e.target.getBoundingClientRect();
20320
20321 if (e.target.classList.contains('jfloating')) {
20322 if (e.changedTouches && e.changedTouches[0]) {
20323 var x = e.changedTouches[0].clientX;
20324 var y = e.changedTouches[0].clientY;
20325 } else {
20326 var x = e.clientX;
20327 var y = e.clientY;
20328 }
20329
20330 if (rect.width - (x - rect.left) < 50 && (y - rect.top) < 50) {
20331 setTimeout(function () {
20332 obj.close();
20333 }, 100);
20334 } else {
20335 obj.setState();
20336 }
20337 }
20338 });
20339 }
20340 }
20341
20342 var setType = function () {
20343 obj.container.classList.add('jfloating-' + obj.options.type);
20344 }
20345
20346 obj.state = {
20347 isMinized: false,
20348 }
20349
20350 obj.setState = function () {
20351 if (obj.state.isMinized) {
20352 obj.container.classList.remove('jfloating-minimized');
20353 } else {
20354 obj.container.classList.add('jfloating-minimized');
20355 }
20356 obj.state.isMinized = !obj.state.isMinized;
20357 }
20358
20359 obj.close = function () {
20360 Components.elements.splice(Component.elements.indexOf(obj.container), 1);
20361 obj.updatePosition();
20362 el.remove();
20363 }
20364
20365 obj.updatePosition = function () {
20366 for (var i = 0; i < Component.elements.length; i++) {
20367 var floating = Component.elements[i];
20368 var prevFloating = Component.elements[i - 1];
20369 floating.style.right = i * (prevFloating ? prevFloating.offsetWidth : floating.offsetWidth) * 1.01 + 'px';
20370 }
20371 }
20372
20373 obj.init = function () {
20374 // Set content into root
20375 setContent();
20376
20377 // Set dialog events
20378 setEvents();
20379
20380 // Set dialog type
20381 setType();
20382
20383 // Update floating position
20384 Component.elements.push(obj.container);
20385 obj.updatePosition();
20386
20387 el.floating = obj;
20388 }
20389
20390 obj.init();
20391
20392 return obj;
20393 });
20394
20395 Component.elements = [];
20396
20397 return Component;
20398}
20399
20400/* harmony default export */ var floating = (Floating());
20401;// CONCATENATED MODULE: ./src/plugins/validations.js
20402
20403
20404const validations_HelpersDate = (dist_default()).Helpers;
20405function Validations() {
20406 /**
20407 * Options: Object,
20408 * Properties:
20409 * Constraint,
20410 * Reference,
20411 * Value
20412 */
20413
20414 const isNumeric = function(num) {
20415 return !isNaN(num) && num !== null && (typeof num !== 'string' || num.trim() !== '');
20416 }
20417
20418 const numberCriterias = {
20419 'between': function(value, range) {
20420 return value >= range[0] && value <= range[1];
20421 },
20422 'not between': function(value, range) {
20423 return value < range[0] || value > range[1];
20424 },
20425 '<': function(value, range) {
20426 return value < range[0];
20427 },
20428 '<=': function(value, range) {
20429 return value <= range[0];
20430 },
20431 '>': function(value, range) {
20432 return value > range[0];
20433 },
20434 '>=': function(value, range) {
20435 return value >= range[0];
20436 },
20437 '=': function(value, range) {
20438 return value == range[0];
20439 },
20440 '!=': function(value, range) {
20441 return value != range[0];
20442 },
20443 }
20444
20445 const dateCriterias = {
20446 'valid date': function() {
20447 return true;
20448 },
20449 '=': function(value, range) {
20450 return value === range[0];
20451 },
20452 '!=': function(value, range) {
20453 return value !== range[0];
20454 },
20455 '<': function(value, range) {
20456 return value < range[0];
20457 },
20458 '<=': function(value, range) {
20459 return value <= range[0];
20460 },
20461 '>': function(value, range) {
20462 return value > range[0];
20463 },
20464 '>=': function(value, range) {
20465 return value >= range[0];
20466 },
20467 'between': function(value, range) {
20468 return value >= range[0] && value <= range[1];
20469 },
20470 'not between': function(value, range) {
20471 return value < range[0] || value > range[1];
20472 },
20473 }
20474
20475 const textCriterias = {
20476 'contains': function(value, range) {
20477 return value.includes(range[0]);
20478 },
20479 'not contains': function(value, range) {
20480 return !value.includes(range[0]);
20481 },
20482 'begins with': function(value, range) {
20483 return value.startsWith(range[0]);
20484 },
20485 'ends with': function(value, range) {
20486 return value.endsWith(range[0]);
20487 },
20488 '=': function(value, range) {
20489 return value === range[0];
20490 },
20491 '!=': function(value, range) {
20492 return value !== range[0];
20493 },
20494 'valid email': function(value) {
20495 var pattern = new RegExp(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
20496
20497 return pattern.test(value);
20498 },
20499 'valid url': function(value) {
20500 var pattern = new RegExp(/(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig);
20501
20502 return pattern.test(value);
20503 },
20504 }
20505
20506 // Component router
20507 const component = function(value, options) {
20508 if (typeof(component[options.type]) === 'function') {
20509 if (options.allowBlank && (typeof value === 'undefined' || value === '' || value === null)) {
20510 return true;
20511 }
20512 return component[options.type].call(this, value, options);
20513 }
20514 return null;
20515 }
20516
20517 component.url = function(data) {
20518 var pattern = new RegExp(/(((https?:\/\/)|(www\.))[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]+)/ig);
20519 return pattern.test(data) ? true : false;
20520 }
20521
20522 component.email = function(data) {
20523 var pattern = new RegExp(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
20524 return data && pattern.test(data) ? true : false;
20525 }
20526
20527 component.required = function(data) {
20528 return data && data.trim() ? true : false;
20529 }
20530
20531 component.empty = function(data) {
20532 return typeof data === 'undefined' || data === null || (typeof data === 'string' && !data.toString().trim());
20533 }
20534
20535 component['not exist'] = component.empty;
20536
20537 component.notEmpty = function(data) {
20538 return !component.empty(data);
20539 }
20540
20541 component.exist = component.notEmpty;
20542
20543 component.number = function(data, options) {
20544 if (! isNumeric(data)) {
20545 return false;
20546 }
20547
20548 if (!options || !options.criteria) {
20549 return true;
20550 }
20551
20552 if (!numberCriterias[options.criteria]) {
20553 return false;
20554 }
20555
20556 let values = options.value.map(function(num) {
20557 return parseFloat(num);
20558 })
20559
20560 return numberCriterias[options.criteria](data, values);
20561 };
20562
20563 component.login = function(data) {
20564 let pattern = new RegExp(/^[a-zA-Z0-9._-]+$/);
20565 return data && pattern.test(data) ? true : false;
20566 }
20567
20568 component.list = function(data, options) {
20569 let dataType = typeof data;
20570 if (dataType !== 'string' && dataType !== 'number') {
20571 return false;
20572 }
20573 let list;
20574 if (typeof(options.value[0]) === 'string') {
20575 if (options.source) {
20576 list = options.source;
20577 } else {
20578 list = options.value[0].split(',');
20579 }
20580 } else {
20581 list = options.value[0];
20582 }
20583
20584 if (! Array.isArray(list)) {
20585 return false;
20586 } else {
20587 let validOption = list.findIndex(function (item) {
20588 return item == data;
20589 });
20590
20591 return validOption > -1;
20592 }
20593 }
20594
20595 const getCurrentDateWithoutTime = function() {
20596 let date = new Date();
20597 date.setHours(0, 0, 0, 0);
20598 return date;
20599 }
20600
20601 const relativeDates = {
20602 'one year ago': function() {
20603 let date = getCurrentDateWithoutTime();
20604
20605 date.setFullYear(date.getFullYear() - 1);
20606
20607 return date;
20608 },
20609 'one month ago': function() {
20610 let date = getCurrentDateWithoutTime();
20611
20612 date.setMonth(date.getMonth() - 1);
20613
20614 return date;
20615 },
20616 'one week ago': function() {
20617 let date = getCurrentDateWithoutTime();
20618
20619 date.setDate(date.getDate() - 7);
20620
20621 return date;
20622 },
20623 yesterday: function() {
20624 let date = getCurrentDateWithoutTime();
20625
20626 date.setDate(date.getDate() - 1);
20627
20628 return date;
20629 },
20630 today: getCurrentDateWithoutTime,
20631 tomorrow: function() {
20632 let date = getCurrentDateWithoutTime();
20633
20634 date.setDate(date.getDate() + 1);
20635
20636 return date;
20637 },
20638 };
20639
20640 component.date = function(data, options) {
20641 if (isNumeric(data) && data > 0 && data < 1000000) {
20642 data = validations_HelpersDate.numToDate(data);
20643 }
20644
20645 if (new Date(data) == 'Invalid Date') {
20646 return false;
20647 }
20648
20649 if (!options || !options.criteria) {
20650 return true;
20651 }
20652
20653 if (!dateCriterias[options.criteria]) {
20654 return false;
20655 }
20656
20657 let values = options.value.map(function(date) {
20658 if (typeof date === 'string' && relativeDates[date]) {
20659 return relativeDates[date]().getTime();
20660 }
20661
20662 return new Date(date).getTime();
20663 });
20664
20665 return dateCriterias[options.criteria](new Date(data).getTime(), values);
20666 }
20667
20668 component.text = function(data, options) {
20669 if (typeof data === 'undefined' || data === null) {
20670 data = '';
20671 } else if (typeof data !== 'string') {
20672 return false;
20673 }
20674
20675 if (!options || !options.criteria) {
20676 return true;
20677 }
20678
20679 if (!textCriterias[options.criteria]) {
20680 return false;
20681 }
20682
20683 return textCriterias[options.criteria](data, options.value);
20684 }
20685
20686 component.textLength = function(data, options) {
20687 let textLength;
20688 if (typeof data === 'string') {
20689 textLength = data.length;
20690 } else if (typeof data !== 'undefined' && data !== null && typeof data.toString === 'function') {
20691 textLength = data.toString().length;
20692 } else {
20693 textLength = 0;
20694 }
20695
20696 return component.number(textLength, options);
20697 }
20698
20699 component.time = function(data, options) {
20700 if (! isNumeric(data)) {
20701 return false;
20702 }
20703
20704 if (!options || !options.criteria) {
20705 return true;
20706 }
20707
20708 if (!numberCriterias[options.criteria]) {
20709 return false;
20710 }
20711
20712 let values = options.value.map(function(num) {
20713 return parseInt(parseFloat(num) * 10**17) / 10**17;
20714 })
20715
20716 return numberCriterias[options.criteria](parseInt(parseFloat(data) * 10**17) / 10**17, values);
20717 };
20718
20719 return component;
20720}
20721
20722/* harmony default export */ var validations = (Validations());
20723;// CONCATENATED MODULE: ./src/plugins/form.js
20724
20725
20726
20727
20728function Form() {
20729 var Component = (function(el, options) {
20730 var obj = {};
20731 obj.options = {};
20732
20733 // Default configuration
20734 var defaults = {
20735 url: null,
20736 message: 'Are you sure? There are unsaved information in your form',
20737 ignore: false,
20738 currentHash: null,
20739 submitButton:null,
20740 validations: null,
20741 onbeforeload: null,
20742 onload: null,
20743 onbeforesave: null,
20744 onsave: null,
20745 onbeforeremove: null,
20746 onremove: null,
20747 onerror: function(el, message) {
20748 alert(message);
20749 }
20750 };
20751
20752 // Loop through our object
20753 for (var property in defaults) {
20754 if (options && options.hasOwnProperty(property)) {
20755 obj.options[property] = options[property];
20756 } else {
20757 obj.options[property] = defaults[property];
20758 }
20759 }
20760
20761 // Validations
20762 if (! obj.options.validations) {
20763 obj.options.validations = {};
20764 }
20765
20766 // Submit Button
20767 if (! obj.options.submitButton) {
20768 obj.options.submitButton = el.querySelector('input[type=submit]');
20769 }
20770
20771 if (obj.options.submitButton && obj.options.url) {
20772 obj.options.submitButton.onclick = function() {
20773 obj.save();
20774 }
20775 }
20776
20777 if (! obj.options.validations.email) {
20778 obj.options.validations.email = validations.email;
20779 }
20780
20781 if (! obj.options.validations.length) {
20782 obj.options.validations.length = validations.length;
20783 }
20784
20785 if (! obj.options.validations.required) {
20786 obj.options.validations.required = validations.required;
20787 }
20788
20789 obj.setUrl = function(url) {
20790 obj.options.url = url;
20791 }
20792
20793 obj.load = function() {
20794 ajax({
20795 url: obj.options.url,
20796 method: 'GET',
20797 dataType: 'json',
20798 queue: true,
20799 success: function(data) {
20800 // Overwrite values from the backend
20801 if (typeof(obj.options.onbeforeload) == 'function') {
20802 var ret = obj.options.onbeforeload(el, data);
20803 if (ret) {
20804 data = ret;
20805 }
20806 }
20807 // Apply values to the form
20808 Component.setElements(el, data);
20809 // Onload methods
20810 if (typeof(obj.options.onload) == 'function') {
20811 obj.options.onload(el, data);
20812 }
20813 }
20814 });
20815 }
20816
20817 obj.save = function() {
20818 var test = obj.validate();
20819
20820 if (test) {
20821 obj.options.onerror(el, test);
20822 } else {
20823 var data = Component.getElements(el, true);
20824
20825 if (typeof(obj.options.onbeforesave) == 'function') {
20826 var data = obj.options.onbeforesave(el, data);
20827
20828 if (data === false) {
20829 return;
20830 }
20831 }
20832
20833 ajax({
20834 url: obj.options.url,
20835 method: 'POST',
20836 dataType: 'json',
20837 data: data,
20838 success: function(result) {
20839 if (typeof(obj.options.onsave) == 'function') {
20840 obj.options.onsave(el, data, result);
20841 }
20842 }
20843 });
20844 }
20845 }
20846
20847 obj.remove = function() {
20848 if (typeof(obj.options.onbeforeremove) == 'function') {
20849 var ret = obj.options.onbeforeremove(el, obj);
20850 if (ret === false) {
20851 return false;
20852 }
20853 }
20854
20855 ajax({
20856 url: obj.options.url,
20857 method: 'DELETE',
20858 dataType: 'json',
20859 success: function(result) {
20860 if (typeof(obj.options.onremove) == 'function') {
20861 obj.options.onremove(el, obj, result);
20862 }
20863
20864 obj.reset();
20865 }
20866 });
20867 }
20868
20869 var addError = function(element) {
20870 // Add error in the element
20871 element.classList.add('error');
20872 // Submit button
20873 if (obj.options.submitButton) {
20874 obj.options.submitButton.setAttribute('disabled', true);
20875 }
20876 // Return error message
20877 var error = element.getAttribute('data-error') || 'There is an error in the form';
20878 element.setAttribute('title', error);
20879 return error;
20880 }
20881
20882 var delError = function(element) {
20883 var error = false;
20884 // Remove class from this element
20885 element.classList.remove('error');
20886 element.removeAttribute('title');
20887 // Get elements in the form
20888 var elements = el.querySelectorAll("input, select, textarea, div[name]");
20889 // Run all elements
20890 for (var i = 0; i < elements.length; i++) {
20891 if (elements[i].getAttribute('data-validation')) {
20892 if (elements[i].classList.contains('error')) {
20893 error = true;
20894 }
20895 }
20896 }
20897
20898 if (obj.options.submitButton) {
20899 if (error) {
20900 obj.options.submitButton.setAttribute('disabled', true);
20901 } else {
20902 obj.options.submitButton.removeAttribute('disabled');
20903 }
20904 }
20905 }
20906
20907 obj.validateElement = function(element) {
20908 // Test results
20909 var test = false;
20910 // Value
20911 var value = Component.getValue(element);
20912 // Validation
20913 var validation = element.getAttribute('data-validation');
20914 // Parse
20915 if (typeof(obj.options.validations[validation]) == 'function' && ! obj.options.validations[validation](value, element)) {
20916 // Not passed in the test
20917 test = addError(element);
20918 } else {
20919 if (element.classList.contains('error')) {
20920 delError(element);
20921 }
20922 }
20923
20924 return test;
20925 }
20926
20927 obj.reset = function() {
20928 // Get elements in the form
20929 var name = null;
20930 var elements = el.querySelectorAll("input, select, textarea, div[name]");
20931 // Run all elements
20932 for (var i = 0; i < elements.length; i++) {
20933 if (name = elements[i].getAttribute('name')) {
20934 if (elements[i].type == 'checkbox' || elements[i].type == 'radio') {
20935 elements[i].checked = false;
20936 } else {
20937 if (typeof(elements[i].val) == 'function') {
20938 elements[i].val('');
20939 } else {
20940 elements[i].value = '';
20941 }
20942 }
20943 }
20944 }
20945 }
20946
20947 // Run form validation
20948 obj.validate = function() {
20949 var test = [];
20950 // Get elements in the form
20951 var elements = el.querySelectorAll("input, select, textarea, div[name]");
20952 // Run all elements
20953 for (var i = 0; i < elements.length; i++) {
20954 // Required
20955 if (elements[i].getAttribute('data-validation')) {
20956 var res = obj.validateElement(elements[i]);
20957 if (res) {
20958 test.push(res);
20959 }
20960 }
20961 }
20962 if (test.length > 0) {
20963 return test.join('<br>');
20964 } else {
20965 return false;
20966 }
20967 }
20968
20969 // Check the form
20970 obj.getError = function() {
20971 // Validation
20972 return obj.validation() ? true : false;
20973 }
20974
20975 // Return the form hash
20976 obj.setHash = function() {
20977 return obj.getHash(Component.getElements(el));
20978 }
20979
20980 // Get the form hash
20981 obj.getHash = function(str) {
20982 var hash = 0, i, chr;
20983
20984 if (str.length === 0) {
20985 return hash;
20986 } else {
20987 for (i = 0; i < str.length; i++) {
20988 chr = str.charCodeAt(i);
20989 hash = ((hash << 5) - hash) + chr;
20990 hash |= 0;
20991 }
20992 }
20993
20994 return hash;
20995 }
20996
20997 // Is there any change in the form since start tracking?
20998 obj.isChanged = function() {
20999 var hash = obj.setHash();
21000 return (obj.options.currentHash != hash);
21001 }
21002
21003 // Restart tracking
21004 obj.resetTracker = function() {
21005 obj.options.currentHash = obj.setHash();
21006 obj.options.ignore = false;
21007 }
21008
21009 // Ignore flag
21010 obj.setIgnore = function(ignoreFlag) {
21011 obj.options.ignore = ignoreFlag ? true : false;
21012 }
21013
21014 // Start tracking in one second
21015 setTimeout(function() {
21016 obj.options.currentHash = obj.setHash();
21017 }, 1000);
21018
21019 // Validations
21020 el.addEventListener("keyup", function(e) {
21021 if (e.target.getAttribute('data-validation')) {
21022 obj.validateElement(e.target);
21023 }
21024 });
21025
21026 // Alert
21027 if (! Component.hasEvents) {
21028 window.addEventListener("beforeunload", function (e) {
21029 if (obj.isChanged() && obj.options.ignore == false) {
21030 var confirmationMessage = obj.options.message? obj.options.message : "\o/";
21031
21032 if (confirmationMessage) {
21033 if (typeof e == 'undefined') {
21034 e = window.event;
21035 }
21036
21037 if (e) {
21038 e.returnValue = confirmationMessage;
21039 }
21040
21041 return confirmationMessage;
21042 } else {
21043 return void(0);
21044 }
21045 }
21046 });
21047
21048 Component.hasEvents = true;
21049 }
21050
21051 el.form = obj;
21052
21053 return obj;
21054 });
21055
21056 // Get value from one element
21057 Component.getValue = function(element) {
21058 var value = null;
21059 if (element.type == 'checkbox') {
21060 if (element.checked == true) {
21061 value = element.value || true;
21062 }
21063 } else if (element.type == 'radio') {
21064 if (element.checked == true) {
21065 value = element.value;
21066 }
21067 } else if (element.type == 'file') {
21068 value = element.files;
21069 } else if (element.tagName == 'select' && element.multiple == true) {
21070 value = [];
21071 var options = element.querySelectorAll("options[selected]");
21072 for (var j = 0; j < options.length; j++) {
21073 value.push(options[j].value);
21074 }
21075 } else if (typeof(element.val) == 'function') {
21076 value = element.val();
21077 } else {
21078 value = element.value || '';
21079 }
21080
21081 return value;
21082 }
21083
21084 // Get form elements
21085 Component.getElements = function(el, asArray) {
21086 var data = {};
21087 var name = null;
21088 var elements = el.querySelectorAll("input, select, textarea, div[name]");
21089
21090 for (var i = 0; i < elements.length; i++) {
21091 if (name = elements[i].getAttribute('name')) {
21092 data[name] = Component.getValue(elements[i]) || '';
21093 }
21094 }
21095
21096 return asArray == true ? data : JSON.stringify(data);
21097 }
21098
21099 //Get form elements
21100 Component.setElements = function(el, data) {
21101 var name = null;
21102 var value = null;
21103 var elements = el.querySelectorAll("input, select, textarea, div[name]");
21104 for (var i = 0; i < elements.length; i++) {
21105 // Attributes
21106 var type = elements[i].getAttribute('type');
21107 if (name = elements[i].getAttribute('name')) {
21108 // Transform variable names in pathname
21109 name = name.replace(new RegExp(/\[(.*?)\]/ig), '.$1');
21110 value = null;
21111 // Seach for the data in the path
21112 if (name.match(/\./)) {
21113 var tmp = Path.call(data, name) || '';
21114 if (typeof(tmp) !== 'undefined') {
21115 value = tmp;
21116 }
21117 } else {
21118 if (typeof(data[name]) !== 'undefined') {
21119 value = data[name];
21120 }
21121 }
21122 // Set the values
21123 if (value !== null) {
21124 if (type == 'checkbox' || type == 'radio') {
21125 elements[i].checked = value ? true : false;
21126 } else if (type == 'file') {
21127 // Do nothing
21128 } else {
21129 if (typeof (elements[i].val) == 'function') {
21130 elements[i].val(value);
21131 } else {
21132 elements[i].value = value;
21133 }
21134 }
21135 }
21136 }
21137 }
21138 }
21139
21140 return Component;
21141}
21142
21143/* harmony default export */ var plugins_form = (Form());
21144;// CONCATENATED MODULE: ./src/plugins/mask.js
21145/*
21146 Add '*' as a valid symbol
21147 Formats such as 'DD"th of "MMMM", "YYYY'
21148 Conditional masking
21149 (000) 00000-00
21150 $ (#,##0.00);$ (-#,##0.00)
21151 $ (-#,##0.00)
21152 j.mask.render(0, { mask: 'mm:ss.0' }
21153 j.mask.render(0, { mask: '[h]:mm:ss' }, true)
21154 */
21155
21156
21157
21158
21159/* harmony default export */ var mask = (dist.Mask);
21160
21161;// CONCATENATED MODULE: ./src/plugins/modal.js
21162
21163
21164
21165
21166function Modal() {
21167
21168 var Events = function() {
21169 // Position
21170 var tracker = null;
21171
21172 var keyDown = function (e) {
21173 if (e.which == 27) {
21174 var modals = document.querySelectorAll('.jmodal');
21175 for (var i = 0; i < modals.length; i++) {
21176 modals[i].parentNode.modal.close();
21177 }
21178 }
21179 }
21180
21181 var mouseUp = function (e) {
21182 let element = e.composedPath();
21183 var item = helpers.findElement(element[0], 'jmodal');
21184 if (item) {
21185 // Get target info
21186 var rect = item.getBoundingClientRect();
21187
21188 if (e.changedTouches && e.changedTouches[0]) {
21189 var x = e.changedTouches[0].clientX;
21190 var y = e.changedTouches[0].clientY;
21191 } else {
21192 var x = e.clientX;
21193 var y = e.clientY;
21194 }
21195
21196 if (rect.width - (x - rect.left) < 50 && (y - rect.top) < 50) {
21197 item.parentNode.modal.close();
21198 }
21199 }
21200
21201 if (tracker) {
21202 tracker.element.style.cursor = 'auto';
21203 tracker = null;
21204 }
21205 }
21206
21207 var mouseDown = function (e) {
21208 let element = e.composedPath();
21209 var item = helpers.findElement(element[0], 'jmodal');
21210 if (item) {
21211 // Get target info
21212 var rect = item.getBoundingClientRect();
21213
21214 if (e.changedTouches && e.changedTouches[0]) {
21215 var x = e.changedTouches[0].clientX;
21216 var y = e.changedTouches[0].clientY;
21217 } else {
21218 var x = e.clientX;
21219 var y = e.clientY;
21220 }
21221
21222 if (rect.width - (x - rect.left) < 50 && (y - rect.top) < 50) {
21223 // Do nothing
21224 } else {
21225 if (y - rect.top < 50) {
21226 if (document.selection) {
21227 document.selection.empty();
21228 } else if (window.getSelection) {
21229 window.getSelection().removeAllRanges();
21230 }
21231
21232 tracker = {
21233 left: rect.left,
21234 top: rect.top,
21235 x: e.clientX,
21236 y: e.clientY,
21237 width: rect.width,
21238 height: rect.height,
21239 element: item,
21240 }
21241 }
21242 }
21243 }
21244 }
21245
21246 var mouseMove = function (e) {
21247 if (tracker) {
21248 e = e || window.event;
21249 if (e.buttons) {
21250 var mouseButton = e.buttons;
21251 } else if (e.button) {
21252 var mouseButton = e.button;
21253 } else {
21254 var mouseButton = e.which;
21255 }
21256
21257 if (mouseButton) {
21258 tracker.element.style.top = (tracker.top + (e.clientY - tracker.y) + (tracker.height / 2)) + 'px';
21259 tracker.element.style.left = (tracker.left + (e.clientX - tracker.x) + (tracker.width / 2)) + 'px';
21260 tracker.element.style.cursor = 'move';
21261 } else {
21262 tracker.element.style.cursor = 'auto';
21263 }
21264 }
21265 }
21266
21267 document.addEventListener('keydown', keyDown);
21268 document.addEventListener('mouseup', mouseUp);
21269 document.addEventListener('mousedown', mouseDown);
21270 document.addEventListener('mousemove', mouseMove);
21271 }
21272
21273 var Component = (function (el, options) {
21274 var obj = {};
21275 obj.options = {};
21276
21277 // Default configuration
21278 var defaults = {
21279 url: null,
21280 onopen: null,
21281 onclose: null,
21282 onload: null,
21283 closed: false,
21284 width: null,
21285 height: null,
21286 title: null,
21287 padding: null,
21288 backdrop: true,
21289 icon: null,
21290 };
21291
21292 // Loop through our object
21293 for (var property in defaults) {
21294 if (options && options.hasOwnProperty(property)) {
21295 obj.options[property] = options[property];
21296 } else {
21297 obj.options[property] = defaults[property];
21298 }
21299 }
21300
21301 // Title
21302 if (!obj.options.title && el.getAttribute('title')) {
21303 obj.options.title = el.getAttribute('title');
21304 }
21305
21306 var temp = document.createElement('div');
21307 while (el.children[0]) {
21308 temp.appendChild(el.children[0]);
21309 }
21310
21311 obj.title = document.createElement('div');
21312 obj.title.className = 'jmodal_title';
21313 if (obj.options.icon) {
21314 obj.title.setAttribute('data-icon', obj.options.icon);
21315 }
21316
21317 obj.content = document.createElement('div');
21318 obj.content.className = 'jmodal_content';
21319 obj.content.innerHTML = el.innerHTML;
21320
21321 while (temp.children[0]) {
21322 obj.content.appendChild(temp.children[0]);
21323 }
21324
21325 obj.container = document.createElement('div');
21326 obj.container.className = 'jmodal';
21327 obj.container.appendChild(obj.title);
21328 obj.container.appendChild(obj.content);
21329
21330 if (obj.options.padding) {
21331 obj.content.style.padding = obj.options.padding;
21332 }
21333 if (obj.options.width) {
21334 obj.container.style.width = obj.options.width;
21335 }
21336 if (obj.options.height) {
21337 obj.container.style.height = obj.options.height;
21338 }
21339 if (obj.options.title) {
21340 var title = document.createElement('h4');
21341 title.innerText = obj.options.title;
21342 obj.title.appendChild(title);
21343 }
21344
21345 el.innerHTML = '';
21346 el.style.display = 'none';
21347 el.appendChild(obj.container);
21348
21349 // Backdrop
21350 if (obj.options.backdrop) {
21351 var backdrop = document.createElement('div');
21352 backdrop.className = 'jmodal_backdrop';
21353 backdrop.onclick = function () {
21354 obj.close();
21355 }
21356 el.appendChild(backdrop);
21357 }
21358
21359 obj.open = function () {
21360 el.style.display = 'block';
21361 // Fullscreen
21362 var rect = obj.container.getBoundingClientRect();
21363 if (helpers.getWindowWidth() < rect.width) {
21364 obj.container.style.top = '';
21365 obj.container.style.left = '';
21366 obj.container.classList.add('jmodal_fullscreen');
21367 animation.slideBottom(obj.container, 1);
21368 } else {
21369 if (obj.options.backdrop) {
21370 backdrop.style.display = 'block';
21371 }
21372 }
21373 // Event
21374 if (typeof (obj.options.onopen) == 'function') {
21375 obj.options.onopen(el, obj);
21376 }
21377 }
21378
21379 obj.resetPosition = function () {
21380 obj.container.style.top = '';
21381 obj.container.style.left = '';
21382 }
21383
21384 obj.isOpen = function () {
21385 return el.style.display != 'none' ? true : false;
21386 }
21387
21388 obj.close = function () {
21389 if (obj.isOpen()) {
21390 el.style.display = 'none';
21391 if (obj.options.backdrop) {
21392 // Backdrop
21393 backdrop.style.display = '';
21394 }
21395 // Remove fullscreen class
21396 obj.container.classList.remove('jmodal_fullscreen');
21397 // Event
21398 if (typeof (obj.options.onclose) == 'function') {
21399 obj.options.onclose(el, obj);
21400 }
21401 }
21402 }
21403
21404 if (obj.options.url) {
21405 ajax({
21406 url: obj.options.url,
21407 method: 'GET',
21408 dataType: 'text/html',
21409 success: function (data) {
21410 obj.content.innerHTML = data;
21411
21412 if (!obj.options.closed) {
21413 obj.open();
21414 }
21415
21416 if (typeof (obj.options.onload) === 'function') {
21417 obj.options.onload(obj);
21418 }
21419 }
21420 });
21421 } else {
21422 if (!obj.options.closed) {
21423 obj.open();
21424 }
21425
21426 if (typeof (obj.options.onload) === 'function') {
21427 obj.options.onload(obj);
21428 }
21429 }
21430
21431 // Keep object available from the node
21432 el.modal = obj;
21433
21434 // Create events when the first modal is create only
21435 Events();
21436
21437 // Execute the events only once
21438 Events = function() {};
21439
21440 return obj;
21441 });
21442
21443 return Component;
21444}
21445
21446/* harmony default export */ var modal = (Modal());
21447;// CONCATENATED MODULE: ./src/plugins/notification.js
21448
21449
21450
21451function Notification() {
21452 var Component = function (options) {
21453 var obj = {};
21454 obj.options = {};
21455
21456 // Default configuration
21457 var defaults = {
21458 icon: null,
21459 name: 'Notification',
21460 date: null,
21461 error: null,
21462 title: null,
21463 message: null,
21464 timeout: 4000,
21465 autoHide: true,
21466 closeable: true,
21467 };
21468
21469 // Loop through our object
21470 for (var property in defaults) {
21471 if (options && options.hasOwnProperty(property)) {
21472 obj.options[property] = options[property];
21473 } else {
21474 obj.options[property] = defaults[property];
21475 }
21476 }
21477
21478 var notification = document.createElement('div');
21479 notification.className = 'jnotification';
21480
21481 if (obj.options.error) {
21482 notification.classList.add('jnotification-error');
21483 }
21484
21485 var notificationContainer = document.createElement('div');
21486 notificationContainer.className = 'jnotification-container';
21487 notification.appendChild(notificationContainer);
21488
21489 var notificationHeader = document.createElement('div');
21490 notificationHeader.className = 'jnotification-header';
21491 notificationContainer.appendChild(notificationHeader);
21492
21493 var notificationImage = document.createElement('div');
21494 notificationImage.className = 'jnotification-image';
21495 notificationHeader.appendChild(notificationImage);
21496
21497 if (obj.options.icon) {
21498 var notificationIcon = document.createElement('img');
21499 notificationIcon.src = obj.options.icon;
21500 notificationImage.appendChild(notificationIcon);
21501 }
21502
21503 var notificationName = document.createElement('div');
21504 notificationName.className = 'jnotification-name';
21505 notificationName.innerHTML = obj.options.name;
21506 notificationHeader.appendChild(notificationName);
21507
21508 if (obj.options.closeable == true) {
21509 var notificationClose = document.createElement('div');
21510 notificationClose.className = 'jnotification-close';
21511 notificationClose.onclick = function () {
21512 obj.hide();
21513 }
21514 notificationHeader.appendChild(notificationClose);
21515 }
21516
21517 var notificationDate = document.createElement('div');
21518 notificationDate.className = 'jnotification-date';
21519 notificationHeader.appendChild(notificationDate);
21520
21521 var notificationContent = document.createElement('div');
21522 notificationContent.className = 'jnotification-content';
21523 notificationContainer.appendChild(notificationContent);
21524
21525 if (obj.options.title) {
21526 var notificationTitle = document.createElement('div');
21527 notificationTitle.className = 'jnotification-title';
21528 notificationTitle.innerHTML = obj.options.title;
21529 notificationContent.appendChild(notificationTitle);
21530 }
21531
21532 var notificationMessage = document.createElement('div');
21533 notificationMessage.className = 'jnotification-message';
21534 notificationMessage.innerHTML = obj.options.message;
21535 notificationContent.appendChild(notificationMessage);
21536
21537 obj.show = function () {
21538 document.body.appendChild(notification);
21539 if (helpers.getWindowWidth() > 800) {
21540 animation.fadeIn(notification);
21541 } else {
21542 animation.slideTop(notification, 1);
21543 }
21544 }
21545
21546 obj.hide = function () {
21547 if (helpers.getWindowWidth() > 800) {
21548 animation.fadeOut(notification, function () {
21549 if (notification.parentNode) {
21550 notification.parentNode.removeChild(notification);
21551 if (notificationTimeout) {
21552 clearTimeout(notificationTimeout);
21553 }
21554 }
21555 });
21556 } else {
21557 animation.slideTop(notification, 0, function () {
21558 if (notification.parentNode) {
21559 notification.parentNode.removeChild(notification);
21560 if (notificationTimeout) {
21561 clearTimeout(notificationTimeout);
21562 }
21563 }
21564 });
21565 }
21566 };
21567
21568 obj.show();
21569
21570 if (obj.options.autoHide == true) {
21571 var notificationTimeout = setTimeout(function () {
21572 obj.hide();
21573 }, obj.options.timeout);
21574 }
21575
21576 if (helpers.getWindowWidth() < 800) {
21577 notification.addEventListener("swipeup", function (e) {
21578 obj.hide();
21579 e.preventDefault();
21580 e.stopPropagation();
21581 });
21582 }
21583
21584 return obj;
21585 }
21586
21587 Component.isVisible = function () {
21588 var j = document.querySelector('.jnotification');
21589 return j && j.parentNode ? true : false;
21590 }
21591
21592 return Component;
21593}
21594
21595/* harmony default export */ var notification = (Notification());
21596;// CONCATENATED MODULE: ./src/plugins/progressbar.js
21597function Progressbar(el, options) {
21598 var obj = {};
21599 obj.options = {};
21600
21601 // Default configuration
21602 var defaults = {
21603 value: 0,
21604 onchange: null,
21605 width: null,
21606 };
21607
21608 // Loop through the initial configuration
21609 for (var property in defaults) {
21610 if (options && options.hasOwnProperty(property)) {
21611 obj.options[property] = options[property];
21612 } else {
21613 obj.options[property] = defaults[property];
21614 }
21615 }
21616
21617 // Class
21618 el.classList.add('jprogressbar');
21619 el.setAttribute('tabindex', 1);
21620 el.setAttribute('data-value', obj.options.value);
21621
21622 var bar = document.createElement('div');
21623 bar.style.width = obj.options.value + '%';
21624 bar.style.color = '#fff';
21625 el.appendChild(bar);
21626
21627 if (obj.options.width) {
21628 el.style.width = obj.options.width;
21629 }
21630
21631 // Set value
21632 obj.setValue = function(value) {
21633 value = parseInt(value);
21634 obj.options.value = value;
21635 bar.style.width = value + '%';
21636 el.setAttribute('data-value', value + '%');
21637
21638 if (value < 6) {
21639 el.style.color = '#000';
21640 } else {
21641 el.style.color = '#fff';
21642 }
21643
21644 // Update value
21645 obj.options.value = value;
21646
21647 if (typeof(obj.options.onchange) == 'function') {
21648 obj.options.onchange(el, value);
21649 }
21650
21651 // Lemonade JS
21652 if (el.value != obj.options.value) {
21653 el.value = obj.options.value;
21654 if (typeof(el.oninput) == 'function') {
21655 el.oninput({
21656 type: 'input',
21657 target: el,
21658 value: el.value
21659 });
21660 }
21661 }
21662 }
21663
21664 obj.getValue = function() {
21665 return obj.options.value;
21666 }
21667
21668 var action = function(e) {
21669 if (e.which) {
21670 // Get target info
21671 var rect = el.getBoundingClientRect();
21672
21673 if (e.changedTouches && e.changedTouches[0]) {
21674 var x = e.changedTouches[0].clientX;
21675 var y = e.changedTouches[0].clientY;
21676 } else {
21677 var x = e.clientX;
21678 var y = e.clientY;
21679 }
21680
21681 obj.setValue(Math.round((x - rect.left) / rect.width * 100));
21682 }
21683 }
21684
21685 // Events
21686 if ('touchstart' in document.documentElement === true) {
21687 el.addEventListener('touchstart', action);
21688 el.addEventListener('touchend', action);
21689 } else {
21690 el.addEventListener('mousedown', action);
21691 el.addEventListener("mousemove", action);
21692 }
21693
21694 // Change
21695 el.change = obj.setValue;
21696
21697 // Global generic value handler
21698 el.val = function(val) {
21699 if (val === undefined) {
21700 return obj.getValue();
21701 } else {
21702 obj.setValue(val);
21703 }
21704 }
21705
21706 // Reference
21707 el.progressbar = obj;
21708
21709 return obj;
21710}
21711;// CONCATENATED MODULE: ./src/plugins/rating.js
21712function Rating(el, options) {
21713 // Already created, update options
21714 if (el.rating) {
21715 return el.rating.setOptions(options, true);
21716 }
21717
21718 // New instance
21719 var obj = {};
21720 obj.options = {};
21721
21722 obj.setOptions = function(options, reset) {
21723 // Default configuration
21724 var defaults = {
21725 number: 5,
21726 value: 0,
21727 tooltip: [ 'Very bad', 'Bad', 'Average', 'Good', 'Very good' ],
21728 onchange: null,
21729 };
21730
21731 // Loop through the initial configuration
21732 for (var property in defaults) {
21733 if (options && options.hasOwnProperty(property)) {
21734 obj.options[property] = options[property];
21735 } else {
21736 if (typeof(obj.options[property]) == 'undefined' || reset === true) {
21737 obj.options[property] = defaults[property];
21738 }
21739 }
21740 }
21741
21742 // Make sure the container is empty
21743 el.innerHTML = '';
21744
21745 // Add elements
21746 for (var i = 0; i < obj.options.number; i++) {
21747 var div = document.createElement('div');
21748 div.setAttribute('data-index', (i + 1))
21749 div.setAttribute('title', obj.options.tooltip[i])
21750 el.appendChild(div);
21751 }
21752
21753 // Selected option
21754 if (obj.options.value) {
21755 for (var i = 0; i < obj.options.number; i++) {
21756 if (i < obj.options.value) {
21757 el.children[i].classList.add('jrating-selected');
21758 }
21759 }
21760 }
21761
21762 return obj;
21763 }
21764
21765 // Set value
21766 obj.setValue = function(index) {
21767 for (var i = 0; i < obj.options.number; i++) {
21768 if (i < index) {
21769 el.children[i].classList.add('jrating-selected');
21770 } else {
21771 el.children[i].classList.remove('jrating-over');
21772 el.children[i].classList.remove('jrating-selected');
21773 }
21774 }
21775
21776 obj.options.value = index;
21777
21778 if (typeof(obj.options.onchange) == 'function') {
21779 obj.options.onchange(el, index);
21780 }
21781
21782 // Lemonade JS
21783 if (el.value != obj.options.value) {
21784 el.value = obj.options.value;
21785 if (typeof(el.oninput) == 'function') {
21786 el.oninput({
21787 type: 'input',
21788 target: el,
21789 value: el.value
21790 });
21791 }
21792 }
21793 }
21794
21795 obj.getValue = function() {
21796 return obj.options.value;
21797 }
21798
21799 var init = function() {
21800 // Start plugin
21801 obj.setOptions(options);
21802
21803 // Class
21804 el.classList.add('jrating');
21805
21806 // Events
21807 el.addEventListener("click", function(e) {
21808 var index = e.target.getAttribute('data-index');
21809 if (index != undefined) {
21810 if (index == obj.options.value) {
21811 obj.setValue(0);
21812 } else {
21813 obj.setValue(index);
21814 }
21815 }
21816 });
21817
21818 el.addEventListener("mouseover", function(e) {
21819 var index = e.target.getAttribute('data-index');
21820 for (var i = 0; i < obj.options.number; i++) {
21821 if (i < index) {
21822 el.children[i].classList.add('jrating-over');
21823 } else {
21824 el.children[i].classList.remove('jrating-over');
21825 }
21826 }
21827 });
21828
21829 el.addEventListener("mouseout", function(e) {
21830 for (var i = 0; i < obj.options.number; i++) {
21831 el.children[i].classList.remove('jrating-over');
21832 }
21833 });
21834
21835 // Change
21836 el.change = obj.setValue;
21837
21838 // Global generic value handler
21839 el.val = function(val) {
21840 if (val === undefined) {
21841 return obj.getValue();
21842 } else {
21843 obj.setValue(val);
21844 }
21845 }
21846
21847 // Reference
21848 el.rating = obj;
21849 }
21850
21851 init();
21852
21853 return obj;
21854}
21855;// CONCATENATED MODULE: ./src/plugins/search.js
21856
21857
21858
21859function Search(el, options) {
21860 if (el.search) {
21861 return el.search;
21862 }
21863
21864 var index = null;
21865
21866 var select = function(e) {
21867 if (e.target.classList.contains('jsearch_item')) {
21868 var element = e.target;
21869 } else {
21870 var element = e.target.parentNode;
21871 }
21872
21873 obj.selectIndex(element);
21874 e.preventDefault();
21875 }
21876
21877 var createList = function(data) {
21878 if (typeof(obj.options.onsearch) == 'function') {
21879 var ret = obj.options.onsearch(obj, data);
21880 if (ret) {
21881 data = ret;
21882 }
21883 }
21884
21885 // Reset container
21886 container.innerHTML = '';
21887 // Print results
21888 if (! data.length) {
21889 // Show container
21890 el.style.display = '';
21891 } else {
21892 // Show container
21893 el.style.display = 'block';
21894
21895 // Show items (only 10)
21896 var len = data.length < 11 ? data.length : 10;
21897 for (var i = 0; i < len; i++) {
21898 if (typeof(data[i]) == 'string') {
21899 var text = data[i];
21900 var value = data[i];
21901 } else {
21902 // Legacy
21903 var text = data[i].text;
21904 if (! text && data[i].name) {
21905 text = data[i].name;
21906 }
21907 var value = data[i].value;
21908 if (! value && data[i].id) {
21909 value = data[i].id;
21910 }
21911 }
21912
21913 var div = document.createElement('div');
21914 div.setAttribute('data-value', value);
21915 div.setAttribute('data-text', text);
21916 div.className = 'jsearch_item';
21917
21918 if (data[i].id) {
21919 div.setAttribute('id', data[i].id)
21920 }
21921
21922 if (obj.options.forceSelect && i == 0) {
21923 div.classList.add('selected');
21924 }
21925 var img = document.createElement('img');
21926 if (data[i].image) {
21927 img.src = data[i].image;
21928 } else {
21929 img.style.display = 'none';
21930 }
21931 div.appendChild(img);
21932
21933 var item = document.createElement('div');
21934 item.innerHTML = text;
21935 div.appendChild(item);
21936
21937 // Append item to the container
21938 container.appendChild(div);
21939 }
21940 }
21941 }
21942
21943 var execute = function(str) {
21944 if (str != obj.terms) {
21945 // New terms
21946 obj.terms = str;
21947 // New index
21948 if (obj.options.forceSelect) {
21949 index = 0;
21950 } else {
21951 index = null;
21952 }
21953 // Array or remote search
21954 if (Array.isArray(obj.options.data)) {
21955 var test = function(o) {
21956 if (typeof(o) == 'string') {
21957 if ((''+o).toLowerCase().search(str.toLowerCase()) >= 0) {
21958 return true;
21959 }
21960 } else {
21961 for (var key in o) {
21962 var value = o[key];
21963 if ((''+value).toLowerCase().search(str.toLowerCase()) >= 0) {
21964 return true;
21965 }
21966 }
21967 }
21968 return false;
21969 }
21970
21971 var results = obj.options.data.filter(function(item) {
21972 return test(item);
21973 });
21974
21975 // Show items
21976 createList(results);
21977 } else {
21978 // Get remove results
21979 ajax({
21980 url: obj.options.data + str,
21981 method: 'GET',
21982 dataType: 'json',
21983 success: function(data) {
21984 // Show items
21985 createList(data);
21986 }
21987 });
21988 }
21989 }
21990 }
21991
21992 // Search timer
21993 var timer = null;
21994
21995 // Search methods
21996 var obj = function(str) {
21997 if (timer) {
21998 clearTimeout(timer);
21999 }
22000 timer = setTimeout(function() {
22001 execute(str);
22002 }, 500);
22003 }
22004 if(options.forceSelect === null) {
22005 options.forceSelect = true;
22006 }
22007 obj.options = {
22008 data: options.data || null,
22009 input: options.input || null,
22010 searchByNode: options.searchByNode || null,
22011 onselect: options.onselect || null,
22012 forceSelect: options.forceSelect,
22013 onsearch: options.onsearch || null,
22014 onbeforesearch: options.onbeforesearch || null,
22015 };
22016
22017 obj.selectIndex = function(item) {
22018 var id = item.getAttribute('id');
22019 var text = item.getAttribute('data-text');
22020 var value = item.getAttribute('data-value');
22021 var image = item.children[0].src || '';
22022 // Onselect
22023 if (typeof(obj.options.onselect) == 'function') {
22024 obj.options.onselect(obj, text, value, id, image);
22025 }
22026 // Close container
22027 obj.close();
22028 }
22029
22030 obj.open = function() {
22031 el.style.display = 'block';
22032 }
22033
22034 obj.close = function() {
22035 if (timer) {
22036 clearTimeout(timer);
22037 }
22038 // Current terms
22039 obj.terms = '';
22040 // Remove results
22041 container.innerHTML = '';
22042 // Hide
22043 el.style.display = '';
22044 }
22045
22046 obj.isOpened = function() {
22047 return el.style.display ? true : false;
22048 }
22049
22050 obj.keydown = function(e) {
22051 if (obj.isOpened()) {
22052 if (e.key == 'Enter') {
22053 // Enter
22054 if (index!==null && container.children[index]) {
22055 obj.selectIndex(container.children[index]);
22056 e.preventDefault();
22057 } else {
22058 obj.close();
22059 }
22060 } else if (e.key === 'ArrowUp') {
22061 // Up
22062 if (index!==null && container.children[0]) {
22063 container.children[index].classList.remove('selected');
22064 if(!obj.options.forceSelect && index === 0) {
22065 index = null;
22066 } else {
22067 index = Math.max(0, index-1);
22068 container.children[index].classList.add('selected');
22069 }
22070 }
22071 e.preventDefault();
22072 } else if (e.key === 'ArrowDown') {
22073 // Down
22074 if(index == null) {
22075 index = -1;
22076 } else {
22077 container.children[index].classList.remove('selected');
22078 }
22079 if (index < 9 && container.children[index+1]) {
22080 index++;
22081 }
22082 container.children[index].classList.add('selected');
22083 e.preventDefault();
22084 }
22085 }
22086 }
22087
22088 obj.keyup = function(e) {
22089 if (! obj.options.searchByNode && obj.options.input) {
22090 if (obj.options.input.tagName === 'DIV') {
22091 var terms = obj.options.input.innerText;
22092 } else {
22093 var terms = obj.options.input.value;
22094 }
22095 } else {
22096 // Current node
22097 var node = helpers.getNode();
22098 if (node) {
22099 var terms = node.innerText;
22100 }
22101 }
22102
22103 if (typeof(obj.options.onbeforesearch) == 'function') {
22104 var ret = obj.options.onbeforesearch(obj, terms);
22105 if (ret) {
22106 terms = ret;
22107 } else {
22108 if (ret === false) {
22109 // Ignore event
22110 return;
22111 }
22112 }
22113 }
22114
22115 obj(terms);
22116 }
22117
22118 obj.blur = function(e) {
22119 obj.close();
22120 }
22121
22122 // Add events
22123 if (obj.options.input) {
22124 obj.options.input.addEventListener("keyup", obj.keyup);
22125 obj.options.input.addEventListener("keydown", obj.keydown);
22126 obj.options.input.addEventListener("blur", obj.blur);
22127 }
22128
22129 // Append element
22130 var container = document.createElement('div');
22131 container.classList.add('jsearch_container');
22132 container.onmousedown = select;
22133 el.appendChild(container);
22134
22135 el.classList.add('jsearch');
22136 el.search = obj;
22137
22138 return obj;
22139}
22140;// CONCATENATED MODULE: ./src/plugins/slider.js
22141function Slider(el, options) {
22142 var obj = {};
22143 obj.options = {};
22144 obj.currentImage = null;
22145
22146 if (options) {
22147 obj.options = options;
22148 }
22149
22150 // Focus
22151 el.setAttribute('tabindex', '900')
22152
22153 // Items
22154 obj.options.items = [];
22155
22156 if (! el.classList.contains('jslider')) {
22157 el.classList.add('jslider');
22158 el.classList.add('unselectable');
22159
22160 if (obj.options.height) {
22161 el.style.minHeight = parseInt(obj.options.height) + 'px';
22162 }
22163 if (obj.options.width) {
22164 el.style.width = parseInt(obj.options.width) + 'px';
22165 }
22166 if (obj.options.grid) {
22167 el.classList.add('jslider-grid');
22168 var number = el.children.length;
22169 if (number > 4) {
22170 el.setAttribute('data-total', number - 4);
22171 }
22172 el.setAttribute('data-number', (number > 4 ? 4 : number));
22173 }
22174
22175 // Add slider counter
22176 var counter = document.createElement('div');
22177 counter.classList.add('jslider-counter');
22178
22179 // Move children inside
22180 if (el.children.length > 0) {
22181 // Keep children items
22182 for (var i = 0; i < el.children.length; i++) {
22183 obj.options.items.push(el.children[i]);
22184
22185 // counter click event
22186 var item = document.createElement('div');
22187 item.onclick = function() {
22188 var index = Array.prototype.slice.call(counter.children).indexOf(this);
22189 obj.show(obj.currentImage = obj.options.items[index]);
22190 }
22191 counter.appendChild(item);
22192 }
22193 }
22194 // Add caption
22195 var caption = document.createElement('div');
22196 caption.className = 'jslider-caption';
22197
22198 // Add close buttom
22199 var controls = document.createElement('div');
22200 var close = document.createElement('div');
22201 close.className = 'jslider-close';
22202 close.innerHTML = '';
22203
22204 close.onclick = function() {
22205 obj.close();
22206 }
22207 controls.appendChild(caption);
22208 controls.appendChild(close);
22209 }
22210
22211 obj.updateCounter = function(index) {
22212 for (var i = 0; i < counter.children.length; i ++) {
22213 if (counter.children[i].classList.contains('jslider-counter-focus')) {
22214 counter.children[i].classList.remove('jslider-counter-focus');
22215 break;
22216 }
22217 }
22218 counter.children[index].classList.add('jslider-counter-focus');
22219 }
22220
22221 obj.show = function(target) {
22222 if (! target) {
22223 var target = el.children[0];
22224 }
22225
22226 // Focus element
22227 el.classList.add('jslider-focus');
22228 el.classList.remove('jslider-grid');
22229 el.appendChild(controls);
22230 el.appendChild(counter);
22231
22232 // Update counter
22233 var index = obj.options.items.indexOf(target);
22234 obj.updateCounter(index);
22235
22236 // Remove display
22237 for (var i = 0; i < el.children.length; i++) {
22238 el.children[i].style.display = '';
22239 }
22240 target.style.display = 'block';
22241
22242 // Is there any previous
22243 if (target.previousElementSibling) {
22244 el.classList.add('jslider-left');
22245 } else {
22246 el.classList.remove('jslider-left');
22247 }
22248
22249 // Is there any next
22250 if (target.nextElementSibling && target.nextElementSibling.tagName == 'IMG') {
22251 el.classList.add('jslider-right');
22252 } else {
22253 el.classList.remove('jslider-right');
22254 }
22255
22256 obj.currentImage = target;
22257
22258 // Vertical image
22259 if (obj.currentImage.offsetHeight > obj.currentImage.offsetWidth) {
22260 obj.currentImage.classList.add('jslider-vertical');
22261 }
22262
22263 controls.children[0].innerText = obj.currentImage.getAttribute('title');
22264 }
22265
22266 obj.open = function() {
22267 obj.show();
22268
22269 // Event
22270 if (typeof(obj.options.onopen) == 'function') {
22271 obj.options.onopen(el);
22272 }
22273 }
22274
22275 obj.close = function() {
22276 // Remove control classes
22277 el.classList.remove('jslider-focus');
22278 el.classList.remove('jslider-left');
22279 el.classList.remove('jslider-right');
22280 // Show as a grid depending on the configuration
22281 if (obj.options.grid) {
22282 el.classList.add('jslider-grid');
22283 }
22284 // Remove display
22285 for (var i = 0; i < el.children.length; i++) {
22286 el.children[i].style.display = '';
22287 }
22288 // Remove controls from the component
22289 counter.remove();
22290 controls.remove();
22291 // Current image
22292 obj.currentImage = null;
22293 // Event
22294 if (typeof(obj.options.onclose) == 'function') {
22295 obj.options.onclose(el);
22296 }
22297 }
22298
22299 obj.reset = function() {
22300 el.innerHTML = '';
22301 }
22302
22303 obj.next = function() {
22304 var nextImage = obj.currentImage.nextElementSibling;
22305 if (nextImage && nextImage.tagName === 'IMG') {
22306 obj.show(obj.currentImage.nextElementSibling);
22307 }
22308 }
22309
22310 obj.prev = function() {
22311 if (obj.currentImage.previousElementSibling) {
22312 obj.show(obj.currentImage.previousElementSibling);
22313 }
22314 }
22315
22316 var mouseUp = function(e) {
22317 // Open slider
22318 if (e.target.tagName == 'IMG') {
22319 obj.show(e.target);
22320 } else if (! e.target.classList.contains('jslider-close') && ! (e.target.parentNode.classList.contains('jslider-counter') || e.target.classList.contains('jslider-counter'))){
22321 // Arrow controls
22322 var offsetX = e.offsetX || e.changedTouches[0].clientX;
22323 if (e.target.clientWidth - offsetX < 40) {
22324 // Show next image
22325 obj.next();
22326 } else if (offsetX < 40) {
22327 // Show previous image
22328 obj.prev();
22329 }
22330 }
22331 }
22332
22333 if ('ontouchend' in document.documentElement === true) {
22334 el.addEventListener('touchend', mouseUp);
22335 } else {
22336 el.addEventListener('mouseup', mouseUp);
22337 }
22338
22339 // Add global events
22340 el.addEventListener("swipeleft", function(e) {
22341 obj.next();
22342 e.preventDefault();
22343 e.stopPropagation();
22344 });
22345
22346 el.addEventListener("swiperight", function(e) {
22347 obj.prev();
22348 e.preventDefault();
22349 e.stopPropagation();
22350 });
22351
22352 el.addEventListener('keydown', function(e) {
22353 if (e.which == 27) {
22354 obj.close();
22355 }
22356 });
22357
22358 el.slider = obj;
22359
22360 return obj;
22361}
22362;// CONCATENATED MODULE: ./src/plugins/tags.js
22363
22364
22365
22366
22367function Tags(el, options) {
22368 // Redefine configuration
22369 if (el.tags) {
22370 return el.tags.setOptions(options, true);
22371 }
22372
22373 var obj = { type:'tags' };
22374 obj.options = {};
22375
22376 // Limit
22377 var limit = function() {
22378 return obj.options.limit && el.children.length >= obj.options.limit ? true : false;
22379 }
22380
22381 // Search helpers
22382 var search = null;
22383 var searchContainer = null;
22384
22385 obj.setOptions = function(options, reset) {
22386 /**
22387 * @typedef {Object} defaults
22388 * @property {(string|Array)} value - Initial value of the compontent
22389 * @property {number} limit - Max number of tags inside the element
22390 * @property {string} search - The URL for suggestions
22391 * @property {string} placeholder - The default instruction text on the element
22392 * @property {validation} validation - Method to validate the tags
22393 * @property {requestCallback} onbeforechange - Method to be execute before any changes on the element
22394 * @property {requestCallback} onchange - Method to be execute after any changes on the element
22395 * @property {requestCallback} onfocus - Method to be execute when on focus
22396 * @property {requestCallback} onblur - Method to be execute when on blur
22397 * @property {requestCallback} onload - Method to be execute when the element is loaded
22398 */
22399 var defaults = {
22400 value: '',
22401 limit: null,
22402 search: null,
22403 placeholder: null,
22404 validation: null,
22405 onbeforepaste: null,
22406 onbeforechange: null,
22407 onremoveitem: null,
22408 onlimit: null,
22409 onchange: null,
22410 onfocus: null,
22411 onblur: null,
22412 onload: null,
22413 }
22414
22415 // Loop through though the default configuration
22416 for (var property in defaults) {
22417 if (options && options.hasOwnProperty(property)) {
22418 obj.options[property] = options[property];
22419 } else {
22420 if (typeof(obj.options[property]) == 'undefined' || reset === true) {
22421 obj.options[property] = defaults[property];
22422 }
22423 }
22424 }
22425
22426 // Placeholder
22427 if (obj.options.placeholder) {
22428 el.setAttribute('data-placeholder', obj.options.placeholder);
22429 } else {
22430 el.removeAttribute('data-placeholder');
22431 }
22432 el.placeholder = obj.options.placeholder;
22433
22434 // Update value
22435 obj.setValue(obj.options.value);
22436
22437 // Validate items
22438 filter();
22439
22440 // Create search box
22441 if (obj.options.search) {
22442 if (! searchContainer) {
22443 searchContainer = document.createElement('div');
22444 el.parentNode.insertBefore(searchContainer, el.nextSibling);
22445
22446 // Create container
22447 search = Search(searchContainer, {
22448 data: obj.options.search,
22449 onselect: function(a,b,c) {
22450 obj.selectIndex(b,c);
22451 }
22452 });
22453 }
22454 } else {
22455 if (searchContainer) {
22456 search = null;
22457 searchContainer.remove();
22458 searchContainer = null;
22459 }
22460 }
22461
22462 return obj;
22463 }
22464
22465 /**
22466 * Add a new tag to the element
22467 * @param {(?string|Array)} value - The value of the new element
22468 */
22469 obj.add = function(value, focus) {
22470 if (typeof(obj.options.onbeforechange) == 'function') {
22471 var ret = obj.options.onbeforechange(el, obj, obj.options.value, value);
22472 if (ret === false) {
22473 return false;
22474 } else {
22475 if (ret != null) {
22476 value = ret;
22477 }
22478 }
22479 }
22480
22481 // Make sure search is closed
22482 if (search) {
22483 search.close();
22484 }
22485
22486 if (limit()) {
22487 if (typeof(obj.options.onlimit) == 'function') {
22488 obj.options.onlimit(obj, obj.options.limit);
22489 } else {
22490 alert(dictionary.translate('You reach the limit number of entries') + ' ' + obj.options.limit);
22491 }
22492 } else {
22493 // Get node
22494 var node = helpers.getNode();
22495
22496 if (node && node.parentNode && node.parentNode.classList.contains('jtags') &&
22497 node.nextSibling && (! (node.nextSibling.innerText && node.nextSibling.innerText.trim()))) {
22498 div = node.nextSibling;
22499 } else {
22500 // Remove not used last item
22501 if (el.lastChild) {
22502 if (! el.lastChild.innerText.trim()) {
22503 el.removeChild(el.lastChild);
22504 }
22505 }
22506
22507 // Mix argument string or array
22508 if (! value || typeof(value) == 'string') {
22509 var div = createElement(value, value, node);
22510 } else {
22511 for (var i = 0; i <= value.length; i++) {
22512 if (! limit()) {
22513 if (! value[i] || typeof(value[i]) == 'string') {
22514 var t = value[i] || '';
22515 var v = null;
22516 } else {
22517 var t = value[i].text;
22518 var v = value[i].value;
22519 }
22520
22521 // Add element
22522 var div = createElement(t, v);
22523 }
22524 }
22525 }
22526
22527 // Change
22528 change();
22529 }
22530
22531 // Place caret
22532 if (focus) {
22533 setFocus(div);
22534 }
22535 }
22536 }
22537
22538 obj.setLimit = function(limit) {
22539 obj.options.limit = limit;
22540 var n = el.children.length - limit;
22541 while (el.children.length > limit) {
22542 el.removeChild(el.lastChild);
22543 }
22544 }
22545
22546 // Remove a item node
22547 obj.remove = function(node) {
22548 // Remove node
22549 node.parentNode.removeChild(node);
22550 // Make sure element is not blank
22551 if (! el.children.length) {
22552 obj.add('', true);
22553 } else {
22554 change();
22555 }
22556
22557 if (typeof(obj.options.onremoveitem) == 'function') {
22558 obj.options.onremoveitem(el, obj, node);
22559 }
22560 }
22561
22562 /**
22563 * Get all tags in the element
22564 * @return {Array} data - All tags as an array
22565 */
22566 obj.getData = function() {
22567 var data = [];
22568 for (var i = 0; i < el.children.length; i++) {
22569 // Get value
22570 var text = el.children[i].innerText.replace("\n", "");
22571 // Get id
22572 var value = el.children[i].getAttribute('data-value');
22573 if (! value) {
22574 value = text;
22575 }
22576 // Item
22577 if (text || value) {
22578 data.push({ text: text, value: value });
22579 }
22580 }
22581 return data;
22582 }
22583
22584 /**
22585 * Get the value of one tag. Null for all tags
22586 * @param {?number} index - Tag index number. Null for all tags.
22587 * @return {string} value - All tags separated by comma
22588 */
22589 obj.getValue = function(index) {
22590 var value = null;
22591
22592 if (index != null) {
22593 // Get one individual value
22594 value = el.children[index].getAttribute('data-value');
22595 if (! value) {
22596 value = el.children[index].innerText.replace("\n", "");
22597 }
22598 } else {
22599 // Get all
22600 var data = [];
22601 for (var i = 0; i < el.children.length; i++) {
22602 value = el.children[i].innerText.replace("\n", "");
22603 if (value) {
22604 data.push(obj.getValue(i));
22605 }
22606 }
22607 value = data.join(',');
22608 }
22609
22610 return value;
22611 }
22612
22613 /**
22614 * Set the value of the element based on a string separeted by (,|;|\r\n)
22615 * @param {mixed} value - A string or array object with values
22616 */
22617 obj.setValue = function(mixed) {
22618 if (! mixed) {
22619 obj.reset();
22620 } else {
22621 if (el.value != mixed) {
22622 if (Array.isArray(mixed)) {
22623 obj.add(mixed);
22624 } else {
22625 // Remove whitespaces
22626 var text = (''+mixed).trim();
22627 // Tags
22628 var data = extractTags(text);
22629 // Reset
22630 el.innerHTML = '';
22631 // Add tags to the element
22632 obj.add(data);
22633 }
22634 }
22635 }
22636 }
22637
22638 /**
22639 * Reset the data from the element
22640 */
22641 obj.reset = function() {
22642 // Empty class
22643 el.classList.add('jtags-empty');
22644 // Empty element
22645 el.innerHTML = '<div></div>';
22646 // Execute changes
22647 change();
22648 }
22649
22650 /**
22651 * Verify if all tags in the element are valid
22652 * @return {boolean}
22653 */
22654 obj.isValid = function() {
22655 var test = 0;
22656 for (var i = 0; i < el.children.length; i++) {
22657 if (el.children[i].classList.contains('jtags_error')) {
22658 test++;
22659 }
22660 }
22661 return test == 0 ? true : false;
22662 }
22663
22664 /**
22665 * Add one element from the suggestions to the element
22666 * @param {object} item - Node element in the suggestions container
22667 */
22668 obj.selectIndex = function(text, value) {
22669 var node = helpers.getNode();
22670 if (node) {
22671 // Append text to the caret
22672 node.innerText = text;
22673 // Set node id
22674 if (value) {
22675 node.setAttribute('data-value', value);
22676 }
22677 // Remove any error
22678 node.classList.remove('jtags_error');
22679 if (! limit()) {
22680 // Add new item
22681 obj.add('', true);
22682 }
22683 }
22684 }
22685
22686 /**
22687 * Search for suggestions
22688 * @param {object} node - Target node for any suggestions
22689 */
22690 obj.search = function(node) {
22691 // Search for
22692 var terms = node.innerText;
22693 }
22694
22695 // Destroy tags element
22696 obj.destroy = function() {
22697 // Bind events
22698 el.removeEventListener('mouseup', tagsMouseUp);
22699 el.removeEventListener('keydown', tagsKeyDown);
22700 el.removeEventListener('keyup', tagsKeyUp);
22701 el.removeEventListener('paste', tagsPaste);
22702 el.removeEventListener('focus', tagsFocus);
22703 el.removeEventListener('blur', tagsBlur);
22704
22705 // Remove element
22706 el.parentNode.removeChild(el);
22707 }
22708
22709 var setFocus = function(node) {
22710 if (el.children.length) {
22711 var range = document.createRange();
22712 var sel = window.getSelection();
22713 if (! node) {
22714 var node = el.childNodes[el.childNodes.length-1];
22715 }
22716 range.setStart(node, node.length)
22717 range.collapse(true)
22718 sel.removeAllRanges()
22719 sel.addRange(range)
22720 el.scrollLeft = el.scrollWidth;
22721 }
22722 }
22723
22724 var createElement = function(label, value, node) {
22725 var div = document.createElement('div');
22726 div.textContent = label ? label : '';
22727 if (value) {
22728 div.setAttribute('data-value', value);
22729 }
22730
22731 if (node && node.parentNode.classList.contains('jtags')) {
22732 el.insertBefore(div, node.nextSibling);
22733 } else {
22734 el.appendChild(div);
22735 }
22736
22737 return div;
22738 }
22739
22740 var change = function() {
22741 // Value
22742 var value = obj.getValue();
22743
22744 if (value != obj.options.value) {
22745 obj.options.value = value;
22746 if (typeof(obj.options.onchange) == 'function') {
22747 obj.options.onchange(el, obj, obj.options.value);
22748 }
22749
22750 // Lemonade JS
22751 if (el.value != obj.options.value) {
22752 el.value = obj.options.value;
22753 if (typeof(el.oninput) == 'function') {
22754 el.oninput({
22755 type: 'input',
22756 target: el,
22757 value: el.value
22758 });
22759 }
22760 }
22761 }
22762
22763 filter();
22764 }
22765
22766 /**
22767 * Filter tags
22768 */
22769 var filter = function() {
22770 for (var i = 0; i < el.children.length; i++) {
22771 if (el.children[i].tagName === 'DIV') {
22772 // Create label design
22773 if (!obj.getValue(i)) {
22774 el.children[i].classList.remove('jtags_label');
22775 } else {
22776 el.children[i].classList.add('jtags_label');
22777
22778 // Validation in place
22779 if (typeof (obj.options.validation) == 'function') {
22780 if (obj.getValue(i)) {
22781 if (!obj.options.validation(el.children[i], el.children[i].innerText, el.children[i].getAttribute('data-value'))) {
22782 el.children[i].classList.add('jtags_error');
22783 } else {
22784 el.children[i].classList.remove('jtags_error');
22785 }
22786 } else {
22787 el.children[i].classList.remove('jtags_error');
22788 }
22789 } else {
22790 el.children[i].classList.remove('jtags_error');
22791 }
22792 }
22793 }
22794 }
22795
22796 isEmpty();
22797 }
22798
22799 var isEmpty = function() {
22800 // Can't be empty
22801 if (! el.innerText.trim()) {
22802 if (! el.children.length || el.children[0].tagName === 'BR') {
22803 el.innerHTML = '';
22804 setFocus(createElement());
22805 }
22806 } else {
22807 el.classList.remove('jtags-empty');
22808 }
22809 }
22810
22811 /**
22812 * Extract tags from a string
22813 * @param {string} text - Raw string
22814 * @return {Array} data - Array with extracted tags
22815 */
22816 var extractTags = function(text) {
22817 /** @type {Array} */
22818 var data = [];
22819
22820 /** @type {string} */
22821 var word = '';
22822
22823 // Remove whitespaces
22824 text = text.trim();
22825
22826 if (text) {
22827 for (var i = 0; i < text.length; i++) {
22828 if (text[i] == ',' || text[i] == ';' || text[i] == '\n') {
22829 if (word) {
22830 data.push(word.trim());
22831 word = '';
22832 }
22833 } else {
22834 word += text[i];
22835 }
22836 }
22837
22838 if (word) {
22839 data.push(word);
22840 }
22841 }
22842
22843 return data;
22844 }
22845
22846 /** @type {number} */
22847 var anchorOffset = 0;
22848
22849 /**
22850 * Processing event keydown on the element
22851 * @param e {object}
22852 */
22853 var tagsKeyDown = function(e) {
22854 // Anchoroffset
22855 anchorOffset = window.getSelection().anchorOffset;
22856
22857 // Verify if is empty
22858 isEmpty();
22859
22860 // Comma
22861 if (e.key === 'Tab' || e.key === ';' || e.key === ',') {
22862 var n = window.getSelection().anchorOffset;
22863 if (n > 1) {
22864 if (limit()) {
22865 if (typeof(obj.options.onlimit) == 'function') {
22866 obj.options.onlimit(obj, obj.options.limit)
22867 }
22868 } else {
22869 obj.add('', true);
22870 }
22871 }
22872 e.preventDefault();
22873 } else if (e.key == 'Enter') {
22874 if (! search || ! search.isOpened()) {
22875 var n = window.getSelection().anchorOffset;
22876 if (n > 1) {
22877 if (! limit()) {
22878 obj.add('', true);
22879 }
22880 }
22881 e.preventDefault();
22882 }
22883 } else if (e.key == 'Backspace') {
22884 // Back space - do not let last item to be removed
22885 if (el.children.length == 1 && window.getSelection().anchorOffset < 1) {
22886 e.preventDefault();
22887 }
22888 }
22889
22890 // Search events
22891 if (search) {
22892 search.keydown(e);
22893 }
22894
22895 // Verify if is empty
22896 isEmpty();
22897 }
22898
22899 /**
22900 * Processing event keyup on the element
22901 * @param e {object}
22902 */
22903 var tagsKeyUp = function(e) {
22904 if (e.which == 39) {
22905 // Right arrow
22906 var n = window.getSelection().anchorOffset;
22907 if (n > 1 && n == anchorOffset) {
22908 obj.add('', true);
22909 }
22910 } else if (e.which == 13 || e.which == 38 || e.which == 40) {
22911 e.preventDefault();
22912 } else {
22913 if (search) {
22914 search.keyup(e);
22915 }
22916 }
22917
22918 filter();
22919 }
22920
22921 /**
22922 * Processing event paste on the element
22923 * @param e {object}
22924 */
22925 var tagsPaste = function(e) {
22926 if (e.clipboardData || e.originalEvent.clipboardData) {
22927 var text = (e.originalEvent || e).clipboardData.getData('text/plain');
22928 } else if (window.clipboardData) {
22929 var text = window.clipboardData.getData('Text');
22930 }
22931
22932 var data = extractTags(text);
22933
22934 if (typeof(obj.options.onbeforepaste) == 'function') {
22935 var ret = obj.options.onbeforepaste(el, obj, data);
22936 if (ret === false) {
22937 e.preventDefault();
22938 return false;
22939 } else {
22940 if (ret) {
22941 data = ret;
22942 }
22943 }
22944 }
22945
22946 if (data.length > 1) {
22947 obj.add(data, true);
22948 e.preventDefault();
22949 } else if (data[0]) {
22950 document.execCommand('insertText', false, data[0])
22951 e.preventDefault();
22952 }
22953 }
22954
22955 /**
22956 * Processing event mouseup on the element
22957 * @param e {object}
22958 */
22959 var tagsMouseUp = function(e) {
22960 if (e.target.parentNode && e.target.parentNode.classList.contains('jtags')) {
22961 if (e.target.classList.contains('jtags_label') || e.target.classList.contains('jtags_error')) {
22962 var rect = e.target.getBoundingClientRect();
22963 if (rect.width - (e.clientX - rect.left) < 16) {
22964 obj.remove(e.target);
22965 }
22966 }
22967 }
22968
22969 // Set focus in the last item
22970 if (e.target == el) {
22971 setFocus();
22972 }
22973 }
22974
22975 var tagsFocus = function() {
22976 if (! el.classList.contains('jtags-focus')) {
22977 if (! el.children.length || obj.getValue(el.children.length - 1)) {
22978 if (! limit()) {
22979 createElement('');
22980 }
22981 }
22982
22983 if (typeof(obj.options.onfocus) == 'function') {
22984 obj.options.onfocus(el, obj, obj.getValue());
22985 }
22986
22987 el.classList.add('jtags-focus');
22988 }
22989 }
22990
22991 var tagsBlur = function() {
22992 if (el.classList.contains('jtags-focus')) {
22993 if (search) {
22994 search.close();
22995 }
22996
22997 for (var i = 0; i < el.children.length - 1; i++) {
22998 // Create label design
22999 if (! obj.getValue(i)) {
23000 el.removeChild(el.children[i]);
23001 }
23002 }
23003
23004 change();
23005
23006 el.classList.remove('jtags-focus');
23007
23008 if (typeof(obj.options.onblur) == 'function') {
23009 obj.options.onblur(el, obj, obj.getValue());
23010 }
23011 }
23012 }
23013
23014 var init = function() {
23015 // Bind events
23016 if ('touchend' in document.documentElement === true) {
23017 el.addEventListener('touchend', tagsMouseUp);
23018 } else {
23019 el.addEventListener('mouseup', tagsMouseUp);
23020 }
23021
23022 el.addEventListener('keydown', tagsKeyDown);
23023 el.addEventListener('keyup', tagsKeyUp);
23024 el.addEventListener('paste', tagsPaste);
23025 el.addEventListener('focus', tagsFocus);
23026 el.addEventListener('blur', tagsBlur);
23027
23028 // Editable
23029 el.setAttribute('contenteditable', true);
23030
23031 // Prepare container
23032 el.classList.add('jtags');
23033
23034 // Initial options
23035 obj.setOptions(options);
23036
23037 if (typeof(obj.options.onload) == 'function') {
23038 obj.options.onload(el, obj);
23039 }
23040
23041 // Change methods
23042 el.change = obj.setValue;
23043
23044 // Global generic value handler
23045 el.val = function(val) {
23046 if (val === undefined) {
23047 return obj.getValue();
23048 } else {
23049 obj.setValue(val);
23050 }
23051 }
23052
23053 el.tags = obj;
23054 }
23055
23056 init();
23057
23058 return obj;
23059}
23060;// CONCATENATED MODULE: ./src/plugins/upload.js
23061
23062
23063
23064
23065
23066function Upload(el, options) {
23067 var obj = {};
23068 obj.options = {};
23069
23070 // Default configuration
23071 var defaults = {
23072 type: 'image',
23073 extension: '*',
23074 input: false,
23075 minWidth: false,
23076 maxWidth: null,
23077 maxHeight: null,
23078 maxJpegSizeBytes: null, // For example, 350Kb would be 350000
23079 onchange: null,
23080 multiple: false,
23081 remoteParser: null,
23082 };
23083
23084 // Loop through our object
23085 for (var property in defaults) {
23086 if (options && options.hasOwnProperty(property)) {
23087 obj.options[property] = options[property];
23088 } else {
23089 obj.options[property] = defaults[property];
23090 }
23091 }
23092
23093 // Multiple
23094 if (obj.options.multiple == true) {
23095 el.setAttribute('data-multiple', true);
23096 }
23097
23098 // Container
23099 el.content = [];
23100
23101 // Upload icon
23102 el.classList.add('jupload');
23103
23104 if (obj.options.input == true) {
23105 el.classList.add('input');
23106 }
23107
23108 obj.add = function(data) {
23109 // Reset container for single files
23110 if (obj.options.multiple == false) {
23111 el.content = [];
23112 el.innerText = '';
23113 }
23114
23115 // Append to the element
23116 if (obj.options.type == 'image') {
23117 var img = document.createElement('img');
23118 img.setAttribute('src', data.file);
23119 img.setAttribute('tabindex', -1);
23120 if (! el.getAttribute('name')) {
23121 img.className = 'jfile';
23122 img.content = data;
23123 }
23124 el.appendChild(img);
23125 } else {
23126 if (data.name) {
23127 var name = data.name;
23128 } else {
23129 var name = data.file;
23130 }
23131 var div = document.createElement('div');
23132 div.innerText = name || obj.options.type;
23133 div.classList.add('jupload-item');
23134 div.setAttribute('tabindex', -1);
23135 el.appendChild(div);
23136 }
23137
23138 if (data.content) {
23139 data.file = helpers.guid();
23140 }
23141
23142 // Push content
23143 el.content.push(data);
23144
23145 // Onchange
23146 if (typeof(obj.options.onchange) == 'function') {
23147 obj.options.onchange(el, data);
23148 }
23149 }
23150
23151 obj.addFromFile = function(file) {
23152 var type = file.type.split('/');
23153 if (type[0] == obj.options.type) {
23154 var readFile = new FileReader();
23155 readFile.addEventListener("load", function (v) {
23156 var data = {
23157 file: v.srcElement.result,
23158 extension: file.name.substr(file.name.lastIndexOf('.') + 1),
23159 name: file.name,
23160 size: file.size,
23161 lastmodified: file.lastModified,
23162 content: v.srcElement.result,
23163 }
23164
23165 obj.add(data);
23166 });
23167
23168 readFile.readAsDataURL(file);
23169 } else {
23170 alert(dictionary.translate('This extension is not allowed'));
23171 }
23172 }
23173
23174 obj.addFromUrl = function(src) {
23175 if (src.substr(0,4) != 'data' && ! obj.options.remoteParser) {
23176 console.error('remoteParser not defined in your initialization');
23177 } else {
23178 // This is to process cross domain images
23179 if (src.substr(0,4) == 'data') {
23180 var extension = src.split(';')
23181 extension = extension[0].split('/');
23182 var type = extension[0].replace('data:','');
23183 if (type == obj.options.type) {
23184 var data = {
23185 file: src,
23186 name: '',
23187 extension: extension[1],
23188 content: src,
23189 }
23190 obj.add(data);
23191 } else {
23192 alert(obj.options.text.extensionNotAllowed);
23193 }
23194 } else {
23195 var extension = src.substr(src.lastIndexOf('.') + 1);
23196 // Work for cross browsers
23197 src = obj.options.remoteParser + src;
23198 // Get remove content
23199 ajax({
23200 url: src,
23201 type: 'GET',
23202 dataType: 'blob',
23203 success: function(data) {
23204 //add(extension[0].replace('data:',''), data);
23205 }
23206 })
23207 }
23208 }
23209 }
23210
23211 var getDataURL = function(canvas, type) {
23212 var compression = 0.92;
23213 var lastContentLength = null;
23214 var content = canvas.toDataURL(type, compression);
23215 while (obj.options.maxJpegSizeBytes && type === 'image/jpeg' &&
23216 content.length > obj.options.maxJpegSizeBytes && content.length !== lastContentLength) {
23217 // Apply the compression
23218 compression *= 0.9;
23219 lastContentLength = content.length;
23220 content = canvas.toDataURL(type, compression);
23221 }
23222 return content;
23223 }
23224
23225 var mime = obj.options.type + '/' + obj.options.extension;
23226 var input = document.createElement('input');
23227 input.type = 'file';
23228 input.setAttribute('accept', mime);
23229 input.onchange = function() {
23230 for (var i = 0; i < this.files.length; i++) {
23231 obj.addFromFile(this.files[i]);
23232 }
23233 }
23234
23235 // Allow multiple files
23236 if (obj.options.multiple == true) {
23237 input.setAttribute('multiple', true);
23238 }
23239
23240 var current = null;
23241
23242 el.addEventListener("click", function(e) {
23243 current = null;
23244 if (! el.children.length || e.target === el) {
23245 helpers.click(input);
23246 } else {
23247 if (e.target.parentNode == el) {
23248 current = e.target;
23249 }
23250 }
23251 });
23252
23253 el.addEventListener("dblclick", function(e) {
23254 helpers.click(input);
23255 });
23256
23257 el.addEventListener('dragenter', function(e) {
23258 el.style.border = '1px dashed #000';
23259 });
23260
23261 el.addEventListener('dragleave', function(e) {
23262 el.style.border = '1px solid #eee';
23263 });
23264
23265 el.addEventListener('dragstop', function(e) {
23266 el.style.border = '1px solid #eee';
23267 });
23268
23269 el.addEventListener('dragover', function(e) {
23270 e.preventDefault();
23271 });
23272
23273 el.addEventListener('keydown', function(e) {
23274 if (current && e.which == 46) {
23275 var index = Array.prototype.indexOf.call(el.children, current);
23276 if (index >= 0) {
23277 el.content.splice(index, 1);
23278 current.remove();
23279 current = null;
23280 }
23281 }
23282 });
23283
23284 el.addEventListener('drop', function(e) {
23285 e.preventDefault();
23286 e.stopPropagation();
23287
23288 var html = (e.originalEvent || e).dataTransfer.getData('text/html');
23289 var file = (e.originalEvent || e).dataTransfer.files;
23290
23291 if (file.length) {
23292 for (var i = 0; i < e.dataTransfer.files.length; i++) {
23293 obj.addFromFile(e.dataTransfer.files[i]);
23294 }
23295 } else if (html) {
23296 if (obj.options.multiple == false) {
23297 el.innerText = '';
23298 }
23299
23300 // Create temp element
23301 let img = [];
23302 utils_filter(html, img);
23303 if (img.length) {
23304 for (var i = 0; i < img.length; i++) {
23305 obj.addFromUrl(img[i]);
23306 }
23307 }
23308 }
23309
23310 el.style.border = '1px solid #eee';
23311
23312 return false;
23313 });
23314
23315 el.val = function(val) {
23316 if (val === undefined) {
23317 return el.content && el.content.length ? el.content : null;
23318 } else {
23319 // Reset
23320 el.innerText = '';
23321 el.content = [];
23322
23323 if (val) {
23324 if (Array.isArray(val)) {
23325 for (var i = 0; i < val.length; i++) {
23326 if (typeof(val[i]) == 'string') {
23327 obj.add({ file: val[i] });
23328 } else {
23329 obj.add(val[i]);
23330 }
23331 }
23332 } else if (typeof(val) == 'string') {
23333 obj.add({ file: val });
23334 }
23335 }
23336 }
23337 }
23338
23339 el.upload = el.image = obj;
23340
23341 return obj;
23342}
23343
23344// EXTERNAL MODULE: ./packages/sha512/sha512.js
23345var sha512 = __webpack_require__(195);
23346var sha512_default = /*#__PURE__*/__webpack_require__.n(sha512);
23347// EXTERNAL MODULE: ./node_modules/@lemonadejs/calendar/dist/index.js
23348var calendar_dist = __webpack_require__(763);
23349// EXTERNAL MODULE: ./node_modules/@lemonadejs/color/dist/index.js
23350var color_dist = __webpack_require__(541);
23351// EXTERNAL MODULE: ./node_modules/@lemonadejs/contextmenu/dist/index.js
23352var contextmenu_dist = __webpack_require__(238);
23353// EXTERNAL MODULE: ./node_modules/@lemonadejs/dropdown/dist/index.js
23354var dropdown_dist = __webpack_require__(692);
23355// EXTERNAL MODULE: ./node_modules/@lemonadejs/modal/dist/index.js
23356var modal_dist = __webpack_require__(72);
23357// EXTERNAL MODULE: ./node_modules/@lemonadejs/switch/dist/index.js
23358var switch_dist = __webpack_require__(539);
23359// EXTERNAL MODULE: ./node_modules/@lemonadejs/tabs/dist/index.js
23360var tabs_dist = __webpack_require__(560);
23361// EXTERNAL MODULE: ./node_modules/@lemonadejs/topmenu/dist/index.js
23362var topmenu_dist = __webpack_require__(330);
23363// EXTERNAL MODULE: ./node_modules/@lemonadejs/rating/dist/index.js
23364var rating_dist = __webpack_require__(867);
23365;// CONCATENATED MODULE: ./src/jsuites.js
23366
23367
23368
23369
23370
23371
23372
23373
23374
23375
23376
23377
23378
23379
23380
23381
23382
23383
23384
23385
23386
23387
23388
23389
23390
23391
23392
23393
23394
23395
23396
23397
23398
23399
23400
23401
23402
23403
23404
23405
23406
23407
23408
23409
23410
23411
23412
23413
23414
23415
23416
23417
23418
23419
23420
23421
23422
23423
23424
23425
23426
23427
23428
23429
23430
23431
23432
23433
23434
23435
23436
23437
23438
23439
23440
23441var jSuites = {
23442 // Helpers
23443 ...dictionary,
23444 ...helpers,
23445 /** Current version */
23446 version: '6.3.1',
23447 /** Bind new extensions to Jsuites */
23448 setExtensions: function(o) {
23449 if (typeof(o) == 'object') {
23450 var k = Object.keys(o);
23451 for (var i = 0; i < k.length; i++) {
23452 jSuites[k[i]] = o[k[i]];
23453 }
23454 }
23455 },
23456 tracking: tracking,
23457 path: Path,
23458 sorting: Sorting,
23459 lazyLoading: LazyLoading,
23460 // Plugins
23461 ajax: ajax,
23462 animation: animation,
23463 calendar: calendar,
23464 color: Color,
23465 contextmenu: contextmenu,
23466 dropdown: dropdown,
23467 editor: editor,
23468 floating: floating,
23469 form: plugins_form,
23470 mask: mask,
23471 modal: modal,
23472 notification: notification,
23473 palette: palette,
23474 picker: Picker,
23475 progressbar: Progressbar,
23476 rating: Rating,
23477 search: Search,
23478 slider: Slider,
23479 tabs: Tabs,
23480 tags: Tags,
23481 toolbar: Toolbar,
23482 upload: Upload,
23483 validations: validations,
23484}
23485
23486// Legacy
23487jSuites.image = Upload;
23488jSuites.image.create = function(data) {
23489 var img = document.createElement('img');
23490 img.setAttribute('src', data.file);
23491 img.className = 'jfile';
23492 img.setAttribute('tabindex', -1);
23493 img.content = data;
23494
23495 return img;
23496}
23497
23498jSuites.tracker = plugins_form;
23499jSuites.loading = animation.loading;
23500jSuites.sha512 = (sha512_default());
23501
23502
23503/** Core events */
23504const Events = function() {
23505
23506 if (typeof(window['jSuitesStateControl']) === 'undefined') {
23507 window['jSuitesStateControl'] = [];
23508 } else {
23509 // Do nothing
23510 return;
23511 }
23512
23513 const find = function(DOMElement, component) {
23514 if (DOMElement[component.type] && DOMElement[component.type] == component) {
23515 return true;
23516 }
23517 if (DOMElement.component && DOMElement.component == component) {
23518 return true;
23519 }
23520 if (DOMElement.parentNode) {
23521 return find(DOMElement.parentNode, component);
23522 }
23523 return false;
23524 }
23525
23526 const isOpened = function(e) {
23527 let state = window['jSuitesStateControl'];
23528 if (state && state.length > 0) {
23529 for (let i = 0; i < state.length; i++) {
23530 if (state[i] && ! find(e, state[i])) {
23531 state[i].close();
23532 }
23533 }
23534 }
23535 }
23536
23537 // Width of the border
23538 let cornerSize = 15;
23539
23540 // Current element
23541 let element = null;
23542
23543 // Controllers
23544 let editorAction = false;
23545
23546 // Event state
23547 let state = {
23548 x: null,
23549 y: null,
23550 }
23551
23552 // Tooltip element
23553 let tooltip = document.createElement('div')
23554 tooltip.classList.add('jtooltip');
23555
23556 const isWebcomponent = function(e) {
23557 return e && (e.shadowRoot || (e.tagName && e.tagName.includes('-')));
23558 }
23559
23560 const getElement = function(e) {
23561 let d;
23562 let element;
23563 // Which component I am clicking
23564 let path = e.path || (e.composedPath && e.composedPath());
23565
23566 // If path available get the first element in the chain
23567 if (path) {
23568 element = path[0];
23569 // Adjustment sales force
23570 if (element && isWebcomponent(element) && ! element.shadowRoot && e.toElement) {
23571 element = e.toElement;
23572 }
23573 } else {
23574 // Try to guess using the coordinates
23575 if (e.target && isWebcomponent(e.target)) {
23576 d = e.target.shadowRoot;
23577 } else {
23578 d = document;
23579 }
23580 // Get the first target element
23581 element = d.elementFromPoint(x, y);
23582 }
23583 return element;
23584 }
23585
23586 // Events
23587 const mouseDown = function(e) {
23588 // Verify current components tracking
23589 if (e.changedTouches && e.changedTouches[0]) {
23590 var x = e.changedTouches[0].clientX;
23591 var y = e.changedTouches[0].clientY;
23592 } else {
23593 var x = e.clientX;
23594 var y = e.clientY;
23595 }
23596
23597 let element = getElement(e);
23598 // Editable
23599 let editable = element && element.tagName === 'DIV' && element.getAttribute('contentEditable');
23600 // Check if this is the floating
23601 let item = jSuites.findElement(element, 'jpanel');
23602 // Jfloating found
23603 if (item && ! item.classList.contains("readonly") && ! editable) {
23604 // Keep the tracking information
23605 let rect = item.getBoundingClientRect();
23606 let angle = 0;
23607 if (item.style.rotate) {
23608 // Extract the angle value from the match and convert it to a number
23609 angle = parseFloat(item.style.rotate);
23610 }
23611 let action = 'move';
23612 if (element.getAttribute('data-action')) {
23613 action = element.getAttribute('data-action');
23614 } else {
23615 if (item.style.cursor) {
23616 action = 'resize';
23617 } else {
23618 item.style.cursor = 'move';
23619 }
23620 }
23621
23622 // Action
23623 editorAction = {
23624 action: action,
23625 a: angle,
23626 e: item,
23627 x: x,
23628 y: y,
23629 l: rect.left,
23630 t: rect.top,
23631 b: rect.bottom,
23632 r: rect.right,
23633 w: rect.width,
23634 h: rect.height,
23635 d: item.style.cursor,
23636 actioned: false,
23637 }
23638 // Make sure width and height styling is OK
23639 if (! item.style.width) {
23640 item.style.width = rect.width + 'px';
23641 }
23642 if (! item.style.height) {
23643 item.style.height = rect.height + 'px';
23644 }
23645 } else {
23646 // No floating action found
23647 editorAction = false;
23648 }
23649
23650 isOpened(element);
23651
23652 focus(e);
23653 }
23654
23655 const calculateAngle = function(x1, y1, x2, y2, x3, y3) {
23656 // Calculate dx and dy for the first line
23657 const dx1 = x2 - x1;
23658 const dy1 = y2 - y1;
23659 // Calculate dx and dy for the second line
23660 const dx2 = x3 - x1;
23661 const dy2 = y3 - y1;
23662 // Calculate the angle for the first line
23663 let angle1 = Math.atan2(dy1, dx1);
23664 // Calculate the angle for the second line
23665 let angle2 = Math.atan2(dy2, dx2);
23666 // Calculate the angle difference in radians
23667 let angleDifference = angle2 - angle1;
23668 // Convert the angle difference to degrees
23669 angleDifference = angleDifference * (180 / Math.PI);
23670 // Normalize the angle difference to be within [0, 360) degrees
23671 if (angleDifference < 0) {
23672 angleDifference += 360;
23673 }
23674 return angleDifference;
23675 }
23676
23677 const mouseUp = function(e) {
23678 if (editorAction && editorAction.e) {
23679 if (typeof(editorAction.e.refresh) == 'function' && state.actioned) {
23680 editorAction.e.refresh();
23681 }
23682 editorAction.e.style.cursor = '';
23683 }
23684
23685 // Reset
23686 state = {
23687 x: null,
23688 y: null,
23689 }
23690
23691 editorAction = false;
23692 }
23693
23694 const mouseMove = function(e) {
23695 if (editorAction) {
23696 let x = e.clientX || e.pageX;
23697 let y = e.clientY || e.pageY;
23698
23699 if (state.x == null && state.y == null) {
23700 state.x = x;
23701 state.y = y;
23702 }
23703
23704 // Action on going
23705 if (editorAction.action === 'move') {
23706 var dx = x - state.x;
23707 var dy = y - state.y;
23708 var top = editorAction.e.offsetTop + dy;
23709 var left = editorAction.e.offsetLeft + dx;
23710
23711 // Update position
23712 editorAction.e.style.top = top + 'px';
23713 editorAction.e.style.left = left + 'px';
23714
23715 // Update element
23716 if (typeof (editorAction.e.refresh) == 'function') {
23717 state.actioned = true;
23718 editorAction.e.refresh('position', top, left);
23719 }
23720 } else if (editorAction.action === 'rotate') {
23721 let ox = editorAction.l+editorAction.w/2;
23722 let oy = editorAction.t+editorAction.h/2;
23723 let angle = calculateAngle(ox, oy, editorAction.x, editorAction.y, x, y);
23724 angle = angle + editorAction.a % 360;
23725 angle = Math.round(angle / 2) * 2;
23726 editorAction.e.style.rotate = `${angle}deg`;
23727 // Update element
23728 if (typeof (editorAction.e.refresh) == 'function') {
23729 state.actioned = true;
23730 editorAction.e.refresh('rotate', angle);
23731 }
23732 } else if (editorAction.action === 'resize') {
23733 let top = null;
23734 let left = null;
23735 let width = null;
23736 let height = null;
23737
23738 if (editorAction.d == 'e-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'se-resize') {
23739 width = editorAction.e.offsetWidth + (x - state.x);
23740
23741 if (e.shiftKey) {
23742 height = editorAction.e.offsetHeight + (x - state.x) * (editorAction.e.offsetHeight / editorAction.e.offsetWidth);
23743 }
23744 } else if (editorAction.d === 'w-resize' || editorAction.d == 'nw-resize'|| editorAction.d == 'sw-resize') {
23745 left = editorAction.e.offsetLeft + (x - state.x);
23746 width = editorAction.e.offsetLeft + editorAction.e.offsetWidth - left;
23747
23748 if (e.shiftKey) {
23749 height = editorAction.e.offsetHeight - (x - state.x) * (editorAction.e.offsetHeight / editorAction.e.offsetWidth);
23750 }
23751 }
23752
23753 if (editorAction.d == 's-resize' || editorAction.d == 'se-resize' || editorAction.d == 'sw-resize') {
23754 if (! height) {
23755 height = editorAction.e.offsetHeight + (y - state.y);
23756 }
23757 } else if (editorAction.d === 'n-resize' || editorAction.d == 'ne-resize' || editorAction.d == 'nw-resize') {
23758 top = editorAction.e.offsetTop + (y - state.y);
23759 height = editorAction.e.offsetTop + editorAction.e.offsetHeight - top;
23760 }
23761
23762 if (top) {
23763 editorAction.e.style.top = top + 'px';
23764 }
23765 if (left) {
23766 editorAction.e.style.left = left + 'px';
23767 }
23768 if (width) {
23769 editorAction.e.style.width = width + 'px';
23770 }
23771 if (height) {
23772 editorAction.e.style.height = height + 'px';
23773 }
23774
23775 // Update element
23776 if (typeof(editorAction.e.refresh) == 'function') {
23777 state.actioned = true;
23778 editorAction.e.refresh('dimensions', width, height);
23779 }
23780 }
23781
23782 state.x = x;
23783 state.y = y;
23784 } else {
23785 let element = getElement(e);
23786 // Resize action
23787 let item = jSuites.findElement(element, 'jpanel');
23788 // Found eligible component
23789 if (item) {
23790 // Resizing action
23791 let controls = item.classList.contains('jpanel-controls');
23792 if (controls) {
23793 let position = element.getAttribute('data-position');
23794 if (position) {
23795 item.style.cursor = position;
23796 } else {
23797 item.style.cursor = '';
23798 }
23799 } else if (item.getAttribute('tabindex')) {
23800 let rect = item.getBoundingClientRect();
23801 //console.log(e.clientY - rect.top, rect.width - (e.clientX - rect.left), cornerSize)
23802 if (e.clientY - rect.top < cornerSize) {
23803 if (rect.width - (e.clientX - rect.left) < cornerSize) {
23804 item.style.cursor = 'ne-resize';
23805 } else if (e.clientX - rect.left < cornerSize) {
23806 item.style.cursor = 'nw-resize';
23807 } else {
23808 item.style.cursor = 'n-resize';
23809 }
23810 } else if (rect.height - (e.clientY - rect.top) < cornerSize) {
23811 if (rect.width - (e.clientX - rect.left) < cornerSize) {
23812 item.style.cursor = 'se-resize';
23813 } else if (e.clientX - rect.left < cornerSize) {
23814 item.style.cursor = 'sw-resize';
23815 } else {
23816 item.style.cursor = 's-resize';
23817 }
23818 } else if (rect.width - (e.clientX - rect.left) < cornerSize) {
23819 item.style.cursor = 'e-resize';
23820 } else if (e.clientX - rect.left < cornerSize) {
23821 item.style.cursor = 'w-resize';
23822 } else {
23823 item.style.cursor = '';
23824 }
23825 }
23826 }
23827 }
23828 }
23829
23830 let position = ['n','ne','e','se','s','sw','w','nw','rotate'];
23831 position.forEach(function(v, k) {
23832 position[k] = document.createElement('div');
23833 position[k].classList.add('jpanel-action');
23834 if (v === 'rotate') {
23835 position[k].setAttribute('data-action', 'rotate');
23836 } else {
23837 position[k].setAttribute('data-action', 'resize');
23838 position[k].setAttribute('data-position', v + '-resize');
23839 }
23840 });
23841
23842 let currentElement;
23843
23844 const focus = function(e) {
23845 let element = getElement(e);
23846 // Check if this is the floating
23847 let item = jSuites.findElement(element, 'jpanel');
23848 if (item && ! item.classList.contains("readonly") && item.classList.contains('jpanel-controls')) {
23849 item.append(...position);
23850
23851 if (! item.classList.contains('jpanel-rotate')) {
23852 position[position.length-1].remove();
23853 }
23854
23855 currentElement = item;
23856 } else {
23857 blur(e);
23858 }
23859 }
23860
23861 const blur = function(e) {
23862 if (currentElement) {
23863 position.forEach(function(v) {
23864 v.remove();
23865 });
23866 currentElement = null;
23867 }
23868 }
23869
23870 const mouseOver = function(e) {
23871 let element = getElement(e);
23872 var message = element.getAttribute('data-tooltip');
23873 if (message) {
23874 // Instructions
23875 tooltip.innerText = message;
23876
23877 // Position
23878 if (e.changedTouches && e.changedTouches[0]) {
23879 var x = e.changedTouches[0].clientX;
23880 var y = e.changedTouches[0].clientY;
23881 } else {
23882 var x = e.clientX;
23883 var y = e.clientY;
23884 }
23885
23886 tooltip.style.top = y + 'px';
23887 tooltip.style.left = x + 'px';
23888 document.body.appendChild(tooltip);
23889 } else if (tooltip.innerText) {
23890 tooltip.innerText = '';
23891 document.body.removeChild(tooltip);
23892 }
23893 }
23894
23895 const contextMenu = function(e) {
23896 var item = document.activeElement;
23897 if (item && typeof(item.contextmenu) == 'function') {
23898 // Create edition
23899 item.contextmenu(e);
23900
23901 e.preventDefault();
23902 e.stopImmediatePropagation();
23903 } else {
23904 // Search for possible context menus
23905 item = jSuites.findElement(e.target, function(o) {
23906 return o.tagName && o.getAttribute('aria-contextmenu-id');
23907 });
23908
23909 if (item) {
23910 var o = document.querySelector('#' + item);
23911 if (! o) {
23912 console.error('JSUITES: contextmenu id not found: ' + item);
23913 } else {
23914 o.contextmenu.open(e);
23915 e.preventDefault();
23916 e.stopImmediatePropagation();
23917 }
23918 }
23919 }
23920 }
23921
23922 const keyDown = function(e) {
23923 let item = document.activeElement;
23924 if (item) {
23925 if (e.key === "Delete" && typeof(item.delete) == 'function') {
23926 item.delete();
23927 e.preventDefault();
23928 e.stopImmediatePropagation();
23929 }
23930 }
23931
23932 let state = window['jSuitesStateControl'];
23933 if (state && state.length > 0) {
23934 item = state[state.length - 1];
23935 if (item) {
23936 if (e.key === "Escape" && typeof(item.isOpened) == 'function' && typeof(item.close) == 'function') {
23937 if (item.isOpened()) {
23938 item.close();
23939 e.preventDefault();
23940 e.stopImmediatePropagation();
23941 }
23942 }
23943 }
23944 }
23945 }
23946
23947 const input = function(e) {
23948 if (e.target.getAttribute('data-mask') || e.target.mask) {
23949 jSuites.mask.oninput(e);
23950 }
23951 }
23952
23953 document.addEventListener('focusin', focus);
23954 document.addEventListener('mouseup', mouseUp);
23955 document.addEventListener("mousedown", mouseDown);
23956 document.addEventListener('mousemove', mouseMove);
23957 document.addEventListener('mouseover', mouseOver);
23958 document.addEventListener('keydown', keyDown);
23959 document.addEventListener('contextmenu', contextMenu);
23960 document.addEventListener('input', input);
23961}
23962
23963if (typeof(document) !== "undefined") {
23964 Events();
23965}
23966
23967/* harmony default export */ var jsuites = (jSuites);
23968}();
23969jSuites = __webpack_exports__["default"];
23970/******/ })()
23971;
23972
23973 return jSuites;
23974})));