srcElement.readOnly and target.readOnly problems in Internet Explorer - javascript

I'm not sure I understand the behavior of IE in this script I'm working. This is part of the script I'm using that seems to work fine in Chrome
$(document).keydown(function (event) {
var keyvalue = event.which || event.keyCode;
var eventtarget = event.srcElement.nodeName || event.target.nodeName;
var readonlycheck = event.srcElement.readOnly || event.target.readOnly;
});
The problem comes in on the readonlycheck variable. In IE I get the error of
"Unable to get property 'readOnly' of undefined or null reference."
In Chrome, readOnly returns 'true' if it's defined and 'false' if it's not. IE gives me an error, even though it still works with the nodeName.
Where I get really confused is that I can make it work by changing the last line to eliminate the target.readOnly. So this seems to work in both browsers...
var readonlycheck = event.srcElement.readOnly;
Can anyone explain why this behaves differently for readOnly? Also, I thought srcElement was IE only, so why is Chrome still working without the target.readOnly?
Any help would be appreciated. I'm still very new to javascript and jquery so I'm sure I'm missing something.

var readonlycheck = event.srcElement.readOnly || event.target.readOnly;
should change it to
var readonlycheck = (event.srcElement !== undefined) ? event.srcElement.readOnly : event.target.readOnly;
how you wrote your code, even though srcElement.readOnly does exist, when it evaluates to false it attempts to read event.target, which breaks IE.

In your code you specify function(e) though in your function you use event instead of e.
Additionally as event.target and event.srcElement are the same thing it would make more sense to initiate the target once at the start.
var target = event.target || event.srcElement;
Updating your code to something similar to the below should work:
$(document).keydown(function (event) {
var target = event.target || event.srcElement;
var keyvalue = event.which || event.keyCode;
var eventtarget = target.nodeName;
var readonlycheck = target.readOnly;
});

The problem is the short-circuit || operator. If event.srcElement.readOnly evaluates to false, the right operand, (which should be) e.target.readOnly will be evaluated. It's the same as writing, for example:
var readonlycheck = false || e.target.readOnly;
You can use braces instead to work around this issue:
var readonlycheck = (e.target || event.srcElement).readOnly
Note that I moved the standards compliant to the left hand side so that it's evaluated first. It doesn't make much of a difference here, but on more time-consuming operations it could, so I just find that it's a good practice to get into.
I start most of my event handlers with the following code when I need the event object and the event target:
function evtHandler(evt) {
evt = evt || window.event;
var target = evt.target || evt.srcElement;
}

Related

RegExp TAB in Firefox

This code works in all popular browsers except Mozilla Firefox. The problem is that the TAB-key doesn't work. Can anyone figure out why? It's connected to a form of text fields. I've tried adding '\t', didn't work. It works in all browsers for me, except Firefox...
$('.mail').bind('keypress', function (event) {
var regex = new RegExp("^[a-zA-Z0-9#\S._\n\r\b-]+$");
var key = String.fromCharCode(!event.charCode ? event.which : event.charCode);
if (!regex.test(key)) {
event.preventDefault();
return false;
}
});
without going into the regular expression, you can easily allow the tab keypress by comparing against its code:
$('.mail').bind('keydown', function (event) {
var regex = new RegExp("^[a-zA-Z0-9#\S._\n\r\b-]+$");
var key = String.fromCharCode(!event.charCode ? event.which : event.charCode);
if (!regex.test(key) && event.which != 9) {
event.preventDefault();
return false;
}
});
If you run into more cases that should work but don't it might be good to revisit the regex but if that's the only case then this quick workaround should be enough.
Also note I'm using keydown instead of keypress (event.which throws different codes on keypress)
jsfiddle

Create KeyEvent in Javascript

