pass an event AND a variable to an anon function in firefox - javascript

I come again with my inabilities to comprehend javascript.
I have a draggable library and it has a command that is called like so (the _ag is just namespacing stuff):
_ag.drag(event,targetDiv);
// targetDiv can be a string, btw - converted to an element in the function
so I've got code that looks like so (passing some data with a closure - a new trick to me):
header.onmousedown=function(targetDiv){
return function(){
_ag.drag(event,targetDiv)
}
}(aTargetDiv)
works great! just great! in...IE! SF! Chrome! NOT IN FIREFOX!
No, firefox cannot find the event. Now normally this is easy enough with something like this (formed slightly differently - hope it's still valid):
header.onmousedown=function(event){
alert(event.screenX)
}
However if I decide to pass some parameters in, it blows away event, which I guess is some sort of invisible parameter in FF?
//broken thing 1:
header.onmousedown=function(event){
alert(event.screenX) // somethingToPass in covers event in FF
}(somethingToPassIn)
// broken thing 2:
header.onmousedown=function(event){
alert(event.screenX)
}(event,somethingToPassIn) // event is undefined
SO FIREFOX: How do I send you events? Here's hoping this is a very stupid question, and that hoards of SO folks have the answers! Thanks in advance, I'll be right here banging my head against the wall.

Firefox probably doesn't have support for event, but instead passes it into your function when the event fires. So,
header.onmousedown=function(targetDiv){
return function(e){
e = e || event; //This will give support for global event and passing the event into the function
_ag.drag(e, targetDiv);
}
}(aTargetDiv)
You don't need the closure unless the aTargetDiv variable changes sometime later in the code. Instead, you could do:
header.onmousedown=function(e){
e = e || event;
_ag.drag(e, aTargetDiv);
};

Related

Cant set properties of created event object in javascript

I hope I'm doing everything right on my first post!
I stuck trying to create a JS event which I would dispatch later.
I realized that I couldn't set the properties of the event, so I ended up playing around in the browser console, but I can't get it to work.
This is my code I execute:
var e = new WheelEvent('mousewheel');
e.wheelDelta = 1;
console.log(e.wheelDelta);
As the result shows, the wheelDelta property is still zero.
I feel like an idiot right now, would appreciate any help!
Edit:
Since it seems to be related to Chrome and the event to be obsolete, I tried the same with 'click' and bubbles, which should be supported on every browser. Same issue...
var e = new Event('click');
e.bubbles = true;
console.log(e.bubbles);
SOLVED:
I found out the properties were somehow read-only.
Another post solved this.

calling a function using a mouse event without attaching it to an HTML element?

I am taking a web development class. Today the teacher gave us a piece of code that raised some questions that I haven't been able to satisfactorily solve through my own searching. The code in question was essentially this:
<script>
function selectmouse(e){
...
...
}
document.onmousedown = selectmouse;
</script>
My first question, is this a legitimate way of calling functions? Is this something that is done? I am of course familiar with the typical way of calling functions from HTML elements, for example
<body onmousedown="selectmouse(event)">
The code was supposed to be calling the function and passing it the event object for the onmousedown. After playing with the code for a while I found a few unusual things.
First, if I put parenthesis after the function call, like I am used to doing (i.e. selectmouse();), then the function resolved immediately upon loading the page, with a value of 'undefined' for the variable. This makes intuitive sense to me, because I assume the browser is treating it like a variable assignment and therefore calling the function as it parses the code, as it normally would to assign a variable.
However the part that is weird to me happened when I deleted the '()' and left it as it is coded above. In this instance it seemed to function like she wanted it to. It would call the function when the mouse was pressed in any part of the body, and it sent the event object as the variable for the function. But I can't figure out why. I can't find reference to anything similar to it online, and I've never seen anything like it before. Is this a legitimate way to do something like this? Or is this bad code that happens to be working for some reason and would probably cause problems in the future? Why is it working?
document.onmousedown = selectmouse; //note: never do this except in old browsers
However the part that is weird to me happened when I deleted the '()' and left it as it is coded above. In this instance it seemed to function like she wanted it to.
That's not weird. You are passing the reference of the function to the browser, not executing it.
For example, you have this function:
function callback(){
alert("clicked!");
}
document.body.onclick = callback;
You pass the reference to onclick and the browser will know what function to call when the event is triggered. But if you do it like this:
document.body.onclick = callback();
This will be evaluated into:
document.body.onclick = alert("clicked!");
//Note that this is simplified explanation to visualize what is happening.
//The returned value of alert() is not assigned to onclick.
//To be exact the returned value of callback() is the one that is being assigned.
//Similar to:
// ...onclick = (function(){ alert("clicked!"); })();
Then you will see an alert, and the browser will continue executing the rest of the code:
document.body.onclick = undefined;
<body onmousedown="selectmouse(event)"> <!-- Don't do this too -->
The parentheses are necessary because this code is not executed instantly. It is only executed when the event is triggered.
Anyway, you shouldn't attach events both using .onmousedown or onmousdown="...". There is a better way of doing it:
element.addEventListener("mousedown", callback, false);
Reason: If you use the onmousedown property, you can only attach one mousedown event. In most cases you would want to attach more than one.
Also attaching events inline might cause security problems (cross-site scripting), and that is exactly why Google decided to prohibit all developers from using them in developing Chrome apps/extensions.
This is legitimate code and is working as it should.
The way you are comfortable with is just a method we tried while the web was evolving, but at present we should better use the second way you showed, although its changed bit more to make you understand it in a better way using event bindings.
When you do
function selectmouse(e){
...
...
}
javascript will create a variable named selectmouse and save the function in that variable. So selectmouse is a variable of type function with the function body as its value.
document on the other hand can be related to class or specifically an object which is an instance. Each document and each HTML element or DOM node can have in it variables to store the functions to be called on user events like onmousedown.
so when doing
document.onmousedown = selectmouse;
we are inturn saying
when mousedown happens in document, the function named selectmouse
should be called
If you do
document.onmousedown = selectmouse();
it means
run the function selectmouse immediately and get the result, assign
the result to onmousedown event of the DOM Node document.
And if you ask why this is taken apart from the form
<body onmousedown="selectmouse(event)">
To answer in a simple way, HTML is Hyper Text Markup Language, its sole purpose is to represent formatted data, the quick evolution of web inturn made it deranged with behaviours like this and presentation code like inline css. So to make behaviour and presentation out of HTML and thus a better design we do this.
Please take time to take a look at how you can bind a function to an event which is the current tradeoff in doing this same thing.
For a detailed explanation please check the events sectio of ppk blog here
I think that is correct, because the function is being called within the script as if it were an object, to me is not the best way to do it, I would have like this (with jquery):
$(document).mousedown(function (event) {
// here the content of the function
});
<body onmousedown="selectmouse(event)">
In this example the browser evaluates the result of the expression selectmouse(event) and assigns it to the onmousedown property of the body, event is undefined and the selectmouse doesn't return anything so it's result is undefined.
It is equivalent of the following if it was inside a script tag
<script>
function selectmouse(e) {
}
document.body.onmousedown = selectmouse(event);
</script>
<body onmousedown="selectmouse">
When you remove the () you are assigning a function to the onmousedown property. Now the browser fires your callback method whenever the mousedown event is raised and it bubbles up to the body, passing the current event as the parameter you're declaring as "e". If another element also had an onmousedown event handler declared but it cancelled the event ( by calling event.cancelBubble = true ) the body's onmousedown handler will not be invoked.
<script>
function selectmouse(e) {
}
document.body.onmousedown = selectmouse;
</script>

event.srcElement in firefox

I have some old code that I'm updating to work in firefox, and I've run across a problem.
In the code, there's a function that looks like this:
function tableEnter() {
myLocation = event.srcElement;
}
This doesn't work in firefox. I've researched this quite a bit, but most of the solutions I've found require an event to be passed to this function, and then act on the e parameter that was passed. ...Unfortunately in the code that I'm updating, I'm not getting any parameters passed.
What's the solution to making the event.srcElemet work in firefox, without any parameters being passed to my function?
Edit:
Okay, the question is becoming: How do i pass the event object to my tableEnter() function?
Here's what the code is currently doing:
$(document).ready(function () {
//make table rows
//for every new table row...
myRow.onmouseover = tableEnter; (this is probably a bad name. it should be like..rowEnter. But this is the way I found the code)
});
the question is now, how do i pass the event object into tableEnter() so that I can do the things suggested on the internet, and the answers below.
Thanks.
I honestly can't see why you would want to have access to the event object, without it being an argument of your handler. But, hey, that's just me. Although no parameters are specified, FF and chrome just do as they please and pass the event object to the handler anyway. So:
function tableEnter()
{
var evt = window.event || arguments[0];
var src = evt.target || evt.srcElement;
}
And that's it. Personally, I would advise you to do what the whole wide web is doing:
function handler(e)
{
e = e || window.event;
var target = e.target || e.srcElement;
}
Since you're using FF, you shouldn't try to diverge from any of the coding conventions or standards too much, however vague they might be. At least it's better than no standards or conventions at all.
In view of your update, just change your function definition to:
function tableEnter(e)
{
//though in jQuery, I suspect e is allready X-browser-proof
e = e || window.event;
//just leave ^^this^^ line out, and check in IE: alert(typeof e);
//if it alerts object, jQuery passed the event object for you
var theRow = this;//<-- this points to the row that triggered the mouseover
var jQRow = $(this);//gives you access to jQuery methods
var target = e.target || e.srcElement;//<-- mainly of importance in delegation
}

Adding a javascript function call to an event (such as 'window.resize') instead of overwriting what is already there

Is there a way to tell the browser to run an addtional java script function on an event such as 'window.resize' instead of overwriting what is already there?
Using jquery's
$(window).resize(<something>);
Seems to replace what is already there. Is there a way to tell it to do something in addition?
Is this a poor design / wrong way to do it?
I wouldn't think that jQuery would break what's there, but you could wrap the functions in a single function:
// if a function already exists...
if( window.onresize ) {
var prev_func = window.onresize; // cache the old function
window.onresize = function( event ) { // new function for resize
prev_func.call( window, event ); // call the old one, setting the
// context (for "strict mode") and
// passing on the event object
// call your code or function
};
}
EDIT: Fixed it to use onresize instead of resize.
EDIT2: Missed one! Fixed.
If you're using jQuery to bind all event handlers, then you're not breaking anything. jQuery supports multiple handlers for same event.
But if other code (not using jQuery) binds to the event, then you'll overwrite handler with your statement. The solution will be: always use jQuery for event binding or try to save old handler (see patrick dw's answer).
See element.addEventListener (element.attachEvent in IE 8 and under):
// Standards
if (window.addEventListener){
window.addEventListener("resize", callOnResize, false);
// IE 8 and under
} else if (window.attachEvent){
window.attachEvent('resize', callOnResize);
}
function callOnResize() {
console.log("resized");
}
Keep in mind this is pure JavaScript—jQuery (and pretty much any big JS library) has a method to handle creating standards and IE handlers without you needing to write each. Still, it's good to know what's happening behind the scenes.
jQuery and all other frameworks supporting custom events attach a function to the event of the elem (or observe it). That function then triggers all functions that have been bound (using bind) for a specific event type.
domelement.addEventListener does not override an other function and your function added can't be removed by other (bad) javascript, except when it would know the exact footprint of your function.

