JSFiddle - React, Tailwind, and code Playground

by Anthony DiSalvo

HTML

<script src="http://codeorigin.jquery.com/jquery-1.10.2.min.js"></script>
    <span data-bind="text:successes"></span>
    <div data-bind="templateWrapper: { dataInput: $data.successes, itemName: 'successes', maxLength:8000 }"></div>
    <script id="textTrackerTemplate" type="text/html">
        <textarea data-bind="value: itemText, hasFocus:hasFocus,event: { keyup:updateRemaining }"></textarea>                          
        <div class="lengthmessage edit" data-bind="visible:hasFocus" >
            <div >
                <em>Length:</em> <span data-bind="text:currentLength"></span>
                <em>Remaining:</em> <span data-bind="text:remainingLength"></span>
            </div>    
        </div>  
    </script>

JavaScript

(function (ko) {
            ko.bindingHandlers.templateWrapper = {
                init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
                    var existingOptions = ko.utils.unwrapObservable(valueAccessor());
                    newOptions = ko.bindingHandlers.templateWrapper.buildTemplateOptions(existingOptions, valueAccessor);
                    return ko.bindingHandlers.template.init(element, function () { return newOptions; }, allBindingsAccessor, viewModel, context);          
                },
                'update': function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
                    var existingOptions = ko.utils.unwrapObservable(valueAccessor());
                    newOptions = ko.bindingHandlers.templateWrapper.buildTemplateOptions(existingOptions, valueAccessor);
                    ko.bindingHandlers.template.update(element, function () { return newOptions; }, allBindingsAccessor, viewModel, context);
                },
                buildTemplateOptions: function (options, valueAccessor) {
                    valueAccessor().dataInput = valueAccessor().dataInput.extend({ textTracker: options.maxLength });
                    return { data: valueAccessor, name: ko.bindingHandlers.templateWrapper.templateName };
                },
                templateName: "textTrackerTemplate"
            };

            var viewModel = {
                successes: ko.observable("Test input")
            };
            
            ko.extenders.textTracker = function (target, maxLength) {
                target.itemText = ko.computed({
                    read: function () {
                        return target();
                    },
                    write: function (value) {
                        target(value);
                    }
                });

                target.maxLength = ko.observable(maxLength);
                target.currentLength =...