Use jQuery Tabs within each function - javascript

I have this script so that I can make tabs very easy. But I can't have two, three, four and so on - tab function on the same page. I've tried to wrap into an each.function, but I just don't work for me. The tab changes on both rows at the same time :/
I use WordPress so the HTML markup is a little long so I've created a Codepen.
I also want this: if you click on the selected tab, I want it to be not active, like an accordion.
Markup here:
(function($) {
$('.section .row').each(function() {
$(this).find('.nav_wrap .tab').on('click', function() {
show_content($(this).index());
});
});
show_content(99); // choose 0 to start with first tab
function show_content(index) {
$('.row').each(function() {
// Make the content visible
$(this).find('.content_wrap .content.visible').removeClass('visible');
$(this).find('.content_wrap .content:nth-of-type(' + (index + 1) + ')').addClass('visible');
// Set the tab to selected
$(this).find('.nav_wrap .tab.selected').removeClass('selected');
$(this).find('.nav_wrap .tab:nth-of-type(' + (index + 1) + ')').addClass('selected');
});
}
})(jQuery);
.row {
background: lightblue;
margin-bottom: 80px;
}
.nav_wrap, .content_wrap {
display: flex;
}
.tab, .content {
padding: 20px;
}
.tab {
cursor: pointer;
}
.tab:hover,
.tab.selected {
background:pink;
}
.content_wrap .content {
display: none;
}
.content_wrap .content.visible {
display: flex;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="section">
<div class="row">
<div class="nav_wrap">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
</div>
<div class="content_wrap">
<div class="content">Tab 1 content goes here</div>
<div class="content">Tab 2 content goes here</div>
<div class="content">Tab 3 content goes here</div>
</div>
</div>
<div class="row">
<div class="nav_wrap">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
</div>
<div class="content_wrap">
<div class="content">Tab 1 content goes here</div>
<div class="content">Tab 2 content goes here</div>
<div class="content">Tab 3 content goes here</div>
</div>
</div>
</div>

Find the index of clicked element and add class to next content of clicked element based on clicked element index. Here I have updated your above code into one function. And I have checked if the clicked has selected class or not with hasClass() method. I guess this is what you are looking for.
(function($) {
$('.nav_wrap .tab').on('click', function() {
if(!$(this).hasClass('selected')) {
$(this).parent().find('.selected').removeClass('selected');
}
$(this).toggleClass('selected');
if(!$(this).parent().next().find('.content').eq($(this).index()).hasClass('visible')) {
$(this).parent().next().find('.visible').removeClass('visible');
} $(this).parent().next().find('.content').eq($(this).index()).toggleClass('visible');
});
})(jQuery);
.row {
background: lightblue;
margin-bottom: 80px;
}
.nav_wrap, .content_wrap {
display: flex;
}
.tab, .content {
padding: 20px;
}
.tab {
cursor: pointer;
}
.tab:hover,
.tab.selected {
background:pink;
}
.content_wrap .content {
display: none;
}
.content_wrap .content.visible {
display: flex;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<div class="section">
<div class="row">
<div class="nav_wrap">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
</div>
<div class="content_wrap">
<div class="content">Tab 1 content goes here</div>
<div class="content">Tab 2 content goes here</div>
<div class="content">Tab 3 content goes here</div>
</div>
</div>
<div class="row">
<div class="nav_wrap">
<div class="tab">Tab 1</div>
<div class="tab">Tab 2</div>
<div class="tab">Tab 3</div>
</div>
<div class="content_wrap">
<div class="content">Tab 1 content goes here</div>
<div class="content">Tab 2 content goes here</div>
<div class="content">Tab 3 content goes here</div>
</div>
</div>
</div>

Related

jQuery class tabs removing

It is a tabs, the active tab has a red dot and the inactive tab has grey dot but when i click the grey dot it will turn red all dot (remove all inactive class). Why happens this?
<div id="tabs">
<div class="dots">
<div class="dot"></div>
<p id="tab1" class="menu">Profile</p>
</div>
<div class="dots">
<div class="dot"></div>
<p id="tab2" class="menu">The Dic Approach</p>
</div>
<div class="dots">
<div class="dot"></div>
<p id="tab3" class="menu">The partners</p>
</div>
</div>
<div class="container" id="tab1C">1Some content</div>
<div class="container" id="tab2C">2Some content</div>
<div class="container" id="tab3C">3Some content</div>
Javascript
$(document).ready(function() {
$("#tabs .dots .dot:not(:first)").addClass("inactive");
$('.container').hide();
$('.container:first').show();
$("#tabs .dots .menu").click(function(){
var t = $(this).attr("id");
if($(".dot").hasClass("inactive")){
$(".dot").addClass("inactive");
$(".dot").removeClass("inactive");
$(".container").hide();
$("#" + t + "C").fadeIn("slow");
}
})
});
If you change
$(".dot")
to
$(this).closest(".dots").find(".dot")
(or similar) then it will use the dot that matches the currently clicked-on menu
Updated snippet:
$("#tabs .dots .dot:not(:first)").addClass("inactive");
$('.container').hide();
$('.container:first').show();
$("#tabs .dots .menu").click(function(){
var t = $(this).attr("id");
var dot = $(this).closest(".dots").find(".dot");
if (dot.hasClass("inactive")){
$(".dot").addClass("inactive");
dot.removeClass("inactive");
$(".container").hide();
$("#" + t + "C").fadeIn("slow");
}
})
.dot { color: red; float:left; }
.dot.inactive { color: #CCC; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="tabs">
<div class="dots">
<div class="dot">[.]</div>
<p id="tab1" class="menu">Profile</p>
</div>
<div class="dots">
<div class="dot">[.]</div>
<p id="tab2" class="menu">The Dic Approach</p>
</div>
<div class="dots">
<div class="dot">[.]</div>
<p id="tab3" class="menu">The partners</p>
</div>
</div>
<div class="container" id="tab1C">1Some content</div>
<div class="container" id="tab2C">2Some content</div>
<div class="container" id="tab3C">3Some content</div>
when you are using global selector like $(".dot") it's get all elements with that (dot) class name

How to show the content of a custom nav tab with JQuery?

I have made custom tabs with a function in JQuery. This is my custom tabs:
<div class="row">
<div class="col-4 master-advanced-left-tab master-advanced-left-tab-active">
<p>Item 1</p>
</div>
<div class="col-4 master-advanced-left-tab">
<p>Item 2</p>
</div>
<div class="col-4 master-advanced-left-tab">
<p>Item 3</p>
</div>
</div>
<div class="item1">
Show content from item 1
</div>
<div class="item2">
Show content from item 2
</div>
<div class="item3">
Show content from item 3
</div>
This is the custom styling I made with the tabs:
.master-advanced-left-tab {
overflow: hidden;
cursor: pointer;
padding-bottom: 10px;
padding-top: 10px;
}
.master-advanced-left-tab > p {
text-overflow: ellipsis;
height: 20px;
}
.master-advanced-left-tab-active {
color: #1C72DF;
border-bottom: 3px #1C72DF solid;
}
And this is my function to activate the tabs (working)
$('.master-advanced-left-tab').removeClass('master-advanced-left-tab-active');
elem.addClass('master-advanced-left-tab-active');
switch (elem.data('id')) {
case 'item1':
//show div for item1
break;
case 'item2':
//show div for item2
break;
default:
}
When I switch from tab I want to show the content from the class. I have tried with the toggle() function from JQuery. Also I have checked this stackoverflow post:
Bootstrap tab activation with JQuery
This is what I want but it didn't work for my solution because I don't use the nav tabs of bootstrap.
How can I show the content from each nav tab?
To show content you can simply call show() on it. You can also make your logic more DRY and extensible by converting the clickable div elements to a and using the href attribute to target the content to be displayed. This saves you having to write endless if conditions or switch cases, as it will work for an infinite number of tabs. It also means that, if required, you can open tabs when the page loads via the fragment of the URL. Try this:
let $tabs = $('.tab-content');
let $triggers = $('.master-advanced-left-tab').on('click', function(e) {
e.preventDefault();
$triggers.removeClass('master-advanced-left-tab-active');
var $elem = $(this).addClass('master-advanced-left-tab-active');
$tabs.hide();
$tabs.filter($elem.attr('href')).show();
});
$triggers.first().trigger('click');
.master-advanced-left-tab {
display: block;
overflow: hidden;
cursor: pointer;
padding-bottom: 10px;
padding-top: 10px;
}
.master-advanced-left-tab>p {
text-overflow: ellipsis;
height: 20px;
}
.master-advanced-left-tab-active {
color: #1C72DF;
border-bottom: 3px #1C72DF solid;
}
.tab-content {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<a href="#item1" class="col-4 master-advanced-left-tab">
<p>Item 1</p>
</a>
<a href="#item2" class="col-4 master-advanced-left-tab">
<p>Item 2</p>
</a>
<a href="#item3" class="col-4 master-advanced-left-tab">
<p>Item 3</p>
</a>
</div>
<div class="tab-content" id="item1">
Show content from item 1
</div>
<div class="tab-content" id="item2">
Show content from item 2
</div>
<div class="tab-content" id="item3">
Show content from item 3
</div>
hide and show the method can be used for this purpose, Hope this helps
$('.master-advanced-left-tab').click(function(e){
$(this).addClass('master-advanced-left-tab-active').siblings().removeClass('master-advanced-left-tab-active')
var class1 = $(this).attr('data-id')
$('.'+class1+'').removeClass('hide').siblings().addClass('hide')
})
.master-advanced-left-tab {
overflow: hidden;
cursor: pointer;
padding-bottom: 10px;
padding-top: 10px;
}
.master-advanced-left-tab > p {
text-overflow: ellipsis;
height: 20px;
}
.master-advanced-left-tab-active {
color: #1C72DF;
border-bottom: 3px #1C72DF solid;
}
.hide
{
display:none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<div class="row">
<div class="col-4 master-advanced-left-tab master-advanced-left-tab-active" data-id="item1">
<p>Item 1</p>
</div>
<div class="col-4 master-advanced-left-tab" data-id="item2">
<p>Item 2</p>
</div>
<div class="col-4 master-advanced-left-tab" data-id="item3">
<p>Item 3</p>
</div>
</div>
<div class="wrap">
<div class="item1 ">
Show content from item 1
</div>
<div class="item2 hide">
Show content from item 2
</div>
<div class="item3 hide">
Show content from item 3
</div>
</div>
You can see my code:
<div class="row">
<div class="col-4 master-advanced-left-tab master-advanced-left-tab-active" data-id="item1">
<p>Item 1</p>
</div>
<div class="col-4 master-advanced-left-tab" data-id="item2">
<p>Item 2</p>
</div>
<div class="col-4 master-advanced-left-tab" data-id="item3">
<p>Item 3</p>
</div>
</div>
<div class="content-item item1 active">
Show content from item 1
</div>
<div class="content-item item2">
Show content from item 2
</div>
<div class="content-item item3">
Show content from item 3
</div>
Css: add more some line:
.content-item {
display: none
}
.content-item.active {
display: block
}
Then JS:
$('.master-advanced-left-tab').click(function (){
let elem = $(this);
$('.master-advanced-left-tab').removeClass('master-advanced-left-tab-active');
$('.content-item').removeClass('active');
elem.addClass('master-advanced-left-tab-active');
switch (elem.data('id')) {
case 'item1':
$('.item1').addClass('active')
break;
case 'item2':
$('.item2').addClass('active')
break;
default:
$('.item3').addClass('active')
}
})
This is a demo: https://codepen.io/phuongnm153/pen/vYBXBGM
Instead of swith you can use something more responsive like this:
function changeTab(element) {
// remove 'active' class from item and tab to prevent multiple
// tab selection
$('.master-advanced-left-tab').removeClass('active');
$('.tab').removeClass('active');
// add class 'active' to clicked item and proper tab
// tab class is taken from 'data-tab' property from item in html
$(element).addClass('active');
$('.tab.' + $(element).data('tab')).addClass('active');
}
// change tab to first at init to prevent none tab selected
// You can replace this by adding class 'active' to
// 'master-advanced-left-tab' and 'tab' item in html
changeTab( $('.master-advanced-left-tab:first-child') );
// not much to explain
$('.master-advanced-left-tab').on('click', function(){
changeTab(this);
})
.master-advanced-left-tab {
overflow: hidden;
cursor: pointer;
padding-bottom: 10px;
padding-top: 10px;
}
.master-advanced-left-tab > p {
text-overflow: ellipsis;
height: 20px;
}
/* changed from .master-advanced-left-tab-active to shorten code */
.master-advanced-left-tab.active {
color: #1C72DF;
border-bottom: 3px #1C72DF solid;
}
.tab {
height: 0;
overflow:hidden;
}
.tab.active {
height: auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="row">
<!-- property 'data-tab' for js function to select proper tab -->
<div data-tab="item1" class="col-4 master-advanced-left-tab">
<p>Item 1</p>
</div>
<div data-tab="item2" class="col-4 master-advanced-left-tab">
<p>Item 2</p>
</div>
<div data-tab="item3" class="col-4 master-advanced-left-tab">
<p>Item 3</p>
</div>
</div>
<div class="tab item1">
Show content from item 1
</div>
<div class="tab item2">
Show content from item 2
</div>
<div class="tab item3">
Show content from item 3
</div>

Add / remove div for each button on click

I'm trying use append to give each button it's own div (.modal-item) that can be created and removed inside of the .modal container when the button is clicked. Each .item has it's own button and different content nested inside.
What I need as an example: If I click the button labelled Btn 1, I want a .modal-item div created inside of .modal that has the content from the Btn 1 .item. If I click Btn 1 again, it is removed. The same goes for each of the buttons.
The buttons should act as a checkbox for creating and removing the .modal-items. So in other words, the adding/removing of each .modal-item is handled by it's button.
$(function() {
$('#btn').click(function() {
var newDiv = $('<div class="modal-item"><h4><a>Dynamic Title</a></h4> </div>');
$('.modal').append(newDiv);
});
});
.container {
display: flex;
border: 1px solid blue;
}
.item,
.modal-item {
width: 100px;
border: 1px solid;
}
.modal {
display: flex;
border: 1px solid green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item">
<button id="btn">Btn 1</button>
<h4> Test 1 </h4>
<div class="subtitle"> Title 1 </div>
<div class="info"> This is Info / Description 1. </div>
</div>
<div class="item">
<button id="btn">Btn 2</button>
<h4> Test 2 </h4>
<div class="subtitle"> Title 2 </div>
<div class="info"> This is Info / Description 2. </div>
</div>
<div class="item">
<button id="btn">Btn 3</button>
<h4> Test 3 </h4>
<div class="subtitle"> Title 3 </div>
<div class="info"> This is Info / Description 3. </div>
</div>
</div>
<div class="modal"></div>
1st: id must be unique so you need to change id="btn" to class="btn"
2nd: by using data attribute for each btn and pass it to the modal-item div it can be done
$(function() {
$('.btn').click(function() {
var newDiv = $('<div data-btn="'+$(this).attr("data-btn")+'" class="modal-item"><h4><a>Dynamic Title'+ ($(this).closest('.item').index() + 1) +'</a></h4> </div>');
if($('.modal .modal-item[data-btn="'+$(this).attr("data-btn")+'"]').length < 1 ){
$('.modal').append(newDiv);
}else{
$('.modal .modal-item[data-btn="'+$(this).attr("data-btn")+'"]').remove();
}
});
});
.container {
display: flex;
border: 1px solid blue;
}
.item,
.modal-item {
width: 100px;
border: 1px solid;
}
.modal {
display: flex;
border: 1px solid green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="item">
<button class="btn" data-btn="btn1">Btn 1</button>
<h4> Test 1 </h4>
<div class="subtitle"> Title 1 </div>
<div class="info"> This is Info / Description 1. </div>
</div>
<div class="item">
<button class="btn" data-btn="btn2">Btn 2</button>
<h4> Test 2 </h4>
<div class="subtitle"> Title 2 </div>
<div class="info"> This is Info / Description 2. </div>
</div>
<div class="item">
<button class="btn" data-btn="btn3">Btn 3</button>
<h4> Test 3 </h4>
<div class="subtitle"> Title 3 </div>
<div class="info"> This is Info / Description 3. </div>
</div>
</div>
<div class="modal"></div>

positioning div classes next to another div using jquery

below is my current html layout, inside my .container class I have two <span> tags with classes of .download-btn and .save-btn. I want, whenever page load, remove those <span> from there and postioning near <div class="share"></div>
tag.
current layout
<div class="container">
<div class="col-md-6 col-center">
<span class="download-btn">download</span>
<span class="save-btn">save</span>
</div>
<div id="options">
<div class="share"></div>
</div>
expected layout when page load
<div class="container">
<div class="col-md-6 col-center">
</div>
<div id="options">
<span class="download-btn">download</span>
<span class="save-btn">save</span>
<div class="share"></div>
</div>
</div>
pls advice how to proceed using js ?
Using jQuery,
It can be done in a one line of code.
$("#options").prepend($(".save-btn")).prepend($(".download-btn"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="col-md-6 col-center">
<span class="download-btn">download</span>
<span class="save-btn">save</span>
</div>
<div id="options">
<div class="share"></div>
</div>
</div>
Use prepend() to move the buttons to the beginning of the element with ID options:
$('#options').prepend($('.download-btn, .save-btn'));
In this example I'm removing this two buttons from their places, and append them before <div class="share"></div> (and I have added content "share" to this div to see the difference):
var downloadBtn = $('.download-btn');
var saveBtn = $('.save-btn');
$('.share').before(saveBtn).before(downloadBtn);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="col-md-6 col-center">
<span class="download-btn">download</span>
<span class="save-btn">save</span>
</div>
<div id="options">
<div class="share">share</div>
</div>
Use button for for the buttons. It's semantically correct and accessible.
$(window).on('load', function() {
var download = $('.download-btn'),
save = $('.save-btn'),
options = $('#options');
download.remove();
save.remove();
options.prepend(download, save);
});
.container {
border: .1rem solid red;
min-height: 5rem;
margin-bottom: 1rem;
}
#options {
border: .1rem solid blue;
min-height: 100px;
}
button {
padding: 1rem;
background-color: #ddd;
display: inline-block;
margin: .5rem;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="col-md-6 col-center">
<button class="download-btn">download</button>
<button class="save-btn">save</button>
</div>
</div>
<div id="options">
<div class="share"></div>
</div>

Simple sort DIV by name, and number

I want to sort my div using vanilla JS by name and number. Before i sorting only list, and this is not a problem, but here i have a problem how to do this.
Maybe need create object, and save all value to him, and then sorting object?
Now i trying loop or items, but i can't get item-price or item-name in 'item'
var sortByNameBtn = document.getElementById('sortByName');
var sortByPriceBtn = document.getElementById('sortByPrice');
function sortingByName(){
var items = document.querySelectorAll('.item');
}
function sortingByPrice(){
var items = document.querySelectorAll('.item');
}
sortByNameBtn.addEventListener('click', sortingByName);
sortByPriceBtn.addEventListener('click', sortingByPrice);
.item {
background: #eee;
padding: 10px;
margin-bottom: 10px;
font-size: 20px;
display: inline-block;
border: 1px solid black;
}
<div class="items">
<div class="item">
<div class="item-price">12321</div>
<div class="item-name">Car</div>
</div>
<div class="item">
<div class="item-price">123</div>
<div class="item-name">Table</div>
</div>
<div class="item">
<div class="item-price">88</div>
<div class="item-name">Toys</div>
</div>
<div class="item">
<div class="item-price">1223</div>
<div class="item-name">Window</div>
</div>
<div class="item">
<div class="item-price">19</div>
<div class="item-name">Bad</div>
</div>
<div class="item">
<div class="item-price">50</div>
<div class="item-name">Mouse</div>
</div>
<div class="item">
<div class="item-price">500</div>
<div class="item-name">iPhone</div>
</div>
<div class="item">
<div class="item-price">100</div>
<div class="item-name">Mobile</div>
</div>
<div class="item">
<div class="item-price">12</div>
<div class="item-name">Cake</div>
</div>
<div class="item">
<div class="item-price">500</div>
<div class="item-name">Laptop</div>
</div>
</div>
<p>
<button id="sortByName">Sort by name</button>
</p>
<p>
<button id="sortByPrice">
Sort By price
</button>
</p>
Using flexbox for this could be useful cuz you can rearrange them with order, and it will save you a lot of re-rendering and moving bit's and pieces
Doe the flex layout will make it behave a little differently. So you might have to fix the css a bit.
Also the tab index might not be what you expect if you have inputs and what not.
var sortByNameBtn = document.getElementById('sortByName');
var sortByPriceBtn = document.getElementById('sortByPrice');
function sortingByName() {
var items = document.querySelectorAll('.item');
// get all items as an array and call the sort method
Array.from(items).sort(function(a, b) {
// get the text content
a = a.querySelector('.item-name').innerText.toLowerCase()
b = b.querySelector('.item-name').innerText.toLowerCase()
return (a > b) - (a < b)
}).forEach(function(n, i) {
n.style.order = i
})
}
function sortingByPrice(){
var items = document.querySelectorAll('.item')
Array.from(items).sort(function(a, b) {
// using ~~ to cast the value to a number instead of a string
a = ~~a.querySelector('.item-price').innerText
b = ~~b.querySelector('.item-price').innerText
return a - b
}).forEach(function(n, i) {
n.style.order = i
})
}
sortByNameBtn.addEventListener('click', sortingByName);
sortByPriceBtn.addEventListener('click', sortingByPrice);
.items {
display: flex;
}
.item {
background: #eee;
padding: 10px;
margin-bottom: 10px;
font-size: 20px;
display: inline-block;
border: 1px solid black;
}
<div class="items">
<div class="item">
<div class="item-price">12321</div>
<div class="item-name">Car</div>
</div>
<div class="item">
<div class="item-price">123</div>
<div class="item-name">Table</div>
</div>
<div class="item">
<div class="item-price">88</div>
<div class="item-name">Toys</div>
</div>
<div class="item">
<div class="item-price">1223</div>
<div class="item-name">Window</div>
</div>
<div class="item">
<div class="item-price">19</div>
<div class="item-name">Bad</div>
</div>
<div class="item">
<div class="item-price">50</div>
<div class="item-name">Mouse</div>
</div>
<div class="item">
<div class="item-price">500</div>
<div class="item-name">iPhone</div>
</div>
<div class="item">
<div class="item-price">100</div>
<div class="item-name">Mobile</div>
</div>
<div class="item">
<div class="item-price">12</div>
<div class="item-name">Cake</div>
</div>
<div class="item">
<div class="item-price">500</div>
<div class="item-name">Laptop</div>
</div>
</div>
<p>
<button id="sortByName">Sort by name</button>
</p>
<p>
<button id="sortByPrice">
Sort By price
</button>
</p>

Categories