How to create function that swaps divs with different ids? - javascript

I'm trying to create function in js to swap content of webpage using .style.display = "none" or "block" but the main problem is that there are few different divs with different id's for that. The main aim of doing this is chagning content after clicking specific buttons without loading new page. The biggest problem for me is creating script which will change "id"
independently of what id was before. Normally I could write all of id's one by one and just swap them but this is not the case. Content should be changed automatically so no matter what id was before it will replace for specific one after pressing button.
I have tried with querySelector in many ways by changing id with class, by using remove / set Attribute but none of these methods work for me. Im trying to write this fuction for 2 weeks and I don't have any ideas.
I'm worried that bootstrap classes may cause problem with this...
Can someone help me with this? Any tips?
This is my first post here so if I did something wrong, sorry for that.
I cannot paste here my code as everything is on my company laptop which I left when I was finish my job.

Here is an agnostic approach using no HTML ids or classes.
const container = document.querySelector('.container');
const buttons = container.querySelectorAll('button');
const divs = container.querySelectorAll(':scope > div');
function handleButtonClick() {
this.previousElementSibling.classList.toggle('hide');
}
buttons.forEach(button => {
button.addEventListener('click', handleButtonClick);
});
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
}
.hide {
display: none;
}
<div class="container">
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quis sed, dicta quasi in blanditiis nam atque odio, nobis a. Eos incidunt debitis tenetur rerum, esse ratione quisquam possimus quasi nam.</p>
<button>Toggle Content</button>
</div>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quis sed, dicta quasi in blanditiis nam atque odio, nobis a. Eos incidunt debitis tenetur rerum, esse ratione quisquam possimus quasi nam.</p>
<button>Toggle Content</button>
</div>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quis sed, dicta quasi in blanditiis nam atque odio, nobis a. Eos incidunt debitis tenetur rerum, esse ratione quisquam possimus quasi nam.</p>
<button>Toggle Content</button>
</div>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quis sed, dicta quasi in blanditiis nam atque odio, nobis a. Eos incidunt debitis tenetur rerum, esse ratione quisquam possimus quasi nam.</p>
<button>Toggle Content</button>
</div>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quis sed, dicta quasi in blanditiis nam atque odio, nobis a. Eos incidunt debitis tenetur rerum, esse ratione quisquam possimus quasi nam.</p>
<button>Toggle Content</button>
</div>
</div>
jsFiddle

Related

Is there a better way of creating tabs using vanilla JavaScript than this?

