On my website about music I have a voting system made with radio buttons so that registered users assign a note from 1 to 5 to each song:
<span class="estrellas mt-3 ml-2">
<?php
if($_SESSION['conectado']) for($i = 1; $i <= 5; $i++)
{
echo '<input type="radio" name="'.$id_cancion.'" value="'.$i.'"';
echo ($i == $nota) ? " checked><i></i>" : "><i></i>";
}
?>
</span>
Which looks like this (if for example you have given 4 stars to a song):
The system is controlled by a jQuery script that sends the information through .ajax()
a PHP file, which is in charge of inserting it into my MySQL database:
$(function()
{
/*$('input[type=radio]:checked').click(function()
{
$(this).attr('checked', false);
})*/
$('input[type=radio]').change(function()
{
var voto = $(this).val();
var idCancion = $(this).attr('name');
var cancion = $(this).parent().parent().siblings('.row').find('.cancion').text();
var autor = $(this).parent().parent().siblings('.row').find('.autor-recopilatorio').text();
$.ajax(
{
type: 'POST', url: 'votacion.php', data: {voto: voto, id_cancion: idCancion},
success: function()
{
if(voto == 5) swal("¡Guau!", "¡Amor a primera vista!", "success");
else if(voto == 4) swal("¡Genial!", `¡Disfruta de ${autor}!`, "success");
else if(voto == 3) swal(":)", "Buena canción, ¿eh?", "success");
else if(voto == 2) swal("Vaya...", `¿No te convence ${cancion}?`, "success");
else swal("Bueno...", "No a todo el mundo le puede gustar lo mismo...", "success");
},
error: function()
{
swal("Vaya...", "Parece que tu voto no se ha podido enviar", "error");
}
})
})
});
Subsequently, another PHP file makes a call to the database and in a loop presents all the pertinent information for each song -YouTube video, album cover, various artist data, etc.-, including the voting system whose code you see at the beginning of the message.
The system's PHP code is such that if the user has previously voted for a song, it will have one $nota
in the database and the radio button whose value $i
matches it will appear checked
:
<input type="radio" name="135" value=4 checked>
Well, the voting system works perfectly but as of today there is no way to delete the votes, so I have started to modify my script to solve it; the first step has been to try that if the user clicks on the marked radio button, it will checked
disappear:
$('input[type=radio]:checked').click(function()
{
$(this).attr('checked', false);
})
As you can see, this piece of code is the one that appears commented in the body of the script above.
This apparently works; if a song has $nota
and the radiobutton whose is equivalent is clicked value
, the attribute checked
disappears:
<input type="radio" name="135" value=4>
The problem is that if you then click another radiobutton (in this case, 1, 2, 3, or 5), change the vote, and then click the initial radiobutton again (4), the DOM still takes over. that that is the checked
and deletes the vote again (although now it is no longer a 4, but another value of the five possible).
Obviously, then there would be many other issues to solve for this to be viable, but I am struck by this behavior checked
that I have already encountered at the beginning. I suspect that it has to do with differences between .attr()
and .prop()
, so let's see if you can help me.
The main problem is that jquery cannot correctly detect when a radio button is unchecked to check it:
As you can see in the following example, the state of the radio button can be changed correctly through the buttons, but it fails when clicking on it:
This happens because the default action of the radio button makes it activate automatically on click, so the result of
$("#radio").is(':checked')
is alwaystrue
(and the algorithm always returns true, while the code insideelse
it is never executed).The problem can be solved by adding a
data-set
to the radio buttons that stores their state so that they can be compared later.In this case adding
data-actual
and the status of the option (true
orfalse
) to the radiobutton we mark and unmark the option, to assign the value of data with jquery we usedata('set', valor)
.Then to trigger the state change event instead of using
you can use
On the other hand you have the problem of returning to the previous button when selecting a different option. For that, first the name of the set of radio buttons is obtained (I imagine that you can have several), with:
Then you must change the value of all
data-actual
of the song, for that you use:That before assigning the new option.
Here is an example of how the code would work:
In short, your jquery code would look like this:
and your php code:
That way it already works as you want.
Finally, regarding your question about the differences between
prop()
andattr()
:Both functions do relatively the same thing, replacing
attr()
withprop()
in code usually works.attr()
returns an HTML attribute.prop()
returns a property of the element.When the browser interprets the HTML code, the attributes of an element are transformed into properties.
Properties are generally simpler to deal with than attributes. The attribute value can only be a string, while a property can be of any type. For example, property
checked
is a boolean, propertystyle
is an object with individual properties for each style, propertysize
is a number.In short
attr()
, it is more recommended to obtain the value of an attribute while itprop()
is more recommended to assign properties.For more information you can review:
What is the difference between attr and prop in jQuery?
I hope you find it useful, greetings.