I want my webpage to have two slideshows. I have one at the moment that works fine, but having trouble adding the second slideshow, as the images for the second slideshow appear outside of it.
I thought I could probably just copy and paste the code I did for the first slideshow and just change the div class names, but this did not work. I also have javascript controlling my slideshow but I didn't think copying the function I did for the first slideshow, would work for the second.
Can someone give me advice on how I can create the second slideshow using HTML, javascript and css?
Well, part of the key is to parameterize all of the required details - that is, don't hard-code things like the output container's id or that of the target image element if you decide to use a single image and change it's source.
Some approaches use an unordered-list and set it (with css) so only the first item is visible. Changing slides then becomes a matter of moving the li items around inside their container. I.e if one calls appendChild on the parent with the first li item as a parameter, it will be hidden since it's now the last li item and the 2nd item will now be the first and this will be the one displayed.
While the second approach is a little more straight forward, the 1st has the benefits of (0) not needing to know or care how many images there are - you simply move the first li item to be the last, or move the last one to be first and, (1) all the images are loaded at the start, so you don't get a small delay as each slide is shown for the first time and loaded.
Other approaches change the src of an image element.
I've utilized the second here. I've not bothered with prev/next buttons - this may mean this answer is beyond you at the moment. I would add prev/next functions inside the startSlideshow function and return the function itself - i.e return this;, rather than the id of the timer (which is to allow it to be stopped via clearInterval)
JS
function newEl(tag){return document.createElement(tag)}
function byId(id){return document.getElementById(id)}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
var slideshow1TimerId = startSlideshow( ['uqrsGpO.jpg', 'vote-pedro.jpg'], 'slide1', 3000 );
var slideshow2TimerId = startSlideshow( ['zS0lOud.jpg', 'tree.png', 's13.bmp'], 'slide2', 1000 );
}
function startSlideshow(imgNameArray, idOfContainer, msPerSlide)
{
var container = byId(idOfContainer);
var tgtImgElem = newEl('img');
container.appendChild(tgtImgElem);
var timerId = setInterval(setSlideImg, msPerSlide);
var slideIndex = 0;
var numSlides = imgNameArray.length;
function setSlideImg()
{
tgtImgElem.src = imgNameArray[slideIndex];
slideIndex++;
if (slideIndex >= numSlides)
slideIndex = 0;
}
return timerId;
}
CSS
#slide1 img, #slide2 img
{
height: 128px;
}
HTML
<div id='slide1'></div>
<div id='slide2'></div>
Related
I'm trying to create a generic function that can be placed just once in my site and work across multiple pages, nice and lightweight.
I want to be able to make certain divs on the site fade-in when you reach 10px above them on the scroll.
I want to do this by simply adding the following attributes to my divs:
.fade-in-block
#specific-block-name
The idea is that I could go through the site, add this class and an ID, and the animation would work.
I almost have it working except for one thing, the scroll listening constantly continues to console.log after the function has been called. I don't like this as it feels like it's going to be constantly trying to apply the animation, which won't really be seen from the front-end but I feel the constant maths behind the scenes could slow stuff down.
Here is my jQuery:
$('body .fade-in-block').each(function(){
var block = '#'+$(this).attr('id');
console.log('Block class is = '+block);
var offset = $(block).offset().top;
var $w = $(window).scroll(function () {
if ($w.scrollTop() > offset - 10) {
console.log('reached block turn-on point for '+block);
$(block).removeAttr('id'); // remove the ID from the element so the script doesn't continue to find the element
// fade and rise animation here
}
});
});
And here is a JSFiddle. It works just fine, but once you hit the block you'll see it logs constantly every pixel scrolled.
I tried to remedy this by removing the selecting id from the element once the event has occurred, but it continues to run.
Scroll and resize events both have this problem and the solution is said to be debouncing. However, I've never actually gotten debouncing to work properly. Instead I typically create a sort of switch that is turned off once the scroll condition has activated. In your case, since you have multiple elements, you would need to assign a switch to each element.
$(window).on('scroll', function(){
$('.fade-in-block').each(function(){
var appear = $(this).attr('data-appeared');
if(!appear){
$(this).attr('data-appeared', true);
//do something to $(this)
}
})
})
Here I'm adding a data attribute after it has appeared and checking for it again once it has.
the code: http://jsfiddle.net/n2m4absf/ (wont be functional, this is linked for code display purposes). trying to use:
setInterval(function(){slideCard();}
, 5000);
this carousel is a div box that moves in -883px chunks of margin-left. i want it to scroll automatically (thinking set interval would be the logic to use) every 5 seconds or so.
i have other js that handles the on click functions for navigating the carousel manually, but i dont think they should be effecting the autoplay. they do however live in the same file as the above js.
just need to get autoplay working and not sure why my js isnt doing it.
There are multiple problems in the script.
The variable count is declared as local to the method so in every call it will get initiated to 0 causing the first if block to execute.
Since you have used different if blocks, each if blocks will get evaluated in each iteration, so only the value of the last block will be affected
Since you don't have a constant logic for the margin value, I think you can use an array of margin values like
var slide = $('div.inner > ul');
var count = 0,
margins = ['-883px', '-1686px', 0];
function slideCard() {
slide.css('margin-left', margins[count++ % 3]);
};
setInterval(function () {
slideCard();
}, 1000);
I'm trying at the moment to target multiple instances of the same div class (.overlay) - the basic idea I'm trying to execute is that each div contains a HTML5 video inside another wrapped div which on mouseenter reveals itself, sets the video timeline to 0 and plays, and on mouseout resets the video to 0 again.
The problem I'm having is that only the first item of my grid works at the moment with nothing happening on the rollover of the others. This is my Javascript:
$(document).ready(function() {
$('.overlay').mouseenter(function(){
$('#testvideo').get(0).play();
}).mouseout(function() {
$('#testvideo').get(0).pause();
$('#testvideo').get(0).currentTime = 0;
})
});
I've also tried the following
$(document).ready(function() {
$('.overlay').mouseenter.each(function(){
$('#testvideo').get(0).play();
}).mouseout(function() {
$('#testvideo').get(0).pause();
$('#testvideo').get(0).currentTime = 0;
})
});
but that simply broke the functionality all together!
Here is a fiddle showing what should happen: http://jsfiddle.net/jameshenry/ejmfydfy/
The only difference between this and the actual site is that there are multiple grid items and thumbnails. I also don't want the behaviour to by asynchronous but rather individual - does anyone have any idea where I'm going wrong (I'm guessing my javascript!)
The problem is that you're using always $('#testvideo'), independent on the div you're entering the mouse. Since the HTML's id property must be unique, only the first element that you set the id testvideo will work the way you expect.
You should be using the video tag referenced by the div.overlay, or you could add a CSS class to the video tags, so you could use that class to find the video.
The code below will get the overlayed video, independent of which it is.
$(document).ready(function() {
$('.overlay').hover(function() {
$(this).parent().find('video').get(0).play();
}, function() {
var video = $(this).parent().find('video').get(0);
video.pause();
video.currentTime = 0;
});
});
Take a look at your updated fiddle.
The first way you did it should work, the second one not. But, you shouldn't use an id like #testvideo if there are a lot of videos (one on each .overley element). Having multiple instances of the same id produce unexpected behaviuor, like "only working on the first item".
You should change your #testvideo with .testvideo and change your code to something like this:
$(document).ready(function() {
$('.overlay').mouseenter(function(){
$(this).find('.testvideo').play();
}).mouseout(function() {
$(this).find('.testvideo').pause();
$(this).find('.testvideo').currentTime = 0;
})
});
I made a script in order to create this "slideshow": http://jsfiddle.net/LWBJG/2/
yet I can not go back to the last slide if I hit "previous" when it is on the first slide
I tried using the last-child selector but had no success
I also tried resetting the count directly like so:
if(count==1){
count=2;
$(".slideshow :nth-child("+count+")").fadeIn();
}
I've been stuck with this for two days, I'm trying to understand what I'm doing wrong!
all I what's left to do is to go to the last slide if I hit "previous" while I'm "standing" on the first slide
First you need to hide all the other .slideshow img elements not being shown when your page first loads. You can do that multiple ways, but here's an example:
$(".slideshow img:not(:nth-child(" + count + "))").hide();
Next, you need to hide the current showing slide when going to the previous one:
$(".slideshow :nth-child(" + count + ")").fadeOut();
Finally, you need to set the count to the number of elements in .slideshow img when going to the last image:
count = $(".slideshow img").length;
Here's a working example: http://jsfiddle.net/LWBJG/22/
You simply were not fading out in the prev loop like you were in the next button loop.
$(".slideshow :nth-child("+count+")").fadeOut()
Also, in the css, i put the following code:
.slideshow > img:not(:first-child) { display:none;}
This makes only the first img appear as default, and then the other ones will fade in as necessary. The way you currently have it, is count is updating properly but your images are inline and are appearing behind the current image number 1.. But on your next loop click, you properly fade out the images.
Hope this helps. Here is the http://jsfiddle.net/LWBJG/18/
Yes i know, i'am late to the party, but I played around a bit. Maybe someone will find the solution useful later on.
Here is a demo: http://jsfiddle.net/NicoO/LWBJG/25/
var $slideContainer = $(".slideshow")
var totalSlides = getAllSlides().length;
var slideIndex = 0;
function getAllSlides(){
return $slideContainer.children("img");
}
function getSlide(index){
return $slideContainer.children().eq(index);
}
function slideExists(index){
return getSlide(index).length;
}
function getCurrentSlide(){
return getSlide(slideIndex);
}
function animateSlide(){
getAllSlides().fadeOut();
getCurrentSlide().fadeIn();
}
$("#next").on("click", function () {
slideIndex++;
if(!slideExists(slideIndex))
slideIndex = 0;
animateSlide();
});
$("#prev").on("click", function () {
slideIndex--;
if(!slideExists(slideIndex))
slideIndex = totalSlides-1;
animateSlide();
});
Using multiple fadeIn()s might lead to a mess. In your case, if you really want to do so, you can first fadeOut() all images before fadeIn() the desired one. This solves the problem.
$(".slideshow img").fadeOut();
$(".slideshow :nth-child("+count+")").fadeIn();
hide() should also work.
Simply put I'm trying to sync two slideshows created using widgetkit lib in a joomla website, eg. when user clicks next slide on one, the other one also runs nextSlide() function in the slideshow.js. Same for previous. The problems I'm having is widgetkit uses anonymous functions for creating those slideshows and I dont have global references to them after they are created. With my limited programming knowledge I cant seem to trigger the nextSlide function for other slideshows once inside click handler.
If anyone can take a look it would be most welcome.
EDIT:
Of course I forgot to link the example webpage
http://www.yootheme.com/widgetkit/examples/slideshow
Mine is similar with only 2 slideshows, but is still only on local server.
Taking a brief look at widgetkit here is one possible solution. Using jquery you can search for any objects that have a class of slides with a child of next and click all others. The code provided below isn't tested but should point you in the right direction. As long as you don't call stop propagation or prevent default then the original click handlers should still fire.
var slideshow_count = $('.slides .next').length;
var cascade_countdown = 0;
$('.slides .next').each(function() {
$(this).click(function() {
// stop an infinite loop if we're already cascading till we've done it for all the elements.
if(cascade_countdown != 0) {
cascade_countdown--;
return true;
}
// we don't include the slideshow we're clicking in this count
cascade_countdown = slideshow_count - 1;
var clicked_el = this;
$('.slides .next').each(function() {
// only click elements that aren't the initiator
if(this !== clicked_el) {
$(this).click();
}
});
});
});