I am trying to add to my accordion minus sign to appear after clicking on the row.
I've tried adding minus/plus let and tried to add display.styles for it. But it seems really buggy and not working properly. How can I set this up properly? And it only works for first element instead of all.
const tabs = document.querySelectorAll(".faq__tab").forEach(button => {
button.addEventListener("click", () => {
const tabsContent = button.nextElementSibling;
button.classList.toggle('active-faq');
let minus = document.querySelector(".plus")
let plus = document.querySelector(".minus")
if (button.classList.contains('active-faq')) {
tabsContent.style.maxHeight = tabsContent.scrollHeight + 'px';
plus.style.display = 'none';
minus.style.display = 'flex';
} else {
tabsContent.style.maxHeight = 0;
minus.style.display = 'none';
plus.style.display = 'flex';
}
})
});
.plus {
padding-left: 10px;
}
.minus {
padding-left: 10px;
display: none;
}
.faq__panel {
max-height: 0px;
overflow: hidden;
}
<button class="faq__tab">Question
<img src='img/plus.svg' alt="Show" class="plus">
<img src='img/minus-svg.png' alt="Hide" class="minus">
</button>
<div class="faq__panel">
<p>Answerr
</p>
</div>
You probably need to use inline-flex instead of flex:
const tabs = document.querySelectorAll(".faq__tab").forEach(button => {
button.addEventListener("click", () => {
const tabsContent = button.nextElementSibling;
button.classList.toggle('active-faq');
let minus = button.querySelector(".plus");//instead of document use button to target the corresponding element
let plus = button.querySelector(".minus");//instead of document use button to target the corresponding element
if (button.classList.contains('active-faq')) {
tabsContent.style.maxHeight = tabsContent.scrollHeight + 'px';
minus.style.display = 'none';
plus.style.display = 'inline-flex';
} else {
tabsContent.style.maxHeight = 0;
plus.style.display = 'none';
minus.style.display = 'inline-flex';
}
})
});
.plus {
padding-left: 10px;
}
.minus {
padding-left: 10px;
display: none;
}
.faq__panel {
max-height: 0px;
overflow: hidden;
}
<button class="faq__tab">Question1
<img src='img/plus.svg' alt="Show" class="plus">
<img src='img/minus-svg.png' alt="Hide" class="minus">
</button>
<div class="faq__panel">
<p>Answer1</p>
</div>
<button class="faq__tab">Question2
<img src='img/plus.svg' alt="Show" class="plus">
<img src='img/minus-svg.png' alt="Hide" class="minus">
</button>
<div class="faq__panel">
<p>Answer2</p>
</div>
The problem in that you're setting image display to flex, either give the button faq__tab display: flex in the css file, or set display: inline to images
if (button.classList.contains('active-faq')) {
tabsContent.style.maxHeight = tabsContent.scrollHeight + 'px';
plus.style.display = 'none';
minus.style.display = 'inline';
} else {
tabsContent.style.maxHeight = 0;
minus.style.display = 'none';
plus.style.display = 'inline';
}
Related
I have problem that I need help with
I put a simple exemple of my code from w3schools to make it more simple.
I have a tab gallary with 4 images, that you can click on an image so it will get viewed bigger under.
This thing is working with onclick function.
What I want is to make the onclick= none until a condition happened (if text is contains something in this exemple.
I made the image onclick = none and the condition to be true so the myFunction(this). In other word to make the image clickable to get viewed under, but this is not working.
Sorry for my bad explanation,check the code and you will get it fast.
I just want to be able to activate the clicking on the image when a condition is true.
function myFunction(imgs) {
var expandImg = document.getElementById("expandedImg");
var imgText = document.getElementById("imgtext");
expandImg.src = imgs.src;
imgText.innerHTML = imgs.alt;
expandImg.parentElement.style.display = "block";
}
var mytextvar= document.getElementById("mytext").textContent
if(mytextvar == "keyboard"){
document.getElementById("mytext").onclick = "myFunction(this);"
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Arial;
}
/* The grid: Four equal columns that floats next to each other */
.column {
float: left;
width: 25%;
padding: 10px;
}
/* Style the images inside the grid */
.column img {
opacity: 0.8;
cursor: pointer;
}
.column img:hover {
opacity: 1;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* The expanding image container */
.container {
position: relative;
display: none;
}
/* Expanding image text */
#imgtext {
position: absolute;
bottom: 15px;
left: 15px;
color: white;
font-size: 20px;
}
/* Closable button inside the expanded image */
.closebtn {
position: absolute;
top: 10px;
right: 15px;
color: white;
font-size: 35px;
cursor: pointer;
}
<!-- The four columns -->
<p id="mytext">keyboard</p>
<div class="row">
<div class="column">
<img src="https://picsum.photos/200" alt="Nature" style="width:100%" onclick="myFunction(this);">
</div>
<div class="column">
<img src="https://picsum.photos/201" alt="Snow" style="width:100%" onclick="">
</div>
<div class="column">
<img src="https://picsum.photos/202" alt="Mountains" style="width:100%" onclick="myFunction(this);">
</div>
<div class="column">
<img src="https://picsum.photos/204" alt="Lights" style="width:100%" onclick="myFunction(this);">
</div>
</div>
<div class="container">
<span onclick="this.parentElement.style.display='none'" class="closebtn">×</span>
<img id="expandedImg" style="width:100%">
<div id="imgtext"></div>
</div>
function showImage(sourceImg) {
var expandImg = document.getElementById("expandedImg");
var imgText = document.getElementById("imgtext");
expandImg.src = sourceImg.src;
imgText.innerHTML = sourceImg.alt;
expandImg.parentElement.style.display = "block";
}
var imgs = document.querySelectorAll(".img-cls");
imgs.forEach((img) => {
img.addEventListener('click', function(event) {
checkStatus(this);
});
});
function doImgAction(source, type) {
if (source.classList.contains(type)) {
showImage(source);
} else {
alert("You don't have enough credits to perform this action!");
}
}
function checkStatus(source) {
var mytextvar = document.getElementById("mytext");
var myText = mytextvar.textContent.toLowerCase();
switch (myText) {
case "sliver":
{
doImgAction(source, 'sliver');
break;
}
case "gold":
{
doImgAction(source, 'gold');
break;
}
case "diamond":
{
doImgAction(source, 'diamond');
break;
}
default:
{
return;
}
}
}
You are using a conditional for adding an onclick event:
if(mytextvar == "keyboard"){
document.getElementById("mytext").onclick = "myFunction(this);"
}
However, when the condition mytextvar == "keyboard" is true, the event will be added and then it would never be deactivated, because you never deactivate it in the code.
What you can do is to move the conditional inside the function, so js would check the conditional every time an image is clicked, and then the code would be executed or not depending on the condition
function myFunction(imgs) {
var mytextvar= document.getElementById("mytext").textContent
// If condition is false, return of the function
if(mytextvar != "keyboard")
return;
var expandImg = document.getElementById("expandedImg");
var imgText = document.getElementById("imgtext");
expandImg.src = imgs.src;
imgText.innerHTML = imgs.alt;
expandImg.parentElement.style.display = "block";
}
document.getElementById("mytext").onclick = "myFunction(this);"
Note: the event would always be executed, but you return early if the condition is false
i am trying to find a solution on how i can execute my script when div appears, in this particular case i have a div that is section counter and i want when this div appears to start counting my stats (that is my script) and i don't know how to do that.
This is my section counter:
/**********************
Section Counter
**********************/
.section-counter{
height: 380px;
background-image: url('../imgAboutGuitars/section-counter-bg.jpg');
/* Center and scale the image nicely */
background-position: center;
background-repeat: no-repeat;
background-size: cover;
background-attachment: fixed;
}
.overlay{
width: 100%;
height: 380px;
position: absolute;
background-color: #000;
opacity: .5;
}
.icon-container{
width: 80px;
height: 80px;
margin: 0 auto;
position: relative;
margin-bottom: 20px;
z-index: 0;
}
.icon-container:before {
content: '';
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
transition: 0.5s ease;
border: 2px solid #c49b63;
}
.icon-container:hover:before {
transform: rotate(135deg);
background: #fff;
}
.box i{
font-size: 40px;
color: #c49b63;
margin-top: 20px;
position: relative;
}
.icon-container:hover i{
color: #000;
}
.counter-box {
display: block;
position:relative;
margin-top: 20px;
padding-top: 1em;
}
.counter {
display: block;
font-size: 32px;
font-weight: 700;
color: #c49b63;
line-height: 28px
}
.counter-box span {
color: #bfbfbf;
font-size: 18px;
font-weight: 500;
margin-top: 0.5em;
display: block;
}
<!-- Section Counter -->
<div class="overlay"></div>
<div class="container-fluid section-counter">
<div class="row justify-content-center h-100">
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-4 col-4 my-auto box text-center">
<div class="icon-container">
<i class="fa fa-thumbs-o-up"></i>
<div class="counter-box">
<strong class="counter counterHappy">0</strong>
<span>Happy Customers</span>
</div>
</div>
</div>
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-4 col-4 my-auto box text-center">
<div class="icon-container">
<i class="fa fa-check"></i>
<div class="counter-box">
<strong class="counter counterConstructed">0</strong>
<span>Basses Guitars</span>
</div>
</div>
</div>
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-4 col-4 my-auto box text-center">
<div class="icon-container">
<i class="fa fa-shopping-cart"></i>
<div class="counter-box">
<strong class="counter counterOrders">0</strong>
<span>Orders</span>
</div>
</div>
</div>
</div>
</div>
As you can see the stats is zero for every icon, the script for counting is below here:
// getting the products
class countProducts{
async fetchProducts(){
try{
var result = await fetch('./json/products.json')
var data = await result.json();
var products = data.items;
return products;
}catch (error){
console.log('error');
}
}
}
class uiCount{
getProducts(products){
this.countDisplay(products);
}
countDisplay(products){
//Speed of Counter
const speed = 200;
//Varible for type of Guitar
var typeGuitar = document.querySelector('.wallpaper_text').innerText;
//Array for every type of Guitar
var arrayOfElectrical = 0;
var arrayOfAcoustic = 0;
var arrayOfBasses = 0;
const counterGuitars = document.querySelectorAll('.counterConstructed');
for(var i=0;i < products.length;i++){
//Count if Type is Electrical
if(typeGuitar == "Electrical Type"){
if(products[i].type == "Electrical"){
arrayOfElectrical++;
}
//Second Column of Section Counter
counterGuitars.forEach((counter)=>{
counter.innerText = '0';
const updateCounter = () =>{
const target = arrayOfElectrical;
const count = +counter.innerText;
const increment = target / 200;
if(count < target){
counter.innerText = `${Math.ceil(count + increment)}`;
setTimeout(updateCounter,1);
}else{
counter.innerText = target;
}
};
updateCounter();
});
}
//Count if Type is Acoustic
else if(typeGuitar == "Acoustic Type"){
if(products[i].type == "Acoustics"){
arrayOfAcoustic++;
}
//Second Column of Section Counter
counterGuitars.forEach((counter)=>{
counter.innerText = '0';
const updateCounter = () =>{
const target = arrayOfAcoustic;
const count = +counter.innerText;
const increment = target / 200;
if(count < target){
counter.innerText = `${Math.ceil(count + increment)}`;
setTimeout(updateCounter,1);
}else{
counter.innerText = target;
}
};
updateCounter();
});
}
//Count if Type is Basses
else if(typeGuitar == "Basses Type"){
if(products[i].type == "Basses"){
arrayOfBasses++;
}
//Second Column of Section Counter
counterGuitars.forEach((counter)=>{
counter.innerText = '0';
const updateCounter = () =>{
const target = arrayOfBasses;
const count = +counter.innerText;
const increment = target / 200;
if(count < target){
counter.innerText = `${Math.ceil(count + increment)}`;
setTimeout(updateCounter,1);
}else{
counter.innerText = target;
}
};
updateCounter();
});
}
}
//First Column of Section Counter
const counterHappy = document.querySelectorAll('.counterHappy');
counterHappy.forEach((counter)=>{
counter.innerText = '0';
const updateCounter = () =>{
const target = 3800;
const count = +counter.innerText;
const increment = target / 200;
if(count < target){
counter.innerText = `${Math.ceil(count + increment)}`;
setTimeout(updateCounter,1);
}else{
counter.innerText = target;
}
};
updateCounter();
});
//Third Column of Section Counter
const counterOrders = document.querySelectorAll('.counterOrders');
counterOrders.forEach((counter)=>{
counter.innerText = '0';
const updateCounter = () =>{
const target = 7500;
const count = +counter.innerText;
const increment = target / 200;
if(count < target){
counter.innerText = `${Math.ceil(count + increment)}`;
setTimeout(updateCounter,1);
}else{
counter.innerText = target;
}
};
updateCounter();
});
}
}
//saving the products
class saveCountProducts{
static saveProducts(products){
return products;
}
}
document.addEventListener('DOMContentLoaded', () => {
const products = new countProducts();
const ui = new uiCount();
const storage = new saveCountProducts();
products.fetchProducts();
products.fetchProducts().then(products => {
saveCountProducts.saveProducts(products);
ui.getProducts(products);
});
})
Therefore, when page loads the section starts counting as a result when the user reaches on section counter the stats have already counted, so i want when the user reach on this div then and only stats would start counting.
PS: Sorry in advance for my english, if you have any question i will appreciate it if you express it!
I used javascript to drag&drop multi files. than I am showing those images. Below is fully runable with no errors
Need help with: I want ability to remove those image as well. Please take a look at attached image below, I want to create [x] buttons at top right on image. if click on [x] than it will remove image depending on which [x] you click. close is in drop function below
below is my javascript so far. need help in drop function
var dropZone = document.getElementById('dropZone');
var details = document.querySelector('#imgDetail');
///////////
// dragover
///////////
dropZone.addEventListener('dragover', function (e) {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
document.getElementById('dropZone').classList.add("hoverActive");
});
/////////////
//drag leave
/////////////
dropZone.addEventListener('dragleave', function (e) {
document.getElementById('dropZone').classList.remove("hoverActive");
});
////////////
// drop file
////////////
dropZone.addEventListener('drop', (e) => {
document.getElementById('dropZone').classList.remove("hoverActive");
document.getElementById('BackgroundText').style.visibility = "hidden";
e.stopPropagation();
e.preventDefault();
details.innerHTML = '';
var files = e.dataTransfer.files;
Object.values(files).forEach((file) => {
var reader = new FileReader();
reader.onloadend = () => {
//display image
var img = document.createElement('img');
img.src = reader.result;
img.style.paddingRight = 5;
img.width = 150;
img.height = 150;
img.border = 2;
var div = document.getElementById('imageHold')
div.appendChild(img);
//create button
div.innerHTML += '<button id="btn" name="btn">X</button>';
//display file name
details.innerHTML += `<p>Name: ${file.name}<p>';
//details.innerHTML += <p>Size: ${bytesToSize(file.size)}</p>`;
};
reader.readAsDataURL(file);
});
});
function bytesToSize(bytes) {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes == 0) return '0 Byte';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}
#dropZone
{
border: 2px dashed gray;
height: 200px;
width: auto;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
#dropZone header{
font-size: 20px;
font-weight:bold;
}
.hoverActive{
border: 2px dashed darkred !important;
}
<br /><br />
<div class="container">
<div class="row">
<div>
<div id="dropZone">
<div class="icon"><i class="fas fa-cloud-upload-alt"></i></div>
<header id="BackgroundText">Drag & Drop to Upload File</header>
<div id="imageHold" style="float:left;">
</div>
</div>
</div>
</div>
</div>
<div id="imgDetail">test</div>
html code
var dropZone = document.getElementById('dropZone');
var details = document.querySelector('#imgDetail');
///////////
// dragover
///////////
dropZone.addEventListener('dragover', function (e) {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = 'copy';
document.getElementById('dropZone').classList.add("hoverActive");
});
/////////////
//drag leave
/////////////
dropZone.addEventListener('dragleave', function (e) {
document.getElementById('dropZone').classList.remove("hoverActive");
});
////////////
// drop file
////////////
dropZone.addEventListener('drop', (e) => {
document.getElementById('dropZone').classList.remove("hoverActive");
document.getElementById('BackgroundText').style.visibility = "hidden";
e.stopPropagation();
e.preventDefault();
details.innerHTML = '';
var files = e.dataTransfer.files;
Object.values(files).forEach((file) => {
var reader = new FileReader();
reader.onloadend = () => {
//create frame elem section
let dv = document.createElement('div');
dv.style.cssText = `
display: inline-block;
position: relative;
width: 150px;
height: 150px;
border: 1px #ddd solid;
margin-right: 5px;
`;
//create image elem
var img = document.createElement('img');
img.src = reader.result;
// optional 100%
// img.style.width = "100%";
img.style.width = "150px";
img.style.height= "150px";
//add img to frame
dv.append(img);
//create btn remove
let btn = document.createElement('button');
btn.innerHTML = "x";
btn.style.cssText = `
position: absolute;
right: 2px;
top:2px;
`;
//add btn to frame
dv.append(btn);
//set frame to target elem
document.getElementById('imageHold').append(dv);
//set event btn and exec remove frame
btn.addEventListener('click', e => {
e.target.parentElement.remove();
});
//display file name
details.innerHTML += `<p>Name: ${file.name}<p>';
//details.innerHTML += <p>Size: ${bytesToSize(file.size)}</p>`;
};
reader.readAsDataURL(file);
});
});
function bytesToSize(bytes) {
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
if (bytes == 0) return '0 Byte';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}
#dropZone
{
border: 2px dashed gray;
height: 200px;
width: auto;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
#dropZone header{
font-size: 20px;
font-weight:bold;
}
.hoverActive{
border: 2px dashed darkred !important;
}
<br /><br />
<div class="container">
<div class="row">
<div>
<div id="dropZone">
<div class="icon"><i class="fas fa-cloud-upload-alt"></i></div>
<header id="BackgroundText">Drag & Drop to Upload File</header>
<div id="imageHold" style="float:left;">
</div>
</div>
</div>
</div>
</div>
<div id="imgDetail">test</div>
Demo Page
HTML:
div.innerHTML += '<button id="btn" name="btn" onclick=removeImage_and_btn(this)>X</button>';
You could use previousSibling to get the previous element
JS:
function removeImage_and_btn(el){
if(!el.previousSibling.tagName){//if it is textnode like newline etc. we go one back
var el = el.previousSibling;
}
if(el.previousSibling.tagName && el.previousSibling.tagName=='IMG'){
el.previousSibling.remove();
el.remove();
}
}
This jQuery toggle() function is working great. What is good practice for doing the same in vanilla javascript (ES6 preferred)?
$("#sign_up_btn").click(function(e) {
$(signUpForm).toggle("hide");
$(loginForm).toggle("hide");
});
$("#login_btn").click(function(e) {
$(signUpForm).toggle("hide");
$(loginForm).toggle("hide");
});
Native Toggle
Class can be toggled natively via Element.classList.toggle:
const button = document.querySelector('#sign_up_btn');
button.addEventListener('click', e => {
document.querySelector('.content').classList.toggle('hide')
})
.hide {
display: none;
}
<button id="sign_up_btn">toggle</button>
<div class="content">Toggle this content</div>
You can do something like this:
Note: the CSS is just so we can test here.
document.getElementById('sign_up_btn').addEventListener('click', () => {
var signUpForm = document.getElementById('signUpForm');
var loginForm = document.getElementById('loginForm');
if(window.getComputedStyle(signUpForm).display === "block") {
signUpForm.style.display = "none";
loginForm.style.display = "block";
} else {
signUpForm.style.display = "block";
loginForm.style.display = "none";
}
});
#signUpForm {
position: relative;
float: left;
background-color: #09f;
width: 100px;
height: 100px;
display: block;
margin-right: 20px;
}
#loginForm {
position: relative;
float: left;
background-color: #f00;
width: 100px;
height: 100px;
display: none;
}
#sign_up_btn {
position: relative;
float: left;
margin-right: 20px;
}
<input type="button" id="sign_up_btn" value="Sign up" />
<div id="signUpForm">Sign up form</div>
<div id="loginForm">Log in form</div>
You can do this way.
var show = function (elem) {
elem.style.display = 'block';
};
var hide = function (elem) {
elem.style.display = 'none';
};
var toggle = function (elem) {
// If the element is visible, hide it
if (window.getComputedStyle(elem).display === 'block') {
hide(elem);
return;
}
// Otherwise, show it
show(elem);
};
// Listen for click events
document.addEventListener('click', function (event) {
// Make sure clicked element is our toggle
if (!event.target.classList.contains('toggle')) return;
// Prevent default link behavior
event.preventDefault();
// Get the content
var content = document.querySelector(event.target.hash);
if (!content) return;
// Toggle the content
toggle(content);
}, false);
<p>
<a class="toggle" href="#example">Toggle Div</a>
</p>
<div class="toggle-content" id="example">
Here's some text we want to toggle visibility of. Let's do it!
</div>
If signUpForm and loginForm are ids then you can try the following:
document.getElementById('sign_up_btn').addEventListener('click', function(){
elToggle();
});
document.getElementById('login_btn').addEventListener('click', function(){
elToggle();
});
function elToggle(){
var s = document.getElementById('signUpForm');
if (s.style.display == "none") {
s.style.display = "block";
} else {
s.style.display = "none";
}
var l = document.getElementById('loginForm');
if (l.style.display == "none") {
l.style.display = "block";
} else {
l.style.display = "none";
}
}
What I'm trying to accomplish is a java readmore/readless content toggle function that disable other content when one content's onclick triggers. I'm using getElementsByClassName, setTimeout, and transition.
The problem I'm having is that display: none is not responding to setTimeout. Any suggestion outside of javascript is welcome too.
Here is the Javascript:
function toggle(cont, tog, id) {
for (var i = 0; i < cont.length; i++) {
if (tog[id].innerHTML != "Click Here to Read Less!") {
/* Toggle On */
tog[id].innerHTML = "Click Here to Read Less!";
cont[id].style.height = "250px";
/* Disable other */
setTimeout(function () { cont[i].style.display = "none" }, 500);
setTimeout(function () { tog[i].style.display = "none" }, 500);
for (var x = 0; x < cont.length; x++) {
cont[x].style.opacity = "0";
tog[x].style.opacity = "0";
setTimeout(function () { cont[x].style.display = "none" }, 500);
setTimeout(function () { tog[x].style.display = "none" }, 500);
if (cont[id] == cont[x]) {
cont[id].style.opacity = "1";
tog[id].style.opacity = "1";
}
}
} else {
/* Toggle Off */
tog[id].innerHTML = "Click Here to Read More!";
cont[id].style.height = "100px";
/* Enable other */
for (var x = 0; x < cont.length; x++) {
cont[x].style.opacity = "1";
tog[x].style.opacity = "1";
cont[x].style.display = "block";
tog[x].style.display = "block";
}
}
}
}
Here is my HTML:
<div class="content">
<p>
Content Here!
</p>
</div>
Click Here to Read More!
<div class="content">
<p>
Content Here!
</p>
</div>
Click Here to Read More!
<div class="content">
<p>
Content Here!
</p>
</div>
Click Here to Read More!
And CSS for formatting sake:
/* Centering Content */
#wrapper {
margin: 0 auto;
height: auto;
width: 70%;
text-align: center;
font-family: Sans-Serif, Calibri;
}
/* Styling Content */
.content {
padding: 25px 50px;
margin: 0 auto;
height: 100px;
width: 500px;
display: block;
text-align: left;
overflow: hidden;
-webkit-transition: all 0.5s;
transition: all 0.5s;
}