I've implemented the AnythingSlider (http://css-tricks.com/anythingslider-jquery-plugin/) using image and video content (videos use the longtail flv player - licensed version 5).
Problem: When the user plays the video, the slideshow doesn't know this has happened, so the slideshow keeps cycling while the video runs. So you have the slideshow running - and user can hear the audio but the video has cycled off.
UPDATE - here is a link to see what's going on: http://silverberry.org/beta/slider-longtail/
I'm trying to figure out an event-listener that will look and see when the LONGTAIL player is in PLAYING state and signals to the AnythingSlider that it needs to STOP.
Here's what I've got so far ... the video player event listeners are working (right now I have alerts popping up so that I can be sure the events are being heard). An alert pops up with the player is initialized .. and alert pops up when we press the PLAY button on the video ... and an alert pops up when the video STOPS playing. But ... I've yet to work out the proper syntax for signaling to the anythingslider to STOP!
I thought it would be this:
$VUslider.startStop(false);
Below is the code I have so far ... beginning with the code that initializes the slider.
function formatText(index, panel) {
return index + "";
}
$(function () {
$('.VUslider').VUslider({
autoPlay: true,
delay: 7000,
startStopped: false,
animationTime: 200,
hashTags: true,
buildNavigation: false,
pauseOnHover: true,
navigationFormatter: formatText
});
});
var player = null;
function playerReadyCallback(obj) {
player = document.getElementsByName(obj.id)[0];
alert('the videoplayer '+obj['id']+' has been instantiated');
player.addModelListener('STATE', 'stateMonitor');
}
function stateMonitor(obj) {
currentState = obj['newstate'];
if(currentState == 'PLAYING') {
alert ('the videoplayer '+obj['id']+' is playing now!');
$VUslider.startStop(false); // Trigger slideshow stop
}
if(obj.newstate == 'COMPLETED') {
alert ('the videoplayer '+obj['id']+' has stopped playing now!');
$VUslider.startStop(true); // Trigger slideshow start
}
}
FOR REFERENCE ... HERE IS THE ANYTHING SLIDER CODE:
(function($){
$.VUslider = function(el, options){
// To avoid scope issues, use 'base' instead of 'this'
// to reference this class from internal events and functions.
var base = this;
// Access to jQuery and DOM versions of element
base.$el = $(el);
base.el = el;
// Set up a few defaults
base.currentPage = 1;
base.timer = null;
base.playing = false;
// Add a reverse reference to the DOM object
base.$el.data("AnythingSlider", base);
base.init = function(){
base.options = $.extend({},$.VUslider.defaults, options);
// Cache existing DOM elements for later
base.$wrapper = base.$el.find('> div').css('overflow', 'hidden');
base.$slider = base.$wrapper.find('> ul');
base.$items = base.$slider.find('> li');
base.$single = base.$items.filter(':first');
// Build the navigation if needed
if(base.options.buildNavigation) base.buildNavigation();
// Get the details
base.singleWidth = base.$single.outerWidth();
base.pages = base.$items.length;
// Top and tail the list with 'visible' number of items, top has the last section, and tail has the first
// This supports the "infinite" scrolling
base.$items.filter(':first').before(base.$items.filter(':last').clone().addClass('cloned'));
base.$items.filter(':last' ).after(base.$items.filter(':first').clone().addClass('cloned'));
// We just added two items, time to re-cache the list
base.$items = base.$slider.find('> li'); // reselect
// Setup our forward/backward navigation
base.buildNextBackButtons();
// If autoPlay functionality is included, then initialize the settings
if(base.options.autoPlay) {
base.playing = !base.options.startStopped; // Sets the playing variable to false if startStopped is true
base.buildAutoPlay();
};
// If pauseOnHover then add hover effects
if(base.options.pauseOnHover) {
base.$el.hover(function(){
base.clearTimer();
}, function(){
base.startStop(base.playing);
});
}
// If a hash can not be used to trigger the plugin, then go to page 1
if((base.options.hashTags == true && !base.gotoHash()) || base.options.hashTags == false){
base.setCurrentPage(1);
};
};
base.gotoPage = function(page, autoplay){
// When autoplay isn't passed, we stop the timer
if(autoplay !== true) autoplay = false;
if(!autoplay) base.startStop(false);
if(typeof(page) == "undefined" || page == null) {
page = 1;
base.setCurrentPage(1);
};
// Just check for bounds
if(page > base.pages + 1) page = base.pages;
if(page < 0 ) page = 1;
var dir = page < base.currentPage ? -1 : 1,
n = Math.abs(base.currentPage - page),
left = base.singleWidth * dir * n;
base.$wrapper.filter(':not(:animated)').animate({
scrollLeft : '+=' + left
}, base.options.animationTime, base.options.easing, function () {
if (page == 0) {
base.$wrapper.scrollLeft(base.singleWidth * base.pages);
page = base.pages;
} else if (page > base.pages) {
base.$wrapper.scrollLeft(base.singleWidth);
// reset back to start position
page = 1;
};
base.setCurrentPage(page);
});
};
base.setCurrentPage = function(page, move){
// Set visual
if(base.options.buildNavigation){
base.$nav.find('.cur').removeClass('cur');
$(base.$navLinks[page - 1]).addClass('cur');
};
// Only change left if move does not equal false
if(move !== false) base.$wrapper.scrollLeft(base.singleWidth * page);
// Update local variable
base.currentPage = page;
};
base.goForward = function(autoplay){
if(autoplay !== true) autoplay = false;
base.gotoPage(base.currentPage + 1, autoplay);
};
base.goBack = function(){
base.gotoPage(base.currentPage - 1);
};
// This method tries to find a hash that matches panel-X
// If found, it tries to find a matching item
// If that is found as well, then that item starts visible
base.gotoHash = function(){
if(/^#?panel-\d+$/.test(window.location.hash)){
var index = parseInt(window.location.hash.substr(7));
var $item = base.$items.filter(':eq(' + index + ')');
if($item.length != 0){
base.setCurrentPage(index);
return true;
};
};
return false; // A item wasn't found;
};
// Creates the numbered navigation links
base.buildNavigation = function(){
base.$nav = $("<div id='thumbNav'></div>").appendTo(base.$el);
base.$items.each(function(i,el){
var index = i + 1;
var $a = $("<a href='#'></a>");
// If a formatter function is present, use it
if( typeof(base.options.navigationFormatter) == "function"){
$a.html(base.options.navigationFormatter(index, $(this)));
} else {
$a.text(index);
}
$a.click(function(e){
base.gotoPage(index);
if (base.options.hashTags)
base.setHash('panel-' + index);
e.preventDefault();
});
base.$nav.append($a);
});
base.$navLinks = base.$nav.find('> a');
};
// Creates the Forward/Backward buttons
base.buildNextBackButtons = function(){
var $forward = $('<a class="arrow forward">></a>'),
$back = $('<a class="arrow back"><</a>');
// Bind to the forward and back buttons
$back.click(function(e){
base.goBack();
e.preventDefault();
});
$forward.click(function(e){
base.goForward();
e.preventDefault();
});
// Append elements to page
base.$wrapper.after($back).after($forward);
};
// Creates the Start/Stop button
base.buildAutoPlay = function(){
base.$startStop = $("<a href='#' id='start-stop'></a>").html(base.playing ? base.options.stopText : base.options.startText);
base.$el.append(base.$startStop);
base.$startStop.click(function(e){
base.startStop(!base.playing);
e.preventDefault();
});
// Use the same setting, but trigger the start;
base.startStop(base.playing);
};
// Handles stopping and playing the slideshow
// Pass startStop(false) to stop and startStop(true) to play
base.startStop = function(playing){
if(playing !== true) playing = false; // Default if not supplied is false
// Update variable
base.playing = playing;
// Toggle playing and text
if(base.options.autoPlay) base.$startStop.toggleClass("playing", playing).html( playing ? base.options.stopText : base.options.startText );
if(playing){
base.clearTimer(); // Just in case this was triggered twice in a row
base.timer = window.setInterval(function(){
base.goForward(true);
}, base.options.delay);
} else {
base.clearTimer();
};
};
base.clearTimer = function(){
// Clear the timer only if it is set
if(base.timer) window.clearInterval(base.timer);
};
// Taken from AJAXY jquery.history Plugin
base.setHash = function ( hash ) {
// Write hash
if ( typeof window.location.hash !== 'undefined' ) {
if ( window.location.hash !== hash ) {
window.location.hash = hash;
};
} else if ( location.hash !== hash ) {
location.hash = hash;
};
// Done
return hash;
};
// <-- End AJAXY code
// Trigger the initialization
base.init();
};
$.VUslider.defaults = {
easing: "swing", // Anything other than "linear" or "swing" requires the easing plugin
autoPlay: true, // This turns off the entire FUNCTIONALY, not just if it starts running or not
startStopped: false, // If autoPlay is on, this can force it to start stopped
delay: 3000, // How long between slide transitions in AutoPlay mode
animationTime: 600, // How long the slide transition takes
hashTags: true, // Should links change the hashtag in the URL?
buildNavigation: true, // If true, builds and list of anchor links to link to each slide
pauseOnHover: true, // If true, and autoPlay is enabled, the show will pause on hover
startText: "Start", // Start text
stopText: "Stop", // Stop text
navigationFormatter: null // Details at the top of the file on this use (advanced use)
};
$.fn.VUslider = function(options){
if(typeof(options) == "object"){
return this.each(function(i){
(new $.VUslider(this, options));
// This plugin supports multiple instances, but only one can support hash-tag support
// This disables hash-tags on all items but the first one
options.hashTags = false;
});
} else if (typeof(options) == "number") {
return this.each(function(i){
var anySlide = $(this).data('AnythingSlider');
if(anySlide){
anySlide.gotoPage(options);
}
});
}
};
})(jQuery);
Are you setting $VUslider to equal $('.VUslider').VUslider({ . . }); ?
In your example code you are not.
You should be doing something like this:
$VUslider = $('.VUslider').VUslider({
autoPlay: true,
delay: 7000,
startStopped: false,
animationTime: 200,
hashTags: true,
buildNavigation: false,
pauseOnHover: true,
navigationFormatter: formatText
});
This is somewhat of a stab in the dark, so I'll try to explain my reasoning a bit.
After you've created the VUslider bits as you're already doing, try doing this to start/stop the slider:
$('.VUslider').VUslider.startStop(false);
// this will toggle between starting and stopping but doesn't give control
// to call start or stop specifically.
$('#start-stop').click();
When you call $('.VUslider').VUslider({...}), it doesn't return anything, so there's no handle to VUslider at that point ($.each(..) doesn't return anything). This will hopefully get you a reference to the script and to the startStop function.
HTH
Related
I'm using Skrollr-menu to animate down a page on a button press using the following
HTML
<div class="trigger-scroll left">></div>
... the page i want to reveal, using scrolling ...
<section id="End" class="scroll-here">
<div class="hsContainer bottom"></div>
</section>
JavaScript
var s = skrollr.init();
skrollr.menu.init(s, {
animate: true,
//How long the animation should take in ms.
duration: function(currentTop, targetTop) {
//By default, the duration is hardcoded at 500ms.
return 18000;
//But you could calculate a value based on the current scroll position (`currentTop`) and the target scroll position (`targetTop`).
//return Math.abs(currentTop - targetTop) * 10;
},
//This event is triggered right before we jump/animate to a new hash.
change: function(newHash, newTopPosition) {
//Do stuff
},
//Add hash link (e.g. `#foo`) to URL or not.
updateUrl: false //defaults to `true`.
});
What happens when I click the button is that it works, that is not the problem.
The problem is that it seems to change speed as skrollr-menu animates the page. It starts off quite quickly, which means that the first few elements on the page (about the first 2000px) flash past without being readable. Then the speed evens out and is fine right until the last 3000px (approximately) where skrollr-menu is very slow. What I want is for the click of the button to resemble holding the down arrow on the keyboard or the scroll sidebar, which by default it seems skrollr-menu does not do.
I've tried using math equations to change the speed but the issue persists no matter what i try, and there doesn't seem to be any "simple" way to change the acceleration speed, and I suspect the problem is somewhere within the Skrollr.menu.js file, but I can't see where.
Is there any way which I can make the scrolling an even speed, rather than fast at the start and slow at the end?
Note: I'm not very experienced in JavaScript or jQuery, so it's probably something simple I've overlooked.
skrollr menu on github
https://github.com/Prinzhorn/skrollr-menu
Skrollr.menu.js
/*!
* Plugin for skrollr.
* This plugin makes hashlinks scroll nicely to their target position.
*
* Alexander Prinzhorn - https://github.com/Prinzhorn/skrollr
*
* Free to use under terms of MIT license
*/
(function(document, window) {
'use strict';
var DEFAULT_DURATION = 500;
var DEFAULT_EASING = 'sqrt';
var DEFAULT_SCALE = 1;
var MENU_TOP_ATTR = 'data-menu-top';
var MENU_OFFSET_ATTR = 'data-menu-offset';
var MENU_DURATION_ATTR = 'data-menu-duration';
var MENU_IGNORE_ATTR = 'data-menu-ignore';
var skrollr = window.skrollr;
var history = window.history;
var supportsHistory = !!history.pushState;
/*
Since we are using event bubbling, the element that has been clicked
might not acutally be the link but a child.
*/
var findParentLink = function(element) {
//We reached the top, no link found.
if(element === document) {
return false;
}
//Yay, it's a link!
if(element.tagName.toUpperCase() === 'A') {
return element;
}
//Maybe the parent is a link.
return findParentLink(element.parentNode);
};
/*
Handle the click event on the document.
*/
var handleClick = function(e) {
//Only handle left click.
if(e.which !== 1 && e.button !== 0) {
return;
}
var link = findParentLink(e.target);
//The click did not happen inside a link.
if(!link) {
return;
}
if(handleLink(link)) {
e.preventDefault();
}
};
/*
Handles the click on a link. May be called without an actual click event.
When the fake flag is set, the link won't change the url and the position won't be animated.
*/
var handleLink = function(link, fake) {
var hash;
//When complexLinks is enabled, we also accept links which do not just contain a simple hash.
if(_complexLinks) {
//The link points to something completely different.
if(link.hostname !== window.location.hostname) {
return false;
}
//The link does not link to the same page/path.
if(link.pathname !== document.location.pathname) {
return false;
}
hash = link.hash;
} else {
//Don't use the href property (link.href) because it contains the absolute url.
hash = link.getAttribute('href');
}
//Not a hash link.
if(!/^#/.test(hash)) {
return false;
}
//The link has the ignore attribute.
if(!fake && link.getAttribute(MENU_IGNORE_ATTR) !== null) {
return false;
}
//Now get the targetTop to scroll to.
var targetTop;
var menuTop;
//If there's a handleLink function, it overrides the actual anchor offset.
if(_handleLink) {
menuTop = _handleLink(link);
}
//If there's a data-menu-top attribute and no handleLink function, it overrides the actual anchor offset.
else {
menuTop = link.getAttribute(MENU_TOP_ATTR);
}
if(menuTop !== null) {
//Is it a percentage offset?
if(/p$/.test(menuTop)) {
targetTop = (menuTop.slice(0, -1) / 100) * document.documentElement.clientHeight;
} else {
targetTop = +menuTop * _scale;
}
} else {
var scrollTarget = document.getElementById(hash.substr(1));
//Ignore the click if no target is found.
if(!scrollTarget) {
return false;
}
targetTop = _skrollrInstance.relativeToAbsolute(scrollTarget, 'top', 'top');
var menuOffset = scrollTarget.getAttribute(MENU_OFFSET_ATTR);
if(menuOffset !== null) {
targetTop += +menuOffset;
}
}
if(supportsHistory && _updateUrl && !fake) {
history.pushState({top: targetTop}, '', hash);
}
var menuDuration = parseInt(link.getAttribute(MENU_DURATION_ATTR), 10);
var animationDuration = _duration(_skrollrInstance.getScrollTop(), targetTop);
if(!isNaN(menuDuration)) {
animationDuration = menuDuration;
}
//Trigger the change if event if there's a listener.
if(_change) {
_change(hash, targetTop);
}
//Now finally scroll there.
if(_animate && !fake) {
_skrollrInstance.animateTo(targetTop, {
duration: animationDuration,
easing: _easing
});
} else {
defer(function() {
_skrollrInstance.setScrollTop(targetTop);
});
}
return true;
};
var jumpStraightToHash = function() {
if(window.location.hash && document.querySelector) {
var link = document.querySelector('a[href="' + window.location.hash + '"]');
if(!link) {
// No link found on page, so we create one and then activate it
link = document.createElement('a');
link.href = window.location.hash;
}
handleLink(link, true);
}
};
var defer = function(fn) {
window.setTimeout(fn, 1);
};
/*
Global menu function accessible through window.skrollr.menu.init.
*/
skrollr.menu = {};
skrollr.menu.init = function(skrollrInstance, options) {
_skrollrInstance = skrollrInstance;
options = options || {};
_easing = options.easing || DEFAULT_EASING;
_animate = options.animate !== false;
_duration = options.duration || DEFAULT_DURATION;
_handleLink = options.handleLink;
_scale = options.scale || DEFAULT_SCALE;
_complexLinks = options.complexLinks === true;
_change = options.change;
_updateUrl = options.updateUrl !== false;
if(typeof _duration === 'number') {
_duration = (function(duration) {
return function() {
return duration;
};
}(_duration));
}
//Use event bubbling and attach a single listener to the document.
skrollr.addEvent(document, 'click', handleClick);
if(supportsHistory) {
skrollr.addEvent(window, 'popstate', function(e) {
var state = e.state || {};
var top = state.top || 0;
defer(function() {
_skrollrInstance.setScrollTop(top);
});
}, false);
}
jumpStraightToHash();
};
//Expose the handleLink function to be able to programmatically trigger clicks.
skrollr.menu.click = function(link) {
//We're not assigning it directly to `click` because of the second ("private") parameter.
handleLink(link);
};
//Private reference to the initialized skrollr.
var _skrollrInstance;
var _easing;
var _duration;
var _animate;
var _handleLink;
var _scale;
var _complexLinks;
var _change;
var _updateUrl;
//In case the page was opened with a hash, prevent jumping to it.
//http://stackoverflow.com/questions/3659072/jquery-disable-anchor-jump-when-loading-a-page
defer(function() {
if(window.location.hash) {
window.scrollTo(0, 0);
}
});
}(document, window));
The problem was the easing function found here
//Now finally scroll there.
if(_animate && !fake) {
_skrollrInstance.animateTo(targetTop, {
duration: animationDuration,
easing: _easing
});
} else {
defer(function() {
_skrollrInstance.setScrollTop(targetTop);
});
}
return true;
It seems that, even though Skrollr states that easing's default is linear (no easing), the default is ACTUALLY set to sqrt (or at least it was in my case). The problem can be solved by forcing easing to linear in skrollr.menu.init, or chaning the skrollr.menu.js file to remove easing from the function. The first of these two solutions is cleaner, and won't cause issues later.
skrollr.menu.init(s, {
duration: function(currentTop, targetTop) {return 20000;},
easing: 'linear'
});
I have made a jQuery plugin which acts as a slideshow. All of my problem is that it does fades out first, and then the next images fades in. Which is a little odd. I have thought all the day and am really beat about it. Can anyone helps me? Here is the info:
Below is a list of websites with current slideshow hosted:
http://behdis.org
www.ms-models.com
www.royal-fci.com
Now, PROBLEM is:
there are naturally a bunch of images for the slideshow to fade them in and out. Now, the slideshow makes the first image faded out and then makes the next image faded in. I want the slideshow to begin fading in the next image when the current image has already begun fading out. Just like hundreds of slideshows out there on many websites. No need to give link.
Here is the plugin script itself:
(function(){
/* function read_line (path_to_file, container, tag, url_prefix)
{
myObject = {}; //myObject[numberline] = "textEachLine";
$.get(, functipath_to_fileon(myContentFile) {
var lines = myContentFile.split("\r\n");
for(var i in lines)
{
myObject[i] = i;
container.append('<'+tag+'>'+"<img src='"+url_prefix+'/'+lines[i]+"'>"+'</img>'+'</'+tag+'>');
}
}, 'text');// end of anonymous function
} */
$.fn.mtSlideGallery = function(options){
var options = $.extend({
fullWidth : false, // this makes a full background slideshow
FadeIn : 2, // this is the duration of fading in
FadeOut : 2, // this is the duration of fading out
visibilityDuration : 2, // this is the duration of visible image
startSlide : 1, // this is the first slide when the page loads
height : '100%',
height_fixed : true,
enable_error : false,
enable_gallery : false,
slide_previous : '.slide-left-control', // this is the name of class for previous-picture-handle
slide_next : '.slide-right-control', // this is the name of class for next-picture-handle
print_output : false,
print_area : '.slideshow-label',
seo_campatible : false, // this allows the script to print the title of each slide out into a h1-h6 tag
seo_suggestion : 'h2' // this allows the user to specify which h1-h6 tag be used. default is h6
/*auto_generate_from_file : false, // if true, then it will generate the div tag based on a file given
auto_generate_url : false, // if true, then a url_prefix is added to each line of text
auto_generate_tag : 'div', // the tag inside which the image tags nest. default is div and it is recommended no to change
auto_generate_url_prefix : "" // this is the url added to each image address. Depends on auto_generate_url options*/
}, options)
// develope $fn protype
return this.each(function(){
if(options.print_output === true)
{
var text_for_output = $(this).children('div').eq(options.startSlide).children('img').attr('alt');
$(options.print_area).text(text_for_output);
}
if(options.fullWidth === true)
{
$("body").css({'padding' : '0', 'margin' : '0'});
$("body").css({'overflow' : 'hidden'});
$("html").css({'padding' : '0', 'margin' : '0'});
$(this).css({'width' : '100%', 'height' : options.height});
$(this).css({'margin' : '0', 'padding' : '0'});
}
if(options.height_fixed === true)
{
$(this).css({'overflow' : 'hidden'});
}
var slideWrapper = $(this);
var slidesGroup = slideWrapper.children('div');
slidesLength = slidesGroup.length;
if(options.enable_error == true)
{
if(options.startSlide > slidesLength)
{
alert("Please correct the \"slideStart\" option. The number has to be less than the total number of images.")
}
}
i = options.startSlide;
slidesGroup.not(":eq("+i+")").hide();
console.log(slidesLength);
////////////////////// Print To label if true
var print_label = function(i)
{
var label = slidesGroup.eq(i).children('img').attr('alt');
$(options.print_area).text(label);
}
;
///////////////////// End of printing label
//////////////// GALLERY SLIDESHOW IF ENABLED USES THIS SCRIPT
if(options.enable_gallery === true)
{
$(options.slide_previous).click(function(event){ // this is a click event for the previous picture in the queue
event.preventDefault();
event.stopPropagation();
slidesGroup.eq(i).hide();
if(i === slidesLength)
{
i=0;
}
i -= 1;
slidesGroup.eq(i).show();
if(options.print_output === true)
{
print_label(i);
}
});
$(options.slide_next).click(function(event){ // this is a click event for the next picture in the queue
event.preventDefault();
event.stopPropagation();
slidesGroup.eq(i).hide();
if(i === slidesLength)
{
i=0;
}
i += 1;
slidesGroup.eq(i).show();
if(options.print_output === true)
{
print_label(i);
}
});
}
////////////////////// END OF GALLERY-ENABLED SCRIPT
////////////////////////////////////////////////////////
var slideShow = function () {
slidesGroup.eq(i).fadeOut(options.FadeOut*1000, function(){
slidesGroup.eq(i).hide();
i += 1;
if(i === slidesLength)
{
i=0;
}
slidesGroup.eq(i).fadeIn(options.FadeIn*1000);
if(options.print_output === true)
{
print_label(i);
}
})
}
setInterval(slideShow, options.visibilityDuration*1000);
})
}
})(jQuery)
Now, the slideshow makes the first image faded out and then makes the
next image faded in. I want the slideshow to begin fading in the next
image when the current image has already begun fading out.
The issue here is that the call to fade in the next slide is part of an anonymous callback function that does not fire until the initial jQuery animation is complete. You'll want to rewrite your code such that the $.fadeOut() and $.fadeIn() functions occur simultaneously:
var transition = function() {
//Determine the index of the next slide to show, based on the current index
var next_index = (current_index < slidesLength - 1) ? current_index + 1 : 0;
//Fade out the 'old' slide while fading in the 'new' slide
slidesGroup.eq(current_index).fadeOut({
duration: options.FadeOut*1000,
start: function() {
slidesGroup.eq(next_index).fadeIn({
duration: options.FadeIn*1000
});
},
complete: function() {
//Update the value of current_index
current_index = next_index;
}
});
}
However, this function pretty much restricts you to forward-only transitions. You could include a function argument that specifies a transition direction (forward and backward) that will determine the 'next slide' index.
Working jsFiddle: http://jsfiddle.net/gh25s/
EDIT: To clarify, you'll want to replace this part of your code:
var slideShow = function () {
slidesGroup.eq(i).fadeOut(options.FadeOut*1000, function(){
slidesGroup.eq(i).hide();
i += 1;
if(i === slidesLength) {
i=0;
}
slidesGroup.eq(i).fadeIn(options.FadeIn*1000);
if(options.print_output === true) {
print_label(i);
}
});
};
with this:
var slideShow = function() {
//Determine the index of the next slide to show, based on the current index
var next_index = (i < slidesLength - 1) ? i + 1 : 0;
//Fade out the 'old' slide while fading in the 'new' slide
slidesGroup.eq(i).fadeOut({
duration: options.FadeOut*1000,
start: function() {
slidesGroup.eq(next_index).fadeIn({
duration: options.FadeIn*1000
});
},
complete: function() {
//Update the value of i
i = next_index;
}
});
}
Also, using the variable name i throughout your code is confusing. I would suggest giving it a more meaningful, descriptive name like current_index. Variable names like i are typically read as temporary, local variables that are being used for some kind of iteration.
I wrote a slideshow plugin, but for some reason maybe because I've been working on it all day, I can't figure out exactly how to get it to go back to state one, once it's reached the very last state when it's on auto mode.
I'm thinking it's an architectual issue at this point, because basically I'm attaching the amount to scroll left to (negatively) for each panel (a panel contains 4 images which is what is currently shown to the user). The first tab should get: 0, the second 680, the third, 1360, etc. This is just done by calculating the width of the 4 images plus the padding.
I have it on a setTimeout(function(){}) currently to automatically move it which works pretty well (unless you also click tabs, but that's another issue). I just want to make it so when it's at the last state (numTabs - 1), to animate and move its state back to the first one.
Code:
(function($) {
var methods = {
init: function(options) {
var settings = $.extend({
'speed': '1000',
'interval': '1000',
'auto': 'on'
}, options);
return this.each(function() {
var $wrapper = $(this);
var $sliderContainer = $wrapper.find('.js-slider-container');
$sliderContainer.hide().fadeIn();
var $tabs = $wrapper.find('.js-slider-tabs li a');
var numTabs = $tabs.size();
var innerWidth = $wrapper.find('.js-slider-container').width();
var $elements = $wrapper.find('.js-slider-container a');
var $firstElement = $elements.first();
var containerHeight = $firstElement.height();
$sliderContainer.height(containerHeight);
// Loop through each list element in `.js-slider-tabs` and add the
// distance to move for each "panel". A panel in this example is 4 images
$tabs.each(function(i) {
// Set amount to scroll for each tab
if (i === 1) {
$(this).attr('data-to-move', innerWidth + 20); // 20 is the padding between elements
} else {
$(this).attr('data-to-move', innerWidth * (i) + (i * 20));
}
});
// If they hovered on the panel, add paused to the data attribute
$('.js-slider-container').hover(function() {
$sliderContainer.attr('data-paused', true);
}, function() {
$sliderContainer.attr('data-paused', false);
});
// Start the auto slide
if (settings.auto === 'on') {
methods.auto($tabs, settings, $sliderContainer);
}
$tabs.click(function() {
var $tab = $(this);
var $panelNum = $(this).attr('data-slider-panel');
var $amountToMove = $(this).attr('data-to-move');
// Remove the active class of the `li` if it contains it
$tabs.each(function() {
var $tab = $(this);
if ($tab.parent().hasClass('active')) {
$tab.parent().removeClass('active');
}
});
// Add active state to current tab
$tab.parent().addClass('active');
// Animate to panel position
methods.animate($amountToMove, settings);
return false;
});
});
},
auto: function($tabs, settings, $sliderContainer) {
$tabs.each(function(i) {
var $amountToMove = $(this).attr('data-to-move');
setTimeout(function() {
methods.animate($amountToMove, settings, i, $sliderContainer);
}, i * settings.interval);
});
},
animate: function($amountToMove, settings, i, $sliderContainer) {
// Animate
$('.js-slider-tabs li').eq(i - 1).removeClass('active');
$('.js-slider-tabs li').eq(i).addClass('active');
$('#js-to-move').animate({
'left': -$amountToMove
}, settings.speed, 'linear', function() {});
}
};
$.fn.slider = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
return false;
}
};
})(jQuery);
$(window).ready(function() {
$('.js-slider').slider({
'speed': '10000',
'interval': '10000',
'auto': 'on'
});
});
The auto and animate methods are where the magic happens. The parameters speed is how fast it's animated and interval is how often, currently set at 10 seconds.
Can anyone help me figure out how to get this to "infinitely loop", if you will?
Here is a JSFiddle
It would probably be better to let go of the .each() and setTimeout() combo and use just setInterval() instead. Using .each() naturally limits your loop to the length of your collection, so it's better to use a looping mechanism that's not, and that you can break at any point you choose.
Besides, you can readily identify the current visible element by just checking for .active, from what I can see.
You'd probably need something like this:
setInterval(function () {
// do this check here.
// it saves you a function call and having to pass in $sliderContainer
if ($sliderContainer.attr('data-paused') === 'true') { return; }
// you really need to just pass in the settings object.
// the current element you can identify (as mentioned),
// and $amountToMove is derivable from that.
methods.animate(settings);
}, i * settings.interval);
// ...
// cache your slider tabs outside of the function
// and just form a closure on that to speed up your manips
var slidertabs = $('.js-slider-tabs');
animate : function (settings) {
// identify the current tab
var current = slidertabs.find('li.active'),
// and then do some magic to determine the next element in the loop
next = current.next().length >= 0 ?
current.next() :
slidertabs.find('li:eq(0)')
;
current.removeClass('active');
next.addClass('active');
// do your stuff
};
The code is not optimized, but I hope you see where I'm getting at here.
I am just a beginner in jquery. I have used the tooltip script from this site. http://www.twinhelix.com/dhtml/supernote/demo/#demo4 .They used the following function to close the tooltip on clicking the close button.
<script type="text/javascript">
// SuperNote setup: Declare a new SuperNote object and pass the name used to
// identify notes in the document, and a config variable hash if you want to
// override any default settings.
var supernote = new SuperNote('supernote', {});
// Available config options are:
//allowNesting: true/false // Whether to allow triggers within triggers.
//cssProp: 'visibility' // CSS property used to show/hide notes and values.
//cssVis: 'inherit'
//cssHid: 'hidden'
//IESelectBoxFix: true/false // Enables the IFRAME select-box-covering fix.
//showDelay: 0 // Millisecond delays.
//hideDelay: 500
//animInSpeed: 0.1 // Animation speeds, from 0.0 to 1.0; 1.0 disables.
//animOutSpeed: 0.1
// You can pass several to your "new SuperNote()" command like so:
//{ name: value, name2: value2, name3: value3 }
// All the script from this point on is optional!
// Optional animation setup: passed element and 0.0-1.0 animation progress.
// You can have as many custom animations in a note object as you want.
function animFade(ref, counter)
{
//counter = Math.min(counter, 0.9); // Uncomment to make notes translucent.
var f = ref.filters, done = (counter == 1);
if (f)
{
if (!done && ref.style.filter.indexOf("alpha") == -1)
ref.style.filter += ' alpha(opacity=' + (counter * 100) + ')';
else if (f.length && f.alpha) with (f.alpha)
{
if (done) enabled = false;
else { opacity = (counter * 100); enabled=true }
}
}
else ref.style.opacity = ref.style.MozOpacity = counter*0.999;
};
supernote.animations[supernote.animations.length] = animFade;
// Optional custom note "close" button handler extension used in this example.
// This picks up click on CLASS="note-close" elements within CLASS="snb-pinned"
// notes, and closes the note when they are clicked.
// It can be deleted if you're not using it.
addEvent(document, 'click', function(evt)
{
var elm = evt.target || evt.srcElement, closeBtn, note;
while (elm)
{
if ((/note-close/).test(elm.className)) closeBtn = elm;
if ((/snb-pinned/).test(elm.className)) { note = elm; break }
elm = elm.parentNode;
}
if (closeBtn && note)
{
var noteData = note.id.match(/([a-z_\-0-9]+)-note-([a-z_\-0-9]+)/i);
for (var i = 0; i < SuperNote.instances.length; i++)
if (SuperNote.instances[i].myName == noteData[1])
{
setTimeout('SuperNote.instances[' + i + '].setVis("' + noteData[2] +
'", false, true)', 100);
cancelEvent(evt);
}
}
});
// Extending the script: you can capture mouse events on note show and hide.
// To get a reference to a note, use 'this.notes[noteID]' within a function.
// It has properties like 'ref' (the note element), 'trigRef' (its trigger),
// 'click' (whether its shows on click or not), 'visible' and 'animating'.
addEvent(supernote, 'show', function(noteID)
{
// Do cool stuff here!
});
addEvent(supernote, 'hide', function(noteID)
{
// Do cool stuff here!
});
// If you want draggable notes, feel free to download the "DragResize" script
// from my website http://www.twinhelix.com -- it's a nice addition :).
</script>
I have tried to edit this function for closing the tooltip on clicking the esckey too. But i couldn't. How can i modify the function?
I'm currently using the anythingSlider plugin, it works totally fine except when there is only one <li>.
The <li>s are generated from the database so sometimes there's only one.
However, the anythingSlider plugin still tries to slide through the <li>s, it works by sliding back to the first slide. Although this doesn't look great.
Does anybody know of a way of stopping it sliding if there's only one <li>?
-- EDIT --
Hi!
Can anybody else help with this? I've tried the solution by Greg and I've also tried:
if (banners<1) {
.anythingSlider({
startStopped: true,
buildNavigation: false
});
}
'banners' is my variable that I'm calling.
And this disables the anythingSlider function altogether.
Help please?!
-- EDIT 2 --
The original code is in the page of the html
<script type="text/javascript">
var banners=[];
banners[0]="http://image.ebuyer.com/customer/promos/UK/AcerAspire5536.jpg";
//banners[1]="http://image.ebuyer.com/customer/promos/2150/banner.jpg";
//banners[2]="http://image.ebuyer.com/customer/promos/UK/257653_FerrariOne_tb20091026.jpg";
//banners[3]="http://image.ebuyer.com/customer/promos/UK/247038_compaq_images/247038_compaq_incentive_banner20090814.jpg"; //added 03/09/2009
//banners[4]="http://image.ebuyer.com/customer/promos/UK/247858-samsung-tv-comp-tb20090817.jpg"; //added 19/08/2009
var bannerLink=[];
bannerLink[0]="http://www.ebuyer.com/product/173536";
//bannerLink[1]="/special/2150";
//bannerLink[2]="/product/172295";
//bannerLink[3]="/compaq-cash-incentive";
//bannerLink[4]="/special/2101";
var bannerAlt=[];
bannerAlt[0]="Acer Aspire 5536";
//bannerAlt[1]="The X5 range for Asus";
//bannerAlt[2]="Acer Ferrari One Laptop";
//bannerAlt[3]="Buy these three products together and claim £75 cashback";
//bannerAlt[4]="Win a Samsung 46in LCV TV";
</script>
It's then being actioned by this file: http://image.ebuyer.com/customer/promos/js/topbanners.js
// function to import css and javascript from external locations
function loadjscssfile(filename, filetype){
if (filetype=="js"){ //if filename is a external JavaScript file
var fileref=document.createElement('script')
fileref.setAttribute("type","text/javascript")
fileref.setAttribute("src", filename)
}
else if (filetype=="css"){ //if filename is an external CSS file
var fileref=document.createElement("link")
fileref.setAttribute("rel", "stylesheet")
fileref.setAttribute("type", "text/css")
fileref.setAttribute("href", filename)
}
if (typeof fileref!="undefined")
document.getElementsByTagName("head")[0].appendChild(fileref)
}
// importing css and javascript
loadjscssfile("http://static.ebuyer.com/css/slider.css", "css") ////dynamically load and add this .css file
// setting the variables
var banner = document.getElementById('tehBanner');
var link = document.getElementById('tehLink');
// this function creates the tracking tags
function tracking (x) {
if (x.indexOf("?")>=0){x+='&tb='+(i+1);}else{x+='?tb='+(i+1);}
return x
}
// telling the javascript to display all available variables
for (var i in banners) {
banner.alt = bannerAlt[i];
link.href = tracking(bannerLink[i]);
banner.src = banners[i];
document.write('' + '<img src="' + banners[i] + '" id="slide-image" alt="' + bannerAlt[i] + '" />');
}
// remove the original banner
$ ('a#tehLink').parent().remove();
// hide banners to begin with
$('a.slide-link').hide();
/*
anythingSlider v1.1
By Chris Coyier: http://css-tricks.com
with major improvements by Doug Neiner: http://pixelgraphics.us/
based on work by Remy Sharp: http://jqueryfordesigners.com/
To use the navigationFormatter function, you must have a function that
accepts two paramaters, and returns a string of HTML text.
index = integer index (1 based);
panel = jQuery wrapped LI item this tab references
#return = Must return a string of HTML/Text
navigationFormatter: function(index, panel){
return index + " Panel"; // This would have each tab with the text 'X Panel' where X = index
}
*/
(function($){
$.anythingSlider = function(el, options){
// To avoid scope issues, use 'base' instead of 'this'
// to reference this class from internal events and functions.
var base = this;
// Access to jQuery and DOM versions of element
base.$el = $(el);
base.el = el;
// Set up a few defaults
base.currentPage = 1;
base.timer = null;
base.playing = false;
// Add a reverse reference to the DOM object
base.$el.data("AnythingSlider", base);
base.init = function(){
base.options = $.extend({},$.anythingSlider.defaults, options);
// Cache existing DOM elements for later
base.$wrapper = base.$el.find('> div').css('overflow', 'hidden');
base.$slider = base.$wrapper.find('> ul');
base.$items = base.$slider.find('> li');
base.$single = base.$items.filter(':first');
// Build the navigation if needed
if(base.options.buildNavigation) base.buildNavigation();
// Get the details
base.singleWidth = base.$single.outerWidth();
base.pages = base.$items.length;
// Top and tail the list with 'visible' number of items, top has the last section, and tail has the first
// This supports the "infinite" scrolling
base.$items.filter(':first').before(base.$items.filter(':last').clone().addClass('cloned'));
base.$items.filter(':last' ).after(base.$items.filter(':first').clone().addClass('cloned'));
// We just added two items, time to re-cache the list
base.$items = base.$slider.find('> li'); // reselect
// Setup our forward/backward navigation
base.buildNextBackButtons();
// If autoPlay functionality is included, then initialize the settings
if(base.options.autoPlay) {
base.playing = !base.options.startStopped; // Sets the playing variable to false if startStopped is true
base.buildAutoPlay();
};
// If pauseOnHover then add hover effects
if(base.options.pauseOnHover) {
base.$el.hover(function(){
base.clearTimer();
}, function(){
base.startStop(base.playing);
});
}
// If a hash can not be used to trigger the plugin, then go to page 1
if((base.options.hashTags == true && !base.gotoHash()) || base.options.hashTags == false){
base.setCurrentPage(1);
};
};
base.gotoPage = function(page, autoplay){
// When autoplay isn't passed, we stop the timer
if(autoplay !== true) autoplay = false;
if(!autoplay) base.startStop(false);
if(typeof(page) == "undefined" || page == null) {
page = 1;
base.setCurrentPage(1);
};
// Just check for bounds
if(page > base.pages + 1) page = base.pages;
if(page < 0 ) page = 1;
var dir = page < base.currentPage ? -1 : 1,
n = Math.abs(base.currentPage - page),
left = base.singleWidth * dir * n;
base.$wrapper.filter(':not(:animated)').animate({
scrollLeft : '+=' + left
}, base.options.animationTime, base.options.easing, function () {
if (page == 0) {
base.$wrapper.scrollLeft(base.singleWidth * base.pages);
page = base.pages;
} else if (page > base.pages) {
base.$wrapper.scrollLeft(base.singleWidth);
// reset back to start position
page = 1;
};
base.setCurrentPage(page);
});
};
base.setCurrentPage = function(page, move){
// Set visual
if(base.options.buildNavigation){
base.$nav.find('.cur').removeClass('cur');
$(base.$navLinks[page - 1]).addClass('cur');
};
// Only change left if move does not equal false
if(move !== false) base.$wrapper.scrollLeft(base.singleWidth * page);
// Update local variable
base.currentPage = page;
};
base.goForward = function(autoplay){
if(autoplay !== true) autoplay = false;
base.gotoPage(base.currentPage + 1, autoplay);
};
base.goBack = function(){
base.gotoPage(base.currentPage - 1);
};
// This method tries to find a hash that matches panel-X
// If found, it tries to find a matching item
// If that is found as well, then that item starts visible
base.gotoHash = function(){
if(/^#?panel-\d+$/.test(window.location.hash)){
var index = parseInt(window.location.hash.substr(7));
var $item = base.$items.filter(':eq(' + index + ')');
if($item.length != 0){
base.setCurrentPage(index);
return true;
};
};
return false; // A item wasn't found;
};
// Creates the numbered navigation links
base.buildNavigation = function(){
base.$nav = $("<div id='thumbNav'></div>").appendTo(base.$el);
base.$items.each(function(i,el){
var index = i + 1;
var $a = $("<a href='#'></a>");
// If a formatter function is present, use it
if( typeof(base.options.navigationFormatter) == "function"){
$a.html(base.options.navigationFormatter(index, $(this)));
} else {
$a.text(index);
}
$a.click(function(e){
base.gotoPage(index);
if (base.options.hashTags)
base.setHash('panel-' + index);
e.preventDefault();
});
base.$nav.append($a);
});
base.$navLinks = base.$nav.find('> a');
};
// Creates the Forward/Backward buttons
base.buildNextBackButtons = function(){
var $forward = $('<a class="arrow forward">></a>'),
$back = $('<a class="arrow back"><</a>');
// Bind to the forward and back buttons
$back.click(function(e){
base.goBack();
e.preventDefault();
});
$forward.click(function(e){
base.goForward();
e.preventDefault();
});
// Append elements to page
base.$wrapper.after($back).after($forward);
};
// Creates the Start/Stop button
base.buildAutoPlay = function(){
base.$startStop = $("<a href='#' id='start-stop'></a>").html(base.playing ? base.options.stopText : base.options.startText);
base.$el.append(base.$startStop);
base.$startStop.click(function(e){
base.startStop(!base.playing);
e.preventDefault();
});
// Use the same setting, but trigger the start;
base.startStop(base.playing);
};
// Handles stopping and playing the slideshow
// Pass startStop(false) to stop and startStop(true) to play
base.startStop = function(playing){
if(playing !== true) playing = false; // Default if not supplied is false
// Update variable
base.playing = playing;
// Toggle playing and text
base.$startStop.toggleClass("playing", playing).html( playing ? base.options.stopText : base.options.startText );
if(playing){
base.clearTimer(); // Just in case this was triggered twice in a row
base.timer = window.setInterval(function(){
base.goForward(true);
}, base.options.delay);
} else {
base.clearTimer();
};
};
base.clearTimer = function(){
// Clear the timer only if it is set
if(base.timer) window.clearInterval(base.timer);
};
// Taken from AJAXY jquery.history Plugin
base.setHash = function ( hash ) {
// Write hash
if ( typeof window.location.hash !== 'undefined' ) {
if ( window.location.hash !== hash ) {
window.location.hash = hash;
};
} else if ( location.hash !== hash ) {
location.hash = hash;
};
// Done
return hash;
};
// <-- End AJAXY code
// Trigger the initialization
base.init();
};
$.anythingSlider.defaults = {
easing: "swing", // Anything other than "linear" or "swing" requires the easing plugin
autoPlay: true, // This turns off the entire FUNCTIONALY, not just if it starts running or not
startStopped: false, // If autoPlay is on, this can force it to start stopped
delay: 3000, // How long between slide transitions in AutoPlay mode
animationTime: 600, // How long the slide transition takes
hashTags: true, // Should links change the hashtag in the URL?
buildNavigation: true, // If true, builds and list of anchor links to link to each slide
pauseOnHover: true, // If true, and autoPlay is enabled, the show will pause on hover
startText: "Start", // Start text
stopText: "Stop", // Stop text
navigationFormatter: null // Details at the top of the file on this use (advanced use)
};
$.fn.anythingSlider = function(options){
if(typeof(options) == "object"){
return this.each(function(i){
(new $.anythingSlider(this, options));
// This plugin supports multiple instances, but only one can support hash-tag support
// This disables hash-tags on all items but the first one
options.hashTags = false;
});
} else if (typeof(options) == "number") {
return this.each(function(i){
var anySlide = $(this).data('AnythingSlider');
if(anySlide){
anySlide.gotoPage(options);
}
});
}
};
})(jQuery);
// this function wraps the elements in the neccessary tags to work with anything Slider
$ (document).ready(function() {
$('a.slide-link')
.wrap('<li class="slide-list-item"></li>');
$('li.slide-list-item')
.wrapAll('<ul id="slide-list"></ul>');
$('ul#slide-list')
.wrapAll('<div class="wrapper"></div>');
$('div.wrapper')
.wrapAll('<div class="anythingSlider internalSlider"></div>');
$('.anythingSlider')
.anythingSlider({
easing: "swing", // Anything other than "linear" or "swing" requires the easing plugin
autoPlay: true, // This turns off the entire FUNCTIONALY, not just if it starts running or not
startStopped: false, // If autoPlay is on, this can force it to start stopped
delay: 7000, // How long between slide transitions in AutoPlay mode
animationTime: 600, // How long the slide transition takes
hashTags: false, // Should links change the hashtag in the URL?
buildNavigation: true, // If true, builds and list of anchor links to link to each slide
pauseOnHover: true, // If true, and autoPlay is enabled, the show will pause on hover
startText: "Start", // Start text
stopText: "Stop", // Stop text
navigationFormatter: null // Details at the top of the file on this use (advanced use)
});
$('a.slide-link').show();
});
It's a bit of a hash job but works fine as long as there's more than one <li>
Try this:
// this function wraps the elements in the neccessary tags to work with anything Slider
$ (document).ready(function() {
$('a.slide-link')
.wrap('<li class="slide-list-item"></li>');
$('li.slide-list-item')
.wrapAll('<ul id="slide-list"></ul>');
$('ul#slide-list')
.wrapAll('<div class="wrapper"></div>');
$('div.wrapper')
.wrapAll('<div class="anythingSlider internalSlider"></div>');
if(banners.length > 1){
autoplayval= true;
} else {
autoplayval= false;
}
$('.anythingSlider')
.anythingSlider({
easing: "swing", // Anything other than "linear" or "swing" requires the easing plugin
autoPlay: autoplayval, // This turns off the entire FUNCTIONALY, not just if it starts running or not
startStopped: false, // If autoPlay is on, this can force it to start stopped
delay: 7000, // How long between slide transitions in AutoPlay mode
animationTime: 600, // How long the slide transition takes
hashTags: false, // Should links change the hashtag in the URL?
buildNavigation: true, // If true, builds and list of anchor links to link to each slide
pauseOnHover: true, // If true, and autoPlay is enabled, the show will pause on hover
startText: "Start", // Start text
stopText: "Stop", // Stop text
navigationFormatter: null // Details at the top of the file on this use (advanced use)
});
$('a.slide-link').show();
});
Changing this
$('.anythingSlider').anythingSlider({...});
to this
$('.anythingSlider:has(li:nth-child(2)').anythingSlider({...});
should do it
This assumes you don't have nested lists.
I had this problem and could only resolve this with a new version of the plugin: v1.5.3
URL: https://github.com/ProLoser/AnythingSlider/downloads
Once you've got the latest version, only change one line:
base.setCurrentPage(startPanel, false); // added to trigger events for FX code
When I have only one <li> the anythingControls element's style is display=none.
This will only activate the slider if more than 1 <LI> elements are present:
jQuery("#sliderDiv:has(>li:eq(1))").anythingSlider({...})
it assumes your HTML structure is like this:
<div id="sliderDiv">
<li>Offer 1</li>
<li>Offer 2</li>
</div>
You'll need something like
if($([ULELEMENT]).children('li').length > 1){
//Your code
}
Something along those lines. If you post your code, I can give it a try.