I'm trying to learn Javascript before I learn jQuery so I can get the foundation down before moving up.
To learn, I've made a simple guessing game that works in Chrome & Safari, but not Firefox. (I guess that is why people use jQuery!).
I adjusted the code based on this answer. But it is still not working in Firefox. Here's the relevant code. Any ideas?
function reportAnswer(e) {
if(!e) e = window.event;
questionNumber++;
document.getElementById("myCount").innerHTML = (questionNumber + 1);
var x = e.target || e.srcElement;
checkAnswer();
}
function checkAnswer() {
var thisAnswer = questionDatabase[currentQuestion].answer;
if(event.target.id == thisAnswer) {
document.getElementById("answer").innerHTML = ("YES! </br>" + questionDatabase[currentQuestion].photo);
score++;
}
else {
document.getElementById("answer").innerHTML = ("<img src=http://philly.barstoolsports.com/files/2012/11/family-feud-x2.png width='370' height='370'>");
}
}
Your checkAnswer function uses the nonstandard global window.event. You want to do two things:
Add an event or e argument to it like #thesystem suggests.
Make sure to pass that argument in from whatever your event handler is.
Related
I've try to use code from this question: How to detect `focusin` support?
but for Chromium that supports offline event hasEvent('offline') return false. Anybody know how to detect offline/online events in JavaScript?
You can try
'onoffline' in window
or
'onoffline' in document.body
It seems that online and offline events start on body and bubble up so you can't use div to detect it. But I've created this code:
var body = document.getElementsByTagName('body')[0];
body.setAttribute('ononline', 'return;')
typeof body.ononline == 'function';
Try:
return !!window.applicationCache;
If I understand properly your question, you also may want to read this article.
EDIT:
Basically you can use the following function:
function reportConnectionEvent(e)
{
if (!e) e = window.event;
if ('online' == e.type) {
alert( 'The browser is ONLINE.' );
}
else if ('offline' == e.type) {
alert( 'The browser is OFFLINE.' );
}
else {
alert( 'Unexpected event: ' + e.type );
}
}
window.onload = function() {
document.body.ononline = reportConnectionEvent;
document.body.onoffline = reportConnectionEvent;
}
Also you may check this for demo http://html5demos.com/offline-events
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
Apologize if this is answered already. Went through some of the related questions and google, but ultimately failed to see why this isn't working.
My code is as follows
<iframe id="editor"></iframe>
editorWindow = document.getElementById('editor').contentWindow;
isCtrlDown = false;
function loadEditor()
{
editorWindow.document.designMode = "on";
editorWindow.document.onkeyup = function(e) {
if (e.which == 91) isCtrlDown = false;
}
editorWindow.document.onkeydown = handleKeyDown;
}
function handleKeyDown(e)
{
if (e.which == 91) isCtrlDown = true;
if (e.which == 66 && isCtrlDown) editFont('bold');
if (e.which == 73 && isCtrlDown) editFont('italic');
}
function editFont(a,b)
{
editorWindow.document.execCommand(a,false,b);
editorWindow.focus();
}
This code works perfectly in Chrome, but the keyboard shortcuts do not work in Firefox. In fact, in Firefox it does not seem to register the events for keyup/keydown at all.
Am I doing something grossly wrong here that is mucking up Firefox?
For editable documents, you need to use addEventListener to attach key events rather than DOM0 event handler properties:
editorWindow.document.addEventListener("keydown", handleKeyDown, false);
If you care about IE 6-8, you will need to test for the existence addEventListener and add the attachEvent equivalent if it is missing.
Try using:
editorWindow = document.getElementById('editor').frameElement;
I'm not sure this will solve the issue, it may also be:
editorWindow = document.getElementById('editor').contentDocument;
Or even possibly:
editorWindow = document.getElementById('editor').frameElement.contentDocument;
One thing you can do is put the entire string in a try statement to catch any errors and see if the content is being grabbed from within the iframe.
try { editorWindow = document.getElementById('editor').contentWindow; } catch(e) { alert(e) };
The only other thought I have is that you're typing into a textbox which is within an iframe, and you may possibly have to add the onkeydown event to that specific item, such as:
var editorWindow = document.getElementById('editor').contentDocument;
var textbox = editorWindow.getElementById('my_textbox');
function loadEditor()
{
editorWindow.document.designMode = "on";
textbox.onkeydown = function(e) {
alert('hello there');
}
}
I hope one of these is the solution. I often find when it comes to cross-platform functionality it often boils down to a little trial and error.
Good Luck!
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.