Требуется помощь в 5-звездочном рейтинге - Jquery - PullRequest
4 голосов
/ 04 декабря 2010

Я пытаюсь построить систему звездного рейтинга. Код, который у меня сейчас есть, делает следующее:

Подсвечивать звездочки, когда мышь наводит на них курсор, но возвращать их в предыдущее состояние, когда мышь удалена.

Я хочу добавить в него следующую функциональность: Когда я нажимаю на звезду, количество нажатых звездочек должно оставаться выделенным даже после удаления мыши из звездочек.

Может кто-нибудь помочь мне в этом?

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd"
    >
<html lang="en">
<head>
    <title>AJAX 5 Star Rating</title>

    <script src="http://code.jquery.com/jquery-latest.js"></script>
    <script>

    // This is the first thing we add ------------------------------------------
    $(document).ready(function() {

        $('.rate_widget').each(function(i) {
            var widget = this;
            var out_data = {
                widget_id : $(widget).attr('id'),
                fetch: 1
            };
            $.post(
                'ratings.php',
                out_data,
                function(INFO) {
                    $(widget).data( 'fsr', INFO );
                    set_votes(widget);
                },
                'json'
            );
        });


        $('.ratings_stars').hover(
            // Handles the mouseover
            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());
            }
        );


        // This actually records the vote
        $('.ratings_stars').bind('click', function() {
            var star = this;
            var widget = $(this).parent();

            var clicked_data = {
                clicked_on : $(star).attr('class'),
                widget_id : $(star).parent().attr('id')
            };
            $.post(
                'ratings.php',
                clicked_data,
                function(INFO) {
                    widget.data( 'fsr', INFO );
                    set_votes(widget);
                },
                'json'
            ); 
        });



    });

    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;

        window.console && console.log('and now in set_votes, it thinks the fsr is ' + $(widget).data('fsr').number_votes);

        $(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)' );
    }
    // END FIRST THING








    </script>

    <style>
        .rate_widget {
            border:     1px solid #CCC;
            overflow:   visible;
            padding:    10px;
            position:   relative;
            width:      180px;
            height:     32px;
        }
        .ratings_stars {
            background: url('star_empty.png') no-repeat;
            float:      left;
            height:     28px;
            padding:    2px;
            width:      32px;
        }
        .ratings_vote {
            background: url('star_full.png') no-repeat;
        }
        .ratings_over {
            background: url('star_highlight.png') no-repeat;
        }
        .total_votes {
            background: #eaeaea;
            top: 58px;
            left: 0;
            padding: 5px;
            position:   absolute;  
        } 
        .event_choice {
            font: 10px verdana, sans-serif;
            margin: 0 auto 40px auto;
            width: 180px;
        }
        h1 {
            text-align: center;
            width: 400px;
            margin: 20px auto;
        }
    </style>
</head>
<body>
<h1> Rate the event! </h1>
<div class='event_choice'>
    Rate: Raiders of the Lost Ark
    <div id="r1" class="rate_widget">
        <div class="star_1 ratings_stars"></div>
        <div class="star_2 ratings_stars"></div>
        <div class="star_3 ratings_stars"></div>
        <div class="star_4 ratings_stars"></div>
        <div class="star_5 ratings_stars"></div>
        <div class="total_votes">vote data</div>
    </div>
</div>

<div class='event_choice'>
    Rate: The Hunt for Red October
    <div id="r2" class="rate_widget">
        <div class="star_1 ratings_stars"></div>
        <div class="star_2 ratings_stars"></div>
        <div class="star_3 ratings_stars"></div>
        <div class="star_4 ratings_stars"></div>
        <div class="star_5 ratings_stars"></div>
        <div class="total_votes">vote data</div>
    </div>
</div>
</body>
</html>

1 Ответ

2 голосов
/ 04 декабря 2010

Я нашел отличный CSS единственный способ делать эффекты при наведении . Сохранение выделенных звезд все еще потребует некоторого JavaScript, но намного меньше.

Общая идея заключается в том, что у вас есть фоновое изображение (звезда) для ul с установленной длиной (в вашем случае, в 5 раз больше ширины изображения, для 5 звезд) и повторное изображение по оси x (background: url(star.gif) repeat-x;). Каждый <a> имеет разную ширину (20%, 40%, 60%, 80%, 100% для 5 звезд) и помещается в другой z-индекс.

Вот обновление идеи автора, которая немного ближе к вашему варианту использования:

HTML:

<div class='rate_widget'>
    <ul>
        <li><a href='#' class='one-star'>1</a></li>
        <li><a href='#' class='two-stars'>2</a></li>
        <li><a href='#' class='three-stars'>3</a></li>
        <li><a href='#' class='four-stars'>4</a></li>
        <li><a href='#' class='five-stars'>5</a></li>
    </ul>
</div>

CSS:

.rate_widget ul{
    background: url(star_empty.png) repeat-x;
}

.rate_widget a:hover{
    background: url(star_highlight.png) repeat-x;
}

.rate_widget a:active,
.rate_widget a:focus,
.rate_widget a.checked{
    background: url(star_full.png) repeat-x;
}

.rate_widget ul{
    position:relative;
    width:125px; /*5 times the width of your star*/
    height:25px; /*height of your star*/
    overflow:hidden;
    list-style:none;
    margin:0;
    padding:0;
    background-position: left top;
}

.rate_widget li{
    display: inline;
}

.rate_widget a{
    position:absolute;
    top:0;
    left:0;
    text-indent:-1000em;
    height:25px; /*height of your star*/
    line-height:25px; /*height of your star*/
    outline:none;
    overflow:hidden;
    border: none;
}

.rate_widget a.one-star{
    width:20%;
    z-index:6;
}

.rate_widget a.two-stars{
    width:40%;
    z-index:5;
}

.rate_widget a.three-stars{
    width:60%;
    z-index:4;
}

.rate_widget a.four-stars{
    width:80%;
    z-index:3;
}

.rate_widget a.five-stars{
    width:100%;
    z-index:2;
}

.rate_widget a.checked{
    z-index:1;
}

Javascript:

$('.rate_widget a').click(function(){
    // make sure the chosen star stays selected
    var star = $(this);
    star.closest('ul').find('.checked').removeClass('checked');
    star.addClass('checked');

    //whatever else you want to do when something gets clicked
});

А вот скрипка, чтобы увидеть это в действии: http://www.jsfiddle.net/BHaTu/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...