Skip to content
Advertisement

Dynamic Div Tags in a While Loop

I have a while loop that populates 4 div tabs (in one parent div) with PHP.

I also have a copy-to-clipboard script to copy text from a P tag. Unfortunately, this function works only if the tag and button have a unique Id.

So my question is this: How do I assign a sequential Id to my looped P tags? In the sense that I want the first set of tabs in the first populated div to have Ids 1,2,3,4, and the next one to have 5,6,7,8…and so on.

Here is the HTML in the PHP loop:

<div id='content' class='tab-content'>
   <div id='navpills-1' class='tab-pane active'>
      <p id='text'>Text to be copied to clipboard.</p>
      <button id='jsbtn' class='btn jsbtn' onclick='copyToClipboard('p#text')'>Copy</button>
   </div>
</div>

Here is the script I’m using to copy text from the P tag to the clipboard:

<script>
    function copyToClipboard(element) {
      var $temp = $("<textarea>");
      var brRegex = /<brs*[/]?>/gi;
      $("body").append($temp);
      $temp.val($(element).html().replace(brRegex, "rn")).select();
      document.execCommand("copy");
      $temp.remove();
    }
</script>

Advertisement

Answer

If you are not committed to using jQuery then you can easily accomplish your goal with some fairly basic, vanilla Javascript. The Clipboard API provides the modern solution for copying text (& other things) to & from the system clipboard.

In general working with IDs can become troublesome as they need to be unique within the DOM so where the same functionality needs to be applied to multiple it items you must try to do what you were initially hoping to do – assign sequential IDs or some other such solution and reference that ID in the function call. This does not scale well and better options exist.

The following uses no ID attributes anywhere – instead the event handler assigned to each button uses the event to identify which element was clicked ( invoked the handler ) and from that node it is possible, given that you know the DOM structure, to find other nodes of interest. In the code below the event.target refers to the button – from there we find it’s parent and from that parent we find the specific P element whose content is to be copied. The method suggested by @CBroe does this using jQuery methods – something I’m not familiar with.

<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>Basic Clipboard Copy Example</title>
    </head>
    <body>
        <div class='tab-content'>
           <div class='tab-pane active'>
              <p class='copy'>Text to be copied to clipboard.</p>
              <button class='btn jsbtn'>Copy</button>
           </div>
           <div class='tab-pane active'>
              <p class='copy'>Some other text to be copied to clipboard.</p>
              <button class='btn jsbtn'>Copy</button>
           </div>
           <div class='tab-pane active'>
              <p class='copy'>Guess what...more text and not an ID in sight</p>
              <button class='btn jsbtn'>Copy</button>
           </div>
           <div class='tab-pane active'>
              <p class='copy'>And the final Paragraph and final chapter and final word.</p>
              <button class='btn jsbtn'>Copy</button>
           </div>
        </div>
        
        <textarea cols=100 rows=10></textarea>
        
        <script>
            document.querySelectorAll('button.jsbtn').forEach( bttn=>bttn.addEventListener('click',e=>{

              const pttn=/<brs*[/]?>/gi;
              const paragraph=e.target.parentNode.querySelector('p.copy');
              const textarea=document.querySelector('textarea');

              // writeText copies text to the clipboard
              navigator.clipboard.writeText( paragraph.innerHTML.replace( pttn, String.fromCharCode( 10 ) ) )
                .then(
                  ()=>{
                    /* 
                       All good... and to illustrate reading this copied text... 
                       readText - reads from the clipboard
                    */
                    navigator.clipboard.readText()
                        .then( text=>{
                            textarea.value=text;
                        })
                  },
                  (e)=>{console.log( 'error: %s',e.message )}
                )
            }));
        </script>
    </body>
</html>
Advertisement