I'm trying to create tabs within a webpage using HTML buttons and vanilla JavaScript. I've come up with this solution:
const tab1 = document.getElementById("tab-1");
const tab2 = document.getElementById("tab-2");
const tab3 = document.getElementById("tab-3");
const tabs = [tab1, tab2, tab3];
const tab1Content = document.getElementById("tab-1-content");
const tab2Content = document.getElementById("tab-2-content");
const tab3Content = document.getElementById("tab-3-content");
const tabContents = [tab1Content, tab2Content, tab3Content];
tab1.addEventListener("click", () => {displayTab(tab1, tab1Content)});
tab2.addEventListener("click", () => {displayTab(tab2, tab2Content)});
tab3.addEventListener("click", () => {displayTab(tab3, tab3Content)});
function displayTab(tab, tabContent) {
for (let i = 0; i < tabs.length; i++) {
if (tabs[i].classList.contains("active")) {
tabs[i].classList.remove("active");
tabContents[i].classList.add("hide");
}
}
tab.classList.add("active");
tabContent.classList.remove("hide");
}
.hide { display: none }
.active { font-weight : bold }
<h1>Tabs</h1>
<div class="tabBtns">
<button id="tab-1" class="active">Tab 1</button>
<button id="tab-2">Tab 2</button>
<button id="tab-3">Tab 3</button>
</div>
<div class="content">
<div id="tab-1-content">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dignissimos qui labore, quam dicta voluptate
libero est blanditiis perspiciatis voluptatibus perferendis velit repudiandae. Maxime, eligendi. Vitae
magnam similique harum sunt quibusdam.
</div>
<div id="tab-2-content" class="hide">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolores similique assumenda reprehenderit eaque
itaque in magni vero repudiandae, totam maiores saepe iste culpa labore quam esse ipsam fugit cupiditate
facilis sunt aliquid ad sit voluptatibus veritatis non. Eligendi accusantium libero veniam facere, expedita,
magnam quia assumenda similique quas, voluptatum nostrum.
</div>
<div id="tab-3-content" class="hide">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Culpa, sunt?
</div>
</div>
Is there a more efficient way of doing this? It feels like it might be a little redundant having to manually add each tab and its content into their respective arrays, and then having to apply an event listener to each manually as well. I would appreciate a more elegant solution if one is possible.
Iterate over all tabs and hide them when a button is clicked. Find the
index of the clicked button and you can get to the associated <div>, no IDs needed.
const contents = document.querySelectorAll('.content > div');
const buttons = document.querySelectorAll('.tabBtns button');
buttons.forEach((button, i) => {
button.addEventListener('click', () => {
buttons.forEach(button => button.classList.remove('active'));
contents.forEach(content => content.classList.add('hide'));
button.classList.add('active');
contents[i].classList.remove('hide');
});
});
.active {
background-color: yellow;
}
.hide {
display: none;
}
<h1>Tabs</h1>
<div class="tabBtns">
<button class="active">Tab 1</button>
<button>Tab 2</button>
<button>Tab 3</button>
</div>
<div class="content">
<div>
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dignissimos qui labore, quam dicta voluptate libero est blanditiis perspiciatis voluptatibus perferendis velit repudiandae. Maxime, eligendi. Vitae magnam similique harum sunt quibusdam.
</div>
<div class="hide">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolores similique assumenda reprehenderit eaque itaque in magni vero repudiandae, totam maiores saepe iste culpa labore quam esse ipsam fugit cupiditate facilis sunt aliquid ad sit voluptatibus
veritatis non. Eligendi accusantium libero veniam facere, expedita, magnam quia assumenda similique quas, voluptatum nostrum.
</div>
<div class="hide">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Culpa, sunt?
</div>
</div>
You could also save the index of the last clicked button in a persistent variable instead of looping over each element inside the click handler.
you could make a little function to build your tabs
function buildTab(content, number, etc...) {
const tab = document.createElement("div")
tab.innerHTML = content
tab.addEventListener...
// whatever else you wanna do
return tab
}
//json containing all the content you wanna display(?)
const tabs = contentArray.map(c => buildTab(...c))
You can do that with
event delegation
data attribute
you must also use the classList.toggle() method with its boolean option to add or remove a class,
const buttonsParent = document.querySelector('div#tab-Btns')
, all_tab_elms = document.querySelectorAll('button[data-tab], div[data-tab]')
;
buttonsParent.onclick = ({target}) =>
{
if (!target.matches('button[data-tab]')) return // ignore other click in this area (like spaces between buttons)
all_tab_elms.forEach( elTab => elTab.classList
.toggle('active', (elTab.dataset.tab===target.dataset.tab )))
}
button[data-tab].active { font-weight: bold; }
div[data-tab] { display: none; }
div[data-tab].active { display: block; }
<h1>Tabs</h1>
<div id="tab-Btns">
<button data-tab="tab-1" class="active">Tab 1</button>
<button data-tab="tab-2">Tab 2</button>
<button data-tab="tab-3">Tab 3</button>
</div>
<div id="tab-content">
<div data-tab="tab-1" class="active">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dignissimos qui labore, quam dicta voluptate
libero est blanditiis perspiciatis voluptatibus perferendis velit repudiandae. Maxime, eligendi. Vitae
magnam similique harum sunt quibusdam.
</div>
<div data-tab="tab-2">
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolores similique assumenda reprehenderit eaque
itaque in magni vero repudiandae, totam maiores saepe iste culpa labore quam esse ipsam fugit cupiditate
facilis sunt aliquid ad sit voluptatibus veritatis non. Eligendi accusantium libero veniam facere, expedita,
magnam quia assumenda similique quas, voluptatum nostrum.
</div>
<div data-tab="tab-3">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Culpa, sunt?
</div>
</div>

