I have some jQuery that works great when one carousel is on the page. I need to have two carousels in the same page and it's currently not working. Can someone please tell me how to make it work?
var Carousel = (function($) {
var $carousel = $('.carousel');
var activeItemIndex = 0;
var s;
return {
settings: {
delay: 10000,
items: $carousel.find('.carousel__item'),
totalItems: 0,
dots: $carousel.find('.carousel__dots'),
dotLinks: $carousel.find('.carousel__dot-link'),
timeout: 0,
},
init: function(args) {
if ($carousel.length) {
s = $.extend({}, this.settings, args);
s.totalItems = s.items.length;
if (s.totalItems > 1) {
this.setupDotsData();
this.activate();
this.eventListeners();
$carousel.addClass('active');
}
}
},
eventListeners: function() {
s.dotLinks.on('click', function() {
var index = $(this).data('index');
Carousel.stop();
Carousel.show(index);
});
},
setupDotsData: function() {
s.dots.each(function() {
$(this).find('li').each(function(index) {
$(this).data('index', index);
});
});
},
activate: function() {
if (s.totalItems > 1) {
Carousel.show(0);
} else {
s.items.eq(0).addClass('active');
}
},
show: function(index) {
s.items.removeClass('active');
s.dotLinks.removeClass('active');
s.items.eq(index).addClass('active');
s.dotLinks.filter(':nth-child(' + (index + 1) + ')').addClass('active');
activeItemIndex = index;
Carousel.play();
},
next: function(e) {
var nextItemIndex = activeItemIndex + 1 >= s.totalItems ? 0 : activeItemIndex + 1;
e && e.preventDefault();
Carousel.stop();
Carousel.show(nextItemIndex);
},
play: function() {
s.timeout = window.setTimeout(Carousel.next, s.delay);
},
stop: function() {
window.clearTimeout(s.timeout);
}
};
})(jQuery);
Carousel.init();
Example on JSFIDDLE
You need some modifications for handling multiple instance of Carousel:
https://jsfiddle.net/dmz7wk6f/7/
Try this (loop through each carousel, grab the id and initialize it):
Fiddle: https://jsfiddle.net/4o00o7n6/
$(".carousel").each(function(x){
var carouselId = $(this).attr('id');
var Carousel = (function($) {
'use strict';
//var wrap = $('.carousel');
var wrap = $('#' + carouselId);
var activeItemIndex = 0;
var s;
return {
settings: {
delay: 10000,
items: wrap.find('.carousel__item'),
totalItems: 0,
dots: wrap.find('.carousel__dots'),
dotLinks: wrap.find('.carousel__dot-link'),
timeout: 0,
},
init: function(args) {
if (wrap && wrap.length) {
s = $.extend({}, this.settings, args);
s.totalItems = s.items.length;
if (s.totalItems > 1) {
this.setupDotsData();
this.activate();
this.eventListeners();
wrap.addClass('active');
}
}
},
eventListeners: function() {
s.dotLinks.on('click', function() {
var index = $(this).data('index');
Carousel.stop();
Carousel.show(index);
});
},
setupDotsData: function() {
s.dots.each(function() {
$(this).find('li').each(function(index) {
$(this).data('index', index);
});
});
},
activate: function() {
if (s.totalItems > 1) {
Carousel.show(0);
} else {
s.items.eq(0).addClass('active');
}
},
show: function(index) {
s.items.removeClass('active');
s.dotLinks.removeClass('active');
s.items.eq(index).addClass('active');
s.dotLinks.filter(':nth-child(' + (index + 1) + ')').addClass('active');
activeItemIndex = index;
Carousel.play();
},
next: function(e) {
var nextItemIndex = activeItemIndex + 1 >= s.totalItems ? 0 : activeItemIndex + 1;
e && e.preventDefault();
Carousel.stop();
Carousel.show(nextItemIndex);
},
play: function() {
s.timeout = window.setTimeout(Carousel.next, s.delay);
},
stop: function() {
window.clearTimeout(s.timeout);
}
};
})(jQuery);
Carousel.init();
});
Related
I am testing my page in Chrome. I right click on the element that I am having issues with and I get this:
element.style {
height: 147px;
position: relative;
width: 100%;
overflow: hidden;
}
without a file attached to it. This tells me that the element style is coming from either an inline code (my page has none) or a js file (which my page has a number).
When I turn off the position: relative, I no longer have any issues.
I think I have narrowed it down to one js file that is screwing up my page, but I don't have a clue as to how to fix it or how to figure it out.
Here are some images better describing the issue:
http://i.imgur.com/Yxv2zLe.png
http://i.imgur.com/wtqkqw5.png
If you look at the first image, the blue box over the image needs to be directly over the orange box so that everything lines up properly.
In the second image, when I turn off the position, the image is positions correctly under the overlay.
My problem is that I don't know enough about js to fix the code to fix the position.
Here is the code that I think is responsible, if it helps.
/* ---------------------------------------------------------------------- */
/* Entry Slider
/* ---------------------------------------------------------------------- */
if ($().cycle) {
var entrySliders = $('.entry-slider > ul');
$.fn.cycle.transitions.scrollHorizontal = function ($cont, $slides, opts) {
$cont.css('overflow', 'hidden');
opts.before.push($.fn.cycle.commonReset);
var w = $cont.width();
opts.cssFirst.left = 0;
opts.cssBefore.left = w;
opts.cssBefore.top = 0;
opts.animIn.left = 0;
opts.animOut.left = 0 - w;
if ($cont.data('dir') === 'prev') {
opts.cssBefore.left = -w;
opts.animOut.left = w;
}
};
function initEntrySlider(entrySliders, isFirstTime) {
entrySliders.each(function (i) {
var slider = $(this);
var initPerformed = isFirstTime && slider.data('initInvoked');
if (!initPerformed) {
slider.data('initInvoked', 'true');
var sliderId = 'entry-slider-' + i;
slider.attr('id', sliderId);
var prevButtonId = sliderId + '-prev';
var nextButtonId = sliderId + '-next';
if (slider.data('enable') === 'false') {
return;
}
slider.css('height', slider.children('li:first').height());
var firstSlide = slider.children('li')[0];
var lastSlide = slider.children('li')[slider.children('li').length - 1];
if (slider.children('li').length > 1) {
if (slider.parent().find('#' + prevButtonId).length == 0) {
slider.parent().append('<div class="entry-slider-nav"><a id="' + prevButtonId + '" class="prev">Prev</a><a id="' + nextButtonId + '" class="next">Next</a></div>');
}
}
slider.cycle({
onPrevNextEvent: function (isNext, zeroBasedSlideIndex, slideElement) {
$(slideElement).parent().data('dir', isNext ? 'next' : 'prev');
},
before: function (curr, next, opts, forwardFlag) {
var $this = $(this);
var sliderId = $this.closest('ul').attr('id');
// set the container's height to that of the current slide
$this.parent().stop().animate({height: $this.height()}, opts.speed);
if (opts['nowrap']) {
var prevButton = $('#' + sliderId + '-prev');
var nextButton = $('#' + sliderId + '-next');
if ((firstSlide == next) && (!prevButton.hasClass('disabled'))) {
prevButton.addClass('disabled');
} else {
prevButton.removeClass('disabled');
}
if ((lastSlide == next) && (!nextButton.hasClass('disabled'))) {
nextButton.addClass('disabled');
} else {
nextButton.removeClass('disabled');
}
}
},
containerResize: false,
pauseOnPagerHover: true,
nowrap: false, // if true, the carousel will not be circular
easing: 'easeInOutExpo',
fx: 'scrollHorizontal',
speed: 600,
timeout: 0,
fit: true,
width: '100%',
pause: true,
slideResize: true,
slideExpr: 'li',
prev: '#' + prevButtonId,
next: '#' + nextButtonId
});
}
});
if (Modernizr.touch && $().swipe) {
function doEntrySliderSwipe(e, dir) {
var sliderId = $(e.currentTarget).attr('id');
if (dir == 'left') {
$('#' + sliderId + '-next').trigger('click');
}
if (dir == 'right') {
$('#' + sliderId + '-prev').trigger('click');
}
}
entrySliders.each(function () {
var slider = $(this);
var initPerformed = isFirstTime && slider.data('swipeInvoked');
if (!initPerformed) {
slider.data('swipeInvoked', 'true');
slider.swipe({
click: function (e, target) {
$(target).trigger('click');
},
swipeLeft: doEntrySliderSwipe,
swipeRight: doEntrySliderSwipe,
allowPageScroll: 'auto'
});
}
});
}
}
function initAllEntrySliders(isFirstTime) {
if (isFirstTime) {
var timer = window.setTimeout(function () {
window.clearTimeout(timer);
initEntrySlider($('.entry-slider > ul'), isFirstTime);
}, 100);
} else {
initEntrySlider($('.entry-slider > ul'), isFirstTime);
}
}
function resizeEntrySlider(entrySliders) {
entrySliders.each(function () {
var slider = $(this);
slider.css('height', slider.children('li:first').height());
});
}
function loadEntrySlider() {
var entrySliderImages = $('.entry-slider > ul > li> a > img');
var unloadedImagesCount = 0;
var unloadedImages = [];
entrySliderImages.each(function () {
if (!this.complete && this.complete != undefined) {
unloadedImages.push(this);
unloadedImagesCount++;
}
});
if (unloadedImagesCount == 0) {
initAllEntrySliders(true);
} else {
var initAllEntrySlidersInvoked = false;
var loadedImagesCount = 0;
$(unloadedImages).bind('load', function () {
loadedImagesCount++;
if (loadedImagesCount === unloadedImagesCount) {
if (!initAllEntrySlidersInvoked) {
initAllEntrySlidersInvoked = true;
initAllEntrySliders(true);
}
}
});
var timer = window.setTimeout(function () {
window.clearTimeout(timer);
$(unloadedImages).each(function () {
if (this.complete || this.complete === undefined) {
$(this).trigger('load');
}
});
}, 50);
}
}
loadEntrySlider();
$(window).on('resize', function () {
var timer = window.setTimeout(function () {
window.clearTimeout(timer);
resizeEntrySlider(entrySliders);
}, 30);
});
}
And if I should be asking this somewhere else or something, let me know.
Before I get into details, please take a look at the live example where this problem occurs - http://jsfiddle.net/66HFU/ (Script code at the bottom of this post)
Now if you would click on any image at last row, it would display these. However if you would click on upper row images, below row images are shown.
Further investigation shows that for somewhat reason the letter called function selector elements only get binded with event listener while the firstly called functions selector elements do not.
So, I would like to know is there are any ways to make the function call independent so the latter function call does not override first one (if that would fix the problem, of-course)?
The place where the event function gets bind on the element can be found in function f_AddEvents first lines.
And the the main function calls that are used to initialize Light Box is at the bottom of the code like this:
LightBox.init({
selector: "[data-simplbox='demo1']",
boxId: "simplbox"
});
LightBox.init({
selector: "[data-simplbox='demo2']",
boxId: "simplbox",
imageLoadStart: activityIndicatorOn,
imageLoadEnd: activityIndicatorOff
});
All code:
;(function (window, document, undefined) {
var docElem = document.documentElement;
var DomM = (function() {
var f_ToDOMStyle = function (p_Style) {
return p_Style.replace(/\-[a-z]/g, function (p_Style) {
return p_Style.charAt(1).toUpperCase();
});
};
return {
event: {
set: function (p_Element, p_Events, p_Function) {
var i = 0,
j = 0;
p_Events = p_Events.split(" ");
if (!p_Element.length) {
for (i = 0; i < p_Events.length; i++) {
p_Element.addEventListener(p_Events[i], p_Function, false);
}
} else {
for (i = 0; i < p_Element.length; i++) {
for (j = 0; j < p_Events.length; j++) {
p_Element[i].addEventListener(p_Events[j], p_Function, false);
}
}
}
}
},
css: {
set: function (p_Element, p_Style) {
var j;
if (!p_Element.length) {
for (j in p_Style) {
if (p_Style.hasOwnProperty(j)) {
j = f_ToDOMStyle(j);
p_Element.style[j] = p_Style[j];
}
}
} else {
for (var i = 0; i < p_Element.length; i++) {
for (j in p_Style) {
if (p_Style.hasOwnProperty(j)) {
j = f_ToDOMStyle(j);
p_Element[i].style[j] = p_Style[j];
}
}
}
}
}
}
};
}());
var _LightBox = {
f_MergeObjects: function (p_Original, p_Updates) {
for (var i in p_Updates) {
if (p_Updates.hasOwnProperty(i)) {
p_Original[i] = p_Updates[i];
}
}
return p_Original;
},
f_isFunction: function (p_Function) {
return !!(p_Function && p_Function.constructor && p_Function.call && p_Function.apply);
},
f_Initialize: function (p_Options) {
var base = this;
base.m_Options = base.f_MergeObjects(_LightBox.options, p_Options || {});
base.m_Elements = document.querySelectorAll(base.m_Options.selector);
base.m_ElementsLength = base.m_Elements.length - 1;
base.m_Body = document.getElementsByTagName("body")[0];
base.m_CurrentImageElement = false;
base.m_CurrentImageNumber = 0;
base.m_Direction = 1;
base.m_InProgress = false;
base.m_InstalledImageBox = false;
console.log(base.m_Elements);
// Check if hardware acceleration is supported and check if touch is enabled.
base.f_CheckBrowser();
// Adds events.
base.f_AddEvents();
},
f_CheckBrowser: function () {
var base = this,
isTouch = "ontouchstart" in window || window.navigator.msMaxTouchPoints || navigator.maxTouchPoints || false,
vendors = ["ms", "O", "Moz", "Webkit", "Khtml"],
rootStyle = docElem.style,
hardwareAccelerated = false;
if ("transform" in rootStyle) {
hardwareAccelerated = true;
} else {
while (vendors.length) {
if (vendors.pop() + "Transform" in rootStyle) {
hardwareAccelerated = true;
}
}
}
base.browser = {
"isHardwareAccelerated": hardwareAccelerated,
"isTouch": isTouch
};
},
f_AddEvents: function () {
var base = this;
// Add open image event on images.
for (var i = 0; i < base.m_Elements.length; i++) {
(function (i) {
base.m_Elements[i].addEventListener("click", function (event) {
event.preventDefault();
console.log(base.m_Elements[i]);
if (base.f_isFunction(base.m_Options.onImageStart)) {
base.m_Options.onImageStart();
}
base.f_OpenImage(i);
}, false);
})(i);
}
// Resize event for window.
window.addEventListener("resize", function (event) {
event.preventDefault();
base.f_SetImage();
}, false);
// Add keyboard support.
if (base.m_Options.enableKeyboard) {
var keyBoard = {
left: 37,
right: 39,
esc: 27
};
window.addEventListener("keydown", function (event) {
event.preventDefault();
if (base.m_CurrentImageElement) {
if (base.m_InProgress) {
return false;
}
switch (event.keyCode) {
case keyBoard.left:
// If the previous one is out of target range then go to the last image.
if ((base.m_CurrentImageNumber - 1) < 0) {
base.f_OpenImage(base.m_ElementsLength, "left");
} else {
base.f_OpenImage(base.m_CurrentImageNumber - 1, "left");
}
return false;
case keyBoard.right:
// If the next one is out of target range then go to the first image.
if ((base.m_CurrentImageNumber + 1) > base.m_ElementsLength) {
base.f_OpenImage(0, "right");
} else {
base.f_OpenImage(base.m_CurrentImageNumber + 1, "right");
}
return false;
case keyBoard.esc:
base.f_QuitImage();
return false;
}
}
return false;
}, false);
}
// Add document click event.
if (base.m_Options.quitOnDocumentClick) {
document.body.addEventListener("click", function (event) {
var target = event.target ? event.target : event.srcElement;
event.preventDefault();
if (target && target.id != "imagelightbox" && base.m_CurrentImageElement && !base.m_InProgress && base.m_InstalledImageBox) {
base.f_QuitImage();
return false;
}
return false;
}, false);
}
},
f_OpenImage: function (p_WhichOne, p_Direction) {
var base = this,
newFragment = document.createDocumentFragment(),
newImageElement = document.createElement("img"),
target = base.m_Elements[p_WhichOne].getAttribute("href");
if (base.m_CurrentImageElement) {
base.f_RemoveImage();
}
if (base.f_isFunction(base.m_Options.imageLoadStart)) {
base.m_Options.imageLoadStart();
}
base.m_InProgress = true;
base.m_InstalledImageBox = false;
base.m_Direction = typeof p_Direction === "undefined" ? 1 : p_Direction == "left" ? -1 : 1;
newImageElement.setAttribute("src", target);
newImageElement.setAttribute("alt", "LightBox");
newImageElement.setAttribute("id", base.m_Options.boxId);
newFragment.appendChild(newImageElement);
base.m_Body.appendChild(newFragment);
base.m_CurrentImageElement = document.getElementById(base.m_Options.boxId);
base.m_CurrentImageElement.style.opacity = "0";
base.m_CurrentImageNumber = p_WhichOne;
if (base.m_Options.quitOnImageClick) {
base.f_ImageClickEvent = function (event) {
event.preventDefault();
base.f_QuitImage();
};
base.m_CurrentImageElement.addEventListener("click", base.f_ImageClickEvent, false);
}
if (base.browser.isHardwareAccelerated) {
DomM.css.set(base.m_CurrentImageElement, base.f_AddTransitionSpeed(base.m_Options.animationSpeed));
}
base.f_SetImage();
DomM.css.set(base.m_CurrentImageElement, base.f_doTranslateX(50 * base.m_Direction + "px"));
setTimeout(function () {
if (base.browser.isHardwareAccelerated) {
setTimeout(function () {
DomM.css.set(base.m_CurrentImageElement, base.f_doTranslateX("0px"));
}, 50);
}
if (base.f_isFunction(base.m_Options.imageLoadEnd)) {
base.m_Options.imageLoadEnd();
}
}, 20);
setTimeout(function () {
base.m_InProgress = false;
base.m_InstalledImageBox = true;
}, base.m_Options.animationSpeed - 200);
},
f_SetImage: function () {
var base = this,
screenHeight = window.innerHeight || docElem.offsetHeight,
screenWidth = window.innerWidth || docElem.offsetWidth,
tmpImage = new Image(),
imageWidth, imageHeight, imageSizeRatio;
if (!base.m_CurrentImageElement) {
return;
}
tmpImage.onload = function () {
imageWidth = this.width;
imageHeight = this.height;
imageSizeRatio = imageWidth / imageHeight;
if (Math.floor(screenWidth/imageSizeRatio) > screenHeight) {
imageWidth = screenHeight * imageSizeRatio * 0.7;
imageHeight = screenHeight * 0.7;
} else {
imageWidth = screenWidth * 0.7;
imageHeight = screenWidth / imageSizeRatio * 0.7;
}
DomM.css.set(base.m_CurrentImageElement, {
"top": ((screenHeight - imageHeight) / 2) + "px",
"left": ((screenWidth - imageWidth) / 2) + "px",
"width": Math.floor(imageWidth) + "px",
"height": Math.floor(imageHeight) + "px",
"opacity": 1
});
};
tmpImage.src = base.m_CurrentImageElement.getAttribute("src");
},
f_RemoveImage: function () {
var base = this;
if (base.m_CurrentImageElement) {
if (base.f_isFunction(base.m_Options.quitOnImageClick)) {
base.m_CurrentImageElement.removeEventListener("click", base.f_ImageClickEvent, false);
}
base.m_CurrentImageElement.parentNode.removeChild(base.m_CurrentImageElement);
base.m_CurrentImageElement = false;
}
return false;
},
f_QuitImage: function () {
var base = this;
if (base.m_CurrentImageElement) {
setTimeout(function () {
DomM.css.set(base.m_CurrentImageElement, {
"opacity": 0,
"transition": ("opacity " + base.m_Options.fadeOutSpeed + "ms ease")
});
setTimeout(function () {
base.f_RemoveImage();
if (base.f_isFunction(base.m_Options.onImageQuit)) {
base.m_Options.onImageQuit();
}
}, base.m_Options.fadeOutSpeed);
}, 20);
}
},
f_IsValidSource: function (p_Src) {
return new RegExp().test(p_Src);
},
f_doTranslateX: function (p_Pixels) {
return {
"-webkit-transform": "translateX(" + p_Pixels + ")",
"-moz-transform": "translateX(" + p_Pixels + ")",
"-o-transform": "translateX(" + p_Pixels + ")",
"-ms-transform": "translateX(" + p_Pixels + ")",
"transform": "translateX(" + p_Pixels + ")"
};
},
f_AddTransitionSpeed: function (p_Speed) {
var base = this;
return {
"-webkit-transition": "transform " + p_Speed + "ms ease, opacity " + base.m_Options.fadeInSpeed + "ms ease",
"-moz-transition": "transform " + p_Speed + "ms ease, opacity " + base.m_Options.fadeInSpeed + "ms ease",
"-o-transition": "transform " + p_Speed + "ms ease, opacity " + base.m_Options.fadeInSpeed + "ms ease",
"transition": "transform " + p_Speed + "ms ease, opacity " + base.m_Options.fadeInSpeed + "ms ease"
};
}
};
_LightBox.options = {
selector: "[data-imagelightbox]",
boxId: "imagelightbox",
allowedTypes: "png|jpg|jpeg|gif",
quitOnImageClick: true,
quitOnDocumentClick: true,
enableKeyboard: true,
animationSpeed: 750,
fadeInSpeed: 500,
fadeOutSpeed: 200,
imageLoadStart: function () {},
imageLoadEnd: function () {},
onImageQuit: function () {},
onImageStart: function () {}
};
LightBox.init = function (p_Options) {
_LightBox.f_Initialize(p_Options);
};
})(window, document, window.LightBox = window.LightBox || {});
var activityIndicatorOn = function () {
var newE = document.createElement("div"),
newB = document.createElement("div");
newE.setAttribute("id", "imagelightbox-loading");
newE.appendChild(newB);
document.body.appendChild(newE);
},
activityIndicatorOff = function () {
var elE = document.getElementById("imagelightbox-loading");
elE.parentNode.removeChild(elE);
};
LightBox.init({
selector: "[data-simplbox='demo1']",
boxId: "simplbox"
});
LightBox.init({
selector: "[data-simplbox='demo2']",
boxId: "simplbox",
imageLoadStart: activityIndicatorOn,
imageLoadEnd: activityIndicatorOff
});
Your code is almost working. What you handled badly is the fact that you can perform several init. On each init, you overwrite some items, especially with this line :
base.m_Elements = document.querySelectorAll(base.m_Options.selector);
So base.m_Elements will only have the elements of the last init.
( Based on the name 'init' i wonder if the real use case wouldn't be to allow just one call of init... )
Quick-fix is to do one single init with :
LightBox.init({
selector: "[data-simplbox='demo1'],[data-simplbox='demo2']",
boxId: "simplbox"
});
(erase the two calls to init)
And here it works.
http://jsfiddle.net/gamealchemist/66HFU/1/
So i guess either you want to support several init, or (easier to maintain in fact), throw exception on multiple init and expect the lib user to write the right selector in the single init call.
Edit : Super quick fix for your issue : rather than having LightBox as a singleton, have it as a Class :
function LightBox( initArguments ) {
// something like what was done in init
}
LightBox.prototype = {
f_RemoveImage : function() {
} ,
f_OpenImage : function( ..., ... ) {
} ,
...
}
then you can call with no issue :
var demo1LB = new LightBox({ selector: "[data-simplbox='demo1']",
boxId: "simplbox" });
var demo2LB = new LightBox({ selector: "[data-simplbox='demo2']",
boxId: "simplbox" });
Still very new at Javascript and jQuery, so this one is tough for me.
I'm using this Bootstrap Lightbox plugin: https://github.com/duncanmcdougall/Responsive-Lightbox
Trying to use it on this site (WIP): http://lastdetailwd.com/modernmetalfabricators/furniture.html
I'm looking to use the title attribute from the A tags as captions for this lightbox. Any clue on how to get this done?
jQuery:
(function ($) {
'use strict';
$.fn.lightbox = function (options) {
var opts = {
margin: 50,
nav: true,
blur: true,
minSize: 0
};
var plugin = {
items: [],
lightbox: null,
image: null,
current: null,
locked: false,
selector: "#lightbox",
init: function (items) {
plugin.items = items;
plugin.selector = "lightbox-"+Math.random().toString().replace('.','');
if (!plugin.lightbox) {
$('body').append(
'<div id="lightbox" class='+plugin.selector+' style="display:none;">'+
'' +
'<div class="lightbox-nav">'+
'' +
'' +
'</div>' +
'</div>'
);
plugin.lightbox = $("."+plugin.selector);
}
if (plugin.items.length > 1 && opts.nav) {
$('.lightbox-nav', plugin.lightbox).show();
} else {
$('.lightbox-nav', plugin.lightbox).hide();
}
plugin.bindEvents();
},
loadImage: function () {
if(opts.blur) {
$("body").addClass("blurred");
}
$("img", plugin.lightbox).remove();
plugin.lightbox.fadeIn('fast').append('<span class="lightbox-loading"></span>');
var img = $('<img src="' + $(plugin.current).attr('href') + '" draggable="false">');
$(img).load(function () {
$('.lightbox-loading').remove();
plugin.lightbox.append(img);
plugin.image = $("img", plugin.lightbox).hide();
plugin.resizeImage();
});
},
resizeImage: function () {
var ratio, wHeight, wWidth, iHeight, iWidth;
wHeight = $(window).height() - opts.margin;
wWidth = $(window).outerWidth(true) - opts.margin;
plugin.image.width('').height('');
iHeight = plugin.image.height();
iWidth = plugin.image.width();
if (iWidth > wWidth) {
ratio = wWidth / iWidth;
iWidth = wWidth;
iHeight = Math.round(iHeight * ratio);
}
if (iHeight > wHeight) {
ratio = wHeight / iHeight;
iHeight = wHeight;
iWidth = Math.round(iWidth * ratio);
}
plugin.image.width(iWidth).height(iHeight).css({
'top': ($(window).height() - plugin.image.outerHeight()) / 2 + 'px',
'left': ($(window).width() - plugin.image.outerWidth()) / 2 + 'px'
}).show();
plugin.locked = false;
},
getCurrentIndex: function () {
return $.inArray(plugin.current, plugin.items);
},
next: function () {
if (plugin.locked) {
return false;
}
plugin.locked = true;
if (plugin.getCurrentIndex() >= plugin.items.length - 1) {
$(plugin.items[0]).click();
} else {
$(plugin.items[plugin.getCurrentIndex() + 1]).click();
}
},
previous: function () {
if (plugin.locked) {
return false;
}
plugin.locked = true;
if (plugin.getCurrentIndex() <= 0) {
$(plugin.items[plugin.items.length - 1]).click();
} else {
$(plugin.items[plugin.getCurrentIndex() - 1]).click();
}
},
bindEvents: function () {
$(plugin.items).click(function (e) {
if(!$("#lightbox").is(":visible") && ($(window).width() < opts.minSize || $(window).height() < opts.minSize)) {
$(this).attr("target", "_blank");
return;
}
var self = $(this)[0];
e.preventDefault();
plugin.current = self;
plugin.loadImage();
// Bind Keyboard Shortcuts
$(document).on('keydown', function (e) {
// Close lightbox with ESC
if (e.keyCode === 27) {
plugin.close();
}
// Go to next image pressing the right key
if (e.keyCode === 39) {
plugin.next();
}
// Go to previous image pressing the left key
if (e.keyCode === 37) {
plugin.previous();
}
});
});
// Add click state on overlay background only
plugin.lightbox.on('click', function (e) {
if (this === e.target) {
plugin.close();
}
});
// Previous click
$(plugin.lightbox).on('click', '.lightbox-previous', function () {
plugin.previous();
return false;
});
// Next click
$(plugin.lightbox).on('click', '.lightbox-next', function () {
plugin.next();
return false;
});
// Close click
$(plugin.lightbox).on('click', '.lightbox-close', function () {
plugin.close();
return false;
});
$(window).resize(function () {
if (!plugin.image) {
return;
}
plugin.resizeImage();
});
},
close: function () {
$(document).off('keydown'); // Unbind all key events each time the lightbox is closed
$(plugin.lightbox).fadeOut('fast');
$('body').removeClass('blurred');
}
};
$.extend(opts, options);
plugin.init(this);
};
})(jQuery);
Author did just update it to include captions. Closing this.
I'm using a jquery plugin for a slider. It contains a pauseSlide function which I am trying to call from outside. Here is the plugin:
(function ($) {
$.fn.liteSlider = function (options) {
var defaults = {
content: '.content',
width: 500,
height: 250,
autoplay: false,
delay: 3,
buttonsClass: '',
activeClass: '',
controlBt: '',
playText: ' Play',
pauseText: 'Pause'
};
var options = $.extend(defaults, options);
var slideNo = 1;
var timer = 0;
var playStatus = options.autoplay;
var thisClass = ($(this).attr('class')).split(' ');
var theClass = '.' + thisClass[0];
var count = 0;
var slides;
var currentSlide = 1;
var delay = parseInt(options.delay) * 1000;
$(this).children(options.content).each(function () {
slides = ++count;
});
function wrapContent(ele) {
ele.wrap('<div class="sliderContentsWrap" />');
}
function applyCss(ele) {
$('.sliderContentsWrap').css({
padding: 0,
margin: 0,
width: options.width,
height: options.height,
overflow: 'hidden',
position: 'relative'
});
ele.css({
padding: 0,
margin: 0,
width: options.width * slides,
height: options.height,
position: 'absolute'
});
ele.children(options.content).css({
float: 'left',
width: options.width,
height: options.height
});
}
function resetButtons() {
i = 0;
$('.' + options.buttonsClass).each(function () {
i++;
$(this).addClass('bt' + i);
$(this).attr('rel', i);
});
}
function goToSlide(theSlide) {
var animateLeft = -(options.width) * (parseInt(theSlide) - 1);
$('.sliderContentsWrap' + ' ' + theClass)
.animate({
left: animateLeft
});
$('.' + options.buttonsClass).each(function () {
$(this).removeClass(options.activeClass);
if ($(this).hasClass('bt' + theSlide)) {
$(this).addClass(options.activeClass)
}
});
currentSlide = theSlide;
}
function autoplay() {
if (currentSlide < slides) {
goToSlide(parseInt(currentSlide) + 1);
} else {
goToSlide(1);
}
}
function playSlide() {
clearInterval(timer);
timer = setInterval(function () {
autoplay();
}, delay);
$(options.controlBt).text(options.pauseText);
playStatus = true;
}
function pauseSlide() {
clearInterval(timer);
$(options.controlBt).text(options.playText);
playStatus = false;
}
function init(ele) {
wrapContent(ele);
applyCss(ele);
resetButtons();
if (options.autoplay == true) {
playSlide()
} else {
pauseSlide();
}
}
return this.each(function () {
init($(this));
$('.' + options.buttonsClass).click(function (e) {
e.preventDefault();
pauseSlide();
goToSlide($(this).attr('rel'));
});
$(options.controlBt).click(function (e) {
e.preventDefault();
if (playStatus == true) {
pauseSlide()
} else {
playSlide()
};
});
});
};
//added this
$.liteSlider = {
pause: function() {
alert('clicked');
pauseSlide();
}
};
})(jQuery);
Outside of this I am using $.liteSlider.pause(); which displays the alert but it doesn't run the pauseSlide() function. Any suggestions?
Regarding the plugins authoring of jQuery, especially the namespacing point:
http://docs.jquery.com/Plugins/Authoring#Namespacing
[...] you should collect all of your plugin's methods in an object literal
and call them by passing the string name of the method to the plugin. [...]
(function($) {
var YourPluginMethods = {
init: function (options) {
return this.each(function () {
});
},
pauseSlide : function(options) {
return this.each(function () {
// Do some stuff for each instance of your plugin here
});
}
};
$.fn.YourPlugin = function(method) {
// Method calling logic
if (YourPluginMethods[method]) {
return YourPluginMethods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (!method || typeof method === 'object') {
return YourPluginMethods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.YourPlugin');
}
};
})(jQuery);
$('your-selector').YourPlugin('pauseSlide', {
speed: 'slow'
});
Once you have declared your methods this way, your can call it on any HTML selector.
pauseSlide is out of scope. An easy way around this might be to declare var pauseSlide; somewhere in scope, then assign it later.
(function ($) {
var pauseSlide;
$.fn.liteSlider = function (options) {
var defaults = {
content: '.content',
width: 500,
height: 250,
autoplay: false,
delay: 3,
buttonsClass: '',
activeClass: '',
controlBt: '',
playText: ' Play',
pauseText: 'Pause'
};
var options = $.extend(defaults, options);
var slideNo = 1;
var timer = 0;
var playStatus = options.autoplay;
var thisClass = ($(this).attr('class')).split(' ');
var theClass = '.' + thisClass[0];
var count = 0;
var slides;
var currentSlide = 1;
var delay = parseInt(options.delay) * 1000;
$(this).children(options.content).each(function () {
slides = ++count;
});
function wrapContent(ele) {
ele.wrap('<div class="sliderContentsWrap" />');
}
function applyCss(ele) {
$('.sliderContentsWrap').css({
padding: 0,
margin: 0,
width: options.width,
height: options.height,
overflow: 'hidden',
position: 'relative'
});
ele.css({
padding: 0,
margin: 0,
width: options.width * slides,
height: options.height,
position: 'absolute'
});
ele.children(options.content).css({
float: 'left',
width: options.width,
height: options.height
});
}
function resetButtons() {
i = 0;
$('.' + options.buttonsClass).each(function () {
i++;
$(this).addClass('bt' + i);
$(this).attr('rel', i);
});
}
function goToSlide(theSlide) {
var animateLeft = -(options.width) * (parseInt(theSlide) - 1);
$('.sliderContentsWrap' + ' ' + theClass)
.animate({
left: animateLeft
});
$('.' + options.buttonsClass).each(function () {
$(this).removeClass(options.activeClass);
if ($(this).hasClass('bt' + theSlide)) {
$(this).addClass(options.activeClass)
}
});
currentSlide = theSlide;
}
function autoplay() {
if (currentSlide < slides) {
goToSlide(parseInt(currentSlide) + 1);
} else {
goToSlide(1);
}
}
function playSlide() {
clearInterval(timer);
timer = setInterval(function () {
autoplay();
}, delay);
$(options.controlBt).text(options.pauseText);
playStatus = true;
}
pauseSlide = function() {
clearInterval(timer);
$(options.controlBt).text(options.playText);
playStatus = false;
}
function init(ele) {
wrapContent(ele);
applyCss(ele);
resetButtons();
if (options.autoplay == true) {
playSlide()
} else {
pauseSlide();
}
}
return this.each(function () {
init($(this));
$('.' + options.buttonsClass).click(function (e) {
e.preventDefault();
pauseSlide();
goToSlide($(this).attr('rel'));
});
$(options.controlBt).click(function (e) {
e.preventDefault();
if (playStatus == true) {
pauseSlide()
} else {
playSlide()
};
});
});
};
//added this
$.liteSlider = {
pause: function() {
alert('clicked');
pauseSlide();
}
};
The problem is that the call to pauseSlide is not in the same scope as the declaration.
How can I stop the autoplay function of cSlider with an onmouseover event?
HTML:
<div id="da-slider" class="da-slider">
<div class="da-slide">
<p>Text</p>
</div>
<div class="da-slide">
<p>More text</p>
</div>
</div>
What I have tried so far with jQuery:
$(function() {
$('#da-slider').cslider({
autoplay : true,
bgincrement : 450
});
});
$('#da-slider').hover(function() {
if($('#daslider').autoplay('true')){
autoplay: false
}
}, function () {
autoplay: true
});
This is the one I'm using:
http://tympanus.net/codrops/2012/03/15/parallax-content-slider-with-css3-and-jquery/
This feature not implemented by default but this shouldn't stop you from implementing it on your own. Look at modified plugin code below (draw attention on stop and 'start' methods)
(function ($, undefined) {
/*
* Slider object.
*/
$.Slider = function (options, element) {
this.$el = $(element);
this._init(options);
};
$.Slider.defaults = {
current: 0, // index of current slide
bgincrement: 50, // increment the bg position (parallax effect) when sliding
autoplay: false, // slideshow on / off
interval: 4000 // time between transitions
};
$.Slider.prototype = {
_init: function (options) {
this.options = $.extend(true, {}, $.Slider.defaults, options);
this.$slides = this.$el.children('div.da-slide');
this.slidesCount = this.$slides.length;
this.current = this.options.current;
if (this.current < 0 || this.current >= this.slidesCount) {
this.current = 0;
}
this.$slides.eq(this.current).addClass('da-slide-current');
var $navigation = $('<nav class="da-dots"/>');
for (var i = 0; i < this.slidesCount; ++i) {
$navigation.append('<span/>');
}
$navigation.appendTo(this.$el);
this.$pages = this.$el.find('nav.da-dots > span');
this.$navNext = this.$el.find('span.da-arrows-next');
this.$navPrev = this.$el.find('span.da-arrows-prev');
this.isAnimating = false;
this.bgpositer = 0;
this.cssAnimations = Modernizr.cssanimations;
this.cssTransitions = Modernizr.csstransitions;
if (!this.cssAnimations || !this.cssAnimations) {
this.$el.addClass('da-slider-fb');
}
this._updatePage();
// load the events
this._loadEvents();
// slideshow
if (this.options.autoplay) {
this._startSlideshow();
}
},
_navigate: function (page, dir) {
var $current = this.$slides.eq(this.current), $next, _self = this;
if (this.current === page || this.isAnimating) return false;
this.isAnimating = true;
// check dir
var classTo, classFrom, d;
if (!dir) {
(page > this.current) ? d = 'next' : d = 'prev';
}
else {
d = dir;
}
if (this.cssAnimations && this.cssAnimations) {
if (d === 'next') {
classTo = 'da-slide-toleft';
classFrom = 'da-slide-fromright';
++this.bgpositer;
}
else {
classTo = 'da-slide-toright';
classFrom = 'da-slide-fromleft';
--this.bgpositer;
}
this.$el.css('background-position', this.bgpositer * this.options.bgincrement + '% 0%');
}
this.current = page;
$next = this.$slides.eq(this.current);
if (this.cssAnimations && this.cssAnimations) {
var rmClasses = 'da-slide-toleft da-slide-toright da-slide-fromleft da-slide-fromright';
$current.removeClass(rmClasses);
$next.removeClass(rmClasses);
$current.addClass(classTo);
$next.addClass(classFrom);
$current.removeClass('da-slide-current');
$next.addClass('da-slide-current');
}
// fallback
if (!this.cssAnimations || !this.cssAnimations) {
$next.css('left', (d === 'next') ? '100%' : '-100%').stop().animate({
left: '0%'
}, 1000, function () {
_self.isAnimating = false;
});
$current.stop().animate({
left: (d === 'next') ? '-100%' : '100%'
}, 1000, function () {
$current.removeClass('da-slide-current');
});
}
this._updatePage();
},
_updatePage: function () {
this.$pages.removeClass('da-dots-current');
this.$pages.eq(this.current).addClass('da-dots-current');
},
_startSlideshow: function () {
var _self = this;
this.slideshow = setTimeout(function () {
var page = (_self.current < _self.slidesCount - 1) ? page = _self.current + 1 : page = 0;
_self._navigate(page, 'next');
if (_self.options.autoplay) {
_self._startSlideshow();
}
}, this.options.interval);
},
page: function (idx) {
if (idx >= this.slidesCount || idx < 0) {
return false;
}
if (this.options.autoplay) {
clearTimeout(this.slideshow);
this.options.autoplay = false;
}
this._navigate(idx);
},
stop: function () {
if (this.options.autoplay) {
clearTimeout(this.slideshow);
this.options.autoplay = false;
}
},
start: function () {
this.options.autoplay = true;
this._startSlideshow();
},
_loadEvents: function () {
var _self = this;
this.$pages.on('click.cslider', function (event) {
_self.page($(this).index());
return false;
});
this.$navNext.on('click.cslider', function (event) {
if (_self.options.autoplay) {
clearTimeout(_self.slideshow);
_self.options.autoplay = false;
}
var page = (_self.current < _self.slidesCount - 1) ? page = _self.current + 1 : page = 0;
_self._navigate(page, 'next');
return false;
});
this.$navPrev.on('click.cslider', function (event) {
if (_self.options.autoplay) {
clearTimeout(_self.slideshow);
_self.options.autoplay = false;
}
var page = (_self.current > 0) ? page = _self.current - 1 : page = _self.slidesCount - 1;
_self._navigate(page, 'prev');
return false;
});
if (this.cssTransitions) {
if (!this.options.bgincrement) {
this.$el.on('webkitAnimationEnd.cslider animationend.cslider OAnimationEnd.cslider', function (event) {
if (event.originalEvent.animationName === 'toRightAnim4' || event.originalEvent.animationName === 'toLeftAnim4') {
_self.isAnimating = false;
}
});
}
else {
this.$el.on('webkitTransitionEnd.cslider transitionend.cslider OTransitionEnd.cslider', function (event) {
if (event.target.id === _self.$el.attr('id'))
_self.isAnimating = false;
});
}
}
}
};
var logError = function (message) {
if (this.console) {
console.error(message);
}
};
$.fn.cslider = function (options) {
if (typeof options === 'string') {
var args = Array.prototype.slice.call(arguments, 1);
this.each(function () {
var instance = $.data(this, 'cslider');
if (!instance) {
logError("cannot call methods on cslider prior to initialization; " +
"attempted to call method '" + options + "'");
return;
}
if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
logError("no such method '" + options + "' for cslider instance");
return;
}
instance[options].apply(instance, args);
});
}
else {
this.each(function () {
var instance = $.data(this, 'cslider');
if (!instance) {
$.data(this, 'cslider', new $.Slider(options, this));
}
});
}
return this;
};
})(jQuery);
With updated plugin you can pause and renew autiplaying with this code:
$('#da-slider').hover(
function () {
$(this).cslider("stop");
},
function () {
$(this).cslider("start");
}
);