Tooltips

Deoarece mi s-a spus că scripturile scurte sunt utile, dar și pentru că am primit ceva cereri pentru acest subiect, m-am gândit să-ți arăt cum poți face tooltip-uri cu jQuery într-un mod foarte simplu. Îți voi arăta două feluri de tooltips: statice și cu conținutul preluat prin ajax.

De ce tooltips cu javascript? Primele motive ce-mi vin în cap sunt:

  1. Știi sigur că sunt afișate cum trebuie în toate browserele. Oricât de ciudat pare, atributul responsabil cu tooltips în browsere nu prea își face treaba. Sau cel puțin nu cum trebuie. Ba textul e trunchiat (dacă e prea lung), ba nu este afișat suficient de mult timp pentru a fi citit, ba e fontul prea mic, atributul title (căci despre el e vorba) se dovedește de multe ori insuficient pentru nevoile de zi cu zi.
  2. Le poți stiliza fix cum vrei tu. Le vrei negre, cu fundal semtransparent, și un glow subtil? Crezi că le poți face fără javascript? Mult succes!

Alternative

Înainte de a vedea cum poți face tooltips (într-un mod simplu, așa cum am făcut și până acum), hai să-ți prezit câteva alternative (în cazul în care chiar ți-e extrem de lene sau ești în criză de timp, sunt bune și astea):

Și alte câteva (zeci). Totul e să ai răbdare să le cauți. Oricum, cât timp ai pierde căutând și configurând un script pentru tooltip care habar n-ai cum funcționează și îți mănâncă și inutil de mult bandwidth-ul, ai putea sta cinci minute să încerci acest tutorial (care are o introducere mult prea mare :) )

Poți stiliza elementul în funcție de ce ai nevoie. De obicei, am folosit tooltips la mesaje scurte de ajutor (în pagină), prin urmare le stilizam fie cu o imagine cu litera „i” fie cu un semn al întrebării, tot imagine. De ce imagine? Simplu, pentru că arată mai bine :D

Tooltips statice

Varianta cea mai simplă este cea în care afișezi un tooltip în funcție de atributul title (sau alt, depinde ce preferi). Asta presupune un element cu o clasă și un titlu:

<a href="#" class="nTip" title="Tooltip de test">?</a>

Ca să fiu băiat bun, îți arăt cum poți face tot script sub forma unui mic plugin de jQuery. Da, e atât de simplu!

jQuery.fn.nTip = function() {
	$(document.createElement('div')).attr('id', 'nTipWrapper').appendTo('body');
	$(this).each(function(){
		var tooltipEl=$(this);
		tooltipEl.data('title', tooltipEl.attr('title')).removeAttr('title');
		tooltipEl.hover(function(e){
			$('#nTipWrapper').empty().html(tooltipEl.data('title')).css({
				left:e.pageX+20,
				top:e.pageY+20
			}).show();
			tooltipEl.bind('mousemove.nTip', function(el){
				if( Math.round($(window).width()/2) > el.pageX ) {
					$('#nTipWrapper').css({
						marginLeft:0
					});
				} else {
					$('#nTipWrapper').css({
						marginLeft:-$('#nTipWrapper').outerWidth()-20
					})
				}
				$('#nTipWrapper').css({
					left:el.pageX+20,
					top:el.pageY+20
				})
			});
		}, function(){
			tooltipEl.unbind('mousemove.nTip');
			$('#nTipWrapper').empty().hide();
		});
	});
};
$('.nTip').nTip();

Ce se întâmplă?

  1. jQuery.fn.nTip inițiază plugin-ul. nTip este numele pluginului (și îl poți schimba dacă nu îți place)
  2. Facem un div și îl inserăm în body. Așa cum am mai zis și în alt articol, această variantă e mai rapidă, dar se pare că în jQuery 1.4 va fi la fel de rapidă ca $('<div>')
  3. Iterăm fiecare element și îl atribuim variabilei tooltipEl
  4. Pentru a scoate tooltip-ul ce apare implicit, setăm .data('title') să aibe valoarea atributului title, după care ștergem atributul title
  5. La hover golim #nTipWrapper, îl poziționăm lângă elementul „victimă” (cel pentru care afișăm tooltip) și îl afișăm
  6. Acum urmează o treabă tare deșteaptă ce va mișca tooltip-ul după mouse și va poziționa tooltip-ul în partea stângă, în cazul în care elementul este prea în margine. Se numește namespaced events și ne permite să îi dăm un nume bindului. Astfel, dacă mai ai și alte event-uri pe elementul respectiv, nu va fi niciun conflict la unbind (citește mai jos).
  7. el.pageX și el.pageY reprezintă poziția cursorului la mousemove. În funcție de mousemove se schimbă și pageX, respectiv pageY. Aceeași metodă e folosită și la hover, un pic mai sus.
  8. La mouseout (a doua funcție din hover) ascundem și golim #nTipWrapper, după care facem unbind la eventul mousemove. De ce facem asta? Să evităm probleme de genul re-re-re-re-bind pentru un element :)
  9. Inițializăm plugin-ul pentru toți selectorii cu clasa .nTip.

