【问题标题】:Javascript Copy function handle not workingJavascript复制函数句柄不起作用
【发布时间】:2021-03-21 03:55:33
【问题描述】:

我正在为代码块编写复制按钮,但该按钮无法处理“复制”事件。

按钮是使用createElement 方法创建的,并且在附加到块之前,通过foreach 循环将事件添加到按钮中,并使用addEventListener 到按钮。

JSFiddle Link 的块

创建按钮代码:

const textspan = document.createElement("SPAN");
const bgbutton = document.createElement("BUTTON");

bgbutton.classList.add("btnCopy", "badge");
bgbutton.innerText = "copy";
bgbutton.addEventListener('click', copytextHandle);

textspan.appendChild(bgbutton);

const codeSyn = document.querySelectorAll("pre");

codeSyn.forEach(function(el) {
    el.insertAdjacentElement('afterbegin', textspan);
})

在我的文本中,我有三个块,但只有一个按钮可见(最后一个),前两个块没有按钮。

另外,点击事件和功能不能用click钩子实现。问题很直接,点击事件,请说明导致错误的原因。

window.addEventListener('load', function() {
    var y = document.querySelectorAll("pre code");
    
    for(var i = 0; i < y.length; i++) {
        y[i].innerHTML = y[i].innerHTML.replace(/^\r?\n/, "");
    }
    
    const textspan = document.createElement("SPAN");
    const bgbutton = document.createElement("BUTTON");
    
    bgbutton.classList.add("btnCopy", "badge");
    bgbutton.innerText = "copy";
    bgbutton.addEventListener('click', copytextHandle);

    textspan.appendChild(bgbutton);
    
    const codeSyn = document.querySelectorAll("pre");
    
    codeSyn.forEach(function(el) {
        el.insertAdjacentElement('afterbegin', textspan);
    })  
})

const copytextHandle = (e) => {
    const codeBlock = document.querySelectorAll(".hljs-ln")[e.target.dataset.idx];
    const text = codeBlock
       .innerText
       .trim()
       .replace(/\s+/g, " ")
       .replace(/}/g, "}\n")
          .replace(/{ /g, "{\n  ")
          .replace(/;/g, ";\n  ")
        copySuccess.classList.remove('hide');
    navigator.clipboard.writeText(text).then(() => setTimeout(() => bgbutton.innerHTML("Copied"),200),
      (e) => {
        console.log('Error writing to the clipboard', e.message);
         copySuccess.classList.add('hide');
       }
    );  
};
span > button.btnCopy {
  position: absolute;
  right: 0;
  margin-top: 0.6rem;
}

pre {
  position: relative;
}

