Es gibt ein paar Probleme mit Ihrem Code.
- Warum
/ 5
? Die Breite der Zeichen hängt ab von font-family
y font-size
.
- Sie müssen entkommen
str
in der Kurzbezeichnung (andernfalls wird der Code durch ein " ungültig).
diff
wird nicht deklariert und landet im globalen Bereich
- Le site
substring
sollte so nicht funktionieren. Welchen Browser verwenden Sie?
hidden
ist kein gültiger Wert von style.display
. Um sie auszublenden, sollten Sie den Wert none
aber dann berechnet der Browser nicht die offsetWidth
. Verwenden Sie style.visibility="hidden"
stattdessen.
- Die Suche nach der richtigen Länge ist sehr ineffizient.
- Muss entkommen
</abbr>
"
Ich habe ihn für Sie umgeschrieben und Folgendes hinzugefügt className
Sie können also einen Stil verwenden, um die font-family
y font-size
. Herr Fooz schlug vor, die gesamte Zeichenfolge mit einem Mouseover anzuzeigen. Das ist nicht notwendig, da moderne Browser dies für Sie tun (getestet mit FF, IE, Opera und Chrome)
function fitStringToSize(str,len,className) {
var result = str; // set the result to the whole string as default
var span = document.createElement("span");
span.className=className; //Allow a classname to be set to get the right font-size.
span.style.visibility = 'hidden';
span.style.padding = '0px';
document.body.appendChild(span);
// check if the string don't fit
span.innerHTML = result;
if (span.offsetWidth > len) {
var posStart = 0, posMid, posEnd = str.length;
while (true) {
// Calculate the middle position
posMid = posStart + Math.ceil((posEnd - posStart) / 2);
// Break the loop if this is the last round
if (posMid==posEnd || posMid==posStart) break;
span.innerHTML = str.substring(0,posMid) + '…';
// Test if the width at the middle position is
// too wide (set new end) or too narrow (set new start).
if ( span.offsetWidth > len ) posEnd = posMid; else posStart=posMid;
}
//Escape
var title = str.replace("\"",""");
//Escape < and >
var body = str.substring(0,posStart).replace("<","<").replace(">",">");
result = '<abbr title="' + title + '">' + body + '…<\/abbr>';
}
document.body.removeChild(span);
return result;
}
Bearbeiten: Bei weiteren Tests habe ich ein paar Fehler gefunden.
-
Ich habe Math.ceil
anstelle der vorgesehenen Math.floor
(Ich mache dafür Folgendes verantwortlich dass Englisch nicht meine Muttersprache ist Sprache ist)
-
Wenn der Eingabe-String html-Tags enthielt hätte, wäre das Ergebnis undefiniert (es ist nicht gut, ein Tag in der Mitte abzuschneiden der Mitte abzuschneiden oder offene Tags zu lassen)
Verbesserungen:
- Die Zeichenkette, die an allen Stellen in den Span kopiert wird, muss entschlüsselt werden. Sie können weiterhin html-Einträge verwenden, aber es sind keine Tags erlaubt (
<
y >
wird angezeigt)
- Umgeschrieben wurde die
while
-Anweisung (es ist eine etwas schneller, aber der Hauptgrund war es, den Fehler zu beseitigen, der der zusätzliche Runden verursachte und um die die Break-Anweisung loszuwerden)
- Umbenennung der Funktion in
fitStringToWidth
Version 2:
function fitStringToWidth(str,width,className) {
// str A string where html-entities are allowed but no tags.
// width The maximum allowed width in pixels
// className A CSS class name with the desired font-name and font-size. (optional)
// ----
// _escTag is a helper to escape 'less than' and 'greater than'
function _escTag(s){ return s.replace("<","<").replace(">",">");}
//Create a span element that will be used to get the width
var span = document.createElement("span");
//Allow a classname to be set to get the right font-size.
if (className) span.className=className;
span.style.display='inline';
span.style.visibility = 'hidden';
span.style.padding = '0px';
document.body.appendChild(span);
var result = _escTag(str); // default to the whole string
span.innerHTML = result;
// Check if the string will fit in the allowed width. NOTE: if the width
// can't be determined (offsetWidth==0) the whole string will be returned.
if (span.offsetWidth > width) {
var posStart = 0, posMid, posEnd = str.length, posLength;
// Calculate (posEnd - posStart) integer division by 2 and
// assign it to posLength. Repeat until posLength is zero.
while (posLength = (posEnd - posStart) >> 1) {
posMid = posStart + posLength;
//Get the string from the beginning up to posMid;
span.innerHTML = _escTag(str.substring(0,posMid)) + '…';
// Check if the current width is too wide (set new end)
// or too narrow (set new start)
if ( span.offsetWidth > width ) posEnd = posMid; else posStart=posMid;
}
result = '<abbr title="' +
str.replace("\"",""") + '">' +
_escTag(str.substring(0,posStart)) +
'…<\/abbr>';
}
document.body.removeChild(span);
return result;
}