0

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();
};

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thx:) i will make it a dictionary!
1

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.

3 Comments

ok thx! that wil help! but another question. is there no faster way of checking the text size a way without appending it to the DOM.
DOM is what creates the greatest performance hit in javascript. Even greater than looping through an array unecessarily. If what you want is to check the size of text in a hidden tag I dont think there is a reliable way without using DOM, but I recommend that you create as little DOM as possible, either by reusing it or deleting it straight after you create it. Note that appending values to a cache variable is not adding anything to DOM, only adding new tags using document.createElement(), node.innerText = blah and node.appendChild();
thats a pitty! i will make the cache as a object! i will continue searching for a sulution that can calculate the text size without appending it to the DOM i think that makes it mutch faster! how to they do it on google docs. because that stays fast when you copy a huge text in it.
0

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.)

1 Comment

Thx for making this peace of code but its verry important that it works on the following browsers!: IE7 of higher, FireFox, Chrome, Safari. but I will try to fix that!:) Thank you verry mutch!:)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.