Can you please explain the function of this JavaScript code for the Isotope filter?

I am struggling to grasp the functionality of a section of vanilla JS code related to the Isotope filter. You can find the original code here.

var buttonGroups = document.querySelectorAll('.button-group');

for (var i = 0; i < buttonGroups.length; i++) {
  var buttonGroup = buttonGroups[i];
  var onButtonGroupClick = getOnButtonGroupClick(buttonGroup);
  buttonGroup.addEventListener('click', onButtonGroupClick);
}

function getOnButtonGroupClick(buttonGroup) {
  return function(event) {
    // check for only button clicks
    var isButton = event.target.classList.contains('button');
    if (!isButton) {
      return;
    }
    var checkedButton = buttonGroup.querySelector('.is-checked');
    checkedButton.classList.remove('is-checked')
    event.target.classList.add('is-checked');
  }
}

Can someone explain the relationship between the getOnButtonGroupClick function and its assignment to a variable in the preceding for loop?

Answer №1

getButtonGroupClick creates a closure that stores the value of buttonGroup. This closure is used when a button in the group is clicked - it searches for the currently selected button, deselects it, and selects the newly clicked button.

In reality, this level of complexity is unnecessary. When an event listener is triggered, event.currentTarget refers to the element the listener is attached to, simplifying the process.

var buttonGroups = document.querySelectorAll('.button-group');

for (var i = 0; i < buttonGroups.length; i++) {
  var buttonGroup = buttonGroups[i];
  buttonGroup.addEventListener('click', onButtonGroupClick);
}

function OnButtonGroupClick(event) {
  // only handle button clicks
  var isButton = event.target.classList.contains('button');
  if (!isButton) {
    return;
  }
  var checkedButton = event.currentTarget.querySelector('.is-checked');
  checkedButton.classList.remove('is-checked')
  event.target.classList.add('is-checked');
}

Answer №2

The purpose of the for loop in this code is to iterate through all elements with the class of button-group and attach a click event listener to each of them. The function getOnButtonGroupClick generates a function that will act as the event listener for when an element is clicked.

var buttonGroups = document.querySelectorAll('.button-group');
//Select all elements with the class name 'button-group' from the document
//Stored in the NodeList variable 'buttonGroups'

for (var i = 0; i < buttonGroups.length; i++) {
//Loop through each element with the 'button-group' class
  var buttonGroup = buttonGroups[i];
  //Get the specific element at index i
  var onButtonGroupClick = getOnButtonGroupClick(buttonGroup);
  //Generate the function to be executed when the element is clicked
  buttonGroup.addEventListener('click', onButtonGroupClick);
  //Assign the generated function as the click event listener for the element
}

function getOnButtonGroupClick(buttonGroup) {
  return function(event) {
    // Check if the click event occurred on a button
    var isButton = event.target.classList.contains('button');
    //Verify if the clicked element has the class 'button'
    if (!isButton) {
      //Do nothing if the clicked element is not a button
      return;
    }
    var checkedButton = buttonGroup.querySelector('.is-checked');
    checkedButton.classList.remove('is-checked')
    event.target.classList.add('is-checked');
  }
}

Answer №3

If I have interpreted your query correctly, it appears that a click event is being attached to each button within the buttonGroups. In my opinion, a more efficient and organized approach would be to utilize a forEach loop, as demonstrated below:

