Sjaak Hijmering
Sjaak Hijmering

Reputation: 7

Size of a string with a css class

Hi i have build my own text-wrap class. and i've run into a small problem it is kind off slow, because my script that checks the size of the font puts the string into a div with the classes but thats on a big scale intens for the DOM. so is there another way?

as you can see i tryed to build a cache controller but that makes it slower

var textMetrics = function (appendTo) {
    var span;
    var cache = [];

    this.init = function () {
        span = document.createElement("span");
            appendTo.appendChild(span);
            span.style.position = 'absolute';
            span.style.left     = -9999 + 'px';
    };

    this.checkCache = function (word, style) {

        for (var i = 0; i < cache.length; i++) {
            if (cache[i].word == word) {
                return cache[i].value;
            }
        }
        return false;
    };

    this.addCache = function (word, style, value) {
        cache.push({
            "word": word,
            "style": style,
            "value": value
        });
    };

    this.getSize = function (word, style) {
        word = word.replaceAll(" ", "&nbsp;");

        //var inCache = this.checkCache(word, style);
        var inCache = false;
        if (inCache === false) {

            span.innerHTML = word;

            for (var i in style) {
                span.style[i] = style[i];
            }

            var coords = {
                "width": span.offsetWidth,
                "height": span.offsetHeight
            };


            for (var i in style) {
                span.style[i] = "";
            }

            span.innerHTML = "";

            this.addCache(word, style, coords);

            return coords;
        }
        else {
            return inCache;
        }

    };

    this.init();
};

Upvotes: 0

Views: 172

Answers (3)

Jan P&#246;schko
Jan P&#246;schko

Reputation: 5570

You could try to approximate the text width using the widths of individual characters. This will introduce problems when there's special kerning for combinations like "ff", of course. I wrote a function that caches the widths of pairs of characters to accommodate for that. Thus, only a constant number of DOM manipulations is needed. It's on http://jsfiddle.net/wbL9Q/6/ and https://gist.github.com/1562233 (too much code for here).

However, while this worked for me in Safari (Mac), it did not give the correct results in Firefox. Apparently, some even more complex kerning is applied there. Maybe extending the algorithm to triples of characters (or even more) could help.

(Sorry for posting my 2nd answer, but I thought it makes sense because it's a completely different aspect.)

Upvotes: 0

Steven de Salas
Steven de Salas

Reputation: 21467

Since you are basically using a dictionary the best format for your cache is a simple javascript object that behaves as a hashmap.

var cache = {};

You can then assign words to it as follows:

this.addCache = function (word, style, value) {
    cache[word] = {style: style, value: value};
};

And check them as follows:

this.checkCache = function (word) {
    return cache[word];
};

So then you can:

var cachedItem = this.checkCache(word);
if (cachedItem ) {
    alert(cachedItem.value);
}

This should speed up your cache searches considerably as you dont have to loop through an array that keeps getting larger and larger.

Upvotes: 1

Jan P&#246;schko
Jan P&#246;schko

Reputation: 5570

You could consider making your cache a dictionary (JS object) instead of a list:

var cache = {};

this.addCache = function (word, style, value) {
    cache[word] = value;
};

this.checkCache = function (word, style) {
    var value = cache[word];
    if (typeof value != "undefined")
        return value;
    return false;
};

I didn't really get what your style variable is about — maybe you should add it to the cache key as well.

Upvotes: 1

Related Questions