I was going through the source of waypoints.js and came across the following function ::
NoFrameworkAdapter = function(event, handler) {
var eventParts = event.split('.')
var eventType = eventParts[0]
var namespace = eventParts[1] || '__default'
var nsHandlers = this.handlers[namespace] = this.handlers[namespace] || {}
var nsTypeList = nsHandlers[eventType] = nsHandlers[eventType] || []
nsTypeList.push(handler)
this.element.addEventListener(eventType, handler)
}
To understand this function, I wanted to console.log events so I wrote the below code:
var elem = document.getElementById('a');
handler = function(){console.log('test')};
elem.addEventListener(event , handler); // error is throw here .
Since I am passing event instead of event type to the add event listener, an error is thrown, but all I really want to do is to print the event to the console, so I can see the contents of it.
How can I do that? I know that I am missing something but I cannot find it.
The function concerned can be seen HERE ,
Related
I'm developing a cordova app and within it, I'm using an iFrame. I'm using the following code to communicate between the iFrame and the app itself:
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
var message = "";
var output = "";
eventer(messageEvent, function(e) {
message = e.data;
var data = JSON.parse(message);
for (var i = 0; i < data.messages.length; i++){
var msg = data.messages[i];
output = msg.msg;
alert(output); //*1
}
}, false);
I'm copying the code from here: https://davidwalsh.name/window-iframe
The alert inside the eventer at *1 show the output variable is what I want. But once outside of this eventer function, the variable output reverts to blank.
After some research I think it might because I'm creating a Window object, but I'm not sure if that's the case or exactly what it is.
How can I permenently modify the variable "output"? Thanks.
Try changing the for loop to this:
for (var i = 0; i < data.messages.length; i++){
var dataMsg = data.messages[i].msg;
output = dataMsg; alert(output); //*1
}
I don't know if there is an issue with assigning msg.msg to output.
The problem is with your understanding of how events work.
Judging from your comments, this is how you think it works:
// Ordering
var output = ""; // 1. Assign empty string to output
eventer(messageEvent, function(e) {
// assign value to output // 2. Assign value to output
});
alert(output); // 3. Print output
In reality, it works like this:
var output = ""; // 1. Assign empty string to output
eventer(messageEvent, function(e) {
// assign value to output // 3. Assign value to output
});
alert(output); // 2. Print output
The value is changed by your callback function, but you are accessing it in the wrong order. eventer, or in modern browsers, .addEventListener, registers a callback function. Your callback function will only get triggered after the current thread is finished. Of course it will print out an empty value, since alert is executed before you even changed its value.
If you are not familiar with the basics of event-based programming, I suggest you to take a look at this tutorial.
Just a side note, never use an iframe unless you have specific reasons of doing so. And also you do not need the first few lines since you are using Cordova. attachEvent is IE-specific.
As a general advice, try not to pollute the global scope with unnecessary variables in the future.
I read a lot of answers here in S.O. about finding events and event listeners but none suited me.
Probably I am missing something or doing something wrong because I am new to JS.
I am binding some events on the document like so:
var eventNames = [
'feedbackGiven',
'emailEntered',
'viewedOptin',
'agreedOptin'
];
var createEvents = function (eventNames){
for (var i=0; i < eventNames.length; i++){
// Create and Init the events to their types
var event = document.createEvent('Event');
event.initEvent(eventNames[i], true, true);
}
};
Later on I also bind some listeners but lets keep it short for now.
Now I want to test my code and see if indeed it creates the events. I am using Qunit for testing and I want to assert if the events are indeed created and initialised.
Is there a way to achieve that?
There is no problem
You want to test if the events are created. But I don't think you understand how events work.
You are creating an Event object, but not doing anything with it.
In fact, all but the last event object are unavailable after your for-loop (you overwrite the event var).
But back to your "check or an event is created" problem. You don't need to create an event to be able to use it.
Simply add an eventListner to an event you want to listen to:
document.addEventListener('myCustomEvent', function(e) {
console.log('The event object: ');
console.log(e); //the event object
});
then later on in your code, we can dispatch an event:
var e = new Event('myCustomEvent');
document.dispatchEvent(e);
that's it. The event object will be passed to all the callbacks attached with addEventListener
In DOM level 2 you can't, in level 3 (non yet supported) you will have eventListenerList that will do the job.
Actually you have to take an array for events.
You can build your addevent method:
var events = [];
var addEvent = function (event, node, fn) {
var i = 0, len = events.length, nullix = -1;
while (i != len) {
if (events[i] == null) {
if (nullix == -1) nullix = i;
i++;
continue;
}
if (events[i].event == event &&
events[i].node == node &&
events[i].fn == fn) {
return this;
}
i++;
}
if (nullix != -1) {
events[nullix] = {
event: event,
node: node,
fn: fn
}
} else {
events[events.length] = {
event: event,
node: node,
fn: fn
};
}
node.addEventListener(event, fn);
};
I need to write functions on the fly while avoiding the use of global variables. They'll be 'connected' to event listener.
I currently have a function to create a connection. They receive:
The object I want to connect
Two variables: IDX and id I have to identify some element that I want to use.
This is my code so far:
create_fun = function (obj, IDX,id) {
var f = function () {document.getElementById(IDX+"_"+id).display = "block";}
obj.addEventListener('click', f,false);
}
This code runs OK. I see in the Chrome Event Listeners Panel the click event connected to the objected that I wanted.
The Problem: IDX and id are variables, and as they are not globals, they are undefined.
At chrome Eventlistener inspection I see:
handler = function ()
{document.getElementById(IDX+"_"+id).display = "block";}
But, being IDX = "sec1" and id="3", I'd like to see :
handler = function ()
{document.getElementById("sec1+"_"+"3").display = "block";}
Is this possible? How would I do this?
The fix is given by Function constructor
var f = new Function ( "document.getElementById('"+IDX+"_"+id+"').style.display = 'block';" );
obj.addEventListener('click', f,false);
}
I am dynamically creating event listener for some events. In that event listener i want to do another emit call based on the event name, so i want to get the event listener name
I am using node.js eventemitter.
var events = require('events').EventEmitter;
var util = require('util');
.....
.....
for(i in events) {
transport.on(events[i],function(userId) {
eventName = events[i];
var acct = accountsList[userId];
if(acct) {
acct.emit(events[i],userId);
}
});
}
The above method is working but the problem line is
acct.emit(events[i],userId);
that events[i] is having last value of the loop. so if received any event it always emitting the final loop of the events[i] value...
So you are preserving value of event_name in a closure. It is legal, but doesn't look very neat.
Instead, you could use EventEmitter2 module like this
var EventEmitter = require('eventemitter2').EventEmitter2;
var emitter = new EventEmitter();
emitter.on('ev1', function (line) {
console.log(this.event); // here's your fired event
});
emitter.emit('ev1', 'has fired');
Check out the documentation, you could do much more than the original EventEmitter
i overcome this by function ...but i want to know this right way or not...
for(i in events) {
function test(event_name){
transport.purpleEvents.on(event_name,function(userId) {
var acct = accountsList[userId];
if(acct) {
acct.emit(event_name,userId);
}
});
}
test(events[i]);
}
The for loop you are using is async and results in all calls using the last value in events. If you replace that with forEach it will run sync. Try something like this untested code:
events.forEach(function(i) {
transport.on(events[i],function(userId) {
eventName = events[i];
var acct = accountsList[userId];
if(acct) {
acct.emit(events[i],userId);
}
});
});
you can use a closure like this which can be practical soln..
for(i in events) {
transport.on(events[i],closureplusopn(events[i]))
}
function closureplusopn(eventName){
return function(userID){
var acct = accountsList[userId];
if(acct) {
acct.emit(eventName,userID);
}
}
}
You can pass the event name through the context param.
On EventEmitter3 the .on function params are (eventName, functionName, context).
What helped me figure out how to get the eventName in the callback function was to pass this string as context and access it with the this keyword. Hope this helps whoever comes to this question and has something like this as an issue.
Forgive me if I'm not very clear here. I'm trying to learn a lot of things at once by doing.
I have an event listener with multiple events like this:
$account.on({
tap: function() {
accountOpen = true;
ui.openAccount(this);
},
swiperight: etc. etc.
}
I have all my ui functions in an object literal. Example:
var ui = PROJECT.ui = {
openAccount: function(account) {
var $account = $(account),
$trans = $('.transactions'),
$closeBtn= $account.find('.close-btn');
$account.removeClass('pay-open').removeClass('move-open');
$trans.appendTo($a)
.slideDown(400,function(){
$closeBtn.fadeIn(100);
});
}
}
What's the proper way to send the event target / this from the event handler to ui.openAccount() function without have to repeatedly capture the vars? (i.e. how do I stop repeating myself?) Do I use a constructor? Is there where an account object with a closure would come in handy?
I was thinking something like this:
var account = (function(){
var acct = {
this.container = $(this),
this.closeBtn = $(this).find('.close-btn')
}
return acct;
}());
And I could send the var account to ui.openAccount(), but I know i'm definitely not doing it right.
Try passing the event to the function you are calling:
$account.on({
tap: function(e) {
var my_cool_new_object = {};
console.log("your event is here")
console.log(e)
accountOpen = true;
// populate your object
my_cool_new_object.target = e.target;
my_cool_new_object.foo = bar;
...
// pass to method
ui.openAccount(my_cool_new_object);
},
swiperight: etc. etc.
}