jQuery - this.option becomes undefined in load function - javascript

I'm trying to alter a Plugin a little bit, here's the Prototype function, I've marked what lines I've added.
OK, so my problem happens inside the img-load function I've added. I've surrounded the old code with one to assure that the script waits until the image has loaded.
The problem is, that "this" inside the load-function is not connected with the one outside. I've tried giving the load function a parameter but apparently it's not working or I'm doing something wrong.
Do you know an easy way to sort-of inherit "this"? I don'T really know what else to do.
Plugin.prototype._fade = function(number) {
var $element, currentSlide, next, slidesControl, value,
_this = this;
$element = $(this.element);
this.data = $.data(this);
if (!this.data.animating && number !== this.data.current + 1) {
$.data(this, "animating", true);
currentSlide = this.data.current;
if (number) {
number = number - 1;
value = number > currentSlide ? 1 : -1;
next = number;
} else {
value = this.data.direction === "next" ? 1 : -1;
next = currentSlide + value;
}
if (next === -1) {
next = this.data.total - 1;
}
if (next === this.data.total) {
next = 0;
}
this._setActive(next);
slidesControl = $(".slidesjs-control", $element);
var nxtImg = $(slidesControl.children(":eq(" + next + ")")).find("img:eq(0)"); // added
if ( nxtImg.attr("longdesc") !== undefined ) { // added
nxtImg.attr("src", nxtImg.attr("longdesc")); // added
nxtImg.removeAttr("longdesc"); // added
} // added
nxtImg.load(function(){ // added
slidesControl.children(":eq(" + next + ")").css({
display: "block",
left: 0,
zIndex: 0
});
this.options.callback.start(currentSlide + 1);
if (this.options.effect.fade.crossfade) {
return slidesControl.children(":eq(" + this.data.current + ")").stop().fadeOut(this.options.effect.fade.speed, (function() {
slidesControl.children(":eq(" + next + ")").css({
zIndex: 10
});
$.data(_this, "animating", false);
$.data(_this, "current", next);
return _this.options.callback.complete(next + 1);
}));
} else {
slidesControl.children(":eq(" + next + ")").css({
display: "none"
});
return slidesControl.children(":eq(" + currentSlide + ")").stop().fadeOut(this.options.effect.fade.speed, (function() {
slidesControl.children(":eq(" + next + ")").stop().fadeIn(_this.options.effect.fade.speed).css({
zIndex: 10
});
$.data(_this, "animating", false);
$.data(_this, "current", next);
return _this.options.callback.complete(next + 1);
}));
}
}); // added
}
};

You're capturing the this in a closure variable "_this". Isn't that working?

Related

Extending Touch EventListener to Additional DOM Element