Tooltips + ajax = Love

O variantă la tooltips statice sunt cele dinamice, preluate cu ajax. Asta înseamnă că poți afișa text formatat și stilizat după cum ai nevoie. În plus, poți avea un panou de control în care poți schimba fiecare tooltip într-un mod foarte simplu deoarece fiecărui tooltip îi este atribuit un ID din baza de date:

<a href="tooltip.php?id=1" class="nTip">?</a>

Observi acum că atributul title a dispărut iar href are o valoare reală, de care ne folosim. Parametrul trimis către tooltip.php este ID-ul menționat un pic mai sus. Codul javascript suferă mici modificări:

jQuery.fn.nTip = function() {
	if(!$('#nTipWrapper').length) {$(document.createElement('div')).attr('id', 'nTipWrapper').appendTo('body');}
	$(this).filter(function(){return $(this).data('hasTooltip') === true ? this : '';}).each(function(){
		var tooltipEl=$(this);
		tooltipEl.data('hasTooltip', true);
		tooltipEl.hover(function(e){
			$('#nTipWrapper').addClass('busy').empty().css({
				left:e.pageX+20,
				top:e.pageY+20
			}).show();
			if(typeof(tooltipEl.data('tooltip'))==='undefined') {
				$('#nTipWrapper').addClass('busy');
				$.ajax({
					type: "GET",
					url: tooltipEl.attr('href'),
					cache: false,
					success: function(data){
						tooltipEl.data('tooltip', data);
						$('#nTipWrapper').removeClass('busy').html(data);
					}
				});
			}else {
				$('#nTipWrapper').removeClass('busy').html(tooltipEl.data('tooltip'));
			}
			tooltipEl.bind('mousemove.nTip', function(el){
				if( Math.round($(window).width()/2) > el.pageX ) {
					$('#nTipWrapper').css({
						marginLeft:0
					});
				} else {
					$('#nTipWrapper').css({
						marginLeft:-$('#nTipWrapper').outerWidth()-20
					})
				}
				$('#nTipWrapper').css({
					left:el.pageX+20,
					top:el.pageY+20
				})
			});
		}, function(){
			tooltipEl.unbind('mousemove.nTip');
			$('#nTipWrapper').empty().hide();
		});
	});
};
$('.nTip').nTip();

Ce se întâmplă?

  1. La hover peste fiecare element, golim, poziționăm și afișăm #nTipWrapper. De asemenea îi adăugăm o clasă busy. Aceasta ne permite să stilizăm tooltip-ul pentru momentele în care se face request spre server. Spunem utilizatorului ce se întâmplă și, în plus, arată bine :P
  2. Dacă .data('tooltip') este nedefinit, facem un request ajax iar rezultatul îl introducem în tooltip și în .data('tooltip'). De ce se întâmplă asta? Pentru a evita câte un request la fiecare hover. Prin acest sistem de caching mărim viteza de răspuns a scriptului. Practic, după primul hover, tooltipul va funcționa fix ca cel static.
  3. Continuarea codului este explicată mai sus, la tooltip-urile statice (este folosit același cod)

Avantaje/dezavantaje/Când le folosești?

Metoda statică

Avantaje
  • Avantajul acestei metode: textul e disponibil imediat (metoda cu cererea AJAX implică și un timp de așteptare ce variază în funcție de server dar și de conexiunea utilizatorului);
  • Dacă – din varii motive – javascript-ul nu s-a încărcat, aceste tooltips funcționează în continuare fără probleme (desigur, nestilizate).
Dezavantaje
  • Textul va fi destul de sec, neputând să-i pui formatare (decât cu BBcode, dar asta e altă poveste);
  • Poți folosi doar texte scurte, pentru a nu încărca inutil pagina.
Când le folosești?

Când ai texte mici sau când target-ul site-ului sunt fie utilizatori cu conexiune slabă, fie cei cu dizabilități vizuale (deci cu js dezactivat)

