The hyperscript Cookbook

Below is a collection of hyperscript snippets for achieving various patterns in web development.

Hello World - concat two strings

Example: Concatenate two strings in _hyperscript
<p id="first">Hello</p>
<p id="second">World</p>
<button class="btn primary" _="on click set my.innerText to #first.innerText + ' ' + #second.innerText">
Concat
</button>

Hello

World

This example illustrates how to use an event handler to fetch state from other elements, perform a simple operation, and then store that state in another location.

Set a checkbox to indeterminate state on load/reset

Example: Click 'Reset' to get an indeterminate checkbox
<form>
<input class="indeterminate" type="checkbox" _="on load set my.indeterminate to true">
<input type="reset" _="on click set .indeterminate.indeterminate to true">
</form>

HTML checkboxes technically have three states - checked, unchecked and indeterminate. Oddly, the indeterminate state can only be set via the JavaScript runtime - there is no way to set the state via HTML or CSS alone.

In this example, the checkbox sets the indeterminate state when the page is loaded. In addition, the "indeterminate" class is also set, allowing the handler on the reset button to use a CSS query to reset all matching elements back to the indeterminate state.

Fade & Remove

If you wish to fade an element out and remove it from the DOM, you can use something like this:

Example: Using the transition command
<button _="on click transition opacity to 0 then remove me">
Fade & Remove
</button>

Disable a Button During an htmx Request

If you wish to disable a button during an htmx request, you can use this snippet:

Example: Disable button until request finishes
<button
    class="button is-primary"
    hx-get="/example"
    _="on click toggle @disabled until htmx:afterOnLoad">
    Do It
</button>

Disable all Buttons During an htmx Request

If you wish to disable every button during an htmx request, you can use this snippet:

Example
<body _="on every htmx:beforeSend in <button:not(.no-disable)/> 
         tell it 
             toggle [@disabled='true'] until htmx:afterOnLoad">

</body>

Here we use the every keyword to avoid queuing events, and then the in modifier to filter only clicks that occur within buttons that do not have the .no-disable class on them. When the body gets an event that matches this requirement, it will toggle the disabled property to true on the button, until it receives an htmx:afterLoad event from the button.

We use the with command to make it (the button) the default target (me) for the toggle command

Filter A Group Of Elements

You can easily filter down the visibility of a set of elements based on a condition by using the show ... when form of the show command

Example
<input type="text" placeholder="Search Quotes..."
     _="on keyup
         if the event's key is 'Escape'
           set my value to ''
           trigger keyup
         else
          show <blockquote/> in #quotes when its textContent contains my value">

Here we do the search on keyup. If the key was an escape, we reset the value of the input and rerun the event, which shows all quotes.

Programming Quotes

"Talk is cheap. Show me the code."

– Linus Torvalds

"when you don't create things, you become defined by your tastes rather than ability. your tastes only narrow & exclude people. so create."

– Why The Lucky Stiff

"Programs must be written for people to read, and only incidentally for machines to execute."

– Harold Abelson, Structure and Interpretation of Computer Programs

"Programming today is a race between software engineers striving to build bigger and better idiot> –proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning."

– Rick Cook, The Wizardry Compiled

"Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live"

– John Woods

"The best programs are written so that computing machines can perform them quickly and so that human beings can understand them clearly. A programmer is ideally an essayist who works with traditional aesthetic and literary forms as well as mathematical concepts, to communicate the way that an algorithm works and to convince a reader that the results will be correct."

– Donald E. Knuth, Selected Papers on Computer Science

"I'm not a great programmer; I'm just a good programmer with great habits."

– Kent Beck

"Give a man a program, frustrate him for a day. Teach a man to program, frustrate him for a lifetime."

– Muhammad Waseem

"Truth can only be found in one place: the code."

– Robert C. Martin, Clean Code: A Handbook of Agile Software Craftsmanship

"That's the thing about people who think they hate computers. What they really hate is lousy programmers."

– Larry Niven

"A language that doesn't affect the way you think about programming is not worth knowing."

– Alan J. Perlis

"The most disastrous thing that you can ever learn is your first programming language."

– Alan Kay

"Objectoriented programming offers a sustainable way to write spaghetti code. It lets you accrete programs as a series of patches."

– Paul Graham, Hackers & Painters: Big Ideas from the Computer Age

"Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?"

– Brian Kernighan

Drag-and-drop elements

You can drag and drop elements by listening to drag events and using the dataTransfer object.

<p _="on dragstart call event.dataTransfer.setData('text/plain',target.textContent)">
  <button class="btn primary" draggable=true>DRAG ME</button>
  <button class="btn primary" draggable=true>OR ME</button>
</p>
<pre _="
  on dragover or dragenter halt the event
    then set the target's style.background to 'lightgray'
  on dragleave or drop set the target's style.background to ''
  on drop get event.dataTransfer.getData('text/plain')
    then put it into the next <output/>">Drop Area
&nbsp;
&nbsp;
&nbsp;
Drop Area</pre>
Result: <output></output>

When a drag starts, we set the value of the dataTransfer object. When the drag goes over a valid drop zone we set the background. When leaving a drop zone or after a drop we reset the background. Upon a drop we recover the original value and display it.

Drop Area
 
 
 
Drop Area

Result:

This can also be used to accept dragged files for an <input type="file"> element.

Event Filter

You can easily filter events based on a condition by using the on <event-name>[] form of the on feature

<button _="on click[event.altKey] remove .primary then settle then add .primary">CLICK ME</button>

In this case we simply check if the Alt key is being held down or not.

Filter table rows

You can filter rows from a table:

<table>
  <thead><tr><th><input _="on input
   show <tbody>tr/> in closest <table/>
     when its textContent.toLowerCase() contains my value.toLowerCase()
  "/></th></tr></thead>
  <tbody style="height:10em;display:block;overflow-y:scroll">
    <tr><td>Foo Bar</td><td>Item 1</td></tr>
    <tr><td>Boo Bar</td><td>Item 2</td></tr>
    <tr><td>Gru Bar</td><td>Item 3</td></tr>
    <tr><td>Zoo Bar</td><td>Item 4</td></tr>
    <tr><td>Foo Bar</td><td>Item 5</td></tr>
  </tbody>
</table>

Here we use the show command along with when and with clauses to filter rows. Note that we use a query selector to ensure we only perform operation over the body of the table instead of on the input. We set a static height for the <tbody> element and set scrollbars for overflow-y to avoid reflow for the rest of the page during filtering.

Foo BarItem 1
Boo BarItem 2
Gru BarItem 3
Zoo BarItem 4
Foo BarItem 5