Ashika Kamath
Ashika Kamath

Reputation: 31

Create copy button in Javascript

Hey am new web developer and I have been working on a project. I was working on a quote website. Firstly you visit my CodePen and visit my project.

Please visit my CodePen website then answer or else you cannot understand the question or else I have written my project in the bottom. https://codepen.io/Akash11166666/pen/JjRzqzp

As you saw in my pen there are many copy button under each quote, but they are not working. Although I have tried many Javascript but know of them work.

Remember that the <div>,<p> and <button>Copy</button> elements for quotes are not in html because the are created by Javascript. Just see the javascript carefully.

For reference I will give my Javascript which I tried but it is not working.

The Javascript (Doesn't Work)

var buttons = document.getElementsByClassName('copystatus');
for (let button of buttons) {
  button.addEventListener('click', function() {
     let statusElement = this.closest('.latestatus');
     let textToCopy = statusElement.getElementsByClassName('copytxt')[0].innerHTML;
    
    copyTextToClipboard(textToCopy);
    addCopyStatusAlert(this.parentNode);
  });
}
function copyTextToClipboard(text) {
  const copyText = document.createElement('textarea');
  copyText.style.position="absolute";
  copyText.value = text;

  document.body.appendChild(copyText);
  copyText.select();
  document.execCommand('copy');
  document.body.removeChild(copyText);
}

function addCopyStatusAlert(element) {
  if (!element.getElementsByClassName('status-copy-alert').length) {
    let copyAlertElement = document.createElement('span');
    copyAlertElement.classList.add('status-copy-alert')
    let copyMessage = document.createTextNode('Copied!');
    copyAlertElement.appendChild(copyMessage);
      element.appendChild(copyAlertElement);
    setTimeout(function() {
      element.removeChild(copyAlertElement);
    }, 700);
  }
}
    

Again I will tell my problem that, I need the copy button to be worked so that it could copy the respective quote when respective button is clicked. Please visit my pen to understand it clearly or see below.

For reference my CodePen project

<html>
<head>
<style>
/* Main Status */
.mainStatus{
 background-color: #fff;
 border-radius: 10px;
 box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
 padding-bottom: 5px;
 margin: 10px;
 margin-top: 10px;
 max-width: 95%;
 width: 95%;
 height: auto;
 border-radius: 20px;
 box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
}
.statusHeading{
 text-align: center;
 background-color: #18b495;
 color: #ffffff;
 padding: 10px 10px 10px 10px;
 border-top-right-radius: 20px;
 border-top-left-radius: 20px;
 font-weight: 300;
 font-size: 20px;
}
.latestatus{
 display: grid;
 height: auto;
 box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
 padding: 10px 20px 10px 20px;
 border-radius: 30px;
 margin: 10px 10px 10px 10px;
 width: 445px;
 min-height: 130px;
 font-size: 15px;
}
.allStatus{
 display: flex;
}
.latestatus p{
 width: auto;
 position: relative;
}
.copystatus{
 font-weight: 500;
 text-transform: uppercase;
 width: 100px;
 height: 40px;
}
.pagable {
  display: flex;
  flex-direction: column;
  border: var(--pageable-border);
  background: var(--pageable-background);
}

.pagable .pagable-results {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 0.25em;
}

.pagable .pagable-status {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  padding: 0.25em;
  background: var(--pageable-status-background);
}

.pagable .pagable-actions {
  display: grid;
  grid-auto-flow: column;
  grid-gap: 0.25em;
}
.pagable .pagable-actions input[name="page-curr"] {
  width: 3em;
}
</style>
</head>
<body>
  <div class="mainStatus">
   <h2 class="statusHeading">Latest English Status</h2>
<div class="allquotes"></div>
<div class="pagable-status">
  <label>Page <span class="page-no-curr">1</span> of <span class="page-no-count">1</span></label>
  <div class="pagable-actions">
    <button class="page-btn-first">&#x226A;</button>
    <button class="page-btn-prev">&#60;</button>
    <input type="number" name="page-curr" min="1" value="1" />
    <button class="page-btn-next">&#62;</button>
    <button class="page-btn-last">&#x226B;</button>
    <select name="page-size">
      <option>5</option>
      <option>10</option>
      <option>20</option>
    </select>
  </div>
  <label>(<span class="result-count"></span> items)</label>
</div>
<script>
const resultEl = document.querySelector('.allquotes');
const pageSize = document.querySelector('select[name="page-size"]');
const pageCurr = document.querySelector('input[name="page-curr"]')
const resultCount = document.querySelector('.result-count')
const pageNoCurr = document.querySelector('.page-no-curr');
const pageNoCount = document.querySelector('.page-no-count')
const btnFirst = document.querySelector('.page-btn-first');
const btnPrev = document.querySelector('.page-btn-prev');
const btnNext = document.querySelector('.page-btn-next');
const btnLast = document.querySelector('.page-btn-last');

let results = [];

const getResultCount = () => results.length;
const getPageSize = () => +pageSize.value;
const getCurrPage = () => +pageCurr.value;
const getPageCount = () => Math.ceil(getResultCount() / getPageSize());

const pageResponse = (records, pageSize, page) =>
  (start => records.slice(start, Math.min(records.length, start + pageSize)))
  (pageSize * (page - 1));

const main = async() => {
  btnFirst.addEventListener('click', navFirst);
  btnPrev.addEventListener('click', navPrev);
  btnNext.addEventListener('click', navNext);
  btnLast.addEventListener('click', navLast);
  pageSize.addEventListener('change', changeCount);

  results = await retrieveAllQuotes();
  updatePager(results);
  redraw();
};
const redraw = () => {
  resultEl.innerHTML = '';
  const paged = pageResponse(results, getPageSize(), getCurrPage());
  const contents = document.createElement('div');
  contents.innerHTML = paged.map(record => `<div class='latestatus'><p class='copytxt'>${record.quotes}</p><div> <button class="copystatus btn">Copy</button></div></div>`).join('');
  resultEl.append(contents);
};

const navFirst = (e) => {
  pageNoCurr.textContent = 1;
  pageCurr.value = 1;
  redraw();
}

const navPrev = (e) => {
  const pages = getPageCount();
  const curr = getCurrPage();
  const prevPage = curr > 1 ? curr - 1 : curr;
  pageCurr.value = prevPage;
  pageNoCurr.textContent = prevPage;
  redraw();
}

const navNext = (e) => {
  const pages = getPageCount();
  const curr = getCurrPage();
  const nextPage = curr < pages ? curr + 1 : curr;
  pageCurr.value = nextPage;
  pageNoCurr.textContent = nextPage;
  redraw();
}

const navLast = (e) => {
  pageNoCurr.textContent = getPageCount();
  pageCurr.value = getPageCount();
  redraw();
}

const changeCount = () => {
  updatePager();
  redraw();
};

const updatePager = () => {
  const count = getPageCount();
  const curr = getCurrPage();
  pageCurr.value = curr > count ? 1 : curr;
  pageNoCurr.textContent = curr > count ? 1 : curr;
  pageNoCount.textContent = count;
  resultCount.textContent = getResultCount();
};

const retrieveAllQuotes = async function() {

  // write your asynchronous fetching here

  return[{
      quotes: "1The cat is better than dog."
    },
    {
      quotes: "2Google is a open source library."
    },
    {
      quotes: "3Cats are better than ferrets."
    },
    {
      quotes: "4Love books."
    },
    {
      quotes: "5Life is short make it possible."
    },
    {
      quotes: "6The cat is better than dog"
    },
    {
      quotes: "7Google is a open source library."
    },
    {
      quotes: "8Cats are better than ferrets."
    },
    {
      quotes: "9Love books."
    },
    {
      quotes: "10Life is short make it possible."
    },
]; 
}
main();
</script>
</body>
</html>

Upvotes: 2

Views: 927

Answers (3)

robbinc91
robbinc91

Reputation: 524

I just checked your codepen. Just add this onclick='copyTextToClipboard("${record.quotes}")' in your copy button.

I mean, change this:

contents.innerHTML = paged.map(record => `<div class='latestatus'><p class='copytxt'>${record.quotes}</p><div> <button class="copystatus btn" >Copy</button></div></div>`).join('');

into this:

contents.innerHTML = paged.map(record => `<div class='latestatus'><p class='copytxt'>${record.quotes}</p><div> <button class="copystatus btn" onclick='copyTextToClipboard("${record.quotes}")'>Copy</button></div></div>`).join('');

Your copyToClipboard function is OK, add it to your codepen too, and you're good to go

Upvotes: 1

Hassan Imam
Hassan Imam

Reputation: 22574

You can attach the event handler to parent container of your quotes div and inside the handler determine the clicked button and find the quote in it. Once you have the quote you can copy to the clipboard.

document.querySelector('.allquotes').addEventListener(
  'click',
  function (e) {
    e.preventDefault();
    if (e.target && e.target.matches('.copystatus')) {
        const quote = e.target.parentNode.closest('.latestatus')
            .childNodes[0].textContent;
        const textArea = document.createElement('textarea');
        textArea.value = quote;
        document.body.appendChild(textArea);
        textArea.select();
        document.execCommand('Copy');
        textArea.remove();
    }
  },
  false
);

Upvotes: 3

Muhammad Minhaj
Muhammad Minhaj

Reputation: 129

You can try like this code below:

let btn = document.querySelector("#Your-Btn-ID")
let text = document.querySelector("#Your-Text-ID")

btn.addEventListener('click',()=>{

   text.disabled = false 
   text.select()
   text.setSelectionRange(0, 99999)
   document.execCommand('copy')
   document.getSelection().removeAllRanges()
   text.disabled = true
          
})

Upvotes: 0

Related Questions