I am looking at some JS code from the 20th century, and they are using document.layers in code that is trying to get the current key code. What browser are they sniffing for?
i am about to replace the code with something like this:
var fn = function(event){
event = event || window.event;
var code = event.charCode || event.keyCode;
}
but i am afraid of breaking something arcane and releasing the evil
document.layers exists in Netscape 4 and holds all <layer> and <ilayer> elements.
It was an early precursor to true DHTML.
For more information, see here. (Ten years old)
Netscape 4 is not able to display any modern web-page due to it's total lack of CSS support - so if you drop the support for this browser then you are not breaking anything that isnt already broken.
Related
I didn't notice it in Modernizr's documentation but I imagine you create a menu element then check if it exists? My only concern is that the browser may support that but not type context. Any ideas? Thanks.
I have come up with a rather shoddy solution that returns true for Firefox as far as I can tell then returns false for Chrome, IE and Opera. Check it out:
// Detect context menu support.
function contextMenuSupported() {
var oMenu = document.createElement("menu");
// Kind of backwards but seems to work.
if (oMenu.type == "list")
return true;
return false;
}
Let me know if that just horrifies you. It seems when a menu element is created with a browser that supports it, certain attributes are intrinsically defined.
I'm integrating a mootools script onto a page which has very old JavaScript functions which run a navigation vertical menu. This old script will be hard to change now.
The line breaking is:
function stgobj(id) {
with(document) return nIE && nVER < 5 ? all[id] : nNN4 ? layers[id] : getElementById(id);
}
Not sure exactly what's it's purpose, but it looks like it's rendering some elements. If commented the menu will disappear.
FF, Chrome, IE(doesn't crash, but menu does not render)
Any quick patch to resolve the browsers crashing?
Looks like its purpose is to return the element corresponding to the given ID. The code simply uses some different methods based on the browser - document.all for IE5 and earlier, and document.layers for Netscape 4. Unless you need to support those ancient browsers, you could alter the function to return just document.getElementById(id). Or better yet, ditch this function altogether and call document.getElementById directly.
However, if it's crashing modern browsers like Firefox and Chrome, then you should also look at the browser detection logic (the code that populates the nIE, nVER and nNN4 variables), otherwise it might just end up crashing elsewhere.
It's a "compatibility" function for document.getElementById. I think you should be able to equal it:
stgobj = document.getElementById.bind(document);
This question already has answers here:
ReferenceError: event is not defined error in Firefox
(2 answers)
Closed 6 years ago.
I'm using this code to check for keydown and display the string 'Pressed' while a key is down.
<body onKeyDown="doKey(window.event.keyCode)" onKeyUp="doKey2(window.event.keyCode)">
<script>
function doKey($key) {
document.getElementById('keydown').innerHTML='Pressed';
}
function doKey2($key) {
document.getElementById('keydown').innerHTML='';
}
</script>
<div id="keydown"></div>
The problem is that for some reason it's only working on Chrome. I think the 'window.event.keyCode' doesn't return anything. How do I make it work at least in Firefox too? Thanks
Some browsers have a global event object, other send the event object to the event handler as a parameter. Chrome and Internet Exlporer uses the former, Firefox uses the latter.
Some browsers use keyCode, others use charCode.
Use arguments[0] to pick up the event object sent as a parameter, and if there is no object there, there is a global object instead:
onkeydown="doKey(arguments[0] || window.event)"
In the method you can check for either keyCode or charCode
function doKey(event) {
var key = event.keyCode || event.charCode;
...
}
Note the lowercase name onkeydown. If you are using XHTML event names has to be lowercase, or the browser might ignore it.
<html>
<body onKeyDown="doKey(event)" onKeyUp="doKey2(event)">
<script>
function doKey(e) {
evt = e || window.event; // compliant with ie6
document.getElementById('keydown').innerHTML = evt.keyCode+' Pressed';
}
function doKey2(e) {
document.getElementById('keydown').innerHTML='';
}
</script>
<div id="keydown"></div>
</body>
</html>
If we passed event as parameter, most modern browsers will work well. I have tested with Chrome 12, Firefox 4, IE 7/8/9.
I've run into the same problem, as I'm sure thousands of coders have.
The problem is that the browsers (other than IE) don't like window.event.
I'm poking around trying to find a solution (which is how I stumbled across this), and I found the following (so far):
1) Write JQuery:
$(document).keyup(function(e) {
var GetKey = e.keyCode;
`enter code here`
}
});
2) Redefine the key variable:
var key = (window.event) ? evt.keyCode : evt.which;
I tried the JQuery solution. It seems to be okay in FF, but I ran into an unexpected bug in IE that I'm still trying to solve. I haven't yet tried the second solution; that's next, if I can't get the JQuery to work.
I'm working on a web app that works fine inside the LAN using HTTP but when I test it remotely over SSL it fails for IE (7 & 8). Firefox, Camino and Safari all work perfectly.
I've tracked down the issue to key being undefined. The relevant bit of code is:
function showResult(e,str,num) {
var key = (window.Event) ? e.which : e.keyCode;
if(((key > 32 && key < 58) || (key > 64 && key < 91) || (key > 95 && key < 123)) && (str.length >= num)) {
Any clues as to why key would be undefined for IE over SSL but works fine over HTTP? Better yet, can someone tell me how to overcome this problem? FWIW, I don't need to support IE prior to version 7.
Update:
There was an answer which suggested replacing
var key = (window.event) ? e.which : e.keyCode;
with
var key;
e = e || window.event;
key = e.keyCode || e.which;
That works. The problem now is that I can't accept that answer because it has been deleted.
Ok, I'll re-add that answer, even though it wasn't mine, and add some info along the way so you can feel OK with accepting it even if it wasn't my answer from the beginning.
So, the suggested code is this:
var key;
e = e || window.event;
key = e.keyCode || e.which;
What does || do? For one it's the logical or operator, which would return true if one of the sides evaluate to boolean true.
It also has another use in JS. If you give it two arguments and the first one is undefined, it will return the second argument. This means, in the code above, that if e is undefined, you instead get window.event which is IE's traditional event object.
Same thing goes with e.keyCode || e.which whichever one exists is used. So in the end, you're likely to end up with a valid key code on various browsers. All is good in wonderland.
But wait, doesn't your original code do something similar?
var key = (window.Event) ? e.which : e.keyCode;
Uh-huh. What's that? JavaScript is case-sensisitive, so window.Event is not the same as window.event in the code above. window.event is IE's traditional event object that you would use get information about the event that occurred, while window.Event (which you can see from the initial capital letter) is a constructor, or more specifically in this case an interface.
Point is, in that code it was used to detect Mozilla. If it exists, choose e.which (One of the places where Mozilla stores the key code) otherwise go for e.keyCode where IE would store the key code.
However, this is based on the flawed assumption that IE doesn't have the window.Event constructor defined. It does have it defined as of IE8, at least. This means that e.which is chosen over e.keyCode, on newer versions of IE. e.which has never and will never be supported in IE. That's why key ends up being undefined.
But, uhm, why does it differ between encrypted and unencrypted connections? That's a good question. While I cannot know for sure without access to your development environment, I would assume it has something with IE's compatibility modes.
IE has historically (over the last 10 years) been the most quirky and non-standard browser around. This has lead to people a) programming ignorantly according to IE's standards b) creating workarounds for IE's behaviors. If MS just made IE standards-compliant, that would break many pages which rely on IE's quirky behavior in one way or the other. Microsoft has ackowledged this by making IE8+ emulate older versions of IE so pages won't break, unless told otherwise.
I can only assume that, for whatever reason, in your test environment the page ends up running in the "IE7" mode which might not have the window.Event constructor/interface defined. This would make your old code use e.keyCode which is ey OK. Then perhaps in your production environment, or maybe just because of the encrypted connection (only ghawd knows what MS is doing) you end up with a newer IE mode so window.Event is actually defined and e.which is chosen. This makes IE a cheeky monkey.
Bottom line: Use the new code.
Most probably, you've included a script over http (rather than https), which will fail to load because the page itself is secure and the included file insecure.
I've been searching for this for a couple of days now and so far, the best I can come up with is checking the list below. I really don't like to check for support based on User-Agent, especially since it can be spoofed. I've also heard of at least one instance where the list below is incorrect (noted below).
Is Internet Explorer?
Is WebKit? (But I've read that mobile Safari doesn't support it)
Is Opera?
Is Gecko and version >= 1.9? (meaning Firefox 3 or later)
Is there a better method based on testing for support directly via JavaScript, or is this pretty much the only way to test for support?
var canEditContent= 'contentEditable' in document.body;
The best way to check for a certain feature is to actually test for that feature on an element that you know should support it, like this:
if(element.contentEditable != null)
// then it's supported
or
if(typeof(element.contentEditable) != 'undefined')
// same thing.. but with typeof you can be more specific about the type of property you need to find
The best solution for my scenario (similar to yours) I came up with is below. It's not probably bulletproof, but covers most of the situations:
var ua = navigator.userAgent;
var android_version = ua.match(/Android ([0-9\.]+)/);
var div = document.createElement("DIV");
if( typeof(div.contentEditable) == 'undefined' ||
(/(iPhone|iPod|iPad)/i.test(ua) && /OS [1-4]_\d like Mac OS X/i.test(ua)) ||
(android_version!=null && parseFloat(android_version[1])<3 ) ||
(/(Opera Mobi)/i.test(ua))
) {
// doesn't support contenteditable
} else {
// supports contenteditable
}
You can test it out in this jsFiddle.
Notice: Depending on your needs and purpose, you might need to detect IE version as well, because it's support of contenteditable is ... "not ideal" :-) Most of the pains is dealt by super library Rangy.js.
bobince's answer works for the most part but, as has been said, you will need user agent sniffing to exclude iOS and Android versions that don't bring up the software keyboard. I'm currently using something like this:
function isContentEditable() {
var canEditContent = 'contentEditable' in document.body;
if (canEditContent) {
var webkit = navigator.userAgent.match(/(?:iPad|iPhone|Android).* AppleWebKit\/([^ ]+)/);
if (webkit && parseInt(webkit[1]) < 534) {
return false;
}
}
return canEditContent;
}
This should stop older iOS and Android devices from returning true. It still has one problem though: physical keyboards. If, for example, a device is running Android 2.3 but has a physical keyboard then the user will be able to use contentEditable but this function will return false. Physical keyboards are quite rare though.
More commonly, on some devices it may be possible for the user to bring up the on screen keyboard by pressing and holding the menu button. Obviously this isn't really something you should expect your users to know about.
You could mitigate these issues slightly by having some way for the user to manually override the sniffing part of the detection script. You could implement this in the isContentEditable function by adding an override check to "if (canEditContent)". However, Implementing the UI for this might present more of a challenge ;).