Only Bolivian Here Only Bolivian Here - 5 months ago 10
HTML Question

jQuery gurus, can this code be simplified?

Live demo:
http://jsfiddle.net/stapiagutierrez/KKdsb/29/




I'm just trying to create my own star rating UI for websites and so far it works just how I want it to, but I'd like to see if I can trim down my code without sacrificing legibility.

Since I'm new to jQuery, maybe I'm doing things the roundabout way.

Any suggestions on where to improve?

ul {
list-style-type:none;
margin-top:10px;
margin-left:10px;
border:1px solid #333;
border-radius:8px;
overflow:hidden;
width:111px;
cursor:pointer;
}

li {
float:left;
margin-left:5px;
padding-top:2px;
}

<ul>
<li>
<img class="onestar rating" src="http://i.imgur.com/8LA1i.png" alt="no-star" />
</li>

<li>
<img class="twostar rating" src="http://i.imgur.com/8LA1i.png" alt="no-star" />
</li>

<li>
<img class="threestar rating" src="http://i.imgur.com/8LA1i.png" alt="no-star" />
</li>

<li>
<img class="fourstar rating" src="http://i.imgur.com/8LA1i.png" alt="no-star" />
</li>

<li>
<img class="fivestar rating" src="http://i.imgur.com/8LA1i.png" alt="no-star" />
</li>
</ul>

$(document).ready(function() {
$(".rating").click(function() {
if ($(this).hasClass("onestar")) {
alert("Clicked on 1 star!");
}
else if ($(this).hasClass("twostar")) {
alert("Clicked on 2 stars!");
}
else if ($(this).hasClass("threestar")) {
alert("Clicked on 3 stars!");
}
else if ($(this).hasClass("fourstar")) {
alert("Clicked on 4 stars!");
}
else if ($(this).hasClass("fivestar")) {
alert("Clicked on 5 stars!");
}
});

$(".rating").mouseleave(function() {
$(".rating").each(function() {
$(this).attr("src", "http://i.imgur.com/8LA1i.png");
});
});

$(".rating").mouseover(function() {
if ($(this).hasClass("onestar")) {
$(".onestar").attr('src', 'http://i.imgur.com/X68bI.png');
}
else if ($(this).hasClass("twostar")) {
$(".onestar").attr('src', 'http://i.imgur.com/X68bI.png');
$(".twostar").attr('src', 'http://i.imgur.com/X68bI.png');
}
else if ($(this).hasClass("threestar")) {
$(".onestar").attr('src', 'http://i.imgur.com/X68bI.png');
$(".twostar").attr('src', 'http://i.imgur.com/X68bI.png');
$(".threestar").attr('src', 'http://i.imgur.com/X68bI.png');
}
else if ($(this).hasClass("fourstar")) {
$(".onestar").attr('src', 'http://i.imgur.com/X68bI.png');
$(".twostar").attr('src', 'http://i.imgur.com/X68bI.png');
$(".threestar").attr('src', 'http://i.imgur.com/X68bI.png');
$(".fourstar").attr('src', 'http://i.imgur.com/X68bI.png');
}
else if ($(this).hasClass("fivestar")) {
$(".onestar").attr('src', 'http://i.imgur.com/X68bI.png');
$(".twostar").attr('src', 'http://i.imgur.com/X68bI.png');
$(".threestar").attr('src', 'http://i.imgur.com/X68bI.png');
$(".fourstar").attr('src', 'http://i.imgur.com/X68bI.png');
$(".fivestar").attr('src', 'http://i.imgur.com/X68bI.png');
}
});
});

Answer

That was kinda fun, here's the jsFiddle: http://jsfiddle.net/KKdsb/30/

NOTE: The usage of two parent() functions in the mouseover handler is subject to your html structure. I'd recommend a class or similar to access the parent <ul> element directly using $(this).closest('.classname').

jQuery code:

$(document).ready(function() {
    $(".rating").click(function() {
        var position = $(this).parent().index();
    });

    $(".rating").mouseleave(function() {
        $(".rating").each(function() {
            $(this).attr("src", "http://i.imgur.com/8LA1i.png");
        });
    });

    $(".rating").mouseover(function() {
        var position = $(this).parent().index() + 1;
        $(this).parent().parent().find("li:lt("+position+") > img").each(function (i, e) {
            $(e).attr('src', 'http://i.imgur.com/X68bI.png');
        });
    });
});

Reference: