In general, I need to make a pop-up menu with a choice of a category, everything works for me, but there is one point that needs to be improved.
When the category has already been selected, it is necessary that in the blog-filter class, All should be changed to the selected category, I tried many options, but all the non-working ones turned out to be.
html
<div class="blog-filter">
<div class="blog-filter_item active js-filter-blog-list" data-filter="all">All</div>
</div>
<div class="blog-filter-container">
<div class="container">
<h1 class="blog-filter-title">Choose Category</h1>
<div class="item-wrapper">
<div class="blog-filter_item active" data-filter="all">All</div>
#foreach($categories as $category)
<div class="blog-filter_item" data-filter=".category_{{$category->id}}">{{ $category->title }} ({{ $category->articles_count }})</div>
#endforeach
</div>
</div>
</div>
#foreach ($articles as $article)
<div class="blog-list category_{{ $article->blog_category_id }}">
<div class="article article--left" >
<h2 class="article_title">{{ $article->title }}</h2>
</div>
<div class="article article--right">
<h2 class="article_title">{{ $article->title }}</h2>
</div>
</div>
#endforeach
js
$('.js-filter-blog-list').on('click', event => {
const modalFilter = document.querySelector('.blog-filter-container');
$(modalFilter).toggleClass('open');
});
document.querySelectorAll('.blog-filter_item').forEach(el => {
el.addEventListener('click', () => {
document
.querySelector('.blog-filter_item.active')
.classList.remove('active');
el.classList.add('active');
var dataFilter = $(el).attr('data-filter');
if (dataFilter == 'all') {
$('.blog-list').show();
}
else {
$('.blog-list').hide();
$(dataFilter).show();
}
});
});
Solution:
#foreach($categories as $category)
<div class="blog-filter_item" data-filter=".category_{{$category->id}}" value="{{ $category->title }} ({{ $category->articles_count }})>{{ $category->title }} ({{ $category->articles_count }})</div>
#endforeach
var dataFilter = $(el).attr('data-filter');
var value = $(el).attr('value');
if (dataFilter == 'all') {
$('.blog-list').show();
$('.js-filter-blog-list').text('All');
}
else {
$('.blog-list').hide();
$(dataFilter).show();
$('.js-filter-blog-list').text(value);
}
I'm trying to figure out why my function that renders bootstrap 5 cards fails but only after first clicking a pagination button then selecting a drop down menu option. The pagination buttons work fine it seems and the dropdown menu also works fine but only if a pagination button is never clicked.
The problem seems to be in my displayList() function. After clicking a pagination button and clicking a dropdown option the correct array is passed into displayList() but let paginatedItems = items.slice(start, end); returns an empty array. Any help at all would be greatly appreciated.
I've my stripped down code so that hopefully it's easier to read and understand:
const setPosters = [{id:'1',img:'libs/images/pdfFile.jpg',title:'Virus Treatments',author:'Sam Smith',category:'treatments'},{id:'2',img:'libs/images/pdfFile.jpg',title:'Treatments',author:'Dave Smith',category:'illness'},{id:'3',img:'libs/images/pdfFile.jpg',title:'Pain',author:'Sam Smith',category:'illness'},{id:'4',img:'libs/images/pdfFile.jpg',title:'Virus Treatments',author:'Bob Burke',category:'illness'},{id:'5',img:'libs/images/pdfFile.jpg',title:'Pain Treatments',author:'James Frank',category:'cures'},{id:'6',img:'libs/images/pdfFile.jpg',title:'Sinus Treatments',author:'Ted Reed',category:'illness'},{id:'7',img:'libs/images/pdfFile.jpg',title:'Migrain Treatments',author:'Ted Reed',category:'remedy'},{id:'8',img:'libs/images/pdfFile.jpg',title:'Flu Treatments',author:'Ted Reed',category:'remedy'},{id:'9',img:'libs/images/pdfFile.jpg',title:'Virus Treatments',author:'James Frank',category:'remedy'},{id:'10',img:'libs/images/pdfFile.jpg',title:'Flu Treatments',author:'Ralph Barnes ',category:'remedy'},{id:'11',img:'libs/images/pdfFile.jpg',title:'Virus Treatments',author:'Thomas Smith',category:'cures'},{id:'12',img:'libs/images/pdfFile.jpg',title:'Pain Treatments',author:'Ralph Barnes',category:'remedy'},{id:'13',img:'libs/images/pdfFile.jpg',title:'Virus Treatments',author:'Sam Smith',category:'treatments'},{id:'14',img:'libs/images/pdfFile.jpg',title:'Treatments',author:'Dave Smith',category:'illness'},{id:'15',img:'libs/images/pdfFile.jpg',title:'Pain',author:'Sam Smith',category:'illness'},]
// this continues for a total of about 80 cards in my local version
let posters;
const cardElement = $('#cards');
const paginationElement = $('#pagination');
let currentPage = 1;
let rows = 10;
let page_count;
///////////\\\\\\\\\\\
// **** Functions ***\\
//////////\\\\\\\\\\\\\\
function displayList(items, wrapper, rows_per_page, page) {
wrapper.html("");
page--;
console.log('displayList', items);
let start = rows_per_page * page;
let end = start + rows_per_page;
let paginatedItems = items.slice(start, end);
console.log('paginatedItems:', paginatedItems);
for (let i = 0; i < paginatedItems.length; i++) {
wrapper.append(`
<div class="col gx-2">
<div class="card">
<img
src=${paginatedItems[i].img}
class="card-img-top"
alt="..."
/>
<div class="card-body p-1">
</div>
<div class="card-footer">
Title: ${paginatedItems[i].title}
Category: <strong>${paginatedItems[i].category}</strong><br>
Author: ${paginatedItems[i].author}<br>
id: ${paginatedItems[i].id}<br>
</div>
</div>
</div>
`)
};
};
function setupPagination(items, wrapper, rows_per_page) {
wrapper.html("");
page_count = Math.ceil(items.length / rows_per_page) + 1;
for (let i = 1; i < page_count; i++) {
wrapper.append(`<li class="page-item"><a class="page-link" href="#">${i}</a></li>`);
};
};
/////////////////////\\\\\\\\\\\\\\\\\\\\
// **** Posters By Category Dropdown ***\\
////////////////////\\\\\\\\\\\\\\\\\\\\\\
//Adds Categories to Dropdown Select Options
uniqCatergoriesArray = uniqCatergories(setPosters, it => it.category);
function uniqCatergories(data, key) {
return [...new Map(data.map(x => [key(x), x])).values()]
}
for (var i = 0; i < uniqCatergoriesArray.length; i++) {
$('#selPosterCat').append($('<option>', {
value: uniqCatergoriesArray[i].category,
text: uniqCatergoriesArray[i].category,
}));
}
//Displays Posters By Category
$('#selPosterCat').on('change', function() {
console.log($('#selPosterCat').val());
$('#textSearchResult').html(' ');
$('#inlineFormInput').val('');
if ($('#selPosterCat').val() === 'all') {
posters = setPosters.filter(item => item);
displayList(posters, cardElement, rows, currentPage);
setupPagination(posters, paginationElement, rows);
} else {
posters = setPosters.filter(item => item.category === $('#selPosterCat').val());
console.log('dropdown', posters);
displayList(posters, cardElement, rows, currentPage);
setupPagination(posters, paginationElement, rows);
}
});
/////////////////\\\\\\\\\\\\\
// **** Pagination Click ***\\
/////////////////\\\\\\\\\\\\\\
$(document).on("click", "ul.pagination li a:not(.static)", function(e) {
currentPage = parseInt($(this).text());
posters = setPosters.filter(item => item);
displayList(posters, cardElement, rows, currentPage);
});
posters = setPosters.filter(item => item)
displayList(posters, cardElement, rows, currentPage);
setupPagination(posters, paginationElement, rows);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- *** Main Content Container *** -->
<div class="container-fluid" id="mainContainer">
<div id="mainCardContainer">
<!-- *** Search Bar *** -->
<div class="container-fluid">
<div class="row">
<div class="col">
<form id="form-id">
<div class="mb-3 d-flex justify-content-center" style="margin-top: 5vh;">
<select id="selPosterCat" class="form-select-sm w-25" aria-label="Default select example" style="border-right: none; border-width: 1px; height: 2rem;">
<option value="all" selected>All Categories</option>
<!-- other options added here by javaScript -->
</select>
</div>
</form>
</div>
</div>
<div class="row row-cols-1 row-cols-lg-5 row-cols-sm-2 g-4" id="cards">
<!-- individual cards added here by javaScript -->
</div>
<!-- *** Pagination Bar *** -->
<div class="container-fluid mt-3 pe-0 me-0">
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-end">
<li class="page-item" id="previousBtn">
<a class="page-link static" href="#" tabindex="-1" aria-disabled="true" id="">Previous</a>
</li>
<div class="d-flex" id="pagination">
<!-- page numbers added here by javaScript -->
</div>
<li class="page-item" id="nextBtn">
<a class="page-link static" id="" href="#">Next</a>
</li>
</ul>
</nav>
</div>
Just change this code:
item => item.category === $('#selPosterCat').val()
With this:
item => item.category = $('#selPosterCat').val()
and be sure from adding these links respectively:
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js
https://cdn.jsdelivr.net/npm/bootstrap#5.0.1/dist/css/bootstrap.min.css
https://cdn.jsdelivr.net/npm/bootstrap#5.0.1/dist/js/bootstrap.bundle.min.js
http://jsfiddle.net/rewan_95/107zxr3g is the fiddle I tested on.
Note: don't forget to add the above links for testing on jsfiddle
I'm trying to filter certain films based on selections from the below dropdowns.
<select id="filmDropdown">
<option value="0">All Films</option>
<option value="1">Film 1</option>
<option value="2">Film 2</option>
<option value="3">Film 3</option>
</select>
<select id="dateDropdown">
<option value="All">All Dates</option>
<option value="Mon">Mon</option>
<option value="Tues">Tues</option>
<option value="Wed">Wed</option>
<option value="Thurs">Thurs</option>
<option value="Fri">Fri</option>
<option value="Sat">Sat</option>
<option value="Sun">Sun</option>
</select>
<input type="button" value="Search" onclick="getSelectedValues()" />
And here's the html for the films to be selected.
<div id="allFilms">
<div id="1" class="filmTag">
Film 1
<p>
Mon
</p>
<ul>
<li>12:00</li>
<li>16:00</li>
</ul>
<p>
Wed
</p>
<ul>
<li>19:00</li>
</ul>
</div>
<div id="2" class="filmTag">
Film 2
<p>
Tues
</p>
<ul>
<li>12:00</li>
<li>16:00</li>
<li>18:00</li>
</ul>
</div>
<div id="3" class="filmTag">
Film 3
<p>
Wed
</p>
<ul>
<li>12:00</li>
<li>16:00</li>
</ul>
</div>
</div>
I'm trying to use Javascript to hide all the films other than the one selected. This is what I'm doing but it doesn't seem to pick up the selected film and will just hide everything.
<script>
function getSelectedValues() {
var f = document.getElementById("filmDropdown");
var selectedFilm = f.value;
if (selectedFilm !== 0) {
var filmClass = document.getElementsByClassName("filmTag");
for (var i = 0; i < filmClass.length; i++) {
if (filmClass.id === selectedFilm) {
filmClass[i].style.display = "block";
}
else {
filmClass[i].style.display = "none";
}
}
}
}
</script>
If you are developing your own application you might want to render the html based on a structure, like React does, for example. So you have a state where you can also represent your filters. Doing the other way around using selectors is not convenient and very confusing, you might incur in race conditions too, it doesn't worth it.
If you are doing it as external script in a page you didn't develop, something like a Grease Monkey script, then it's a different story. But if you can control how your page is rendered, you might want to change your approach.
For a quick and dirty fix, this line:
if (filmClass.id === selectedFilm) {
needs to be:
if (filmClass[i].id === selectedFilm) {
It's generally not a good idea to use inline event handlers
Here's an alternative using event delegation css selectors and data attributes to filter the elements. Dropped the button and applied a change handler and simplified html.
document.addEventListener("change", showSelected);
function showSelected(evt) {
if (/dropdown/i.test(evt.target.id)) {
const selectValues = {
films: document.querySelector("#filmDropdown").value,
weekday: document.querySelector("#dateDropdown").value
};
// (re)show all initially
document.querySelectorAll("[data-films], [data-weekday]")
.forEach(elem => elem.classList.remove("hide"));
// nothing to do (selected all/all)
if (selectValues.films < 1 && selectValues.weekday === "All") {
return true
}
// css queryselectors based on values
// i.e. all elements *not* in current selection
const films = selectValues.films !== "0" ?
`[data-films]:not([data-films='Film ${selectValues.films}'])` : '';
const weekdays = selectValues.weekday !== "All" ?
`${films ? `, ` : ''}[data-weekday]:not([data-weekday='${
selectValues.weekday}'])` : '';
//hide all not selected elements
document.querySelectorAll(`${films}${weekdays}`)
.forEach(elem => elem.classList.add("hide"));
}
}
body {
font: normal 12px/15px verdana, arial;
margin: 2rem;
}
.hide {
display: none;
}
ul[data-films] {
margin-left: -1rem;
}
li[data-weekday]:before {
content: attr(data-weekday)' ';
}
ul[data-films]:before {
content: attr(data-films);
position: relative;
background-color: green;
color: white;
padding: 1px 3px;
margin-left: -1rem;
margin-bottom: 1rem;
bottom: 4px;
font-weight: bold;
}
<select id="filmDropdown">
<option value="0">All Films</option>
<option value="1">Film 1</option>
<option value="2">Film 2</option>
<option value="3">Film 3</option>
</select>
<select id="dateDropdown">
<option value="All">All Days</option>
<option value="Mon">Monday</option>
<option value="Tues">Tuesday</option>
<option value="Wed">Wednesday</option>
<option value="Thurs">Thursday</option>
<option value="Fri">Friday</option>
<option value="Sat">Saturday</option>
<option value="Sun">Sunday</option>
</select>
<ul data-films="Film 1">
<li data-weekday="Sun">14:00</li>
<li data-weekday="Sun">16:00</li>
<li data-weekday="Sun">20:00</li>
<li data-weekday="Mon">16:00</li>
<li data-weekday="Mon">12:00</li>
<li data-weekday="Mon">16:00</li>
</ul>
<ul data-films="Film 2">
<li data-weekday="Tues">12:00</li>
<li data-weekday="Tues">16:00</li>
<li data-weekday="Wed">12:00</li>
<li data-weekday="Wed">16:00</li>
<li data-weekday="Sun">18:00</li>
<li data-weekday="Sun">20:00</li>
</ul>
<ul data-films="Film 3">
<li data-weekday="Tues">10:00</li>
<li data-weekday="Tues">14:00</li>
<li data-weekday="Wed">12:00</li>
<li data-weekday="Wed">16:00</li>
<li data-weekday="Fri">12:00</li>
<li data-weekday="Fri">16:00</li>
<li data-weekday="Sat">10:00</li>
<li data-weekday="Sat">16:00</li>
<li data-weekday="Sat">17:00</li>
</ul>
Pie1 displays by default. Clicking the drop down for Pie2 or Pie3 leaves the DIV blank, selecting Pie1 once again returns echarts_Pie1. MY dropdown for pie2 and pie3 is not working.
<script language="javascript">
ivan = {};
ivan.showhide = function(val1)
{
if(val1 == 1)
{
document.getElementById('echart_pie1').style.display = "";
document.getElementById('echart_pie2').style.display = "none";
document.getElementById('echart_pie3').style.display = "none";
}
else if (val1 == 2)
{
document.getElementById('echart_pie1').style.display = "none";
document.getElementById('echart_pie2').style.display = "";
document.getElementById('echart_pie3').style.display = "none";
}
else if (val1 == 3)
{
document.getElementById('echart_pie1').style.display = "none";
document.getElementById('echart_pie2').style.display = "none";
document.getElementById('echart_pie3').style.display = "";
}
}
</script>
Pie1 displays by default. Clicking the drop down for Pie2 or Pie3 leaves the DIV blank, selecting Pie1 once again returns echarts_Pie1. MY dropdown for pie2 and pie3 is not working.
<div class="col-md-3 col-sm-4 col-xs-12">
<div class="x_panel">
<div class="x_title">
<h2>Storage</h2>
<ul class="nav navbar-right panel_toolbox">
<li><a class="collapse-link"><i class="fa fa-chevron-up"></i></a>
</li>
<li class="dropdown">
<i class="fa fa-wrench"></i>
<ul class="dropdown-menu" role="menu">
<option onclick="ivan.showhide(1)">Pie1</option>
<option onclick="ivan.showhide(2)">Pie2</option>
<option onclick="ivan.showhide(3)">Pie3</option>
</ul>
</li>
<li><a class="close-link"><i class="fa fa-close"></i></a>
</li>
</ul>
<div class="clearfix"></div>
</div>
<div class="x_content">
<div id="echart_pie1" style="height:180px;"></div>
<div id="echart_pie2" style="height:180px; display:none;"></div>
<div id="echart_pie3" style="height:180px; display:none;"></div>
</div>
Is this the result, you was searching for?
HTML:
<ul role="menu">
<option onclick="ivan.showhide(1)">Pie1</option>
<option onclick="ivan.showhide(2)">Pie2</option>
<option onclick="ivan.showhide(3)">Pie3</option>
</ul>
<div id="echart_pie1" style="height:180px;">a</div>
<div id="echart_pie2" style="height:180px; display:none;">b</div>
<div id="echart_pie3" style="height:180px; display:none;">c</div>
JS:
ivan = {};
ivan.showhide = function(val1)
{
if(val1 == 1)
{
document.getElementById('echart_pie1').style.display = "";
document.getElementById('echart_pie2').style.display = "none";
document.getElementById('echart_pie3').style.display = "none";
}
else if (val1 == 2)
{
document.getElementById('echart_pie1').style.display = "none";
document.getElementById('echart_pie2').style.display = "";
document.getElementById('echart_pie3').style.display = "none";
}
else if (val1 == 3)
{
document.getElementById('echart_pie1').style.display = "none";
document.getElementById('echart_pie2').style.display = "none";
document.getElementById('echart_pie3').style.display = "";
}
}
Actually i didnt even change something, except the contents in your DIV's ( i used a, b and c). This works if it it the result that you expected.
The echarts library might need the containers to be visible during the generation of the graphics, so I would suggest to remove the display:none style from the HTML:
<ul role="menu">
<option onclick="ivan.showhide(1)">Pie1</option>
<option onclick="ivan.showhide(2)">Pie2</option>
<option onclick="ivan.showhide(3)">Pie3</option>
</ul>
<div id="echart_pie1" style="height:180px;"></div>
<div id="echart_pie2" style="height:180px;"></div>
<div id="echart_pie3" style="height:180px;"></div>
In the JavaScript code you have code to initialise the graphics, with calls like these:
var echartPie1 = echarts.init(document.getElementById('echart_pie1'), theme);
// ... etc
Right after that code, add this line:
ivan.showhide(1);
This assumes of course that you have already defined ivan at this point. If not, put that definition first, and then add the above line below it.
A simplification
Not related to the problem, but note that you can simplify the showhide function to this:
ivan = {};
ivan.showhide = function(val1)
{
document.getElementById('echart_pie1').style.display = val1 !== 1 ? "none" : "";
document.getElementById('echart_pie2').style.display = val1 !== 2 ? "none" : "";
document.getElementById('echart_pie3').style.display = val1 !== 3 ? "none" : "";
}
If all three graphs flash at page load
Maybe the page will for a fraction of a second show all three graphs when the page loads. If that is a problem, try this, although it might bring back the original problem:
Add the style visibility: hidden to the ul tag:
<ul role="menu" style="visibility: hidden">
Remove that style once you have called showhide(1):
ivan.showhide(1);
document.querySelector('ul[role=menu]').style.visibility = 'visible';
It doesn't really matter if the <div> is visible when init with ECharts. What matters is that it should have width and height as a container.
So, you could set them with all three charts when page loaded, no matter which one is visible.
document.getElementById('echart_pie1').style.width = '800px';
document.getElementById('echart_pie1').style.height = '600px';
document.getElementById('echart_pie2').style.width = '800px';
document.getElementById('echart_pie2').style.height = '600px';
document.getElementById('echart_pie3').style.width = '800px';
document.getElementById('echart_pie3').style.height = '600px';
onclick function is not work in option element ! So try to change your option format a little bit
<select class="dropdown-menu" role="menu" onchange="ivan.showhide(this.value)">
<option value="1">Pie1</option>
<option value="2">Pie2</option>
<option value="3">Pie3</option>
</select>
Thank you everyone for assisting. Its working now - I tested it using pie1a, pie1b, pie1c.
<script type="text/javascript">
function doLoadStuff()
{
document.getElementById('echart_pie1b').style.display = "none";
document.getElementById('echart_pie1c').style.display = "none";
}
</script>
HTML
<body class="nav-md" onload="doLoadStuff()">
...
<ul class="dropdown-menu" role="menu">
<option onclick="showhidePie1('a')">Pie1a</option>
<option onclick="showhidePie1('b')">Pie1b</option>
<option onclick="showhidePie1('c')">Pie1c</option>
</ul>
<div id="echart_pie1a" style="height:200px;"></div>
<div id="echart_pie1b" style="height:200px;"></div>
<div id="echart_pie1c" style="height:200px;"></div>
I then initialized my 3 pies inside the bottom script
var echartBar1a = echarts.init(document.getElementById('echart_bar1a'), theme);
echartBar1a.setOption(
{
Options...
}
And then used a function to set the style.
function showhidePie1(theChar) {
document.getElementById('echart_pie1a').style.display = "none";
document.getElementById('echart_pie1b').style.display = "none";
document.getElementById('echart_pie1c').style.display = "none";
document.getElementById('echart_pie1'+theChar).style.display = "";
}
Its now working perfectly. Thank you.
I have a website where I need to filter a list of media types depending on the media family. ie: if print is chosen, it must only show options to do with print, if digital is chosen, it must only show options to do with digital stuff.
I can update the list with new values, but then they are not clickable anymore?
Here are the screenshots:
I am already using: $("#mec_id").trigger("liszt:updated"); where mec_id is the id of the select. Here is the HTML after the media family is chosen, when trying to click on the media type it does not give the option to click/select the option. In the code I have selected print because there is only one value for the dropdown there (to save space in the code).
HTML:
<select id="mec_id" class=" chosen-select" tabindex="-1" multiple="" style="width: 100%; display: none;" data-placeholder="Select Media Type" name="mec_id[]">
<option data-val="12" value="print">print</option>
</select>
<div id="mec_id_chosen" class="chosen-container chosen-container-multi" style="width: 349px;" title="">
<ul class="chosen-choices">
<li class="search-field">
<input class="default" type="text" style="width: 132px;" autocomplete="off" value="Select Media Type" tabindex="8">
</li>
</ul>
<div class="chosen-drop">
<ul class="chosen-results">
<li class="active-result" data-option-array-index="12">print</li>
</ul>
</div>
</div>
JavaScript/JQuery (function of the AJAX Success call):
success: function (data) {
var ul = document.createElement('ul');
ul.className = "chosen-results";
for (var i = 0; i < data.length; i++) {
if (i == 0) {
$('#media_types .chosen-drop').contents().remove();
$('#mec_id').contents().remove();
}
var text = data[i].text;
var li = document.createElement('li');
li.className = "active-result";
li.setAttribute('data-option-array-index', data[i].id);
li.innerHTML = text;
ul.appendChild(li);
// create options
var option = document.createElement('option');
option.setAttribute('data-val', data[i].id);
option.value = data[i].text;
option.text = data[i].text;
document.getElementById("mec_id").appendChild(option);
}
$('#mec_id_chosen .chosen-drop').append(ul);
$("#mec_id").trigger("liszt:updated");
},
Are you sure it's not suppose to be chosen:updated instead of liszt:updated
I don't see any references to liszt - http://harvesthq.github.io/chosen/