const buttonGroups = document.querySelectorAll('.button-group');
buttonGroups.forEach(button => button.addEventListener("click", handleClick)

function handleClick(event) {
  // checking for button clicks only
  let isButton = event.target.classList.contains('button');
  if (!isButton) {
    return;
  }
  let checkedButton = event.currentTarget.querySelector('.is-checked');
  checkedButton.classList.remove('is-checked')
  event.target.classList.add('is-checked');
}

Essentially, you are associating a click event with every button within the buttonGroups, triggering the function handleClick.

UPDATE: There is no real necessity to assign the function in that manner... instead, simply invoke it during the click event.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for customizing the heading titles on various pages within the Next.js application directory?

Within the app directory of Next.js 13, I have a default root layout setup: import "./globals.css"; export default function RootLayout({ children }) { return ( <html lang="en"> <head> <title>Create ...

What is the most efficient way to retrieve the key at a specific index within a JavaScript map object?

If I have the map object shown below: const items = new Map([['item1','A'], ['item2','B'], ['item3', 'C']]) I am trying to retrieve the key at index 2. Is there a method other than using a for ...

Dependency management in ReactJS components

I am grappling with the optimal structure for a React component that is composed of other components. Let's look at the first example: <ColorSelect id="color" label={this.state.selectLabel} trigger={{ color: "lime", text: "Lime"}} onPropagateCli ...

Utilizing JSON data from Jade in local JavaScript: A comprehensive guide

Attempting to utilize a JSON object (the entire object, not just a portion) from Node via Jade in my local myScript.js. Here is what my Jade file looks like: span(class="glyphicon glyphicon-pencil" onclick="confirm(\"#{myJSON.taskid}\", \" ...

Using a different method to handle multiple callbacks in Angular or a suitable replacement for $.Callbacks

Is there a similar functionality in Angular to jQuery $.Callbacks? I am seeking a straightforward method to manage callback lists within Angular. My goal is to achieve the following using Angular: function Broadcast(){ var self= this; this._status ...

The Link Element Does Not Appear Properly When Styled Using nth-of-type Selector

https://codesandbox.io/s/damp-worker-k7fj6y?file=/src/App.js Can anyone help me understand why the fourth .content <Link/> is not displaying when using the given CSS styling? Could it be a bug in the code, or am I overlooking something important? ...

Explore records within a specific date range AS WELL AS insert data within a defined date range

I'm working on developing a search application that allows users to view data based on the inputted date range. However, I also want to incorporate predefined date ranges into the final output. Although I've been searching for a solution, I have ...

Disabling pointer-events on material-ui textField input is ineffective

I have a material-ui textField input and I want to prevent the user from entering text by setting the css to pointer-events: none. However, this method does not work as expected. While I am aware that I can use the disabled={true} flag to disable the inpu ...

display PHP JSON information using jQuery AJAX

I'm completely new to this subject. I have a Json result that looks like the following : { "span": " 1", "numcard": "12", "chan": " Yes", "idle": "Yes", "level": "idle ", "call": "No ", "name": "" } My goal is to ...

What is the best way to configure input fields as readonly, except for the one being actively filled by the user

Is there a way to make all input fields readonly except the one that the user is trying to fill data into? After the user loads the page index.php and attempts to input data into, for example, <input id="edValue2" ...>, I want to set all input field ...

Conflict between Angular's ng-repeat directive and Sass styling

Currently, I am working on a project and encountering an issue that is causing some difficulty: In order to create a navigation bar with equally distributed list elements based on the number of items, I am utilizing ng-repeat for data binding and Sass for ...

Array Filtering with Redux

I have come across similar queries, but I am still unable to find a solution. While typing in the search box, the items on the screen get filtered accordingly. However, when I delete a character from the search box, it does not show the previous items. For ...

Import a fixed JSON document in Webpack

In the code I have, there is a construction that looks like this: var getMenu = function () { return window.fetch("portal/content/json/menu.json").then(function (data) { return data.json(); }); }; I attempted the following in my webpack.c ...

Enable autocomplete feature in a PHP form once the user starts typing their name

After searching for similar questions, I couldn't find any with the same "variables," so here's my dilemma: I have a basic form where I input a name and I want the rest of the form to be filled in automatically (ID). Retrieving data from the da ...

Having multiple Angular two applications running simultaneously within a single webpage

I have encountered an issue while trying to display two separate Calendars on a single page. The first Calendar loads successfully, but the second one does not load at all. There seems to be no attempt made to load it. As I am relatively new to Angular, I ...

The JQuery Ajax call returned with a status of 0 and an empty ResponseText

Here is the ajax request I am using: $.ajax({ type: "POST", url: "https://forlineplus.forsa.com.co/projects/validar-redireccion-sio?fup=" + idFup, //contentType: "application/json; charset=utf-8", ...

Chromium is having issues with updating the dynamic source attribute

One portion of my script that pertains to the question is as follows: <script type="text/javascript> function handleImageClick() { var image = $("#image_id"); $(image).attr("src", "ajax-loader.gif"); $.ajax({ ...

My method for updating form input properties involves switching the disable attribute from "false" to "true" and vice versa

I have a form that uses Ajax to submit data. Once the user submits the form, the text is updated to indicate that the data was sent successfully, and then the form is displayed with the fields filled out. I want to display the form but prevent users from r ...

Generating a JavaScript array containing all elements belonging to a specific class name

As I work on my website, I am attempting to create an array from elements that have a specific class. This array should retrieve the videofile attribute value from all `a` tags with the class `videoLink`. The desired values in the final array should be: ...

issue involving extension that interrupts downloads

Trying to develop a browser extension that can intercept downloads and automatically rename them. manifest.json: { "name": " Book Renamer", "description": "Automatically rename downloaded ebooks from gutenberg.or ...