how to use a queryselector on object HTMLInputElement

I am trying that when the text field has focus, the div is selected with the class:autocomplete, this is an example to understand my idea, in my real problem it is more complex. I simply need that once the element that has the focus is identified, select the nearest div with .autocomplete class on the same level, I want to get it this way. I know that in css I should use something like:
input ~ div.autocomplete
($event.target is input in my case)
but I don't know how to do it in this case. Thank you.
function fn_selectAutocompleteClass($event) {
console.log(($event.target));
}
.selectAutocomplete {
background: green;
}
<input id="text" type="text" onfocus="fn_selectAutocompleteClass(event)">
<i class="icon"></i>
<div class="autocomplete">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rerum itaque placeat, ad vel reprehenderit illo, harum nemo laudantium, dolorem unde aut distinctio! Consectetur vitae deleniti veritatis autem numquam officia eaque.</div>
In this case you can access the .autocomplete using the querySelectorAll on the target elements parent like below snippet. Get the 0th index as that will be the first element matching the selector query.
function fn_selectAutocompleteClass($event) {
console.log($event.target.parentNode.querySelectorAll('.autocomplete')[0]);
}
.selectAutocomplete {
background: green;
}
<input id="text" type="text" onfocus="fn_selectAutocompleteClass(event)">
<i class="icon"></i>
<div class="autocomplete">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Rerum itaque placeat, ad vel reprehenderit illo, harum nemo laudantium, dolorem unde aut distinctio! Consectetur vitae deleniti veritatis autem numquam officia eaque.</div>
Hope this helps :)

How to go to next and previous and loop them

