Cannot pass jQuery object.method to another function to be executed - javascript

I have the following JavaScript:
function MyMethod(func)
{
func();
}
$('#Btn').on('click', function(e)
{
e.preventDefault();
var form = $(this).parent();
MyMethod(form.submit);
});
http://codepen.io/chrisnicholson/pen/YGxOdJ
This doesn't work, giving the following error in Chrome:
jquery.min.js:4 Uncaught TypeError: Cannot read property 'trigger' of undefined
If I modify the call to MyMethod to use the following then it works:
MyMethod(function(){
form.submit();
});
http://codepen.io/chrisnicholson/pen/amyRXX
Can someone explain why this is?

Ah, good ol' binding of this at work! If you only provide the method, it will not be called on the form but on the global object, like
submit.call(window) // resp. undefined in strict mode. Hence the error, I guess.
where what you want is
submit.call(form)
One way to fix this: Bind the submit method to the form:
MyMethod(form.submit.bind(form));

Your code be. Just pass the object is enough.
function MyMethod(formSubmit)
{
formSubmit.submit();
}
$('#Btn').on('click', function(e)
{
e.preventDefault();
var form = $(this).parent();
MyMethod(form);
})

Without the parentheses, .submit would just be a property of the jQuery object that you have. In this instance, your form.
Adding the parentheses actually calls the .submit() method on the form object.

Related

i have an javascript function that not working

function filter_effect(effect_name){
var tmp_img = document.createElement("IMG");
tmp_img.src = get_cropped_image()
tmp_img.style.display = "none"
Caman(tmp_img, function (){
this[effect_name]();
this.render(function () {
change_picture(this.canvas.toDataURL("image/jpeg"))
});
});
}
this is my code and when I run this I get this error
Uncaught TypeError: this[effect_name] is not a function
Can anyone help that what I should do to fix this?
You should change your function call and pass the this. Change this line, it would be solved:
Caman.call(this, tmp_img, function (){
/* Your callback function body */
});
Here this means the filter_effect function. When you want to change the this object in function calls, you have to use .apply() or .call() to change it.
Here is a reference for this post.
You have to clarify 'this' reference value, it must be refer to a javascript object which effect_name property of which be declared as function, use browser's debugger to have scrutiny over it's value

Uncaught TypeError: Illegal invocation on callback

function submit() {
console.log('Submit!');
}
function foo(callback, param) {
console.log(callback);
// ... //
callback(param); // <-- Script fails here
}
<input type="button" onclick="foo(submit)">
Why isn't this working?
function submit() { [native code] } foo.js:241
Uncaught TypeError: Illegal invocation
Intrinsic event attributes (like onclick) have weird scoping rules that I don't pretend to fully understand.
submit inside the attribute is the submit property of the form element to which the input belongs.
Either:
Explicitly pass window.submit
Rename the function to something else or
Bind your event handler with JavaScript instead of HTML.
I'd go the latter route myself on general principles (taking the opportunity to stop using globals), and consider renaming the function anyway to minimise confusion.
<input type="button">
<script>
// Scoping IIFE omitted from this simplified example
var button = document.getElementsByTagName('button')[0];
button.addEventListener("click", function () { foo(submit); });
function submit // etc etc
</script>

Why must callbacks in jQuery be anonomous?

This works just as expected but I don't like it.
$('#login-form').on('submit', function(event){
event.preventDefault();
init.login();
});
var init = {
login: function() {
// do login stuff
}
};
This is what I want but it does not work.
$('#login-form').on('submit', init.login(event));
var init = {
login: function(event) {
event.preventDefault();
// do login stuff
}
};
Why?
It will work, you're calling the function (the value given as a callback will be the result of the function) rather than passing it as a value
$('#login-form').on('submit', init.login);
init.login(event) calls the function init.login, passing the (non-existent) variable event to it. If you want to pass the function itself as callback, don't call it:
$('#login-form').on('submit', init.login);
You will have to declare that function before you pass it though, at this point init.login is undefined.
You're already calling the function in that line (with undefined, there is no event yet). You need to pass the function itself (not its result):
$('#login-form').on('submit', init.login);
Notice that init.login is still an anonymous function, it has no name :-) Also beware that the method is called with this being the login form element, not the init object. If you needed that, you'd use .on('submit', init.login.bind(init)).

Using $(this) & event in named handler function

I have this function:
function showPost(event){
event.preventDefault();
$(this).parent('article').animate({width:'100%'}, 'slow');
}
I am attempting to use it like so:
$('.article-header').click(function(event){showPost(event);});
When I use it in the above manner, the event property is passed just fine, however $(this) doesn't work within the function. If I attempt to include this as a parameter in the .click method, it returns an error claiming this is undefined. I have even gone so far as to set var ths = $(this); to no avail.
Please, what is the proper way to make this function happen?
Just use the function directly:
$('.article-header').click(showPost);
You're loosing this because you're calling the function "naked", with no object receiver. You could do this too (but don't because there's no point here):
$('.article-header').click(function(event) { showPost.call(this, event); });

Underscore bindAll: preserving the 'this' context

I am having issues attempting to preserve uploader as the this context when onSubmit is called. Can any JS gurus help out?
uploader: {
init: function(){
var that = this;
var fileUploader = new Uploader.FileUploaderBasic({
button : $("#upload-btn")[0],
action : "/filesCollection",
onSubmit : that.onSubmit
});
_.bindAll(this, this.onSubmit); // attempting to bind 'this'
},
onSubmit: function(id, fileName){
console.log(this); // still refers to 'fileUploader' object :(
}
}
Results in the following error:
Uncaught TypeError: Cannot read property 'bind' of undefined
Example: http://jsfiddle.net/WilsonPage/BE3Lp/5/
Problem Solved: http://jsfiddle.net/WilsonPage/BE3Lp/41/
Several Important Things I Discovered:
The _.bindAll() must be called before the function is assigned.
The first argument must be the object or this you wish to bind.
The arguments that follow must be the names of the functions present within the object (this) and they must be in string form!
If you want to bind all functions in the object (this) then omit any function names and have the object (this) as the only argument eg. _.bindAll(this)
Hope this helps some confused peeps like me!
By using call or apply you can specify the context for this for any function. This should do the trick (in the fileUploader declaration):
onSubmit: function() {
that.onSubmit.apply(that, arguments);
}
Edit: Updated jsfiddle: http://jsfiddle.net/WDTBV/1/

Categories

Resources