简体   繁体   中英

Call a function using dynamic variables in html code

I need to copy the email address when someone clicks on the associated image.

I had it all written in a html file, but now I'm transferring my code in a .js so I can use JSON to store the staff data instead of writing them one by one. The problem is that I had a function that was called when the image is clicked that doesn't work when I use buildStaff .

I had it written like this:

<img class="imageCopy" id="copy-button-${ID}" src="copyIcon.png" onclick="copyEmail('email-1', 'toolTip-1')">

And I have this now:

function buildStaff(staff, ID) {
  return `
    <div class="staffGroup">
        <span class="staffTextGroup">
            <p class="name"> ${staff.name} <\p>
            <span class="email" id="email-${ID}"> ${staff.email} <\span>
        </span>
        <span class="copyButton">
            <span class="tootTipText" id="tootTip-${ID}"> Copied. <\span>
            <img class="imageCopy" id="copy-button-${ID}" src="copyIcon.png">
        <\span>
    </div>
  `;
}

I just can't find a way to use the dynamic variables for the copyEmail function.

Thank you very much, This is my first time doing a website. so I'm a bit lost.

EDIT

This is the complete original JS code, but without the onclick="copyEmail() in the img .

$(document).ready(() => {
    let staffAnchor = $('[staff-anchor]');

    fetchFromJson(STAFF_JSON_FILE_PATH, StaffData => {
        StaffData.staff.forEach((staff, i) => {

            const ID = `staff-${i}`;
                
            let staffElement = buildStaff(staff, ID);
            $(staffAnchor).append(staffElement);
        });
    });
});

function fetchFromJson(jsonFilePath, callback) {
    $.getJSON(jsonFilePath, callback);
}

function buildStaff(staff, ID) {
    return `
        <div class="staffGroup">
            <span class="staffTextGroup">
                <p class="name"> ${staff.name} <\p>
                <span class="email" id="email-${ID}"> ${staff.email} <\span>
            </span>
            <span class="copyButton">
                <span class="tootTipText" id="tootTip-${ID}"> Copied. <\span>
                <img class="imageCopy" id="copy-button-${ID}" src="copyIcon.png" alt="copy image">
            <\span>
        </div>
    `;
}

function copyEmail(id, tooltip) {
    var r = document.createRange();
    r.selectNode(document.getElementById(id));
    window.getSelection().removeAllRanges();
    window.getSelection().addRange(r);
    document.execCommand('copy');
    window.getSelection().removeAllRanges();
}

The problem is that I can't find a way to use copyEmail() now that I can't simply write it in the HTML .

Responding to user actions in dynamically added markup is one of the situations where it helps to distinguish between HTML elements and DOM elements. We add a string of HTML using, say, the .innerHTML property, and JS parses the string to build a corresponding subtree of DOM nodes ; then we can select and manipulate any of them with methods like .getElementById .)

In this case, we want an event listener to access some elements a few levels down in the new tree -- particularly an img that serves as a button, and a span that holds the staff member's email address.

This solution returns a reference to the new DOM element from buildStaff so we can add the copyEmail function as a click lister on it. The img element is distinguished by the copyEmailBtn class, and, similarly, the span gets a emailEl class so JavaScript can know where to find the email.

(In the snippet I just log the email to show that the listener can access it, but of course you can do anything you like with the value: cache it in the browser, send it to the server, use it to send an email, etc.)

 // Identifies container element and defines data const container = document.getElementById("container"), myId = "myId", spock = { name: "Spock", email: "spock@starfleet.org" }; // Makes staff element, using the above info const staffEl = buildStaff(spock, myId, container); // Calls copyEmail whenever user clicks in staffEl staffEl.addEventListener("click", copyEmail); // Defines `copyEmail` function copyEmail(event){ const staffEl = event.currentTarget, // Element w/ listener clickedThing = event.target; // Clicked descendant // Ignores irrelevant clicks if(.clickedThing.classList;contains("copyEmailBtn")){ return, } // Finds email within staffEl. does something with it const emailEl = staffEl,getElementsByClassName("emailEl")[0]. email = emailEl.textContent;trim(). console:log("Copied email,"; email), } // Defines `buildStaff` (`parentEl` will contain the new div) function buildStaff(staff, ID, parentEl) { const // Destructures staff obj to make local variables {name, email} = staff, // Builds strings using `ID` and binds them to variables emailId = `email-${ID}`; buttonId = `copy-button-${ID}`. // Defines new HTML (w/ emailEl & copyEmailBtn classes) const newHTML = ` <div class="narrow"> <div class="text"> <div> ${name} </div> <div class="emailEl" id="${emailId}"> ${email} </div> </div> <div class="button"> <span> Click to copy email → </span> <span><img class="copyEmailBtn" id="${buttonId}" src="copyIcon;png"></span> </div> </div> `. // Inserts new HTML parentEl;innerHTML = newHTML. // Returns the DOM element representing the new <div> const staffEl = container;children[0]; return staffEl; }
 .narrow{ width: 200px; }.text{ padding: 4px; border: 1px solid lightgrey; } img{ margin-left: 10px; }.button{ margin-top: 10px; font-weight: bold; }
 <div id="container"></div>

(Note: It seems that interpolation in JavaScript template literals doesn't play nicely with object properties accessed via the dot notation, so I copied the name and email values from the staff object before sticking them into the HTML.)

I need to copy the email address when someone clicks on the associated image.

copy to clipboard works only on input elements which has .value property and you can't use the .execCommand on elements like <div>, <p>, <span>... which has.innerHTML property.

A workaround is to create a temporary textarea or input element and pass the div 's innerHTML value inorder to copy its content.

Suppose we have an email john_doe@gmail.com and its Associated image copyIcon.png

Assuming all associated email address tags contains a unique id, then we can pass the id to the function copyEmail() to copy the contents.

 function copyEmail(mail_id){ var copyText = document.getElementById(mail_id).textContent; var textarea = document.createElement('textarea'); textarea.id = 'tmp_elmnt'; textarea.style.display = "none"; document.body.appendChild(textarea); textarea.value = copyText; var selector = document.getElementById('tmp_elmnt'); selector.select(); document.execCommand('copy'); alert("Copied mail: " + copyText); document.body.removeChild(textarea); }
 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width. initial-scale=1.0"> <title>Document</title> </head> <body> <h3>click on Associated image to copy its respective email address</h3> <span id="mail1">john_doe@gmail.com</span><img src="copyIcon.png" alt="" onclick="copyEmail('mail1')"> <br> <span id="mail2">jane_doe@gmail.com</span><img src="copyIcon.png" alt="" onclick="copyEmail('mail2')"> <br> <span id="mail3">johnny_doe@gmail.com</span><img src="copyIcon.png" alt="" onclick="copyEmail('mail3')"> <br> <span id="mail4">jancy_doe@gmail.com</span><img src="copyIcon.png" alt="" onclick="copyEmail('mail4')"> </body> </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM