W firmie pojawił się ostatnio problem przycinania tekstu. Wykonywanie go w trakcie generowania kodu HTML jest mało przyjazne, a co gorsza mało elastyczne, bo tekst lolita nie ma tej samej szerokości co wymówi przy tej samej liczbie znaków. Jak to polepszyć? CSS 3 zawiera text-overflow:ellipsis;, które automatycznie dodaje wielokropek (...), gdy tekst jest za długi. Problem w tym, że tę wersję obsługuje tylko IE6+, Safari i prawdopodobnie Konqueror (nie testowałem). Opera 9 ratuje nas własnym rozwiązaniem -o-text-overflow: ellipsis;. Ale co z Firefox?
Okazuje się, że Firefox 2 ani Firefox 3b1 nie obsługują wielokropka w CSS. Ktoś genialny [Firefox Ellipsis Hack](http://www.hedgerwow.com/360/dhtml/text_overflow/demo3.php] przypomniał sobie, że przecież Firefox obsługuje wielokropek w swoim interfejsie (choćby w about:config) i spróbował to wykorzystać. Niestety, rozwiązanie to wymaga odrobiny kodu JavaScript. Co więcej, rozwiązanie autora wymaga użycia Yui. Prezentowane poniżej rozwiazanie jest zlepkiem trzech rozwiązań - wspomnianej wcześniej sztuczki, funkcji Getelementsbyclassname z The Ultimate Getelementsbyclassname oraz trzech linijek kodu zaczerpniętych z biblioteki jQuery. Razem powstaje kod, który zajmuje 30 linii i nie wymaga zewnętrznych bibliotek. Do dzieła...
Kod HTML i CSS
<div id="e">
<span class="ellipsis">To jest bardzo długi tekst do przycięcia.
</div></span>
Ponieważ wszystko działa tylko wtedy, gdy element blokowy ma ustaloną szerokość, sam tekst umieszczamy w div. By ułatwić całą sztuczkę i zwiększyć jej elastyczność, sam tekst do przycięcia opakowujemy w span. Ponieważ przycinany tekst może zajmować tylko jedną linię, podejście to pozwala sterować tym, które fragmenty będą przycinane, a które nie (przykład znajduje się na CSS3 text).
Kod CSS również trudny nie jest i działa od razu we wszystkich przeglądarkach obsługujących wielokropek na poziomie CSS.
div#e {
width: 100px; /* Ściśle określona szerokość musi wystąpić, dla dodatkowo użyj table-layout: fixed. */
text-overflow: ellipsis; /* Dla IE i Safari. */
-o-text-overflow: ellipsis; /* Dla Opery. */
overflow: hidden; /* Wymagane, by działał ellipsis. */
border: 1px solid red; /* By ładnie widzieć granicę */
}
div#e span.ellipsis {
white-space: nowrap; /* Wymagane, by działał ellipsis. */
width:100%; /* Bez tego, w IE nie zadziała. */
}
/* Oba poniższe wpisy dotyczą Firefoxa i muszą wystąpić, by kod JS zadziałał poprawnie. */
div#e window{ width:100%; -moz-user-focus:normal; -moz-user-select:text; }
div#e description{ -moz-user-focus:normal; -moz-user-select:text; }
Na tym możemy zakończyć, jeśli nie interesuje nas Firefox. Ponieważ to nasza ulubiona (no, może akurat nie w tym temacie) przeglądarka, idźmy dalej...
Kod JavaScript
Poniższy kod wystarczy umieścić w dowolnym miejscu na stronie lub załadować z zewnętrznego pliku.
// Autorzy funkcji: Jonathan Snook (http://www.snook.ca/jonathan) i Robert Nyman (http://www.robertnyman.com)
function getElementsByClassName(oElm, strTagName, strClassName){
var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
strClassName = strClassName.replace(/\-/g, "\\-");
var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
var oElement;
for(var i=0; i<arrElements.length; i++){
oElement = arrElements[i];
if(oRegExp.test(oElement.className)){
arrReturnElements.push(oElement);
};
};
return (arrReturnElements);
};
// Właściwy kod powodujący magię wielokropka.
var _userAgent = navigator.userAgent.toLowerCase();
if (/mozilla/.test(_userAgent) && !/(compatible|webkit)/.test(_userAgent)) {
document.addEventListener( "DOMContentLoaded", function() {
var sNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
var xml = document.createElementNS(sNS , 'window');
var label = document.createElementNS(sNS, 'description');
label.setAttribute('crop','end');
xml.appendChild(label);
var e = getElementsByClassName(document,'span','ellipsis');
for (i in e) {
var xml2 = xml.cloneNode(true);
xml2.firstChild.setAttribute('value',e[i].textContent);
e[i].innerHTML = '';
e[i].appendChild(xml2);
};
}, false );
};
Kod będzie działał poprawnie dla wszystkich elementów span z przypisaną klasą ellipsis.
Podsumowanie
Generalnie wielokropek działa we wszystkich systemach całkiem przyjemnie, ale jako taki ma jedną wadę ogólną i jedną z wiązaną z Firefoxem:
- działa tylko dla fragmentów jednolinijkowych (nie jest dobry, gdy chcemy zużyć całe dostępne miejsce ograniczone zarówno szerokością, jak i wysokością (czyli mamy miejsce na 5 linijek, więc 4 wyświetlamy normalnie, ale 5 przycinamy). Użycie
spannie zapewni w tym momencie elastyczności z powodów opisanych w pierwszym akapicie. Jedyne rozwiązanie to JavaScript, ale o tym innym razem. - ponieważ rozwiązanie dla Firefox działa, używając zwykłego tekstu, nie możemy użyć w przycinanym tekście znaczników.