ClassName, Index, Multiple dropdown - javascript

I have several links in the menu. Each link is making opacity from 0 to 1 for hidden div. I made dropdown menu this way because I use flex inside that div so I toggle the opacity.
I am using document.getElementsByClassName for selecting an elements. When someone is making a variable with this selector basically he or she has an array with all of the elements with this class.
My code is working, because when I envoke the function from HTML, I'm doing it using parameters. What I would like to do is to connect the link I'm clicking and the div that it shows by index. For example, all links with class A are opening divs with class B. I want to be sure that the first link with class A always opens the first link with class B. I don't want to rely on the parameters in HTML.
How can I do it more efficiently?
function showDropDown(n) {
let hiddenDiv = document.getElementsByClassName("hidden_dropdown_div");
hiddenDiv[n].classList.toggle("active");
for (let i = 0; i < hiddenDiv.length; i++) {
if (i != n) {
hiddenDiv[i].classList.remove("active")
};
}
};
$(".maindrop_link").click(function(e) {
e.stopPropagation(); // This is the preferred method.
return false; // This should not be used unless you do not want
// any click events registering inside the div
});
$(document).click(function() {
let hiddenDiv = document.getElementsByClassName("hidden_dropdown_div");
for (let i = 0; i < hiddenDiv.length; i++) {
hiddenDiv[i].classList.remove("active");
}
});
.hidden {
opacity: 0;
}
.active {
opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- See the link above the hidden block -->
<li class="dropmenu inlineblock">
<a class="maindrop_link" href="#" onclick="showDropDown(0)">Makeup</a>
</li>
<div class="hidden_dropdown_div hidden" id="hidden_dropdown_div">
<div class="hidden_dropdown_link_wrapper">
<ul class="hidden_dropdown_ul">
<li><a class="hiddendrop_link" href="#">Wedding Makeup</a></li>
<li><a class="hiddendrop_link" href="#">Event Makeup</a></li>
<li><a class="hiddendrop_link" href="#">Creative Makeup</a></li>
</ul>
</div>
<div class="hidden_dropdown_pic_wrapper">
<div class="item_for_hidden_div">
<div class="picholder_for_hidden_div"></div>
<div class="textholder_for_hidden_div"></div>
</div>
<div class="item_for_hidden_div">
<div class="picholder_for_hidden_div"></div>
<div class="textholder_for_hidden_div"></div>
</div>
<div class="item_for_hidden_div">
<div class="picholder_for_hidden_div"></div>
<div class="textholder_for_hidden_div"></div>
</div>
</div>
</div>

Related

How do I change a specific image when a list class is active

I have website which is made with materialize. I am using a ul with three li elements which are all collapsible. On top of that is a card with an image. I want to change the image when a li element is active, respectively, expanded.
There were some similar question on here already, but none really fit my problem.
Following is an example layout of my code.
<div class="card">
<div class="card-image">
<img src="img/image-1.jpg"/>
</div>
<ul class="collapsible expandable">
<li class="active">
<div class="collapsible-header">
<div class="collabsible-body">
</li>
</ul>
</div>
The active class appears when you expand the respective li element. It disappears again if you close it.
image-1.jpg should change, corresponding to the li element when the respective li element is active.
Any help is greatly appreciated!
If you are the one toggling the class between active and collapsed, you could add additional code to your toggle function which can swap out the src of that image.
If not, you can use a Mutation Observer to fire a callback when the class of that DOM element has changed. You'll still have to update the src in response to the class change.
// will watch target element for changes to the 'class'
// attribute and fire the callback with an array of the
// class names when changed
const observeClassList = (element, callback) => {
const config = { attributes: true }
const mutationCallback = mutationsList => {
mutationsList.forEach(mutation => {
if (mutation.attributeName === `class`)
callback([...mutation.target.classList])
})
}
const observer = new MutationObserver(mutationCallback)
observer.observe(element, config)
}
// example implementation
// it's up to you to watch for any class changes you desire on any element,
// and make changes to any other element (ie updating and image src) when desired
const changeImageOnToggle = (imageElement, toggleElement) => {
const callback = classArray => {
if (classArray.includes(`active-li`)) {
// update the image element src
}
}
observeClassList(toggleElement, callback)
}
Is this what you want?
$('.active-li').click(function(){
$(this).toggleClass("active");
var new_src = $(this).attr('data-img');
$(".card-image img").attr("src",new_src);
$(".card-image p").text('src of this img is '+new_src);
});
.active{
color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="card">
<div class="card-image">
<img src="img/image-1.jpg"/>
<p > </p>
</div>
<ul class="collapsible expandable">
<li data-img="img/image-2.jpg" class="active-li">
Lorem
</li>
<li data-img="img/image-1.jpg" class="active-li">
Lorem
</li>
</ul>
</div>
I used Midos logic and it worked fine ... but how do I return the image back to its original image?
$('.egg').click(function(){
$(this).toggleClass("active");
var new_src = $(this).attr('data-img');
$(".green-egg img").attr("src",new_src);
return;
});

addEventListener not working on first click

This code is for opening and closing an accordion menu, but the event I added to 'acc' does not work on the first click.
let acc = document.getElementById("acc");
let list = document.getElementById("list");
let rest = document.getElementById("rest");
let nav = document.getElementById("nav");
let line = document.getElementsByClassName("line")
acc.addEventListener("click", () => {
if (list.style.left == '-50%') {
list.style.left = "0";
Array.prototype.forEach.call(line, function(value, index) {
line[index].style.backgroundColor = "lightBlue";
});
} else {
list.style.left = "-50%";
Array.prototype.forEach.call(line, function(value, index) {
line[index].style.backgroundColor = 'rgba(0, 0, 0, 0.781)';
});
}
});
rest.addEventListener("click", () => {
list.style.left = "-50%";
Array.prototype.forEach.call(line, function(value, index) {
line[index].style.backgroundColor = 'rgba(0, 0, 0, 0.781)';
});
})
<nav class="nav" id="nav">
<p class="header">koooooooooooooon</p>
<button class="accordion" id="acc">
<div class="wrap">
<div class="line"></div>
<div class="line"></div>
<div class="line"></div>
</div>
</button>
</nav>
<div class="list" id="list">
<ul class="ul">
<li>home</li>
<li>konkor</li>
<li>konkor arshad</li>
<li>emtehan nahaii</li>
</ul>
</div>
<div class="rest" id="rest">
<p class="p">welcome to our lil app</p>
</div>
I couldn't think of any other way to do this.
For this syndrome the tipical problem is: CSS overrides. If you hide by default via css class your menu, then in the first click the script will detect the oposit what you think it will. Set the initial value in the style attribute, or use classes to determinate the current state of the elements.
A little explanation: if you use only pure JavaScript, it won't take care about the style settings which you set on the Element with classes. It only returns those style which are directly set on the element with the style attribute.
ie. You set via css the Left property of the element to -50%. The JavaScript will return "" if you call the style.left because it can't detect the CSS class' value. Then on second click it will work properly and it will return -50% than 0 than again -50%. This will be invisible because, the style attribute will be set to a value on first click which is the default value you set with a class previously.
Also I want to note, this is not true in case of jQuery. If you using jQuery it detects somehow the attributes on the Elements, which was applied via classes.

Detect click outside divs with particular class and hide them

My DOM looks like this:
<div class = filter x>
<div class = a>
<ul><li>……..</li></ul>
</div>
</div>
<div class = filter y>
<div class = a>
<ul><li>……..</li></ul>
</div>
</div>
Both the divs with class a are dropdown menus. The expected functionality is:
Whenever I click on divs with class filter, js-active class is added
and the dropdown opens.
Whenever I click anywhere outside the div or
the dropdown, js-active class is removed and the dropdown hides.
At a time, only one out of the two dropdowns will be open.
Another event that I am handling is that if one dropdown is visible and I click on another dropdown, first one hides (remove class js-active)
I am able to achieve this with the following code:
$(document).on('mouseup touchend', function(e){
var xContainer = $(‘.filter x’);
var yContainer = $(‘.filter y’);
if (!xContainer.is(e.target) && xContainer.has(e.target).length === 0)
{
xContainer.removeClass('js-active');
}
if (!yContainer.is(e.target) && yContainer.has(e.target).length === 0)
{
yContainer.removeClass('js-active');
}
});
I want to optimize this code. I tried using jQuery "each" to iterate over all the divs with class filter and use the same logic but it didn’t work as expected. Any suggestions would be helpful. Thanks.
There is no need to handle both x & y separately, you can do something like
$(document).on('mouseup touchend', function(e) {
var $filter = $(e.target).closest('.filter');
if ($filter.length) {
$filter.addClass('active');
}
$('.filter.active').not($filter).removeClass('active');
});
.filter {
min-height: 20px;
background-color: lightgrey;
margin-bottom: 5px;
}
.filter .a {
display: none;
}
.filter.active .a {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="filter x">
<div class="a">
<ul>
<li>……..</li>
</ul>
</div>
</div>
<div class="filter y">
<div class="a">
<ul>
<li>……..</li>
</ul>
</div>
</div>
Some other content
After trying more, I got this to work too:
$(document).on('mouseup touchend', function(e){
$('.filter').each(function(){
if(!$(this).is(e.target) && $(this).has(e.target).length === 0)
{
$(this).removeClass('js-active');
}
});
});
Works on all devices.

jquery hide div loaded previously with jquery click function

I'm trying to create a menu that will show a div when one of the items is clicked by adding the class "visible".
When a second Item is clicked on the menu, it's suppose to hide the previous div by replacing the class "visible" with hidden"
I am not able to make it hide the previous div and I have tried using if conditionals I guess I'm doing something wrong. I appreciate any help on this.
This is the menu I'm using:
<ul class="product_dynamic list_male">
<li><span class="title">option 1</span></li>
<li><span class="title">option 2</span></li>
</ul>
Jquery
for (var i = 1; i <= 3; ++i) {
(function (n) {
$('.prod_switch_' + n).bind('click',function() {
$('#prod_switch_' + n).removeClass('hidden');
$('#prod_switch_' + n).addClass('visible');
});
})(i);
}
html
<div class="product_display visible" id="prod_switch_1">content</div>
<div class="product_display visible" id="prod_switch_2">content</div>
EDIT
Read the question completely wrong the first time :P You shouldn't need to change any HTML, just take a look at this JS.
Use JS to remove the active class from all elements before adding it to the clicked one.
JS:
for (var i = 1; i <= 3; ++i) {
(function (n) {
$('.prod_switch_' + n).bind('click',function() {
$('#prod_switch_' + n).removeClass('hidden');
$('.product_display').removeClass('visible');
$('#prod_switch_' + n).addClass('visible');
});
})(i);
}
To hide any visible product_display divs on list item on click, try:
$('.product_dynamic a').on('click', function(evt) {
$('.product_display.visible').removeClass('visible'); // hide all visible product_display divs
var targetID = $(evt.target).attr('class'); // get ID of element to show
$('#' + targetID).addClass('visible'); // show that element
});
$(".list_male a").click(function(event){
event.preventDefault();
$(".product_display").removeClass("visible");//HIDE ALL CONTENTS
var new_content=$(this).data("content");//GET ID FROM NEW OBJECT TO ADD visible CLASS
$("#"+new_content).addClass("visible");//SHOW NEW CONTENT
return false;
});
.visible{
display:block !important;
}
.product_display{
display:none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script>
<ul class="product_dynamic list_male">
<li><span class="title">option 1</span></li>
<li><span class="title">option 2</span></li>
</ul>
<div class="product_display" id="content_1">content 1</div>
<div class="product_display" id="content_2">content 2</div>

Linking to a section of a site that is hidden by a hide/show JavaScript function

I am using a bit of JavaScript to show/hide sections of a site when a tab is clicked. I'm trying to figure out if there is a way I can link back to the page and have a certain tab open based on that link.
Here is the JS:
var ids=new Array('section1','section2','section3','section4');
function switchid(id, el){
hideallids();
showdiv(id);
var li = el.parentNode.parentNode.childNodes[0];
while (li) {
if (!li.tagName || li.tagName.toLowerCase() != "li")
li = li.nextSibling; // skip the text node
if (li) {
li.className = "";
li = li.nextSibling;
}
}
el.parentNode.className = "active";
}
function hideallids(){
//loop through the array and hide each element by id
for (var i=0;i<ids.length;i++){
hidediv(ids[i]);
}
}
function hidediv(id) {
//safe function to hide an element with a specified id
document.getElementById(id).style.display = 'none';
}
function showdiv(id) {
//safe function to show an element with a specified id
document.getElementById(id).style.display = 'block';
}
And the HTML
<ul>
<li class="active"><a onclick="switchid('section1', this);return false;">One</a></li>
<li><a onclick="switchid('section2', this);return false;">Two</a></li>
<li><a onclick="switchid('section3', this);return false;">Three</a></li>
<li><a onclick="switchid('section4', this);return false;">Four</a></li>
</ul>
<div id="section1" style="display:block;">
<div id="section2" style="display:none;">
<div id="section3" style="display:none;">
<div id="section4" style="display:none;">
I haven't been able to come up with a way to link back to a specific section. Is it even possible with this method?
Thanks!
You could run some script when your page loads that checks the url hash & loads the appropriate section:
// on page load
var sectionid = /section\d/i.exec(location.hash);
if (sectionid) {
var link = document.getElementById(switchid[0] +"_link");
switchid(sectionid[0], link);
}
& add an id to your links:
<li><a id="section2_link" onclick="switchid('section2', this);return false;">Two</a></li>
HTML functionality is entirely independent of CSS. Therefore the following code will always work even if the intended section is set to display:none.
Link to section3

Categories

Resources