skip to Main Content

I’m struggling with getting data from a div in PHP to process in an external JavaScript file.

In a PHP file I have a while-loop that generates, from a DB, a lot of HTML divs (up to 250 records at a time) with various values from the DB inside them. For each div/record there is a button so people can copy one specific value to their clipboard.

My problem is that I can’t select the value by ID as that is different and unpredictable for each element.

PHP simulation for testing purposes:

<?php
    
    // Simulate a loop
    echo '<div class="item_bio">';
        $value = uniqid();  // A randomly generated value to simulate the value we get from the DB
        echo '<span>'.$value.'<button class="buttons value_copy_button" id="'.$value.'" data-valuetocopy="'.$value.'">Copy</button></span>';
    echo '</div>';
    
    echo '<hr>';
    
    echo '<div class="item_bio">';
        $value = uniqid();  // A randomly generated value to simulate the value we get from the DB
        echo '<span>'.$value.'<button class="buttons value_copy_button" id="'.$value.'" data-valuetocopy="'.$value.'">Copy</button></span>';
    echo '</div>';
    // End of simulated loop
    
    echo '<script src="./assets/scripts/copy_value_to_clipboard_tester.js"></script>';

?>

JavaScript in copy_value_to_clipboard_tester.js:

const button = document.querySelector("button");

button.addEventListener("click", copyToClipboard);
      function copyToClipboard() {
        window.focus() // Focus the window to make sure writing to the clipboard is allowed
        navigator.clipboard.writeText(document.getElementById('copyValue').dataset.valuetocopy).then()
}

The challenge, and the reason I’m using an external JS file, is that I can’t use inline JavaScript because of the Content Security Policy (CSP) on the site that doesn’t allow any inline JS. That means I can’t use onclick with the unique value as I would normally have done.

How do I capture that $value from the button that was clicked if there are potentially hundreds of buttons with unpredictable IDs on the page?

2

Answers


  1. 2 things.

    You can select any element with querySelectorAll function using any CSS selector. Don’t have to be id.

    And once you attach the click event and it is triggered by a click, you can detect the originating element using ev.target parameter.

    var foo_click = function(ev) {
      var elem = ev.target
      console.log(elem.innerText)
    }
    
    // simple, 4 handlers
    document.querySelectorAll("button").forEach(function(elem) {
      elem.addEventListener('click', foo_click)
    })
    
    // efficient, 1 handler for the parent element
    document.querySelectorAll(".container").forEach(function(elem) {
      elem.addEventListener('click', foo_click)
    })
    <div class="container">
      <button>a</button>
      <button>b</button>
      <button>c</button>
      <button>d</button>
    </div>
    Login or Signup to reply.
  2. You can use event delegation to handle the clicks you are looking for.

    On any common ancestor of the buttons (document.body used below, but use a more specific container if you have one) add an event handler to respond to buttons that have the class "value_copy_button" – individual event handlers are not then needed. Example:

    document.body.addEventListener('click', event => {
      const button = event.target.closest("button");
      if(button.classList.contains("value_copy_button")) {
        copyToClipBoard(button.dataset.valueTocopy);
      }
    });
    

    For this particular code example you would also change copyToClipBoard to take a single string argument, not a reference to the button clicked.

    Note the event.target.closest('button') code is to allow any permitted content for button elements, not just plain text, … and no id values are required to be generated for the button elements.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search