Have you ever stumbled upon the issue of radio buttons losing their “checked” state while dragging and dropping a div containing them using the Sortable module of jQuery UI? It is not a pleasant experience and is a known issue even in jQuery 1.7.x bundled in WordPress 3.3 – 3.4. Read on to learn how to fix this.
The issue
If you have stumbled upon this, you surely know your way on jQuery so let’s go straight to the point: while using Sortable from jQuery UI, if you drag and drop an element containing radio buttons already checked, they will lose their state (their “checkedness”).
There are a bunch of solutions around, to detect the moment when you start dragging and then dropping, but a bit complicated. I found a solution on WordPress Trac but it was complicated since it requires to register a listener for mouse events and then trigger a click on the radio button that was previously checked.
We don’t need any that: the Sortable module has a callback that is triggered when you start dragging the element so we will use it and we will simply set the checked property on those radio inputs that were checked.
However, this solution was useful in their approach of storing a pointer of only those radio buttons that have been checked.
Fixing it
So let’s consider this code:
[js]
jQuery(document).ready(function ($) {
$(‘#tr-blocks’).sortable({
opacity: 0.5,
helper: ‘clone’,
placeholder: ‘ui-state-highlight’,
start: function (e, ui) {
//The code you need begins here
var radio_checked= {};
$(‘input[type="radio"]’, this).each(function(){
if($(this).is(‘:checked’))
radio_checked[$(this).attr(‘name’)] = $(this).val();
$(document).data(‘radio_checked’, radio_checked);
});
}
}).bind(‘sortstop’, function (event, ui) {
var radio_restore = jQuery(document).data(‘radio_checked’);
for(radio in radio_restore){
$(‘input[id="’+ radio + radio_restore[radio]+’"]’).prop(‘checked’, true);
}
//and ends here
});
});
[/js]
This will save only the names and value of checked radio buttons when user starts dragging using jQuery’s data. When the dragged element is dropped, the data is retrieved and each radio button that was checked before has its checkedness restored using prop.
Now, if you have a keen eye for details, you might have noticed this
[js]
$(‘input[id="’+ radio + radio_restore[radio]+’"]’)
[/js]
why not using the plain ID? like
[js]
$(‘#’+ radio + radio_restore[radio])
[/js]
it was simply because my fields had this notation
[html]
#optionsSetName[subset]value
[/html]
and for some reason using the traditional selector throw an empty array []. Didn’t paid too much attention as it was correctly fixed using the ID attribute, but I just want to clarify that maybe you won’t have to use this selector format.
Another option
Not exactly a fix but an alternative would be to use <select elements. You won’t experience this issue as its checked option is correctly preserved during drag and drop, at least with jQuery 1.7.x.
Oh, how I love this blog desing, it is just awesome!
Awesome solution, bro, helped me a lot – I used your solution to make a more generic one, hope it helps: https://gist.github.com/4195753
Cheers and thank you for sharing!
You’re welcome, good to know it was helpful Luiza.
Thanks for some other wonderful article. The place
else may just anybody get that kind of info in such an ideal manner of writing?
I have a presentation next week, and I’m at the look for such information.