pinokiod 2.15.80 → 2.15.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1541 +0,0 @@
1
- <html>
2
- <head>
3
- <title><%=config.title%></title>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
6
- <link href="/css/fontawesome.min.css" rel="stylesheet">
7
- <link href="/css/solid.min.css" rel="stylesheet">
8
- <link href="/css/regular.min.css" rel="stylesheet">
9
- <link href="/css/brands.min.css" rel="stylesheet">
10
- <link href="/markdown.css" rel="stylesheet"/>
11
- <link href="/noty.css" rel="stylesheet"/>
12
- <link href="/style.css" rel="stylesheet"/>
13
- <script src="/hotkeys.min.js"></script>
14
- <script src="/sweetalert2.js"></script>
15
- <script src="/nav.js"></script>
16
- <script src="/opener.js"></script>
17
- <script src="/report.js"></script>
18
- <script src="/normalize.js"></script>
19
- <script src="/Socket.js"></script>
20
- <script src="/noty.js"></script>
21
- <script src="/notyq.js"></script>
22
- <% if (agent === "electron") { %>
23
- <link href="/electron.css" rel="stylesheet"/>
24
- <% } %>
25
- <style>
26
- #menu {
27
- display: flex;
28
- }
29
- #menu i {
30
- display: block;
31
- }
32
- #menu img {
33
- display: none;
34
- height: 30px;
35
- object-fit: contain;
36
- /*
37
- border-radius: 20px
38
- */
39
- }
40
- #menu.margin {
41
- padding: 5px;
42
- }
43
- #menu.margin i {
44
- display: none;
45
- }
46
- #menu.margin img {
47
- display: block;
48
- }
49
- html, body {
50
- width: 100%;
51
- height: 100%;
52
- margin: 0;
53
- }
54
- body {
55
- display: flex;
56
- }
57
- .menu {
58
- overflow: auto;
59
- }
60
- body.dark .m {
61
- border-top: 1px solid rgba(255,255,255,0.04);
62
- }
63
- .m {
64
- border-top: 1px solid rgba(0,0,0,0.04);
65
- }
66
- .container {
67
- position: relative;
68
- display: flex;
69
- flex-direction: column;
70
- flex-grow: 1;
71
- }
72
- body aside {
73
- /*
74
- background: var(--light-bg);
75
- */
76
- border-right: 1px solid rgba(0,0,0,0.04);
77
- height: 100%;
78
- }
79
- body.dark aside {
80
- background: var(--dark-bg);
81
- border-right: 1px solid rgba(255,255,255,0.04);
82
- }
83
- aside {
84
- display: flex;
85
- flex-direction: column;
86
- width: 200px;
87
- overflow: auto;
88
- box-sizing: border-box;
89
- flex-shrink: 0;
90
- }
91
- main {
92
- flex-grow: 1;
93
- min-height: 0;
94
- /*
95
- height: 100%;
96
- */
97
- }
98
- main iframe[name^=http] {
99
- background: white;
100
- }
101
- main iframe {
102
- width: 100%;
103
- height: 100%;
104
- border: none;
105
- }
106
- .header-item {
107
- /*
108
- display: block;
109
- */
110
- display: flex;
111
- font-size: 12px;
112
- text-decoration: none;
113
- align-items: center;
114
- border-radius: 0;
115
- cursor: pointer;
116
- }
117
- .header-item.selected {
118
- }
119
- .header-item .btn2 {
120
- margin: 0;
121
- border: none;
122
- padding: 5px;
123
- /*
124
- color: var(--light-color);
125
- */
126
- }
127
- body.dark .header-item .btn2 {
128
- /*
129
- color: var(--darkt-color);
130
- */
131
- }
132
- .bar .btn2 i {
133
- display: block;
134
- margin-right: 5px;
135
- }
136
- .header-item > * {
137
- display: block;
138
- }
139
- .header-item img {
140
- /*
141
- width: 60px;
142
- */
143
- height: 80px;
144
- width: 80px;
145
- border-radius: 10px;
146
- object-fit: contain;
147
- display: inline-block;
148
- /*
149
- border-radius: 30px;
150
- */
151
- }
152
- body.dark .header-item.btn {
153
- /*
154
- color: white;
155
- */
156
- color: var(--dark-color);
157
- }
158
- .header-item.btn {
159
- padding: 10px;
160
- background: none !important;
161
- color: var(--light-color);
162
- }
163
- .logo {
164
- font-size: 20px;
165
- padding: 20px;
166
- }
167
- body .logo {
168
- color: var(--light-color);
169
- }
170
- body.dark .logo {
171
- color: var(--dark-btn-color);
172
- /*
173
- color: white;
174
- */
175
- }
176
- body #new-window {
177
- color: var(--light-color);
178
- }
179
- body.dark #new-window {
180
- color: var(--dark-btn-color);
181
- /*
182
- color: white;
183
- */
184
- }
185
- .app-info {
186
- /*
187
- display: flex;
188
- */
189
- box-sizing: border-box;
190
- text-align: center;;
191
- font-weight: bold;
192
- align-items: center;
193
- padding: 20px 0px;
194
- }
195
- .app-info i {
196
- font-size: 60px;
197
- }
198
- .app-info > * {
199
- padding: 5px;
200
- color: var(--light-color);
201
- text-decoration: none;
202
- box-sizing: border-box;
203
- }
204
- body.dark .app-info > * {
205
- color: var(--dark-color);
206
- }
207
- .footer {
208
- /*
209
- display: flex;
210
- */
211
- display: grid;
212
- grid-template-columns: repeat(4, 1fr);
213
- }
214
- .footer > * {
215
- padding: 10px !important;
216
- display: block;
217
- box-sizing: border-box;
218
- font-size: 12px !important;
219
- text-align: center;
220
- }
221
- .footer i {
222
- margin: 0 !important;
223
- padding: 5px;
224
- }
225
- .footer a {
226
- font-size: 14px;
227
- }
228
- body .footer {
229
- border-bottom: 1px solid rgba(0,0,0,0.04);
230
- }
231
- body.dark .footer {
232
- border-bottom: 1px solid rgba(255,255,255,0.04);
233
- }
234
- body.dark .header-item.cursor {
235
- background: rgba(0,0,0, 0.2) !important;
236
- }
237
- .header-item.cursor {
238
- background: rgba(0,0,100, 0.03) !important;
239
- /*
240
- border-left: 5px solid gold;
241
- */
242
- }
243
- .frame-link {
244
- cursor: pointer;
245
- }
246
- body .frame-link.selected {
247
- /*
248
- border-right: 10px solid gold;
249
- */
250
- background: black !important;
251
- color: white;
252
- /*
253
- background: rgba(0,0,100,0.06) !important;
254
- */
255
- }
256
- .frame-link.selected .del {
257
- color: white;
258
- }
259
- body.dark .frame-link.selected {
260
- background: rgba(0,0,0,0.7) !important;
261
- }
262
- .frame-link .loader {
263
- /*
264
- padding: 5px;
265
- */
266
- }
267
- .loader .btn:hover {
268
- color: royalblue;
269
- border-color: royalblue;
270
- }
271
- .loader .btn {
272
- padding: 4px 8px;
273
- border: 1px solid rgba(255,255,255,0.3);
274
- }
275
- .frame-link .tab {
276
- flex-grow: 1;
277
- /*
278
- width: 100%;
279
- */
280
- word-break: break-word;
281
- /*
282
- margin-right: 10px;
283
- */
284
- }
285
- .frame-link .tab .flexible {
286
- min-width: 5px;
287
- }
288
- .frame-link .tab .display {
289
- word-break: break-word;
290
- }
291
- body.dark .grid-btns {
292
- border-top: 1px solid rgba(255,255,255,0.04);
293
- border-bottom: 1px solid rgba(255,255,255,0.04);
294
- }
295
- .grid-btns {
296
- border-top: 1px solid rgba(0,0,0,0.04);
297
- border-bottom: 1px solid rgba(0,0,0,0.04);
298
- display: grid;
299
- grid-template-columns: repeat(2, 1fr);
300
- grid-template-rows: repeat(2, 1fr);
301
- /*
302
- grid-template-columns: repeat(3, 1fr);
303
- grid-template-rows: repeat(1, 1fr);
304
- */
305
- box-sizing: border-box;
306
- }
307
- .grid-btns .btn2 {
308
- padding: 10px 10px;
309
- color: var(--light-color);
310
- border-radius: 0;
311
- cursor: pointer;
312
- font-size: 11px;
313
- }
314
- body.dark .grid-btns .btn2 {
315
- /*
316
- color: white;
317
- */
318
- color: var(--dark-btn-color);
319
- }
320
- .footer {
321
- width: 100%;
322
- }
323
- .tab {
324
- flex-grow: 1;
325
- display: flex;
326
- align-items: center;
327
- }
328
- .label i {
329
- margin-right: 10px;
330
- }
331
- .tab i {
332
- margin-right: 10px;
333
- }
334
- .temp-menu {
335
- /*
336
- border-top: 1px solid rgba(0,0,0,0.1);
337
- */
338
- }
339
- .temp-menu .del i {
340
- margin: 0;
341
- }
342
- #delete {
343
- color: brown;
344
- }
345
- body .footer {
346
- }
347
- body.dark nav {
348
- /*
349
- border-bottom: 1px solid rgba(255,255,255,0.04);
350
- */
351
- border-top: 1px solid rgba(255,255,255,0.04);
352
- }
353
- /*
354
- .container:hover nav {
355
- display: block;
356
- }
357
- */
358
- nav {
359
- /*
360
- overflow: hidden;
361
- max-height: 0;
362
- transition: max-height 0.4s ease-out;
363
- display: none;
364
- */
365
-
366
- background: white;
367
- /*
368
- position: absolute;
369
- bottom: 0;
370
- left: 0;
371
- right: 0;
372
- */
373
- /*
374
- padding: 5px;
375
- */
376
- padding: 0;
377
- cursor: grab !important;
378
- -webkit-app-region: drag !important;
379
- /*
380
- border-bottom: 1px solid rgba(0,0,0,0.04);
381
- */
382
- border-top: 1px solid rgba(0,0,0,0.04);
383
- box-sizing: border-box;
384
- }
385
- body.dark nav .btn2 {
386
- border-right: 1px solid rgba(255,255,255,0.04);
387
- }
388
- nav .btn2 {
389
- padding: 15px;
390
- font-size: 12px;
391
- /*
392
- width: 70px;
393
- */
394
- box-sizing: border-box;
395
- border-right: 1px solid rgba(0,0,0,0.04);
396
- border-radius: 0;
397
- text-transform: lowercase;
398
- flex-shrink: 0;
399
-
400
- display: flex;
401
- /*
402
- flex-direction: column;
403
- */
404
- justify-content: center;
405
- align-items: center;
406
- }
407
- nav .logo {
408
- font-size: 14px;
409
- padding: 10px;
410
- }
411
- body.dark #location {
412
- color: white;
413
- }
414
- #location {
415
- background: none;
416
- padding: 15px;
417
- font-size: 12px;
418
- font-family: verdana;
419
- box-sizing: border-box;
420
- flex-grow: 1;
421
- border: none;
422
- outline: none;
423
- }
424
- .bar {
425
- -webkit-app-region: no-drag !important;
426
- cursor: auto;
427
- display: flex;
428
- align-items: stretch;
429
- width: 100%;
430
- flex-wrap: wrap;
431
- }
432
- body.dark .header-item.cursor.header-top {
433
- background: none !important;
434
- }
435
- .header-item.cursor.header-top {
436
- background: none !important;
437
- }
438
- .header-item.header-top {
439
- display: block;
440
- }
441
- #new-tab:hover {
442
- background: rgba(0,0,0,0.06) !important;
443
- color: rgb(200,0,0) !important;
444
- }
445
-
446
- #new-tab {
447
- cursor: pointer !important;
448
- justify-content: center;
449
- /*
450
- border-top: 1px solid rgba(0,0,0,0.04);
451
- */
452
- }
453
-
454
- body.dark #new-tab {
455
- /*
456
- border-top: 1px solid rgba(255,255,255,0.04);
457
- */
458
- }
459
- .submenu {
460
- padding-left: 15px;
461
- box-sizing: border-box;
462
- }
463
- .loader-dialog {
464
- padding: 10px;
465
- }
466
- body.dark .loader-popup {
467
- background: rgba(0,0,0,0.2);
468
- color: whitesmoke;
469
- }
470
- .loader-popup {
471
- text-transform: uppercase;
472
- font-size: 12px;
473
- letter-spacing: 1px;
474
- padding: 20px;
475
- background: rgba(0,0,0,0.2);
476
- color: white;
477
- }
478
- body.dark .loader-container {
479
- background: rgba(255,255,255,0.3);
480
- }
481
- #menu-mobile {
482
- display: none;
483
- }
484
- .tabmenu .label {
485
- padding: 10px;
486
- border-bottom: 1px solid rgba(255,255,255,0.04);
487
- text-transform: uppercase;
488
- font-size: 12px;
489
- font-weight: bold;
490
- }
491
- .disk-usage {
492
- flex-grow: 1;
493
- text-align: right;
494
- font-weight: bold;
495
- }
496
- .disk-usage i {
497
- margin-right: 5px;
498
- font-size: 16px !important;
499
- }
500
- @media only screen and (max-width: 480px) {
501
- nav .btn2 {
502
- width: auto !important;
503
- min-width: 40px;
504
- border-right: none;
505
- flex-direction: column;
506
- }
507
- .app-info {
508
- display: flex;
509
- padding: 10px;
510
- }
511
- .app-info img {
512
- width: 60px;
513
- height: 60px;
514
- }
515
-
516
- .header-item {
517
- font-size: 16px;
518
- }
519
- aside.active {
520
- width: 100%;
521
- z-index: 10000000;
522
- }
523
- aside:not(.active) {
524
- display: none;
525
- }
526
- .container {
527
- display: none;
528
- }
529
- .container.active {
530
- display: block;
531
- position: absolute;
532
- z-index: 10000000;
533
- width: 100%;
534
- height: 100%;
535
- }
536
- /*
537
- .grid-btns {
538
- display: none;
539
- }
540
- */
541
- #menu {
542
- display: none;
543
- }
544
- #menu-mobile {
545
- display: flex;
546
- }
547
- }
548
- </style>
549
- </head>
550
- <body class='<%=theme%>' data-platform="<%=platform%>">
551
- <aside class='active'>
552
- <!--
553
- <div class='footer'>
554
- <button class='btn header-item' id='clone-tab'><i class='fa-regular fa-copy'></i></button>
555
- <a class='btn header-item' id='open-browser' target="_blank" href="" features="browser"><i class="fa-solid fa-square-arrow-up-right"></i></a>
556
- <button class='btn header-item' id='reload'><i class="fa-solid fa-rotate-right"></i></button>
557
- <div id='new-tab' class='btn header-item'><i class="fa-solid fa-plus"></i></div>
558
- </div>
559
- -->
560
- <div class='header-top header-item'>
561
- <div class='app-info'>
562
- <% if (config.icon) { %>
563
- <img src="<%=rawpath%>/<%=config.icon%>?raw=true"/>
564
- <% } else { %>
565
- <i class="fa-regular fa-circle-dot"></i>
566
- <% } %>
567
- <div><%=config.title%></div>
568
- </div>
569
- </div>
570
- <div class='m n system' data-type="n">
571
- <!--<a data-index="0" target="<%=src%>" href="<%=src%>" class='btn header-item frame-link'>-->
572
- <div id='delete' data-name="<%=name%>" class='btn header-item frame-link'>
573
- <div class='tab'><i class="fa-solid fa-trash-can"></i> Delete</div>
574
- </div>
575
- <a target="<%=src%>" href="<%=src%>" class='btn header-item frame-link' data-index="0">
576
- <div class='tab'><i class="fa-regular fa-folder-open"></i> Files <div class='disk-usage'></div></div>
577
- </a>
578
- <a target="/share/<%=name%>" href="/share/<%=name%>", class="btn header-item frame-link" data-index="1" data-mode="refresh">
579
- <div class='tab'><i class="fa-solid fa-wifi"></i> Share</div>
580
- </a>
581
- <a target="/env/api/<%=name%>" href="/env/api/<%=name%>", class="btn header-item frame-link" data-index="1" data-mode="refresh">
582
- <div class='tab'><i class="fa-solid fa-gear"></i> Configure</div>
583
- </a>
584
- </div>
585
- <div class='m h menu' data-type='h'>
586
- <% if (config.menu) { %>
587
- <%- include('./partials/menu', { menu: config.menu }) %>
588
- <% } %>
589
- </div>
590
- <div class='m s temp-menu' data-type='s'>
591
- <%tabs.forEach((tab, i) => { %>
592
- <a target="s<%=i%>" href="<%=tab%>" class="btn header-item frame-link" data-index="<%=i%>">
593
- <div class='tab'>
594
- <i class="fa-solid fa-link"></i><div class='display'><%=tab%></div><div class='flexible'></div><button class='btn2 del'><i class="fa-solid fa-xmark"></i></button>
595
- </div>
596
- </a>
597
- <%})%>
598
- </div>
599
- <div class='flexible'></div>
600
- <!--
601
- <div class='tabmenu'>
602
- <div id='new-tab' class='btn header-item'><div class='tab'><i class="fa-solid fa-plus"></i> New</div></div>
603
- <button class='btn header-item' id='clone-tab'><div class='tab'><i class='fa-regular fa-copy'></i> Clone</div></button>
604
- <a class='btn header-item' id='open-browser' target="_blank" href="" features="browser"><div class='tab'><i class="fa-solid fa-square-arrow-up-right"></i> Popout</div></a>
605
- <button class='btn header-item' id='reload'><div class='tab'><i class="fa-solid fa-rotate-right"></i> Refresh</div></button>
606
- </div>
607
- -->
608
- <div class='grid-btns'>
609
- <a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
610
- <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Debug</div></button>
611
- <a id='downloadlogs' download class='hidden btn2' href="/pinokio/logs.zip"><div><i class="fa-solid fa-download"></i></div><div>Download logs</div></a>
612
- <a class='btn2' href="/"><div><i class="fa-solid fa-house"></i></div><div>Home</div></a>
613
- <button class='btn2' id='new-window' title='open a new window'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
614
- </div>
615
- <!--
616
- <div class='grid-btns'>
617
- <a class='btn2' href="/?mode=explore" id='explore'><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
618
- <a class='btn2' id='report'><div><i class="fa-solid fa-bug"></i></div><div>Report Bug</div></a>
619
- <a class='btn2' href='https://discord.gg/TQdNwadtE4' target="_blank"><div><i class="fa-brands fa-discord"></i></div><div>Discord</div></a>
620
- <a class='btn2' href='https://twitter.com/cocktailpeanut' target="_blank"><div><i class="fa-brands fa-twitter"></i></div><div>Twitter</div></a>
621
- </div>
622
- -->
623
- </aside>
624
- <div class='container'>
625
- <nav>
626
- <div class='bar'>
627
- <button class='btn2' id='menu-mobile'><i class="fa-solid fa-bars"></i></button>
628
- <button class='btn2' id='menu'>
629
- <img src="<%=rawpath%>/<%=config.icon%>?raw=true"/>
630
- <i class="fa-solid fa-arrow-right-to-bracket fa-rotate-180"></i>
631
- </button>
632
- <% if (agent === "electron") { %>
633
- <button class='btn2' id='back'><i class="fa-solid fa-chevron-left"></i></button>
634
- <button class='btn2' id='forward'><i class="fa-solid fa-chevron-right"></i></button>
635
- <% } %>
636
- <button class='btn2' id='reload'><i class="fa-solid fa-rotate-right"></i> Refresh</button>
637
- <% if (agent === "electron") { %>
638
- <a class='btn2' id='open-browser' target="_blank" href="" features="browser"><i class="fa-solid fa-square-arrow-up-right"></i> Popout</a>
639
- <% } else { %>
640
- <a class='btn2' id='open-browser' target="_blank" href=""><i class="fa-solid fa-square-arrow-up-right"></i> Popout</a>
641
- <% } %>
642
- <button class='btn2' id='clone-tab'><i class='fa-regular fa-copy'></i> Clone</button>
643
- <div id='new-tab' class='btn2'><i class="fa-solid fa-plus"></i> Tab</div>
644
- <input type='url' id='location' readonly>
645
- </div>
646
- </nav>
647
- <main class='browserview'>
648
- <% if (false) { %>
649
- <% if (config.menu) { %>
650
- <% config.menu.forEach((item) => { %>
651
- <% if (item.btn && item.src) { %>
652
- <iframe name='<%=item.src%>' class='hidden'></iframe>
653
- <% } %>
654
- <% }) %>
655
- <% } %>
656
- <% } %>
657
- </main>
658
- </div>
659
- <script>
660
- let loaded = {}
661
- let cursorIndex = 0;
662
- const n = new N()
663
- const getTarget = (href) => {
664
- let u
665
- if (href.startsWith("http")) {
666
- return href
667
- } else if (href.startsWith("/")) {
668
- u = new URL("http://localhost" + href)
669
- u.search = ""
670
- return u.pathname
671
- } else {
672
- u = new URL("http://localhost/" + href)
673
- u.search = ""
674
- return u.pathname
675
- }
676
- }
677
- const subUrlOf = (s, f) => {
678
-
679
- let subsetUrl = (s.startsWith("http") ? s : "http://localhost" + s)
680
- let fullUrl = (f.startsWith("http") ? f: "http://localhost" + f)
681
-
682
- const subsetParsed = new URL(subsetUrl)
683
- const fullParsed = new URL(fullUrl)
684
-
685
- if (subsetParsed.pathname !== fullParsed.pathname) {
686
- return false;
687
- }
688
-
689
- // Check if all search parameters in the subset URL are present in the full URL
690
- for (const [key, val] of subsetParsed.searchParams) {
691
-
692
- if (!fullParsed.searchParams.has(key)) {
693
- return false
694
- }
695
- if (fullParsed.searchParams.get(key) !== val) {
696
- return false
697
- }
698
- }
699
-
700
- return true;
701
- }
702
- const renderCursor = () => {
703
- document.querySelectorAll(".selectable").forEach((el) => {
704
- el.classList.remove("cursor")
705
- })
706
- const target = document.querySelector(".selectable[data-index='" + cursorIndex + "']")
707
- target.classList.add("cursor")
708
- }
709
- const nav = (type) => {
710
- let targetFrame = document.querySelector("iframe:not(.hidden)")
711
- if (type === "back") {
712
- // targetFrame.contentWindow.history.back()
713
- targetFrame.contentWindow.postMessage({
714
- action: "back"
715
- }, "*")
716
- } else if (type === "forward") {
717
- // targetFrame.contentWindow.history.forward()
718
- targetFrame.contentWindow.postMessage({
719
- action: "forward"
720
- }, "*")
721
- }
722
-
723
-
724
-
725
- // if (location.hash && location.hash.length > 0) {
726
- //// let id = getTarget(location.hash.slice(1))
727
- //// let target = document.querySelector("aside [target='" + id + "']")
728
- // let id = location.hash.slice(1)
729
- // let type = id[0]
730
- // let index = id.slice(1)
731
- // let target = document.querySelector(`aside .${type} [data-index='${index}']`)
732
- // let targetFrame = document.querySelector(`iframe[name='${target.target}']`)
733
- // console.log({ target, targetFrame })
734
- // if (type === "back") {
735
- // targetFrame.contentWindow.history.back()
736
- // } else if (type === "forward") {
737
- // targetFrame.contentWindow.history.forward()
738
- // }
739
- // /*
740
- // targetFrame.contentWindow.postMessage({
741
- // action: type
742
- // }, "*")
743
- // */
744
- // }
745
- }
746
- const renderSelection = (e, force) => {
747
- // if the menu has a default item, or if the url specifies a selection
748
- let selection = document.querySelector("[data-default]")
749
- if (selection || location.hash && location.hash.length > 0) {
750
- let target
751
- if (location.hash && location.hash.length > 0) {
752
- // document.querySelector(".bar").classList.remove("hidden")
753
- //let id = getTarget(location.hash.slice(1))
754
- let id = location.hash.slice(1)
755
-
756
-
757
- let selector
758
- if (id.startsWith("@")) {
759
- //selector = `aside [target='${id.slice(1)}']`
760
- selector = `aside [target='${id}']`
761
- } else {
762
- let type = id[0]
763
- let index = id.slice(1)
764
- console.log({ type, index })
765
- selector = `aside .${type} [data-index='${index}']`
766
- }
767
-
768
-
769
- // select the selected link
770
- // document.querySelectorAll(".frame-link").forEach((el) => {
771
- // el.classList.remove("selected")
772
- // })
773
-
774
-
775
-
776
- // const target = document.querySelector(`[target='${id}']`)
777
-
778
-
779
- if (e) {
780
- // If the renderSelection is triggered by an event, look for the frame-link that's triggering the event
781
- if (e.target.classList.contains("frame-link")) {
782
- target = e.target
783
- } else {
784
- target = e.target.closest(".frame-link")
785
- }
786
- } else {
787
- // if not triggered by an event, look for the target from the location hash
788
- target = document.querySelector(selector)
789
- }
790
- } else {
791
- if (selection) {
792
- target = selection
793
- }
794
- }
795
-
796
-
797
- // if the target was found either through:
798
- // 1. looking for the frame-link that triggered the event
799
- // 2. or by looking at the location hash
800
- //
801
- // => select that tab and frame
802
-
803
- if (target) {
804
-
805
- // display the menu button at the top
806
- // maximize container
807
- // minimize aside
808
-
809
- document.querySelector(".container").classList.add("active")
810
- document.querySelector("aside").classList.remove("active")
811
- } else {
812
- document.querySelector(".container").classList.remove("active")
813
- document.querySelector("aside").classList.add("active")
814
- }
815
-
816
- if (target) {
817
-
818
-
819
- // Instantiate a frame with the selected target's href
820
- let url = target.href
821
- document.querySelector("#open-browser").href = url
822
- document.querySelector("#clone-tab").setAttribute("data-href", url)
823
- document.querySelector("#location").value = url
824
-
825
-
826
- // select the selected target element (tab)
827
- target.classList.add("selected")
828
-
829
- // hide all frames
830
- document.querySelectorAll("iframe").forEach((el) => {
831
- el.classList.add("hidden")
832
- })
833
-
834
-
835
-
836
- // Look for the frame
837
- // 1. if it's hard (".h")
838
- // look for the url that matches
839
- // 2. if it's soft (".s")
840
- // find using the name attribute
841
- let targetFrame;
842
- if (target.closest(".h")) {
843
- let hardFrames = document.querySelectorAll(".browserview iframe[name^='@']")
844
- let port = new URL(target.href).port || 80
845
- for(let frame of hardFrames) {
846
- console.log({ src: frame.src, href: target.href, target: target.target })
847
- // Types of links in the tab
848
- if (String(port) === "<%=port%>") {
849
- // 1. running from <%=port%> => find a frame whose base URL matches the tab's base URL
850
- // Pinokio links
851
- let targetPath = new URL(target.href).pathname
852
- let framePath = new URL(frame.src).pathname
853
- if (targetPath === framePath) {
854
- let beforeName = frame.name
855
- frame.name = target.target
856
- console.log("SET FRAME", { before: beforeName, after: frame.name, target: target.target })
857
- targetFrame = frame
858
- break
859
- }
860
- } else {
861
- // 2. rest => find the frame whose src exactly matches the tab's url
862
- if (target.href === frame.src) {
863
- frame.name = target.target
864
- targetFrame = frame
865
- break
866
- }
867
- }
868
- // find the frame whose path matches
869
- }
870
- } else if (target.closest(".s")) {
871
- targetFrame = document.querySelector(`iframe[name='${target.target}']`)
872
- } else if (target.closest(".n")) {
873
- targetFrame = document.querySelector(`iframe[name='${target.target}']`)
874
- }
875
-
876
- /*
877
- // Load the link in the frame
878
-
879
- 1. if the frame was found:
880
- - if "refresh": true => refresh
881
- - otherwise,
882
- - if the target frame has been already loaded, don't do anything
883
- - frame: start.json?mode=abc, link: start.json?mode=abc => don't touch
884
- - link === frame
885
- - frame: start.json?mode=abc, link: start.json?mode=def => should load
886
- - link !== frame && !frame.includes(link)
887
- - frame: start.json?mode=abc, link: start.json => don't touch
888
- - link !== frame && frame.includes(link)
889
-
890
-
891
-
892
- if the link is different
893
-
894
- - if the target frame has not been loaded, refresh
895
- 2. if the frame was NOT found => create one
896
-
897
- */
898
-
899
- if (targetFrame) {
900
- targetFrame.classList.remove("hidden")
901
- let mode = target.getAttribute("data-mode")
902
- if (mode === "refresh") {
903
- targetFrame.src = target.href
904
- } else {
905
- if (e) {
906
- if (target.closest(".h")) {
907
- e.preventDefault()
908
- e.stopPropagation()
909
- let sub = subUrlOf(target.href, targetFrame.src)
910
- if (!sub) {
911
- targetFrame.src = target.href
912
- }
913
- //if (target.href === targetFrame.src) {
914
- // // same url. don't do anything
915
- // e.preventDefault()
916
- // e.stopPropagation()
917
- //} else {
918
- // if (targetFrame.src.includes(target.href)) {
919
- // // different url, but the frame's url contains the tab url => don't touch
920
- // e.preventDefault()
921
- // e.stopPropagation()
922
- // } else {
923
- // // different url, and the frame's url does not contain the tab url => change the src of the frame and load
924
- // targetFrame.src = target.href
925
- // e.preventDefault()
926
- // e.stopPropagation()
927
- // }
928
- //}
929
- } else if (target.closest(".s")) {
930
- // load unconditionally => .s doesn't change
931
- e.preventDefault()
932
- e.stopPropagation()
933
- } else if (target.closest(".n")) {
934
- // load unconditionally => .n doesn't change
935
- e.preventDefault()
936
- e.stopPropagation()
937
- }
938
- } else {
939
- if (force) {
940
- targetFrame.src = target.href
941
- }
942
- }
943
- targetFrame.contentWindow.postMessage({
944
- action: "foreground"
945
- }, "*")
946
- }
947
- } else {
948
- let frame = document.createElement("iframe")
949
- frame.name = target.target
950
- frame.src = target.href
951
- frame.setAttribute(
952
- "allow",
953
- "clipboard-read *; clipboard-write *; accelerometer *; ambient-light-sensor *; autoplay *; battery *; camera *; display-capture *; gamepad *; geolocation *; gyroscope *; hid *; identity-credentials-get *; microphone *; midi *; otp-credentials *; serial *;"
954
- )
955
- document.querySelector("main").appendChild(frame)
956
- loaded[target.target] = true
957
- }
958
-
959
- // if (targetFrame) {
960
- // targetFrame.classList.remove("hidden")
961
- //
962
- // // if the iframe already exists, do not
963
- // if (loaded[target.target]){
964
- //
965
- // // Force refresh option
966
- // //
967
- // // menu := [{
968
- // // text,
969
- // // icon,
970
- // // mode: "refresh" => refresh regardless of any condition
971
- // // }]
972
- // let mode = target.getAttribute("data-mode")
973
- // if (mode === "refresh") {
974
- // targetFrame.src = target.href
975
- // } else {
976
- // console.log("# 4")
977
- // if (e) {
978
- // // if triggered by a click event,
979
- // // 1. if it's a hard link (".h")
980
- // // - ignore if the pathname is the same
981
- // // - reload if
982
- // console.log("# 5", { src: targetFrame.src, href: target.href, target: target.target })
983
- // // triggered with a click
984
- // // do not reload iframe if the href and the src is the same
985
- // if (target.closest(".h")) {
986
- // // if (targetFrame.src.includes(target.target)) {
987
- // if (targetFrame.src.includes(target.href)) {
988
- // // if (targetFrame.src === target.href) {
989
- // e.preventDefault()
990
- // e.stopPropagation()
991
- // }
992
- // } else if (target.closest(".s")) {
993
- // e.preventDefault()
994
- // e.stopPropagation()
995
- // }
996
- // } else {
997
- // // if not triggered by event
998
- // // refresh ONLY if programmatically forced refresh
999
- // console.log("# 6")
1000
- // if (force) {
1001
- // console.log("# 7")
1002
- // targetFrame.src = target.href
1003
- // }
1004
- // }
1005
- // }
1006
- //
1007
- // } else {
1008
- // console.log("# 8")
1009
- // //targetFrame.contentWindow.addEventListener("load", () => {
1010
- // if (e) {
1011
- // console.log("# 9")
1012
- // // coming from a click => don't need to set the src
1013
- // } else {
1014
- // console.log("# 10")
1015
- // // load without click
1016
- // if (targetFrame.src !== target.href) {
1017
- // console.log("# 11")
1018
- // targetFrame.src = target.href
1019
- // }
1020
- // }
1021
- // loaded[target.target] = true
1022
- // //});
1023
- // }
1024
- // } else {
1025
- // console.log("# 12")
1026
- // let frame = document.createElement("iframe")
1027
- // frame.name = target.target
1028
- // frame.src = target.href
1029
- // frame.setAttribute(
1030
- // "allow",
1031
- // "clipboard-read *; clipboard-write *; accelerometer *; ambient-light-sensor *; autoplay *; battery *; camera *; display-capture *; gamepad *; geolocation *; gyroscope *; hid *; identity-credentials-get *; microphone *; midi *; otp-credentials *; serial *;"
1032
- // )
1033
- // document.querySelector("main").appendChild(frame)
1034
- // loaded[target.target] = true
1035
- // }
1036
- } else {
1037
- console.log("# 13")
1038
- // couldn't find item,
1039
- // clear the hash
1040
- //
1041
- location.hash = ""
1042
- }
1043
- } else {
1044
- console.log("# 14")
1045
- document.querySelector(".container").classList.remove("active")
1046
- document.querySelector("aside").classList.add("active")
1047
-
1048
- }
1049
- }
1050
- console.log("loaded before", loaded)
1051
- <% if (type === "run" && env.PINOKIO_SCRIPT_DEFAULT && env.PINOKIO_SCRIPT_DEFAULT.toString().toLowerCase() === "true") { %>
1052
- renderSelection()
1053
- <% } %>
1054
- //renderCursor()
1055
- console.log("loaded after", loaded)
1056
- //Reporter()
1057
- document.querySelector("#reload").addEventListener("click", (e) => {
1058
- /*
1059
- // get selected
1060
- let target = document.querySelector(".selected").target
1061
- location.hash = target
1062
- // force refresh
1063
- renderSelection(null, true)
1064
- */
1065
- let frame = document.querySelector("iframe:not(.hidden)")
1066
- frame.src = frame.src
1067
- // frame.contentWindow.location.reload();
1068
- })
1069
- <% if (agent === "electron") { %>
1070
- document.querySelector("#back").addEventListener("click", (e) => {
1071
- nav("back")
1072
- })
1073
- document.querySelector("#forward").addEventListener("click", (e) => {
1074
- nav("forward")
1075
- })
1076
- <% } %>
1077
-
1078
- document.querySelector("#new-tab").addEventListener("click", async (e) => {
1079
- const u = prompt("url")
1080
-
1081
- if (u) {
1082
- let url
1083
- if (/^[ ]*http:/i.test(u)) {
1084
- url = u
1085
- } else if (/^[ ]*https:/i.test(u)) {
1086
- url = u
1087
- } else {
1088
- let o = {}
1089
- if (/^[0-9.:]/.test(u)) {
1090
- o.forceHttp = true
1091
- } else if (/^localhost/.test(u)) {
1092
- o.forceHttp = true
1093
- } else {
1094
- o.forceHttps = true
1095
- }
1096
- url = normalizeURL(u, o)
1097
- }
1098
-
1099
- if (url && url.trim().length > 0) {
1100
- console.log("url", url)
1101
- const { tab, frame } = await addTab(url)
1102
- tab.click()
1103
- }
1104
- }
1105
- })
1106
- document.querySelector("#clone-tab").addEventListener("click", async (e) => {
1107
- const url = document.querySelector("#clone-tab").getAttribute("data-href")
1108
- if (url && url.trim().length > 0) {
1109
- console.log("url", url)
1110
- const { tab, frame } = await addTab(url)
1111
- tab.click()
1112
- }
1113
- })
1114
-
1115
- const syncTabs = async () => {
1116
- let tabs = []
1117
- document.querySelectorAll(".temp-menu .frame-link").forEach((el) => {
1118
- tabs.push(el.href)
1119
- })
1120
-
1121
-
1122
- // persist
1123
- console.log("sync tabs", tabs)
1124
-
1125
- await fetch("/pinokio/tabs", {
1126
- method: "POST",
1127
- headers: {
1128
- "Content-Type": "application/json"
1129
- },
1130
- body: JSON.stringify({
1131
- name: "<%=name%>",
1132
- tabs
1133
- })
1134
- })
1135
- }
1136
- const addTab = async (url) => {
1137
- let item = document.createElement("a")
1138
- //let id = "ts" + Date.now()
1139
- let index = document.querySelectorAll("aside .s .frame-link").length
1140
-
1141
- let id = "s" + index
1142
- // let id = url
1143
- item.target = id
1144
- item.href = url
1145
- item.setAttribute("data-index", index)
1146
- item.className = "btn header-item frame-link"
1147
- item.innerHTML = `<div class='tab'><i class="fa-solid fa-link"></i><div class='display'>${url}</div><div class='flexible'></div><button class='btn2 del'><i class="fa-solid fa-xmark"></i></button></div>`
1148
-
1149
- document.querySelector(".temp-menu").appendChild(item)
1150
-
1151
- let frame = document.createElement("iframe")
1152
- frame.name = id
1153
- frame.src = item.href
1154
- frame.setAttribute(
1155
- "allow",
1156
- "clipboard-read *; clipboard-write *; accelerometer *; ambient-light-sensor *; autoplay *; battery *; camera *; display-capture *; gamepad *; geolocation *; gyroscope *; hid *; identity-credentials-get *; microphone *; midi *; otp-credentials *; serial *;"
1157
- )
1158
- document.querySelector("main").appendChild(frame)
1159
-
1160
- await syncTabs()
1161
-
1162
-
1163
- return {
1164
- tab: item,
1165
- frame
1166
- }
1167
-
1168
- }
1169
-
1170
-
1171
-
1172
-
1173
- if (document.querySelector("#menu-mobile")) {
1174
- document.querySelector("#menu-mobile").addEventListener("click", async (e) => {
1175
- location.hash = ""
1176
- refresh(false, { nodelay: true })
1177
- })
1178
- }
1179
- if (document.querySelector("#menu")) {
1180
- document.querySelector("#menu").addEventListener("click", async (e) => {
1181
- document.querySelector("aside").classList.toggle("hidden")
1182
- document.querySelector("#menu").classList.toggle("margin")
1183
- })
1184
- }
1185
- document.querySelector(".app-info").addEventListener("click", async (e) => {
1186
- e.preventDefault()
1187
- e.stopPropagation()
1188
- location.hash = ""
1189
- renderSelection()
1190
-
1191
- })
1192
- document.querySelector("#delete").addEventListener("click", async (e) => {
1193
- e.preventDefault()
1194
- e.stopPropagation()
1195
- const confirmed = confirm("Are you sure you wish to delete the app?")
1196
- if (confirmed) {
1197
- let name = document.querySelector("#delete").getAttribute("data-name")
1198
- console.log("delete", name)
1199
- Swal.fire({
1200
- html: '<i class="fa-solid fa-circle-notch fa-spin"></i> Deleting',
1201
- customClass: {
1202
- container: "loader-container",
1203
- popup: "loader-popup",
1204
- htmlContainer: "loader-dialog",
1205
- footer: "hidden",
1206
- actions: "hidden"
1207
- }
1208
- });
1209
- let res = await fetch("/pinokio/delete", {
1210
- method: "post",
1211
- headers: {
1212
- "Content-Type": "application/json"
1213
- },
1214
- body: JSON.stringify({ name })
1215
- }).then((res) => {
1216
- return res.json()
1217
- })
1218
- console.log("res", res)
1219
- Swal.close()
1220
- if (res) {
1221
- if (res.success) {
1222
- location.href = "/"
1223
- } else if (res.error) {
1224
- alert(res.error)
1225
- }
1226
- }
1227
- } else {
1228
- }
1229
- })
1230
- document.querySelector("aside").addEventListener("click", async (e) => {
1231
- let target
1232
-
1233
-
1234
- // 1. handle delete
1235
- if (e.target.classList.contains("del")) {
1236
- target = e.target
1237
- } else {
1238
- target = e.target.closest(".del")
1239
- }
1240
-
1241
- if (target) {
1242
- e.preventDefault()
1243
- e.stopPropagation()
1244
- // Delete
1245
- // delete link
1246
- let el = target.closest(".frame-link")
1247
- console.log("target", el.target)
1248
- let iframe = document.querySelector("iframe[name='" + el.target + "']")
1249
- console.log("iframe", iframe)
1250
- if (iframe) {
1251
- // delete iframe
1252
- iframe.remove()
1253
- }
1254
- el.remove()
1255
- // update tabs
1256
- await syncTabs()
1257
- return
1258
- }
1259
-
1260
-
1261
- // 2. handle shudown
1262
- if (e.target.classList.contains("shutdown")) {
1263
- target = e.target
1264
- } else {
1265
- target = e.target.closest(".shutdown")
1266
- }
1267
- if (target) {
1268
- e.preventDefault()
1269
- e.stopPropagation()
1270
- let link = target.closest("[href]")
1271
- let src = new URL(link.href).pathname
1272
- target.querySelector("i.fa-square").className = "fa-solid fa-check"
1273
- n.Noty({
1274
- text: `stopping ${src}`,
1275
- silent: true,
1276
- timeout: 2000
1277
- })
1278
- console.log("src", src)
1279
-
1280
- let socket = new Socket()
1281
- socket.run({
1282
- method: "kernel.api.stop",
1283
- params: {
1284
- uri: "~" + src
1285
- }
1286
- }, (packet) => {
1287
- if (packet.type === "result") {
1288
- socket.close()
1289
- n.Noty({
1290
- timeout: 2000,
1291
- text: `stopped`,
1292
- silent: true
1293
- })
1294
- refresh(true)
1295
- }
1296
- })
1297
-
1298
- return
1299
- }
1300
-
1301
-
1302
-
1303
- // 3. handle select
1304
- if (e.target.classList.contains("frame-link")) {
1305
- target = e.target
1306
- } else {
1307
- target = e.target.closest(".frame-link")
1308
- }
1309
-
1310
-
1311
-
1312
- if (target) {
1313
-
1314
- // if data-confirm exists, ask for confirmation
1315
- // if not, then just go forward
1316
- let confirmText = target.getAttribute("data-confirm")
1317
- if (confirmText && confirmText.length > 0) {
1318
- const confirmed = confirm(confirmText)
1319
- if (!confirmed) {
1320
- e.preventDefault()
1321
- e.stopPropagation()
1322
- return
1323
- }
1324
- }
1325
-
1326
- if (target.getAttribute("data-action")) {
1327
- let actionStr = target.getAttribute("data-action")
1328
- let action = JSON.parse(actionStr)
1329
- console.log("action", action)
1330
- if (action.method === "stop" && action.uri) {
1331
- let socket = new Socket()
1332
- socket.run({
1333
- method: "kernel.api.stop",
1334
- params: {
1335
- uri: action.uri//"~" + location.pathname
1336
- }
1337
- }, (packet) => {
1338
- if (packet.type === "result") {
1339
- socket.close()
1340
- // location.href = location.href
1341
- }
1342
- })
1343
- }
1344
- } else if (target.getAttribute("data-filepath")) {
1345
- return
1346
- } else if (target.target === "_blank") {
1347
- // nothing
1348
- } else {
1349
- if (target.classList.contains("reveal")) {
1350
- // nested menu
1351
- target.closest(".nested-menu").querySelector(".submenu").classList.toggle("hidden")
1352
- e.preventDefault()
1353
- e.stopPropagation()
1354
- } else {
1355
- //location.hash = target.target
1356
-
1357
-
1358
- // let id = getTarget(target.getAttribute("href"))
1359
- // console.log("ID", id, target.href)
1360
- // location.hash = id
1361
-
1362
- //location.hash = target.getAttribute("href")
1363
-
1364
- if (target.closest(".h")) {
1365
- location.hash = target.target
1366
- } else {
1367
- let index = target.getAttribute("data-index")
1368
- let type = target.closest(".m").getAttribute("data-type")
1369
-
1370
-
1371
- location.hash = type + index
1372
- }
1373
-
1374
- document.querySelectorAll(".frame-link").forEach((el) => {
1375
- el.classList.remove("selected")
1376
- })
1377
- target.classList.add("selected")
1378
-
1379
- renderSelection(e)
1380
- }
1381
- }
1382
- }
1383
-
1384
-
1385
-
1386
- })
1387
- const refresh_du = () => {
1388
- console.log("REFRESH DU")
1389
- fetch("/du/<%=name%>").then((res) => {
1390
- return res.json()
1391
- }).then((res) => {
1392
- let val
1393
- //let k = 1024
1394
- let k = 1000
1395
- if (res.du > k * k * k) {
1396
- // GB
1397
- val = `${Math.floor(res.du/k/k/k * 100) / 100} GB`
1398
- } else if (res.du > k * k) {
1399
- // MB
1400
- val = `${Math.floor(res.du/k/k * 100) / 100} MB`
1401
- } else {
1402
- // KB
1403
- val = `${Math.floor(res.du/k * 100) / 100} KB`
1404
- }
1405
- console.log("DU VAL", val)
1406
- //document.querySelector(".disk-usage").innerHTML = `<i class="fa-regular fa-hard-drive"></i> ${val}`
1407
- document.querySelector(".disk-usage").innerHTML = val
1408
- })
1409
- }
1410
- const refresh = async (silent, options) => {
1411
- if (options && options.nodelay) {
1412
- } else {
1413
- await new Promise((resolve, reject) => {
1414
- setTimeout(() => {
1415
- resolve()
1416
- }, 1000)
1417
- })
1418
- }
1419
- const html = await fetch("<%=sidebar%>").then((res) => {
1420
- return res.text()
1421
- })
1422
- document.querySelector(".menu").innerHTML = html
1423
- location.hash = ""
1424
-
1425
- // render the selected frame only if not silent
1426
- if (silent) {
1427
- } else {
1428
- if (options && options.nodelay) {
1429
- } else {
1430
- // await new Promise((resolve, reject) => {
1431
- // setTimeout(() => {
1432
- // resolve()
1433
- // }, 500)
1434
- // })
1435
- }
1436
- renderSelection()
1437
- }
1438
- refresh_du()
1439
- }
1440
- if (document.querySelector("#genlog")) {
1441
- document.querySelector("#genlog").addEventListener("click", (e) => {
1442
- e.preventDefault()
1443
- e.stopPropagation()
1444
- e.target.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i>'
1445
- fetch("/pinokio/log", {
1446
- method: "post",
1447
- }).then((res) => {
1448
- let btn = document.querySelector("#genlog")
1449
- let btn2 = document.querySelector("#downloadlogs")
1450
- btn2.classList.remove("hidden")
1451
- btn.classList.add("hidden")
1452
- btn.innerHTML = '<i class="fa-solid fa-circle-check"></i> Generated!'
1453
- //btn.classList.add("hidden")
1454
- })
1455
- })
1456
- }
1457
- window.addEventListener('message', (event) => {
1458
-
1459
- // only process the event it's coming from pinokio
1460
- let origin = event.origin
1461
- if (origin) {
1462
- let port = new URL(origin).port || 80
1463
- console.log("port", port)
1464
- if (String(port) === "<%=port%>") {
1465
- console.log("Message received from the child: ", event); // Message received from child
1466
- if (event.data) {
1467
- if (event.data.action) {
1468
- if (event.data.action.type === "newtab") {
1469
- console.log("create tab", event.data.action.url)
1470
- addTab(event.data.action.url)
1471
- } else if (event.data.action.type === "title") {
1472
- console.log("title", event.data)
1473
- } else if (event.data.action.type === "location") {
1474
- let url = event.data.action.url
1475
- console.log({ action: event.data.action })
1476
- document.querySelector("#open-browser").href = url
1477
- //document.querySelector("#location").innerHTML = url
1478
- document.querySelector("#location").value = url
1479
- }
1480
- } else if (event.data.type) {
1481
- let asideHidden = (window.getComputedStyle(document.querySelector("aside")).display === "none")
1482
- console.log("asideHidden", asideHidden)
1483
- if (!asideHidden) {
1484
- // refresh only if aside
1485
-
1486
- if (event.data.type === 'disconnect') {
1487
- refresh()
1488
- } else {
1489
- refresh()
1490
- }
1491
- }
1492
- }
1493
- } else {
1494
- refresh()
1495
- }
1496
- }
1497
- }
1498
-
1499
-
1500
- });
1501
- refresh_du()
1502
- /*
1503
- document.addEventListener("keydown", (e) => {
1504
- let size = document.querySelectorAll(".selectable").length
1505
- console.log("size", size)
1506
- e = e || window.event;
1507
- if (e.key === "ArrowUp") {
1508
- console.log("up arrow pressed");
1509
- if (cursorIndex > 0) {
1510
- cursorIndex--;
1511
- } else {
1512
- cursorIndex = size-1;
1513
- }
1514
- //renderCursor()
1515
- //let cursor = document.querySelector(".selectable.cursor")
1516
- //cursor.scrollIntoView(false)
1517
- //
1518
- } else if (e.key === "ArrowDown") {
1519
- if (cursorIndex < size-1) {
1520
- cursorIndex++;
1521
- } else {
1522
- cursorIndex = 0;
1523
- }
1524
- //renderCursor()
1525
- console.log("down arrow pressed");
1526
- //let cursor = document.querySelector(".selectable.cursor")
1527
- //cursor.scrollIntoView(false)
1528
- } else if (e.key === "Enter") {
1529
- //let selected = document.querySelector(".line.selected:not(.hidden) .btns a.selected")
1530
- let cursor = document.querySelector(".selectable.cursor")
1531
- if (cursor) {
1532
- e.preventDefault()
1533
- e.stopPropagation()
1534
- cursor.click()
1535
- }
1536
- }
1537
- });
1538
- */
1539
- </script>
1540
- </body>
1541
- </html>