.btnCopy{border:none; background-color: #e8e8e8;}
/*background-color:a5a5a5, 9c9c9c*/
.btnCopy:hover{background-color: #585858}
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Testing HighlightJS</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/styles/routeros.min.css">
</head>
<body>
    <h3>Testing HighlightJS Multiple blocks</h3>
    <h4>First Code block</h4>
    <pre><code class="language-css">
    .class{
    font-size: 0.85rem;
    font-weight: 600;
    font-family: monospace;
    }
    h1 .header{
    font-size: 1.5rem;;
    font-family: Arial;
    }
    </code></pre>
    
    <h4>Second Code block</h4>
    <pre><code class="language-css">
    .class{
    font-size: 0.85rem;
    font-weight: 600;
    font-family: monospace;
    }
    h1 .header{
    font-size: 1.5rem;;
    font-family: Arial;
    }
    </code></pre>
    
    <h4>Third Code block</h4>
    <pre><code class="language-css">
    .class{
    font-size: 0.85rem;
    font-weight: 600;
    font-family: monospace;
    }
    h1 .header{
    font-size: 1.5rem;;
    font-family: Arial;
    }
    </code></pre>
    
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/highlight.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/languages/css.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.6.0/highlightjs-line-numbers.min.js"></script>
<script>hljs.highlightAll(); hljs.initLineNumbersOnLoad();</script>
    
</body>
</html>

【问题讨论】:

  • 您只获得了最后一个代码块上的按钮,因为您只创建了一个按钮。在您的循环中,您将其添加到第一个代码块,然后将其 移动 到第二个代码块,然后将其移动到最后一个代码块。您需要cloneNode 按钮将其添加到每个块中。

标签: javascript


【解决方案1】:

单击按钮copy 后,您可以使用以下代码访问&lt;table&gt; 元素,该元素位于您的&lt;code&gt; 元素之一中:

const codeBlock = e.target.parentNode.nextSibling.children[0];

一旦应用,&lt;code&gt; 中的文本将被复制到变量text,我们可以通过运行下面的代码并检查控制台输出来查看。

copy 按钮现在出现在所有&lt;code&gt; 块上。我在codeSyn.forEach(function(el) { ... } 中添加了用于创建buttonspan 的代码,以便为您正在迭代的每个&lt;pre&gt; 创建新元素。

出现的另一个问题是:

未捕获的 ReferenceError:未定义 copySuccess

要解决此错误,您应该将具有类 hide 的 HTML 元素分配给变量 copySuccess,这样才能正常工作:

copySuccess.classList.remove('hide');

检查以下代码:

window.addEventListener('load', function() {
    var copySuccess = document.getElementById("copySuccess");
    var y = document.querySelectorAll("pre code");
    
    for(var i = 0; i < y.length; i++) {
        y[i].innerHTML = y[i].innerHTML.replace(/^\r?\n/, "");
    }
    
    const codeSyn = document.querySelectorAll("pre");
    
    codeSyn.forEach(function(el) {
        const textspan = document.createElement("SPAN");
        const bgbutton = document.createElement("BUTTON");
    
        bgbutton.classList.add("btnCopy", "badge");
        bgbutton.innerText = "copy";
        bgbutton.addEventListener('click', copytextHandle);

        textspan.appendChild(bgbutton);
        el.insertAdjacentElement('afterbegin', textspan);
    })  
})

const copytextHandle = (e) => {
    const codeBlock = e.target.parentNode.nextSibling.children[0];
    const text = codeBlock
       .innerText
       .trim()
       .replace(/\s+/g, " ")
       .replace(/}/g, "}\n")
          .replace(/{ /g, "{\n  ")
          .replace(/;/g, ";\n  ");
    navigator.clipboard.writeText(text).then(() => setTimeout(() => e.target.innerHTML = "copied",2000),
      (e) => {
        console.log('Error writing to the clipboard', e.message);
      }
    );
};
span > button.btnCopy {
  position: absolute;
  right: 0;
  margin-top: 0.6rem;
}

pre {
  position: relative;
}

.hide {
  display: none;
}

.btnCopy{border:none; background-color: #e8e8e8;}
/*background-color:a5a5a5, 9c9c9c*/
.btnCopy:hover{background-color: #585858}
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Testing HighlightJS</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/styles/routeros.min.css">
</head>
<body>
    <h3>Testing HighlightJS Multiple blocks <span id="copySuccess" class="hide">Copied...</span></h3>
    <h4>First Code block</h4>
    <pre><code class="language-css">
    .class{
    font-size: 0.85rem;
    font-weight: 600;
    font-family: monospace;
    }
    h1 .header{
    font-size: 1.5rem;
    font-family: Arial;
    }
    </code></pre>
    
    <h4>Second Code block</h4>
    <pre><code class="language-css">
    .class{
    font-size: 0.85rem;
    font-weight: 600;
    font-family: monospace;
    }
    h1 .header{
    font-size: 1.5rem;
    font-family: Arial;
    }
    </code></pre>
    
    <h4>Third Code block</h4>
    <pre><code class="language-css">
    .class{
    font-size: 0.85rem;
    font-weight: 600;
    font-family: monospace;
    }
    h1 .header{
    font-size: 1.5rem;
    font-family: Arial;
    }
    </code></pre>
    
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/highlight.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/languages/css.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.6.0/highlightjs-line-numbers.min.js"></script>
<script>hljs.highlightAll(); hljs.initLineNumbersOnLoad();</script>
    
</body>
</html>

【讨论】:

【解决方案2】:

发生的事情是,您将循环中的同一个按钮一直移动到最后一个 pre。使用例如。 cloneNode 为每个前置元素创建一个新按钮。

简单的移动场景 (https://jsfiddle.net/jtg6fczd/)

document.querySelector("div").append(button) // adds button to div
document.body.append(button) // moves button out of div 

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 2011-07-13
  • 1970-01-01
  • 1970-01-01
  • 2018-08-28
  • 2012-11-30
相关资源
最近更新 更多