I used a Codrops article/experiment to create an interactive environment for a local group to use at their conferences. The problem with this is the default interaction is not very intuitive. The template used Flickity.js and what seems like classie.js to create this sliding interface I am having trouble with.
The page can be found here:
www.eyeconic.tv/ky-ffa/
Issue: The only way to activate the view-full is by clicking on the html element:
<h2 class=".stack-title">
// After the stack is active you should be able to activate the full view by clicking on the first .stack-item used to create the thumbnail below it. This entire div should be clickable. Users are touching everywhere all over the screen and not actually clicking the title for the desired action. I hope this makes sense.
In other words you should be able to click the stack-title and the image below the title of each stack to pull the stack into the full view mode on the screen. Then click the x or anywhere else on the screen to close the full view.
The following is located in main.js and the reference I found to create the events I am referring to.
//
function initEvents() {
stacks.forEach(function(stack) {
var titleEl = stack.querySelector('.stack-title');
// expand/close the stack
titleEl.addEventListener('click', function(ev) {
ev.preventDefault();
if( classie.has(stack, 'is-selected') ) { // current stack
if( classie.has(bodyEl, 'view-full') ) { // stack is opened
var closeStack = function() {
classie.remove(bodyEl, 'move-items');
onEndTransition(slider, function() {
classie.remove(bodyEl, 'view-full');
bodyEl.style.height = '';
flkty.bindDrag();
flkty.options.accessibility = true;
canMoveHeroImage = true;
});
};
// if the user scrolled down, let's first scroll all up before closing the stack.
var scrolled = scrollY();
if( scrolled > 0 ) {
smooth_scroll_to(isFirefox ? docElem : bodyEl || docElem, 0, 500).then(function() {
closeStack();
});
}
else {
closeStack();
}
}
else if( canOpen ) { // stack is closed
canMoveHeroImage = false;
classie.add(bodyEl, 'view-full');
setTimeout(function() { classie.add(bodyEl, 'move-items'); }, 25);
bodyEl.style.height = stack.offsetHeight + 'px';
flkty.unbindDrag();
flkty.options.accessibility = false;
}
}
else if( classie.has(stack, 'stack-prev') ) {
flkty.previous(true);
}
else if( classie.has(stack, 'stack-next') ) {
flkty.next(true);
}
});
titleEl.addEventListener('mouseenter', function(ev) {
if( classie.has(stack, 'is-selected') ) {
canMoveHeroImage = false;
imghero.style.WebkitTransform = 'perspective(1000px) translate3d(0,0,0) rotate3d(1,1,1,0deg)';
imghero.style.transform = 'perspective(1000px) translate3d(0,0,0) rotate3d(1,1,1,0deg)';
}
});
titleEl.addEventListener('mouseleave', function(ev) {
// if current stack and it's not opened..
if( classie.has(stack, 'is-selected') && !classie.has(bodyEl, 'view-full') ) {
canMoveHeroImage = true;
}
});
});
window.addEventListener('mousemove', throttle(function(ev) {
if( !canMoveHeroImage ) return false;
var xVal = -1/(win.height/2)*ev.clientY + 1,
yVal = 1/(win.width/2)*ev.clientX - 1,
transX = 20/(win.width)*ev.clientX - 10,
transY = 20/(win.height)*ev.clientY - 10,
transZ = 100/(win.height)*ev.clientY - 50;
imghero.style.WebkitTransform = 'perspective(1000px) translate3d(' + transX + 'px,' + transY + 'px,' + transZ + 'px) rotate3d(' + xVal + ',' + yVal + ',0,2deg)';
imghero.style.transform = 'perspective(1000px) translate3d(' + transX + 'px,' + transY + 'px,' + transZ + 'px) rotate3d(' + xVal + ',' + yVal + ',0,2deg)';
}, 100));
// window resize
window.addEventListener( 'resize', throttle(function(ev) {
// recalculate window width/height
win = { width: window.innerWidth, height: window.innerHeight };
// reset body height if stack is opened
if( classie.has(bodyEl, 'view-full') ) { // stack is opened
bodyEl.style.height = stacks[flkty.selectedIndex].offsetHeight + 'px';
}
}, 50));
// Flickity events:
flkty.on('cellSelect', function() {
canOpen = false;
classie.remove(bodyEl, 'item-clickable');
var prevStack = stacksWrapper.querySelector('.stack-prev'),
nextStack = stacksWrapper.querySelector('.stack-next'),
selidx = flkty.selectedIndex,
cellsCount = flkty.cells.length,
previdx = selidx > 0 ? selidx - 1 : cellsCount - 1;
nextidx = selidx < cellsCount - 1 ? selidx + 1 : 0;
if( prevStack ) {
classie.remove(prevStack, 'stack-prev');
}
if( nextStack ) {
classie.remove(nextStack, 'stack-next');
}
classie.add(stacks[previdx], 'stack-prev');
classie.add(stacks[nextidx], 'stack-next');
});
flkty.on('dragStart', function() {
canOpen = false;
classie.remove(bodyEl, 'item-clickable');
});
flkty.on('settle', function() {
classie.add(bodyEl, 'item-clickable');
canOpen = true;
});
}
init();
})();
I wrapped the title and the first stack item in a div class .touch-me and it worked fairly well. I had previously tried to do this and received an error. But I may have mistyped something because it only made sense.
ISSUE: It works on mouseclick, but it is not working with touch on windows. I have untested it in any other environment because it will be deployed on a windows touch screen.
Although I cannot tell the layer not to close on touch when you swipe or touch the header image for the stack.... I'm afraid I do not have the skillset to properly modify the logic in the javascript since I do not entirely understand the plugins being used.

Jquery Carousel - calculations if active slide is not one with specific ID then to slide to it.

