I have a function that shows an html element when hovered upon, but it does not seem to be working as intended.
My code in the js file is as follows:
const htmlIc = document.querySelector('.fa-html5');
const htmlInfo = document.querySelector('.info-section');
htmlIc.addEventListener("mouseover", toggleHtml);
function toggleHtml() {
htmlInfo.classList.add("show");
}
This is the element that the event listener is listening upon (the icon):
<div class="icons">
<a href="#!">
<i class="fab fa-html5 fa-2x"></i>
</a>
</div>
This is the element I would like to have the show class applied to:
<div class="info-section">
<h1>Lorem ipsum</h1>
</div>
I use SASS in this project, and I have verified by manually adding the show class to the element, and it is not a problem from that part
You can do something where you are toggling them via the style display option. One thing you could do is if you are married to using show class then you would need to create a similar toggle between displaying show and hide.
const htmlIc = document.querySelector(".fa-html5");
const htmlInfo = document.querySelector(".info-section");
htmlIc.addEventListener("mouseover", toggleHtml);
function toggleHtml() {
let infoSection = document.querySelector(".info-section");
if (infoSection.style.display === "none") {
infoSection.style.display = "block";
} else {
infoSection.style.display = "none";
}
}
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<div class="icons">
<a href="#!">
<i class="fab fa-html5 fa-2x">hh</i>
</a>
<div class="info-section" style="display: none;">
<h1>Lorem ipsum</h1>
</div>
</div>
<script src="src/index.js"></script>
</body>
</html>
it's work!
also add .show css class
const htmlIc = document.querySelector('.fa-html5');
const htmlInfo = document.querySelector('.info-section');
htmlIc.addEventListener("mouseover", toggleHtml);
function toggleHtml() {
htmlInfo.classList.add("show");
}
<div class="icons">
<a href="#!">
<i class="fab fa-html5 fa-2x"></i>
</a>
</div>
<div class="info-section">
<h1>Lorem ipsum</h1>
</div>
htmlInfo.classList.toggle("show");
I just had to use the .toggle method for the classList. Since I was using a hover effect, the toggle was more suited for this situation. Credit goes to #BerkCoşar in the comments for this solution
Related
I need to display the title value of the image (class name: media_image) in another p tag (class name: media_folder_title) for every row. But I can't able to get the value. I have attached the sample code here.
Screenshot:
HTML Code:
<div id="media-folder">
<div class="media_folder">
<i class="fa fa-folder-open"></i>
<img src="/img/artist/default.jpg" alt="5382" title="Test" class="media_image">
<p class="media_folder_title"></p>
</div>
<div class="media_folder">
<i class="fa fa-folder-open"></i>
<img src="/img/artist/default.jpg" alt="5383" title="test1" class="media_image">
<p class="media_folder_title"></p>
</div>
<div class="media_folder">
<i class="fa fa-folder-open"></i>
<img src="/img/artist/default.jpg" alt="5118" title="Uploads" class="media_image">
<p class="media_folder_title"></p>
</div>
</div>
jQuery Code:
$(".media_folder img.media_image").each(function(){
var imgtitle = $(this).attr("title");
console.log(imgtitle);
setTimeout(function(){
console.log("settimout ok");
$(this).append("<p>"+imgtitle+"</p>");
}, 3000);
});
The problem is with the $(this) in the timeout because it's no longer the image but the window.
Also, append aims to append an element inside another element. It's not possible appending an element inside an image.
As your snippet implies, you want to append the p tag after the image, after is the right function for that.
$(".media_folder img.media_image").each(function() {
const $img = $(this);
const imgtitle = $img.attr("title");
setTimeout(function() {
$img.after("<p>" + imgtitle + "</p>");
}, 3000);
});
<div id="media-folder">
<div class="media_folder">
<i class="fa fa-folder-open"></i>
<img src="/img/artist/default.jpg" alt="5382" title="Test" class="media_image">
<p class="media_folder_title"></p>
</div>
<div class="media_folder">
<i class="fa fa-folder-open"></i>
<img src="/img/artist/default.jpg" alt="5383" title="test1" class="media_image">
<p class="media_folder_title"></p>
</div>
<div class="media_folder">
<i class="fa fa-folder-open"></i>
<img src="/img/artist/default.jpg" alt="5118" title="Uploads" class="media_image">
<p class="media_folder_title"></p>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
Change the selectors in the first line into:
.media_folder img .media_image
Sometimes space is important.
Your problem is that you are trying to append something inside an img tag, which is not possible - as with a few other html elements.
What you are looking for is $.after()
Try $(this).after($('<p />').text(imgtitle))
I'm not the best at JavaScript but hope that someone can help me with this.
What i want is that when you press on the one of the buttons, the button gives the div the class open.
I have multiple buttons, so what i mean by this is click on button, button gives content1 the class open, when you press on one of the other buttons the class of that div will be gonna and assign on the other div that button was linked to and so on.
What I now get is that all the open divs stay at the class and didn't get removed. I have tried multiple things like search on google or use other technics but nothing works..
const content1 = document.querySelector('.content1');
const content2 = document.querySelector('.content2');
const content3 = document.querySelector('.content3');
var dn = document.querySelector('.dn');
const one = document.querySelector('.one');
const two = document.querySelector('.two');
const three = document.querySelector('.three');
one.addEventListener('click', () => {
if (dn.classList.contains('open')) {
dn.classList.remove('open');
} else {
content1.classList.add('open');
}
})
two.addEventListener('click', () => {
if (dn.classList.contains('open')) {
dn.classList.remove('open');
} else {
content2.classList.add('open');
}
})
three.addEventListener('click', () => {
if (dn.classList.contains('open')) {
dn.classList.remove('open');
} else {
content3.classList.add('open');
}
})
.dn {
display: none;
}
.open {
display: block;
}
<div id="mainBOX" class="mainBOX">
<button class="btn one">btn1</button>
<button class="btn two">btn2</button>
<button class="btn three">btn3</button>
<div class="dn content1">
<h1>Lorem Ipsum</h1>
</div>
<div class="dn content2">
<h1>Lorem Ipsum2</h1>
</div>
<div class="dn content3">
<h1>Lorem Ipsum3</h1>
</div>
</div>
If you you are trying to make sure that the current clicked item becomes open, you need to first make sure you close all the existing elements matching .dn. Your code was only addressing the first one.
Your code was never removing the open from any of the divs.
Lastly, two things that will improve your code greatly:
Event delegation: so that you only need a single handler
Using data attributes to associate buttons with their divs (someone else suggested using index which is OK but most people try to stay away from parallel arrays)
document.getElementById('mainBOX').addEventListener('click', (e)=> {
// Ignore clicks not on buttons
if (e.target.tagName !== 'BUTTON') {
return;
}
// Close all divs
Array.from(document.querySelectorAll('.dn')).forEach(
dn => dn.classList.remove('open')
);
// Open the current one
document.querySelector('.' + e.target.dataset.for).classList.add('open');
});
.dn {
display: none;
}
.open {
display: block;
}
<div id="mainBOX" class="mainBOX">
<button data-for="content1" class="btn">btn1</button>
<button data-for="content2" class="btn">btn2</button>
<button data-for="content3" class="btn">btn3</button>
<div class="dn content1">
<h1>Lorem Ipsum</h1>
</div>
<div class="dn content2">
<h1>Lorem Ipsum2</h1>
</div>
<div class="dn content3">
<h1>Lorem Ipsum3</h1>
</div>
</div>
I'd just target your divs by index:
$('.btn').click(function() {
// get the zero-based index of the clicked element
let index = $(this).index();
// hide all divs inside the container and remove the 'open' class
$('#mainBOX div').hide().removeClass('open');
// show just the div with the right index and add the 'open' class
$('#mainBOX div').eq(index).show().addClass('open');
});
.dn {
display: none;
}
<script
src="https://code.jquery.com/jquery-3.5.1.slim.min.js"
integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs="
crossorigin="anonymous"></script>
<div id="mainBOX" class="mainBOX">
<button class="btn one">btn1</button>
<button class="btn two">btn2</button>
<button class="btn three">btn3</button>
<div class="dn content1">
<h1>Lorem Ipsum</h1>
</div>
<div class="dn content2">
<h1>Lorem Ipsum2</h1>
</div>
<div class="dn content3">
<h1>Lorem Ipsum3</h1>
</div>
</div>
To summarize:
Use DOM traversal to target elements rather than specific class names
Use class names to identify sets of like elements
Don't bother with classes to toggle visibility (unless you want elaborate animations)
If using jQuery, familiarize yourself with the common methods it provides so you aren't reinventing wheels
Rather than separate classes for open and not open, just make one the default and apply the other
Don't Repeat Yourself in your code
I have shortened your code using the forEach() method and the toggle() method for each content.
Was it necessary?
const btn = document.querySelectorAll('.btn');
const content = document.querySelectorAll('.dn');
Array.from(btn).forEach(function(btnArray, i) {
btnArray.addEventListener('click', function() {
content[i].classList.toggle('open');
});
});
.dn {
display: none;
}
.open {
display: block;
}
<div id="mainBOX" class="mainBOX">
<button class="btn one">btn1</button>
<button class="btn two">btn2</button>
<button class="btn three">btn3</button>
<div class="dn content1">
<h1>Lorem Ipsum</h1>
</div>
<div class="dn content2">
<h1>Lorem Ipsum2</h1>
</div>
<div class="dn content3">
<h1>Lorem Ipsum3</h1>
</div>
</div>
Take a look at this. Use a forEach function to handle the click event in all buttons with a specific class
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Hide and show</title>
<style>
.dn {
display: none;
}
.btn {
margin-right: 10px;
}
.open {
display: block;
}
</style>
</head>
<body>
<!-- Sample with three contents -->
<div id="c1" class="dn content">
<h1>Content 1</h1>
</div>
<div id="c2" class="dn content">
<h1>Content 2</h1>
</div>
<div id="c3" class="dn content">
<h1>Content 3</h1>
</div>
<!-- Sample with three buttons -->
<button id="btn1" class="action-btn">Button 1</button>
<button id="btn2" class="action-btn">Button 2</button>
<button id="btn3" class="action-btn">Button 3</button>
<button id="clean" class="action-btn">Limpiar</button>
<script>
const buttons = document.querySelectorAll(".action-btn");
const contents = document.querySelectorAll(".content");
buttons.forEach(function (item) {
item.addEventListener("click", function (e) {
if (item.id === "clean") {
contents.forEach((item) => item.classList.remove("open")); // Clean all the open classes
} else {
contents.forEach((item) => item.classList.remove("open"));
switch (item.id) {
case "btn1":
const c1 = document.getElementById("c1");
if (!c1.classList.contains("open")) {
c1.classList += " open";
}
break;
case "btn2":
const c2 = document.getElementById("c2");
if (!c2.classList.contains("open")) {
c2.classList += " open";
}
break;
case "btn3":
const c3 = document.getElementById("c3");
if (!c3.classList.contains("open")) {
c3.classList += " open";
}
break;
}
}
});
});
</script>
</body>
</html>
OK, I rewrote my contribution from scratch, as I did not read OP requirements properly at first.
Undoubtedly, #isherwood's answer should be the accepted one here, as it uses the index of the clicked button and because it uses jQuery which makes the script so much more easy to read!
However, in my contribution I would like to show that the same is also possible without jQuery. Admittedly, it gets a little more complicated:
The whole action happens within an IIFE ((function(){...})()) to keep the global name space clean. mBox is the #mainBox DOM element to which I attach the delegated click event for all BUTTONs.
Every time the click event handler is fired it collects all the buttons in mBox in the array btns (the [...mBox.SelectorAll()] construct is necessary to create a JavaScript Array from the collection that is returned by .querySelectorAll()).
odiv is the (potentially) open div from a previous operation that needs to be closed again by removing the class open from it.
Eventually the open class gets added to the div with the same index as the clicked button in the line
mBox.querySelectorAll('div')[btns.indexOf(ev.target)].classList.add('open');
By using delegated event listening and by cheching the available buttons and divs after each click it is possible to dynamically add buttons and divs to the page without having to attach event listeners to these elements.
(function(){
const mBox=document.getElementById('mainBOX');
mBox.onclick=ev=>{
const btns=[...mBox.querySelectorAll('button')];
if (ev.target.tagName=="BUTTON"){
let odiv=mBox.querySelector('div .open')
if (odiv) odiv.classList.remove('open');
mBox.querySelectorAll('div')[btns.indexOf(ev.target)].classList.add('open');
}
}
})()
.dn { display: none; }
.open { display: block;}
<div id="mainBOX" class="mainBOX">
<button class="btn one">first </button>
<button class="btn two">second</button>
<button class="btn three">third</button>
<button class="btn four">fourth</button>
<button class="btn five">fifth</button>
<button class="btn six">sixth</button>
<button class="btn seven">seventh</button>
<button class="btn eight">eighth</button>
<button class="btn nine">nineth</button>
<button class="btn ten">tenth</button>
<div class="dn content1">
<h1>Lorem Ipsum</h1>
</div>
<div class="dn content2">
<h1>Lorem Ipsum2</h1>
</div>
<div class="dn content3">
<h1>Lorem Ipsum3</h1>
</div>
<div class="dn content4">
<h1>Lorem Ipsum4</h1>
</div>
<div class="dn content5">
<h1>Lorem Ipsum5</h1>
</div>
<div class="dn content6">
<h1>Lorem Ipsum6</h1>
</div>
<div class="dn content7">
<h1>Lorem Ipsum7</h1>
</div>
<div class="dn content8">
<h1>Lorem Ipsum8</h1>
</div>
<div class="dn content9">
<h1>Lorem Ipsum9</h1>
</div>
<div class="dn content10">
<h1>Lorem Ipsum10</h1>
</div>
</div>
Close button which remove the elements from DOM, work only on the second click.
Here is HTML part of button: That is closeBtn.
function removeHeader() {
var list = document.getElementById("main");
list.removeChild(list.childNodes[0]);
}
<div id="main">
<div class="nanoSaturnBanner">
<p>teteasdasdasdsadasds sad asdasdasdasdasdas</p>
<div class="banner-buttons">
<label class="showme">Ads by Google</label>
<a class="infoLink" href="https://support.google.com/adsense/#topic=3373519" target="_blank">
<i class="fas fa-info-circle"></i>
</a>
<div class="closeBtn" onclick="removeHeader()">
closeBtn
</div>
</div>
</div>
</div>
You should use list.childNodes[1] because the list.childNodes[0] represent the #text node that is the whitespaces after <div id="main">. So, in first click it was removing that node and in second click it was removing the actual node with <div class="nanoSaturnBanner">
function removeHeader() {
var list = document.getElementById("main");
list.removeChild(list.childNodes[1]);
}
<div id="main">
<div class="nanoSaturnBanner">
<p>teteasdasdasdsadasds sad asdasdasdasdasdas</p>
<div class="banner-buttons">
<label class="showme">Ads by Google</label>
<a class="infoLink" href="https://support.google.com/adsense/#topic=3373519" target="_blank">
<i class="fas fa-info-circle"></i>
</a>
<div class="closeBtn" onclick="removeHeader()">
<i class="far fa-window-close">close</i>
</div>
</div>
</div>
Note: Whitespace inside elements is considered as text, and text is considered as nodes. Comments are also considered as nodes.
As childNodes get none element nodes as well, like text and comment, use e.g. children instead to get the first actual element.
Note, with that you also make sure getting the element no matter how many "none element nodes" their might be in your markup.
Stack snippet
function removeHeader() {
var list = document.getElementById("main");
list.removeChild(list.children[0]);
}
<div id="main">
<div class="nanoSaturnBanner">
<p>teteasdasdasdsadasds sad asdasdasdasdasdas</p>
<div class="banner-buttons">
<label class="showme">Ads by Google</label>
<a class="infoLink" href="https://support.google.com/adsense/#topic=3373519" target="_blank">
<i class="fas fa-info-circle"></i>
</a>
<div class="closeBtn" onclick="removeHeader()">
<i class="far fa-window-close">close</i>
</div>
</div>
</div>
function removeHeader() {
var list = document.getElementById("main");
list.remove(list.childNodes[0]); // replacing removeChild with remove worked
}
Check the fiddle.
I'm trying to make a box with a title and 2 arrows left and right of the title. When you click on either arrow, the box should fade out and the next one should fade in. I have another one like this on my page with 2 option (send and go back) and that one works fine, but for some reason it breaks when I have 3 options. I suspect it's my jQuery code that breaks when adding a third option.
My JSFiddle (minimal CSS to avoid confusion, the problem isn't there)
$('#go2').click(function(e) {
$('.box1, .box3').fadeOut('fast', function() {
$('.box2').fadeIn('slow');
});
});
$('#go3').click(function(e) {
$('.box2, .box1').fadeOut('fast', function() {
$('.box3').fadeIn('slow');
});
});
$('#go1').click(function(e) {
$('.box2, .box3').fadeOut('fast', function() {
$('.box1').fadeIn('slow');
});
});
The IDs must be unique (refer to id="go2").
The jQuery library must be included before the other libs.
You can simplify everything using a unique handler:
$('.box1, .box2, .box3').on('click', function(e) {
var isArrowRight = $(e.target).is('.right');
var isLeftArrow = $(e.target).is('.left');
if (!(isArrowRight || isLeftArrow)) {
return; // do nothing if you don't click the left/right arrow...
}
var nextEle = (isArrowRight) ? $(this).next('[class^=box]') : $(this).prev('[class^=box]');
if (nextEle.length == 0) {
nextEle = (isArrowRight) ? $('.box1') : $('.box3');
}
$('.box1:visible, .box2:visible, .box3:visible').fadeOut('fast', function(){
nextEle.fadeIn('slow');
});
});
i {
display: inline;
}
h1 {
display: inline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap..css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.0/components/icon.min.css">
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.3.0/semantic.min.js"></script>
<div class="box1">
<div class="boxTitle">
<i id="go3" class="icon angle left"></i>
<h1>Box 1</h1>
<i id="go22" class="icon angle right"></i>
</div>
<div class="boxField1">
Boxfield 1
</div>
</div>
<div class="box2" style="display: none">
<div class="boxTitle">
<i id="1" class="icon angle left"></i>
<h1>Box 2</h1>
<i id="3" class="icon angle right"></i>
</div>
<div class="boxField2">
Boxfield 2
</div>
</div>
<div class="box3" style="display: none">
<div class="boxTitle">
<i id="go2" class="icon angle left"></i>
<h1>Box 3</h1>
<i id="go1" class="icon angle right"></i>
</div>
<div class="boxField3">
Boxfield 3
</div>
</div>
Sorry but looking your jsfiddle file I see 2 problems:
you use the same id for more html tag, it's not possible try using class.
On the box2 you use id="1" and id="3" but on js you use go1, go2, go3.
I want to show only one div when the user clicks the links on the icon bar and hide others. When the user clicks home link of the icon bar only 'hoediv'is visible and others hidden.
My work is below please help!!
<!doctype HTML>
<head>
<div class="main-header-div">
<a id="home" href="" > Home</a>
<a id="about" href=""> About us</a>
</div>
</head>
<body>
<script>
$(function(){
$("#home").click(function(){
$("#homediv").show();
$("#aboutus").hide();
return false;
});
});
</script>
<div id="homediv" style="color:white; background-color:red;height:89px;
width:100%;font-size:150%; display:none;">This is my site.
</div>
<div id="aboutus" style="display:none;">
this is about us page
</div>
</body>
</html>
What you need to fix?
Firstly, <head></head> only includes metadata, the rest should be in the <body></body>.
If you're not going to make use <a> anchor tags for hyperlinking, then pass the value href="JavaScript:Void(0);" (The void operator evaluates the given expression and then returns undefined) or better yet, don't use anchor tags better yet span or button.
You didn't import jquery.js in your html file.
You can make this a lot more effecient, but I'd suggest you learn some basic html from the widely available sources and then CSS, Jquery,etc.
Sources to refer:
https://www.w3schools.com/html/html5_intro.asp
https://www.w3schools.com/css/default.asp
https://www.w3schools.com/jquery/default.asp
$(function() {
$("#home").click(function() {
$("#homediv").show();
$("#aboutus").hide();
});
$("#about").click(function() {
$("#homediv").hide();
$("#aboutus").show();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main-header-div">
<a id="home" href="JavaScript:Void(0);"> Home</a>
<a id="about" href="JavaScript:Void(0);"> About us</a>
</div>
<div id="homediv" style="color:white; background-color:red;height:89px;
width:100%;font-size:150%; display:none;">This is my site.
</div>
<div id="aboutus" style="display:none;">
this is about us page
</div>
If you want to simplify it, you can use classes and data attributes to toggle wanted content:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main-header-div">
<a class="header-link" id="home" data-toggle="homediv" href="#" > Home</a>
<a class="header-link" id="about" data-toggle="aboutus" href="#"> About us</a>
</div>
<div class="content" id="homediv" style="color:white; background-color:red;height:89px;
width:100%;font-size:150%; display:none;">
This is my site.
</div>
<div class="content" id="aboutus" style="display:none;">
this is about us page
</div>
<script>
$(document).ready(function() {
$(".header-link").click(function(){
$(".content").hide();
$("#" + $(this).attr("data-toggle")).show();
});
});
</script>