【问题标题】:Disable select if there is nothing to show如果没有可显示的内容,则禁用选择
【发布时间】:2019-10-14 06:48:29
【问题描述】:

我制作了一个包含多个选项的过滤器。如您所见,有时没有结果。我将其作为用户反馈回馈给访问者:没有结果。

现在我想说明,如果某些组合由过滤器(某些值)组成,则只有在实际存在值时才能使用过滤器(因此,如果页面上没有值,则隐藏一个选项)。通过这种方式,我可以防止用户不得不进行无休止的过滤器组合来找到正确的结果。有人可以帮我吗?

$("select.filterby").change(function() {
  var filters = $.map($("select.filterby").toArray(), function(e) {
    return $(e).val();
  }).join(".");
  $("div#FilterContainer").find("div.job-offer-card").hide();
  if ($("div#FilterContainer").find("div.job-offer-card." + filters).length) {
    $("div#FilterContainer").find("div.job-offer-card." + filters).show();

  } else {
    $("div#FilterContainer").find("div.noresults").show();
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span> View by:</span>


    <label for="location">Location</label>
    <select id="location" class="filterby">
       <option value="all">Show All</option>
       <option value="australia">Australia</option>
       <option value="singapore">Singapore</option>
       <option value="newzealand">New Zealand</option>
       <option value="usa">USA</option>
       <option value="uk">UK</option>
       <option value="vietnam">Vietnam</option>
       <option value="global">Global</option>
       <option value="othercountry">Other</option>
    </select>


    <label for="type">Type</label>
    <select id="type" class="filterby">
       <option value="all">Show All</option>
       <option value="accommodation">Accommodation</option>
       <option value="app">App/Technology</option>
       <option value="business">Business</option>
       <option value="health">Health</option>
       <option value="hospitality">Hospitality</option>
       <option value="education">Education</option>
       <option value="retail">Retail</option>
       <option value="services">Services</option>
       <option value="travel">Travel</option>
    </select>

    <label for="code">Code</label>
    <select id="code" class="filterby">
       <option value="all">Show All</option>
       <option value="001">001</option>
       <option value="002">002</option>
       <option value="003">003</option>
       <option value="004">004</option>
    </select>

<div id="FilterContainer">
  <div class="job-offer-card noresults">
    <p>no results</p>
  </div>
  <div class="job-offer-card all vietnam accommodation travel 004">
    <p>1 all vietnam accommodation travel</p>
  </div>
  <div class="job-offer-card all vietnam  travel 003">
    <p>2 all vietnam travel</p>
  </div>
  <div class="job-offer-card all vietnam accommodation travel">
    <p>3 all vietnam accommodation travel</p>
  </div>
  <div class="job-offer-card all australia accommodation travel 003">
    <p>4 all australia accommodation travel</p>
  </div>
  <div class="job-offer-card all australia education">
    <p>5 all australia</p>
  </div>
  <div class="job-offer-card all vietnam newzealand usa accommodation">
    <p>6 all vietnam accommodation</p>
  </div>
  <div class="job-offer-card all vietnam accommodation travel">
    <p>7 all vietnam accommodation travel</p>
  </div>
  <div class="job-offer-card all vietnam  travel">
    <p>8 all vietnam travel</p>
  </div>
  <div class="job-offer-card all vietnam accommodation travel">
    <p>9 all vietnam accommodation travel</p>
  </div>
  <div class="job-offer-card all australia accommodation travel">
    <p>10 all australia accommodation travel</p>
  </div>
  <div class="job-offer-card all australia health 001">
    <p>11 all australia</p>
  </div>
  <div class="job-offer-card all vietnam accommodation 002">
    <p>12 all vietnam accommodation</p>
  </div>
</div>

【问题讨论】:

  • 你想要一个 JS 答案吗?不是 jQuery 答案?
  • 嗨@西蒙!感谢您的回复。但它有点不同。如果没有特定值,我想隐藏一个选项,例如:if filter nr.选择 1 时,过滤器 2 等可能有不同的选项。
  • @MisterJojo 是的,这也很好!
  • 只是一个改进:为什么要查找某些内容而不是再次查找?将其存储到变量中。 var items = $("div#FilterContainer").find("div.job-offer-card." + filters); if (items.length) {items.show()} else {}

标签: javascript css


【解决方案1】:

显示动态选择和动态 FilterContainer 元素的解决方案。

备注:类名 001 ... 004 应更改为 _001 ..._004,因为它们不是有效的类名 见 => Which characters are valid in CSS class names/selectors?
或者使用数据集可能更清楚 => https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset

const
    Selects = document.querySelectorAll('select')                      // 3 selects in this story
  , mainFC  = document.querySelector('#FilterContainer')               // result part
  , all_FC  = document.querySelectorAll('#FilterContainer div')        // details result part
  , zeroFC  = document.querySelector('#FilterContainer div.noresults') // when there is nothing
;

var PossibleOptions = new Set();  // set for all options feet in #FilterContainer div

all_FC.forEach(d=>{d.className.split(' ').forEach(c=>{PossibleOptions.add(c)})}) // first attempt

// for the start : set only options availables + onchange listener
Selects.forEach(s=>{                                // for each Select 
  s.querySelectorAll('option').forEach(o=>{         // and for each option, in
    o.disabled = !PossibleOptions.has(o.value);     // is there 1 a result div using this class ?.
    if (o.value==='all') o.selected=true;           // start the select at position for all
  })
  s.onchange = SelecChange;                         // give listener 'change' to function named 'SelecChange'
})



function SelecChange(e)              // for every select action...
{
  //  e.target.value 
  let                               // prepare ;
    List_Selects = []               // - array for all selects value
  , no_FC        = true             // - flag to know if there is no FS as result
  ;
  PossibleOptions.clear();          // new start

  Selects.forEach(s=>{              // make List_Selects
    if(s.value!='all')              // everything is nothing
    { List_Selects.push(s.value) }  // add select value
  });
 
  all_FC.forEach(d=>{               // for each FilterContainer <div> as 'd'
    let ok = true;
    for(let cLS of List_Selects)    // for each option choosed in a select
    { ok = ok && d.classList.contains(cLS) } // check if in class list of the <div>

    if (ok){
      d.classList.remove('noShow');   // so this div will be shown
      d.className.split(' ').forEach(c=>{ PossibleOptions.add(c) }); 
                                      // and all the div class item be added on the set
      no_FC = false;                  // one is enough
    }
    else {
      d.classList.add('noShow');    // soory guy, your not in the team for this time
    }
  })

  // now we have disable all options witch as no reality in FilterContainer
  Selects.forEach(s=>{ 
    s.querySelectorAll('option').forEach(o=>{
      o.disabled = !PossibleOptions.has(o.value);   // PossibleOptions know
    })
  })

  // last things: is there results ?
  if (no_FC) { zeroFC.classList.remove('noShow') }  // there is none
  else       { zeroFC.classList.add('noShow')    }  // there is one (or more)
}
.noShow { display: none }
<h4> View by:</h4>

<label for="location">Location</label>
<select id="location" class="filterby">
    <option value="all">Show All</option>
    <option value="australia">Australia</option>
    <option value="singapore">Singapore</option>
    <option value="newzealand">New Zealand</option>
    <option value="usa">USA</option>
    <option value="uk">UK</option>
    <option value="vietnam">Vietnam</option>
    <option value="global">Global</option>
    <option value="othercountry">Other</option>
</select>

<label for="type">Type</label>
<select id="type" class="filterby">
    <option value="all">Show All</option>
    <option value="accommodation">Accommodation</option>
    <option value="app">App/Technology</option>
    <option value="business">Business</option>
    <option value="health">Health</option>
    <option value="hospitality">Hospitality</option>
    <option value="education">Education</option>
    <option value="retail">Retail</option>
    <option value="services">Services</option>
    <option value="travel">Travel</option>
</select>

<label for="code">Code</label>
<select id="code" class="filterby">
    <option value="all">Show All</option>
    <option value="001">001</option>
    <option value="002">002</option>
    <option value="003">003</option>
    <option value="004">004</option>
</select>
<hr>

<div id="FilterContainer">
  <div class="job-offer-card noresults noShow">
    <p>no results</p>
  </div>
  <div class="job-offer-card all vietnam accommodation travel 004">
    <p>1 all vietnam accommodation travel _004</p>
  </div>
  <div class="job-offer-card all vietnam travel _003">
    <p>2 all vietnam travel _003</p>
  </div>
  <div class="job-offer-card all vietnam accommodation travel">
    <p>3 all vietnam accommodation travel</p>
  </div>
  <div class="job-offer-card all australia accommodation travel 003">
    <p>4 all australia accommodation travel 003</p>
  </div>
  <div class="job-offer-card all australia education">
    <p>5 all australia education</p>
  </div>
  <div class="job-offer-card all vietnam newzealand usa accommodation">
    <p>6 all vietnam newzealand usa accommodation</p>
  </div>
  <div class="job-offer-card all vietnam accommodation travel">
    <p>7 all vietnam accommodation travel</p>
  </div>
  <div class="job-offer-card all vietnam travel">
    <p>8 all vietnam travel</p>
  </div>
  <div class="job-offer-card all vietnam accommodation travel">
    <p>9 all vietnam accommodation travel</p>
  </div>
  <div class="job-offer-card all australia accommodation travel">
    <p>10 all australia accommodation travel</p>
  </div>
  <div class="job-offer-card all australia health 001">
    <p>11 all australia health _001</p>
  </div>
  <div class="job-offer-card all vietnam accommodation 002">
    <p>12 all vietnam accommodation _002</p>
  </div>
</div>

相同的解决方案,但使用 数据选项
=> &lt;div class="job-offer-card" data-options="all vietnam accommodation 002"&gt;
(JS =>element.dataset.options)

const
    Selects = document.querySelectorAll('select')                      // 3 selects in this story
  , mainFC  = document.querySelector('#FilterContainer')               // result part
  , all_FC  = document.querySelectorAll('#FilterContainer div')        // details result part
  , zeroFC  = document.querySelector('#FilterContainer div.noresults') // when there is nothing
;

var PossibleOptions = new Set();  // set for all options feet in #FilterContainer div

all_FC.forEach(d=>{ d.dataset.options.split(' ').forEach(c=>{PossibleOptions.add(c)})}) // first attempt

// for the start : set only options availables + onchange listener
Selects.forEach(s=>{                                // for each Select 
  s.querySelectorAll('option').forEach(o=>{         // and for each option, in
    o.disabled = !PossibleOptions.has(o.value);     // is there 1 a result div using this class ?.
    if (o.value==='all') o.selected=true;           // start the select at position for all
  })
  s.onchange = SelecChange;                         // give listener 'change' to function named 'SelecChange'
})

function SelecChange(e)              // for every select action...
{
  //  e.target.value 
  let                               // prepare ;
    List_Selects = []               // - array for all selects value
  , no_FC        = true             // - flag to know if there is no FS as result
  ;
  PossibleOptions.clear();          // new start

  Selects.forEach(s=>{              // make List_Selects
    if(s.value!='all')              // everything is nothing
    { List_Selects.push(s.value) }  // add select value
  });
 
  all_FC.forEach(d=>{               // for each FilterContainer <div> as 'd'
    let
      ok  = true,
      opt = d.dataset.options.split(' ');
 
    for(let cLS of List_Selects)    // for each option choosed in a select
    { ok = ok && opt.includes(cLS) } // check if in class list of the <div>

    if (ok){
      opt.forEach(c=>{ PossibleOptions.add(c) }); // all the data-options item  be added on the set
      d.classList.remove('noShow');              // so this div will be shown
      no_FC = false;                            // one is enough
    }
    else {
      d.classList.add('noShow');    // soory guy, your not in the team for this time
    }
  })

  // now we have disable all options witch as no reality in FilterContainer
  Selects.forEach(s=>{ 
    s.querySelectorAll('option').forEach(o=>{
      o.disabled = !PossibleOptions.has(o.value);   // PossibleOptions know
    })
  })

  // last things: is there results ?
  if (no_FC) { zeroFC.classList.remove('noShow') }  // there is none
  else       { zeroFC.classList.add('noShow')    }  // there is one (or more)
}
.noShow { display: none }
<label for="location">Location</label>
<select id="location" class="filterby">
    <option value="all">Show All</option>
    <option value="australia">Australia</option>
    <option value="singapore">Singapore</option>
    <option value="newzealand">New Zealand</option>
    <option value="usa">USA</option>
    <option value="uk">UK</option>
    <option value="vietnam">Vietnam</option>
    <option value="global">Global</option>
    <option value="othercountry">Other</option>
</select>

<label for="type">Type</label>
<select id="type" class="filterby">
    <option value="all">Show All</option>
    <option value="accommodation">Accommodation</option>
    <option value="app">App/Technology</option>
    <option value="business">Business</option>
    <option value="health">Health</option>
    <option value="hospitality">Hospitality</option>
    <option value="education">Education</option>
    <option value="retail">Retail</option>
    <option value="services">Services</option>
    <option value="travel">Travel</option>
</select>

<label for="code">Code</label>
<select id="code" class="filterby">
    <option value="all">Show All</option>
    <option value="001">001</option>
    <option value="002">002</option>
    <option value="003">003</option>
    <option value="004">004</option>
</select>
<hr>

<div id="FilterContainer">
  <div class="job-offer-card noresults noShow" data-options="all">
    <p>no results</p>
  </div>
  <div class="job-offer-card" data-options="all vietnam accommodation travel 004">
    <p>1 all vietnam accommodation travel _004</p>
  </div>
  <div class="job-offer-card" data-options="all vietnam travel _003">
    <p>2 all vietnam travel _003</p>
  </div>
  <div class="job-offer-card" data-options="all vietnam accommodation travel">
    <p>3 all vietnam accommodation travel</p>
  </div>
  <div class="job-offer-card" data-options="all australia accommodation travel 003">
    <p>4 all australia accommodation travel 003</p>
  </div>
  <div class="job-offer-card" data-options="all australia education">
    <p>5 all australia education</p>
  </div>
  <div class="job-offer-card" data-options="all vietnam newzealand usa accommodation">
    <p>6 all vietnam newzealand usa accommodation</p>
  </div>
  <div class="job-offer-card" data-options="all vietnam accommodation travel">
    <p>7 all vietnam accommodation travel</p>
  </div>
  <div class="job-offer-card" data-options="all vietnam travel">
    <p>8 all vietnam travel</p>
  </div>
  <div class="job-offer-card" data-options="all vietnam accommodation travel">
    <p>9 all vietnam accommodation travel</p>
  </div>
  <div class="job-offer-card" data-options="all australia accommodation travel">
    <p>10 all australia accommodation travel</p>
  </div>
  <div class="job-offer-card" data-options="all australia health 001">
    <p>11 all australia health _001</p>
  </div>
  <div class="job-offer-card" data-options="all vietnam accommodation 002">
    <p>12 all vietnam accommodation _002</p>
  </div>
</div>

【讨论】:

    【解决方案2】:

    所以如果我检查你的问题是正确的:

    const
      All_Select          = document.querySelectorAll('select')
    , All_FilterContainer = document.querySelectorAll('#FilterContainer div')
    ;
    
    var List_of_everthing   = new Set();
    All_FilterContainer.forEach(d=>{
      d.className.split(' ').forEach(c=>{List_of_everthing.add(c.toLowerCase())});
    })
    
    All_Select.forEach(s=>{
      s.querySelectorAll('option').forEach(o=>{
        o.disabled = !List_of_everthing.has(o.value);
      })
    })
    

    【讨论】:

    • 你是个传奇!这让我很开心。非常感谢!
    • 您认为可以继续检查是否可以组合吗?现在看来,这似乎只在开始时才有可能。使用某些组合,您会得到新的组合结果:没有结果。
    • 这个我稍后再看,需要反思
    • 我只看到一堆代码,并不能一眼看出它与问题中的原始代码有何不同。如果您解释您更改/添加的什么以及如何以及为什么它会起作用,这将是一个更多更好的答案。请记住,SO 的存在不仅仅是为了解决 OP 的紧迫问题,而是为了帮助未来找到此问答的人。
    • @Stephen P 我明白了,我现在会努力提高教育水平,但这让我付出了代价,因为英语不是我的母语,而且我花时间在这两种语言中翻译大量的 stackoverflow 信息方向
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    • 2013-02-02
    • 2017-09-11
    相关资源
    最近更新 更多