gpt4 book ai didi

javascript - jQuery 过滤器显示数据属性任意或全部

转载 作者:行者123 更新时间:2023-11-28 05:17:20 25 4
gpt4 key购买 nike

我有一些下拉菜单,用户可以使用它们filter()下面的div。这些按钮引用三个单独的数据属性。单击按钮时,该值将添加到数组中,然后我根据这些数组中的值过滤内容。虽然我只有两个下拉菜单,但我运行了四个场景来测试数组是否为空:如果它是空的,我只是测试数据属性是否存在,如果有一个值,那么我用它来过滤。

添加第三个过滤器后,我(我认为)有 9 种可能的场景可供测试,并想知道是否有更好的方法来做到这一点。

例如,当我只有两个过滤器时,我的数组可能如下所示:

["united-kingdom", "ireland"] //country
[] //type

var results = $(".collaborator[data-country][data-collaborator_type][data-interest]").filter(function() {
var $this = $(this);

if( countryArr.length !== 0 && collaborator_typeArr.length !== 0 ) {
return countryArr.includes($this.attr("data-country")) && collaborator_typeArr.includes($this.attr("data-collaborator_type"));

} else if( countryArr.length === 0 && collaborator_typeArr.length === 0 ) {
return $this.attr('data-country') && $this.attr('data-collaborator_type');

} else if( countryArr.length === 0 ) {
console.log('any country');
return $this.attr('data-country') && collaborator_typeArr.includes($this.attr("data-collaborator_type"));

} else if( collaborator_typeArr.length === 0 ) {
console.log('any type');
return countryArr.includes($this.attr("data-country")) && $this.attr('data-collaborator_type');
}
});

$('section.collaborator').slideUp('fast');
results.slideDown('fast');

这将返回英国和爱尔兰任何类型的结果。

我想不出更好的方法来实现“任意”值。有没有一种方法可以测试“任何”或通配符值,而不是检查数组是否为空。

如果我的数组看起来像这样怎么办

["united-kingdom", "ireland"] //country
["*"] //type

我如何过滤以返回通配符过滤器的所有内容?

最佳答案

因为我自己的脚本风格使我能够制作一些可适度扩展的东西,而无需附加案例 - 无论添加这些案例是简单还是复杂 - 我改变了脚本中采用的方法。

我还在您的 HTML 中添加了几个组件,不过您可以根据需要删除这些组件。

也就是说,我采取的方法如下,我尝试在注释中完整地解释代码(即使是原文中存在的那些部分,也是为了那些将来可能查看问题和答案的人的利益) ):

// delegating the event handler to the '#network-filters'
// element, binding the anonymous function of the on()
// method to act as the 'click' event-handler for the
// click events on those elements contained within that
// match the 'a.filter' selector:
$('#network-filters').on('click', 'a.filter', function(event) {

// preventing the default action of the <a> elements,
// preventing the page from following the clicked links:
event.preventDefault();

// using the 'let' statement to declare variables, this is
// possible in ES6-supporting browsers, for older browsers
// you may have to use 'var' instead (in this situation
// they're interchangeable).

// caching the clicked element:
let clicked = $(this),

// finding the elements that contain the elements to
// be filtered (I added the '#results' element):
results = $('#results .collaborator');

// toggling the 'toggled' class, to turn it 'on' or 'off'
// on the clicked <a>, and removing it from the sibling
// elements:
clicked.toggleClass('toggled').siblings().removeClass('toggled');

// caching '.dropdown' elements:
let dropdowns = $('#network-filters .dropdown'),

// declaring 'empty' variables for use within
// the up-coming 'Array.prototype.map()' call:
filter,
active,
filterValue,

// here we convert the dropdowns jQuery collection into
// a native JavaScript Array using get(), and then we
// iterate over that Array using Array.prototype.map():
selector = dropdowns.get().map(function(dropdown) {
// 'dropdown' a reference to the current element
// in the Array of elements over which we're
// iterating.

// assigning values to the declared 'empty' variables:
// here we retrieve the value of the 'data-tax'
// custom attribute, using the Element.dataset API:
filter = dropdown.dataset.tax;

// here we retrieve the element matching the supplied
// CSS selector contained within the current
// dropdown element, querySelector returns the first
// or no matching elements:
active = dropdown.querySelector('a.filter.toggled');

// if we have an 'active' element we pass the value
// of its 'data-filter' attribute to the variable,
// otherwise we return false:
filterValue = active ? active.dataset.filter : false;

// if there was an active element:
if (active) {
// we construct a selector to return to the Array
// we're creating via Array.prototype.map(), that
// selector takes the form of:
// 'data-' plus the attribute-value of the
// 'data-tax' attribute, followed by either an
// empty string (if the filterValue is exactly
// equal to 'any') or a string containing '='
// follwed by the found filterValue; this is
// all then followed by a ']' character to
// close the formed attribute-selector:
return '[data-' + filter + (filterValue === 'any' ? '' : '=' + filterValue) + ']';

// otherwise:
} else {
// we simply return false, if there was no active
// element:
return false;
}

// we then use Array.prototype.filter(Boolean) to retain
// only those true/truthy values in the Array
}).filter(Boolean)

// and join all array-elements together with an empty string:
.join('');

// those results (the '#results .collaborator' elements) are
// then filtered; those that do not match the created selector
// are hidden via the slideUp() method:
results.not(selector).slideUp();

// then we filter the results array to find those that
// are hidden (.not(':visible') - using the ':visible'
// jQuery/Sizzle custom selector) which match the
// formed selector and apply slideDown() to those
// elements; this is simply to avoid sliding elements
// both up and down if they're already visible:
results.not(':visible').filter(selector).slideDown();

// here we use a comparison to discover whether or not
// we have any results; if the number of results elements
// filtered by the selector is greater than 0, we return
// true (because we have found some results), otherwise
// we return false (because there were no matching results):
let resultsAvailable = results.filter(selector).length > 0;

// here we find the element (added by me to your HTML) which
// conveys the 'result-state', and toggle the 'noResult'
// class using the switch, in which we invert the
// resultsAvailble variable, so that the class is added if
// there are no results available, and removed if there are
// results available (its default state is to be hidden,
// and shown only if there are no results, this is in the CSS):
$('#results .resultState').toggleClass('noResult', !resultsAvailable);

});

