chrome 分机中的手风琴使用香草 JS

Accordion in a chrome ext using vanilla JS

我想在我的 chrome 分机中创建一个简单的手风琴来显示数据。我正在使用 following JS tutorial,但我似乎很难注册点击。

我使用以下方法返回了一些数据:

//background.js

...

 // Looping through object's key value pair to place into divs
  for (const [key, value] of Object.entries(params)) {
    queryParams += `
      <div class="text-sm my-1">
        <span class="font-bold uppercase mr-1">${key}: </span><span class="font-normal font-mono capitalizev c-word-wrap">${value}</span>
      </div>
    `;
  }

return (completeData += `
    <div class="element my-3">

      <div id="click-parent" class="question flex justify-between px-6 py-4 bg-purple-500">
        <span class="text-base text-white font-bold">${pixelType}</span>
        <button id="click-btn">
          <i class="fas fa-plus-circle"></i>
        </button>
      </div>

<!-- OR -->
<div  class="question flex justify-between px-6 py-4 bg-purple-500">
        <span class="text-base text-white font-bold">${pixelType}</span>
        <button id="click-parent">
          <i id="click-btn" class="click-btn fas fa-plus-circle"></i>
        </button>
      </div>
<!-- end of other example -->

      <div class="answer hideText">
        <span id="pixel-url" class="c-word-wrap text-sm font-mono">${pixelUrl}</span>
          <span id="query-params">${queryParams}</span>
      </div>

    </div>
 
  `);
...

然后我将我的逻辑放在一个单独的文件中

//popup.js

document.addEventListener('DOMContentLoaded', function () {
  // get data
  document.getElementById('getCurrentURL').addEventListener('click', function () {
    chrome.runtime.sendMessage({}, function (response) {
      document.getElementById('data').innerHTML = response;
    });
  });

  // accordion code
  const elements = document.querySelectorAll('.element');

  elements.forEach((element) => {
    let btn = element.querySelector('.question button');
    let icon = element.querySelector('.question button i');
    var answer = element.lastElementChild;
    var answers = document.querySelectorAll('.element .answer');

    btn.addEventListener('click', () => {
      alert('clicked ');
      console.log('clicked');

      answers.forEach((ans) => {
        let ansIcon = ans.parentElement.querySelector('button i');
        if (answer !== ans) {
          ans.classList.add('hideText');
          ansIcon.className = 'fas fa-plus-circle';
        }
      });

      answer.classList.toggle('hideText');
      icon.className === 'fas fa-plus-circle'
        ? (icon.className = 'fas fa-minus-circle')
        : (icon.className = 'fas fa-plus-circle');
    });
  });
});

我正在像这样加载我的票据...

popup.html

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="../main.css"/>

    <!-- TailWind CSS -->
    <link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
  </head>
  <body class="flex flex-col min-h-screen">

    <main class="main flex-grow">

        <h1 class="text-center py-2 text-xl font-bold">HCP365 Debugger</h1>

        <section>
          <div id="data" class=""></div>
        </section>

    </main>

    <footer class="mb-4">
      <div class="flex justify-center">
        <button id="getCurrentURL" type="button" class="text-center text-base py-4 px-14 text-white font-bold drop-shadow bg-purple-500 capitalize outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150 hover:bg-purple-800">get url</button>
      </div>
    </footer>

    <!-- Scripts -->
    <script src="popup.js"></script>
    <script src="../background.js"></script>
    <!-- Accordion -->
    <script src="../fa.js"></script>
    <script src="../accordion.js"></script> 
  </body>
</html>

如果有人能指导我指出我哪里出错了,那就太好了。我也试过在 chrome ext 之外复制教程并且它工作得很好

文件结构

.
├── README.md
├── accordion.js
├── background.js
├── fa.js
├── images
│   ├── icon_128.png
│   ├── icon_16.png
│   ├── icon_32.png
│   └── icon_48.png
├── main.css
├── manifest.json
└── popup
    ├── popup.html
    └── popup.js

更新

我找到了一个存储库,其中有人创建了一个简单的计算器。在他们的 popup.js 中,他们有类似于

的东西
document.getElementById('clickBtn').addEventListener('click', () => {
    document.getElementById('textChange').innerHTML = 'hello i was clicked';
  });

我在 popup.html 中有一个 div 以及按钮。当我点击它时效果很好。

我继续这样添加...

document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('getCurrentURL').addEventListener('click', function () {
    chrome.runtime.sendMessage({}, function (response) {
      document.getElementById('data').innerHTML = response;
    });
  });

  // new code here --------------------------------
  document.getElementById('btn').addEventListener('click', () => {
    document.getElementById('textChange').innerHTML = 'hello i was clicked';
  });
  // end ---
});

使用动态按钮...但它不起作用!这现在令人沮丧……至少我们知道这是动态内容的问题。

您可能需要仅在 DOMContent 完全加载后才将侦听器添加到文档中。对于动态元素,您可能必须在元素容器上添加 onClick 侦听器

参见下面的示例:

// wait for the DOM to be loaded
document.addEventListener('DOMContentLoaded', function() {

  var checkPageButton = document.getElementById('checkPage');

  // add listener only after DOM loaded
  checkPageButton.addEventListener('click', function() {
    alert('clicked');
  }, false);
}, false);
<!doctype html>
<html>

<head>
  <title>Tester</title>
  <script src="popup.js"></script>
</head>

<body>
  <h1>Tester</h1>
  <button id="checkPage">Test this now!</button>
</body>

</html>

哇哦!!完成了!

当我在里面发布函数时,我意识到了一些事情

document.addEventListener('DOMContentLoaded', function () { ...

我变得不确定,然后我意识到 .btn 仅在内容加载后出现,该内容位于...

document.getElementById('getCurrentURL').addEventListener('click', function () {
    chrome.runtime.sendMessage({}, function (response) {
      document.getElementById('data').innerHTML = response;

所以我把它放在下面。

document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('getCurrentURL').addEventListener('click', function () {
    chrome.runtime.sendMessage({}, function (response) {
      document.getElementById('data').innerHTML = response;

      // ----------------------------------------------------------------
      const elements = document.querySelectorAll('.element');

      elements.forEach((element) => {
        let btn = element.querySelector('.question button');
        let icon = element.querySelector('.question button i');
        var answer = element.lastElementChild;
        var answers = document.querySelectorAll('.element .answer');

        btn.addEventListener('click', () => {
          answers.forEach((ans) => {
            let ansIcon = ans.parentElement.querySelector('button i');
            if (answer !== ans) {
              ans.classList.add('hideText');
              ansIcon.className = 'fas fa-plus-circle';
            }
          });

          answer.classList.toggle('hideText');
          icon.className === 'fas fa-plus-circle'
            ? (icon.className = 'fas fa-minus-circle')
            : (icon.className = 'fas fa-plus-circle');
        });
      });
      // end ---
    });
  });
});

一切都按预期进行。虽然我不得不使用 let btn = element.querySelector('.question button'); 而不是通过它的 ID 获取按钮,因为它只能工作一次