Is there a better method to accomplish this task in a more effective manner?

Is there a more efficient way to achieve this code with fewer lines of code? I'm looking for a solution that avoids repetition and makes it easier to manage, especially since I plan on creating multiple instances of this. Performance is a key consideration for me.

Jquery:

$( document ).ready(function() {
        $( "#q1" ).click(function() {
            $( "#a1" ).slideToggle( "slow", function() {});
            if ($(this).hasClass('on')){
                    $(this).removeClass('on');
            }else{
                $(this).addClass('on');
            }
        });
        // Repeat similar blocks for q2, q3, and q4
    });

HTML:

<div id="faq_content">
  <div class="faq_box">
    <div class="questions" id="q1">
      <span>xyz</span>
    </div>
    <div class="answers" id="a1">
      <span>xyz</span>
    </div>
  </div>
  // Repeat similar HTML structure for q2, q3, and q4
</div>

Answer №1

If you're looking for a straightforward solution based on your HTML structure, consider the following approach:

$(document).ready(function() {

  // Selecting all necessary elements and assigning a click event handler:
  $("#q1, #q2").click(function() {

    // Referencing the clicked element and navigating to the next sibling with the specified selector:
    $(this)
      .next('.answers')
      .slideToggle('slow', () => {
        // Toggling a class based on whether it already exists on the element:
        $(this).toggleClass('on');
    });

  // Triggering the click event on page load to initially hide the answers:
  }).click();
});

$(document).ready(function() {
  $("#q1, #q2").click(function() {
    $(this).next('.answers').slideToggle('slow', () => {
      $(this).toggleClass('on');
    });
  }).click();
});
*,
 ::before,
 ::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.faq_box {
  border: 1px solid #000;
  margin: 0.2em auto;
  width: 80vw;
}

.questions {
  background-color: #ffff;
  border: 1px solid transparent;
  border-bottom-color: #000;
  cursor: pointer;
  font-size: 1.2em;
  font-weight: bold;
  transition: background-color 0.3s linear;
}

.questions::before {
  content: attr(id) ': ';
  text-transform: capitalize;
}

.answers::before {
  content: attr(id) ': ';
}