i have a situation where i need to go to next and previous div content
for example:
if user clicks CTRL + n or next then it should go to (1st time run)
first div content (if cliked CTRL + n)
second div content (if cliked CTRL + n)
third div content
so on .....
for previous this pattern will continue
below is my whole code:
$(function(){
// CTRL + n ===> Next
//CTRL + p ===> Previous
var index = 0;
$('#next').on('click',function(){
});
$('#previous').on('click',function(){
});
// window.location = '#third' should change dynamically
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#first">
first
</a>
<a href="#second">
second
</a>
<a href="#third">
third
</a>
<a href="#fourth">
fourth
</a>
<div id="first">
<hr>
First
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae provident quibusdam maiores laudantium rem quas doloremque expedita tempora omnis, accusantium vel, consectetur eos ratione modi alias obcaecati numquam sapiente temporibus.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis quam ipsam voluptates sit minus minima quas quasi itaque error natus, exercitationem, praesentium, laudantium voluptas ut quidem dolore? Rem, id quasi.
</div>
<div id="second">
<hr>
Second
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Possimus illo harum, numquam optio iure quae ducimus ipsam velit corporis quidem omnis fugiat expedita autem vitae magni molestiae doloribus, ullam mollitia.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Velit, asperiores eum rem, nostrum provident qui sunt ut neque, consequatur quaerat repellendus error? Aliquam deleniti cum et error in, at voluptate.
</div>
<div id="third">
<hr>
Third
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab, officia? Id voluptatem voluptas similique, reprehenderit odit ab! Laboriosam deserunt illo est obcaecati quaerat, consequuntur, maxime quia quisquam corrupti recusandae, voluptas.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Velit repellendus laborum molestiae asperiores necessitatibus repellat eveniet, obcaecati blanditiis numquam aut soluta veritatis unde, quis, dicta illo dolorem, consectetur temporibus molestias!
</div>
<div id="fourth">
<hr>
Fourth
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut ea tempore corrupti, hic vitae repudiandae quod cumque fugiat iste qui accusantium ipsam amet inventore, dignissimos magnam? Ipsam error eaque inventore!
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illum ipsa itaque eius accusantium. Necessitatibus fugiat dolorum rerum, quam praesentium, aliquam sapiente molestias maiores molestiae. Facilis officia cupiditate quae nisi animi.
</div>
Next |
Previous
Here is jsfiddle: https://jsfiddle.net/jLqt2d1g/9/
See the JS fiddle link JSFiddle(next and previous function)
$(function(){
// CTRL + n ===> Next
//CTRL + p ===> Previous
var id_arr=["first","second","third","fourth"];
var index = 0;
$('#next').on('click',function(){
index++;
var div_id = id_arr[index];
if(index>5){
alert('No More div in this Page');
}else{
alert(div_id);
//based on div_id show the div in page
}
});
$('#previous').on('click',function(){
index--;
var div_id = id_arr[index];
if(index<0){
alert('No More div in this Page');
}else{
alert(div_id);
//based on div_id show the div in page
}
});
// window.location = '#third' should change dynamically
});
i am updated code in the JSfiddle refer that code
In that code in next and previous function you will get the div_id's based on the div'id show div in page

How to stop Drag and Drop bubbling?

I've looked everywhere and cannot seem to find a solution. I am using HTML5's native drag and drop features, which are working great, until I drag a card over another card and they're combining. I don't want them to combine but to drop under the next card.
I assume it's something to do with the appendChild or the fact the cards are within the droppable wrapper? But I can't seem to find another way... Any help?
The codepen is here: https://codepen.io/_and_why_/pen/RyVGPG
<div class="wrap__global">
<div class="wrap__col col__ideas" id="target" ondrop="drop_handler(event);" ondragover="dragover_handler(event);">
<h2 class="col__title">Ideas</h2>
<div id="card0" class="wrap__card" draggable="true" ondragstart="dragstart_handler(event);">
<h2>Dmmy Idea</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium, libero asperiores! Iusto ut, est, facilis dignissimos assumenda sit neque blanditiis deleniti eum libero facere aspernatur numquam repudiandae quas labore enim!</p>
</div>
<div id="card1" class="wrap__card" draggable="true" ondragstart="dragstart_handler(event);">
<h2>Dmmy Idea 2</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Laudantium, libero asperiores! Iusto ut, est, facilis dignissimos assumenda sit neque blanditiis deleniti eum libero facere aspernatur numquam repudiandae quas labore enim!</p>
</div>
</div>
<div class="wrap__col col__prom" id="target" ondrop="drop_handler(event);" ondragover="dragover_handler(event);">
<h2 class="col__title">Promising</h2>
<div id="card2" class="wrap__card" draggable="true" ondragstart="dragstart_handler(event);">
<h2>Dummy promise</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ex necessitatibus nobis quasi odit, harum quis culpa. Ad blanditiis deleniti officia, at ducimus ratione, aliquam, ullam, architecto eum tempora nam nulla!</p>
</div>
</div>
<div class="wrap__col col__do" id="target" ondrop="drop_handler(event);" ondragover="dragover_handler(event);">
<h2 class="col__title">Do</h2>
<div id="card3" class="wrap__card" draggable="true" ondragstart="dragstart_handler(event);">
<h2>Do dummy idea 1</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi unde non dolor corporis repellendus neque modi? Excepturi soluta placeat, quos aliquam enim, tenetur aspernatur officiis hic, quia, rerum iusto alias!</p>
</div>
</div>
</div>
const card = document.querySelectorAll('.wrap__card');
const columns = document.querySelectorAll('.wrap__col');
function dragstart_handler(e) {
e.dataTransfer.setData('text/plain', e.target.id);
e.dropEffect = "move";
}
function dragover_handler(e) {
e.preventDefault();
e.stopPropogation();
e.dataTransfer.dropEffect = "move";
}
function drop_handler(e) {
e.preventDefault();
var data = e.dataTransfer.getData("text/plain");
e.target.appendChild(document.getElementById(data));
}
In case anyone else comes looking, I figured it out. I added the noAllowDrop function to the cards and now you can't drag on top of them.
<div id="card2" class="wrap__card" draggable="true" ondragstart="dragstart_handler(event);" ondragover="noAllowDrop(event)">
<h2>Dummy promise</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ex necessitatibus nobis quasi odit, harum quis culpa. Ad blanditiis deleniti officia, at ducimus ratione, aliquam, ullam, architecto eum tempora nam nulla!</p>
</div>
function noAllowDrop(ev) {
ev.stopPropagation();
}

How to make accordion tabs in different color when active

I need to design accordion in the following way... http://jsfiddle.net/gmcLnowa/1/ as shown on fiddle.
I need to two things to be fixed.
One: How to keep first Tab open by default.
Second: How to show each active tab in different colour when that particular tab contents are active or visible.
Let us say when active
Example One: In Blue colour
Example Two: in red colour
Example Three: In yellow colour.
<div id="accordion">
<ul>
<li>
Example one
</li>
<li>
Example two
</li>
<li>
Example three
</li>
</ul>
<div id="one" class="accordion">
ONE Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet in laborum praesentium esse aliquam molestiae animi non facilis perspiciatis corporis ad molestias quo harum suscipit ipsum incidunt ea voluptates accusantium.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet in laborum praesentium esse aliquam molestiae animi non facilis perspiciatis corporis ad molestias quo harum suscipit ipsum incidunt ea voluptates accusantium.
</div>
<div id="two" class="accordion">
TWO Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet in laborum praesentium esse aliquam molestiae animi non facilis perspiciatis corporis ad molestias quo harum suscipit ipsum incidunt ea voluptates accusantium.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet in laborum praesentium esse aliquam molestiae animi non facilis perspiciatis corporis ad molestias quo harum suscipit ipsum incidunt ea voluptates accusantium.
</div>
<div id="three" class="accordion">
THREE Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet in laborum praesentium esse aliquam molestiae animi non facilis perspiciatis corporis ad molestias quo harum suscipit ipsum incidunt ea voluptates accusantium.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Amet in laborum praesentium esse aliquam molestiae animi non facilis perspiciatis corporis ad molestias quo harum suscipit ipsum incidunt ea voluptates accusantium.
</div>
</div>
You can trigger a click on the first anchor on ready() to show the first accordian by default: Note that you should trigger it on the native element rather than the jQuery element.
JS:
$("a").click(function(){
$(".active").removeClass("active");
$(this).addClass("active");
})
$("a:first")[0].click()
CSS:
a[href="#one"].active{
background:blue !important;
}
a[href="#two"].active{
background:red !important;
}
a[href="#three"].active{
background:yellow !important;
}
Demo
this is possible with jQuery
Example one
chage color of custom color attribute that you want
$('#accordion a').click(function(){
$('#accordion a').css('backgroundColor','transparent');
$(this).css('backgroundColor',$(this).attr('colr'));
});
fiddle
You should alter your HTML to get this effect.
Added CSS:
#accordion div#one.accordion:target + a {
color: blue;
}
#accordion div#two.accordion:target + a {
color: red;
}
#accordion div#three.accordion:target + a {
color: yellow;
}
Altered HTML: (example)
<div id="accordion">
<ul>
<li>
<div id="one" class="accordion">ONE.......</div>
Example one
</li>
<li>
<div id="two" class="accordion">TWO.........</div>
Example two
</li>
<li>
<div id="three" class="accordion">THREE........</div>
Example three
</li>
</ul>
</div>
Working Fiddle
For the first problem, I guess the only thing you can do is to append the hash #one to your page url or to use jQuery.
For the second problem, you can add this to your css:
#one {
border-color: #C00;
}
#two {
border-color: #FF0;
}
#three {
border-color: #CF0;
}

Categories

Resources