The question isn't massively helpful I suppose so I'll try to be as clear as I can.
So I have a setup where my header has 4 anchor texts in them. The First part of the body has a custom jquery carousel in it.
What I'm trying to acheive is basically make it so that when any of the four anchor links in the header are clicked they scroll to a specific slide which I have given an ID. The issue I have of course is allowing for the carousel to have any slide active and having the anchor links calculate which slide is active and how much it needs to slide to get to the correct slide.
Here is the jquery for the carousel:
var carousel; // used as the object for the carousel
var carousels = []; // will hold any and all carousels on the page
var preventTimeouts = false;
var intervals = [];
$(document).ready(function () {
carousels.push(new carousel('slideshow_window', 'slidesHolder', '.slide', 920, 10000, 1000, true));
});
carousel = function CarouselSlider(windowName, slideCollectionWrapper,slideCollection, slideWidth, slideChangeInterval, slideChangeSpeed, requireNavButtons) {
// Variables
var slideWidth = slideWidth; // the width of each slide
var slides_array = $(slideCollection).toArray();
var numberOfSlides = slides_array.length;
var slideChangeInterval = slideChangeInterval; // how often the slides will automatically change
var slideChangeSpeed = slideChangeSpeed; // how fast the slides change
var slideIntervalId; // holds the interval event (the event for the next time that the slides should change)
var animating = false; // used to track whether an animation is underway
var currentPosition = 0; // used to highlight the centre image to begin with
var requireNavButtons = requireNavButtons;
var windowName = windowName;
var collectionWrapper = slideCollectionWrapper;
// Carousel
$('#' + windowName).append("<div id=\"" + collectionWrapper + "\"></div>"); // set up the collection wrapper
$('#' + collectionWrapper).css('width', slideWidth * numberOfSlides);
$('#' + collectionWrapper).css('position', "relative");
for (var i = 0; i < slides_array.length; i++) // add items from the collection to the wrapper
$('#' + collectionWrapper).append(slides_array[i]);
$('#' + collectionWrapper).css('left', 920 - slideWidth);
// for (i = 0; i < slides_array.length; i++) { // run one round of the carousel to ensure correct positioning
// currentposition++;
// moveslide(true, true); // set 'forced' to true to disable the animation
// }
function changePosition(forwards) {
forwards ? currentPosition++ : currentPosition--;
moveSlide(forwards, false);
}
function moveSlide(forwards, forced) {
var nextSlide;
animating = true;
if (forwards) {
nextSlide = currentPosition % numberOfSlides;
var t_dur = forced ? 0 : slideChangeSpeed;
$('#' + collectionWrapper).append(slides_array[nextSlide]);
$('#' + collectionWrapper).append(slides_array[nextSlide + 1 > numberOfSlides - 1 ? 0 : nextSlide + 1]); // load the next two slides
$('#' + collectionWrapper)
.animate({ left: "-=" + slideWidth, queue: false },
t_dur,
function () {
$('#' + collectionWrapper + ' ' + slideCollection + ':first').remove();
$('#' + collectionWrapper).css('left', 0);
animating = false;
});
}
else {
nextSlide = (currentPosition % numberOfSlides);
$('#' + collectionWrapper).prepend(slides_array[nextSlide - 1 < 0 ? numberOfSlides + nextSlide : nextSlide]);
$('#' + collectionWrapper).prepend(slides_array[nextSlide < 0 ? numberOfSlides + nextSlide : nextSlide]);
$('#' + collectionWrapper).css('left', 0 - slideWidth); // increase offset to account for prepended slides
$('#' + collectionWrapper)
.animate({ left: "+=" + slideWidth, queue: false },
slideChangeSpeed,
function () {
$('#' + collectionWrapper + ' ' + slideCollection + ':last').remove();
animating = false;
});
}
}
/*
Navigation buttons
*/
$("#next").click(function () {
if (!animating) { // only queue one click at a time
changePosition(true);
}
});
$("#prev").click(function () {
if (!animating) {
changePosition(false);
}
});
$("#prevSearch").click(function () {
if (!animating) {
changePosition(false);
}
});
$("#prevSearch2").click(function () {
$("#modalContainer").hide();
if (!animating) {
changePosition(false);
}
});
}

jQuery bug when using bounce effect

I have problem with jQuery bounce effect. Every thing works good when there is no bounce - with bounce, when You move very fast many times on button - in sometime, box just doesn't hide. What is wrong in this jsfiddle?
My jsfiddle:
http://jsfiddle.net/d6mSA/170/
My JS:
$('.flex_section').delegate('a','mouseenter mouseleave',function(e){
var a = $(this).attr('id');
if (e.type == 'mouseenter'){
clearTimeout(t_on)
if (a == 'abc'){
clearTimeout(t_off)
t_on = setTimeout(function() { popup_show(a,t_on); }, 10);
}
} else {
t_off = setTimeout(function() { popup_remove(a,t_off); }, 1000);
}
)}
function popup_show(type,string){
if (type == 'abc'){
$('#pc_' + type).css('display','block');
$('#pc_' + type).effect( "bounce",{times:3,distance:20},1000);
}
clearTimeout(string);
}
function popup_remove(type,string){
$('#pc_' + type).css('display','none');
clearTimeout(string)
}
Keep it simple:
function popup(){
$('.flex_top a').hover(function(){
var type = $(this).attr('id');
var offset = $('#' + type).offset();
$('#id_' + type).css('display','block')
.offset({left:offset.left + 100, top:offset.top + 380})
.effect( "bounce",{times:3,distance:20},1000);
},function(){
var type = $(this).attr('id');
$('#id_' + type).fadeOut();
}
);
}
And dont call many times the same object search $('#id_' + type)
Try using stop
$('#pc_' + type).stop().effect( "bounce",{times:3,distance:20},1000);

jQuery-UI slider up down buttons

