Day4 Are you my destiny?

  • Multiple criteria filter

继众里寻它後,我们想继续看是否有各个栏位都符合关键字的结果(真命天菜/女神?),这需要根据输入的资料的阵列大小自动调整输入的栏位和对应function的数目,而这功能我问Google大神并没有得到明确的答案,但想想是可以实现的,分成3个部分,分别为生成输入栏位、比对有输入值得栏位做filter,以及调整输入栏位的宽度(如果资料表格会根据内容调整宽度)。

  • Implement

首先我们要修正上次的filterTable这个function,将原本input和table这两个argument改为,并在function内用getElementById取得HTML上的内容,这样就不用外面再包一层(原本filterTable_data()是拗口的写法),第二是再增加一个hold的argument,再原本if (txtValue.indexOf(filter) > -1)的条件中,再增加if (!hold)的条件,当两个条件都达到时,才会有display = "",这是避免在多个条件时,在其中一个条件达成时,会洗掉其他条件的没达成(display = "none"):

function filterTable(inputId, tableId, index, hold) {
  let input = document.getElementById(inputId);
  let table = document.getElementById(tableId);
  // Declare variables
  let filter, tr, td, i, txtValue;
  filter = input.value;
  tr = table.getElementsByTagName("tr");
  // Loop through all table rows, and hide those who don't match the search query
  for (i = 1; i < tr.length; i++) {
    td = tr[i].getElementsByTagName("td")[index];
    if (td) {
      txtValue = td.textContent || td.innerText;
      if (txtValue.indexOf(filter) > -1) {
        if (!hold) {
          tr[i].style.display = "";
        }
      } else {
        tr[i].style.display = "none";
      }
    }
  }
}

接下来是生成输入栏位,我们可以使用在day2生成表格的做法,而同样我们会生成表格,并根据原本表格的栏位的宽度写入属性,这样输入栏位就会对齐(如果原本表格是自动根据内容调整宽度),然後在cell中写入输入,如同在单一输入时的写法,但要额外带着栏位标号以做区分。总结,用JavaScript写表格,用表头格式(与下放表格的表头外观会一致),每个cell()根据资料的表格读取宽度并填入,cell写入输入(我在一开始将固定的文字拆成string1~string5,对应到上方的注解,让後面loop中的code比较乾净):

function genTableFilter(outputId, tableId, keyName) {
  //<input type="text" id="filterInput_data" onkeyup="filterTable_multi('filterInput_data', 'searchTable_data', 'dataTable', 0)" placeholder="Search ..." class="form-control"/>
  const string1 = "<input type=\"text\" id=\"filterInput_";
  const string2 = "\" onkeyup=\"filterTable_multi(\'filterInput_";
  const string3 = "\', \'";
  const string4 = "\', ";
  const string5 = ")\" placeholder=\"Search ...\" class=\"form-control\"/>";
  let table = document.getElementById(tableId);
  td = table.getElementsByTagName("tr")[0].getElementsByTagName("th");

  let content = "<thead><tr>";
  for (let i = 0; i < td.length; i++) {
    //content += "<th>" + cell + "</th>" ;
    let cellWidth = table.rows[0].cells[i].offsetWidth;
    content += "<th width=" + cellWidth + ">" + string1 + keyName + i;
    content += string2 + keyName + i + string3 + outputId + string3 + tableId + string4 + i;
    content += string5 + "</th>";
  }
  content += "</tr></thead>";
  document.getElementById(outputId).innerHTML = content;
}

再来是比对有输入值的栏位做filter,我们逻辑是这样:如果输入栏位有修改值(onkeyup触发),则会依序对所有栏位都读取值,如果有值(!= "")则做filter(filterTable这个function),而只有第一个hold为false,也就是会将符合条件的display设为"",这样可以清除之前的设定,而之後的所做filter的hold为true,则不会洗掉前面判断display = "none"的结果。若loop後hold还是false,表示所有栏位都没有输入值,则同样做一次filter,将所有display = "none"清回display = "",而最後呼叫的adjuctTableWidthByTable则是下一段所要说明调整宽度的function:

function filterTable_multi(inputId, searchId, tableId, index) {
  let table = document.getElementById(tableId);
  td = table.getElementsByTagName("tr")[0].getElementsByTagName("th");
  let hold = false;
  for (let i = 0; i < td.length; i++) {
    let inputId_other = inputId.replace(/(\d+)$/, i);
    if (document.getElementById(inputId_other).value != "") {
      filterTable(inputId_other, tableId, i, hold);
      hold = true;
    }
  }
  if (!hold) {filterTable(inputId, tableId, index, hold);}
  adjuctTableWidthByTable(tableId, searchId);
}

如果资料表格会根据内容调整宽度,则我们在做filter时由於资料变了,则表格的宽度也可能变动,这样输入栏位可能会不对齐,这在使用时会有不协调的感觉。我们同样可以用之前在生成栏位的方式,再用loop依序抓一次资料表格的宽度,然後调整输入栏位宽度的属性:

function adjuctTableWidthByTable(refTableId, targetTableId) {
  let refTable = document.getElementById(refTableId);
  let tarTable = document.getElementById(targetTableId);
  td = refTable.getElementsByTagName("tr")[0].getElementsByTagName("th");
  for (let i = 0; i < td.length; i++) {
    let cellWidth = refTable.rows[0].cells[i].offsetWidth;
    //console.log(cellWidth);
    tarTable.getElementsByTagName("tr")[0].getElementsByTagName("th")[i].width = cellWidth;
    //console.log(tarTable.rows[0].cells[i].offsetWidth);
  }
}

最後我以节录一开始的Bootstrap所附的表格资料做测试,因为资料的内容长度不一致,可以看出第三个调整宽度的功能的结果。
两栏filter输入结果:
https://ithelp.ithome.com.tw/upload/images/20210905/20141158H4CAOXqI5I.jpg
无符合条件结果:
https://ithelp.ithome.com.tw/upload/images/20210905/20141158FkgBzKciYs.jpg
无输入条件结果:
https://ithelp.ithome.com.tw/upload/images/20210905/20141158YxoBMwgjVt.jpg


<<:  AE卷轴制作3-Day4

>>:  Day05 测试写起乃 - Shoulda Matchers

django新手村14-----添加资料

之前在添加资料时,都是手动去资料库添加,这样很不合理,也没有效率 如果只是为了方便,当然可以使用以下...

Day23-介接 API(一)Google Calendar(I)启用 API 与 Events——Create

大家好~ 接着一起来介接 API 吧! 今天先从 Google Calendar API 开始~ 上...

Day 22 中断的运用

在Day 20有稍微提到中断机制,我们稍微深入说明一下,中断其实也是种不浪费资源的方式,如果处理器一...

LocalDB 无法开启时,如何解决

用新版Visual studio 2019开启旧版SQL Server 2012的mdf档时,却出现...

D4(9/4)-王品(2727)

注:发文日和截图的日期不一定是同一天,所以价格计算上和当日不同,是很正常的。 但今日无法交易,所以委...