I have the following problem - I'm catching a key event an I need to create a new altered key event(since it seems the keyCode property is read-only) and afterwards handle the newly created KeyEvent. I came across several old posts in StackOverflow where similar situations are handled, but:
I need this to be working under Webkit /there's a solution here in StackOverfow but it is working only in Gecko/
I need to create another KeyEvent, but not TextInputEvent, since the TextInputEvent will only let my specify a string to be inserted, whilst I cannot do that as I use a third party tool that needs to handle this event and I need a keycode.
I tried jQuery#trigger() but it won't work for me. My code is as follows
var event = jQuery.event('keydown');
event.which = 13; //I'm trying to simulate an enter
$('iframe').contents().find('document').find('body').trigger(event); //my content is inside an iframe
(function($){
$(window).load(function(){
var e = $.Event("keydown");
e.which = 13;
e.keyCode = 13;
$('iframe').contents().find('html, body').trigger(e);
});
})(jQuery);

JavaScript "normalize event object"

This program taken from a book Pro JavaScript Techniques is used to create hover-like functionality for an Element.
I don`t understand what the author means when he says, in the comments, Normalize the Event object.
Can you tell me
a) why is this necessary, explaining what would happen if it wasn`t normalized
b) how does the code provide achieve the effect
Thank you.
var div = document.getElementsByTagName('div')[0];
div.onmouseover = div.onmouseout = function(e) {
//Normalize the Event object
e = e || window.event;
//Toggle the background colover of the <div>
this.style.background = (e.type == 'mouseover') ? '#EEE' : '#FFF';
};
It's referring to window.event, IE's non-standard version of the event object. If it weren't normalized, it would break in at least one browser.
What the code does is set e to itself (essentially a no-op), if the parameter is truthy (the event parameter is properly set). If not (in IE), it sets it to window.event.

JavaScript KeyCode Values are "undefined" in Internet Explorer 8

