Star voting with radio input, javascript/css

Asked

Viewed 13,303 times

7

I am creating a registration form, in it I will insert a voting system, I wanted to do that when clicking on some star, the previous ones will change color too. (Follows the code I created)

<div class="vote">
<label>
    <input type="radio" id="cm_star" name="fb" value="1" />
    <i class="fa"></i>
</label>
<label>
    <input type="radio" id="cm_star" name="fb" value="2" />
    <i class="fa"></i>
</label>
<label>
    <input type="radio" id="cm_star" name="fb" value="3" />
    <i class="fa"></i>
</label>
<label>
    <input type="radio" id="cm_star" name="fb" value="4" />
    <i class="fa"></i>
</label>
<label>
    <input type="radio" id="cm_star" name="fb" value="5" />
    <i class="fa"></i>
</label>

The result in image:

  • 2

    What is the problem you are facing? what is missing to work?

  • I suggest you use a plugin for this, it is easier than doing from scratch. these here for example. https://css-tricks.com/star-ratings/, http://speckyboy.com/2010/04/21/15-javascript-and-plugins-and-tutorials-for-adding-ratings/, http://www.sitepoint.com/10-jquery-rating-plugins/, http://wbotelhos.com/raty

  • I want the old ones to change colors too, like, click on the 4 star at 3, 2 and 1 also change colors.

3 answers

21


It is possible to do using only CSS, with the brother selector ~ and some modifications to HTML.

.estrelas input[type=radio] {
  display: none;
}
.estrelas label i.fa:before {
  content:'\f005';
  color: #FC0;
}
.estrelas input[type=radio]:checked ~ label i.fa:before {
  color: #CCC;
}
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<div class="estrelas">
  <input type="radio" id="cm_star-empty" name="fb" value="" checked/>
  <label for="cm_star-1"><i class="fa"></i></label>
  <input type="radio" id="cm_star-1" name="fb" value="1"/>
  <label for="cm_star-2"><i class="fa"></i></label>
  <input type="radio" id="cm_star-2" name="fb" value="2"/>
  <label for="cm_star-3"><i class="fa"></i></label>
  <input type="radio" id="cm_star-3" name="fb" value="3"/>
  <label for="cm_star-4"><i class="fa"></i></label>
  <input type="radio" id="cm_star-4" name="fb" value="4"/>
  <label for="cm_star-5"><i class="fa"></i></label>
  <input type="radio" id="cm_star-5" name="fb" value="5"/>
</div>

Note: It was necessary to include a preselected empty radio so that the stars are correctly displayed when no value is selected.

  • 1

    Sanction, he would like the previous stars to be selected as well.

  • 2

    @Maiconcarraro, I just saw the comments, I based the image on the question, thank you for warning

  • 1

    @Maiconcarraro updated response

  • Very good ! :))

  • Thank you, that’s just what I needed =D

  • Very cool Sanction! + 1

  • No me browser is showing the stars, when I use the code above.

  • Liked it, helped me!

Show 3 more comments

6

I made using pure javascript, basically created a function to go through all img with the same name and according to which star was clicked (Indice) I assign whether it will be highlights or not.

function seleciona(name, indice) {
   var imgs = document.querySelectorAll('img[name=' + name + ']');
  
   for (var i=0; i < imgs.length; i++) {
       if (i <= indice)
           imgs[i].className = "destaque";
       else
           imgs[i].className = "apagada";
   }
}

window.onload = function() {
   var imgs = document.querySelectorAll('img[name=fb]');
  
   for (var i=0; i < imgs.length; i++) {
       (function(name, i) {
          imgs[i].addEventListener('click', function () {
              seleciona(name, i);
          });
       })(imgs[i].name, i);
   }
}
.apagada {
  background-image: url('http://www.biblecast.net.br/resources/estrela-prata.png');
  width: 32px;
  height: 32px;
  cursor: pointer;
}

.destaque {
  background-image: url('http://imobiliariacincoestrelas.com.br/images/estrela.png');
  width: 32px;
  height: 32px;
  cursor: pointer;
}
<label>
    <img name="fb" class="apagada"/>
</label>
<label>
    <img name="fb" class="apagada"/>
</label>
<label>
    <img name="fb" class="apagada"/>
</label>
<label>
    <img name="fb" class="apagada"/>
</label>
<label>
    <img name="fb" class="apagada"/>
</label>

5

Following its HTML structure, I leave here a suggestion using jQuery.

$('.vote label i.fa').on('click mouseover',function(){
    // remove classe ativa de todas as estrelas
    $('.vote label i.fa').removeClass('active');
    // pegar o valor do input da estrela clicada
    var val = $(this).prev('input').val();
    //percorrer todas as estrelas
    $('.vote label i.fa').each(function(){
        /* checar de o valor clicado é menor ou igual do input atual
        *  se sim, adicionar classe active
        */
        var $input = $(this).prev('input');
        if($input.val() <= val){
            $(this).addClass('active');
        }
    });
    $("#voto").html(val); // somente para teste
});
//Ao sair da div vote
$('.vote').mouseleave(function(){
    //pegar o valor clicado
    var val = $(this).find('input:checked').val();
    //se nenhum foi clicado remover classe de todos
    if(val == undefined ){
        $('.vote label i.fa').removeClass('active');
    } else { 
        //percorrer todas as estrelas
        $('.vote label i.fa').each(function(){
            /* Testar o input atual do laço com o valor clicado
            *  se maior, remover classe, senão adicionar classe
            */
            var $input = $(this).prev('input');
            if($input.val() > val){
                $(this).removeClass('active');
            } else {
                $(this).addClass('active');
            }
        });
    }
    $("#voto").html(val); // somente para teste
});
.vote label {
    cursor:pointer;
}
.vote label input{
    display:none;
}
.vote label i {
    font-family:FontAwesome;
    font-size:18px;
    -webkit-transition-property:color, text;
    -webkit-transition-duration: .2s, .2s;
    -webkit-transition-timing-function: linear, ease-in;
    -moz-transition-property:color, text;
    -moz-transition-duration:.2s;
    -moz-transition-timing-function: linear, ease-in;
    -o-transition-property:color, text;
    -o-transition-duration:.2s;
    -o-transition-timing-function: linear, ease-in;
}
.vote label i:before {
    content:'\f005';
}
.vote label i.active {
    color:gold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<div class="vote">
<label>
    <input type="radio" name="fb" value="1" />
    <i class="fa"></i>
</label>
<label>
    <input type="radio" name="fb" value="2" />
    <i class="fa"></i>
</label>
<label>
    <input type="radio" name="fb" value="3" />
    <i class="fa"></i>
</label>
<label>
    <input type="radio" name="fb" value="4" />
    <i class="fa"></i>
</label>
<label>
    <input type="radio" name="fb" value="5" />
    <i class="fa"></i>
</label>
</div>

<div id="voto">
    
</div>

Jsfiddle

  • 1

    Very interesting solution using content and mouseover, but I’ll leave my answer if anyone wants to do more "manual"

  • @Maiconcarraro certainly your answer is valid, and it is still in pure javascript, if it unites the ideas will be able to reach the result you want.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.