'This' scope in TypeScript - javascript

On my webpage I have remove icons on rows in a table like this:
I am using TypeScript where I have attached an onClick listener to execute a function called OnRemoveClick, like this $('.remove').click(this.OnRemoveClick);
OnRemoveClick zeros 2 fields (on the row the remove icon is clicked) and then executes 2 functions, like this:
private OnRemoveClick(): void {
$(this).parents('tr').find('.input-qty').val('0');
$(this).parents('tr').find('.sub-total').html('0');
this.GetInputFieldsToJson();
this.CalculateTotal();
}
The problem I have is that it falls over when I get to GetInputFieldsToJson I get:
TypeError: this.GetInputFieldsToJson is not a function at
HTMLAnchorElement.Index.OnRemoveClick
I realise it is because this in the context of OnRemoveClick is attached to the HTMLAnchorElement which means I cannot access my functions from there.
What I have tried
I have tried setting the onClick listener with a lambda expression like this:
$('.remove').click(() => this.OnRemoveClick);
but that means that the two jQuery expressions to zero fields on the row no longer work

As you might have already understood, the problem here is, when the event handler is invoked the default context as the dom element which triggered that event. So you are unable to invoke your object's method using that reference.
There are multiple solutions to this problem, one easy solution is to pass a custom context to the callback function using Function.bind() as given below and access the targeted element using Event.currentTarget in the callback like
private OnRemoveClick(e): void {
$(e.currentTarget).parents('tr').find('.input-qty').val('0');
$(e.currentTarget).parents('tr').find('.sub-total').html('0');
this.GetInputFieldsToJson();
this.CalculateTotal();
}
then
$('.remove').click(this.OnRemoveClick.bind(this));

$('.remove').click(() => this.OnRemoveClick); should be $('.remove').click(() => this.OnRemoveClick()); i.e. call the function.
More on this : https://www.youtube.com/watch?v=tvocUcbCupA

Related

Call a function saved to a variable that has an event handler attached to it

Hi I am currently trying to call a function that is saved to a variable, but also has an event handler on it.
col.onclick = function(e){
}
I have not been able to find how to call this kind of set up, and was wondering if it's possible at all, and if it can be done without using jquery.
Help would be nice, thanks in advance.
http://pastebin.com/JJYQeZDG //Code that is the root of the problem.
This code is for a game of checkers, for context.
Simply use () like any other function.
Based on your comments, it looks like you may also have a scoping issue.
I would recommend refactoring your code so your onclick function can be accessed without needed the col object:
var onclick = function(e) {
// note: you will only have "e" if this is invoked as an event callback
};
// later when defining col
col.onclick = onclick;
// ...and later when you want to directly invoke onclick
onclick();

Access parent scope inside child element's onclick callback (Atom Package)

