This works in Firefox, but not IE. Any help would be much appreciated!
var form = document.getElementById('theform')
/* create the event handler */
form.gen.onclick = function( evt ) {
var f = evt.target.form
var y = f.year.value
var m = f.month.value
genCalendar( document, y, m, 'theCalendar' )
}
To get the target of an event in both standards compliant browsers and IE, use
var target = evt ? evt.target : window.event.srcElement;
There's an overview of the different properties of event objects at MDC.
As mentioned, IE does not pass the event object as a parameter. Try this:
var form = document.getElementById('theform')
/* create the event handler */
form.gen.onclick = function( evt ) {
if(!evt)
evt = window.event;
var f = evt.target.form
var y = f.year.value
var m = f.month.value
genCalendar( document, y, m, 'theCalendar' )
}
Or better yet, use a cross-browser library, like Prototype.js or jQuery.
When does this script run? You might have to run this script onload, after the DOM is fully loaded
<script>
function go()
{
alert('dom is loaded: register event handlers now') ;
}
</script>
<body onload=" go(); ">
</body>
This is why you should consider using a javascript library such as jquery, YUI, or prototype. These libraries abstract away the browser based differences which simplifies your coding.
From my own searching the most sucessful was this
function clickHandler(e){
var elem, evt = e ? e:event;
if (evt.srcElement) elem = evt.srcElement;
else if (evt.target) elem = evt.target;
alert (''
+'You clicked the following HTML element: \n <'
+elem.tagName.toUpperCase()
+'>'
)
return true;
}
document.onclick=clickHandler;
Sourced from ther very helpful and explanatory http://www.javascripter.net/faq/eventtargetsrcelement.htm
Related
I have a SELECT element that I am replacing with a dropdown. I have successfully created the dropdown from the SELECT and child OPTION elements, but I need to add a click event.
This click event would be as such:
If LI is clicked, also click corresponding OPTION.
This is because Woocommerce must have some JS or PHP working where depending on the option, it shows stock status and variable amount. As such, I assume that the click event will also bind the OPTION value to the form for adding to cart.
I have this JS code:
window.onload = main;
function main(){
var select = document.querySelector('.turnintodropdown');
var selsOpts = document.querySelector('.turnintodropdown option');
var selsLi = document.querySelector('.selectOption');
var trigger = document.createElement('a');
var openDropdown = 'dropdownVisible';
var closeDropdown = 'dropdownHidden';
(function addDropdown() {
if(select) {
var selsCon = document.createElement('div');
var selsOuter = document.createElement('ul');
selsCon.classList.add('selectContainer');
selsOuter.classList.add('selectOuter');
select.parentNode.insertBefore(selsCon, select);
selsCon.appendChild(selsOuter);
for(var i=0; i<select.length; i++) {
if(select.childNodes[i].classList.contains('enabled') || select.childNodes[i].innerHTML == '- -'){ // Select First Child and <option> Tags with Enabled Class
// Create New Elements
var optsNew = document.createElement('li');
optsNew.innerHTML = select.childNodes[i].text;
optsNew.classList.add('selectOption');
// Set Attributes to New Elements
if(optsNew.innerHTML !== '- -') {
optsNew.setAttribute('value', select.childNodes[i].text);
}
else {
void(0);
}
optsNew.click(clickFunc);
// Add New LI <option> to UL <container>
selsOuter.appendChild(optsNew);
// Click Events
console.log(select.firstChild);
}
}
var clickFunc = function() {
select.click();
};
select.style.display = 'none';
}
})();
}
Any help would be greatly appreciated.
Regards
Michael
I was a bit long to answer, sorry.
the function was originally taken from this webpage and not modified, it is supposed to work with most old browsers. I actually tested on last versions of Firefox / Chrome / Opera / Edge with success.
The version which handles all types of events is more complicated because you have to make cases for standard events to process them by type (not all are MouseEvents).
It also supports the inline functions, with onclick= in the html tag, and works also for events set with jQuery.
Note that if you want the same support for old broswers, you'll have to differentiate cases for the setting of events too, the modern addEventListener being not supported by all.
function fireClick(node){
if ( document.createEvent ) {
var evt = document.createEvent('MouseEvents');
evt.initEvent('click', true, false);
node.dispatchEvent(evt);
} else if( document.createEventObject ) {
node.fireEvent('onclick') ;
} else if (typeof node.onclick == 'function' ) {
node.onclick();
}
}
used like this for example:
fireClick(document.getElementById("myId"));
Vanilla JS (without jQuery)
/**
* Simulate a click event.
* #public
* #param {Element} elem the element to simulate a click on
*/
var simulateClick = function (elem) {
// Create our event (with options)
var evt = new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window
});
// If cancelled, don't dispatch our event
var canceled = !elem.dispatchEvent(evt);
};
To use it, call the function, passing in the element you want to simulate the click on.
var someLink = document.querySelector('a');
simulateClick(someLink);
src / full article: https://gomakethings.com/how-to-simulate-a-click-event-with-javascript/
I have made a JavaScript tab view of a simple HTML page.
I've added onClick functions for header tags using JavaScript via nodes.
The onClick function performs a function called showTab passing on this as a parameter.
I understand that this is [object window].
The header tag onClick functions are set as shown below:
node.onclick = function() { showTab(this); };
The showTab function is as follows:
function showTab(e)
{
var node = (e && e.target) || (window.event && window.event.srcElement);
alert(node.innerHTML);
}
Everything works fine, when i click on one of the headers, an alert appears with its innerHTML.
However, I did use a little help from Google to achieve this. And I would like some help understanding exactly what this line means:
var node = (e && e.target) || (window.event && window.event.srcElement);
I did my own research and saw it can be considered as the equivalent as sender in C#.
But I would like to know thoroughly how it works and what it is referring to and how it knows which node is calling the showTab function as there are 3 header tags that perform the same function, all without id's.
Ah, the joys of dealing with Events and browser.
The Trident Engine (Internet explorer and others based on that engine) deals with events differently than most (all?) of the other browsers.
<html>
<head>
<title>Test</title>
</head>
<body>
<button id="test_button">Click me</button>
<script>
// UGLY, UGLY, UGLY... don't really use this
var button = document.getElementById("test_button");
if (window.attachEvent) {
button.attachEvent("onclick", showTab);
} else {
button.addEventListener("click", showTab);
}
function showTab(e)
{
// Most browsers pass the event as 'e'
// Microsoft puts the event in window.event
// Either way, event will now point to the object we want.
var event = e || window.event;
// Once again, the different browsers handle the `target` property differently.
// Target should now point to the right event.
var target = event.target || event.srcElement;
alert(target.innerHTML);
}
</script>
</body>
This line:
var node = (e && e.target) || (window.event && window.event.srcElement);
is equivalent to this logic:
var node;
if (e && e.target) {
node = e.target;
} else if (window.event && window.event.srcElement) {
node = window.event.srcElement;
} else {
node = undefined;
}
The purpose of this code is to handle the fact rhat older versions of IE don't pass the event structure to an event handler. Instead, it is stored in a global variable window.event and the event target is also stored in a difference property of the event.
It is a bit more common (and I think more readable) to do something like this:
function showTab(e) {
// get the event data structure into e
e = e || window.event;
// get the source of the event
var node = e.target || e.srcElement;
alert(node.innerHTML);
}
In reality, any decent size project should use a library function for abstracting the differences in event handlers so that this browser-specific code only has to be one place in the project or use a pre-built library like jQuery for this type of thing. Here's a cross-browser event handler:
// refined add event cross browser
function addEvent(elem, event, fn) {
if (typeof elem === "string") {
elem = document.getElementById(elem);
}
function listenHandler(e) {
var ret = fn.apply(this, arguments);
if (ret === false) {
e.stopPropagation();
e.preventDefault();
}
return(ret);
}
function attachHandler() {
// older versions of IE
// set the this pointer same as addEventListener when fn is called
// make sure the event is passed to the fn also so that works the same too
// normalize the target of the event
window.event.target = window.event.srcElement;
var ret = fn.call(elem, window.event);
if (ret === false) {
window.event.returnValue = false;
window.event.cancelBubble = true;
}
return(ret);
}
if (elem.addEventListener) {
elem.addEventListener(event, listenHandler, false);
} else {
elem.attachEvent("on" + event, attachHandler);
}
}
It's getting the dom element which was clicked, either e.target for standards compliant browsers or window.event.srcElement (could be e.srcElement instead for newer IE)
see: http://www.quirksmode.org/js/events_properties.html
Only today I figured out how event propagation works and set out pompously to test it on my existing code base but arghhhhhhh damn you javascript......nothing seems to be simple enough with you :X
Here is my problem, I define a set of events on an anchor:
theLink.setAttribute('onMouseOver','doSomething(this)'); **// works**
theLink.addEventListener("mouseout", function(event){doSomethingElse(event)}, false); **// does not work**
theLink.onmouseout = function(event){doSomethingElse(event)}; **// does not work**
Only if I define events as in the first example then it seems to be working in the second or the third definitions as well. But I can not use that definition because I have to pass event object.
Any hints? I am using firefox.
All three of these worked for me using the following code (in firefox):
HTML:
<a id="link1">Link 1</a>
<a id="link2">Link 2</a>
<a id="link3">Link 3</a>
JS:
var link1 = document.getElementById("link1");
var link2 = document.getElementById("link2");
var link3 = document.getElementById("link3");
window.doSomething = function(event) {
console.log(event);
}
link1.setAttribute('onMouseOver', 'doSomething(this)');
link2.addEventListener("mouseout", function(event) {
doSomething(event)
}, false);
link3.onmouseout = function(event) {
doSomething(event)
};
Here is a jsfiddle with it working: http://jsfiddle.net/magicaj/qk6wU/
You might also consider using a library like jQuery that handles cross browser incompatibility with the addEventListener method that is not supported by some versions of IE, the JS would look something like this:
$("#link1").mouseover(doSomething);
$("#link2").mouseover(doSomething);
$("#link3").mouseover(doSomething);
An answer with cross browserness included
function doSomething( event ) {
if( console && console.log ) {
console.log( this );
console.log( event );
}
else {
alert( this === window ? 'WINDOW' : this.tagName );
alert( event );
}
}
var link1 = document.getElementById("link1");
var link2 = document.getElementById("link2");
var link3 = document.getElementById("link3");
// `this` within your handler will be `window` and not the link
link1.setAttribute( 'onMouseOver', 'doSomething( event )' );
// to attach event listeners you have to do a bit more work
// ( best to make a function rather than doing this each time
if( document.addEventListener ) {
// compliant browsers
link2.addEventListener('mouseover', doSomething, false);
} else {
// internet explorer
link2.attachEvent( 'onmouseover', function() {
// grab the event object from the window
var e = window.event;
// normalise it a bit i.e. make it a bit more like a compliant browsers event object
e.target = e.srcElement;
e.preventDefault = function(){ e.returnValue = false };
e.stopPropagation = function(){ e.cancelBubble = true };
// and forward to your handler making sure that `this` is properly set
doSomething.call( this, e );
});
}
link3.onclick = doSomething;
Note
Avoid wrapping your handlers in unecessary anonymous functions, it's wastefull and you lose the this in the handler
so instead of
link3.onclick = function( event ) { doSomething( event ) };
just assign the handler directly
link3.onclick = doSomething;
I'm having troubles getting the attachEvent to work. In all browsers that support the addEventListener handler the code below works like a charm, but in IE is a complete disaster. They have their own (incomplete) variation of it called attachEvent.
Now here's the deal. How do I get the attachEvent to work in the same way addEventListener does?
Here's the code:
function aFunction(idname)
{
document.writeln('<iframe id="'+idname+'"></iframe>');
var Editor = document.getElementById(idname).contentWindow.document;
/* Some other code */
if (Editor.attachEvent)
{
document.writeln('<textarea id="'+this.idname+'" name="' + this.idname + '" style="display:none">'+this.html+'</textarea>');
Editor.attachEvent("onkeyup", KeyBoardHandler);
}
else
{
document.writeln('<textarea id="hdn'+this.idname+'" name="' + this.idname + '" style="display:block">'+this.html+'</textarea>');
Editor.addEventListener("keyup", KeyBoardHandler, true);
}
}
This calls the function KeyBoardHandler that looks like this:
function KeyBoardHandler(Event, keyEventArgs) {
if (Event.keyCode == 13) {
Event.target.ownerDocument.execCommand("inserthtml",false,'<br />');
Event.returnValue = false;
}
/* more code */
}
I don't want to use any frameworks because A) I'm trying to learn and understand something, and B) any framework is just an overload of code I'm nog going to use.
Any help is highly appreciated!
Here's how to make this work cross-browser, just for reference though.
var myFunction=function(){
//do something here
}
var el=document.getElementById('myId');
if (el.addEventListener) {
el.addEventListener('mouseover',myFunction,false);
el.addEventListener('mouseout',myFunction,false);
} else if(el.attachEvent) {
el.attachEvent('onmouseover',myFunction);
el.attachEvent('onmouseout',myFunction);
} else {
el.onmouseover = myFunction;
el.onmouseout = myFunction;
}
ref: http://jquerydojo.blogspot.com/2012/12/javascript-dom-addeventlistener-and.html
The source of your problems is the KeyBoardHandler function. Specifically, in IE Event objects do not have a target property: the equivalent is srcElement. Also, the returnValue property of Event objects is IE-only. You want the preventDefault() method in other browsers.
function KeyBoardHandler(evt, keyEventArgs) {
if (evt.keyCode == 13) {
var target = evt.target || evt.srcElement;
target.ownerDocument.execCommand("inserthtml",false,'<br />');
if (typeof evt.preventDefault != "undefined") {
evt.preventDefault();
} else {
evt.returnValue = false;
}
}
/* more code */
}
Just use a framework like jQuery or prototype. That's what they are there for, this exact reason: being able to do this sort of thing w/out having to worry about cross-browser compatibility. It's super easy to install...just include a .js script and add a line of code...
(edited just for you Crescent Fresh)
With a framework, the code is as simple as...
<script type='text/javascript' src='jquery.js'></script>
$('element').keyup(function() {
// stuff to happen on event here
});
Here is a function I use for both browsers:
function eventListen(t, fn, o) {
o = o || window;
var e = t+Math.round(Math.random()*99999999);
if ( o.attachEvent ) {
o['e'+e] = fn;
o[e] = function(){
o['e'+e]( window.event );
};
o.attachEvent( 'on'+t, o[e] );
}else{
o.addEventListener( t, fn, false );
}
}
And you can use it like:
eventListen('keyup', function(ev){
if (ev.keyCode === 13){
...
}
...
}, Editor)
Different browsers will process events differently. Some browsers have event bubble up throw the controls where as some go top down. For more information on that take a look at this W3C doc: http://www.w3.org/TR/DOM-Level-3-Events/#event-flow
As for this specific issue setting the "userCapture" parameter to false for the addEventListener will make events behave the same as Internet Explorer: https://developer.mozilla.org/en/DOM/element.addEventListener#Internet_Explorer
You might be better off using a JavaScript framework such as MooTools or jQuery of your choice to ease cross-browser support. For details, see also
http://mootools.net/docs/core/Element/Element.Event
http://api.jquery.com/category/events/
MooTools port of parts of your sample code:
var Editor = $(idname).contentWindow.document;
...
$(document.body).grab(new Element('textarea', {
'id' : this.idname,
'name' : this.idname,
'style': 'display:none;',
'html' : this.html
});
Editor.addEvent('keyup', KeyBoardHandler);
By the way, is it on purpose that you use both idname and this.idname in the code above ?
window.event.srcElement.options(window.event.srcElement.selectedIndex).value works in Internet Explorer (and Chrome) but not in FireFox. How to make this work in FireFox as well?
event.target.options[event.target.selectedIndex].value. Though as always with events you'd have to have passed the event object into a function, so eg.:
<script>
function selectChanged(event) {
var target= event.target || event.srcElement;
doSomethingWith(target.options[target.selectedIndex].value);
};
</script>
<select onchange="selectChanged(event)">...</select>
Setting the handler directly and using this may be easier:
<select id="x">...</select>
<script>
document.getElementById('x').onchange= function() {
doSomethingWith(this.options[this.selectedIndex].value);
};
</script>
Note that looking at options[selectedIndex] is for compatibility with older browsers. These days you can usually just get away with saying select.value.
There is no global event object in Firefox. Events are passed to their handlers as an argument. Also, instead of srcElement, you look for target.
If you use a javascript library like jQuery, all the browser specific quirks are handled for you.
Otherwise, I suggest you to read these articles
http://www.quirksmode.org/js/introevents.html
http://www.quirksmode.org/js/events_properties.html
var addEvent = (function() {
function addEventIE(el, ev, fn) {
return el.attachEvent('on' + ev, function(e) {
return fn.call(el, e);
});
}
function addEventW3C(el, ev, fn) {
return el.addEventListener(ev, fn, false);
}
return window.addEventListener ? addEventW3C:addEventIE;
})();
var domRef = document.getElementById('foo');
addEvent( domRef, 'change', function(e) {
e = e || window.event;
var el = e.target ? e.target : e.srcElement,
value = el.value;
alert( value )
});
in IE, event is a property of window, in modern DOM supporting browsers it's passed as the first argument.
IE uses srcElement where most other browsers (including Firefox) use target.
Also, Firefox passes around event objects, whereas IE just populates the global event object w/the current event's data.
You'll have to handle both in your code. How you handle the 2nd one will depend on how you're assigning the handler.
But here's one way.
function changeHanlder( event )
{
var elem = event.target || event.srcElement;
alert( elem.options[elem.selectedIndex].value );
}
It's also worth noting that all the modern javascirpt libraries handle this abstraction for you.
There are two approaches:
Assume there is markup
<SELECT name="ddlQuery" id="ddlQuery" style="width:273px;"
onchange="GetDropDownValue(event)">
...
on HTML.
One using js function:
function GetDropDownValue(e)
{
var rtnVal = "";
var sel = document.getElementById(getTargetID(e));
for (var i = 0; i < sel.options.length; ++i) {
if (sel.options[i].selected == true) {
rtnVal = sel.options[i].value;
break;
}
}
alert(rtnVal);
return rtnVal;
}
function getTargetID(e) {
if (!e) { var e = window.event; }
var objTarget = e.srcElement ? e.srcElement : e.target;
return objTarget.id;
}
another using jQuery:
$('#ddlQuery').val()
Firefox uses e.htmlEvent.target.nodeName
you can use try/catch to handle both browsers.