angularjs directive to fit text in an overflow hidden element

replace text that would be too long to fit an overflow:hidden block with an abbr and an elipse.

by mortimerpa

HTML

<script src="http://code.angularjs.org/1.1.0/angular.min.js"></script>
<div ng-app="jsf">
    <div ng-controller="MyCtrl">
        <div ng-repeat="name in names">
            <long-name class="width" outer="strong" long-val="{{name.first}} {{name.second}}"/>
        </div>
    </div>
</div>

CSS

.width {
    width: 106px;
    border-right: 1px solid black;
    overflow:hidden;
    display: inline-block;
}

JavaScript

angular.module('jsf', []).directive('longName', function() {

    function hasScrollbar(elm) {
        var _elm = elm[0];
        var oldDisplay = elm.css('display');
        var oldWidth = _elm.offsetWidth;
        elm.css('display', 'inline');
        var newWidth = _elm.offsetWidth;
        elm.css('display', oldDisplay);
        if (_elm === undefined) {
            return false;
        }
        if (oldWidth < newWidth) {
            return true;
        }
        return false;
    }

    function dichotomy(low, high, name, elm, outer) {
        if (low >= high) {
            return;
        }
        if (low === 0 && high === name.length) {
            elm.html('<' + outer + '>' + name.substring(0, high) + "</" + outer + ">");

        } else {
            elm.html('<' + outer + '><abbr title="' + name + '">' + name.substring(0, high) + "&hellip;</attr></" + outer + ">");
        }
        if (hasScrollbar(elm)) {
            dichotomy(low, high / 2, name, elm, outer);
        } else {
            dichotomy(high, low + high / 2, name, elm, outer);
        }
    }

    return {
        restrict: 'E',
        link: function(scope, element, attr) {
            attr.$observe('longVal', function() {
                var name = attr.longVal;
                var maxLen = name.length;
                dichotomy(0, name.length, name, element, attr.outer);

            });
        }
    };
}).controller('MyCtrl', function($scope) {
    $scope.names = [{
        first: "Betty",
        second: "Bushaksteinwitzskymansonescubergsen"},
    {
        first: "shorty",
        second: "long"}];
});