VanillaJS v. jQuery v. hyperscript

Below are comparisons of how to implement various common UI patterns in vanilla javascript, jQuery and hyperscript.

In general, the VanillaJS version will be the most awkward.

The jQuery version will be better, but will separate the logic from the element in question. This is considered good practice by some people, in the name of separation of concerns, but it violates locality of behavior, which we feel is usually more important for system maintainability. (If you've ever had to hunt for an obscure event handler in jQuery, you know what we mean.)

Both the VanillaJS and JQuery verisons will often require callbacks, making for awkward expression of logic that is straight-forward and linear in hyperscript. This becomes especially pronounced in more complex promise or callback chains.

Comparisons

Fade And Remove

Pattern: fade and remove an element after it is clicked

VanillaJS

<div onclick="this.style.transition = 'all 500ms ease-out';
              requestAnimationFrame(() => requestAnimationFrame(() => {
                this.style.opacity = '0';
                this.addEventListener('transitionend', () => {
                    this.remove();
                }, {once:true})
              })) ">
              Remove Me
</div>
Remove Me

jQuery

<script>
$(function(){
  $("#divToRemove").click(function(){
    $(this).fadeOut(500, function(){
        $(this).remove();
    });
  });
});
</script>
<div id="divToRemove">
              Remove Me
</div>
Remove Me

hyperscript

<div _="on click transition opacity to 0 then remove me">
              Remove Me
</div>
Remove Me

Fetch And Insert

Pattern: fetch some data and insert it into an element

VanillaJS

<button onclick="fetch('/clickedMessage/')
                  .then(response => response.text())
                  .then(data => {
                      document.getElementById('fetch-target-1').innerHTML = data
                  })">
 Fetch It
</button>
<div id="fetch-target-1"></div>

jQuery

<script>
$(function(){
  $("#fetchBtn").click(function(){
    $.get('/clickedMessage/', function(data){
        $("#fetch-target-2").html(data);
     })
  });
});
</script>
<button id="fetchBtn">
 Fetch It
</button>
<div id="fetch-target-2"></div>

hyperscript

<button _="on click fetch /clickedMessage/ then put the result into #fetch-target-3">
 Fetch It
</button>
<div id="fetch-target-3"></div>

Debounced Input

Pattern: debounce event handling to avoid triggering logic in response to multiple, shortly spaced events

VanillaJS

<input onkeyup="clearTimeout(this.debounce);
                this.debounce = setTimeout(() => {
                  document.getElementById('debounce-target-1').innerHTML = this.value;
                }, 300) "/>
<div id="debounce-target-1"></div>

jQuery

<script>
$(function(){
  var debounce = null;
  $("#debouncedInput").keyup(function(){
     clearTimeout(debounce);
     var self = $(this);
     debounce = setTimeout(function(){
       $('#debounce-target-2').html(self.val());
     }, 300);
  });
});
</script>
<input placeholder="Enter Some Data..."
       id="debouncedInput"/>
<div id="debounce-target-2"></div>

hyperscript

<input _="on keyup debounced at 300ms put my.value into #debounce-target-3"/>
<div id="debounce-target-3"></div>

Toggle A Class

Pattern: toggle a class on another element when clicked

VanillaJS

<button onclick="document.getElementById('toggle-target-1')
                         .classList.toggle('red-border')">
  Toggle Class
</button>
<div id="toggle-target-1"></div>

Toggle Target

jQuery

<script>
$(function(){
  $("#toggleBtn").click(function(){
    $("#toggle-target-2").toggleClass("red-border");
  });
});
</script>
<button id="toggleBtn">
  Toggle Class
</button>
<div id="toggle-target-2">
  Toggle Target
</div>
Toggle Target

hyperscript

<button _="on click toggle .red-border on #toggle-target-3">
  Toggle Class
</button>
<div id="toggle-target-3">
  Toggle Target
</div>
Toggle Target

Trigger An Event

Pattern: trigger a custom event on another element in the DOM

VanillaJS

<button onclick="document.getElementById('event-target-1')
                         .dispatchEvent(new Event('doIt'))">
  Trigger Event
</button>
<div id="event-target-1">
  Event Target
</div>
<script>
  document.getElementById('event-target-1').addEventListener("doIt", () => {
    document.getElementById('event-target-1').remove()
  });
</script>

Event Target

jQuery

<script>
$(function(){
  $("#triggerBtn").click(function(){
    $("#event-target-2").trigger("doIt");
  });
  $("#event-target-2").on('doIt', function(){
    $(this).remove();
  });
});
</script>
<button id="triggerBtn">
  Trigger Event
</button>
<div id="event-target-2">
  Event Target
</div>
Event Target

hyperscript

<button _="on click send doIt to #event-target-3">
  Trigger Event
</button>
<div id="event-target-3"
     _="on doIt remove me">
  Event Target
</div>
Event Target

Show An Element

Make an element visible by setting the display style to block

VanillaJS

<button onclick="document.getElementById('show-target-1').style.display = 'block'">
  Show Element
</button>
<div style="display: none" id="show-target-1">
  Hidden Element
</div>

jQuery

<script>
$(function(){
  $("#showBtn").click(function(){
    $("#show-target-2").show();
  });
});
</script>
<button id="showBtn">
  Show Element
</button>
<div style="display: none" id="show-target-2">
  Hidden Element
</div>

hyperscript

<button _="on click show #show-target-3">
  Show Element
</button>
<div style="display: none" id="show-target-3">
  Hidden Element
</div>