devblog, portfolio

movie producer, zend framework, php, jquery pluginy



jQuery, HTML5: Tooltips

Ponad rok temu opublikowałem artykuł o tym, jak stworzyć przy pomocy javaScript i biblioteki jQuery skrypt generujący tzw. tooltips, czy ramki informacyjne w okolicach kursora. Wtedy korzystaliśmy z atrybutu name jako "pojemnika" na dane. Teraz, kiedy standard HTML5 jest bardziej popularny, dostajemy nowe możliwość przechowywania danych. Stworzymy więc bardziej zaawansowany system wyświetlania podpowiedzi ekranowych korzystający z jquery i atrybutów data-*, dodanych do standardu HTML5.

Atrybuty data-*

Najpierw zastanówmy się, jakie atrybuty data-* będą nam potrzebne. Jeden z pewnością będzie decydował o treści powiadomienia. Będzie to element obowiązkowy. Możemy dodać kilka atrybutów data-*, które nie będą obowiązkowe. Ja, dodałem atrybut pozwalający na dodanie klas do konkretnego powiadomienia.

Aby atrybuty jednoznacznie wskazywały na swoje przeznaczenie, nazwiemy je wg. następującego schematu: data-tooltip-[dodatkowy_parametr]. Dla treści powiadomienia będzie to data-tooltip, dla klas: data-tooltip-class.

Pobieranie wartości atrybutów data-*

W jQuery od kilku wersji jest zaimplementowana metoda data (wcześniej attrData), która pozwala na pobieranie wartości atrybutów data-*.

Aby np. pobrać zawartość data-tooltip wpiszemy:

$('element').data('tooltip');

Do pobrania data-tooltip-class, możem przekazać nazwę w sposób tradycyjny:

$('element').data('tooltip-class');

lub korzystając z notacji "wielbłądziej":

$('element').data('tooltipClass');

Dlaczego HTML5?

Niewątpliwą zaletą tego rozwiązania jest pełna zgodność ze standardami. Korzystając ze standardów XHTML 1.*, nie mogliśmy dodawać dowolnych atrybutów do tych elementów, do których chcieliśmy. Specyfikacje tych standardów nie przewidują również żadnych atrybutów mogących przechowywać dane. Do części elementów nie mogliśmy więc dodać powiadomień tooltips, ponieważ standard nie zezwalał na korzystanie tam z atrybutu name. HTML5 udostępnia atrybuty data-*, która dają nam mnóstwo możliwości.

Zaczynamy!

Na samym początku, w nowym pliku tooltips.js, zdefiniujemy trochę zmiennych i stworzymy zdarzenie ready, dla obiektu document:

var sWidth = screen.width;
var xMove = 20;
var yMove = -25;
var tipWidth;
var speed = 100;
$(document).ready(function() {
  //kod
}

Na początku wyjaśnię, co znaczy każda z wyżej zdefiniowanych zmiennych:

  • sWidth - przechowuje szerokość ekranu użytkownika strony (w px)
  • xMove - przechowuje wartość o jaką zostanie przesunięte względem kursora, w poziomie, powiadomienie 
  • yMove - przesunięcie powiadomienia w pionie
  • tipWidth - będzie zawierała szerokość powiadomienia
  • speed - czas, w milisekundach, jaki będą trwały animacje pojawiania się i znikania powiadomienia

Cały kod, który będziemy teraz tworzyć, umieścimy wewnątrz napisanej funkcji.

Najpierw zabierzmy się więc za stworzenie bloku div#tooltip, który będzie powiadomieniem:

var $tip = $('<div id="tooltip"></div>')
.css({
position: 'absolute',
zIndex: 10,
top: 0,
left: 0
})
.appendTo('body')
.hide();

Od razu definujemy odpowiedni styl, żeby nie trzeba tego było robić w arkuszu css. Wstawiamy blok do sekcji body i ukrywamy.

Teraz czas na znalezienie wszystkich elementów, które posiadają atrybut data-tooltip.

var $items = $('*[data-tooltip]');

Tworzymy współrzędne

Teraz napiszemy funkcję, która będzie ustawiała pozycję powiadomienia na ekranie:

var setPosition = function(e) {
var posX = e.pageX;
var posY = e.pageY;

if (posX + tipWidth + xMove < sWidth - 10) {
$tip
.css('left',posX + xMove);
} else {
$tip
.css('left',posX - tipWidth - xMove);
}

if (posY + yMove > 10) {
$tip
.css('top',posY + yMove);
} else {
$tip
.css('top',posY - yMove);
}
}

Argumentem przekazywanym do funkcji jest obiekt event. Wewnątrz pobieramy z niego współrzędne zdarzenia do zmiennych posX i posY. Dalej pojawiają się krótkie algorytmy sprawdzające czy powiadomienie nie będzie zbyt bliko prawej lub górnej krawędzi ekranu.

Pokazywanie i chowanie powiadomień

Teraz tworzymy odpowiednie zdarzenia, które będą pokazywały, chowały i przemieszczały powiadomienie.

$items
.mouseenter(function(e) {
var text = $(this).data('tooltip');
$tip.html(text);
tipWidth = $tip.width();
setPosition(e);
var cls = $(this).data('tooltipClass');
$tip.removeClass();
if (cls)
$tip.addClass(cls);
$tip
.fadeIn(speed);
})
.mouseout(function() {
$tip
.fadeOut(speed);
})
.mousemove(function(e) { setPosition(e); });

Przy wejściu myszy na obiekt, który posiada atrybut data-tooltip, pobierana jest wartość tego argumentu i wstawiana do bloku powiadomienia. Następnie do zmiennej globalnej przypisywana jest szerokość powiadomienia. Następnie za pomocą stworzonej wcześniej funkcji ustalamy pozycję powiadomienia na ekranie.

Kolejnym krokiem jest pobranie z atrybutu data-tooltip-class, jeśli taki istnieje, nazw klas, które zostaną dodane do powiadomienia. Najpierw czyścimy za pomocą metody removeClass wszystkie klasy, które zostały dodane wcześniej. Następnie, jeśli mieliśmy zdefiniowane jakieś klasy, dodajemy je do bloku div#tooltip. Ostatnim działaniem funkcji dla tego zdarzenia jest wyświetlenie powiadomienia. Aby wyglądało to bardziej efektowanie, korzystamy ze stopniowego pojawiania się obiektu na ekranie. Wykorzystujemy tutaj zmienną speed, aby określić, jak długo ma trwać animacja.

Kolejnym zdarzeniem, na które musimy się przygotować, jest opuszczenie przez kursor danego obiektu. Tworzymy więc funkcję wykorzystującą metodę fadeOut dla zdarzenia mouseout.

Aby nasze powiadomienie przemieszczało się obok kursora myszy, musimy jeszcze wykonywać funkcję setPosition, przy każdym ruchu myszy. Na koniec więc tworzymy obsługę zdarzenie mousemove.

Teraz nasz skrypt jest już gotowy. Jego demo można zobaczyć tutaj. Kod skryptu jest dostępny na listingDump.

Dodaj komentarz »