What steps can I take to streamline and simplify this tab controller code?

I'm looking to simplify this jQuery code because I feel like there's repetition. As someone new to JavaScript and jQuery, I've created two tabs with their respective containers containing miscellaneous information. My goal is to have each container open when its related tab is clicked, as well as highlight the active tab. Additionally, I want all tab containers to disappear when clicking outside of them.

<!-- HTML Code -->
<div class="sort-filters">
  <span class="sort-by active">SORT BY</span>
  <span class="filter">FILTER</span>
</div>

<div class="sort-containers">
  <div class="sort-by-container">Click me here for sorting</div>
  <div class="filter-container">Click me here for filtering</div>
</div>

/* CSS */
.sort-filters {
  display: flex;
  width: 500px;
  height: 30px;
}

.sort-by,
.filter {
  background: #CCC;
  color: #756661;
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: 'Arial', sans-serif;
  cursor: pointer;
}

.sort-by-container,
.filter-container {
  width: 500px;
  background: #756661;
  color: #FFF;
  height: 100px;
  display: none;
}

.active {
  background: #756661;
  color: #FFF;
  transition: 0.2s;
}

// jQuery Code
js = $.noConflict();
var sort = js('.sort-by');
var filter = js('.filter');
var sortContainer = js('.sort-by-container');
var filterContainer = js('.filter-container');

js(sort).click(function() {
  js(filterContainer).hide();
  js(sortContainer).show();
  js(sort).addClass('active');
  js(filter).removeClass('active');
});

js(filter).click(function() {
  js(sortContainer).hide();
  js(filterContainer).show();
  js(filter).addClass('active');
  js(sort).removeClass('active');
});

Answer №1

To avoid redundant actions, I prefer to adhere to naming conventions. This way, I can easily apply the IDs, classes, or attributes of one element to select other elements. For example:

<div id="tabs">
  <span class="active" data-type="sort-by">SORT BY</span>
  <span data-type="filter">FILTER</span>
</div>

All it takes is a single click handler on #tabs span to retrieve the data-type of the clicked span. This information can then be used to filter on the classes of other container elements.

Additionally, you can assign handlers to multiple elements simultaneously. In your scenario,

js('#sort-containers div').hide();
will hide all matching div elements at once.

Results

I have converted some classes to IDs and others to data attributes. Here's a fiddle: https://jsfiddle.net/mq9xk29y/

HTML:

<div id="tabs">
  <span data-type="sort-by">SORT BY</span>
  <span data-type="filter">FILTER</span>
</div>

<div id="sort-containers">
  <div class="sort-by-container">Sort by click me here</div>
  <div class="filter-container">Filter click me here</div>
</div>

JS:

js = $.noConflict();
var $tabs = js('#tabs span');
$tabs.click(function() {
  var $clicked = js(this); //get the element thats clicked on
  var type = $clicked.data('type'); //get the data-type value

  $tabs.removeClass('active'); //remove active from all tabs
  $clicked.addClass('active'); //add active to the current tab
  js('#sort-containers div').hide(); //hide all containers
  js('.' + type + '-container').show().addClass('active'); //add active to current container
});

If you consistently follow the naming convention of data-type: bla in the tabs and bla-container in the classes within sort-container, you won't need to duplicate code for additional tabs.

There may still be room for further optimization, but at least this approach eliminates repetition.

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

Combining the value of $(this) to create an identifier name

I am attempting to create a hover effect on an h1 element that triggers the glowing effect on a span element with an id that corresponds to the value of the h1. While I have successfully set up a glowing effect for a sentence, I am struggling to replicate ...

Executing a script that has been inserted into the page post-loading

I'm facing an issue where the script tag at the bottom of my project is not being executed after adding new pages later on. Main const fetch = (url, call) => { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if ...

Utilizing AJAX for showcasing the data from an XML document

Our professor gave a brief explanation of AJAX, expecting us to showcase the data from an XML file in a scrollable text area on our website. Unfortunately, I am facing issues with loading the XML file into the designated div area. Any assistance or suggest ...

Attempting to eliminate the parent container of a slide generated by the Slick Slider Plugin

I have developed a filter mechanism that hides specific classes within a slick slider based on the data-tag associated with the objects and the value of checkboxes. However, when these classes are hidden, they still occupy space because I should be hiding ...

