Oglasi

Izrada jednostavne ankete

Za početak, moramo nabaviti sve potrebe vanjske kodove koje ćemo koristiti:

Kako bi bilo lakše i jednostavnije editirati anketu, ona će biti napravljena kao html stranica koja će putem ajaxa komunicirati sa PHP kodom. Korištenjem html-a, anketu možete ubaciti u svoju stranicu vrlo jednostavno preko iframe-a ili javascripta.


Pa za početak, napravimo anketu:

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="poll-container">
<h3>Anketa</h3>
<form id="poll" action="poll.php" accept-charset="utf-8" method="post">
 
Odaberite svoj najdraži Javascript framework:
<input id="opt1" name="poll" type="radio" value="opt1" /><label for="opt1"> jQuery</label>
<input id="opt2" name="poll" type="radio" value="opt2" /><label for="opt2"> Ext JS</label>
<input id="opt3" name="poll" type="radio" value="opt3" /><label for="opt3"> Dojo</label>
<input id="opt4" name="poll" type="radio" value="opt4" /><label for="opt4"> Prototype</label>
<input id="opt5" name="poll" type="radio" value="opt5" /><label for="opt5"> YUI</label>
<input id="opt6" name="poll" type="radio" value="opt6" /><label for="opt6"> mootools</label>
<input type="submit" value="Glasaj" />
</form></div>

To je to što se forme tiće, sada slijedi PHP :)
Pošto koristimo ajax koji se bazira na Javascriptu, također moramo pripaziti šta će se desiti ukoliko korisnik nema uključen javascript. Tako da ćemo morati pokriti dvije mogućnosti, ukoliko je Javascript uključen potrebno je:

  • preuzeti podatke
  • provjeriti da li je jedinstven IP
  • spremiti podatke u našu malu bazu
  • vratiti json

Ukoliko podaci dolaze bez Javascripta, postupak je gotovo identičan, osim što ne vračamo json nego html stranicu:

  • preuzeti podatke
  • provjeriti da li je jedinstven IP
  • spremiti podatke u našu malu bazu
  • vratiti html

Za spremanje podataka ćemo koristiti malu skriptu koju je napravio Luke Plant, koja ustvari pretvara tekst datoteku u malu jednostavnu bazu.
Sada, trebamo kreirati polje sa odgovorima koje smo ponudili na izbor:

1
2
3
4
5
6
$options[1] = 'jQuery';  
$options[2] = 'Ext JS';  
$options[3] = 'Dojo';  
$options[4] = 'Prototype';  
$options[5] = 'YUI';  
$options[6] = 'mootools';

Naša “baza” radi na principu da koristi brojeve kao način prepoznavanja kolona, pa prema tome moramo definirati koja kolona predstavlja koji podatak:

1
2
3
define('OPT_ID', 0);  
define('OPT_TITLE', 1);  
define('OPT_VOTES', 2);

Nakon što naša PHP skripta krene u izvršavanje, moramo znati na koju stranicu se vračamo, pa nam treba i:

1
define('HTML_FILE', 'index.html');

Što se tiće naše “baze” trebamo uključiti flatfile.php i inicijalizirati objekt:

1
2
3
4
5
require_once('flatfile.php');  
$db = new Flatfile(); 
$db->datadir = 'data/';  //folder u kojem se nalaze txt datoteke
define('VOTE_DB', 'votes.txt');  //datoteka koja prema glasove
define('IP_DB', 'ips.txt'); //datoteka koja prema ip adrese

Razlika između ajax zahtjeva i običnog nam je u imenu varijable koju šaljemo preko GET metode. Ukoliko se radi o ajax-u, varijabla se zove “vote”, u protivnom je “poll”.

1
2
3
4
5
6
7
8
9
10
11
if (isset($_GET['poll'])) {
	$id = (int)$_GET['poll'];
	poll_submit($id);
}
else if (isset($_GET['vote'])) {
	$id = (int)$_GET['vote'];
	poll_ajax($id);
}
else {
	poll_default();
}

Ukoliko nema podataka niti u poll, niti u vote varijabli, znači da korisnik nije glasao i da mu možemo prikazati formu za glasanje ili rezultate ukoliko je glasao ranije. To nam obavlja poll_default funkcija.

1
2
3
4
5
6
7
8
9
10
11
12
function poll_default() {
  global $db;
 
  $ip_result = $db->selectUnique(IP_DB, 0, $_SERVER['REMOTE_ADDR']);
 
  if (!isset($_COOKIE['vote_id']) && empty($ip_result)) {
    print file_get_contents(HTML_FILE);
  }  
  else {
    poll_return_results($_COOKIE['vote_id']);
  }
}

Ova funkcija provjerava da li IP adresa s koje je posjetioc već postoji u našoj bazi i/ili da li postoji cookie sa glasom, te ovisno o tome prikazuje formu za glasanje ili rezultate. Ovime spriječavamo da korisnik 2 puta glasuje. Naravno, ukoliko se IP adresa promijeni i obriše se cookie, korisnik će moći ponovno glasati, ali je ovo sasvim dovoljna zaštita kako većina korisnika neće glasati više puta.

