JSFiddle - React, Tailwind, and code Playground

by sparebytes

HTML

<h3 class="leak-prone">jQuery Bind</h3>
<div data-bindmethod="jquery.bind">
    <button class="ctrl">-</button>
    <button class="ctrl">+</button>
    <button class="ctrl">Off</button>
    <button class="">0</button>
    <button class="">0</button>
</div>

<h3 class="">jQuery Replace</h3>
<div data-bindmethod="jquery.replace">
    <button class="ctrl">-</button>
    <button class="ctrl">+</button>
    <button class="ctrl">Off</button>
    <button class="">0</button>
    <button class="">0</button>
</div>

<h3 class="leak-prone">Native Bind</h3>
<div data-bindmethod="native.bind">
    <button class="ctrl">-</button>
    <button class="ctrl">+</button>
    <button class="ctrl">Off</button>
    <button class="">0</button>
    <button class="">0</button>
</div>

<h3 class="">Native Replace</h3>
<div data-bindmethod="native.replace">
    <button class="ctrl">-</button>
    <button class="ctrl">+</button>
    <button class="ctrl">Off</button>
    <button class="">0</button>
    <button class="">0</button>
</div>

CSS

.ctrl {
    font-weight: bold;
}

.leak-prone {
}
.leak-prone:after {
    color: red;
    font-size: small;
    content: " Leak Prone";   
}

JavaScript

function causeLeak() {
    var el = this;
    var leaky = junkFactory(5);
    var first = ! el.leaks;
    
    // Bind Method
    var bm = $(this).closest('[data-bindmethod]').data('bindmethod').split('.');
    
    if(first) {
        el.leaks = 0;   
        el.leakTotal = 0;
    }
    el.leaks++;
    el.leakTotal += (leaky && leaky.length) || 0 / 100000;
    
    var clickHandler = function() {
        $(el).text(el.leaks+"   "+el.leakTotal);
        console.log("Handle", (leaky && leaky.length));
    };
    
    evUtil[bm[0]][bm[1]](el, clickHandler);
    
    first && clickHandler();
}

console.clear();



function junkFactory(amount) {
    var base = junkFactory.getBase();
    var junk = base;
    for(var i = 0; i < amount; i++) {
        junk = junk.split('').join(base);
    }
    return junk;
}
junkFactory.getBase = function() {
    var i = junkFactory.baseStart;
    var base = "";
    var bs = i + junkFactory.baseSize;
    for(; i < bs; i++) {
        base += i;
    }
    junkFactory.baseStart = i;
    base += junkFactory.basePostfix;
    return base;    
}
junkFactory.baseStart = 10200
junkFactory.baseSize = 2;
junkFactory.basePostfix = '-';


var evUtil = {
    jquery: {
        bind: function (el, handler){
            $(el).on('click', handler);
        },
        replace: function(el, handler) {
            $(el).off('click').on('click', handler);
        }        
    },
    
    native: {
        bind: function (el, handler){
            var xHandler = el.onclick || function(){};
            el.onclick = function() {
                xHandler.apply(this, arguments);
                handler.apply(this, arguments);
            };
        },
        replace: function(el, handler) {
            el.onclick = handler;
        }        
    }
};

$('body').on('click', 'button:not(.ctrl)', causeLeak);

var context = function(el) {
    return $(el).closest('[data-bindmethod]');
}
var firstNonCtrl = function(trigger) {
    return...