英文:
Using only javascript and css: can I enable the user to selectively display and hide divs of different classes, via a single drop-down menu?
问题
以下是翻译好的内容:
我有一个HTML页面,包含80-100个带有CSS样式的div,每个div都包含一个带有图像和有关单个艺术品信息的网格。(每个div已经具有唯一的Id,以便能够链接到页面中的特定位置。)
许多作品使用多种媒体,我希望用户能够仅显示使用特定媒体的艺术品。
换句话说,我希望使HTML页面的行为类似于可过滤的数据库,其中单个下拉菜单充当过滤器列表,单击“使用视频的艺术品”选项(例如)会隐藏所有不使用视频的作品。
我只希望使用CSS和JavaScript来实现以上目标。
据我了解:
我可以通过分配不同的类别使我的艺术品div可选,例如“.med-drawing”、“.med-video”、“.med-sound”等。这些类别需要有10-12个。
然后,我需要一种方式,通过单击,在“可见所有具有”特定类别的div,并“不可见具有”该类别的div。对于每个10-12个不同的类别都需要这样做。
我一直在尝试一系列JavaScript的“onClick + GetElementsByClass + [某种可见性控制]”函数分配给菜单中的不同元素。我对JavaScript编码的了解有限,到目前为止,我无法让任何东西起作用。
我真正需要的是一个最基本的JavaScript/CSS解决方案,我可以根据我的项目进行修改。
对于任何帮助,我将不胜感激。
英文:
I have an html page consisting of 80-100 css-styled divs each containing a grid with an image and information about a single artwork. (Each div already has a unique Id, to enable linking-in to a specific place in the page.)
Many of the works employ several media, and I want the user to be able to make visible only artworks that use particular media.
In other words, I want to make the html page behave like a filterable database, where a single drop-down menu acts like a list of filters, and clicking on the "artworks using video" option (for e.g.) hides all works that do not use video.
I'm want to achieve the above with css and Javascript only.
As I understand it:
I can make my artwork divs selectable by assigning different classes, such as ".med-drawing" ".med-video" ".med-sound" etc. There would need to be 10-12 of these classes.
Then, I'd need a way, onClick, to "make visible all the divs that do have" a particular class, AND "make invisible the divs that do not have" that class. This, for each of 10 - 12 different classes.
I've been trying a series of Javascript "onClick + GetElementsByClass + [some visibility control]" functions assigned to different elements in a menu. I have limited javascript coding knowledge and so far I can't get anything to work.
What I really need is a bare-essentials javascript/css solution that I can modify to suit my project.
I'd be grateful for any help.
EDIT- 1 day later (code added below these paras):
With the help of the.marolie I now have a basic 'filter/selector' working on a test page. It can select and show/hide divs precisely as I wanted, although utilising "data-type" rather than class.
Thanks!
EDIT 2
I had added more to this post, but, on reflection, realised that my initial question had been perfectly answered by the.marolie. My follow-up material really constututed a different question, so I've removed it here and bumped it to a new post: Using only JS and css: can I implement a filter, so that: clicking/tapping within a JS dropdown menu shows/hides page divs according to data-type?
答案1
得分: 1
为了帮助你入门,一种方法是:
为每个div添加一个常见的类名和一个基于内容类型的 data
属性。例如:
<div class="grid-item" data-type="text">
<span>文本</span>
</div>
<div class="grid-item" data-type="audio">
<span>音频</span>
</div>
有了这个之后,你可以添加一个选择框,其中包含与 data-type
相同的值的选项,如下所示:
<select id="cstm-select" name="filter">
<option value="text">文本</option>
<option value="image">图片</option>
<option value="audio">音频</option>
<option value="video">视频</option>
</select>
如果你看上面的代码,选项的 value
包含了不同的 data-type
属性值,我们将使用它们来过滤内容。
现在对于JavaScript逻辑,首先,我们需要监听 select
元素的 onChange
事件,将选择的值存储在一个变量中,然后在用户选择一个选项后使用 document.querySelectorAll()
函数查询元素,将常见的类名作为函数参数传递,以便只选择需要过滤的元素。
一旦查询到了元素,我们可以使用 forEach
遍历每个元素,然后检查每个元素的 data-type
属性是否与所选的过滤器值匹配,如果不匹配,就向元素添加一个控制元素可见性的类名。
此外,我们需要确保如果 data-type
匹配,我们移除类名,以便在用户选择不同的过滤器时元素是可见的。
将这些组合在一起,这里是一个小的示例。根据你的项目需要修改代码。
var select = document.getElementById('cstm-select');
var filter;
select.addEventListener("change", function() {
filter = select.value;
var elements = document.querySelectorAll('.grid-item');
elements.forEach((el) => {
var type = el.dataset.type.split(' ');
if (type.includes(filter)) {
el.classList.remove('hidden');
} else {
el.classList.add('hidden');
}
});
});
.hidden {
display: none;
}
<select id="cstm-select" name="filter">
<option value="text">文本</option>
<option value="image">图片</option>
<option value="audio">音频</option>
<option value="video">视频</option>
</select>
<div class="grid-container">
<div class="grid-item" data-type="text">
<span>文本</span>
</div>
<div class="grid-item" data-type="audio video">
<span>音频 / 视频</span>
</div>
<div class="grid-item" data-type="video">
<span>视频</span>
</div>
<div class="grid-item" data-type="audio">
<span>音频</span>
</div>
<div class="grid-item" data-type="image">
<span>图片</span>
</div>
<div class="grid-item" data-type="text">
<span>文本</span>
</div>
<div class="grid-item" data-type="text">
<span>文本</span>
</div>
</div>
编辑:根据你的评论,我已经修改了代码,以包括如果单个 grid-item
定义了多个 data-type
的筛选功能。
在这里的逻辑更改是,我们使用这种方式定义多个 data-type
- data-type="audio video"
。在每个项目之间提供一个空格,或者你也可以使用逗号分隔符。
在JavaScript代码中,我们首先使用 str.split()
函数拆分 data-type
,将值存储在数组中,如 [ 'audio', 'video' ]
。
现在,我们只需要检查所选的过滤器是否包含在数据集数组中,并根据需要应用或移除类。查看修改后的jsfiddle。
注意:无论我们在 data-type
属性中使用什么分隔符,我们都需要在JavaScript代码中使用相同的分隔符来拆分。
如果我们使用逗号,那么在JavaScript中将是:
var type = el.dataset.type.split(',');
英文:
To get you started, one approach would be:
Add common class name and a data
attribute to each div based on the type of content. For eg:
<div class="grid-item" data-type="text">
<span>Text</span>
</div>
<div class="grid-item" data-type="audio">
<span>Audio</span>
</div>
Once you have this, you can add a select box which will contain option with values that are same as the data-type
. Like:
<select id="cstm-select" name="filter">
<option value="text">Text</option>
<option value="image">Image</option>
<option value="audio">Audio</option>
<option value="video">Video</option>
</select>
If you see the above code, the value
of option contain the different data-type
attribute values that we will be using to filter the content.
Now for the js logic, first we need to listen to the onChange
event of our select
element, store the selected value in a variable and then query the elements once the use selects an option using the document.querySelectorAll()
function and pass the common class name as the function parameter so that only the elements that we need to filter will be selected.
Once queried, we can loop through each element using forEach
, then check if the data-type
attribute of each element against the selected filter value and if it doesn't match, add a class name to the element which will control the visibility of the element.
Also, we need to make sure that if the data-type
matches, we remove the class name so that the element is visible when the user selects a different filter.
Combining this, here is a small fiddle. Modify the code as required for your project.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
var select = document.getElementById('cstm-select');
var filter;
select.addEventListener("change", function() {
filter = select.value;
var elements = document.querySelectorAll('.grid-item');
elements.forEach((el) => {
var type = el.dataset.type.split(' ');
if (type.includes(filter)) {
el.classList.remove('hidden');
} else {
el.classList.add('hidden');
}
})
});
<!-- language: lang-css -->
.hidden {
display: none;
}
<!-- language: lang-html -->
<select id="cstm-select" name="filter">
<option value="text">Text</option>
<option value="image">Image</option>
<option value="audio">Audio</option>
<option value="video">Video</option>
</select>
<div class="grid-container">
<div class="grid-item" data-type="text">
<span>Text</span>
</div>
<div class="grid-item" data-type="audio video">
<span>Audio / Video</span>
</div>
<div class="grid-item" data-type="video">
<span>Video</span>
</div>
<div class="grid-item" data-type="audio">
<span>Audio</span>
</div>
<div class="grid-item" data-type="image">
<span>Image</span>
</div>
<div class="grid-item" data-type="text">
<span>Text</span>
</div>
<div class="grid-item" data-type="text">
<span>Text</span>
</div>
</div>
<!-- end snippet -->
Edit: As per your comment, I have modified the code to include filter functionality if there are multiple data-type
defined for a single grid-item
.
The logic change here is that, we define the multiple data-type
like this - data-type="audio video"
. Provide a space between each items or you can use a comma separator as well.
And in the js code, we first split the data-type
using str.split()
function which stores the values in an array like ['audio', 'video']
.
Now that we have this, all we need to do is check if the selected filter is included in the dataset array and apply or remove the class as required. Check the modified jsfiddle.
Note: Whatever separator we use in data-type
attribute, we need to define the same separator in the js code while we split.
If we use comma, the in js, it would be:
var type = el.dataset.type.split(',');
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论