I have a simple jquery popup plugin. The usage looks like this:
$("#popupContainer").popup({
onOpen: function () { },
onClose: function () { }
});
$("#popupContainer").popup("open", "/Home/PopupContent");
$("#popupContainer").popup("close");
This works good.
However, i want to pass a different onOpen callback for different url's i have. So i thought about making a wrapper over the plugin, like this:
var popupPlugin = {};
(function () {
var onOpen = null;
var onClose = null;
$("#popupContainer").popup({
onOpen: function () {
if (onOpen) {
onOpen();
}
onOpen = null;
},
onClose: function () {
if (onClose) {
onClose();
}
onClose = null;
}
});
popupPlugin.open = function (url, callback) {
onOpen = callback;
$("#popupContainer").popup("open", url);
}
popupPlugin.close = function (callback) {
onClose = callback;
$("#popupContainer").popup("close");
}
}());
// usage
popupPlugin.open("/Home/PopupContent", function () {
// specific callback
});
This works as expected (i now have different callbacks), but i am worried that i am creating memory leaks somehow.
Is the implementation of the popupPlugin wrapper good?
Related
so i have a function which checks if a checksum is changed and if so it calls the callback which is provided by a parameter.
var watchFileChange = function watchFileChange(oldChecksum, callback){
// some code about checking checksum
if(oldChecksum != newChecksum){
callback()
}
}
exports.watchFileChange = watchFileChange;
my Jasmin specs looks like this.
var t = require('../server.js');
describe("watchFileChange", function() {
spyOn(t.watchFileChange, 'Callback');
var file_false = {
'foo.txt': 'd41dcccc8f00b204e9800998ecf8427e'
}
var file_true = {
'foo.txt': 'd41d8cd98f00b204e9800998ecf8427e'
}
function Callback() {
console.log("Callback Called")
}
it("Checksum is not right, it should call Callback function", function() {
watchFileChange(file_false, Callback);
expect(Callback).toHaveBeenCalled();
});
});
But it just doesn't work that way because Callback is not defined i get that. So my question is there a way to check if the by parameter provided callback is called?
You can create a fake object where you can define you callback function, and then pass it as the argument
var init = {
callback: function() {
console.log("Callback Called")
}
};
describe("watchFileChange", function() {
beforeEach(function() {
spyOn(init, 'callback');
});
//...
it("Checksum is not right, it should call Callback function", function() {
watchFileChange(file_false, init.callback);
expect(init.callback).toHaveBeenCalled();
});
});
http://jsfiddle.net/hRksW/
function test() {
this.alerting = function () {
alert("test");
};
this.something = function () {
setInterval(function () {
this.alerting();
}, 1000);
};
}
var a = new test();
a.something();
Calling the function something() should call the function alerting() every second. This should alert 'test' every second. Why doesn't that happen and how can I make it happen? Note that I want to keep this design of calling a method in a method, if possible.
Store a reference of this in a variable and use it for method that run outside of the current context (like the setInterval does)
function test() {
var that = this;
this.alerting = function () {
alert("test");
};
this.something = function () {
setInterval(function () {
that.alerting();
}, 1000);
};
}
var a = new test();
a.something();
http://jsfiddle.net/N6hPB/
function test() {
this.alerting = function () {
alert("test");
};
this.something = function () {
setInterval(this.alerting, 1000);
};
}
var a = new test();
a.something();
Hope this helps! Here the timer is in ms.
function something(){
window.setInterval(alerting, 1000);
}
function alerting() {
alert('test');
}
Another way to do it is returning an object instead.
function test() {
var self = {
alerting : function () {
console.log("test");
},
something : function () {
setInterval(function () {
self.alerting();
}, 1000);
}
};
return self;
}
var a = new test();
a.something();
You can do it making an object with functions, and then call them without instantiating it.
var testCaller = {
alerting: function() {
alert("test")
},
something: function() {
// Store current scope
var self = this;
setInterval(function() {
self.alerting();
}, 1000);
}
}
testCaller.something();
You can try this code. I have tested it, and it works. In your code, "this" pointer points to somewhere else.
function test() {
test.prototype.alerting = function() {
alert("alert test");
};
test.prototype.something = function () {
setInterval(this.alerting, 1000);
};
}
var a = new test();
a.something();
Creating the closure is easy but using it is confusing for me. Here is my closure. Once I have it I need to be able to call operations on it like doWork, calculateThis, doAnimation, etc. but there doesn't seem to be a way to access functions inside the closure.
function worker(input) {
return function () {
doWork = function () {
alert("doing work");
};
}
}
function caller() {
var myWorker = worker();
myWorker.doWork(); // this fails
}
*The question you're asking appears subjective and is likely to be closed. - Thanks again stackoverflow
I believe this is what you are asking for:
function worker(input) {
return {
doWork: function () {
alert("doing work");
},
doAnimation: function() {
alert("animating");
}
}
}
You can now call it using your code:
var myWorker = worker();
myWorker.doWork();
myWorker.doAnimation();
Note that your code is not really using closures, but this one does:
function worker(input) {
return {
doWork: function () {
alert("doing work: " + input);
},
doAnimation: function() {
alert("animating: " + input);
}
}
}
var workerA = worker('A');
var workerB = worker('B');
workerA.doWork();
workerB.doAnimation();
Can you see the difference?
You are trying to execute a method work() but in your example you return a function, not an object with a property "work".
Here's what you're probably after:
function worker(input) {
return {
work: function () {
alert("doing work");
};
}
}
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.
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);