本例中如何使用JavaScript模仿自定义filter/selector?

How to use JaveScript to imitate the custom filter/selector in this example?

我在this site(基于MediaWiki)上看到了这个自定义过滤器,想在我的同人圈里模仿它的功能,以自学。

我玩的table的代码太长了,直接放in here.


[2019-05-15]

我根据@Kévin Bibollet 的例子修改了我的代码后,遇到了一个新问题。

这是我的js代码,只是将新功能添加到一个按钮进行测试。

//different types of data from the table
const type = document.querySelectorAll("tr td:nth-last-child(1)");
const kiwameStats = document.querySelectorAll("tr td:nth-last-child(2)");

//buttons
const tantouFilter = document.querySelector("div#Tantou");
const wakiFilter = document.querySelector("div#Wakizashi");
const tokuFilter = document.querySelector("div#Toku");
const kiwameFilter = document.querySelector("div#Kiwame");

//path for buttons' image
const waki = "https://vignette.wikia.nocookie.net/a-normal-playground/images/b/b8/Wakizashi.png";
const wakiClicked = "https://vignette.wikia.nocookie.net/a-normal-playground/images/1/1f/Wakizashi-full.png";

//bind events to buttons
wakiFilter.addEventListener("click", () => (filter(waki, wakiClicked, type)));

//general filter method
function filter(unclickedImageSrc, clickedImageSrc, data){
    //store button's img and img's src for future use
    currentImg = this.querySelector("img");
    currentImgSrc = currentImg.getAttribute("src");
    //is the button being clicked
    isFiltered = (currentImgSrc === clickedImageSrc);
    if(isFiltered){ //button was clicked, undo the filtering
        currentImg.setAttribute("src", unclickedImageSrc);
        for(i = 0; i < data.length; i++){
            if(!data[i].innerHTML.includes(this.id)){ 
                data[i].parentElement.style.display = " ";
            }
        }
    }else{ //button isn't clicked, start filtering
        currentImg.setAttribute("src", clickedImageSrc);
        for(i = 0; i < data.length; i++){
            if(!data[i].innerHTML.includes(this.id)){ 
                data[i].parentElement.style.display = "none";
            }
        }
    }
}

当我将它们放入我的 common.js 并在 test page 上尝试时,我的控制台显示 错误:JavaScript 解析错误:解析错误:丢失)在第 16 行 'User:somebody/common.js' 的括号中 这是将事件侦听器绑定到按钮的行 (wakiFilter.addEventListener("click", () => (filter(waki, wakiClicked, type)));)

然后我把代码扔到控制台,点击按钮后,我得到: 类型错误:this.querySelector 不是一个函数

不确定是什么原因造成的。我是在错误地编写我的箭头函数还是...?


[2019-05-14]

我确实弄清楚了如何使用 addEventListener() 一键过滤掉某些列。添加到两个按钮用于测试目的:

//type filter
var type = document.querySelectorAll("tr td:nth-last-child(1)");

//for tantou
const tantouFilter = document.getElementById("Tantou");
tantouFilter.addEventListener("click", function(e){
    for(i = 0; i < type.length; i++){
    if(!type[i].innerHTML.includes(tantouFilter.id)){
        type[i].parentElement.style.display = "none";
    }
  }
});
//for wakizashi
const wakiFilter = document.getElementById("Wakizashi");
wakiFilter.addEventListener("click", function(e){
    wakiFilter.innerHTML = "[[File:Wakizashi-full.png|30px|link=]]";
    for(i = 0; i < type.length; i++){
    if(!type[i].innerHTML.includes(wakiFilter.id)){
        type[i].parentElement.style.display = "none";
    }
  }
});

在第二个函数中,我试图同时改变那个按钮的图像,但是我得到的是:

Before clickling

After clicking

目前我想知道的是:

-如何改变按钮点击后的图片?

-如何通过第二次单击同一按钮来撤消此过滤?

是否可以重新格式化该过滤器功能,以便所有按钮都可以使用相同的功能?

