Disabling a button in vanilla JavaScript and in jQuery
<h3>Vanilla JavaScript</h3>
<p>In vanilla JavaScript, one can easily enable and disable a button using the following statement:</p>
<pre><code>button.disabled = state;
</code></pre>
<p>This works both when humans try to click a button and when buttons are clicked programmatically:</p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>var button = document.getElementById('myButton');

button.addEventListener('click', function() {
    alert('world');
});

button.disabled = true;
button.click(); // No output
button.disabled = false;
button.click(); // Output : "Hello" and "world
button.disabled = true;
button.click(); // No output</code></pre>
<pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;input type="button" id="myButton" value="button" onClick="alert('Hello')"/&gt;</code></pre>
</div>
</div>
</p>
<p>This also works when using the <code>MouseEvent</code> interface:</p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>var button = document.getElementById('myButton');

var click = new MouseEvent("click", {
    "view": window
});

button.addEventListener('click', function() {
    alert('world');
});

button.disabled = true;
button.dispatchEvent(click); // No output
button.disabled = false;
button.dispatchEvent(click); // Output : "Hello" and "world
button.disabled = true;
button.dispatchEvent(click); // No output</code></pre>
<pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;input type="button" id="myButton" value="button" onClick="alert('Hello')"/&gt;</code></pre>
</div>
</div>
</p>
<hr />
<h3>jQuery</h3>
<p>I can't seem to be able to do the same with jQuery, though :</p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>var button = $("#myButton");

button.on("click", function() {
    alert("world");
});

button.prop("disabled", true);
button.click(); // Output : "world" and "Hello"
button.prop("disabled", false);
button.click(); // Output : "world" and "Hello"
button.prop("disabled", true);
button.click(); // Output : "world" and "Hello"</code></pre>
<pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://code.jquery.com/jquery-1.12.2.min.js"&gt;&lt;/script&gt;
&lt;input type="button" id="myButton" value="button" onClick="alert('Hello')"/&gt;</code></pre>
</div>
</div>
</p>
<p>Both <code>button.prop(&quot;disabled&quot;, true);</code> and <code>button.attr(&quot;disabled&quot;, true);</code> simply change the <code>disabled</code> property of the button element, but neither disables the actual click event. This means that events are triggered whenever <code>button.click();</code> is called, even if the button is disabled!</p>
<p>Additionally, &quot;world&quot; and &quot;Hello&quot; are output in the wrong order.</p>
<p>The simplest code I could come up with to emulate the behavior of the vanilla JavaScript versions, is this :</p>
<p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
<div class="snippet-code">
<pre class="snippet-code-js lang-js prettyprint-override"><code>var button = $("#myButton");

button.on("click", function() {
    alert("world");
});

button.disable = (function() {
    var onclick = null;
    var click = [];
    return function(state) {
        if(state) {
            this.prop('disabled', true);
            if(this.prop('onclick') !== null) {
                onclick = this.prop('onclick');
                this.prop('onclick', null);
            }
            var listeners = $._data(this.get()[0], "events");
            listeners = typeof listeners === 'undefined' ? [] : listeners['click'];
            if(listeners &amp;&amp; listeners.length &gt; 0) {
                for(var i = 0; i &lt; listeners.length; i++) {
                    click.push(listeners[i].handler);
                }
                this.off('click');
            }
        } else {
            this.removeProp('disabled');
            if(onclick !== null) {
                this.prop('onclick', onclick);
                onclick = null;
            }
            if(click.length &gt; 0) {
                this.off('click');
                for(var i = 0; i &lt; click.length; i++) {
                    this.on("click", click[i]);
                }
                click = [];
            }
        }
    }
})();

button.disable(true);
button.click(); // No output
button.disable(false);
button.click(); // Output : "Hello" and "world
button.disable(true);
button.click(); // No output</code></pre>
<pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://code.jquery.com/jquery-1.12.2.min.js"&gt;&lt;/script&gt;
&lt;input type="button" id="myButton" value="button" onClick="alert('Hello')"/&gt;</code></pre>
</div>
</div>
</p>
<p>That is, of course, ridiculously convoluted and &quot;hacky&quot; code to achieve something as simple as disabling a button.</p>
<hr />
<h3>My questions</h3>
<ul>
<li>Why is it that jQuery - unlike vanilla JS - doesn't disable the events when disabling a button?</li>
<li>Is this to be considered a bug or a feature in jQuery?</li>
<li>Is there something I'm overlooking?</li>
<li>Is there a simpler way to get the expected behavior in jQuery?</li>
</ul>