Reputation: 85
I'm working on a project that utilizes Isotope Layout to filter HTML elements. Currently, I'm using jQuery to achieve the filtering functionality, but I'd like to transition to pure vanilla JavaScript for better performance and maintainability.
I've attempted to convert the jQuery code to vanilla JavaScript, but I'm encountering errors. Here's the original jQuery code that works as expected:
$(window).on('load', function() {
var $container = $('.portfolioContainer');
var $filter = $('#filter');
$container.isotope({
filter: '*',
layoutMode: 'masonry',
animationOptions: {
duration: 750,
easing: 'linear'
}
});
$filter.find('a').click(function() {
var selector = $(this).attr('data-filter');
$filter.find('a').removeClass('active');
$(this).addClass('active');
$container.isotope({
filter: selector,
animationOptions: {
animationDuration: 750,
easing: 'linear',
queue: false,
}
});
return false;
});
});
the code below is vanilla JavaScript but throw some errors including this one
Uncaught TypeError: Cannot read properties of undefined (reading 'remove') at HTMLAnchorElement.
document.addEventListener('DOMContentLoaded', function() {
var container = document.querySelector('.portfolioContainer');
var filter = document.getElementById('filter');
var iso = new Isotope(container, {
itemSelector: '*',
layoutMode: 'masonry',
animationOptions: {
duration: 750,
easing: 'linear'
}
});
filter = document.querySelectorAll('a');
for (var linkElement of filter) {
linkElement.addEventListener('click', function(event) {
var selector = event.target.getAttribute("data-filter");
selector.classList.remove("active");
var iso = new Isotope(container, {
itemSelector: '*',
layoutMode: 'masonry',
animationOptions: {
duration: 750,
easing: 'linear'
}
});
return false;
});
}
});
Upvotes: 0
Views: 234
Reputation: 349964
There are a few differences:
selector.classList.remove("active");
is not what the jQuery code is doing. The latter does not refer to selector
here, but the collection of a
elements below the filter.
You don't have the equivalent of $(this).addClass('active');
filter = document.querySelectorAll('a');
is not the equivalent of $filter.find('a')
. The latter only selects a
elements below $filter
, while your translation gets all of them, and overwrites filter
-- ignoring what you had stored in filter
before
The second itemSelector: '*'
does not correspond to the original filter: selector
Not a problem, but you never use iso
, so I'd suggest dropping the assignments to this variable.
Here is a correction (assuming the Isotope
constructor is correct):
document.addEventListener('DOMContentLoaded', function() {
const container = document.querySelector('.portfolioContainer');
const filter = document.getElementById('filter');
new Isotope(container, {
itemSelector: '*',
layoutMode: 'masonry',
animationOptions: {
duration: 750,
easing: 'linear'
}
});
const links = filter.querySelectorAll('a');
for (const linkElement of links) {
linkElement.addEventListener('click', function() {
for (const link of links) {
link.classList.toggle("active", linkElement === link);
}
new Isotope(container, {
itemSelector: this.getAttribute("data-filter"),
layoutMode: 'masonry',
animationOptions: {
duration: 750,
easing: 'linear'
}
});
return false;
});
}
});
Upvotes: 1