Run function only if event default is/isn't prevented

Is there a way to run a function only if event.preventDefault() is called on an event (by another unknown function). This is for a jQuery plugin, so I don't have any knowledge of what other parts of the page might be doing. I've tried this:
Event.test = Event.preventDefault;
Event.preventDefault = function () {
alert('Success');
this.test();
}
but it doesn't work... just behaves as normal, with no errors.
Conversely, I want the opposite too... to call a function only if event.preventDefault() isn't called. In effect, to add a function to the default action for an event. Any ideas? Is all this at all possible?
Edit: Based on the comment, I've got a solution to the first problem: http://jsfiddle.net/nathan/VAePB/9/. It works in Chrome (alerts function preventDefault() { [native code] }, but IE alerts undefined. So IE won't let me define Event.prototype.test, but it will let me redefine Event.prototype.preventDefault. Weird. I'm sure I can come up with a solution to the the second problem based on this one if I can just get it to work in IE.
I'm not sure I've understand. Can't you just use event.isDefaultPrevented() like this
For the first problem, try something like this:
oldPreventDefault = Event.prototype.preventDefault;
Event.prototype.preventDefault = function() {
//do stuff
oldPreventDefault.call(this);
}
I don't know if that will work, but it might be worth a shot.
For the second problem, I would try something similar to live event handling. Put a listener on a parent element (i.e. body or a top-level div). If you can get your hook into preventDefault as noted before, you can use that to set a flag. If the event bubbles up to that element and your flag isn't set, do your extended behavior. Though this won't work with all events, since not all events bubble. Another way to tackle this problem might be to delay execution until the current stack has finished using setTimeout(0,...) and then checking the flag.

Categories

Resources