have dumb question.
Here I've got three events calling the same function, connected to the same <div>:
<html>
<head>
<script type='text/javascript'>
function universal_action_handler( event ) {
var eType = event.type;
var eTarget = event.target || event.srcElement;
console.log( "Captured Event, type=", eType, ", target=", eTarget );
if( 'mouseover' == eType ) {
console.info( "onMouseOver: set background color to red." );
eTarget.style.backgroundColor = 'red';
eTarget.style.fontSize = '';
}
if( 'mouseout' == eType ) {
console.info( "onMouseOut: set background color to transparent." );
eTarget.style.backgroundColor = 'transparent';
eTarget.style.fontSize = '';
}
if( 'click' == eType ) {
console.info( "click!" );
eTarget.style.fontSize = 'larger';
}
}
</script>
</head>
<body>
<div style='border: 1px dashed red; display: inline-block;'
onClick="universal_action_handler(event);"
onMouseOver="universal_action_handler(event);"
onMouseOut="universal_action_handler(event);">Click me!</div>
</body>
</html>
I have onClick='', onMouseOver='', and onMouseOut='', all connected to the same <div>, and all calling the same function. If I want to add an event, I have to add an onEventThingy='' and call the same universal action handler function above. Inside the function, it decides what kind of event (event.type) and takes action.
Is there an onAnything='' event that I can use to call the universal function for any event which may happen to that <div>?
Instead of all those onevent attributes (which should be avoided anyway), you could set the onevent properties on the DOM element like so:
div.onclick = div.onmouseover = div.onmouseout = universal_action_handler;
where div is a reference to your DIV element.
Btw this is how I would implement the handler:
function universal_action_handler ( e ) {
var target, style;
e = e || window.event;
target = e.target || e.srcElement;
style = target.style;
if ( e.type === 'click' ) {
style.fontSize = 'larger';
} else {
style.backgroundColor = e.type === 'mouseover' ? 'red' : 'transparent';
style.fontSize = '';
}
}
Live demo: http://jsfiddle.net/rPVUW/
No, there is no universal event.
You can try what Šime Vidas suggested, or some libraries (e.g., jQuery) allow you to bind multiple events to the same handler with a single line of code, but either way you do need to explicitly list out the events to be bound.
No, there's no way to attach the same handler to all possible events. Is that really what you want? This could lead to your handler containing a huge if..else block or big switch statement.
If you want to attach common functionality (logging in your example) to all event handlers, consider this JavaScript:
function logAndHandle(event, innerHandler) {
var eType = event.type;
var eTarget = event.target || event.srcElement;
console.log( "Captured Event, type=", eType, ", target=", eTarget );
return innerHandler(event);
}
Which you'd use like this:
<div onclick="logAndHandle(event, yourClickHandler);"
onmouseover="logAndHandle(event, yourMouseOverHandler);"
onmouseout="logAndHandle(event, yourMouseOutHandler)">Click me!</div>
Given that you seem to want some functionality to run for all events, and other functionality to be specific to particular events, I'd combine Jacob's answer with Šime Vidas's:
var log = function(innerHandler) {
return function(event){
var eType = event.type;
var eTarget = event.target || event.srcElement;
console.log( "Captured Event, type=", eType, ", target=", eTarget );
return innerHandler(event);
};
};
And use it thus:
div.onclick = log(yourClickHandler);
div.onmouseover = log(yourMouseOverHandler);
div.onmouseout = log(yourMouseOutHandler);
Currying the log function makes it very easy to compose future "all event" functionality:
var count = function(innerHandler){
var totalCount = 0;
return function(event){
totalCount += 1;
alert("I've been called " + totalCount + " times.");
return innerHandler(event);
};
};
div.onclick = count(log(yourClickHandler));
Anyway, if you want to do functional-style programming in Javascript, you'd also want to look at Function.apply and Function.call.
Using just javascript, no, there is no 'onAnything' attribute. If you have the ability to add jQuery, you can 'bind' multiple events to the same div and then run the same function.
Related
So basically I am trying to put together some simple event listeners. I've added a button with the ID of "btn" in my HTML file, and basically I want to add a mouseover event, and a click event. I know how to do this, however I want to alert when each event occurs. Is there a way to neaten my code and put this all into one function instead of two? I'm just not sure how I would create two separate alert statements otherwise on the same button. Thanks!
You can define a single function and then reference it as the 2nd argument to .addEventListener.
Example:
<button id='btn' value='some button'>some button</button>
<div id='placeholder'></div>
<script>
(function() {
var btn = document.getElementById("btn");
btn.addEventListener("click",doSomething,false);
btn.addEventListener("mouseover",doSomething,false);
})();
function doSomething(e) {
// example: update the div with the event type
var p=document.getElementById("placeholder");
p.innerHTML=e.type;
}
</script>
JSFIDDLE DEMO
Maybe this will help?
The code below can be improved by adding another argument to determine add/remove, turning the two functions into one, but you get the idea.
(function() {
var btn = document.getElementById("btn");
addEvent(btn, "click mouseover", handler);
function handler ( event ) {
alert("This is the " + event.type + " handler.");
}
})();
function addEvent ( element, event, fnc ) {
var events = event.split(/\s/),
evt = "";
while ( evt = events.shift() ) {
((element.addEventListener) ? element.addEventListener(evt, fnc, false) : element.attachEvent("on" + evt, fnc));
}
}
function removeEvent ( element, event, fnc ) {
var events = event.split(/\s/),
evt = "";
while ( evt = events.shift() ) {
((element.removeEventListener) ? element.removeEventListener(evt, fnc, false) : element.detachEvent("on" + evt, fnc));
}
}
<button id="btn" type="button">Click or Hover</button>
I think this is what you want:
var myfunc = function(event) {
var btn...
btn.addEventListener(event, function()...
}
After you can call it like this:
Myfunc("click");
OK, so there's a question that gets asked around here a lot about Firefox not responding to window.event, where instead you need to add an extra parameter to the function. I have no problems with that; my problem is how the heck do I do that if I want to assign the event listeners from within a different Javascript function?
Basically, what I'm trying to do is the common effect when you can have a form box that has grey text that would say, for example, "Your name..." and then when you click the box the text disappears and the color changes to black; unfocus with the box still empty and the prompt text will return.
Now, instead of coding this directly for every page I want to use it on, I'm trying to make a function that I can call with the ID of the form and it will automatically apply this to every input element. Here's the code:
function fadingForm(formElementID, endColor)
{
var form = document.getElementById(formElementID);
for(var i = 0; i < form.elements.length; i++)
{
form.elements[i].originalValue = form.elements[i].value;
form.elements[i].originalColor = form.elements[i].style.color;
form.elements[i].changedColor = endColor;
// Somehow I need to get that event parameter in here I guess?
// I tried just putting the variable event in as a parameter,
// but as you'd expect, that doesn't work.
form.elements[i].onfocus = function() { focused(); };
form.elements[i].onblur = function() { blurred(); };
}
}
function focused(e)
{
evt = e || window.event;
element = evt.target;
if(element.value == "" || element.value == element.originalValue)
{
element.value = "";
element.style.color = element.changedColor;
}
}
function blurred(e)
{
evt = e || window.event;
element = evt.target;
if(element.value == "" || element.value == element.originalValue)
{
element.value = element.originalValue;
element.style.color = element.originalColor;
}
}
And of course, this works perfectly in Chrome, Safari, etc...just not Firefox.
Your event listeners focused and blurred accept an event object e, but you never provide an event object. The event object that is provided to the anonymous wrapper functions is never used nor passed to focused/blurred. Thus, e is always undefined.
Instead, when you set up your listeners, do:
form.elements[i].onfocus = function(e) { focused(e); };
form.elements[i].onblur = function(e) { blurred(e); };
Or even:
form.elements[i].onfocus = focused;
form.elements[i].onblur = blurred;
So that the event object is passed directly into your listener functions.
I need to have a handler on the calling object of onclick event.
link
<script>
function click123(event) {
//i need <a> so i can manipulate it with Jquery
}
</script>
I want to do this without the use of $().click or $().live of jQuery but with the method described above.
pass in this in the inline click handler
link
or use event.target in the function (according to the W3C DOM Level 2 Event model)
function click123(event)
{
var a = event.target;
}
But of course, IE is different, so the vanilla JavaScript way of handling this is
function doSomething(e) {
var targ;
if (!e) var e = window.event;
if (e.target) targ = e.target;
else if (e.srcElement) targ = e.srcElement;
if (targ.nodeType == 3) // defeat Safari bug
targ = targ.parentNode;
}
or less verbose
function doSomething(e) {
e = e || window.event;
var targ = e.target || e.srcElement || e;
if (targ.nodeType == 3) targ = targ.parentNode; // defeat Safari bug
}
where e is the event object that is passed to the function in browsers other than IE.
If you're using jQuery though, I would strongly encourage unobtrusive JavaScript and use jQuery to bind event handlers to elements.
I think the best way is to use currentTarget property instead of target property.
The currentTarget read-only property of the Event interface identifies the current target for the event, as the event traverses the DOM. It always refers to the element to which the event handler has been attached, as opposed to Event.target, which identifies the element on which the event occurred.
For example:
<span class="icon"></span> blah blah
Javascript:
a.addEventListener('click', e => {
e.currentTarget; // always returns "a" element
e.target; // may return "a" or "span"
})
The easiest way is to pass this to the click123 function or
you can also do something like this(cross-browser):
function click123(e){
e = e || window.event;
var src = e.target || e.srcElement;
//src element is the eventsource
}
http://docs.jquery.com/Events/jQuery.Event
Try with event.target
Contains the DOM element that issued
the event. This can be the element
that registered for the event or a
child of it.
The thing with your method is that you clutter your HTML with javascript. If you put your javascript in an external file you can access your HTML unobtrusive and this is much neater.
Lateron you can expand your code with addEventListener/attackEvent(IE) to prevent memory leaks.
This is without jQuery
link
window.onload = function () {
var el = document.getElementById('elementid');
el.onclick = function (e) {
var ev = e || window.event;
// here u can use this or el as the HTML node
}
}
You say you want to manipulate it with jQuery. So you can use jQuery. Than it is even better to do it like this:
// this is the window.onload startup of your JS as in my previous example. The difference is
// that you can add multiple onload functions
$(function () {
$('a#elementid').bind('click', function (e) {
// "this" points to the <a> element
// "e" points to the event object
});
});
I have a small div above (hover) a big one.
I assign onmouseover and onmouseout events to the wrapper div.
For image caption roll-over animation.
The problem is when the mouse is above the caption itself, causing an unwanted result (probably event bubbling).
And another problem: sometimes when you move mouse from outside to container you get a a triple sequence: (it should be just 2):
-I am over-
-I am out-
-I am over-
How to make it work? (no jQuery)
Must work on all browsers.
Demo
I have added firebug console log, to a better debugging.
UPDATE:
I've added this (not in the online demo) in RollOverDescription:
if (!eventHandle) var eventHandle = window.event;
var srcEle = eventHandle.srcElement.id;
if(srcEle=="imageDescription" ){
return;
}
But it doesn't help.
This article on quirksmode ( near the bottom ) has an explanation of what you are experiencing and a script that might help you. There is a lot of cross browser info regarding mouse events too
OK, here's some working code. I don't promise this is the most efficient or that it won't cause memory leaks in IE (or that it works in IE - please let me know ). This is why people use libraries, much safer and easier.
// a general purpose, cross browser event adder
// returns a function that if run removes the event
function addEvent( el, eventType, handler, capturing ) {
if( el.addEventListener ) {
el.addEventListener( eventType, handler, capturing || false );
var removeEvent = function() { el.removeEventListener( eventType, handler, capturing || false ) };
} else if( el.attachEvent ) {
var fn = function() {
handler.call( el, normalise( window.event ) );
};
el.attachEvent( 'on'+eventType, fn );
var removeEvent = function(){ el.detachEvent( 'on'+eventType, fn ) };
}
function normalise( e ) {
e.target = e.srcElement;
e.relatedTarget = e.toElement;
e.preventDefault = function(){ e.returnValue = false };
e.stopPropagation = function(){ e.cancelBubble = true };
return e;
};
return removeEvent;
};
// adds mouseover and mouseout event handlers to a dom element
// mouseover and out events on child elements are ignored by this element
// returns a function that when run removes the events
// you need to send in both handlers - an empty function will do
function addMouseOverOutEvents( element, overHandler, outHandler ) {
function out( e ) {
var fromEl = e.target;
var toEl = e.relatedTarget;
// if the mouseout didn't originate at our element we can ignore it
if( fromEl != element ) return;
// if the element we rolled onto is a child of our element we can ignore it
while( toEl ) {
toEl = toEl.parentNode;
if( toEl == element ) return;
}
outHandler.call( element, e );
}
function over( e ) {
var toEl = e.target;
var fromEl = e.relatedTarget;
// if the mouseover didn't originate at our element we can ignore it
if( toEl != element ) return;
// if the element we rolled from is a child of our element we can ignore it
while( fromEl ) {
fromEl = fromEl.parentNode;
if( fromEl == element ) return;
}
overHandler.call( element, e );
}
var killers = [];
killers.push( addEvent( element, 'mouseover', over ) );
killers.push( addEvent( element, 'mouseout', out ) );
return function() {
killers[0]();
killers[1]();
}
}
Example of use:
// add the events
var remover = addMouseOverOutEvents(
document.getElementById( 'elementId' ),
function( e ) {
this.style.background = 'red';
console.log( 'rolled in: '+e.target.id );
},
function( e ) {
this.style.background = 'blue'
console.log( 'rolled out: '+e.target.id );
}
);
//remove the events
remover();
Is this possible?
I am attempting to write a function for onmousedown that will return the ID of the element you just clicked for later use in recreating that element in a different div.
You can use event delegation, to basically connect only one event handler to your entire document, and get the element which the event was originally dispatched, using event.target:
document.body.onmousedown = function (e) {
e = e || window.event;
var elementId = (e.target || e.srcElement).id;
// call your re-create function
recreate(elementId);
// ...
}
function recreate (id) {
// you can do the DOM manipulation here.
}
Edit: You can assign events to all your Scriptaculous draggables in this way:
Event.observe(window, 'load', function () {
Draggables.drags.each(function (item) {
Event.observe(item.element, 'mousedown', function () {
alert('mouseDown ' + this.id); // the this variable is the element
}); // which has been "mouse downed"
});
});
Check an example here.
CMS pretty much has the correct answer but you will need to make it a little more cross browser friendly.
document.body.onmousedown = function (e) {
// Get IE event object
e = e || window.event;
// Get target in W3C browsers & IE
var elementId = e.target ? e.target.id : e.srcElement.id;
// ...
}
Pls insert this code to your javascript.
document.getElementById("article").onmouseup(handMu);
If you want to replicate the div id, an easy way might be cloneNode like this:
<div id="node1">
<span>ChildNode</span>
<span>ChildNode</span>
</div>
<div id="container"></div>
<script type="text/javascript">
var node1 = document.getElementById('node1');
var node2 = node1.cloneNode(true);
node2.setAttribute('id', 'node2');
var container = document.getElementById('container');
container.appendChild(node2);
</script>