Im trying to create a Javascript carousel that displays a random div and changes every 3 seconds.
I have the random div displaying on load but unsure what to add make it change to the next one.
var elems = $("div");
if (elems.length) {
var keep = Math.floor(Math.random() * elems.length);
for (var i = 0; i < elems.length; ++i) {
if (i !== keep) {
$(elems[i]).hide();
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="content1">This is content 1</div>
<div id="content2">This is content 2</div>
<div id="content3">This is content 3</div>
<div id="content4">This is content 4</div>
<div id="content5">This is content 5</div>
<div id="content6">This is content 6</div>
put your code in an interval like this :
setInterval(function(){
var elems = $("div");
if (elems.length) {
var keep = Math.floor(Math.random() * elems.length);
for (var i = 0; i < elems.length; ++i) {
if (i !== keep) {
$(elems[i]).hide();
}
else{
$(elems[i]).show();
}
}
}
},1000); // change every 1s ;
================================
UPDATE
to hide all divs before interval starts u have two way .
first way is to use css . u can add a css class to divs named "hide-at-start" and define it like this :
.hide-at-start
{
display:none;
}
and add it to divs :
<div id="content1" class="hide-at-start">This is content 1</div>
<div id="content2" class="hide-at-start">This is content 2</div>
<div id="content3" class="hide-at-start">This is content 3</div>
<div id="content4" class="hide-at-start">This is content 4</div>
<div id="content5" class="hide-at-start">This is content 5</div>
<div id="content6" class="hide-at-start">This is content 6</div>
second way is to do it via javascript like this :
function showRandomDiv(){
var elems = $("div");
if (elems.length) {
var keep = Math.floor(Math.random() * elems.length);
for (var i = 0; i < elems.length; ++i) {
if (i !== keep) {
$(elems[i]).hide();
}
else{
$(elems[i]).show();
}
}
}
}
showRandomDiv(); // runs once
setInterval(showRandomDiv,1000); // change every 1s ;
i prefer the first solution however .
========================
UPDATE
to add animations there are many ways . for instance u can use css #keyframes like this :
#keyframes fade-in-from-left {
0% {left: 0px;opacity: 0;}
50% {left: 20px;opacity: 0.5;}
100%{left:0px;opacity: 1;}
}
.fade-in-from-left{
position: relative;
animation: fade-in-from-left 0.5s forwards;
}
then add fade-in-from-left to your divs like this :
<div class="hide-at-start fade-in-from-left">This is content 1</div>
<div class="hide-at-start fade-in-from-left">This is content 2</div>
<div class="hide-at-start fade-in-from-left">This is content 3</div>
<div class="hide-at-start fade-in-from-left">This is content 4</div>
<div class="hide-at-start fade-in-from-left">This is content 5</div>
<div class="hide-at-start fade-in-from-left">This is content 6</div>
Related
I am using two types of elements, .element and .summary. The index of both classes correspond to each other, so when a user has a mouseover event on .element, a class should be added to its corresponding .summary. Similarly, that same class should be removed on mouseout.
In other words, I'm looking to have the .styling class only applied to .summary when .element is on mouseover
Without declaring so many variables, I was wondering the most efficient way to loop through these elements.
var abc = document.getElementsByClassName("element");
var xyz = document.getElementsByClassName("summary");
for (let i = 1; i < xyz.length; i++) {
abc[i].addEventListener("mouseover", movein(i), false);
abc[i].addEventListener("mouseout", moveout(i), false);
}
function movein(i) {
xyz[i].classList.add("styling");
}
function moveout(i) {
xyz[i].classList.remove("styling");
}
.element {
cursor: pointer;
}
.styling {
background: red;
}
<div class="element">Element 1</div>
<div class="element">Element 2</div>
<div class="element">Element 3</div>
<div class="summary">Summary 1</div>
<div class="summary">Summary 2</div>
<div class="summary">Summary 3</div>
From what I can tell, these functions run but it doesn't work on mouseover.
You don't actually have to loop, in fact it's probably best you don't. If you have containers for each section of your HTML: elements, and summaries, it's much more efficient to use event delegation to catch element events as they bubble up the DOM, and use one handler to decide how to style your summaries depending on their data attributes.
// Cache the containers
const elements = document.querySelector('#elements');
const summaries = document.querySelector('#summaries');
// Add listeners to the containers
elements.addEventListener('mouseover', handleMouse, false);
elements.addEventListener('mouseout', handleMouse, false);
function handleMouse(e) {
// Destructure the type and id from the element
const { type, target: { dataset: { id } } } = e;
// Find the corresponding summary - this uses
// a template literal to create the query
const summary = summaries.querySelector(`[data-id="${id}"]`);
// And then, depending on the event type, add or remove the style
if (type === 'mouseover') {
summary.classList.add("styling");
} else {
summary.classList.remove("styling");
}
}
.element { cursor: pointer; }
.styling { background: red; }
<div id="elements">
<div data-id="1" class="element">Element 1</div>
<div data-id="2" class="element">Element 2</div>
<div data-id="3" class="element">Element 3</div>
</div>
<div id="summaries">
<div data-id="1" class="summary">Summary 1</div>
<div data-id="2" class="summary">Summary 2</div>
<div data-id="3" class="summary">Summary 3</div>
</div>
Additional documentation
Destructuring assignment
Template literals
Data attributes
Fixing your code to just refer to the functions (not call them) in addEventListener, to loop starting at 0 (not 1), and to use ids to get the corresponding elements...
There's nothing wrong with a short loop.
var abc = document.getElementsByClassName("element");
var xyz = document.getElementsByClassName("summary");
// fixed, was i=1
for (let i = 0; i < xyz.length; i++) {
// fixed, was movein(i), moveout(i)
abc[i].addEventListener("mouseover", movein, false);
abc[i].addEventListener("mouseout", moveout, false);
}
// these get events as params, and can use the event.target.id
// to distinguish which element was triggered
function movein(event) {
let id = event.target.id
xyz[id].classList.add("styling");
}
function moveout(event) {
let id = event.target.id
xyz[id].classList.remove("styling");
}
.element {
cursor: pointer;
}
.styling {
background: red;
}
<div class="element" id="0">Element 1</div>
<div class="element" id="1">Element 2</div>
<div class="element" id="2">Element 3</div>
<div class="summary">Summary 1</div>
<div class="summary">Summary 2</div>
<div class="summary">Summary 3</div>
You could do it like this, and not have to update your html. We programmatically set up an attribute so we can get it's index when we mouse over it. Then we use that index to find the associated summary. Note that you don't pass the i through the event listener - you test for the event.target and pick up that shiny new attribute with event.target.dataset per the code below.
Another bonus here is that we've combined the event listener logic which you can see makes sense. This answer leverages your existing structure, uses less code and is easy to understand.
var abc = document.getElementsByClassName("element");
var xyz = document.getElementsByClassName("summary");
for (let i = 0; i < xyz.length; i++) {
abc[i].setAttribute('data-index', i)
abc[i].addEventListener("mouseover", mousemove);
abc[i].addEventListener("mouseout", mousemove);
}
function mousemove(event) {
let element = xyz[event.target.dataset.index];
if (event.type == 'mouseover') element.classList.add("styling");
else element.classList.remove("styling");
}
.element {
cursor: pointer;
}
.styling {
background: red;
}
<div class="element">Element 1</div>
<div class="element">Element 2</div>
<div class="element">Element 3</div>
<div class="summary">Summary 1</div>
<div class="summary">Summary 2</div>
<div class="summary">Summary 3</div>
I have a slider that shows rotate slides on desktop with swipper slider,
I destroy the slider on mobile and would like to show 3 static slides that do not rotate with a show more button.
I added a class called hidden to all the elements except the first 3 and added a button to show more slides on click.
Now when you click on the button I would like to remove the hidden class from all the slides elements but it does not work.
Here is the HTML:
<div class="icon-slider">
<div class="swiper-container js-icon-slider">
<div class="swiper-wrapper">
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
<div class="swiper-slide">
<div class="img-wrap">image here</div>
</div>
</div>
</div>
And my JS code:
var slider = document.querySelector('.icon-slider'),
slides = slider.querySelectorAll('.swiper-slide'),
btnMore = '<div class="more-btn-wrap"><button class="wp-block-button__link">View all</button></div>';
for (let i = 2; i < slides.length; i++) {
slides[i].classList.add('hidden');
}
if (!slider.querySelector(".more-btn-wrap")) {
slider.innerHTML = slider.innerHTML + btnMore;
}
let btn = document.querySelector('.more-btn-wrap');
btn.addEventListener('click', function () {
this.remove();
slides.forEach(slide => slide.classList.remove('hidden'));
});
When I just try to put this line in the console it works as expected so I think it's something with the addEventListener
slides.forEach(slide => slide.classList.remove('hidden'));
You don't need 2 for loops, add eventlistener inside for loop and remove second for loop inside addeventlistener also remove 3 and type 0 to start loop from 0
<style type="text/css">
.slide {
width: 80px;
height: 80px;
background-color: red;
border: 2px solid blue;
}
.hidden {
opacity: 0.1;
}
</style>
<button class="btn">Button</button>
<div class="slider">
<div class="slide">Slide1</div>
<div class="slide">Slide2</div>
<div class="slide">Slide3</div>
</div>
<script>
let btn = document.querySelector('.btn');
let slider = document.querySelector('.slider');
let slides = slider.querySelectorAll('.slide');
for (let i = 0; i < slides.length; i++) {
slides[i].classList.add('hidden');
btn.addEventListener('click', function() {
slides[i].classList.remove('hidden');
});
}
</script>
Right now it cycles through 1 div per click - would it be possible to make this cycle through 4 divs with each click? Completely stumped on it...
HTML:
<div class="outside-buttons">
<div class="prev">Previous</div>
<div class="next">Next</div>
</div>
<div class="parent">
<div class="childclass">some content</div>
<div class="childclass">some content 2</div>
<div class="childclass">some content 3</div>
<div class="childclass">some content 4</div>
<div class="childclass">some content 5</div>
<div class="childclass">some content 6</div>
<div class="childclass">some content 7</div>
<div class="childclass">some content 8</div>
<div class="childclass">some content 9</div>
</div>
jQuery:
var $zDiv = $('.childclass'),
$prNx = $('.prev, .next'),
$btns = $('.zanc > a'),
n = $zDiv.length,
c = 0; // current
d = 4; //number of items
function toggView(){
// content:
$zDiv.hide().eq(c).show();
// buttons:
$prNx.show();
if(c<=0){
$('.prev').hide();
}
if(c>=n-1){
$('.next').hide();
}
}
toggView();
$prNx.click(function(){
c = $(this).hasClass('next') ? ++c : --c;
toggView();
});
$btns.click(function( e ){
c = $(this).index();
toggView();
});
fiddle: https://jsfiddle.net/g1r0ws6w/2/
To always show 4 divs next to each other you need to raise your stepsize within your click() method while displaying more than one item at the same time. I used a for-loop for this purpose.
Concluding You need to adjust the condition to display/hide the next-Button accordingly.
var $zDiv = $('.childclass'),
$prNx = $('.prev, .next'),
$btns = $('.zanc > a'),
n = $zDiv.length,
c = 0; // current
d = 4; //number of items
function toggView(){
// content:
$zDiv.hide();
for(i=0;i<d && i+c<n;i++){
$zDiv.eq(i+c).show();
}
// buttons:
$prNx.show();
if(c<=0){
$('.prev').hide();
}
if(c+3>=n-1){
$('.next').hide();
}
}
toggView();
$prNx.click(function(){
c = $(this).hasClass('next') ? c += 4 : c -= 4;
toggView();
});
$btns.click(function( e ){
c = $(this).index();
toggView();
});
This is a corresponding fiddle.
Here's a fiddle. All you needed was where you have ++c/--c you need to add/subtract your d value.
$prNx.click(function(){
c = $(this).hasClass('next') ? c += d : c -= d;
toggView();
});
You can do this
$prNx.click(function(){
c = $(this).hasClass('next') ? c+4 : c-4;
toggView();
});
I added paging for display as default number (You can set whatever number) . c and d will be your current start and end index of current offset .
var $zDiv = $('.childclass'),
$prNx = $('.prev, .next'),
$btns = $('.zanc > a'),
n = $zDiv.length,
paging = 4;
c = 0; // current
d = paging; //number of items
function toggView(){
// content:
$zDiv.hide();
for(var i = c; i < d; i++) {
$zDiv.eq(i).show();
}
// buttons:
$prNx.show();
if(c == 0){
$('.prev').hide();
}
if(c+paging >= n){
$('.next').hide();
}
}
toggView();
$prNx.click(function(){
if($(this).hasClass('next')) {
c += paging;
d += paging;
} else {
c -= paging;
d -= paging;
}
toggView();
});
.childclass {
height: 100px;
display: inline-block;
background: #e3e3e3;
margin: 10px;
}
.current { display: block; }
.childclass { clear: none !important;
display: inline-block;
white-space: nowrap;
width: 25% !Important;
float: none;
}
.parent {
overflow-x: hidden;
overflow-y: hidden;
white-space: nowrap !Important;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="outside-buttons">
<div class="prev">
Previous</div>
<div class="next">
Next</div>
</div>
<div class="parent">
<div class="childclass">
some content
</div>
<div class="childclass">
some content 2
</div>
<div class="childclass">
some content 3
</div>
<div class="childclass">
some content 4
</div>
<div class="childclass">
some content 5
</div>
<div class="childclass">
some content 6
</div>
<div class="childclass">
some content 7
</div>
<div class="childclass">
some content 8
</div>
<div class="childclass">
some content 9
</div>
<div class="childclass">
some content 10
</div>
<div class="childclass">
some content 11
</div>
</div>
The given code is only working in Firefox and not in any other browser.
I have given the Fiddle link for it.The code is working fine in Firefox and the functions are also working but it is not supported by any other browser.
The error shows is
Error due to long Script
Fiddle
Here is the code.
var $boxes;
$(document).ready(function() {
$boxes = $(".box");
setupColumns();
$(window).on("resize", setupColumns);
});
function setupColumns() {
var $columnwrapper = $("#columns");
var w = $("<div>").addClass("column").width();
var cnt = Math.floor($columnwrapper.width() / w);
var cols = [];
for (var i = 0; i < cnt; i++) {
var $col = $("<div>").addClass("column");
cols.push($col);
}
$columnwrapper.append(cols);
var cnt = 0;
$boxes.each(function() {
$(this).detach().appendTo(cols[cnt]);
cnt = (cnt + 1) % cols.length;
});
}
$(".box").click(function() {
if ($(this).height() != 100)
$(this).animate({
height: 100
}, 1000);
else
$(this).animate({
height: 150
}, 1000);
});
.column {
width: 114px;
float: left
}
.box {
height: 100px;
width: 100px;
border: 2px solid;
margin-bottom: 10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="columns"></div>
<div class="box">HELLO WORLD 1</div>
<div class="box">HELLO WORLD 2</div>
<div class="box">HELLO WORLD 3</div>
<div class="box">HELLO WORLD 4</div>
<div class="box">HELLO WORLD 5</div>
<div class="box">HELLO WORLD 6</div>
<div class="box">HELLO WORLD 7</div>
<div class="box">HELLO WORLD 8</div>
<div class="box">HELLO WORLD 9</div>
<div class="box">HELLO WORLD 10</div>
The problem is due to following line:
var w = $("<div>").addClass("column").width();
Apart from Firefox, in other browsers its returning 0 which causes cnt to become Infinity. That's why you are getting a really long running script that's creating infinite divs and adding them to cols[]
Documentation for .width() says:
The value reported by .width() is not guaranteed to be accurate when
the element or its parent is hidden. To get an accurate value, ensure
the element is visible before using .width().
So what you will need to do is:
var $boxes;
$(document).ready(function() {
$boxes = $(".box");
setupColumns();
$(window).on("resize", setupColumns);
});
function setupColumns() {
var $columnwrapper = $("#columns");
//////////start change////////////
var dummy = $("<div>").addClass("column");
dummy.appendTo($columnwrapper); // add it to wrapper so that it gets displayed
var w = dummy.width(); // this now returns 114
dummy.remove(); // now that we have got the width, remove it
// just to be on safer side:
if(w == 0){
console.log("column width is 0.");
return;
}
//////////end change////////////
var cnt = Math.floor($columnwrapper.width() / w);
var cols = [];
for (var i = 0; i < cnt; i++) {
var $col = $("<div>").addClass("column");
cols.push($col);
}
$columnwrapper.append(cols);
var cnt = 0;
$boxes.each(function() {
$(this).detach().appendTo(cols[cnt]);
cnt = (cnt + 1) % cols.length;
});
}
$(".box").click(function() {
if ($(this).height() != 100)
$(this).animate({
height: 100
}, 1000);
else
$(this).animate({
height: 150
}, 1000);
});
.column {
width: 114px;
float: left
}
.box {
height: 100px;
width: 100px;
border: 2px solid;
margin-bottom: 10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="columns"></div>
<div class="box">HELLO WORLD 1</div>
<div class="box">HELLO WORLD 2</div>
<div class="box">HELLO WORLD 3</div>
<div class="box">HELLO WORLD 4</div>
<div class="box">HELLO WORLD 5</div>
<div class="box">HELLO WORLD 6</div>
<div class="box">HELLO WORLD 7</div>
<div class="box">HELLO WORLD 8</div>
<div class="box">HELLO WORLD 9</div>
<div class="box">HELLO WORLD 10</div>
This is maybe because of cross-browser security concept by the modern browsers. If you are trying to run in Google Chrome. You might have to use the older version or install the plugin such as this:
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en
I am using this code to move images randomly in an area. But I need to show atleast 3 images always. Here is what I had done:
HTML
<div class="fade">Image 1</div>
<div class="fade">Image 2</div>
<div class="fade">Image 3</div>
<div class="fade">Image 4</div>
<div class="fade">Image 5</div>
<div class="fade">Image 6</div>
jQuery
(function fadeInDiv() {
var divs = jQuery('.fade');
var elem = divs.eq(Math.floor(Math.random() * divs.length));
if (!elem.is(':visible')) {
elem.prev().remove();
elem.fadeIn(Math.floor(Math.random() * 1000), fadeInDiv);
} else {
elem.fadeOut(Math.floor(Math.random() * 1000), function() {
elem.before('<div> </div>');
fadeInDiv();
});
}
})();
This code fadein and fadeout images randomly as a result show 2 images at a time sometimes 1 image at a time sometime 3. I need to show 3 images with in 6 images every time with fadein fadeout functionality.
Here is how my home page look like:
Image1 Image2
Image3
I want it to look like:
Image1
Image2 Image3
or
Image1
Image2 Image3
or any other pattern with this images
you need to use css properties to change their position on the screen.
You ll have to precise their positionning style, IE absolute.
elem.css('top','15px') and elem.css('left','15px') are the propers method to move objects on screen. You ll adjust the 15px to the value you ll need. It s relative to the top-left corner of your screen.
fadeIn / fadeOut only change opacity property of those objects on the screen.
Try a recursive algorithm with delay lengths depending on the random order of the objects:
window.refresh = function(delay) {
delay *= 1000;
var doms = [];
var randos = [];
var index = 0;
function fadeout() {
if (index < 3) {
var random = $(doms.get(randos[index]));
$(random).delay(delay + 200 * index).fadeTo(200, 0, function() {
$(random).css("visibility", "hidden");
});
doms = doms.not(random);
index++;
fadeout(doms);
}
}
doms = $('.grid-item');
doms.css("visibility","visible");
doms.css("opacity","1");
var num = Math.floor(Math.random() * doms.length);
for (var i = 0; i < doms.length; i++) {
while (randos.indexOf(num) > -1) {
num = Math.floor(Math.random() * doms.length);
}
randos.push(num);
}
fadeout();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grid">
<div class="grid-item">Image 1</div>
<div class="grid-item">Image 2</div>
<div class="grid-item">Image 3</div>
<div class="grid-item">Image 4</div>
<div class="grid-item">Image 5</div>
<div class="grid-item">Image 6</div>
</div>
<br>
<button onclick="refresh(0)">Trigger Animation</button>
<br>
<br>
<input type="number" placeholder="Time in Seconds">
<button onclick="refresh($(this).prev().val())">Trigger Delayed Animation</button>