顺便说一下,我使用 my personal common.js 进行测试,因为在 Fandom wiki 范围内 common.js 需要他们在发布前进行检查。

如果你想玩代码,只需将我的代码复制并粘贴到你的个人 common.js。

您的图片没有更新,因为您插入了“Fandom”标签来替换元素的 HTML。

起初这是个好主意,但你需要知道,假设“Fandom 页面”,肯定会在 [=56] 处转换为 HTML =],并且您的浏览器仅接收 HTML。我不太确定我刚才说的是什么,但我想这就是过程。

简单解释一下,当你在页面加载后添加“Fandom”标签时,没有翻译成HTML,因为没有调用模板引擎。

因此,为了更新您的图像,获取事件侦听器的元素中可能有一个 <img> 标记。它是您需要更新的图像元素的 [src] 属性。

查看您的页面 DOM 树后,我认为您必须自己找出正确的图片 URL。


现在,回答你的问题:

并且通过 if 语句,您可以检查当前显示的是哪张图片,然后选择要显示的图片。

为了让你的所有过滤器都有一个独特的功能,只需制作它并在你的事件监听器中使用它。

document.querySelector('#Tantou').addEventListener('click', function() {
  filter(this, 'url/to/tantou.png', 'url/to/tantou-filtered.png');
});

document.querySelector('#Wakizashi').addEventListener('click', function() {
  filter(this, 'url/to/wakizashi.png', 'url/to/wakizashi-filtered.png');
});

/**
 * @param {HTMLElement} clickedElement - The element that triggered the event.
 * @param {string} imageSrc - The URL of the picture when it is NOT active/clicked.
 * @param {string} imageSrcFiltered - The URL of the picture when it is active/clicked.
 */
function filter(clickedElement, imageSrc, imageSrcFiltered) {
  const types = document.querySelectorAll("tr td:nth-last-child(1)"),
  // Gets the <img> tag.
    imageElement = clickedElement.querySelector('img'),
  // Gets the current [src] attribute's value of the <img>.
    currentImageSrc = imageElement.getAttribute('src'),
  // It is filtered if the current image URL is the same as the one when it is filtered.
    isFiltered = (currentImageSrc === imageSrcFiltered);

  // If filtered, displays the lines.
  if (isFiltered) {
    // Replaces the image URL.
    imageElement.setAttribute('src', imageSrc);
    // ---- Code snippet testing purpose here!
    imageElement.setAttribute('alt', imageSrc.split('/').pop());

    for(let i = 0; i < types.length; i++) {
      if (!types[i].innerHTML.includes(clickedElement.id)) {
        // Sets a CSS style to an empty string to reset its value.
        types[i].parentElement.style.display = '';
      }
    }
  } // If not, hides the lines.
  else {
    // Replaces the image URL.
    imageElement.setAttribute('src', imageSrcFiltered);
    // ---- Code snippet testing purpose here!
    imageElement.setAttribute('alt', imageSrcFiltered.split('/').pop());

    for(let i = 0; i < types.length; i++) {
      if (!types[i].innerHTML.includes(clickedElement.id)) {
        types[i].parentElement.style.display = 'none';
      }
    }
  }
}
<div id="Tantou">
  <img src="url/to/tantou.png" alt="tantou.png">
</div>

<div id="Wakizashi">
  <img src="url/to/wakizashi.png" alt="wakizashi.png">
</div>

<table>
  <thead>
    <tr>
      <th>ID</th>
      <th>A column</th>
      <th>Column checked by filters</th>
    </tr>
  </thead>
  
  <tbody>
    <tr>
      <td>1</td>
      <td>Cell</td>
      <td>Tantou</td>
    </tr>
    
    <tr>
      <td>2</td>
      <td>Cell</td>
      <td>OtherFilter</td>
    </tr>
    
    <tr>
      <td>3</td>
      <td>Cell</td>
      <td>Wakizashi</td>
    </tr>
  </tbody>
</table>

最后,你可以进一步简化这个功能,但我不想给你太多的东西让你一次消化。