上述 JavaScript 与以下 HTML 结合使用:

<div id="network-filters">
<div class="dropdown" data-tax="country">
<div class="dropdown-content">
<a class="filter all" data-filter="any">Show All</a>
<a class="filter" data-filter="ireland">Ireland</a>
<a class="filter" data-filter="united-kingdom">United Kingdom</a>

<!-- the following two <a> elements are added to show how
easily this approach can be extended; note that there
is no matching element for the 'Scotland' <a>, to
demonstrate that the script still works despite that -->
<a class="filter" data-filter="wales">Wales</a>
<a class="filter" data-filter="scotland">Scotland</a>
</div>
</div>
<div class="dropdown" data-tax="collaborator">
<div class="dropdown-content">
<a class="filter all" data-filter="any">Show All</a>
<a class="filter" data-filter="artist">Artist</a>
<a class="filter" data-filter="partner">Partner</a>
</div>
</div>
</div>

<!-- the '#results' element was added to logically group the
elements to be searched together -->
<div id="results">

<!-- the 'resultState' element was added to visibly inform
the user that the search was conducted and the lack of
results is deliberate, rather than the result of a
broken script -->
<div class="resultState">No results available for that choice.</div>
<div class="collaborator" data-country="ireland" data-collaborator="artist">
<ul>
<li>country = ireland</li>
<li>type = artist</li>
</ul>
</div>
<div class="collaborator" data-country="united-kingdom" data-collaborator="partner">
<ul>
<li>country = united-kingdom</li>
<li>type = partner</li>
</ul>
</div>

<!-- the following element was effectively cloned
from the same format as the other elements,
and dropped in justas a demonstration of how
easily this approach can be extended -->
<div class="collaborator" data-country="wales" data-collaborator="partner">
<ul>
<li>country = wales</li>
<li>type = partner</li>
</ul>
</div>
</div>

$('#network-filters').on('click', 'a.filter', function(event) {
event.preventDefault();

let clicked = $(this),
results = $('#results .collaborator');

clicked.toggleClass('toggled').siblings().removeClass('toggled');

let dropdowns = $('#network-filters .dropdown'),
filter,
active,
filterValue,
selector = dropdowns.get().map(function(dropdown) {
filter = dropdown.dataset.tax;
active = dropdown.querySelector('a.filter.toggled');
filterValue = active ? active.dataset.filter : false;

if (active) {
return '[data-' + filter + (filterValue === 'any' ? '' : '=' + filterValue) + ']';
} else {
return false;
}
}).filter(Boolean).join('');

results.not(selector).slideUp();
results.not(':visible').filter(selector).slideDown();

let resultsAvailable = results.filter(selector).length > 0;

$('#results .resultState').toggleClass('noResult', !resultsAvailable);

});
/* SCSS from JS Fiddle demo (https://jsfiddle.net/davidThomas/5c08shbn/1/)
compiled to CSS via 'http://www.sassmeister.com/' */

.dropdown {
margin-bottom: 10px;
}
.dropdown a {
display: inline-block;
cursor: pointer;
border: 1px solid grey;
margin-bottom: 4px;
padding: 4px 6px;
}
.dropdown a:hover {
background-color: grey;
}
.dropdown a.toggled {
/* I just prefer the brighter colour */
background-color: limegreen;
}
.collaborator {
background-color: red;
border: 1px solid red;
margin-bottom: 10px;
padding: 4px 6px;
color: white;
}
.resultState {
height: 2em;
line-height: 2em;
opacity: 0;
transition: all 0.3s linear;
}
.resultState.noResult {
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="network-filters">
<div class="dropdown" data-tax="country">
<div class="dropdown-content">
<a class="filter all" data-filter="any">Show All</a>
<a class="filter" data-filter="ireland">Ireland</a>
<a class="filter" data-filter="united-kingdom">United Kingdom</a>
<a class="filter" data-filter="wales">Wales</a>
<a class="filter" data-filter="scotland">Scotland</a>
</div>
</div>
<div class="dropdown" data-tax="collaborator">
<div class="dropdown-content">
<a class="filter all" data-filter="any">Show All</a>
<a class="filter" data-filter="artist">Artist</a>
<a class="filter" data-filter="partner">Partner</a>
</div>
</div>
</div>
<div id="results">
<div class="resultState">No results available for that choice.</div>
<div class="collaborator" data-country="ireland" data-collaborator="artist">
<ul>
<li>country = ireland</li>
<li>type = artist</li>
</ul>
</div>
<div class="collaborator" data-country="united-kingdom" data-collaborator="partner">
<ul>
<li>country = united-kingdom</li>
<li>type = partner</li>
</ul>
</div>
<div class="collaborator" data-country="wales" data-collaborator="partner">
<ul>
<li>country = wales</li>
<li>type = partner</li>
</ul>
</div>
</div>

JS Fiddle demo .

引用文献:

关于javascript - jQuery 过滤器显示数据属性任意或全部,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40864483/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com