Metoda dinamică (cu ajax)

Avantaje
  • Poți formata textul folosind taguri html;
  • Poți folosi texte oricât de lungi. Desigur, asta nu înseamnă să scrii un roman într-un tooltip :D
  • Poți administra toate tooltips dintr-un site într-un mod destul de ușor.
Dezavantaje
  • Fiecare tooltip înseamnă un request spre server. Fiecare request spre server înseamnă timp în plus;
  • Poți pune tooltip doar pe elemente de tip a (prin atributul href) sau img (prin atributul longdesc);
  • Fără javascript nu există niciun fel de tooltip.
Când le folosești?
  1. Când ai titluri mai lungi și nu vrei să încarci sursa paginii cu text aiurea;
  2. Când vrei să formatezi textul afișat în tooltip.

Concluzie

Š¢i-am arătat cum poți afișa tooltips ceva mai arătoase decât cele standard într-un mod extrem de simplu și foarte rapid. Dacă stau să mă gândesc și să fac o comparație între plugin-urile existente și ce am făcut eu, scriptul meu câștigă detașat la viteză și dimensiune. Desigur, sunt mult mai puține opțiuni, dar în momentul când lucrezi la un proiect trebuie să decizi ce primează: dimensiunea în kb sau opțiunile (de multe ori nefolosite!).

Poți să „go crazy” și stiliza fiecare tooltip în mod diferit, adăugând elementului #nTipWrapper câte o clasă diferită în funcție de elementul pentru care se afișează. De asemenea poți afișa tooltip-urile astfel încât să nu se „plimbe” după mouse. Cu puțină răbdare, desigur. :)

10 Comentarii to “Tooltips”

  1. 1. Imi place cum scrii tutoriale
    2. Misto adresa de RSS (feedburner) ti-ai ales
    3. Sa-mi bag piciorul in Click & Quote, ca am dat de vreo 3 ori din greseala. Am ticul de a selecta in timp ce citesc, sa urmaresc mai usor. Se pare ca acest tic si javascriptul tau intra in conflict:))

  2. Și uite așa am aflat și eu de namespaced events.

    Un tutorial complet și ușor de urmărit.

  3. Staicu Ionuț-Bogdan

    @Andrei:
    1) mă bucur
    2) știu :D
    3) well.. That’s a bummer. Dacă mai primesc încă cel puțin 2-3 plângeri îl scot. Până atunci… Îl consider util :)

    @scribu: abonează-te la feed (dacă nu ești deja abonat); o să mai afli și alte chestii cool :)

  4. Foarte util si interesant tutorialul. In legatura cu plangerile, poti mai adauga inca una. Si eu selectez textul cand citesc, iar la final am gasit jumate de post in textarea pt comentarii :)). Cred ca ar fi foarte utile si 2-3 tutoriale in engleza, aici sau pe dev.

  5. Dacă mai primesc încă cel puțin 2-3 plângeri îl scot.

    ia ghici ? ai primit si a 3a plangere. si eu selectez textul cand citesc :D

    Name

  6. Staicu Ionuț-Bogdan

    Gata, l-am scos :(

  7. De ce nu poate fi formatat textul la metoda statica? Eu am incercat cu strong si br si a mers….

  8. Staicu Ionuț-Bogdan

    @Alin: merge, nu zic că nu merge. Dar… Nu prea mai e valid :)

  9. Salut Ionut. Iti urmaresc blogul de ceva timp. Faci o treaba faina ;) Imi place. As avea si eu o intrebare: spune-mi, te rog, de unde as putea sa iau un tutorial sau orice o fi, sa fac un fel de “carte” virtuala (nu stiu daca m-ai inteles). Cum ar fi de exemplu ygsp.ro, sau macar o alternativa. Merci anticipat

  10. salut, imi plac foarte mult tutorialele tale ,te felicit, vreau sa-ti adresez o intrebare legat de tooltip,am facut un tooltip image cu css pe un site static si merge ok doar ca acelasi tooltip l-am pus pe wordpress si nu-mi afiseaza decat un simplu x in locul imagini, ai idee ce ar putea fi cauza?

Show trackbacks

Ți-a plăcut articolul? Lasă un comentariu!

You can insert code snippets using BBcode:
[js].[/js] [html].[/html] [php].[/php] [css].[/css]
You can also use some HTML tags:
<blockquote>.</blockquote> <code>.</code> <a href="">.</a> <strong>.</strong> <em>.</em>

windows apple dropbox facebook twitter