在此示例中,如何使用JaveScript模仿自定义过滤器/选择器?

时间:2019-05-14 17:25:47

标签: javascript mediawiki

我在this site(基于MediaWiki)上看到了此自定义过滤器,并想模仿其功能以实现自学目的。

我正在使用的表的代码太长,所以我只把它放在in here上。


[2019-05-15]

基于@KévinBibollet的示例修改代码后,遇到了一个新问题。

这是我的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解析错误:解析错误:缺少),位于文件'User:somebody / common中.js'在第16行,该行将事件侦听器绑定到按钮 ( wakiFilter.addEventListener(“ click”,()=>(filter(waki,wakiClicked,type)));

然后将代码放入控制台,然后单击按钮,我得到: TypeError: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上,整个wiki的common.js在发布前都需要时间对其进行检查。

如果您想使用该代码,只需将我的代码复制并粘贴到您的个人common.js中即可。

1 个答案:

答案 0 :(得分:0)

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

起初这是一个不错的主意,但是您需要知道,例如“ Fandom页面”,肯定在服务器端转换为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>

最后,您可以进一步简化此功能,但我不想给您太多东西来一次吸收。