Is there a way to smoothly slide an element in the same way another element can be dragged out

I am currently using AngularJS. My goal is to achieve the following: When the 'Fade in' button is clicked, a hidden element should slide out from the left side. It should appear behind the 'MAIN BASE' element, giving the illusion that ...

Transforming Thomas J Bradley's signature pad JSON into a PNG file using C# programming language

I have been experimenting with the Signature Pad plugin developed by Thomas J Bradley and successfully converted JSON signature to PNG using PHP. Now I am looking to achieve the same result using C#. There is a supplemental class called SignatureToImageDo ...

Error: Unable to use map function on users .. cannot perform mapping on functions

Initially, the map function in my code was working fine. However, suddenly an error started appearing when I included the users.map line. Surprisingly, if I comment out that line, the code works perfectly again. Even more strangely, if I uncomment it, ev ...

Troubleshooting: Vue.js file upload encountering OPTIONS 404 error

In my express app, I have configured CORS and most of the routes are working fine. However, I'm facing an issue with a specific component used for uploading images: <input type="file" class="form-control" @change="imageChanged"> <div @clic ...

When I attempt to click on the Cancel button, the database row remains undeleted

After a user clicks on the "Cancel" button, I want to reset the source and remove the iframe to prevent the file from being uploaded to the server. This function is currently working as intended. However, I am facing an issue where even after clicking on ...

Trouble arises when rendering nested components in React Router 4

My issue lies with implementing React Router 4 while utilizing "nested" routes. The problem arises when one of the top routes renders a component that matches the route, even though I do not want it to be rendered. Let me provide the relevant code snippets ...

The dimensions of the window - creating divs within td elements - the appearance of scroll

Here is the HTML code that I am working with: <table> <tr> <td class='tclone' id='clone'></td> <td class='loader' id='loader'> <div id='tdiv& ...

Failure to Present Outcome on Screen

Seeking assistance! I attempted to create a mini loan eligibility web app using JavaScript, but encountered an issue where the displayed result did not match the expected outcome upon clicking the eligibility button. Here is the HTML and JavaScript Code I ...

Having difficulty updating the parent for all PortfolioItem/Feature that were copied for a specific PortfolioItem/MMF

I'm facing a challenge in setting the parent for multiple features that I've copied for a specific MMF. However, only the parent of the last feature is being set. Below is the code snippet responsible for setting the parent: Record represents th ...

The date and time displayed in the Kendo grid are incorrectly shown as strange values

I have a datetime column formatted like this: { field: "ModifiedDate", dataType: "System.Date", title: accountCodeResourceProvider.ModifiedDate, format: "{0:G}", width: 150, hidden: true }]; However, when an empty value cell appea ...

Unexpected color changes when hovering over sparkline graphs

One of the jquery plugins I'm using is called sparkline Here's an example of how I am using it: $(function(){ $("#sparkline5").sparkline([2, 8, 10, 22], { type: 'pie', height: '140', sliceColors: [ ...

Setting up server-side CORS in ExpressJS will not include the "Access-Control-Allow-Origin" header

Looking to tackle a CORS request for an ExpressJS server, which is new territory for me. Despite encountering similar issues in the past, I can't seem to pinpoint the problem this time around. It appears that the required headers may not be in the cor ...

Is there a way to use Regex to strip the Authorization header from the logging output

After a recent discovery, I have come to realize that we are inadvertently logging the Authorization headers in our production log drain. Here is an example of what the output looks like: {"response":{"status":"rejected",&quo ...

Transform PHP array into a JavaScript array

Currently, I am using Laravel and retrieving a list of values from a database with the following code: $idordenes = DB::table('ordenes')->select('id')->get(); Upon echoing the idordenes variable, the output is as follows: [{"fa ...

Transitioning in CSS involves animating the changing of a CSS property over

My goal with CSS is to create a transition effect with a delay that behaves differently when entering and exiting. Specifically, I want a 1 second delay when an element enters, but no delay (0 seconds) when it exits. transition: width 0.3s ease-in 1s; tra ...

What are the reasons to steer clear of setting y.innerHTML equal to x.innerHTML?

If we have a DIV x on the webpage and want to duplicate its contents into another DIV y, we might be tempted to use the following code: y.innerHTML = x.innerHTML; This can also be achieved using jQuery: $(y).html( $(x).html() ); However, it is recommen ...