I'm not sure how you're normally supposed to handle this within Atom Packages, but this is the situation:
I created a beautiful button
playButton = document.createElement('button');
playButton.onclick = #funkyFreshCallback;
This will call my callback defined as so
funkyFreshCallback: (event, element) ->
console.log(#);
Now, what I want is to be able to use the element's parent scope.
See the # symbol? Right now it returns the button element (because that's the current this, I know)
Now how do I access the scope instead? The same one that defined funkyFreshCallback?
Also, it really doesn't feel like this is how I should be doing things but I haven't found much documentation... at all.
You can bind the parent context onto the function before setting it up as the event handler.
playButton.onclick = #funkyFreshCallback.bind(#);
Another way to avoid the context issue is to setup a function that calls funkyFreshCallback. The event handler should only handle the event and then pass along the minimum set of required data to the callback, like so:
playButton.onclick = (event, element) =>
timePressed = Date.now();
#funkyFreshCallback(timePressed);
With the code above, funkyFreshCallback will be called with the context that you expect, and won't receive a really complex event object as an argument. This helps to make writing unit tests for funkyFreshCallback easier, and it should simplify your callbacks, because they won't have to deal with events.
More on that in Chapter 7 of Maintainable JavaScript

Basic JQuery syntax: What mechnaic is at work in this small (2 line) piece of JavaScript / JQuery

So here' s the piece of code. I'm very new to JavaScript so don't be afraid to explain the obvious
$(".my-css-class").on("click", function() {
($(this).attr("data-property-1"), $(this).attr("data-property-2"), this);
});
There's an element in the .jsp page that looks like this:
<i class="clickMe"></i>
I know the .jsp creates a link-icon, and that the above JavaScript is an event handler. I know that it passes these 3 values as arguments another JavaScript method:
function doStuff(prop1, prop2, obj) {
if (prop1 == 'foo') {
//do stuff with prop2
}
else{
// do stuff with obj
}
}
It all works fine. What I want to know is what exactly is going on to make it work? I can't find anything in the code that connects what the event-handler returns to the 'doStuff' java-script function.
The names are totally different, so it's not reflection, it can't be parameter matching because there's other functions with the same number and type of parameters in the file, it can't be convention based because it still works if I find/replace the name of the function to gibberish.
I guess basically I'm asking what this line is doing:
($(this).attr("data-property-1"), $(this).attr("data-property-2"), this);
tl;dr: I'm at a loss, I know how the properties get as far as the onClick event-handler's anonymous function - but how does JavaScript know to pass them as arguments the to the doStuff() function?
the onClick event is a standard event triggered on click of any clickable html element and is automatically raised by the DOM.
You are hooking in to this by listening on any matched ".my-css-class" elements for an onClick Event.
The jquery syntax ".on" has been simplified over time and allows you to hook into any number of events like "submit" - OnSubmit event , or "load" - onLoad Event
Wherever your on("click", myFunction) event hook is picked up, your myFunction will execute.
Looking at your second point...
because it still works if I find/replace the name of the function to gibberish.
The DoStuff function will be found and replaced across all files in your site? or page? or open tabs? , so therefore it must exist somewhere as "doStuff(" or "giberish(".
so when you do a global find/replace, do each one slowly, until you locate it.
Finally, when you do a view source in the browser, this should either explicitly show you the doStuff function, or at the very least give you a clue as to satelite files loaded at runtime, where you can go and investigate.
Use firebug in firefox to debug loaded resources; the ".net tab" to view external loaded resources and the html/javascript they might contain. (for example: your master page might be loading in an embeded resource that contains the doStuff method, becuase of a user or server control reference in that master page)
Also have a look at this:
http://www.developerfusion.com/article/139949/debugging-javascript-with-firebug/
You can step through the javascipt piece by peice until it hits the doStuff method.
Just remember to set at least 1 breakpoint ;-)

jQuery.off not working with a variable function name

I'm using a modular pattern for writing my Javascript code, and it is totally fun! But I'm stuck very badly at one situation.
My Namespace is as follows:
var settings, handlers, objects,
Namespace = {
handlers: {
//All event handlers go here
},
objects: {
//All jquery button references go here
},
init: function(){
//Initial stuff
}
};
//Call init with the Namespace
I have a button which toggles between two different handlers for a mousedown event on a single object (a div), and handlers are properties of the handlers object. On init, one handler is automatically on to the div and works fine. Now when I click the toggle button, I'm trying to turn off the first handler so I can turn on the other, but it isn't working!
I turn on my first mousedown event handler (or all handlers for that matter!) like this:
Namespace.objects.someObject.on('mousedown', Namespace.handlers.mouseDownHandlerOne);
This works fine. When I try to turn it off like this:
Namespace.objects.someObject.off('mousedown', Namespace.handlers.mouseDownHandlerOne);
It doesn't work! No errors or warnings. If I just use off with mousedown without passing the handlers name, it works. But I need to separate between 2 different handlers!
How should it be done in a modular js environment?
Jquery .off method can take up to 3 arguments, use the following code:
Namespace.objects.someObject.off('mousedown', '**', Namespace.handlers.mouseDownHandlerOne);

Can you bind to jQuery events with plain JavaScript?

I'm working on a project where a number of different companies are working on the same site.
The main developer have set up an event - let's call it init - which indicates the page is ready for our code to execute.
They're basically calling it like this:
$(window).trigger('init');
For a number of reasons I won't go into here, we prefer to avoid using jQuery in our own code wherever possible. I tried to bind to it like this:
window.addEventListener('init', function (event) {
alert('hehehehe');
});
But that doesn't seem to work. This works perfectly, though:
$(window).bind('init', function (event) {
alert('hehehehe');
});
Does jQuery use special event objects by default that you can't bind to with plain JS? Am I just doing something stupid?
The docs for bind seem to contain the answer:
Any string is legal for eventType; if the string is not the name of a native DOM event, then the handler is bound to a custom event. These events are never called by the browser, but may be triggered manually from other JavaScript code using .trigger() or .triggerHandler().
There's no native DOM event called 'init':
http://en.wikipedia.org/wiki/DOM_events
Hence "These events are never called by the browser, but may be triggered manually from other JavaScript code using .trigger() or .triggerHandler()"

Categories