【问题标题】:Create copy buttons alert from javascript从 javascript 创建复制按钮警报
【发布时间】:2021-04-27 04:23:18
【问题描述】:

您好,我是新的网络开发人员,正在开发一个报价网站项目。

我创建了一个 Html 页面,其中有一些引号,所有引号下方都有一个复制按钮。

您可以访问我的 CodePen 清楚地理解问题 https://codepen.io/Akash11166666/pen/JjRzqzp

我已经显示了来自 Javascript 的复制按钮和引号,因此您无法在 HTML 中找到这些元素。

正如您所见,我的 CodePen 运行良好,但我们无法知道文本是否被复制。所以我需要一个<span>Copied</span> 在单击每个复制按钮时可见,而不直接将<span>Copied</span> 插入HTML,即来自与创建复制按钮相同的javascript。它们应该是动态的,以至于对于各个复制按钮,span 元素应该在几秒钟后可见和不可见。

我尝试了很多方法来解决这个问题,但知道它们可以工作,虽然我是 javascript 新手,但我对此了解不多。

我的 CodePen 项目供参考

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."
  },
  ];
}
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
);
main();
.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;
}
<!DOCTYPE html>
<html>

<head>
  <style>
    /* Main Status */
  </style>
</head>

<body>
  <a href="hindinj.html">caeman</a>
  <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>20</option>
          <option>10</option>
          <option>20</option>
        </select>
      </div>
      <label>(<span class="result-count"></span> items)</label>
    </div>

    <script>
    </script>
</body>

</html>

我再次告诉我的问题,当单击每个复制按钮时,我需要一个 &lt;span&gt;Copied&lt;/span&gt; 可见,而不直接将 &lt;span&gt;Copied&lt;/span&gt; 插入 HTML,即来自与复制按钮相同的 javascript已创建。

我非常感谢那些回答这个问题的人。

【问题讨论】:

标签: javascript html scripting dynamic-html


【解决方案1】:

您可以在调用document.execCommand('Copy') 之后立即调用函数来执行此操作。在下面查看我的 sn-p 以获取 showCopied 和 CSS 类 hasCopied。这应该会暂时显示跨度,并使用setTimeout 可以在给定时间(以毫秒为单位)(2000 = 2 秒)后将其删除。

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."
    },
  ];
}
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');

      showCopied();

      textArea.remove();

    }

  },

  false

);

function showCopied() {
  const copiedElement = document.createElement('span');
  copiedElement.innerHTML = "Copied";
  copiedElement.setAttribute("class", "hasCopied");
  resultEl.appendChild(copiedElement);
  setTimeout(() => {
    resultEl.removeChild(copiedElement);
  }, 2000);
}

main();
/* 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;
}

.hasCopied {
  color: black;
  position: absolute;
  top: 30%;
  right: 10%;
}
<!DOCTYPE html>
<html>

<body>
  <a href="hindinj.html">caeman</a>
  <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>20</option>
          <option>10</option>
          <option>20</option>
        </select>
      </div>
      <label>(<span class="result-count"></span> items)</label>
    </div>
</body>

</html>

【讨论】:

    【解决方案2】:

    您可以向您的按钮添加一个函数onclick,每当单击它时,它将在x 秒后使用setTimout() 添加和删除span

    我还在css 上添加了一个class 用于设置跨度的样式,但您可以随时删除或编辑它。

    我在js 上添加的代码只有函数showCopied(),它将创建element 并添加到body。还添加了fade()unfade() 方法,它们将执行这两种方法使用setInterval() 的元素的fadeunfade

    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" onclick="showCopied();">Copy</button></div></div>`).join('');
      resultEl.append(contents);
    };
    
    function showCopied() {
      let spanCopied = document.createElement('span');
      spanCopied.innerHTML = "Copied!";
      spanCopied.classList.add("spanCopied");
      document.body.appendChild(spanCopied);
      fade(spanCopied);
      
      setTimeout(function() {
        document.body.removeChild(spanCopied);
      }, 1400);
    }
    
    function fade(element) {
        var op = 1;  // initial opacity
        var timer = setInterval(function () {
            if (op <= 0.1){
                clearInterval(timer);
                element.style.display = 'none';
            }
            element.style.opacity = op;
            element.style.filter = 'alpha(opacity=' + op * 100 + ")";
            op -= op * 0.1;
        }, 50);
    }
    
    function unfade(element) {
        var op = 0.1;  // initial opacity
        element.style.display = 'block';
        var timer = setInterval(function () {
            if (op >= 1){
                clearInterval(timer);
            }
            element.style.opacity = op;
            element.style.filter = 'alpha(opacity=' + op * 100 + ")";
            op += op * 0.1;
        }, 10);
    }
    
    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."
        },
    ]; 
    }
    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
    
    );
    main();
    /* Main Status */
    body {
      position: relative;
    }
    .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);
    }
    .spanCopied {
      background-color: #f2f2f2;
      border: 1px solid #f2f2f2;
      border-radius: 50px;
      position: fixed;
      left: 0;
      right: 0;
      top: 80vh;
      margin: auto;
      padding: 10px;
      z-index: 3;
      max-width: 90px;
      height: 20px;
      text-align: center;
      box-shadow: 0 1px 9px 0 rgba(0,0,0,.2);
      transition: .3s;
      opacity: 0;
    }
    .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;
    }
    <html>
    
    <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>

    更多关于setTimout的信息可以在这里找到:https://www.w3schools.com/jsref/met_win_settimeout.asp

    更多关于 setInterval 的信息可以在这里找到:https://www.w3schools.com/jsref/met_win_setinterval.asp

    【讨论】:

      猜你喜欢
      • 2021-04-08
      • 1970-01-01
      • 1970-01-01
      • 2020-01-27
      • 2017-02-06
      • 1970-01-01
      • 1970-01-01
      • 2011-06-24
      • 1970-01-01
      相关资源
      最近更新 更多