Didn't find the way to create up and down buttons for vertical slider, to make its appearance like as standard scroller.
Is solution below suitable? Or are there any other ways?
function scroll(step)
{
if (step > 0)
{
if ($("#slider").slider('value') <= (100 - step))
{
$("#slider").slider('value', $("#slider").slider('value') + step);
}
}
else
{
if ($("#slider").slider('value') >= Math.abs(step))
{
$("#slider").slider('value', $("#slider").slider('value') + step);
}
}
return false;
}
What you have certainly works...but if you're worried about the range capping, slider already does this internally, so you can just do this:
function scroll(step) {
var s = $("#slider");
s.slider('value', s.slider('value') + step);
return false;
}
Also note that even setting the value returns it (the capped value), so you can do this for example:
function scroll(step) {
var s = $("#slider");
var newValue = s.slider('value', s.slider('value') + step);
alert("The new value is: " + newValue);
return false;
}
So for example if the range is 0-100 and you're at 90, a step of 10 or more would always result in a newValue of 100.

jQuery / Javascript - loop

I want to make it so when I click somewhere in my website, the background changes. I have three backgrounds, and I want to make a loop of them.
$(document).ready(function() {
$('body').click((function(){
return function()
{
if (counter == null) {
var counter = 1;
}
if(counter == 3) {
$(this).css("background-image","url(3.jpg)");
$(this).css("background-position","10% 35%");
var counter = null;
}
if(counter == 2) {
$(this).css("background-image","url(2.jpg)");
$(this).css("background-position","10% 35%");
var counter = 3;
}
if(counter == 1) {
$(this).css("background-image","url(1.jpg)");
$(this).css("background-position","40% 35%");
var counter = 2;
}
}
})());
});
Why doesn't this work?
Your counter variable isn't scoped right, you need one counter variable. Overall though, why not let .toggle() manage this for you? Here's what it would look like:
$(function() {
$('body').toggle(function(){
$(this).css({"background-image":"url(1.jpg)", "background-position":"40% 35%"});
}, function() {
$(this).css({"background-image":"url(2.jpg)", "background-position":"10% 35%"});
}, function() {
$(this).css({"background-image":"url(3.jpg)", "background-position":"10% 35%"});
});
});
Although the name and common usages suggest that .toggle() only takes 2 functions, it actually takes 2 or more and will cycle through them.
this no longer refers to the body element, it refers to the anonymous function.
Does this code work?
var counter = 1;
$(document).ready(function() {
$('body').click(function() {
if (counter == null) {
counter = 1;
}
if (counter == 3) {
$(this).css("background-image", "url(3.jpg)");
$(this).css("background-position", "10% 35%");
counter = 1;
}
if (counter == 2) {
$(this).css("background-image", "url(2.jpg)");
$(this).css("background-position", "10% 35%");
counter = 3;
}
if (counter == 1) {
$(this).css("background-image", "url(1.jpg)");
$(this).css("background-position", "40% 35%");
counter = 2;
}
});
});
Your function uses this which is refering to itself, not the element. This would fix it:
$('body').click((function(){
var $this = $(this);
return ... {
$this // use $this instead of $(this)
Also, have a look on jQuery .toggle
Your counter declarations are strewn all over the place which makes it difficult to follow what's happening. Further, counter is declared local to the callback function, which means it loses its value every time the function executes.
Here's a simpler solution:
$(function() { // this is equivalent to $(document).ready(...)
var counter = 0;
var images = [
[ '1.jpg', '40% 35%' ],
[ '2.jpg', '10% 35%' ],
[ '3.jpg', '10% 35%' ]
];
$('body').click(function() {
$(this).css('background-image', 'url(' + images[counter][0] + ')');
$(this).css('background-position', images[counter][1]);
// increment counter, wrapping over to 0 when it reaches end of array
counter = (counter + 1) % images.length;
});
});
You can easily extend to this to any number of images by simply adding more entries to the images array.
$(document).ready(function () {
function changeBgImage() {
var imgs = [
["1.jpg", "10% 35%"],
["2.jpg", "10% 35%"],
["3.jpg", "40% 35%"]
];
var counter = 0;
return function() {
$(this).css({
"backgroundImage": "url(" + imgs[counter][0] + ")",
"backgroundPosition": imgs[counter][1]
});
counter += 1;
if (counter === imgs.length) { counter = 0; }
};
}
$('body').click(changeBgImage());
});
Update:
OK, so here we have another solution. It is basically Nick's answer but without redundancy.
$(function () {
var imgs = [["1.jpg", "10% 35%"], ["2.jpg", "10% 35%"], ["3.jpg", "40% 35%"]];
var i = 0;
$("body").click(function () {
$(this).css({"background-image": "url(" + imgs[i][0] + ")", "background-position": imgs[i][1]});
if (++i === imgs.length) { i = 0; }
});
});

Categories