I'm trying to get a reference to cell and it appears null. If I'm understanding it correctly, I should be able to reference the variable. Correct?
$('td[someAttr]').mouseenter(function(cell) {
var timeoutId = setTimeout(function() {
// what should variable cell be?
}, 1000);
});
OR
$('td[someAttr]').mouseenter(function(cell) {
var timeoutId = setTimeout(function() {
// what should variable cell be?
}, 1000, cell);
});
UPDATE: This was obvious but the reason I asked this was because cell.pageX would be undefined if you had:
$('td[someAttr]').mouseenter(function() {
var cell = this; //
var timeoutId = setTimeout(function() {
alert(cell.pageX); // cell.pageX will return null
}, 1000);
});
However, if you had:
$('td[someAttr]').mouseenter(function(cell) {
alert(cell.pageX); // works fine as cell.pageX will have correct value.
});
The context of the event handler is set to the element that triggered the event. You can get at it this way:
$('td[someAttr]').mouseenter(function() {
var cell = this;
var timeoutId = setTimeout(function() {
alert(cell.tagName);
}, 1000);
});
You may also want to wrap it as a jQuery object as well: var cell = $(this);
UPDATE: The first argument is the event object, not the element. The element is set as the context of the callback (i.e. this) and you can get access to the event object in exactly the way that you were in your example:
$('td[someAttr]').mouseenter(function(event) {
var cell = this;
var timeoutId = setTimeout(function() {
alert(cell.tagName + ' ' + event.pageX);
}, 1000);
});
Note that the "cell" element is also accessible as "event.target".
Related
i have a problem accessing variable inside method in OOP.
this is my code :
var slideshow = {
elSet : $(".slideshow"),
next : function() {
},
swipe : function() {
var clear = this.autorun().loop;
onSwipe(function() {
clearInterval(clear); // not working
});
},
autorun : function() {
var self = this;
var loop = setInterval(function() {
self.next();
}, 5000);
},
initial : function() {
this.swipe();
this.autorun();
}
}
slideshow.initial();
i want to clearInterval from variable loop,
on browser console return error TypeError: this.loop(...) is undefined
what's wrong with my code?
Just assign the interval id returned by setInterval to a variable you can access, or like Barmar's answer return it.
var slideshow = {
elSet: $(".slideshow"),
next: function() {
},
swipe: function() {
var self = this;
onSwipe(function() {
//use the interval id to cancel
clearInterval(self.intervalRef);
});
},
// variable to store the interval id
intervalRef: null,
autorun: function() {
var self = this;
//assign the interval id generated by setInterval to a variable you can access
this.intervalRef = setInterval(function() {
self.next();
}, 5000);
},
initial: function() {
this.swipe();
this.autorun();
}
}
slideshow.initial();
Issues:
var clear = this.autorun().loop; Here this will have scope swipe and not object.
var loop = setInterval(function() {}) Here loop will have scope of autorun and will expire after function execution is over.
You can try something like this:
JSFiddle
function SlideShow() {
// self will hold current object reference for all functions
var self = this;
var interval = null;
function next() {
console.log('next');
}
function swipe() {
onSwipe(function() {
console.log("Clearint Interval")
clearInterval(interval);
});
}
// Private function
function onSwipe(callback) {
console.log("On Swipe");
// Check if value is passed and its a function
if (callback && typeof(callback) === 'function')
callback();
}
function loop() {
interval = setInterval(function() {
next();
}, 5000);
}
function init() {
swipe();
loop();
}
// Public properties
return {
elSet: $(".slideshow"),
next: next,
swipe: swipe,
loop: loop,
initial: init,
interval: interval
}
}
// Create a new instance of SlideShow
var slideshow = new SlideShow();
slideshow.initial();
In the swipe function, you have:
var clear = this.autorun().loop;
This expects this.autorun() to return an object, and tries to access the loop property of that object, which should contain the ID of an interval function. But autorun doesn't return anything, let alone an object with a loop property.
Change autorun to:
autorun : function() {
var self = this;
var loop = setInterval(function() {
self.next();
}, 5000);
return loop;
}
Then you can do:
var clear = this.autorun();
You also shouldn't call this.autorun() in the initial function. It's already called by this.swipe(). Running it again will cause two interval functions to run, and the ID of the second one isn't saved anywhere so that you can clear it.
In JavaScript, I have an element (which is an input tag).
This code :
element.addEventListener("focus", function () {
this.parentNode.parentNode.style.outline = this.parentNode.parentNode.dataset.ans_outline;
});
When the input is focused, outline is changed immediately.
My question is : how could I delay this event ?
I've tried :
element.addEventListener("focus", function () {
setTimeout(function(node) {
node.parentNode.parentNode.style.outline = node.parentNode.parentNode.dataset.ans_outline;
}(this), 1000)
});
.. But it doesn't work :(
try this:
element.addEventListener("focus", function () {
var node = this;
setTimeout(function() {
node.parentNode.parentNode.style.outline = node.parentNode.parentNode.dataset.ans_outline;
}, 1000)
});
First argument of setTimeout function is function you want to execute (do not call this function directly).
You can store reference to this in node variable and then use it inside your timed out function (see closures)
Remove the reference to the this and give it this way:
element.addEventListener("focus", function () {
$this = this;
setTimeout(function() {
$this.parentNode.parentNode.style.outline = $this.parentNode.parentNode.dataset.ans_outline;
}, 1000)
});
I've searched and searched and I'm coming up empty on this one guys. Help! I'm watching an input field (#filter_query) for keyup events using JQuery on(). When the user punches in some text into this input field the on() triggers a setTimeout() which then in turns triggers a search function for the site. I'm trying to avoid the search from being fired if the user continues to type into the input field thus the clearTimeout(). For some reason the timeout ID isn't being preserved for clearTimeout and a new ID is being generated each time.
Here's my code:
$(document).on('keyup', '#filter_query', function (event) {
var iTimeoutID,
iTypingDelay = 800,
sFilterVal = $.trim($('#filter_query').val()),
sFilterCat = $('#filter_catagory').val(),
sFilterCol = $('#filter_col').val();
clearTimeout(iTimeoutID);
if (sFilterVal !== "") {
iTimeoutID = setTimeout(
function () {
searchFunction();
},
iTypingDelay
);
}
});
With the above code my search function is being fired off several times regardless of the clearTimeout(). Thank you!
Your iTimeoutID is a local variable to the .on() event handler function and thus it's destroyed each time that function completes and recreated the next time. Move it out of that scope to a higher level or to the global level so it can survive from one event to the next.
You can do it like this;
var iTimeoutID = null;
$(document).on('keyup', '#filter_query', function (event) {
var iTypingDelay = 800,
sFilterVal = $.trim($('#filter_query').val()),
sFilterCat = $('#filter_catagory').val(),
sFilterCol = $('#filter_col').val();
if (iTimeoutID) {
clearTimeout(iTimeoutID);
iTimeoutID = null;
}
if (sFilterVal !== "") {
iTimeoutID = setTimeout(function() {
iTimeoutID = null;
searchFunction();
}, iTypingDelay);
}
});
If you want to avoid global variables or you have more than one of these, you can use jQuery's .data() to store the timer id on the object like this:
$(document).on('keyup', '#filter_query', function (event) {
var self = $(this);
var iTimeoutID = self.data("timerID") || null;
var iTypingDelay = 800,
sFilterVal = $.trim($('#filter_query').val()),
sFilterCat = $('#filter_catagory').val(),
sFilterCol = $('#filter_col').val();
if (iTimeoutID) {
clearTimeout(iTimeoutID);
iTimeoutID = null;
}
if (sFilterVal !== "") {
iTimeoutID = setTimeout(function() {
self.data("timerID", null);
searchFunction();
}, iTypingDelay);
}
self.data("timerID", iTimeoutID);
});
Here's one other version that uses a self-executing function to act as a shell for some variables that can last across the event handlers without being global:
(function() () {
var iTimeoutID = null;
$(document).on('keyup', '#filter_query', function (event) {
var iTypingDelay = 800,
sFilterVal = $.trim($('#filter_query').val()),
sFilterCat = $('#filter_catagory').val(),
sFilterCol = $('#filter_col').val();
if (iTimeoutID) {
clearTimeout(iTimeoutID);
iTimeoutID = null;
}
if (sFilterVal !== "") {
iTimeoutID = setTimeout(function() {
iTimeoutID = null;
searchFunction();
}, iTypingDelay);
}
});
})();
If this was something quick and there was little chance of conflict with other code and there's only one object being served by the event handler, the first option is perfectly fine.
If the .on() event handler served multiple objects and each needed to keep track of it's own state, the 2nd option is perfect for that.
If you don't have multiple objects on the same event handler, then the third option is the simplest way to keep from adding any new global variables.
Because you are defining the variable var iTimeoutID, that means that it's not a global variable and only accessible inside that function. So when the function gets called again, it creates a new variable.
I believe you should be able to fix it by not declaring the variable var iTimeoutID.
I might be wrong so if so, someone please correct me.
OK, I am missing something fundamental here I am sure! But for the life of me can not work it out.
Scenario
It's a simple hide show menu;
// Setup hover
var fadeDuration = 200;
var setDelay;
$level1Item.hover(function () {
$(this).addClass('hover').find('.level-2').fadeIn(fadeDuration);
}, function () {
$(this).removeClass('hover').find('.level-2').fadeOut(fadeDuration);
});
And it works fine... but the drop down is rather LARGE and is irritating when it pops up all be it very sexily when you mouse moves from top to bottom of screen.
So I want to set a timeout and clear it on mouse out...
// Setup hover
var fadeDuration = 200;
var setDelay;
$level1Item.hover(function () {
setDelay = setTimeout("$(this).addClass('hover').find('.level-2').fadeIn(200)", 500);
//$(this).addClass('hover').find('.level-2').fadeIn(fadeDuration);
}, function () {
clearTimeout(setDelay);
$(this).removeClass('hover').find('.level-2').fadeOut(fadeDuration);
});
ABSOLUTELY NOTHING HAPPENS!! I have tried alerts in the timeout function and they work... originally the variable fadeDuration was undefined but a number stops the console error.
Try amending the setTimeout call to use an anonymous function:
// Setup hover
var fadeDuration = 200;
var setDelay;
var $item;
$level1Item.hover(function () {
$item = $(this);
setDelay = setTimeout(function() {
$item.addClass('hover').find('.level-2').fadeIn(200)
}, 500);
},
function () {
clearTimeout(setDelay);
$(this).removeClass('hover').find('.level-2').fadeOut(fadeDuration);
});
When the string you pass to setTimeout is eval()ed, this is window and not whatever object you are expecting.
Don't pass strings to setTimeout, and be careful to preserve the value of this.
var self = this;
setDelay = setTimeout(function () {
$(self).addClass('hover').find('.level-2').fadeIn(200);
}, 500);
You can't use this in the setTimeout-code, since this depends on the context. So when the timeout fires, the this is a different this... bad English, but hopefully it makes sense.
Also, avoid using strings in timers; use functions instead. While you can use a string, which is then evaluated as JavaScript, it's generally bad form compared to simply wrapping the same code in a function
var fadeDuration = 200;
var setDelay;
$level1Item.hover(function () {
var element = $(this);
setDelay = setTimeout(function() {
element.addClass('hover').find('.level-2').fadeIn(fadeDuration);
}, 500);
}, function () {
clearTimeout(setDelay);
$(this).removeClass('hover').find('.level-2').fadeOut(fadeDuration);
});
I have a banner rotator and I wanted to use objects instead of functions so I could make the code more efficient. Anyway I can't seem to get setInterval to work. I think it's got something to do with the object reference. Can anybody explain this? Here's what I've got so far:
window.addEvent('domready', function() {
function set_banner(divid, array)
{
var banner = $(divid);
banner.set('html', '<img src="" alt=""/>');
var banner_link = $(divid).getElement('a');
var banner_image = $(divid).getElement('img');
var delay = 0;
for (var keys in banner1array) {
var callback = (function(key) { return function() {
banner.setStyle('opacity', 0);
var object = array[key];
for (var property in object) {
if (property == 'href') {
var href = object[property];
}
if (property == 'src') {
var src = object[property];
}
}
if (!banner.getStyle('opacity')) {
banner.set('tween', {duration:1000});
banner_link.setProperty('href', href);
banner_image.setProperty('src', src);
banner.tween('opacity', 1);
}
}; })(keys);
setTimeout(callback, delay);
delay += 21000;
}
}
var banner1 = set_banner('banner1', banner1array);
setInterval(function() {set_banner('banner1', banner1array);}, 84000);
var banner2 = set_banner('banner2', banner2array);
setInterval(function() {set_banner('banner2', banner2array);}, 84000);
});
A couple of simple mistake:
var banner1 = new set_banner('banner1');
^ ---------- creates a new object and uses set_banner as the constructor
your code already gets called here
and you get a new object back, which in this case has NO use
....
setInterval(banner1(), 42000);
^----------------- The parenthesis EXECUTE the function
the RETURN VALUE is then passed to setInterval
BUT... banner1() is NOT a function, so this fails
What you want to do in case that you want to call set_banner after 42 seconds AND pass a parameter is to use an anonymous function which then calls set_banner.
setInterval(function() { // pass an anonymous function, this gets executed after 42 seconds...
set_banner('banner1'); // ...and then calls set_banner from within itself
}, 42000);
Something else to consider: http://zetafleet.com/blog/why-i-consider-setinterval-harmful.
(tl:dr Instead of setInterval, use setTimeout.) While I'm not sure that his arguments apply here, it seems like a good thing to get in the habit of avoiding.
function defer_banner(div, bannerArray, delay) {
setTimeout(function() {
setBanner(div, bannerArray);
defer_banner(div, bannerArray, delay);
}, delay);
});