Is there a good tutorial / instructions for the CakeDC ratings plugin anywhere? I'm 4 hours in and still no end in site - the read-me is useless.
Here is some code that I used to get the ratings plugin working. It is all Ajax, so I added one hack to the RatingHelper to avoid showing a "Rate!" button, just add submit=>false to the options.
if ($options['createForm']) {
if (!empty($options['target']) && !empty($options['createForm']['url']) && !empty($options['createForm']['ajaxOptions'])) {
$ajaxOptions = array_merge(array('url' => $options['createForm']['url']), $options['createForm']['ajaxOptions']);
$result .= $this->Js->submit(__d('ratings', 'Rate!'), $ajaxOptions) . "\n";
$flush = true;
} elseif ( !isset($options['submit']) || !empty($options['submit']) ) {
if(empty($options['submit'])) {
$result .= $this->Form->submit(__d('ratings', 'Rate!')) . "\n";
} else {
$result .= $this->Form->submit($options['submit']) . "\n";
}
}
$result .= $this->Form->end() . "\n";
if ($flush) {
$this->Js->writeBuffer();
}
}
I have an index view that is showing a bunch of car models and I show an overall rating and the current users rating:
<?php foreach ($carmodels as $carmodel): ?>
<tr>
<td><?php echo h($carmodel['Carmodel']['id']); ?> </td>
<td><?php echo h($carmodel['Carmodel']['name']); ?> </td>
<td>
<?php echo $this->Html->link($carmodel['Make']['name'], array('controller' => 'makes', 'action' => 'view', $carmodel['Make']['id'])); ?>
</td>
<td>
<?php $overall_div = 'overall-rating' . $carmodel['Carmodel']['id']; ?>
<div id="<?php echo $overall_div; ?>">
<?php
echo $this->element('rating', array('rating' => $carmodel['Carmodel']['rating']));
?>
</div>
</td>
<td>
<?php
$msg_div = 'rating-msg' . $carmodel['Carmodel']['id'];
$rating = 0;
if (!empty($carmodel['Rating'])) {
$rating = $carmodel['Rating'][0]['value'];
}
echo $this->Rating->display(array(
'item' => $carmodel['Carmodel']['id'],
'type' => 'radio',
'stars' => 5,
'value' => $rating,
'submit' => false,
'createForm' => array(
'id' => 'CarmodelsRatingsDemoForm' . $carmodel['Carmodel']['id'],
'url' => array('action' => 'ratings_update', $carmodel['Carmodel']['id']),
'class' => 'rating',
'update-overall' => '#' . $overall_div,
'update-msg' => '#' . $msg_div,
)));
?>
<div id="<?php echo $msg_div; ?>" class="label label-info hidden">
<button class="close" data-dismiss="alert" type="button">×</button>
<div class="msg-default"><?php echo __('One moment...'); ?></div>
<div class="msg-result"></div>
</div>
</td>
Then I have some Jquery goodness to create the stars and then react on the click
$(document).ready(function(){
$('form.rating').stars({
cancelShow:true,
callback: function(ui, type, new_value) {
var values = ui.$form.serializeArray();
values.push({
'name': 'rating',
'value': new_value
});
values = jQuery.param(values);
var msg = ui.$form.attr('update-msg');
$(msg).removeClass('hidden');
$(msg).show();
$(msg).find('div.msg-default').show();
$(msg).find('div.msg-result').hide();
$.ajax({
'type': 'POST',
'dataType': 'json',
'url': ui.$form.attr('action'),
'data': values
}).done(function(data) {
var overall_rating = ui.$form.attr('update-overall');
if(overall_rating && data['overall_rating']){
$(overall_rating).html(data['overall_rating']);
}
if(msg){
$(msg).find('div.msg-default').hide();
if(data['msg']) {
$(msg).find('div.msg-result').show();
$(msg).find('div.msg-result').html(data['msg']);
window.setTimeout(function() {
$(msg).addClass('hidden');
}, 2000);
} else {
$(msg).addClass('hidden');
}
}
if(data['user_rating'] && data['user_rating']>0) {
ui.select(parseInt(data['user_rating']));
}
});
}
});
})
Plus I need a little snippet of css to hide the radio button labels that Cake adds.
form.rating > div.input {
display: none;
}
Then in the controller, I check if the user has rated the item before and save if not. I return a json array that contains a rendered element of the overall rating, the users rating (new or existing) and a string message to show in a div that disappears after 2 seconds.
public function ratings_update($id = null) {
$this->Carmodel->id = $id;
if (!$this->Carmodel->exists()) {
throw new NotFoundException(__('Invalid carmodel'));
}
$ratings = $this->Carmodel->isRatedBy($id, 1);
if (!$ratings) {
$this->Carmodel->rate($id, 1, $this->request->data['rating'], array('values' => array_combine(range(1, 5), range(1, 5))));
$json['msg'] = __('Thank you');
} else {
if ($this->request->data['rating'] == 0) {
$this->Carmodel->removeRating($id, 1);
$json['msg'] = __('Rating removed');
} else {
$json['msg'] = __('Already rated');
}
}
$this->set('rating', $this->Carmodel->field('rating'));
$ratings = $this->Carmodel->isRatedBy($id, 1);
$my_rating = 0;
if (!empty($ratings)) {
$my_rating = $ratings['Rating']['value'];
}
$this->autoRender = false;
App::uses('View', 'View');
$View = new View($this);
$response = $View->render('/Elements/rating', 'ajax');
$json['overall_rating'] = $response;
$json['user_rating'] = $my_rating;
return json_encode($json);
}
Here is the code for the element that shows stars for the overall rating, it probably should be part of the helper.
if (empty($rating)) {
echo __('Be the first to rate!');
} else {
echo str_repeat('<div class="ui-stars-star ui-stars-star-on"><a title=""></a></div>', $rating);
}
So while that isn't a super-detailed instruction, you should be able to figure out what the code is doing and replicate it. It took me the better part of a day to get it working.