Calculate Text Dimensions of Element in Real-time

forked from original: https://coderwall.com/p/kdi8ua

by drzaus

HTML

<div class="form1">
    <div class="field1">
        <input id="inpt" type="text" placeholder="Type in here" />
        <div id="inpt-width"></div>
    </div>
        
    <div class="field2">
        <div id="inpt2" contenteditable>or type in here</div>
        <div id="inpt2-width"></div>
    </div>
    
</div>


Static: <div id="inpt4-width"></div>


<div class="form2">
    <div class="field1">
        <span id="inpt3">some fixed text here</span>
        <div id="inpt3-width"></div>
    </div>
    <em>The following use statically determined font from cloned originals</em>
    <div class="field2">
        <span class="width2" id="inpt5" contenteditable>some moar text here</span>
        <div id="inpt5-width"></div>
    </div>
    <div class="field3">
        <span class="width2" id="inpt6" contenteditable>some moar text here</span>
        <div id="inpt6-width"></div>
    </div>
    <div class="field4">
        <span class="width2b" id="inpt7" contenteditable>some moar text here</span>
        <div id="inpt7-width"></div>
    </div>
    <div class="field5">
        <em>uses original plugin</em><br />
        <span class="width1" id="inpt8" contenteditable>some moar text here</span>
        <div id="inpt8-width"></div>
    </div>
    <div class="field6">
        <em>uses dimension plugin</em><br />
        <span class="dim3" id="inpt9" contenteditable>some moar text here</span>
        <div>Width: <span class="inline" id="inpt9-width"></span></div>
        <div>Height: <span class="inline" id="inpt9-height"></span></div>
    </div>

</div>
    
<a class="btn-size" data-adj="1" href="#increase-size">Increase Size</a>
<a class="btn-size" data-adj="-1" href="#decrease-size">Decrease Size</a>

SCSS

*[contenteditable] { background-color:#ccc; } // so we know what we can change

.form1 {
    .field1, .field1 input { font-family:Verdana, sans-serif; }
    .field2 { font-size:120%; }
}

.form2 {
    .field2 { font-size:80%; text-transform:uppercase; }
    .field3 { font-size:110%; letter-spacing:0.5em; }
    span.placeholder { font-size:50%; } // break plugin style 2 static font
}

.width2b { line-height:3em; }

.big-1 { font-size:120%; }
.big-2 { font-size:140%; }
.big-3 { font-size: 20px; }
.big-4 { font-size:160%; }

input { font-size:inherit; } // so the body resize works
.inline { display:inline-block; }

JavaScript

// dynamic font from call
$.fn.textWidth = function(text, font) {
    if (!$.fn.textWidth.fakeEl) $.fn.textWidth.fakeEl = $('<span>').hide().appendTo(document.body);
    $.fn.textWidth.fakeEl.html(text || this.val() || this.text()).css('font', font || this.css('font'));
    return $.fn.textWidth.fakeEl.width();
};

// static font from clone
$.fn.textWidth2 = function(text) {
    // allow multiple calculations
    return $.map($(this), function(o) {
        var $o = $(o), $fake = $o.data('textWidth2.fake');
        console.log($o, $fake);
        if (!$fake) {
            // cloning causes duplication issues on subsequent calls
            // can attach to parent, but may be unnecessary parsing vs. body if updating font each time
            $fake = $('<span>').hide().addClass('placeholder').empty().appendTo($o.parent());
            $o.data('textWidth2.fake', $fake);
        }
        return $fake.html(text || $o.val() || $o.text()).width();
    });    
};

// get width or height
!(function($) {
    var N = function(key) { return 'getTextSize.' + key; },
        fontMapping = function($o, font) {
            //return {"font": font.font || $o.css('font')};
            var result = {}; // don't affect original object
            $.each(font, function(prop, val) {
                result[prop] = (val || $o.css(prop));
            });
            return result;
        }
    ;
    
    $.fn.getTextSize = function(dimension, text, font) {
        dimension = (dimension || 'width');
        // figure out what font aspects we're concerned with
        if( typeof font === "string" ) {
            font = {"font": font};
        }
        // include other common style properties that affect sizing
        font = $.extend({"font": false, "text-transform": false, "letter-spacing": false}, font);
        
        // allow multiple calculations
        return $.map($(this), function(o) {
            var $o = $(o), $fake = $o.data(N('fake'));
            console.log($o, $fake);
...