How to avoid infinite loop in the function/call that reduces the font size?

Asked

Viewed 127 times

2

I created this small extension of jQuery that aims to reduce the size of the text by setting font-size CSS based on the overflow of its container.

The operation is simple, find the current font size and remove a pixel from it, then apply a new CSS definition to the element in question:

;(function ($) {

    $.fn.fitWidth = function( options ) {

        var opts = $.extend({
            min: "11"
        }, options );

        var tamanho = parseInt(this.css('font-size'));

        if (tamanho > opts.min) {
            return this.css({
                'font-size': tamanho-1        
            });
        }
    };
}( jQuery ));

However, there is a problem:

If the letter indicated by the user, or even the default minimum value is not low enough to avoid the overflow, the call of this extension will cause an infinite cycle:

$('#wrap span').each(function(){
    var $this = $(this),
        overflow = $this[0].scrollWidth > $this.width() ? true : false;

    if (overflow) {
        while (overflow) {
            $this.fitWidth({"min":'1'});
            overflow = $this[0].scrollWidth > $this.width() ? true : false;
        }
    }
});

With minimum letter a 11 for example, we will have an infinite cycle.

Example in Jsfiddle to a minimum of 1, but beware of changing the value to test, an infinite cycle of Javascript can cause the browser to work.

Exemplo a funcionar com letra mínima de 1

Question:

How can I change the extension or the call of it to avoid endless cycles?

1 answer

2


The first idea that comes to me is to limit the while to the current size in pixels, as the excerpt below:

$('#wrap span').each(function(){
    var $this = $(this),
        overflow = $this[0].scrollWidth > $this.width() ? true : false;

    if (overflow) {
        var size = parseInt($this.css('font-size'));
        while (overflow && size-- > 1) {
            $this.fitWidth({"min":'1'});
            overflow = $this[0].scrollWidth > $this.width() ? true : false;
        }
    }
});

I updated the example on jsfiddle.

Obviously it would be good to do a treatment as to the value. And in case you cannot recover an integer or be in another unit, you could limit yourself to a maximum number that, although less elegant, would avoid locking the browser or tab.


Alternatively, the function added to jQuery could encapsulate complete logic, simplifying use:

;(function ($) {

    $.fn.fitWidth = function( options ) {

        var opts = $.extend({
            min: "11"
        }, options );

        this.each(function() {

            var $this = $(this);
            var tamanho = parseInt($this.css('font-size'));

            var overflow = $this[0].scrollWidth > $this.width() ? true : false;
            while (overflow && tamanho > opts.min && tamanho-- > 1) {
                $this.css({
                    'font-size': tamanho
                });
                overflow = $this[0].scrollWidth > $this.width() ? true : false;
            }

        });
        return this;

    };
}( jQuery ));

Use becomes simpler and function encapsulated:

$('#wrap span').fitWidth({"min":'1'}); 

See another version on jsfiddle.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.