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!

Poți insera blocuri de cod folosind BBcode:
[js].[/js] [html].[/html] [php].[/php] [css].[/css]
Poți folosi și câteva tag-uri HTML:
<blockquote>.</blockquote> <a href="">.</a> <strong>.</strong> <em>.</em>