Log in

View Full Version : help altering mootools rating system to update database



thenajsays
11-09-2009, 10:24 PM
im trying to add a star rating system to a website. id like to do something elegant graphically instead of just using a drop down... the javascript framework im using is mootools and i found a great rating system here (http://birijan.com.np/?q=mootools+star+rating), but have no idea how to adjust it so that it updates the database with the new rating vote from the user and it calculates the new average rating.

the way i have the database set up for this is with the following fields:
id (the rating's unique id)
listingid (the listing that the rating corresponds to)
userid (the user that entered the rating)
rating (the rating itself)

i use php to communicate with a mysql database.
the file im going to write will check to see if there is already a rating entered in from the logged in user. if there is, it will update it. if not, it will insert it, then it will calculate the average of all votes for that listing (rounded up) and return the new rating to the page and set the stars to reflect that rating... ive tweaked the code a bit to represent a 5 star system instead of a 10 star system and also so it can be used multiple times on a page.

heres what ive been playing with:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Mootools Simple Star Rating</title>
<script type="text/javascript" src="mootools.js"></script>
<link rel="stylesheet" type="text/css" href="star-rating.css" />
</head>
<body>
<ul id="rate1" class="normal rating fourstar">
<li title="1" class="rate one"><a href="javascript://" title="1 Star">1</a></li>
<li title="2" class="rate two"><a href="javascript://" title="2 Stars">2</a></li>
<li title="3" class="rate three"><a href="javascript://" title="3 Stars">3</a></li>
<li title="4" class="rate four"><a href="javascript://" title="4 Stars">4</a></li>
<li title="5" class="rate five"><a href="javascript://" title="5 Stars">5</a></li>
</ul>
<ul class="featured rating fivestar">
<li title="1" class="rate one"><a href="javascript://" title="1 Star">1</a></li>
<li title="2" class="rate two"><a href="javascript://" title="2 Stars">2</a></li>
<li title="3" class="rate three"><a href="javascript://" title="3 Stars">3</a></li>
<li title="4" class="rate four"><a href="javascript://" title="4 Stars">4</a></li>
<li title="5" class="rate five"><a href="javascript://" title="5 Stars">5</a></li>
</ul>
<script>
$$('.rate').each(function(element,i){
element.addEvent('mouseup', function(){
var myStyles = ['nostar', 'onestar', 'twostar', 'threestar', 'fourstar', 'fivestar'];
myStyles.each(function(myStyle){
if(element.getParent().hasClass(myStyle)){
element.getParent().removeClass(myStyle)
}
});
myStyles.each(function(myStyle, index){
if(index == element.title){
element.getParent().toggleClass(myStyle);
alert(index);
}
});

});
});

</script>
</body>
</html>

and the css:

/* star rating code - use lists because its more semantic */
/* No javascript required */
/* all the stars are contained in one matrix to solve rollover problems with delay */
/* the background position is just shifted to reveal the correct image. */
/* the images are 16px by 16px and the background position will be shifted in negative 16px increments */
/* key: B=Blank : O=Orange : G = Green * /
/*..... The Matrix ....... */
/* colours ....Background position */
/* B B B B B - (0 0)*/
/* G B B B B - (0 -16px)*/
/* G G B B B - (0 -32px)*/
/* G G G B B - (0 -48px)*/
/* G G G G B - (0 -64px)*/
/* G G G G G - (0 -80px)*/
/* O B B B B - (0 -96px)*/
/* O O B B B - (0 -112px)*/
/* O O O B B - (0 -128px)*/
/* O O O O B - (0 -144px)*/
/* O O O O O - (0 -160px)*/


/* the default rating is placed as a background image in the ul */
/* use the background position according to the table above to display the required images*/
.rating{
width:80px;
height:16px;
margin:0 0 20px 0;
padding:0;
list-style:none;
clear:both;
position:relative;
}
.normal{background: url(star-bluebk.gif) no-repeat 0 0;}
.featured{background: url(star-goldbk.gif) no-repeat 0 0;}
/* add these classes to the ul to effect the change to the correct number of stars */
.nostar {background-position:0 0}
.onestar {background-position:0 -16px}
.twostar {background-position:0 -32px}
.threestar {background-position:0 -48px}
.fourstar {background-position:0 -64px}
.fivestar {background-position:0 -80px}
ul.rating li {
cursor: pointer;
/*ie5 mac doesn't like it if the list is floated\*/
float:left;
/* end hide*/
text-indent:-999em;
}
ul.rating li a {
position:absolute;
left:0;
top:0;
width:16px;
height:16px;
text-decoration:none;
z-index: 200;
}
ul.rating li.one a {left:0}
ul.rating li.two a {left:16px;}
ul.rating li.three a {left:32px;}
ul.rating li.four a {left:48px;}
ul.rating li.five a {left:64px;}

ul.rating li a:hover {
z-index:2;
width:80px;
height:16px;
overflow:hidden;
left:0;
}
ul.normal li a:hover { background: url(star-bluebk.gif) no-repeat 0 0}
ul.featured li a:hover { background: url(star-goldbk.gif) no-repeat 0 0}
ul.rating li.one a:hover {background-position:0 -176px;}
ul.rating li.two a:hover {background-position:0 -192px;}
ul.rating li.three a:hover {background-position:0 -208px}
ul.rating li.four a:hover {background-position:0 -224px}
ul.rating li.five a:hover {background-position:0 -240px}

i havent even been able to get the system to average the current rating and the new rating... HELP!!!

thenajsays
11-10-2009, 03:44 AM
a lil more info... i know how to structure an ajax server request, both traditionally and via mootools... its making this code dynamic that im having a problem with

thenajsays
11-10-2009, 10:09 PM
ok, ive made some serious headway... it updates the database and i know it has the ability to update the rating correctly... for some reason its not and i cant quite figure out what im missing... here is the javascript:

// JavaScript Document
var ratequest

function rateIt(id, rating){
ratequest=GetXmlHttpObject();
addId = "add" + id;
if (ratequest==null){
alert ("Your browser does not support AJAX!");
return;
}
var url="ajax/rating.php";
url=url+"?id=" + id;
url=url+"&rating=" + rating;
ratequest.onreadystatechange=stateChanged;
ratequest.open("GET",url,true);
ratequest.send(null);
return newRate;
}

function stateChanged(){
if (ratequest.readyState==4){
newRate = ratequest.responseText;
}
}

function GetXmlHttpObject(){
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari
return new XMLHttpRequest();
}
if (window.ActiveXObject){
// code for IE6, IE5
return new ActiveXObject("Microsoft.XMLHTTP");
}
return null;
}
$$('.rate').each(function(element,i){
element.addEvent('mouseup', function(){
var newPosition = rateIt((element.getParent().get('id').replace('rate','')), parseInt(element.title));
var myStyles = ['nostar', 'onestar', 'twostar', 'threestar', 'fourstar', 'fivestar'];
myStyles.each(function(myStyle){
if(element.getParent().hasClass(myStyle)){
element.getParent().removeClass(myStyle);
}
});
myStyles.each(function(myStyle, index){
if(index == newPosition){
element.getParent().toggleClass(myStyle);
}
});
});
});

and the php file is connects to:

<?php
session_start();
include("../lib/login.php");
login();
$username = $_SESSION['user'];
$listingid = $_GET['id'];
$rating = (int)$_GET['rating'];

$query = "SELECT COUNT(rating) FROM ratings WHERE listingid = '$listingid' AND userid = '$username'";
$result = mysql_query($query) or die(mysql_error());
$row = mysql_fetch_array($result) or die(mysql_error());

$totrecords = $row[0];

if($totrecords == 0){
$query = "INSERT INTO ratings (listingid, userid, rating) VALUES ('$listingid', '$username', '$rating')";
$result = mysql_query($query) or die(mysql_error());
}
else{
$query = "UPDATE ratings SET listingid = '$listingid', userid = '$username', rating = '$rating' WHERE listingid = '$listingid' AND userid = '$username'";
$result = mysql_query($query) or die(mysql_error());
}

$query = "SELECT rating FROM ratings WHERE listingid ='$listingid'";
$result = mysql_query($query);
//$row = mysql_fetch_array($result, MYSQL_ASSOC);
$allratings = array();
$i=0;
while($row = mysql_fetch_array($result, MYSQL_ASSOC)){
$allratings[$i] = $row['rating'];
$i++;
}
$num_of_ratings = count($allratings);
$rating = ceil(array_sum($allratings) / $num_of_ratings);

echo $rating;

?>

what happens is the first time its clicked, it will display the image for no starts... then the second time its clicked, it will show what it should have shown the first time... and so on and so forth... anyone see something im not?

thenajsays
11-13-2009, 07:29 PM
SOLVED

$$('.rate').each(function(element,i){
element.addEvent('mouseup', function(){
var myStyles = ['nostar', 'onestar', 'twostar', 'threestar', 'fourstar', 'fivestar'];
var newPosition;
myStyles.each(function(myStyle){
if(element.getParent().hasClass(myStyle)){
element.getParent().removeClass(myStyle);
}
});
var rateIt = new Request({
url: 'ajax/rating.php',
link: 'chain',
method: 'get',
data: {
'id': element.getParent().get('id').replace('rate',''),
'rating': parseInt(element.title),
ajax: 1
},
onSuccess: function(response){
myStyles.each(function(myStyle, index){
if(index == response){
element.getParent().toggleClass(myStyle);
}
});
}
}).send();
});
});