Sourcefabric Manuals

 English |  Español |  Français |  Italiano |  Português |  Русский |  Shqip

Template library

Article rating by readers

 

As of version 4.1, Newscoop includes a new feature that allows logged in users to rate articles.  The article rating scores are then displayed on the article pages for all users.

How it works

The rating controller provides two actions to retrieve and update article ratings respectively. The show action takes one parameter for the articles unique article number and returns a JSON object with details about the articles current rating statistics. The save action take one parameter for the article number, and another for the new rating score. A JSON object is returned with the updated rating statistics for the article with a field containing an errors that may have been thrown. Save actions require that requests come from logged in Users.

The Newscoop admin has been updated with a default article switch to enable/disable article rating at the article level, and the article info box will now display the current avg article rating.

 

Example Implementation

A 5 star rating example has been added to the the New Custodian Theme. To see the example simple apply the theme to your publication in the newscoop admin ( CONFIGURE -> Themes ) and navigate to any article page on the frontend. You will see the 5 star rating widget at the bottom of the article page, just above the share links and comments section.

To include the article 5 star rating widget in your own custom templates you simply need to include the rating template (_tpl/article-rating.tpl) where ever you want the widget to display:

 {{ include file="_tpl/article-rating.tpl" }}

Customizing the 5 Star Rating Widget

If you want to customize the rating widget you can find the HTML, Javascript, and CSS below:

article-rating.tpl

<link rel="stylesheet" href="rating.css">
<script src="article-rating.js">

<div class='article_rating'>
    Rate this article:
    <div id="{{ $gimme->article->number }}">
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div></div>
        <div>vote data</div>
        <div></div>
    </div>
</div>

article-rating.js

<script type='text/javascript'>

$(document).ready(function() {

   // gets the initial rating
    $('.rate_widget').each(function(i) {
        var widget = this;
        var out_data = {
            f_article_number : $(widget).attr('id')
        };
        $.post(
            '/rating/show',
            out_data,
            function(INFO) {
                $(widget).data( 'fsr', INFO );
                set_votes(widget);
            },
            'json'
        );
    });


    // Handles the mouseover
    $('.ratings_stars').hover(
        function() {
            $(this).prevAll().andSelf().addClass('ratings_over');
            $(this).nextAll().removeClass('ratings_vote');
        },
        // Handles the mouseout
        function() {
            $(this).prevAll().andSelf().removeClass('ratings_over');
            // can't use 'this' because it wont contain the updated data
            set_votes($(this).parent());
        }
    );

    // actually records the vote
    $('.ratings_stars').bind('click', function() {
        var star = this;
        var widget = $(this).parent();
        var score = $(star).attr('class').match(/star_(\d+)/)[1];

        var clicked_data = {
            f_rating_score : score,
            f_article_number : $(star).parent().attr('id')
        };
        $.post(
            '/rating/save',
            clicked_data,
            function(INFO) {
                widget.data( 'fsr', INFO );
                set_votes(widget);
            },
            'json'
        );
    });



});

// binds the rating data returning by the rating controller
// to the widget elements
function set_votes(widget) {

    var avg = $(widget).data('fsr').whole_avg;
    var votes = $(widget).data('fsr').number_votes;
    var exact = $(widget).data('fsr').dec_avg;
    var error = $(widget).data('fsr').error;

    $(widget).find('.star_' + avg).prevAll().andSelf().addClass('ratings_vote');
    $(widget).find('.star_' + avg).nextAll().removeClass('ratings_vote');
    $(widget).find('.total_votes').text( votes + ' votes recorded (' + exact + ' rating)' );
    $(widget).find('.rating_error').text( error );
}

</script>

rating.css

.rate_widget {
    border:     1px solid #CCC;
    overflow:   visible;
    padding:    10px;
    position:   relative;
    width:      180px;
    height:     30px;
}
.ratings_stars {
    background: url('../_img/rating/star_empty.png') no-repeat;
    float:      left;
    height:     30px;
    padding:    2px;
    width:      28px;
}
.ratings_vote {
    background: url('../_img/rating/star_full.png') no-repeat;
}
.ratings_over {
    background: url('../_img/rating/star_highlight.png') no-repeat;
}

.total_votes {
    background: #eaeaea;
    top: 58px;
    left: 0;
    padding: 5px;
    position:   absolute;
}
.article_rating {
    font: 10px verdana, sans-serif;
    margin: 0px 0px 50px 550px;
    width: 180px;
}
.rating_error {
    top: 75px;
    left: 0;
    padding: 5px;
    position: absolute;
    color: red;
    font-weight: bold;
    width: 200px;
}

The rating controller

The rating controller is accessible from [domain]/rating url and implements two available actions.

Show action

parameters:

namedescription
f_article_number the unique article number

example request: 

 http://localhost/rating/show?f_article_number=101

example results:

{"widget_id":"101","number_votes":1,"total_score":3,"dec_avg":3,"whole_avg":3}

Save action

parameters: 

namedescription
f_article_number the unique article number
f_rating_score the desired rating

example request:

http://localhost/rating/save?f_article_number=101&f_rating_score=5

example results:

{"widget_id":"101","number_votes":1,"total_score":5,"dec_avg":5,"whole_avg":5,"error":"Your rating has been updated"}

There has been error in communication with Booktype server. Not sure right now where is the problem.

You should refresh this page.