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

Issue: The data type 'void' cannot be assigned to the data type 'ReactNode'

I am encountering an issue while calling the function, this is just for practice so I have kept everything inside App.tsx. The structure of my class is as follows: enum Actor { None = '', } const initializeCard = () => { //some logic here ...

Troubleshooting: Success with AJAX call in Chrome, but issues in IE

Having issues retrieving JSON data from a URL that displays the last 3 numbers of a webpage. The AJAX call functions correctly in Google Chrome but fails in Internet Explorer. I tried disabling caching using cache: false as suggested, but the problem persi ...

What is the best way to add up the attributes of objects within an array and save the total to the main

I have a collection of objects, illustrated here: var obj = { "ABC" : { "name" : "ABC", "budget" : 0, "expense" : 0, "ledgers" : [{ "Actual1920": 10, "Budget1920": 20, }, { "Actual1920": 10, ...

Triggering an action with JQuery when clicking on a button within an Angular

I need to open a new link whenever a column in my datatable is clicked. Below is the code for my datatable which fetches data through an ajax call- <table datatable="" dt-options="dtOptions" dt-columns="dtColumns" class="featuretable row-border compact ...

What are some alternative ways to create a text field with the same style as Material UI's without relying on the Material UI

With the power of HTML, CSS, and Reactjs I am aiming to create a functionality where the placeholder animates up to the border upon clicking on the text field An example can be seen with Material UI text field: https://material-ui.com/components/text-fie ...

Creating a unique custom selector with TypeScript that supports both Nodelist and Element types

I am looking to create a custom find selector instead of relying on standard javascript querySelector tags. To achieve this, I have extended the Element type with my own function called addClass(). However, I encountered an issue where querySelectorAll ret ...

When using a CSS background image in ReactJS, a white space may appear at the bottom of the window

Currently, I am working on creating a background for a React website and implementing it in the div above component. My purpose is to have this background only appear on specific components and not throughout the entire website. However, I am encountering ...

The Art of Capturing Sound: Unleashing

Currently, I am attempting to capture video via html5 .getUserMedia and play it back without needing to upload it to a server. Despite following numerous tutorials, I have only been successful on Chrome by utilizing canvas to draw the webp image and then c ...

When checking if el.text() is equal to "string", it will return false, regardless of the actual content of the element being "string"

Looking at the code snippet below, it seems that the else block is always being executed instead of the if block. The alert confirms that the variable state has the value 'payment' as expected. var state = $('.check-state').text(); ale ...

Ensure that the heights of various Flexbox rows are always visible within the boundaries of the browser window

Within flexbox, I've laid out three rows of boxes with varying heights. This layout ensures that the rows always align perfectly with the bottom of the browser window without any gaps. You can see the full layout on Codepen by following this link: htt ...

Creating a React Native project without the use of TypeScript

Recently I dived into the world of React Native and decided to start a project using React Native CLI. However, I was surprised to find out that it uses TypeScript by default. Is there a way for me to create a project using React Native CLI without TypeS ...

Stunning CRUD tables in AngularJS featuring dynamic jQuery pop-up windows

Hello, I have developed a small CRUD application using AngularJS and encountered a minor issue. The application is functioning correctly overall, but there is a problem: when adding a new record and then attempting to edit it, the pop-up box I created does ...

Dynamically obtaining the screen width in JSP using a variable

Could someone provide assistance on how to resize an image using an img src="blah.jpg?width=x" so that my page can be displayed at various sizes? I just need x (width) as a JSP variable. Update 2021: It's been 9 years since this question wa ...

What is the best approach for inserting multiple files into MongoDB with just one JavaScript, Node JS, Shell Script, or mongofile CLI script?

Looking for a way to transfer HTML files from a directory to MongoDB using pure JavaScript, NodeJs, shell script, or mongofile CLI. Any assistance would be greatly appreciated. Thank you in advance. ...

Safari displays an inexplicable gray border surrounding the <img/> element, despite the actual presence of the image

https://i.stack.imgur.com/4QR52.png There is an unexpected gray border visible around the dropdown image, as seen above. This occurrence has perplexed me because, according to several other queries, this problem arises when the image's src cannot be ...

Stop HTML elements from shifting position when content is modified using JavaScript

'use strict'; const countdown = () => { // create function to calculate time until launch in Days/Hours/Minutes/Seconds // time difference const countDate = new Date('May 25, 2024 00:00:00').getTime(); const now = new Date( ...

The image in the footer seems to have a mind of its own, refusing to stay put and instead choosing to wander

Is it possible to add a small icon at the bottom of the footer that scrolls up or down as I scroll, instead of remaining fixed? I'm unsure if the issue lies in setting the image as sticky on scroll or if it's a CSS error. I attempted to set the ...

Attempting to execute a PHP script through a JavaScript if statement

I have a form that requires validation with JavaScript. In one of the if statements, after all other conditions have been validated, I want to execute my PHP script that updates an SQL database with one of the passwords. Here is the final validation code: ...

Weather-js efficiently retrieves particular information from the displayed content

I'm currently utilizing weather-js to retrieve weather information based on a user's location determined by their IP address. My main question revolves around streamlining the output data in the console. Unfortunately, this API lacks documentatio ...

Preventing runtime error in Next.js API routes by handling axios exceptions

I am currently working on creating an API route in Next.js that sends a request to my backend and saves the token in the cookies. However, I am facing an issue where 4xx responses are causing an Unhandled runtime error. Despite everything working correctly ...