Tooltip w CSS
12 grudnia 2005
Wszędzie w Internecie widzi się przykłady poradników jak zrobić etykietkę narzędziową dla hiperłącza w CSS. Przykład sprowadza się do ukrycia elementu linka i jego pokazaniu po nakierowaniu myszą, w czym pomaga stan :hover.
Przykładowa składnia:
<a class="tooltip" href="opis.html">Opis linka<dfn>Tooltip</dfn></a>
Użyłem elementu <dfn/>, ponieważ zwykły <span/> nic nie mówi o znaczeniu tego tekstu. Także po wyłączeniu CSS niektóre przeglądarki pokażą tekst w elemencie dfn czcionką pochyłą.
Możemy się domyślić co należy zrobić. Standardowo ukryć element <dfn/> przez display: none. I dodać regułę .tooltip:hover dfn ustawiającą <dfn/> jako display: block; Możemy zawsze poprawić wygląd etykietki i ją spozycjonować, żeby swobodnie pływała sobie nad dokumentem.
Natomiast ten sposób nie działa w IE. Dla niego postanowiłem wykonać operacje na drzewie DOM przy użyciu JavaScript. Dodałem do CSS-a po przecinku kolejny selektor:
.tooltip:hover dfn, .tooltiph dfn
Będę chciał zmienić klasę linka nakierowanego myszą po zdarzeniu mouseover. Można oczywiście dodać od razu w HTML-u takie atrybuty do linków, ale jest to bardzo niewygodne i niezalecane. Tak jak CSS służy do opisywania wyglądu, tak JavaScript zachowania i powinny być to w 99% przypadków oddzielne pliki.
Wykorzystam znowu magiczny komentarz warunkowy dla IE:
<!--[if lt IE 7]><script src="ietooltips.js" type="text/javascript"></script><![endif]-->
Dodam w ten sposób do dokumentu odnośnik do mojego skryptu dla Internet Explorera, nie mieszając nic w przeglądarkach bardziej zgodnych ze standardami.
Co należy zrobić? Pobrać wszystkie linki o klasie tooltip do tablicy, przelecieć po niej pętlą i dodać obsługę zdarzeń myszy. Można skorzystać z getElementsByTagName('a') i sprawdzać czy className nie równa się tooltip, ale ja wolałem użyć gotowej funkcji pobierającej od razu wszystkie elementy o klasie tooltip. Dlaczego? Zawsze istnieje możliwość, że będziemy chcieli zastosować etykietkę także dla zwyczajnego tekstu i po prostu dodamy strukturę, nie musząc walczyć znowu z zachowaniem.
document.getElementsByClassName = function(className) {var children = document.getElementsByTagName('*') || document.all;var elements = new Array();for (var i = 0; i < children.length; i++) {var child = children[i];var classNames = child.className.split(' ');for (var j = 0; j < classNames.length; j++) {if (classNames[j] == className) {elements.push(child);break;}}}return elements;}
Funkcja opisywania zdarzeń wygląda tak:
function ieTooltips() {var tiplinks = document.getElementsByClassName('tooltip');for (var i = 0; i < tiplinks.length; i++) {tiplinks[i].onmouseover = function() { this.className += ' tooltiph' }tiplinks[i].onmouseout = function() { this.className = 'tooltip'; }}}
Pierwsza linijka to pobranie do tablicy wszystkich elementów o klasie tooltip. Następnie w pętli dodajemy zdarzenie onmouseover i onmouseout, korzystając z funkcji lokalnej i obiektu this, odnoszącego się do aktualnego elementu (linka). Po mouseover dopisujemy klasę tooltiph, po mouseout resetujemy nazwę klasy.
Na koniec wypada wykonać zgrabnie funkcję po załadowaniu dokumentu. Aby kod był na wysokim poziomie, skorzystajmy z funkcji dodawania zdarzeń do dokumentu:
function addEvent(obj, evType, fn) {if (obj.attachEvent) {var r = obj.attachEvent("on" + evType, fn);return r;}else {return false;}}
Zrezygnowałem ze sprawdzania, czy agent użytkownika obsługuje addEventListener, bo kod jest pisany tylko pod Internet Explorera 6 i niższe. No ale korzystamy z tej funkcji, aby zakończyć plik:
addEvent(window, "load", ieTooltips);
I już. Strona z przykładem działania.
O wiele lepszy sposób na uporanie się z problemem nie działania standardowego tooltipa w IE rozpisał Wassago.


