Trigger function from object using dynamic key - javascript

I'm struggling on triggering a function which is defined in an object, by pointing to it using a dynamic key. My code looks something like this:
$(function(){
var events = {
Test : function(){
console.log ('init');
}
}
$('#trigger').click(function(){
var e = $(this).data('event');
events[e];
});
});
So basically, there is some element #trigger with an attribute data-event="Test" (or something else), once it gets clicked I check the events object if there is a function defined for that trigger and fire it. However, it doesn't work this way. I can console log the events object but the function isn't executed. What am I doing wrong?
Thanks!

Invoke the function with ()
$('#trigger').click(function(){
var e = $(this).data('event');
events[e]();
// ^^this
});
DEMO

Related

Adding a function with parameter to a variable

I have a function that receives an argument:
function test(arg)
{
alert(this.id);
alert(arg);
}
I want to attach this function to a variable:
variable.addEventListener('mouseup',function (ime_igraca) {
test(ime_igraca);
});
And I want this in function test to refer to the variable on which mouseup happened.
It's just impossible: You can't attach an eventlistener to a variable because a variable that not supports events !
You have more informations here (MDN documentation ;) )
But, why you want to add an addEventListener to your variable ? What is your problem ? And where does the variable ime_igraca come from ?
Edit
Maybe you just want to send existing variable to a listener like that :
JS
let myElement = document.getElementById('myElementId');
let ime_igraca = "Foo";
myElement.addEventListener('mouseup',function () {
test(ime_igraca);
});
function test(arg) {
console.log(arg);
}
HTML
<button id="myElementId">My Button</button>

How to use jQuery events on non-DOM-related objects and their properties?

I need to use jQuery events on non-DOM-related objects.
This works fine:
var o = {
}
$(o).on('bump', function () {
alert('ouch')
})
$(o).trigger('bump')
http://jsfiddle.net/d35bf35y/
But instead I need to attach an event on a property... the following code does not work.
var o = {
prop: 'test'
}
// Bind an event handler
$(o.prop).on('bump', function () {
alert('ouch')
})
// Trigger an event
$(o.prop).trigger('bump')
http://jsfiddle.net/d35bf35y/1/
In my real application that property will have an object.
I would like to know if is possible use jQuery in this way or an alternative solution.
"In my real application that property will have an object."
That part is rather important. This works:
var o = {
prop: {}
}
// Bind an event handler
$(o.prop).on('bump', function () {
alert('ouch')
})
// Trigger an event
$(o.prop).trigger('bump')
You can attach one on the Object and everytime it fires, you run a function that does something with your properties. (check if they're the same, or else)
var o = {
prop: 'test'
};
$(o).on('bump', function (e) {
var props = e.delegateTarget;
// do what you gotta do, like check if something has changed from before.
})
$(o).trigger('bump')
Or if your property is also an object, it should work.

Javascript convert string to be called as function

I have the following scenario where I need to call a function based on the data attributes of the html element.
function func1(arg1){
alert("func1");
}
function func2(arg2){
alert("func2");
}
jQuery(document).on('click', '.func-class', function(){
var funcName = jQuery(this).data('func-name');
var funcArg = jQuery(this).data('func-arg');
//Need to call funcName(funcArg) here
});
HTML:
<div data-func-name="func1" data-func-arg="arg1" class="func-class">Func1</div>
<div data-func-name="func2" data-func-arg="arg2" class="func-class">Func2</div>
JSFiddle of the same:
http://jsfiddle.net/E4HeT/
If those functions are defined in ths global scope, you can do this:
window[funcName](funcArg);
Otherwise, I would suggest putting them in an object like so:
var functions = {
"func1":func1,
"func2":func2
};
functions[funcName](funcArg);
This second one is actually safer, as it helps prevent arbitrary code execution.
you can do like the following this
window[funcName](funcArg)
but you will have to get the reference of the function by setting it in a object for example (like what i did in the window object) because its private in the jQuery.ready function
$('.func-class').click(function(){
var toCallArg = $(this).data('func-arg');
var toCall = function(toCallArg){
//your code
};
toCall(toCallArg);
});

Javascript object methods and binding functions

I'm looking for some help because I don't quite think I understand the Javascript scoping rules. What I'm trying to do in the below example is to push a button on a page that then starts listening for keyboard input. Once the keyboard input has started if there is a break in input for two seconds I want to stop capturing the input and pop an alert with the full contents of the input collected to that point. This is an example I made purely for this question.
What I see is that I click the button and start entering input. On each keypress I am alerted to the string collected to that point. After the two second, no-action timeout takes place I see an alert with the contents "undefined". The first alerts listed above come from startLog(). The second alert comes from stopLog(). What am I doing wrong when I call stopLog that it is telling me that this.message is undefined?
function Logger() {
this.message = '';
this.listenTimer;
this.startLog = function() {
this.message = '';
$(document).bind('keypress', {this_obj:this}, function(event) {
event.preventDefault();
var data = event.data;
clearTimeout(data.this_obj.listenTimer);
data.this_obj.message += String.fromCharCode(event.which);
alert(data.this_obj.message);
data.this_obj.listenTimer = setTimeout(data.this_obj.stopLog, 2000);
});
};
this.stopLog = function() {
$(document).unbind("keypress");
alert(this.message);
};
}
var k = new Logger();
$('.logging-button').click(function() {
k.startLog();
});
The issue is this. When you pass an object method as an event handler, it loses its object context; this will refer to the window object.
There are various ways to fix this, but the main issue is that you need to pass setTimeout a closure that will still refer to the correct context:
setTimeout(function() { data.this_obj.stopLog() }, 2000);
On a separate note, you can save yourself some unnecessary code by just using a closure to refer to the object, rather than binding it as event.data:
this.startLog = function() {
this.message = '';
var this_obj = this;
$(document).bind('keypress', function(event) {
event.preventDefault();
clearTimeout(this_obj.listenTimer);
// etc
});
};
var k = new Logger();
$('.logging-button').click(function() {
k.startLog.apply(this);
//Setting context of "this" so that it refers to element even in startLog()
});

Properly wrapping functions in JavaScript

I have the following problem:
I have a function
workspace.func = function() {console.log(5);}
I attach it as an event handler:
$(workspace).bind("ping", workspace.func);
Then, I change the function definition:
var cF = workspace.func;
workspace.func = function() {
...
cf.call(this);
}
but
$(workspace).trigger("ping")
>>5
How can I properly wrap the function at runtime, so that the handler points to the changed one as well?
You can do it like this:
workspace.func = function() {console.log(5);}
$(workspace).bind("ping", function() {workspace.func()});
var cF = workspace.func;
workspace.func = function() {
...
cf.call(this);
}
After reassigning the value of workspace.func, the ping event handler will go to the new function because it gets the function pointer from the variable and then executes it so if you change which function that variable points to, it will pick up the new value - unlike your original version which had a reference to the actual function so changing the workspace.func variable didn't do anything.

Categories