Search code examples
javascriptasp-classicclipboard

Copy table column DB results Text to Clipboard


I have a classic ASP page that pulls records from a DB and displays the results in a table. One of the columns displays Emails based on the recordset being displayed. Id like to add a Copy to clipboard button on the page that copies all the emails in this column.

Here is current script for looping through the record set.

RESPONSE.WRITE "<tr>"& vbCrlf
RESPONSE.WRITE "<td>FULL NAME</td>"& vbCrlf
RESPONSE.WRITE "<td>EMAIL</td>"& vbCrlf
RESPONSE.WRITE "</tr>"& vbCrlf

IF NOT rsMembers.EOF AND NOT rsMembers.BOF THEN

DO WHILE NOT rsMembers.EOF
RESPONSE.WRITE "<tr>"& vbCrlf          
RESPONSE.WRITE "<td>" & rsMembers("First Name") & " " & rsMembers("Last Name") & "</td>"& vbCrlf

RESPONSE.WRITE "<td><a href='mailto:"&rsMembers("Email")&"'>" & rsMembers("Email") & "</a></td>"& vbCrlf
RESPONSE.WRITE "</tr>"& vbCrlf

rsMembers.MOVENEXT
LOOP

END IF

My Original attempt was to include a hidden field within the Loop for each email record and making the ID for that field unique by adding a number or something to it. And then in the javascript loop through all possible ID's.

RESPONSE.WRITE "<tr>"& vbCrlf
RESPONSE.WRITE "<td>FULL NAME</td>"& vbCrlf
RESPONSE.WRITE "<td>EMAIL</td>"& vbCrlf
RESPONSE.WRITE "</tr>"& vbCrlf

IF NOT rsMembers.EOF AND NOT rsMembers.BOF THEN

DO WHILE NOT rsMembers.EOF
RESPONSE.WRITE "<tr>"& vbCrlf          
RESPONSE.WRITE "<td>" & rsMembers("First Name") & " " & rsMembers("Last Name") & "</td>"& vbCrlf

RESPONSE.WRITE "<td><a href='mailto:"&rsMembers("Email")&"'>" & rsMembers("Email") & "</a><input type='hidden' value='"& rsMembers("Email") &"' id='myInput'></td>"& vbCrlf
RESPONSE.WRITE "</tr>"& vbCrlf

rsMembers.MOVENEXT
LOOP

END IF

Java
<script>
function myFunction() {
  /* Get the text field */
  var copyText = document.getElementById("myInput");

  /* Select the text field */
  copyText.select();

  /* Copy the text inside the text field */
  document.execCommand("copy");

  /* Alert the copied text */
  alert("Copied the text: " + copyText.value);
</script>

Then add a button to copy:

<button onclick="myFunction()">Copy text</button>

Not sure if there is a way to put all email results into and array and then write them out into one hidden field. For example

<input type="hidden" value="DB Array of emails with a comma between each" id="myInput">

Example: enter image description here


Solution

  • Here's a jQuery solution.

    There's a click event triggered by the "copy all" button. The email addresses are collected by retrieving the text values of any elements with an "emails" class then passed to a function called "copyToClipboard" which creates a temporary hidden textarea to select and copy the email values from. It should work in all browsers.

    EDIT: I've updated the code to allow you to copy data from any column. You just have to specify a target class and pass it as a data attribute. You could probably just specify a column number and look for nested table data without having to assign classes, but that's beyond my JavaScript knowledge unfortunately, plus the href links in the emails column would make that tricky.

    <!doctype html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>Database Results</title>
    </head>
    <body>
    <table width="0%" border="2" cellspacing="3" cellpadding="3">
      <tbody>
        <tr>
          <th>Column 1</th>
          <th>Column 2</th>
          <th>Column 3</th>
          <th>Names - <button class="CopyColumn" data-target=".names">Copy All</button></th>
          <th>Emails - <button class="CopyColumn" data-target=".emails" data-separator="; ">Copy All</button></th>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td class="names">Name One</td>
          <td><a href="mailto:email1@email.com" class="emails">email1@email.com</a></td>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td class="names">Name Two</td>
          <td><a href="mailto:email2@email.com" class="emails">email2@email.com</a></td>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td class="names">Name Three</td>
          <td><a href="mailto:email3@email.com" class="emails">email3@email.com</a></td>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td class="names">Name Four</td>
          <td><a href="mailto:email4@email.com" class="emails">email4@email.com</a></td>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td class="names">Name Five</td>
          <td><a href="mailto:email5@email.com" class="emails">email5@email.com</a></td>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td class="names">Name Six</td>
          <td><a href="mailto:email6@email.com" class="emails">email6@email.com</a></td>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td class="names">Name Seven</td>
          <td><a href="mailto:email7@email.com" class="emails">email7@email.com</a></td>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td class="names">Name Eight</td>
          <td><a href="mailto:email8@email.com" class="emails">email8@email.com</a></td>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td class="names">Name Nine</td>
          <td><a href="mailto:email9@email.com" class="emails">email9@email.com</a></td>
        </tr>
        <tr>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td>&nbsp;</td>
          <td class="names">Name Ten</td>
          <td><a href="mailto:email10@email.com" class="emails">email10@email.com</a></td>
        </tr>
      </tbody>
    </table>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script>
    
        $(document).ready(function() {
    
            $(".CopyColumn").click(function(){
    
                var btn = $(this);
    
                // Disable the button whilst the clipboard copy is performed
                btn.prop("disabled", true);
    
                var colData = "";
    
                // Use a line break to seperate the column data if no separator is specified
                var colSeparator = (btn.data("separator")===undefined) ? "\n" : btn.data("separator");
    
                // Loop through all elements with the target class
                $(btn.data("target")).each(function() {
                    // Collect the column data and add the separator
                    colData += $(this).text() + colSeparator;
                });
    
                // Copy the column data to the clipboard
                copyToClipboard(colData.trim());
    
                // Make a copy of the button text
                var btn_txt = btn.html();
    
                // Change the button text to "Copied"
                btn.html("Copied");
    
                // Revert the button text after 1.5 seconds
                setTimeout(function(){
                    btn.html(btn_txt);
                    // Enable the button
                    btn.prop("disabled", false);
                },1500);
    
            });
    
        });
    
        function copyToClipboard(text) {
            if (window.clipboardData && window.clipboardData.setData) {
                // IE specific code path to prevent textarea being shown while dialog is visible.
                return clipboardData.setData("Text", text); 
            } else if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
                var textarea = document.createElement("textarea");
                textarea.textContent = text;
                textarea.style.position = "fixed";  // Prevent scrolling to bottom of page in MS Edge.
                document.body.appendChild(textarea);
                textarea.select();
                try {
                    return document.execCommand("copy");  // Security exception may be thrown by some browsers.
                } catch (ex) {
                    console.warn("Copy to clipboard failed.", ex);
                    return false;
                } finally {
                    document.body.removeChild(textarea);
                }
            }
        }
    
    </script>
    </body>
    </html>
    

    JSfiddle: https://jsfiddle.net/j4r9sxwt/

    The only change you need to make to your ASP code is:

    RESPONSE.WRITE "<td><a href='mailto:"&rsMembers("Email")&"' class='emails'>" & rsMembers("Email") & "</a></td>"& vbCrlf