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
2 things.
You can select any element with
querySelectorAll
function using any CSS selector. Don’t have to beid
.And once you attach the
click
event and it is triggered by a click, you can detect the originating element usingev.target
parameter.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: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.