HI danaev,
So that’s kinda hard to read. Please try formatting it by using three backticks prior to and after the code.
Also, there are a few concepts when using jQuery you’ll want to get used to and start using right away. The first is that, any time you use a jQuery method, you are calling a jQuery function. When you use jQuery to select something, there is an expense to that (in terms of execution time). So, if you’re going to use a selection more that once, it’s best to save it to a variable so that you can refer to it later without having to re-select it. A common approach is to start a collection variable with a $, as that is the abbreviation for jQuery.
So …
$users_from_btn = $( '#users-to' );
$users_to_btn = $( '#users-from' );
It just makes is easier to read later in the code and also means you are not asking the browser to re-select the elements. Things like this become quite important inside of a loop, which is where you are inside of that .each() call;
Another thing to know about is method chaining. That means you can use many Javascript and jQuery methods one right after the other in sequence like …
$a
.attr( 'selected', true )
.hide();
It makes for a simple stack to see the action you are operating on $a
.
Finally, another important thing to know is that when you select something with jQuery, you are given back a “collection” - all items that matched the selector you provided. When you then call a jQuery method, in almost all cases it operates against the entire collection. So you often do not need an .each()
call unless there really is something unique that needs to be done to each item in the collection.
I suggest reading about some of the most common jQuery “best practices”. It will help make your code more efficient and easier to read.
jQuery Best Practices
Now, as to the function itself … basically, on click of a button, you need to find any items that are selected in the source list, detach them, and append them to the destination list. Which button clicked determines what is the source and what is the destination list. Because the process of moving them from one list to another is identical, changing only based on which button is clicked, you can make a single function that both buttons call, altering only which list is passed in as source or destination arguments.
You should look into not just the .append()
method, but also the .detach()
method in jQuery as they are very useful here.
That’s about as far as I can go without writing out a solution, so … be warned … Major spoilers ahead.
function moveElements( selector, $source, $destination ){
// SELECTOR IS A CSS SELECTOR THAT ALLOWS YOU TO DETERMINE WHICH ITEMS ARE SELECTED
// SOURCE IS THE CURRENT LOCATION OF THE ITEMS
/// DESTINATION IS WHERE YOU WANT THEM TO GO.
const $elems = $source.find( selector ).detach();
// NO ELEMENTS WERE SELECTED, NOTHING TO DO ...
if ( !$elems.length )
return;
$destination.append( $elems );
}
const selector = 'option:selected'; // OR SOME SUCH CSS SELECTOR FOR FINDING SELECTED ITEMS
$left = $( '#id_users' );
$right = $( '#id_users_to' );
$( '#users_to' ).click( function(){
moveElements( selector, $left, $right );
});
$( '#users_from' ).click( function(){
moveElements( selector, $right, $left );
});
or something like that …
It should be in the neighborhood of what you are looking for.
In fact, I hacked together a quick pen where it is working just fine.
Working concept.
I left stuff out, like setting the disabled property based on whether or not there were any options selected, etc. Also, you said “move”, but in your code you are copying and then hiding the original. Mine does an actual move.
Anyway, I hope that helps.
Regards,
Micheal