I'm having trouble with some JavaScript that I've written, but only with Internet Explorer 8. I have no problem executing this on Internet Explorer 7 or earlier or on Mozilla Firefox 3.5 or earlier. It also executes properly when I use compatibility mode on Internet Explorer 8.
What I'm doing is overriding the Enter keystroke when a user enters a value into a textbox. So on my element I have this:
<asp:TextBox ID="ddPassword" runat="server" TextMode="Password" onkeypress="doSubmit(event)" Width="325"></asp:TextBox>
And then I have the following JavaScript method:
function doSubmit(e)
{
var keyCode = (window.Event) ? e.which : e.keyCode;
if (keyCode == 13)
document.getElementById("ctl00_ContentPlaceHolder1_Login").click();
}
Again, this all works fine with almost every other browser. Internet Explorer 8 is just giving me a hard time.
Any help you might have is greatly appreciated.
UPDATE: Thanks everyone for your quick feedback. Both Chris Pebble and Bryan Kyle assisted with this solution. I have awarded Bryan the "answer" to help with his reputation. Thanks everyone!
It looks like under IE8 the keyCode property of window.Event is undefined but that same property of window.event (note the lowercase e) has the value. You might try using window.event.
function doSubmit(e)
{
var keyCode = (window.event) ? e.which : e.keyCode;
if (keyCode == 13)
document.getElementById("ctl00_ContentPlaceHolder1_Login").click();
}
Just a hunch, try this:
var keyCode = e.keyCode ? e.keyCode : e.which;
It's worked on this way on my code:
var kcode = (window.event) ? event.keyCode : event.which;
try this:
function checkKeyCode(e){
if (!e) e = window.event; var kCd = e.which || e.keyCode;
return kCd;
}
I personally prefer the multi-key approach. This allows multiple keys to be detected, but also a single key just the same, and it works in every browser I've tested.
map={}//declare object to hold data
onkeydown=onkeyup=function(e){
e=e||event//if e doesn't exist (like in IE), replace it with window.event
map[e.keyCode]=e.type=='keydown'?true:false
//Check for keycodes
}
An alternative method would be to separate the onkeydown and onkeyup events and explicitly define the map subitems in each event:
map={}
onkeydown=function(e){
e=e||event
map[e.keyCode]=true
}
onkeyup=function(e){
e=e||event
map[e.keyCode]=false
}
Either way works fine. Now, to actually detect keystrokes, the method, including bug fixes, is:
//[in onkeydown or onkeyup function, after map[e.keyCode] has been decided...]
if(map[keycode]){
//do something
map={}
return false
}
map[keycode] constitutes a specific keycode, like 13 for Enter, or 17 for CTRL.
The map={} line clears the map object to keep it from "holding" onto keys in cases of unfocusing, while return false prevents, for example, the Bookmarks dialog from popping up when you check for CTRL+D. In some cases, you might want to replace it with e.preventDefault(), but I've found return false to be more efficient in most cases. Just to get a clear perspective, try it with CTRL+D. Ctrl is 17, and D is 68. Notice that without the return false line, the Bookmarks dialog will pop up.
Some examples follow:
if(map[17]&&map[13]){//CTRL+ENTER
alert('CTRL+ENTER was pressed')
map={}
return false
}else if(map[13]){//ENTER
alert('Enter was pressed')
map={}
return false
}
One thing to keep in mind is that smaller combinations should come last. Always put larger combinations first in the if..else chain, so you don't get an alert for both Enter and CTRL+ENTER at the same time.
Now, a full example to "put it all together". Say you want to alert a message that contains instructions for logging in when the user presses SHIFT+? and log in when the user presses ENTER. This example is also cross-browser compatible, meaning it works in IE, too:
map={}
keydown=function(e){
e=e||event
map[e.keyCode]=true
if(map[16]&&map[191]){//SHIFT+?
alert('1) Type your username and password\n\n2) Hit Enter to log in')
map={}
return false
}else if(map[13]){//Enter
alert('Logging in...')
map={}
return false
}
}
keyup=function(e){
e=e||event
map[e.keyCode]=false
}
onkeydown=keydown
onkeyup=keyup//For Regular browsers
try{//for IE
document.attachEvent('onkeydown',keydown)
document.attachEvent('onkeyup',keyup)
}catch(e){
//do nothing
}
Note that some special keys have different codes for different engines. But as I've tested, this works in every browser I currently have on my computer, including Maxthon 3, Google Chrome, Internet Explorer (9 and 8), and Firefox.
I hope this was helpful.
Try adding onkeyup event as well and call the same function.
TIP:
You can add debugger; at beginning of doSubmit to set a break, then you can examine keyCode.
I think window.Event.keyCode works in IE8 (I can't test right now though)
Or something like that.
var keyCode = e.which || e.keyCode;

event is not defined in mozilla firefox for javascript function?

function onlyNumeric() {
if (event.keyCode < 48 || event.keyCode > 57) {
event.returnValue = false;
}
}
onkeypress=onlyNumneric();
In IE, this code is working fine. However, in Mozilla Firefox, the event is an undefined error.
In FF/Mozilla the event is passed to your event handler as a parameter. Use something like the following to get around the missing event argument in IE.
function onlyNumeric(e)
{
if (!e) {
e = window.event;
}
...
}
You'll find that there are some other differences between the two as well. This link has some information on how to detect which key is pressed in a cross-browser way.
Or quite simply, name the parameter event and it will work in all browsers. Here is a jQueryish example:
$('#' + _aYearBindFlds[i]).on('keyup', function(event) {
if(! ignoreKey({szKeyCodeList: gvk_kcToIgnore, nKeyCode: event.keyCode })) this.value = this.value.replace(/\D/g, '');
});
This example allows digits only to be entered for year fields (inside a for each loop selector) where ingoreKey() takes a keyCode list/array and compares the event keyCode and determines if it should be ignored before firing the bind event.
Keys I typically ingore for masks/other are arrow, backspace, tabs, depending on context/desired behaviour.
You can also typically use event.which instead of event.keyCode in most browsers, at least when you are using jQuery which depends on event.which to normalize the key and mouse events.
I don't know for sure what happens under the covers in the js engines, but it seems Mozilla FF respects a stricter scope, wherein, other browsers may be automatically addressing the window.event.keyCode scope on their own when the event is not explicitly passed in to a function or closure.
In FF, you can also address the event by window.event (as shown in some examples here) which would support this thought.
Some browsers may not support keyCode you have to use keyChar
function onlyNumeric() {
var chars = event.keyCode | event.keyChar;
if (chars < 48 || chars > 57) {
event.returnValue = false;
}
}
onkeypress=onlyNumneric();

Categories

Resources