Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a comma separated list of clicked elements with jquery

Tags:

jquery

csv

I'm trying to inject a comma separated list into the DOM that a user can copy and paste into another application. Right now I'm completely stuck on how to handle the first element which is not preceded by a comma.

Right now a user clicks on an element and jquery grabs the ID of the element to build the list. The user should be able to toggle their selections on and off. I also need the list to be generated in the order that the user selects items.

HTML

Comma separated list here: <span id="list"></span>
<br />
<a id="1" class="clickme" href="#"><li>One</li></a>
<a id="2" class="clickme" href="#"><li>Two</li></a>
<a id="3" class="clickme" href="#"><li>Three</li></a>
<a id="4" class="clickme" href="#"><li>Four</li></a>
<a id="5" class="clickme" href="#"><li>Five</li></a>
<a id="6" class="clickme" href="#"><li>Six</li></a>

CSS

.selected {
    background-color: #99CCFF;    
}

JS - jquery is loaded

$('.clickme').click(function (e) {
        e.preventDefault();
        var book_id = $(this).attr('id'); 
        $(this).children('li').toggleClass("selected");
        var list_container = $("#list");
        if ($(this).children('li').is(".selected")) {
            if (list_container.text().length > 0) {
                list_container.append("," + book_id);
            } else {
                list_container.append(book_id);
            }
        } else {
            list_container.text(list_container.text().replace("," + book_id, ""));          
        }
});

This works great to build the comma separated list and it works great to toggle off all but the first value in the list. The problem is that the first value was inserted without a preceding comma and so the replace function can't match it. If I remove the comma from the replace function then I'm left with a bunch of unneeded commas. If I match both then I run the risk of matching part of an ID...ie replacing the 3 in 13 when the 3 is toggled off.

I've tried a ton of variations and can't find anything that works.

My only solution that produced the desired result was to use CSS to inject the commas and wrap the injected IDs with a span element.

CSS TRICK

#list span { display: inline; }
#list span:after { content: ","; }
#list span:last-child:after { content: ""; }

Worked great...except for the actual purpose of this. I need users to be able to copy and paste the generated string. When you use CSS to produce the content the DOM level clipboards in most browsers don't see it. IE copied the string as you see it in the browser, FF and Safari both copied the string without the CSS appended commas.

Fiddle is HERE

like image 539
user2027355 Avatar asked Feb 17 '23 22:02

user2027355


1 Answers

It seems you are way over complicating this problem. Just simply make an array of selected book ids then use .join(',') to display them as a comma-separated list.

$('.clickme').click(function (e) {
    e.preventDefault();
    $(this).children('li').toggleClass("selected");

    var list_container = $("#list");
    var book_ids = $('.clickme:has(li.selected)').map(function(){
        return this.id;
    }).get();

    list_container.text(book_ids.join(','));
});

DEMO: http://jsfiddle.net/rYu6m/2/

EDIT: You say you want to keep the elements in the order they were clicked. In that case, you need to declare the array outside the click handler, then either .push the element onto it or .splice it out. It's much easier to work with arrays, than to work with strings.

var book_ids = [];
$('.clickme').click(function (e) {
    e.preventDefault();
    $(this).children('li').toggleClass("selected");

    var list_container = $("#list");

    var index = $.inArray(this.id, book_ids);
    if(index === -1){
        // Not in array, add it
        book_ids.push(this.id);
    }
    else{
        // In the array, remove it
        book_ids.splice(index, 1);
    }

    list_container.text(book_ids.join(','));
});

DEMO: http://jsfiddle.net/rYu6m/4/

like image 149
Rocket Hazmat Avatar answered Apr 26 '23 22:04

Rocket Hazmat