Nice little directory browser :D
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix/Header: _hyperscript is not very capable...

* i've been fighting with hyperscript for a very long time, and it seems it just isn't a mature language that can do complicated things.
* now only use hs for things it is good at (events, per-element code for arbitrary events, that type of stuff...)
* drop into JS blocks for anything slightly complicated

+131 -35
+54 -33
Components/Header.razor
··· 37 37 38 38 <abbr id="rx-label" title="Search with RegEx">.*</abbr> 39 39 <input id="use-rx-for-search" type="checkbox" autocomplete="off" checked aria-labelledby="rx-label" _="@_scriptForIdUseRxForSearch" /> 40 + <input id="use-rx-for-search" type="checkbox" autocomplete="off" aria-labelledby="rx-label" _="@_scriptForIdUseRxForSearch" /> 41 + 42 + <abbr id="case-label" title="Case sensitive search">Aa</abbr> 43 + <input id="use-case-for-search" type="checkbox" autocomplete="off" aria-labelledby="case-label" /> 40 44 41 45 <span id="file-counter" class="my-auto" _="@_scriptForIdFileCounter" /> 42 46 </div> ··· 55 59 on load 56 60 set my value to '' 57 61 on input 58 - if (#use-rx-for-search's checked is true) then 59 - make a RegExp from my value called rxSearch 60 - show <tbody > tr/> in #filetable when rxSearch.test(the @data-order of .file-name in it) is true 61 - otherwise 62 - show <tbody > tr/> in #filetable when (the first @data-order of .file-name in it) contains my value.toLowerCase() 62 + js(me) 63 + let jme = $(me); 64 + let rxSearch = null; 65 + try { 66 + rxSearch = new RegExp(jme.val(), $('#use-case-for-search').prop('checked') ? '' : 'i'); 67 + } catch (e) { 68 + return null; 69 + } 70 + let rows = $('tbody > tr'); 71 + rows.addClass('hidden'); 72 + rows 73 + .filter((i, el) => rxSearch.test( 74 + $('.file-name', el).attr('data-order') 75 + )) 76 + .removeClass('hidden'); 77 + 63 78 end 64 79 on keydown[key==""Enter""] 65 - if event.isComposing or event.keyCode really equals 229 then 66 - exit 67 - otherwise 68 - send click to the first <#filetable-body > tr:not(.hidden) > .file-name > a/> 69 - set my value to """" 80 + js(me, event) 81 + if (event.isComposing || event.keyCode === 228) { 82 + return 83 + } else { 84 + $('#filetable-body > tr:not(.hidden) > .file-name > a').first().dispatchEvent(newEvent('click')) 85 + $(me).val('') 86 + } 70 87 end 71 88 on keydown from body 72 - make a RegExp from ""^(F|Soft)\\d"" called rx 73 - if not ( 74 - document.activeElement is me or -- dont repeat it! 75 - event.key is """" or -- actually I forgot 76 - event.ctrlKey or event.altKey or event.metaKey or -- dont react on modifier combos 77 - [""Shift"", ""Tab"", ""ArrowUp"", ""ArrowRight"", ""ArrowLeft"", ""ArrowDown"", 78 - ""AltGraph"", ""CapsLock"", ""Fn"", ""FnLock"", ""Hyper"", ""NumLock"", 79 - ""ScrollLock"", ""Super"", ""Symbol"", ""SymbolLock"", ""OS"", ""End"", ""Home"", 80 - ""PageDown"", ""PageUp"", ""Backspace"", ""Clear"", ""Delete"", ""Redo"", 81 - ""Undo"", ""Accept"", ""Again"", ""Attn"", ""Cancel"", ""ContextMenu"", 82 - ""Escape"", ""Find"", ""Pause"", ""Play"", ""Props"", ""Select"", ""ZoomIn"", 83 - ""ZoomOut"", ""Apps"", ""BrightnessDown"", ""BrightnessUp"", ""PrintScreen"", 84 - ""MediaFastForward"", ""MediaPause"", ""MediaPlay"", ""MediaPlayPause"", 85 - ""MediaRecord"", ""MediaRewind"", ""MediaStop"", ""MediaTrackNext"", 86 - ""MediaTrackPrevious""].includes(event.key) or -- special keys to not react on 87 - rx.test(event.key) -- more special keys but these can be regexed 88 - ) 89 - go to the top of the body 89 + js(me, event) 90 + let rx = new RegExp(""^(F|Soft)\d""); 91 + return (!( 92 + document.activeElement === me // dont repeat it! 93 + || event.key == """" // (actually I forgot) 94 + || event.ctrlKey || event.altKey || event.metaKey // dont react on modifier combos 95 + || [""Shift"", ""Tab"", ""ArrowUp"", ""ArrowRight"", ""ArrowLeft"", ""ArrowDown"", 96 + ""AltGraph"", ""CapsLock"", ""Fn"", ""FnLock"", ""Hyper"", ""NumLock"", 97 + ""ScrollLock"", ""Super"", ""Symbol"", ""SymbolLock"", ""OS"", ""End"", ""Home"", 98 + ""PageDown"", ""PageUp"", ""Backspace"", ""Clear"", ""Delete"", ""Redo"", 99 + ""Undo"", ""Accept"", ""Again"", ""Attn"", ""Cancel"", ""ContextMenu"", 100 + ""Escape"", ""Find"", ""Pause"", ""Play"", ""Props"", ""Select"", ""ZoomIn"", 101 + ""ZoomOut"", ""Apps"", ""BrightnessDown"", ""BrightnessUp"", ""PrintScreen"", 102 + ""MediaFastForward"", ""MediaPause"", ""MediaPlay"", ""MediaPlayPause"", 103 + ""MediaRecord"", ""MediaRewind"", ""MediaStop"", ""MediaTrackNext"", 104 + ""MediaTrackPrevious"" 105 + ].includes(event.key) // special keys to not react on 106 + || rx.test(event.key) // more special keys but these can be regexed 107 + )) 108 + end 109 + 110 + if it is true then 90 111 focus() on me 112 + go to the top of the body smoothly 91 113 "; 92 114 93 115 private readonly String _scriptForIdUseRxForSearch = @" 94 116 on load or click -- on load for if this comes checked 95 - if < #use-rx-for-search:checked />'s length 96 - add .font-mono to #search 97 - otherwise 98 - remove .font-mono from #search 117 + js 118 + $('#search') 119 + [ $('#use-rx-for-search').prop('checked') ? 'addClass' : 'removeClass' ]('font-mono') 120 + .dispatchEvent(newEvent('input')) 99 121 end 100 - send input to #search 101 122 "; 102 123 103 124 private readonly String _scriptForIdFileCounter = @"
+75
Components/Layout/MainLayout.razor
··· 29 29 <script src="/.nhnd/htmx.js"></script> 30 30 <script src="/.nhnd/jquery.js"></script> 31 31 <script src="/.nhnd/jquery.marquee.js"></script> 32 + <script type="text/javascript"> 33 + // custom jq extensions, see net.helpimnotdrowning."MB Convenience Buttons" 34 + HTMLElement.prototype.toJQuery = function() { return $(this); } 35 + 36 + jQuery.fn.exists = function() { return this.length > 0; } 37 + jQuery.fn.toDOM = function() { return this[0]; } 38 + jQuery.fn.appendAll = function(elArray) { 39 + /* 40 + * Append an entire array of elements to an element 41 + * 42 + * @@param elArray Array of elements. 43 + * @@returns Itself, *not* any member of the array. 44 + */ 45 + elArray.forEach( (el) => this.append(el) ); 46 + return this; 47 + } 48 + jQuery.fn.dispatchEvent = function(event) { 49 + /* 50 + * I think I made this because the default jQuery event sender didn't work 51 + * correctly/the way I expected. Internally calls the DOM dispatchEvent. 52 + * 53 + * @@param event Event to send. 54 + */ 55 + $(this).toDOM().dispatchEvent(event); 56 + return this; 57 + } 58 + jQuery.fn.setInput = function(value) { 59 + /* 60 + * Set the value of an input, supporting React inputs 61 + * 62 + * @@param value Value 63 + * @@returns Itself 64 + */ 65 + // :heart: https://github.com/jesus2099/konami-command/blob/1db343dc1fef317ab28b79b3386847d9af5771f6/lib/SUPER.js#L163C1-L171C2 66 + if (!this.exists()) { 67 + throw "input doesn't exist!"; 68 + } 69 + 70 + // Tested OK with input of types: <input> <select> <textarea> 71 + // Force react state change by bubbling up the input event : https://nattaylor.com/blog/2022/userscripts-and-reactjs-forms/ 72 + this.dispatchEvent(newEvent('input')); 73 + // Use native input value setter to bypass React (simple value setter is overridden by react) 74 + (Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this.toDOM()), "value").set).call(this.toDOM(), value); 75 + // Without change it was not working, either, in MBS edit artist page, at least 76 + this.dispatchEvent(newEvent('change')); 77 + 78 + return this; 79 + } 80 + jQuery.fn.second = function() { return this.eq(1); } 81 + jQuery.fn.check = function() { 82 + /* 83 + * Set a checkbox to checked. 84 + * 85 + * @@returns Itself 86 + */ 87 + this.toDOM().checked = true; 88 + return this; 89 + } 90 + jQuery.fn.uncheck = function() { 91 + /* 92 + * Set a checkbox to unchecked. 93 + * 94 + * @@returns Itself 95 + */ 96 + this.toDOM().checked = false; 97 + return this; 98 + } 99 + function sleep(ms) { 100 + return new Promise(resolve => setTimeout(resolve, ms)); 101 + } 102 + 103 + function newEvent(name) { 104 + return new Event(name, { bubbles: true }); 105 + } 106 + </script> 32 107 <meta name="htmx-config" content='{"scrollIntoViewOnBoost":false}' /> 33 108 34 109 <meta name="darkreader-lock" />
+1 -1
Tailwind/style.tw.css
··· 309 309 } 310 310 } 311 311 312 - #rx-label { 312 + #rx-label, #case-label { 313 313 @apply my-auto ms-[0ch] me-[-1ch] font-mono cursor-default! 314 314 } 315 315
+1 -1
public/style.css
··· 3343 3343 cursor: default !important; 3344 3344 } 3345 3345 } 3346 - #rx-label { 3346 + #rx-label, #case-label { 3347 3347 margin-block: auto; 3348 3348 margin-inline-start: 0ch; 3349 3349 margin-inline-end: -1ch;