Sljedeća funkcija nam je poll_submit koja se koristi ukoliko je zahtjev došao bez javascripta.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
function poll_submit($id) {
 
	global $db;
	global $options;
 
  $id = str_replace("opt", '', $id);
 
  $ip_result = $db->selectUnique(IP_DB, 0, $_SERVER['REMOTE_ADDR']);
 
  if (!isset($_COOKIE['vote_id']) && empty($ip_result)) {
    $row = $db->selectUnique(VOTE_DB, OPT_ID, $id);
    if (!empty($row)) {
      $ip[0] = $_SERVER['REMOTE_ADDR'];
      $db->insert(IP_DB, $ip);
 
      setcookie("vote_id", $id, time()+31556926); // cookie traje godinu dana :)
 
      $new_votes = $row[OPT_VOTES]+1;
      $db->updateSetWhere(VOTE_DB, array(OPT_VOTES => $new_votes), new SimpleWhereClause(OPT_ID, '=', $id));
 
      poll_return_results($id);
    }
    else if ($options[$id]) {
      $ip[0] = $_SERVER['REMOTE_ADDR'];
      $db->insert(IP_DB, $ip);
 
      setcookie("vote_id", $id, time()+31556926); // cookie traje godinu dana :)
 
      $new_row[OPT_ID] = $id;
      $new_row[OPT_TITLE] = $options[$id];
      $new_row[OPT_VOTES] = 1;
      $db->insert(VOTE_DB, $new_row);
 
      poll_return_results($id);
    }
  }
  else {
    poll_return_results($id);
  }
}

Ova funkcija kao parametar prima ID odgovora na anketu (onaj iz poll varijable). Provjerava da li je tak korisnik već glasovao, te sprema glas ukoliko nije te poziva poll_return_results funkciju koja prikazuje rezultate.

S druge strane, funkcija poll_ajax također prima ID odgovora, ali ona vraća json objekt koji sadrži rezultate.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function poll_ajax($id) {
  global $db;
  global $options;
 
  $ip_result = $db->selectUnique(IP_DB, 0, $_SERVER['REMOTE_ADDR']);
 
  if (empty($ip_result)) {
 
    $ip[0] = $_SERVER['REMOTE_ADDR'];
    $db->insert(IP_DB, $ip);
    if ($id != 'none') {
      $row = $db->selectUnique(VOTE_DB, OPT_ID, $id);
      if (!empty($row)) {
        $new_votes = $row[OPT_VOTES]+1;
 
        $db->updateSetWhere(VOTE_DB, array(OPT_VOTES => $new_votes), new SimpleWhereClause(OPT_ID, '=', $id));
      }
      else if ($options[$id]) {
        $new_row[OPT_ID] = $id;
        $new_row[OPT_TITLE] = $options[$id];
        $new_row[OPT_VOTES] = 1;
        $db->insert(VOTE_DB, $new_row);
      }
    }
  }
 
  $rows = $db->selectWhere(VOTE_DB, new SimpleWhereClause(OPT_ID, "!=", 0), -1, new OrderBy(OPT_VOTES, DESCENDING, INTEGER_COMPARISON));
  print json_encode($rows);
}

Zadnja funkcija poll_return_results vraća HTML koji prikazuje rezultate glasovanja i koristi se u poll_default i poll_submit te je samo iz tog razloga odvojen (kako ne bi bilo ponavljanja koda).

Sada prelazimo na javascript, točnije jQuery. Javascript koji pokreće ovu anketu je ustvari vrlo jednostavan.
Kao prvo, imamo bindan gumb submit koji zove funkciju formProcess.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function formProcess(event){
  event.preventDefault();
 
  var id = $("input[@name='poll']:checked").attr("value");
  id = id.replace("opt",'');
 
  $("#poll-container").fadeOut("slow",function(){
    $(this).empty();
 
    votedID = id;
    $.getJSON("poll.php?vote="+id,loadResults);
 
    $.cookie('vote_id', id, {expires: 365});
    });
}

Šaljemo odabranu vrijednost preko JSON-a na server te istu tu spremamo u cookie kako bi ju mogli kasnije koristiti za provjeru.
Nakon nje, slijedi poziv funkciji animateResults koja radi onu fensi animaciju divova.

1
2
3
4
5
6
7
function animateResults(){
  $("#poll-results div").each(function(){
      var percentage = $(this).next().text();
      $(this).css({width: "0%"}).animate({
				width: percentage}, 'slow');
  });
}

Zadnja funkcija koju imamo je loadResults koju zovemo ukoliko smo našli već postojeći cookie sa glasom.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function loadResults(data) {
  var total_votes = 0;
  var percent;
 
  for (id in data) {
    total_votes = total_votes+parseInt(data[id][OPT_VOTES]);
  }
 
  var results_html = "<div id='poll-results'><h3>Rezultati ankete</h3>\n<dl class='graph'>\n";
  for (id in data) {
    percent = Math.round((parseInt(data[id][OPT_VOTES])/parseInt(total_votes))*100);
    if (data[id][OPT_ID] !== votedID) {
      results_html = results_html+"<dt class='bar-title'>"+data[id][OPT_TITLE]+"</dt><dd class='bar-container'><div id='bar"+data[id][OPT_ID]+"'style='width:0%;'>&nbsp;</div><strong>"+percent+"%</strong></dd>\n";
    } else {
      results_html = results_html+"<dt class='bar-title'>"+data[id][OPT_TITLE]+"</dt><dd class='bar-container'><div id='bar"+data[id][OPT_ID]+"'style='width:0%;background-color:#0066cc;'>&nbsp;</div><strong>"+percent+"%</strong></dd>\n";
    }
  }
 
  results_html = results_html+"</dl><p>Total Votes: "+total_votes+"</p></div>\n";
 
  $("#poll-container").append(results_html).fadeIn("slow",function(){
    animateResults();});
}

I zadnja napomena, zbog toga što je flatfile.php rađen u starijoj verziji PHP-a, moguće je javljanje Notice upozorenja kako neke konstante nisu definirane. Ovo neće pokvariti kod, samo vas obavještava da se 3-4 konstante koriste prije nego što su denifirane. Najjednostavnije je isključiti prikazivanje upozorenja na toj datoteci i to tako da na početak dodate error_reporting funkciju:

1
2
3
<?php
error_reporting(E_ALL ^ E_NOTICE);
/*

Komentari su onemogućeni.