Sistem simplu de votare (rating)
În urmă cu câţiva ani s-a făcut mare tam tam cu web 2.0. Internetul s-a reinventat, gradul de implicare al utilizatorului a crescut, iar tehnologiile au început să fie folosite la adevărata loc capacitate. Dacă înainte de 2003-2004 termenul de aplicaţie web nu exista decât pe hârtie (probabil), după 2004 google a dat startul cu binecunoscutul gmail, ducând web mailul la un nivel la care hotmail sau yahoo! nici nu visau (începând de la organizarea mesajelor – care între noi fie vorba, a fost preluată de microsoft în office 2010 – şi terminând cu capacitatea de stocare).
Ce a reprezentat această revoluţie 2.0? În principiu, modul în care utilizatorul final interacţionează cu un site. Astfel au apărut wikipedia (un site unde utilizatorii pot scrie articole), youtube (unde utilizatorii generează conţinutul) sau blogurile (unde vizitatorii pot comenta pe marginea unui articol). O altă funcţie care a apărut pe multe site-uri sunt voturile. Steluţele alea mici prin care apreciezi calitatea articolului sau a filmului postat. Şi cum sunt mulţi care nu ştiu să le folosească, m-am hotărât să scriu un mic articol. Metoda mea mi se pare cea mai curată (din punct de vedere al codului folosit) din cele existente. De asemenea, îţi voi arăta şi cum să faci un request ajax (se poate să vorbim de web 2.0 fără să amintim de ajax?
) pentru a trimite serverului ce a votat utilizatorul şi să returnezi un mesaj din partea serverului folosindu-te de JSON. Desigur, va trebui să faci procesarea voturilor pe server, cu limbajul preferat (php, asp, ruby etc) deoarece cunoştinţele mele de programare server side sunt destul de limitate.
Avem nevoie de o imagine cu „stările” steluţelor (pot fi frunze, pisici, pahare, etc). De ce trei? Una pentru background (cea albă), una pentru hover (cea galbenă) şi una pentru a arăta votul curent (cea roşie). Desigur, dimensiunile rămân la discreţia fiecăruia, ajustându-le în funcţie de necesităţi. De asemenea, se pot folosi şi trei imagini separate, chiar dacă nu este recomandat.
Folosind această imagine (şi încă una, mai mare), îţi voi arăta cum să încropeşti rapid un sistem de vot foarte simplu.
Markup
Fie că vrei să faci un sistem de votare, fie că vrei doar să afişezi media voturilor, markup-ul e acelaşi: două span-uri :
<span class="rating"><span style="width:25%"></span></span> <span class="rating small"><span style="width:52%"></span></span>
Am specificat width inline din motive de… afişare. Fiecare stea înseamnă 20%. Astfel, trei stele înseamnă 60%, patru 80%, două 40% şamd.
Css-ul în schimb, e un pic mai lung de atât:
.rating,
.rating span {
float:left;
height:64px;
width:320px;
background:url(../images/stars.png) repeat-x left top;
margin-right:1em;
}
.rating.small,
.rating.small span {
height:16px;
width:80px;
background-image:url(../images/stars_mici.png)
}
.rating span,
.rating.small span {
float:none;
display:block;
height:64px;
background-position:left -129px
}
.rating.small span {
height:16px;
background-position:left -32px
}
Ce se întâmplă?
.rating & .rating span:- Setăm fie
floatfiedisplay:blockpentru elementul ce conţine stelele. Astfel, putem specifica şi dimensiunile elementului - Setăm înalţimea unei stele şi lăţimea a cinci stele.
- Setăm imaginea de fundal
.rating.small & .rating.small span- Fiind vorba de stele ceva mai mici, specificăm alte dimensiuni şi altă imagine
Cum votăm?
Avem două posibilităţi:
1) ne complicăm cu ceva cod html
2) ne complicăm cu ceva cod js ce injectează html
Mie îmi place mai mult cea de-a doua variantă. Prin urmare, modificăm puţin markup-ul iniţial în:
<span class="rating" id="stars-1"><span style="width:25%"></span></span>
S-a aduăugat id-ul din motive de… identificare. Vrem să trimitem serverului ce ID are fiecare stea. De aici, începe distracţia cu javascript
var removeThanks ='';
$('.rating:not(.ignore)').each(function(){
var t = $(this);
for(var i=1;i<=5;i++){
$(document.createElement('a')).attr('href', '#').addClass('vot-'+i).appendTo(t);
}
t.addClass('active').find('a').click(function(){
$.ajax({
type: "GET",
url: "vot.php",
data: { nota:t.find('a').index(this), id:t.attr('id') },
dataType:'json',
cache: false,
success: function(data){
t.addClass('votat').find('span').width(data.votNou+'%');
window.clearTimeout(removeThanks);
$('.thanksForVoting').remove();
$(document.createElement('div')).addClass('thanksForVoting').css({
left:t.offset().left+t.width(),
top:t.offset().top
}).text(data.raspuns).appendTo('body');
removeThanks = window.setTimeout(function(){
$('.thanksForVoting').fadeOut(function(){$(this).remove()})
}, 2000);
}
});
return false;
});
});
Explicaţii
- Iterăm fiecare element cu clasa
ratingdar fără clasaignore. Astfel putem avea şi doar stelele afişate, fără să se întâmple nimic la click (de exemplu, stelele votate) - În fiecare element
ratinginjectăm cinci link-uri - La fiecare link ataşăm un event click ce va face un request ajax spre server. Deoarece linkul de vot nu variază (sau cel puţin aşa ar fi normal), acesta este specificat direct în codul JS (vot.php)
- Trimitem către server
ID-ul şi nota (de la 0 la 4) pe care s-a făcut click şi specificăm să primim datele înapoi în formatjson - Actualizăm nota curentă (lăţimea span-ului) şi afişam noua notă (dacă s-a modificat)
- Dacă nu vrei să afişezi niciun mesaj, te poţi opri aici, ai terminat
- Pentru a afişa un mesaj, cea mai la îndemână soluţie (de care poţi fi sigur că nu-ţi strică layout-ul) este de a insera un mic tooltip la sfârşitul documentului şi a-l poziţiona absolut. Prin urmare, îl construim, îl umplem (cu text, desigur), îl injectăm şi îl ascundem (şi ştergem) după X secunde. În cazul de faţă două
document.createEle… ce?
Folosind jQuery ai trei posibilităţi de a include elemente în DOM:
- $(‘<a></a>’).appendTo(element)
- $(‘<a/>’).appendTo(element)
- $(document.createElement(‘a’)).appendTo(element)
Chiar dacă cea de-a treia variantă pare mai lungă, este un pic mai rapidă. Am listat metodele în funcţie de viteză, prima fiind cea mai înceată.
Deoarece injectăm cod html nou, trebuie să-l stilizăm cu puţin CSS suplimentar (ce nu cred că are nevoie de explicaţii suplimentare):
.rating.active {
position:relative;
}
.rating.active a {
position:absolute;
left:0;
top:0;
height:100%;
background:url(../images/stars.png) repeat-x left -999px;
}
.rating.active a:hover {
background-position:left -64px
}
.rating.small.active a {
background:url(../images/stars_mici.png) repeat-x left -999px;
}
.rating.small.active a:hover {
background-position:left -16px;
}
.rating.active a.vot-1 {
width:20%;
z-index: 10;
}
.rating.active a.vot-2 {
width:40%;
z-index: 9;
}
.rating.active a.vot-3 {
width:60%;
z-index: 8;
}
.rating.active a.vot-4 {
width:80%;
z-index: 7;
}
.rating.active a.vot-5 {
width:100%;
z-index: 6;
}
.thanksForVoting {
position:absolute;
background:#fbffde;
z-index: 11;
white-space:nowrap;
border: 1px solid #999;
-moz-border-radius:3px;
-webkit-border-radius: 3px;
border-radius:3px;
padding:3px;
font-weight:700;
font-size:10px;
}
Răspunsul de la server (care am zis la început că este json) :
({
raspuns : 'Mulţumim pentru vot',
votNou : '50' // în procente
})
Atenţie! Nu uita să faci escape la ghilimelele din text (dacă foloseşti).
Cam asta e tot. Ţi-am arătat cum poţi face un simplu sistem de vot cu câteva linii (şi jQuery, desigur), fără să încarci inutil codul HTML. Dezavantajul MAJOR al acestei metode este că, în cazul în care nu se încarcă vreun fişier javascript, votul NU va funcţiona. Soluţia? Pui codul (da, cel pe care îl injectăm) direct în html

Niceee, o sa incerc si eu niste jucarele. Multumesc.
N-am sa mai comentez si la tutorialul asta pentru ca iar ma trezesc ca-mi sar ceilalti vizitatori in cap!
E ok facut, dar functioneaza cam ca si celelalte tutoriale existente pe net.
Eu l-as fi abordat altcumva, adica as fi pus in HTML un formular cu 5 inputuri de tip radio, care sa functioneze cand e JS dezactivat.
) si as fi postat formularul cu AJAX, fara reincarcarea paginii.
Daca JS-ul era activ, atunci as fi ascuns inputurile, as fi modificat probabil label-urile (sau le-as fi inlocuit cu tag-uri <a /> sa multumesc si puritanii care navigheaza pe site-uri doar cu tastatura