.on {
  background-color: #0f06;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="faq_content">
  <div class="faq_box">
    <div class="questions" id="q1">
      <span>xyz</span>
    </div>
    <div class="answers" id="a1">
      <span>xyz</span>
    </div>
  </div>
  <div class="faq_box">
    <div class="questions" id="q2">
      <span>xyz</span>
    </div>
    <div class="answers" id="a2">
      <span>xyz</span>
    </div>
  </div>
</div>

References:

Answer №2

$(document).ready(function(){

    var questionClasses = $('.question');
    
    questionClasses.on('click', function(){
        var $thisQuestion = $(this);
        var answerIds =  $thisQuestion.data('id');

        $(answerIds).slideToggle("slow");

        $thisQuestion.toggleClass("active");
    });

});

Instead of repeating the same functionality for #q1, #q2... you can use classes and link them to their corresponding IDs like

<div id="#q1" class="question" data-id="#a1"></div>
. Additionally, you can set the initial state of #q1 or other questions by setting the class as "active" directly in the HTML instead of checking it in the JavaScript code. For example:
<div id="#q1" class="question active" data-id="#a1"></div>

Answer №3

If you have multiple handlers that share similarities, consider creating a higher-order function that returns a specific function for each handler:

function createHandler(selector) {
    return function() {
        $(selector).slideToggle("slow", function() {});
        if ($(this).hasClass('on')) {
            $(this).removeClass('on');
        } else {
            $(this).addClass('on');
        }
    }
}

Then, apply the created function like this:

$( "#q1" ).click(createHandler("#a1"))

To delve deeper into this concept, look up "Higher-Order Functions" and "Closures" in programming.

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

How can you apply filtering to a table using jQuery or AngularJS?

I am looking to implement a filtering system for my table. The table structure is as follows: name | date | agencyID test 2016-03-17 91282774 test 2016-03-18 27496321 My goal is to have a dropdown menu containing all the &apo ...

What steps can you take to prevent a potential crash from occurring when an unauthorized user attempts to access a page without logging in?

I've encountered an issue where the app crashes when trying to access a page that requires logging in. The reason for this crash is because the page attempts to load undefined data, resulting in the error: TypeError: Cannot read property 'firstN ...

VueJS and Vite: Encountering an unexpected character '�' while attempting to import files that are not JavaScript. Keep in mind that plugins are required for importing such files

I'm puzzled by the error message I'm receiving: [commonjs--resolver] Unexpected character '�' (Note that you need plugins to import files that are not JavaScript) file: /..../..../WebProjects/..../ProjectName/node_modules/fsevents/fse ...

Having difficulty with utilizing array.every() properly, leading to inaccurate results

Struggling to validate an array of IDs using a custom validator in a nestjs project. The issue arises when passing the array of IDs to a service class for database querying, as the validation always returns true even with incorrect IDs. Snippet of the cus ...

Building paths through a jQuery loop

Transform String into Delimited Array, Generate Loop of Check Boxes, and Build New String Given String = "Folder Tier1\Folder Tier2\Folder Tier3\Folder Tier4\Folder Tier5\Folder Tier6\" (Missing) Use "\" as a delimi ...

Module 'BrowserFetcher.js' could not be located

After updating all my npm packages, I encountered an issue when trying to run on my local server. The error message reads: Error: Cannot find module './BrowserFetcher.js' This error specifically points to a line in my puppeteer file located at - ...

Extracting numbers using regular expressions can be tricky especially when dealing with mixed

Currently, I am attempting to create a javascript regex that can extract decimal numbers from a string containing a mix of characters. Here are some examples of the mixed strings: mixed string123,456,00indeed mixed string123,456.00indeed mixed string123,4 ...

Is it possible to conceal and completely empty the TextBox once the checkbox is deselected?

When the checkbox is checked, the textbox is displayed; otherwise, it remains hidden. However, the value is not being cleared. Can someone please help me with this issue? Thank you in advance. HTML <div class="munna"> <in ...

What is the resolution process for importing @angular/core/testing in TypeScript and what is the packaging structure of the Angular core framework?

When using import {Injectable} from '@angular/core';, does the module attribute in package.json point to a file that exports injectable? Also, for the format @angular/core/testing, is there a testing folder within @angular/core that contains anot ...

Tips on personalizing the FirebaseUI- Web theme

Can someone help me find a way to customize the logo and colors in this code snippet? I've only come across solutions for Android so far. if (process.browser) { const firebaseui = require('firebaseui') console.log(firebaseui) ...

Guide to placing a button on the same line as text with the use of JavaScript

Does anyone know how to add a button to the right of text that was added using JS DOM? I've tried multiple techniques but can't seem to get it right - the button always ends up on the next line. Any tips on how to achieve this? var text = docu ...

Refresh the webpage when using the browser's back or forward button in AngularJS with ui-router

In my AngularJS app, I have configured the ui-router state as follows: $locationProvider.html5Mode(true); $stateProvider .state('index', { url: '/index?zoom&center', views: { ...

Avoiding metacharacters and utilizing them as a string variable for selection

For example, I have a variable called myid, and its value is "abc xyz". Then, I use a function to escape metacharacters and assign the result to another variable like this: var x = "#"+escapechars(myid);. The evaluated value of x is #abc\\xyz. ...

The challenges with implementing makeStyles in React Material UI

const useStyles = makeStyles((theme) => ({ toolbarMargin: { ...theme.mixins.toolbar, marginBottom: "3em", }, logo: { height: "7em", }, tabContainer: { marginLeft: "auto", }, tab: { ...theme ...

When building with Angular using the "ng build" command, the JavaScript file names are altered

I'm currently learning Angular and I've noticed that when creating a new project with Angular CLI, files like runtime.js, polyfills.js, main.js, styles.css are generated. However, after running the ng build command, similar files can be found in ...

Making an Ajax request using HTTPS in an HTTP environment

My website currently utilizes both http and https protocols without impacting the content. It incorporates jQuery ajax calls to populate certain sections of the page. However, I have a preference to transition all ajax calls to https protocol. Despite thi ...

Tips for eliminating duplicate values from an array of objects in JavaScript

I am working with an array of objects where my goal is to remove duplicate values from the values array. I would like the final result to be [{name:'test1', values:['35,5', '35,2','35,3']}, {name:'test2', v ...

The accumulation of input using setInterval is not effective

I need some help with my code. Please take a look at this link here. I want the input to count up from zero and hide when I click the "change" button. But when I show the input again, I want its value to reset back to zero. Can anyone guide me on how to ...

Unable to locate module: Unable to locate the file './Header.module.scss' in '/vercel/path0/components/Header'

I encountered an error while attempting to deploy my next application on Vercel. I have thoroughly reviewed my imports, but I am unable to pinpoint the issue. Module not found: Can't resolve './Header.module.scss' in '/vercel/path0/comp ...

Animating a Canvas to Follow Mouse Coordinates

I am looking for a way to animate a circle moving towards specific coordinates, similar to the game . I have attempted using the jquery animate() function, but it is too slow due to the constant updating of the target coordinates. Is there a faster metho ...