I'm converting some javascript to jQuery from ExtJS and I don't know what this does so I'm not sure what it converts to...
hideTimeout = setTimeout(this.hideAll.createDelegate(this), delay);
delay = 200
What I'm not sure about is the createDelegate(this)...
update
All the JS is...
Menu.prototype = {
init: function () {
var that = this;
this.ui.link.bind("mouseover", function (e) {
that.show();
});
this.ui.link.bind("mouseout", function (e) {
that.hide();
});
var subOptions = $("li", this.ui.parent);
$.each(subOptions, function (el) {
el = $(el);
el.bind("mouseover", that.cancelTimeout, this);
el.bind("mouseout", that.hide, this);
});
},
hideAll: function () {
$("#hd .nav ul ul").hide();
},
show: function () {
this.hideAll();
this.cancelTimeout();
showTimeout = setTimeout((function () {
this.el.show();
}).createDelegate(this), delay);
},
hide: function () {
this.cancelTimeout();
hideTimeout = setTimeout(this.hideAll.createDelegate(this), delay);
},
cancelTimeout: function () {
clearTimeout(hideTimeout);
clearTimeout(showTimeout);
}
};
Because you're in a setTimeout, this will represent the window object.
I don't know ExtJS, but it appears to be creating a delegate handler on the window.
Probably best to reference the ExtJS docs. According to the docs for createDelegate:
Creates a delegate (callback) that sets the scope to obj. Call directly on any function. Example: this.myFunction.cre...
EDIT: I believe it would be called like this:
hideTimeout = setTimeout($.proxy( this.hideAll, this), delay);
It will ensure that when hideAll is called, it will be called in its current context.
You can do the same thing for the anonymous function passed to setTimeout in show:
showTimeout = setTimeout($.proxy(function () {
this.el.show();
}, this), delay);
You can accomplish the same thing with jQuery like so:
hideTimeout = setTimeout(jQuery.proxy(this, "hideAll"), delay);
EDIT: Since the method hideAll doesn't contain a reference to this, you can accomplish this even more simply:
hideTimeout = setTimeout(this.hideAll, delay);
Related
Given code snippet of code does not stop even though I'm using setTimeout in it.
var myObj = {
myFunc: function () {
var self = this;
var timer = setTimeout(function () {
console.log('Timeout called');
self.myFunc();
}, 100);
}
};
myObj.myFunc();
myObj = null;
Inside the setTimeout callback, the given code recursively calling myFunc (self.myFunc()), that's why it is going forever.
I have a HTML page with two buttons and I want to use setInterval to evaluate the function multiple times when I click the start button. This works just fine but I can't clear the interval. What am I doing wrong?
function intFunc (func, time) {
interval = setInterval(func, time);
}
$("#startButton").on("click", intFunc(function () {
$.post('link/to/php.php', function(data) {
//do something with data
});
}, 1000));
$("#stopButton").on("click", function () {
clearInterval(interval);
});
First, as the comments suggest you should declare interval above to make sure the scope is clear.
Second, you have a syntax problem. You're invoking intFunc straight away, and passing the result to $("#startButton").on(). This isn't what you want. What you should be passing as that second argument is a callback function. You could reorganize your code like this perhaps:
Third, declaring within a self invoking anonymous function will prevent pollution of the global scope.
(function() {
var interval;
$("#startButton").on("click", function(){
interval = setInterval(function () {
$.post('link/to/php.php', function(data) {
//do something with data
});
}, 1000);
});
$("#stopButton").on("click", function () {
clearInterval(interval);
});
})();
This is how you should (or could) have written it:
var interval;
$("#startButton").on("click", function(){
interval = setInterval(function () {
$.post('link/to/php.php', function(data) {
//do something with data
});
}, 1000);
});
$("#stopButton").on("click", function () {
clearInterval(interval);
});
You cannot use functions like that, because when you write:
$("#startButton").on("click", intFunc(..));
You are executing intFunc immediately, and that doesnt return anything.
I want to run delay function as part of my underscore chain.
It seems like delay function is only able to work with explicit argument passed - not the wrapper object.
This code does not work (undefined is not a function exception):
var message = function (text) {
var txt = text;
var show = function () { alert(txt); };
return {
Text: txt,
Show: show
};
};
_.chain(new message("hello")).delay(function(m) { m.Show(); }, 1000);
This code works:
var x = _.chain(new message("hello")).value();
_.delay(function (m) { m.Show(); }, 1000, x);
Is there a way to make delay work inside of a longer functional expression?
E.g. I want to defer viewmodel instance creation and then delay binding to UI by X ms.
What chain() does in underscore is just pipe its argument through all the following functions, passing it as first argument to those functions.
Since first argument to delay() should be a function then to achieve functionality you desire you'd have to do something like this:
_.chain(function(m) {
m.Show();
}).delay(1000, new message("hello"));
but I guess it doesn't have the structure you desire.
So you can't use delay() directly, but you can use it via tap():
_.chain(new message("hello"))
.tap(function(m) {
_.delay(function() {
m.Show();
}, 1000);
})
or even more concisely with use of tap() and bind():
_.chain(new message("hello"))
.tap(_.delay.bind(null, function(m) {
m.Show();
}, 1000))
If you wan't to pass in collection to chain() and do a delay() for every element of the collection use each() instead of tap().
The following is not an answer as it uses rather github.com/kriskowal/q promises than underscore.js but that's what I think you are trying to do, namely push something through a pipeline of operations some of them async:
var message = function (text) {
var txt = text;
var show = function () { alert(txt); };
return {
Text: txt,
Show: show
};
};
function delay(time) {
return function(m) {
var next = Q.defer();
setTimeout(function() {
next.resolve(m);
}, 1000);
return next.promise;
}
}
Q.when(new message("hello"))
.then(delay(1000))
.then(function(m) {
m.Show();
});
The first argument of _.delay must be a function, but u pass a instance if message class (object).
f.e.
var foo = function(){
console.log('FOO');
}
_.chain(foo).delay(200);
And to use chain in your case is overhead. Try something like that:
var showMsg = function(){
var msg = new message("hello");
msg.Show();
};
_(showMsg).delay(200);
I have to animate an element in an sync way (that is to wait until the animation (fadeIn() in this example) is completed, so I can propertly continue).
As fas as I know I have three options:
doSomething: function () {
$('.someElement').fadeIn(function () {
// do something else here...
});
}
Another approach (using $.proxy() to alter the context):
doSomething: function () {
$('.someElement').fadeIn($.proxy(function () {
this.doSomethingElse();
}, this));
},
doSomethingElse: function () {
// ...
}
However, since using $.proxy() kinda "mixes" the contexts and I really don't like this (because I just don't know when it'll come back and bite my ass off), I'm sometimes using this approach:
doSomething: function () {
$('.someElement').fadeIn(function () {
doSomethingElse();
});
function doSomethingElse () {
// ...
}
}
Now I'm wondering, is there any better approach? Something simpler and more elegant. Like:
doSomething: function () {
$('.someElement').fadeIn(function () {
// do this in an async way...
});
// simply do something else here...
}
This problem really bugs me, because I like clean code and I don't like this simple, yet un-clean solutions.
Create a mediatory variable to refer to your original object:
doSomething: function () {
var that = this;
$('.someElement').fadeIn(function() {
// use "that" here
});
}
If doSomethingElse() is another animation, you can chain and queue them mantaining the original context.
I have this Javascript class:
function PageManager () {
this.timeoutHandler = function () {
alert ("hello");
}
this.startTimeout = function () {
this.timeout = setTimeout ("this.timeoutHandler()", 1000);
}
}
When I call obj.startTimeout (); I get this error:
this.timeoutHandler is not a function
How do I call a class function in the timeout?
If you pass a string to setTimeout, the code is evaluated in the global scope. Always pass a function reference:
this.startTimeout = function () {
var self = this;
this.timeout = setTimeout(function() {
self.timeoutHandler();
}, 1000);
}
Or if you don't need a reference to the object inside timeoutHandler, then you can pass the function directly:
this.timeout = setTimeout(this.timeoutHandler, 1000);
The problem is that you're passing setTimeout a string. This string is eval'd, with a scope of the window. So if you were to do this:
this.timeout = setTimeout ("console.log(this);", 1000);
... with Firebug installed, you'd see that this is window, which does not have a timeoutHandler method, of course.
This is why you should never, ever pass setTimeout a string. Give it a function reference instead.
function PageManager () {
this.timeoutHandler = function () {
alert ("hello");
console.log(this);
}
this.startTimeout = function () {
this.timeout = setTimeout (this.timeoutHandler, 1000);
}
}
obj = new PageManager ();
obj.startTimeout();
When you execute this code, you'll have the scope you're expecing.