document.getElementById('container').addEventListener('copy',beforecopy,false );
In Chrome / Safari, the above will run the "beforecopy" function when the content on the page is being copied. MSIE is supposed to support this functionality as well, but for some reason I'm getting this error:
"Object doesn't support this property or method"
Now, it's my understanding that Internet Explorer won't play with the body node, but I would have thought providing a node by ID would work fine. Does anyone have any ideas about what I'm doing wrong?
** Bonus points for anyone who can tell me what the 3rd parameter "False" is good for.
In IE you have to use attachEvent rather than the standard addEventListener.
A common practice is to check if the addEventListener method is available and use it, otherwise use attachEvent:
if (el.addEventListener){
el.addEventListener('click', modifyText, false);
} else if (el.attachEvent){
el.attachEvent('onclick', modifyText);
}
You can make a function to do it:
function bindEvent(el, eventName, eventHandler) {
if (el.addEventListener){
el.addEventListener(eventName, eventHandler, false);
} else if (el.attachEvent){
el.attachEvent('on'+eventName, eventHandler);
}
}
// ...
bindEvent(document.getElementById('myElement'), 'click', function () {
alert('element clicked');
});
You can run an example of the above code here.
The third argument of addEventListener is useCapture; if true, it indicates that the user wishes to initiate event capturing.
In case you are using JQuery 2.x then please add the following in the
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge;" />
</head>
<body>
...
</body>
</html>
This worked for me.
try adding
<meta http-equiv="X-UA-Compatible" content="IE=edge">
right after the opening head tag
Internet Explorer (IE8 and lower) doesn't support addEventListener(...). It has its own event model using the attachEvent method. You could use some code like this:
var element = document.getElementById('container');
if (document.addEventListener){
element .addEventListener('copy', beforeCopy, false);
} else if (el.attachEvent){
element .attachEvent('oncopy', beforeCopy);
}
Though I recommend avoiding writing your own event handling wrapper and instead use a JavaScript framework (such as jQuery, Dojo, MooTools, YUI, Prototype, etc) and avoid having to create the fix for this on your own.
By the way, the third argument in the W3C model of events has to do with the difference between bubbling and capturing events. In almost every situation you'll want to handle events as they bubble, not when they're captured. It is useful when using event delegation on things like "focus" events for text boxes, which don't bubble.
As of IE11, you need to use addEventListener. attachEvent is deprecated and throws an error.
As PPK points out here, in IE you can also use
e.cancelBubble = true;
Using <meta http-equiv="X-UA-Compatible" content="IE=9">, IE9+ does support addEventListener by removing the "on" in the event name, like this:
var btn1 = document.getElementById('btn1');
btn1.addEventListener('mousedown', function() {
console.log('mousedown');
});
The problem is that IE does not have the standard addEventListener method. IE uses its own attachEvent which does pretty much the same.
Good explanation of the differences, and also about the 3rd parameter can be found at quirksmode.
Related
I have a really strange problem. My example code works [here][1] quite fine, but I have the exactly same code in my aptana studio editor and when I try it in Chrome or the Eclipse browser the events just don't fire. I can't imagine what's the problem, because it's exactly the same code ...
HTML
<!DOCTYPE html>
<html>
<head>
<title>OrderScreen</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="js/script.js" type="text/javascript"></script>
</head>
<body>
Test
</body>
</html>
jQuery
$("a").mouseup(function() {
clearTimeout(pressTimer);
// Clear timeout
return false;
}).mousedown(function() {
// Set timeout
pressTimer = window.setTimeout(function() {
alert("hcbdhaf")
}, 1000);
return false;
}).click(function() {
alert("dfsdg");
});
If your code is really as quoted, the problem is that the elements don't exist as of when you try to hook event handlers to them. jsFiddle's default settings hide this problem from you. (Look on the left, and you'll see that your code isn't run until the load event fires — which is very, very late in the page load process.)
To fix it, either:
Move your script tags to the end of your document, just before or after the closing </body> tag. By the time the browser runs your script, the elements will exist. This is the recommendation of the YUI team and Google's web engineers like it too.
Use jQuery's ready event.
In conjunction with either of those, you might also look at using event delegation instead of directly hooking up events on the elements. Your mouseup and mousedown handlers will get attached to each a element individually. That's a lot of hookups. If there's a container that all of those a elements are in (body or better yet, something nearer), you might instead hook the event on that container (since those events bubble) and then check to see if the event originated in an a element. jQuery supports event delegation, doing most of the hard work for you, via delegate (which I like because it's so explicit) and more recently, one of the half-dozen variations of arguments you pass to on.
<html>
<head>
<title>FML</title>
<script type="text/javascript">
function function1(e, div) {
div.innerHTML="this works"
document.getElementById('myspan').innerHTML= 'x-pos on click: ' + e.clientX
div.addEventListener("mousemove", function(){test(event, this)}, true);
}
function test(e, div) {
div.innerHTML+='<br/>so does this'
//This doesn't work. Can't add event as a parameter to function that has to be executed when using addEventListener
document.getElementById('myspan2').innerHTML= 'y-pos on move: ' + e.clientY
}
</script>
</head>
<body>
<span id="myspan"> </span>
<span id="myspan2"> </span>
<div style="width:100px;height:100px;background-color:blue;overflow:hidden;" onclick="function1(event, this)">
</body>
</html>
Click on the blue div.
I want to add the event mouseover, have it execute the test()-function which should contain following parameters: this, event
When the function test(e, div) is called I keep getting an "event is undefined" error in Firefox and IE, although ironically enough it works perfectly in Chrome and Safari.
Any way I can add the event parameter by using addEventListener? I can get it to work with window.event in Chrome and Safari, but this is the exact setup that I want. I've been googling and trial/erroring for a while now, without success... so FML :/ Any tips/hints/... besides shooting myself in the head?
I know jQuery would probably solve all this, but I want to be proficient in Javascript before migrating to jQuery. Or should I migrate anyway?
div.addEventListener("mousemove", function(){test(event, this)}, true);
Well, of course you get "event is undefined" ! When the mousemove event triggers, your event handler is called:
function(){test(event, this)}
There are two ways to reach the event information object. Either it is passed to the event handler as an argument, or it can be found in window.event.
Suppose the second case holds. As there is no local variable named event in your function, nor is there such variable in function1 that calls it, the browser looks if there is an event defined in the global object. In JavaScript, the global object is called window, so your function is interpreted as
function(){test(window.event, this)}
and it works.
However, as I noted before, in some browsers, the event information is passed in the argument. So your event handler probably wanted to look like this:
function(event){test(event, this)}
otherwise the event passed to test() would be undefined. So, this is how to make a cross-browser handler:
function(event) {
if (!event) // i.e. the argument is undefined or null
event = window.event;
test(event, this);
}
The second problem is that addEventListener() doesn't work in older IEs (it does in IE9, though). For older IEs, you have to use a similar function called attachEvent(). Or, if you only attach one handler, you can do it the simple way
div.onmousemove = function() {...};
In some browsers like Firefox the event has to be passed as a parameter, so you have to replace this code
div.addEventListener("mousemove", function(){test(event, this)}, true);
with this
div.addEventListener("mousemove", function(event){test(event, this)}, true);
Compare carefully the two lines of code and notice the event property passed as parameter of the function added into the second row.
for old IE ver attachEvent() has to be used;
div.attachEvent("onclick", function(event){test(event, this)});
Notice that attachEvent has been replaced in modern standard js with addEventListener and now almost all modern browser support that.
Here
http://caniuse.com/#feat=addeventlistener
is possible to see compatibility table.
I know that JavaScript return false means prevent default event (like preventDefault() method).
#1
click
#2
<a id="a" href="http://stackoverflow.com">click</a>
<script>
document.getElementById('a').addEventListener('click', function(){ return false; }, false);
</script>
I wonder why just #1 prevent default event but not #2. Did I make some mistake?
Edit:
Sorry, I missed an id of anchor tag and third argument of code in #2. I added it but it's still not working.
There are two problems with your second example:
You're using document.getElementById but you're giving a tagname. You can probably use document.getElementsByTagName (which returns a NodeList you would then index into), or give the element an id attribute and use getElementById to look it up.
Your addEventListener call is missing the third argument, which is required. So:
document.getElementById('someId').addEventListener(
'click',
function(){ return false; },
false // <=== Third argument, you almost certainly want `false`
);
Regarding your question about return false: If you're using a browser that supports addEventListener and you're hooking up event handlers with it, no, you don't use return false to prevent the default action. Instead, you use event#preventDefault. (You can also use event#stopPropagation to stop the event bubbling, but DOM0's return false doesn't do that, so that's just an extra bonus.)
document.getElementById('someId').addEventListener(
'click',
function(e){
// Prevent the default action of the link
e.preventDefault();
// Stop the event propagating (bubbling) to the parent element
e.stopPropagation();
},
false
);
Also note that there are a lot of people using IE8 and earlier, which do not support addEventListener (instead, they support Microsoft's original attachEvent; but not all versions support preventDefault or stopPropagation).
Somewhat off-topic: As you can see, handling events in a cross-browser way is a hassle. It's one of the many hassles you can avoid by using a decent JavaScript library like jQuery, Prototype, YUI, Closure, or any of several others. They smooth over browser differences and provide lots of helpful utility functionality, so you can focus on what you're actually trying to build (rather than worrying about how IE7 and earlier have a broken version of getElementById).
Examples:
jQuery: jQuery provides a return false feature (although it's different from the DOM0 one you're talking about), and it also ensures that event#preventDefault and event#stopPropagation work regardless of how the underlying browser handles events. So either of these work with jQuery:
// Using return false (which prevents the default AND -- unlike DOM0 stuff -- stops propagation)
$('#someId').click(function() { return false; });
// Using the DOM standard event methods -- even on browsers that don't support them
$('#someId').click(function(e) {
e.preventDefault();
e.stopPropagation();
});
Prototype: Prototype provides the DOM standard event methods (even on browsers that don't support them) as well as event#stop which is just a combination of preventing the default and stopping propagation:
// Using `stop` (which prevents the default and stops propagation)
$('someId').observe('click', function(e) { e.stop(); });
// Using the DOM standard event methods -- even on browsers that don't support them
$('someId').observe('click', function(e) {
e.preventDefault();
e.stopPropagation();
});
Other libraries will offer similar functionality.
This will not work w/o a proper id (not tag name)
document.getElementById('a')
Try
<a id="example" href="http://stackoverflow.com">click</a>
...
document.getElementById('example')...
If you use getElementById(), you need an id on the element. As the name suggests, this function will find an element by searching for the id.
<a id="a" href="http://stackoverflow.com">click</a>
<script>
document.getElementById('a').addEventListener('click', function(){ return false; });
</script>
If you want to find it by tag name, you can use getElementsByTagName(). It will return an array (actually a NodeList) of those tags.
Using:
var x=document.getElementsByTagName('a')[0];
x will store a reference to the first link (a element) on the page.
you can't get the anchor-tag with document.getElementById(), because it is a TagName and not an Id.
Maybe u have to add "javascript:" before the "return false". Like so:
click
I hope that helps.
I've written this code inside the HEAD tags of my HTML page. It works fine in Firefox, Chrome and Safari, but doesn't in IE7. I would like to know how to fix it.
<script type="text/javascript">
if ( window.addEventListener ) {
window.addEventListener("keydown", function(e) {
alert(e.keyCode);
}, true);
}
</script>
Microsoft has implemented their own way of doing this called attachEvent. You can read more about this over at quirksmode.org: http://www.quirksmode.org/js/events_advanced.html
You're screwed: you're using event capturing (passing true as the last parameter to addEventListener). IE has no such equivalent, in any version, including IE8 in IE8 mode.
Is there a reason you must use event capturing rather that event bubbling here? IOW, pass false as your last parameter? Then, you'd be able to port this (somewhat) to use IE's attachEvent proprietary method, or use a library (as others have suggested and added links for).
There is no window.addEventListener in IE, you need to use attachEvent. There's good documentation on events here, or you could switch to using a library that abstracts away browser differences.
Try:
window.attachEvent
More fully:
//set page event handlers
if (window.attachEvent) {
//IE and Opera
window.attachEvent("keydown", "");
} else if (window.addEventListener) {
// IE 6
window.addEventListener("keydown", "");
} else {
//FireFox
document.addEventListener("keydown", "");
}
In IE exists .setCapture(); .releaseCapture() functions.
What's the equivalent of these functions in Firefox without using jQuery? (my client does not want to use it)
As it has been said above, Firefox does not offer this functionality, and you can work around it by monitoring events on the entire document. To be sure that there is no a better trick, I’ve just checked jQuery UI, and it appears they use the same approach. So for instance if you wanted to capture mouse movements when mouse is down in jQuery, you would do:
$("#someElement").
mousedown(function() { $(document).mousemove(captureMouseMove) }).
mouseup(function() { $(document).unbind("mousemove", captureMouseMove) });
function captureMouseMove(event)
{
// ...
}
https://developer.mozilla.org/en-US/docs/DOM/element.setCapture
setCapture and releaseCapture were added to Firefox 4 (with the release of Gecko 2) on March 22, 2011. However, WebKit (Chrome/Safari) still lacks these functions.
I believe element.setCapture() and document.releaseCapture() were added to Firefox as of FF4:
https://developer.mozilla.org/en/DOM/element.setCapture
"Call element.setCapture() method during the handling of a mousedown event to retarget all mouse events to this element until the mouse button is released or document.releaseCapture() is called."
To capture the mouse at anytime is not good behavior, I think that's why setCapture is not provided.
However, to capture the mouse for a drag-and-drop, you just need to handle the mouse events (mouse{up,down,move}) of the document object, which may be triggered when dragging even outside the client area.
<html>
<head>
<title>Capture test</title>
</head>
<body>
<script type="text/javascript">
document.onmousedown = function () {
state.innerHTML = "Dragging started";
};
document.onmousemove = function (e) {
coord.innerHTML = e.clientX + ',' + e.clientY;
}
document.onmouseup = function (e) {
state.innerHTML = "Dragging stopped";
}
</script>
<p id="state">.</p>
<p id="coord">.</p>
</body>
</html>
#JanZich's solution works great except it doesn't capture the mouse up event if the mouse is outside the element. This worked better for me:
$("#someElement").mousedown(function() {
$(document).mousemove(captureMouseMove);
$(document).mouseup(captureMouseUp);
});
function captureMouseMove(event) {
console.log("mouse move");
}
function captureMouseUp(event) {
console.log("mouse up");
$(document).unbind("mousemove", captureMouseMove);
$(document).unbind("mouseup", captureMouseUp);
}
Use event bubbling: add event listeners for the bubbling mouse events to a high-level container (possibly even document) and use a variable to track which element should be the capturing one.
Without further information on what you're trying to do, there's not really any more to say.
setCapture() and releaseCapture() are Internet Explorer specific non-standard methods. There is no implementation in Firefox. There is a framework called Gimme that gives you some mouse capture functionality. http://www.codeplex.com/gimme/
SetCapture and ReleaseCapture are IE propriatory functions as you've discovered. There is no native way to manipulate the content menu in the same way in Firefox.
It seems like it might be possible with Gimme which can be found at http://www.codeplex.com/gimme/Wiki/Recent.aspx. There is a blog post here: http://blog.stchur.com/2007/11/21/setcapture-with-gimme which describes one scenario of using this to replace the functions.
Use true as the third parameter of the addEventListener method to capture. For example:
document.addEventListener("click", function(event){location.hash=event.target}, true)
Use removeEventListener with the same parameters to release:
document.removeEventListener("click", function(event){location.hash=event.target}, true);
References
DOM Level 3 Event Flow
Netscape 6, Part III: The Event Model
Current Events: A Client Side Tipsheet
There is no such function in FF / JavaScript. The capture functions only exists in JScript.