jquerywordpressjquery-clone

jQuery .clone() only getting first instance of class


I have the following code in a network install WordPress template. My intent is to allow a non-technical user (content manager who helps blog managers keep their content fresh, etc) to view all users of role "custom-role" by blog, then click the button to copy all email addresses to the textarea so she can copy and paste them into the bcc field and communicate with all current users.

However, the script is only cloning the first instance of class "emails". What am I missing? Shouldn't this grab all instances of li.emails?

    <button id="copy">Copy all emails</button>
<textarea id="for-copy"></textarea>

    <?php

    $bcount = get_blog_count();

    global $wpdb;
    $blogs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->blogs WHERE 
    spam = '0' AND deleted = '0' and archived = '0' and public='1'"));
    if(!empty($blogs)){
        foreach($blogs as $blog){
            $details = get_blog_details($blog->blog_id);
            if($details != false){
                $addr = $details->siteurl;
                $name = $details->blogname;
                $id = $details->blog_id;
                $blogusers = get_users( 'blog_id='.$id.'&role=custom-role' );
                if (!empty($blogusers)) {
                    echo '<a href="'.$addr.'">'.$name.'</a>'.'<ul>';
                    foreach ( $blogusers as $user ) {
                    echo '<li class="emails">'.$user->user_email .'</li>';
                    }
                    echo '</ul>';
                }
            }
        }
    }
    ?>

<script>
(function($) {
$('#copy').click(function(e){
var new_list = $(".emails").clone();
$('#for-copy').append(new_list.html()); // also tried val()
});
})( jQuery );
</script>

Solution

  • From the jQuery docs on .html():

    Get the HTML contents of the first element in the set of matched elements or set the HTML contents of every matched element.

    So that's why you're only getting the first element.

    If you just want all the email addresses in a string for pasting into an email client, maybe you could just do something like this:

    var emailAddresses = $('.emails').map(function(i, element) {
      return $(element).text();
    }).toArray().join(';');
    
    $('#for-copy').text(emailAddresses);
    

    This would get all the elements with the .emails class, iterate over them with .map() to get the text, convert the result to an array, and then convert that to a semi-colon separated string via .join(). In this case there is actually no need to clone the elements.