Reputation: 7
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(" ", " ");
//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
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
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
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