JSFiddle - React, Tailwind, and code Playground

by Kai

HTML

<textarea></textarea>

CSS

.bbcode-editor {
    width: 100%;
}

.bbcode-toolbar {
    margin: 0;
    list-style-type: none;
    padding: 0;
}

.bbcode-toolbar li[title] {   
    display: inline;
    padding-left: 18px;    
    margin-left: 10px;
    cursor: pointer;
    opacity: 0.3;
}

.bbcode-toolbar li[title]:hover {
    opacity: 1;
}

.bbcode-toolbar li[class=bbcode-spacer] {   
    display: inline;
    padding-left: 5px;    
    margin-left: 5px;
}

.bbcode-textarea {
    width: 100%;
    height: 150px;
    padding: 5px;
    border: 1px solid #999;
    resize: vertical;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    -ie-box-sizing: border-box;
    -o-box-sizing: border-box;
    box-sizing: border-box;
}

.bbcode-preview {
    position: relative;
    width: 100%;
    height: 150px;
    padding: 5px;
    border: 1px solid #999;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    -ie-box-sizing: border-box;
    -o-box-sizing: border-box;
    box-sizing: border-box;
    background: #F8F8F8; 
    display: none;
}

.bbcode-preview img {
    max-width: 100%;
}

.bbcode-bold {
    background: url(http://i.imgur.com/UWCCq.png) 0px 0px no-repeat;    
}

.bbcode-italic {
    background: url(http://i.imgur.com/UWCCq.png) 0px -26px no-repeat;    
}

.bbcode-underline {
    background: url(http://i.imgur.com/UWCCq.png) 0px -52px no-repeat;
}

.bbcode-strikethrough {
    background: url(http://i.imgur.com/UWCCq.png) 0px -78px no-repeat;
}

.bbcode-link {
    background: url(http://i.imgur.com/UWCCq.png) 0px -104px no-repeat;
}

.bbcode-image {
    background: url(http://i.imgur.com/UWCCq.png) 0px -130px no-repeat;
}

.bbcode-spoiler {
    background: url(http://i.imgur.com/UWCCq.png) 0px -156px no-repeat;
}

.bbcode-markup-preview {
    background: url(http://i.imgur.com/UWCCq.png) 0px -182px no-repeat;
}

.bbcode-quote {
    background: url(http://i.imgur.com/UWCCq.png) 0px -208px no-repeat;    
}

.bbcode-centeralign {
    background:...

JavaScript

/**
 * Rangy Text Inputs, a cross-browser textarea and text input library plug-in for jQuery.
 * http://code.google.com/p/rangyinputs/
 * Copyright %%build:year%%, Tim Down
 * Licensed under the MIT license.
 */
(function($) {
    var UNDEF = "undefined";
    var getSelection, setSelection, deleteSelectedText, deleteText, insertText;
    var replaceSelectedText, surroundSelectedText, extractSelectedText, collapseSelection;

    // Trio of isHost* functions taken from Peter Michaux's article:
    // http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
    function isHostMethod(object, property) {
        var t = typeof object[property];
        return t === "function" || (!!(t == "object" && object[property])) || t == "unknown";
    }

    function isHostProperty(object, property) {
        return typeof(object[property]) != UNDEF;
    }

    function isHostObject(object, property) {
        return !!(typeof(object[property]) == "object" && object[property]);
    }

    function fail(reason) {
        if (window.console && window.console.log) {
            window.console.log("RangyInputs not supported in your browser. Reason: " + reason);
        }
    }

    function adjustOffsets(el, start, end) {
        if (start < 0) {
            start += el.value.length;
        }
        if (typeof end == UNDEF) {
            end = start;
        }
        if (end < 0) {
            end += el.value.length;
        }
        return { start: start, end: end };
    }

    function makeSelection(el, start, end) {
        return {
            start: start,
            end: end,
            length: end - start,
            text: el.value.slice(start, end)
        };
    }

    function getBody() {
        return isHostObject(document, "body") ? document.body : document.getElementsByTagName("body")[0];
    }

    $(document).ready(function() {
        var testTextArea = document.createElement("textarea");

       ...