JSFiddle - React, Tailwind, and code Playground

by Daniel Flores

HTML

<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css">
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css">
<div class="form-group">
    <button type="button" class="btn btn-success" data-toggle="checkbutton">
        <i class="fa fa-fw fa-square-o"></i>Btn - Not Checked - Icon
    </button>
</div>
<div class="form-group">
    <button type="button" class="btn btn-success" data-toggle="checkbutton">Btn - Not Checked - No Icon</button>
</div>
<div class="form-group">
    <button type="button" class="btn btn-success active" data-toggle="checkbutton">
        <i class="fa fa-fw fa-square-o"></i>Btn - Checked - Icon
    </button>
</div>
<div class="form-group">
    <button type="button" class="btn btn-success active" data-toggle="checkbutton">Btn - Checked - No Icon</button>
</div>
<div class="form-group">
    <div class="btn-group">
        <label class="btn btn-primary">
            <input type="checkbox" data-toggle="checkbutton" />                        
            <i class="fa fa-fw fa-square-o"></i>Input - Not Checked - Icon
        </label>
    </div>
</div>
<div class="form-group">
    <div class="btn-group">
        <label class="btn btn-primary">
            <input type="checkbox" data-toggle="checkbutton" />Input - Not Checked - No Icon
        </label>
    </div>
</div>
<div class="form-group">
    <div class="btn-group">
        <label class="btn btn-primary">
            <input type="checkbox" checked="checked" data-toggle="checkbutton" />                        
            <i class="fa fa-fw fa-square-o"></i>Input - Checked - Icon
        </label>
    </div>
</div>
<div class="form-group">
    <div class="btn-group">
        <label class="btn btn-primary">
            <input type="checkbox" checked="checked" data-toggle="checkbutton" />Input - Checked - No Icon
        </label>
    </div>
</div>
<!-- Using Label causes a change in the input -->
<div...

CSS

.btn, .btn:hover, .btn:active, .btn:focus {
    outline: 0 !important;
}

JavaScript

/**
 * Bootstrap/Font Awesome Plugin for buttons to toggle a child icon
 * between a square and a checked square.
 */
$('[data-toggle^=checkbutton]').each(function(){
    var $this = $(this),
        isInput = $this.is('input'),
        $input = isInput ? $this : false,
        $button = isInput ? $this.parent('.btn') : $this,
        $icon = $button.find('.fa-check-square-o, .fa-square-o');
    
    // If no icon is set, prepend it
    if(!$icon.length > 0) {
        $icon = $('<i class="fa fa-fw">');
        isInput ? $this.after($icon) : $button.prepend($icon);
    }
    
    // Hide browser checkbox
    if(isInput) {
        $input.addClass('hidden');
    }
    
    // Update element classes
    var isChecked = isInput ? $input.prop('checked') : $button.hasClass('active');
        $button.toggleClass('active', isChecked);
        $icon.toggleClass('fa-square-o', !isChecked)
             .toggleClass('fa-check-square-o', isChecked);
});
$(document).on('click change', '[data-toggle^=checkbutton]', function(e) {
    var $this = $(this),
        isInput = $this.is('input'),
        $input = isInput ? $this : false,
        $button = isInput ? $this.parent('.btn') : $this,
        $icon = $button.find('.fa-check-square-o, .fa-square-o'),
        eventType = e.type;

    // If input, only continue if there was a change
    if(isInput && !(eventType == 'change')){
        return;
    }
    
    // Update element classes
    if($icon.length > 0) {
        var isChecked = isInput ? !$input.prop('checked') : $button.hasClass('active');
        $button.toggleClass('active', !isChecked);
        $icon.toggleClass('fa-square-o', isChecked)
             .toggleClass('fa-check-square-o', !isChecked);
    }
});
$('#myInput').on('change', function(){
    console.log('myInput');
});