I have a relatively simple demo here where I have two embed elements with the same class, and upon page load one is set to display and the other is not. I'm calling a function and setting an interval for every 5 seconds starting on page load which should toggle the display rules for the classes (only one embed element should show at a time and then they should alternate on the timer).
I have border colors on the embed elements for testing, but it seems like neither element is showing on page load once I added the second 'if' statement in the JS
What am I doing wrong
window.onload = function () {
test();
setInterval(function() {
test();
}, 5000);
}
function test(){
console.log('starting');
var all = document.getElementsByClassName('pdfEmbed');
for (var i = 0; i < all.length; i++) {
if(all[i].style.display = "none"){
all[i].style.display = "block";
}
if(all[i].style.display="block"){
all[i].style.display = "none";
}
}
}
<embed class="pdfEmbed" src="#" style="margin-top: 40px;position:absolute; display: block; left: 0; top: 0; border: 1px solid red;" width="100%" height="100%" type="application/pdf">
<embed class="pdfEmbed" src="#" style="margin-top: 40px;position:absolute; border: 1px solid black; display: none; left: 0; top: 0;" width="100%" height="100%" type="application/pdf">
Here's what's happening with the second if:
// set current child display to "block" if it is "none"
if(all[i].style.display = "none"){
all[i].style.display = "block";
}
// the check is always true, since you just set the display to "block"
if(all[i].style.display="block"){
// therefore, for all elements set display to none
all[i].style.display = "none";
}
The fix is easy: Use an else if instead of the second if. In case you only want to have the two display states "none" and "block", an else is enough.
EDIT: I just noticed a second error. You have to use comparison (== or ===) instead of assignment (=) in your if conditions. So this should be working:
if(all[i].style.display == "none") {
all[i].style.display = "block";
} else {
all[i].style.display = "none";
}
var last_index = 0;
function test() {
var e = document.querySelectorAll(".pdfEmbed");
for (var k = 0; k < e.length; k++) {
e[k].style.display = k == last_index ? "block" : "none";
}
last_index++;
if (last_index >= e.length) { last_index = 0; }
}
Related
I am trying to make a toggle button on a website that I am making that activates a javascript navbar when pressed then when pressed a second time the navbar retracts out of sight. I have got the code working to where the navbar pops out when the button is pressed but I can't work out how to make the navbar retract.
function tog() {
var x = 0;
if (x == 0) {
document.getElementById("Sidenav").style.height = "450px";
document.getElementById("main").style.marginTop = "0px";
document.body.style.backgroundColor = "rgba(0,0,0,1)";
x = 1;
}
else {
document.getElementById("Sidenav").style.height = "0";
document.getElementById("main").style.marginTop= "0";
document.body.style.backgroundColor = "white";
x = 0;
}
};
This is the javascript that controls the toggle function, and the button is:
<div class="panel"><button class='pan' onclick='tog()'></button></div>
Any input as to where I am going wrong would be much appreciated.
Try this, the logic is: x equals 0 ? then x = 1 else x = 0.
var x = 0;
function tog() {
x = x == 0 ? 1 : 0;
if (x == 0) {
console.log(x)
} else if(x == 1){
console.log(x)
}
};
<div class="panel"><button class='pan' onclick='tog()'>Toggle!</button></div>
You could do something like this.
var x = 0;
function toggle() {
if (x === 0) {
document.getElementById("Sidenav").style.height = "150px";
document.body.style.backgroundColor = "rgba(0,0,0,1)";
x = 1;
} else {
document.getElementById("Sidenav").style.height = "0";
document.body.style.backgroundColor = "white";
x = 0;
}
};
#Sidenav {
width: 400px;
border: 1px solid #9c0000;
border-radius: 10px;
height: 0;
}
<div id="Sidenav"></div>
<button onclick="toggle()">toggle</button>
let sideNav = document.getElementById("Sidenav");
function toggle(){
sideNav.classList.toggle("open");
document.body.classList.toggle("open-bg");
}
.open{
height: 450px;
}
.open-bg{
background-color: rgba(0, 0, 0, 1);
}
make use of toggle method for classList to remove and add class alternately when button is clicked.
and try not to change css attributes too much in JavaScript. I mean it's not bad but it makes your code look kinda big.
My goal is to make a script click continuously on this two button without need to call it manually, my script have the ability to click on the button, but I don't know
how to automate the action, what I'm trying to do is keeping clicking with no number limit of clicks.
The script I used to click on the button
let buttonTags = document.getElementsByTagName("button");
let followButton = "Follow";
let unFollowButton = "Unfollow";
let found;
for (let i = 0; i < buttonTags.length; i++) {
if (buttonTags[i].textContent == followButton || unFollowButton) {
found = buttonTags[i];
break;
}
}
found.click()
This is the test, I used two divs intentionally.
HTML
<div id="hidde">
<button onclick="myFunction()">Follow</button>
</div>
<div id="hidden">
<button onclick="myFunction()">Unfollow</button>
</div>
CSS
body{
display: flex;
}
div{
border: #000 solid 1px;
padding: 20px;
}
#hidden {
display: none;
}
Javascript
function myFunction() {
let y = document.getElementById("hidde");
let x = document.getElementById("hidden");
if (x.style.display === "none") {
x.style.display = "block";
y.style.display = "none";
} else {
x.style.display = "none";
y.style.display = "block";
}
}
You can programatically trigger a click with .click()
https://www.w3schools.com/jsref/met_html_click.asp
But also your use case perfectly suits a Do/While loop :)
I am creating a simple image slide with JavaScript, but when I loop through all the images, I can not reset the loop:
var images = document.querySelectorAll(".slide-img");
var index = 0;
var time = 1000;
function reset(){
for(var i = 0; i <= 3; i++){
images[i].style.display = 'none';
images[0].style.display = 'block';
}
}
reset();
var looper = setInterval(function(){
index++;
images[index].style.display = 'block';
if(index == 3){
index = 0;
images[index].style.display = 'block';
//or calling reset() again.
}
}, 1000);
After setting all the image display:noneexcept the first one, I tried calling setInterval for looping all my images, but problem occurs when the index is 3. I am calling the reset() function and it is not working?
Your code has a few problems.
The code inside the if statement doesn't reset all the images to hidden. So you would need to call reset function instead
Your reset function doesn't reset the index.
You should set index 0 to block once, and then loop through the rest instead of setting index 0 to block in each iteration.
Because you reset when index == 3, you will never see the last image. You should reset on the following iteration to ensure that each image is visible for one second.
See my example below.
var images = document.querySelectorAll(".slide-img");
var index = 0;
var time = 1000;
function reset(){
index = 0;
images[0].style.display = 'block';
for(var i = 1; i < images.length; i++){
images[i].style.display = 'none';
}
}
reset();
setInterval(function(){
index++;
if(index >= images.length){
reset();
} else {
images[index].style.display = 'block';
}
}, 1000);
.container {
display: flex;
}
.slide-img {
width: 100px;
height: 100px;
}
<div class="container">
<div class="slide-img" style="background: red"></div>
<div class="slide-img" style="background: blue"></div>
<div class="slide-img" style="background: green"></div>
<div class="slide-img" style="background: purple"></div>
</div>
If you have other question on why my code is different than yours, ask in the comments. But I think the code should be clear and understandable.
I am trying to do include 3 images on my page. These images must have the following behavior done: When an unbordered image is clicked, it gets a border on it. When a bordered imaged is clicked, the border gets removed. In other words the border gets toggled on & off every time it is clicked, for that image.
I can get the border on when clicked, but I can not figure out how to remove it again.
This is what I have for JS so far:
ims = document.getElementsByTagName("img");
for( i=0 ; i<ims.length ; i++ ){
ims[i].onclick=function(){
this.style.borderStyle = "solid";
this.style.borderColor = "red";
}
}
You could check the style:
ims[i].onclick=function() {
if (this.style.borderStyle == "solid") {
this.style.borderStyle = "none";
} else {
this.style.borderStyle = "solid";
this.style.borderColor = "red";
}
}
JSFiddle
Here you have a solution based on Doorknob, but with classes, as I recommended on the comment:
var ims = document.getElementsByTagName("img");
for( var i=0 ; i<ims.length ; i++ ){
ims[i].onclick=function() {
if (this.className == "clicked") {
this.className = "";
} else {
this.className = "clicked";
}
};
}
And the css classes:
img {
padding: 5px;
}
img.clicked {
padding: 0;
border: 5px solid red;
}
Here you can see the benefits of using classes.
Here is the jsFiddle.
For further investigation I would recommend to check how to do it if the img tag has multiple classes ;). Ask again if you have any doubts.
I am trying to make a chessboard using javascript and creating 64 divs with it.
The problem is, that it creates only the first div.
Here is the code:
div {
width: 50px;
height: 50px;
display: block;
position: relative;
float: left;
}
<script type="text/javascript">
window.onload=function()
{
var i=0;
var j=0;
var d=document.createElement("div");
for (i=1; i<=8; i++)
{
for (j=1; j<=8; j++)
{
if ((i%2!=0 && j%2==0)||(i%2==0 && j%2!=0))
{
document.body.appendChild(d);
d.className="black";
}
else
{
document.body.appendChild(d);
d.className="white";
}
}
}
}
</script>
As t-j-crowder has noted, the OP's code only creates one div. But, for googlers, there is one way to append multiple elements with a single appendChild in the DOM: by creating a documentFragment.
function createDiv(text) {
var div = document.createElement("div");
div.appendChild(document.createTextNode(text));
return div;
}
var divs = [
createDiv("foo"),
createDiv("bar"),
createDiv("baz")
];
var docFrag = document.createDocumentFragment();
for(var i = 0; i < divs.length; i++) {
docFrag.appendChild(divs[i]); // Note that this does NOT go to the DOM
}
document.body.appendChild(docFrag); // Appends all divs at once
The problem is, that it creates only the first div.
Right, because you've only created one div. If you want to create more than one, you must call createElement more than once. Move your
d=document.createElement("div");
line into the j loop.
If you call appendChild passing in an element that's already in the DOM, it's moved, not copied.
window.onload=function()
{
var i=0;
var j=0;
for (i=1; i<=8; i++)
{
for (j=1; j<=8; j++)
{
if ((i%2!=0 && j%2==0)||(i%2==0 && j%2!=0))
{
var d=document.createElement("div");
document.body.appendChild(d);
d.className="black";
}
else
{
var d=document.createElement("div");
document.body.appendChild(d);
d.className="white";
}
}
}
}
Although what T.J. Crowder writes works fine, I would recommend rewriting it to the code below, using a documentFragment, like Renato Zannon suggested. That way you will only write to the DOM once.
window.onload = function() {
var count = 5,
div,
board = document.getElementById('board'),
fragment = document.createDocumentFragment();
// rows
for (var i = 0; i < count; ++i) {
// columns
for (var j = 0; j < count; ++j) {
div = document.createElement('div');
div.className = (i % 2 != 0 && j % 2 == 0) || (i % 2 == 0 && j % 2 != 0) ? 'black' : 'white';
fragment.appendChild(div);
}
}
board.appendChild(fragment);
};
#board {
background-color: #ccc;
height: 510px;
padding: 1px;
width: 510px;
}
.black,
.white {
float: left;
height: 100px;
margin: 1px;
width: 100px;
}
.black {
background-color: #333;
}
.white {
background-color: #efefef;
}
<div id="board"></div>
function crt_dv(){
dv=document.createElement('div'),document.body.appendChild(dv)
};
crt_dv(),dv.className='white';crt_dv(),dv.className='black';
Also use: for(i=0;i<2;i++)