Web Bug Track - A place to track Web bugs... in JavaScript, DOM, CSS, XHTML, HTML in all Web Browsers... Firefox, Internet Explorer, Safari, Chrome, Opera, Konqueror and more.
As more and more applications go online in this Web 2.0 world, interactions with forms are critical to an applications success. Safari leads the way with built-in textarea resizing but it has a major issue with form field focus.
Since data entry in forms is a crucial part of online forms, ensuring that your forms are both keyboard and mouse navigable is important. Unfortunately in Safari the keyboard navigation breaks if you use the mouse on radio or checkbox elements. This becomes a major issue because although radio and checkbox elements are keyboard accessible, in general users prefer to use the mouse to make their selection(s).
The issue is this. If you use the mouse to select a radio or checkbox field one expects that that field has the focus and thus a 'Tab' will take you to the next available field (or whatever is defined in the tabindex order). When the user presses 'Tab' in Safari, the focus resets to the first form field on the page!
If you use the mouse for other types of fields, or use only the keyboard the issue doesn't occur.
Will work just fine. When you submit the page, the parameter on the GET/POST request/submission will be called "flower".
However if you plan to use JavaScript to re-access that field in IE (e.g. to perform some client side field validation), don't try to access it by name! It will work in all browsers except Internet Explorer.
The onchange event can be attached (inline or as an event handler) to any form element. It fires whenever the value of the form field changes. Unfortunately, the behavior is a bit strange in IE, in that for a checkbox, or a radio button field, the event doesn't fire when it is supposed to (right when you click the option you want to choose), but instead it only fires, when you click elsewhere on the page/form, or if you explicitly call blur(); on the field.
As soon as you click on either of these radio buttons, the alert should pop up telling you what you just selected.
Try it out!
Green
Blue
You'll notice that it works just fine in all browsers except Internet Explorer. In fact, in IE, clicking once will not pop up the alert, but clicking the other radio button will pop up the alert, but the value is the last radio button clicked.
Known Workarounds: One. Instead of using the onchange event, use the onclick event for radio and checkbox elements instead (or at least for IE)
The button element in HTML, just like an input element (of type button) is designed (by spec) to submit the contents of the value attribute when it is pressed to submit a form. However in Internet Explorer, this functionality is broken as it submits the innerHTML of the button element rather than the contents of the value attribute.
If a user clicked this button, the server should get a parameter called "doAction" with a value of "true_content". IE on the other hand, will return the same parameter, with the value ' <span style="font-weight:bold;">Please</span> click <em>Me</em>!'.
Known Workarounds: None. See MSDN for the latest news on when the button element will be fixed.
The for attribute on a label element will give focus to the related form option, and in the case of radio/checkbox elements, it will select/unselect them. However in IE6, a label with a for attribute linked to a select list will cause a re-selection of the first option instead of just giving focus.
Clicking on "Color:" should put focus on the selected value "Red" in the select box. However IE6 will give it focus, but select another option, in this case "Blue".
Known Workarounds: One. IE has a proprietary event called "onfocusin" if you attach code to this, you can reset the correct value. However most advise that you try to avoid using the label element for a select list with a pre-selected value in IE6.
On Windows XP in IE6 or IE7, with the default themes applied the input button element renders stretched and distorted when the length of the value exceeds 17 characters.
In fact, the padding on the button also changes, depending on the length of the value attribute, which is also a buggy.
Example:
<input type="button" name="test" value="Distorted in IE on XP" onclick="alert('How do I look?');"/>
View this page in Windows XP in IE6 or IE7 to see the rendering bugs.
You don't even have to use Windows XP to see the padding expansion bug. IE6 on Windows2000 or Windows2003 will also display the issue.
Certain attributes can not be retrieved properly in IE. The first example, is the "for" attribute, which is used by <label> tags to link to input fields.
Example:
<script type="text/javascript"> var myLabel = document.getElementById( 'test' ); alert( 'myLabel is for: ' + myLabel.getAttribute( 'for' ) ); </script>
There is a workaround for this (see below)
Known Workarounds: Some.
Example Workaround Code:
<script type="text/javascript"> var myLabel = document.getElementById( 'test' ); alert( 'myLabel is for: ' + myLabel.attributes['for'].nodeValue ); </script>
The above code works perfectly, in all browsers returning the element with the id "description". Well almost. IE will return the element with that id, but it will also return any element with a name set to "description". At first glance this may not seem such an issue, but consider this; Do you have a meta tag on any of your pages? Do any of them have a name attribute with the value description? If so, you will get a reference to the meta tag, not the form element (or whatever you thought you were getting, as indicated in the spec for getElementById).
When you think for a moment, about where the name attribute is set, this becomes rather scary. Any named anchor, can now conflict with your well defined element ids.
Notes: So you might ask, why is this broken in Opera? Opera is usually pretty good at supporting the specs! Well, it seems that for maximum compatibility with IE, even though it is implemented wrong, they mimicked the broken behavior.
Known Workarounds: No direct methods, using Option #3 below is suggested.
Workaround Option: 1 If you rely heavily on getElementById, and you suspect that you may have name conflicts, or that user specific content added to a page may cause conflicts you can use getElementsByTagName( tagName ) then iterate over the results and compare the value returned by getAttribute( 'id' ).
Workaround Option: 2 If you have the ability to globally apply fixes for IE and Opera, the following code will make both of them follow the spec to a 'T', with a very tiny performance hit.
In this example, we redifine the getElementById method, to work as it was intended. Example Workaround Code:
//use browser sniffing to determine if IE or Opera (ugly, but required) var isOpera, isIE = false; if(typeof(window.opera) != 'undefined'){isOpera = true;} if(!isOpera && navigator.userAgent.indexOf('Internet Explorer')){isIE = true;}
//fix both IE and Opera (adjust when they implement this method properly) if(isOpera || isIE){ document.nativeGetElementById = document.getElementById; //redefine it! document.getElementById = function(id){ var elem = document.nativeGetElementById(id); if(elem){ //verify it is a valid match! if(elem.id == id){ //valid match! return elem; } else { //not a valid match! //the non-standard, document.all array has keys for all name'd, and id'd elements //start at one, because we know the first match, is wrong! for(var i=1;i<document.all[id].length;i++){ if(document.all[id][i].id == id){ return document.all[id][i]; } } } } return null; }; }
Oh my! this just gets better and better! (after posting and using this I noted (as did J. Max Wilson) that the second workaround, actually exposes another bug in IE!
Third time's a charm (we hope!)
Workaround Option: 3
Same as workaround 2 above, but rather than test elem.id or elem.getAttribute('id') we'll use the much safer elem.attributes collection. Unfortunately if the element you are looking for, in turn has a child element with a name or id attribute, that is set to "id", it will not test the attribute, but rather the child element. (bug 162 - global namespace pollution)
Example Workaround Code:
//use browser sniffing to determine if IE or Opera (ugly, but required) var isOpera, isIE = false; if(typeof(window.opera) != 'undefined'){isOpera = true;} if(!isOpera && navigator.userAgent.indexOf('Internet Explorer')){isIE = true;}
//fix both IE and Opera (adjust when they implement this method properly) if(isOpera || isIE){ document.nativeGetElementById = document.getElementById; //redefine it! document.getElementById = function(id){ var elem = document.nativeGetElementById(id); if(elem){ //verify it is a valid match! if(elem.attributes['id'] && elem.attributes['id'].value == id){ //valid match! return elem; } else { //not a valid match! //the non-standard, document.all array has keys for all name'd, and id'd elements //start at one, because we know the first match, is wrong! for(var i=1;i<document.all[id].length;i++){ if(document.all[id][i].attributes['id'] && document.all[id][i].attributes['id'].value == id){ return document.all[id][i]; } } } } return null; }; }
<script type="text/javascript"> var checkboxOptions = document.getElementsByName( 'preferences' ); alert( 'There are ' + checkboxOptions.length + ' preference options.' ); </script>
Known Workarounds: No direct methods.
Example 1 Workaround Code: Developers must iterate over all potential tag matches with a call to getElementsByTagName(), then for each NodeList returned, check for a match against the name attribute with getAttribute( 'name' ). Alternatively, if retrieving elements from a form by name, formObj.elements[name]; will return a form element array that will suffice.
Example Workaround Code:
<script type="text/javascript"> //option 1 var inputs = document.getElementsByTagName( 'input' ); var checkboxOptions = []; for(var i=0;i<inputs.length;i++){ if(inputs.item(i).getAttribute( 'name' ) == 'preferences' ){ checkboxOptions.push( inputs.item(i) ); } } var checkboxOptions = document.getElementsByName( 'preferences' ); //option 2 var checkboxOptions = document.forms[formIndex].elements['preferences'];
(Note: If there is only one checkbox, using option 2, the length will be undefined, since browsers treat a single checkbox as an atomic item, but multiple as an array)
Example 2 Workaround Code: Since IE keeps an associative array in the proprietary document.all object, we can carefully iterate over it to solve this issue. (in theory, code below is untested)
<script type="text/javascript"> //use browser sniffing to determine if IE or Opera (ugly, but required) var isOpera, isIE = false; if(typeof(window.opera) != 'undefined'){isOpera = true;} if(!isOpera && navigator.userAgent.indexOf('Internet Explorer')){isIE = true);
if(isIE){ var document._getElementsByName = document.getElementsByName; document.getElementsByName = function(name){ var temp = document.all[name]; var matches = []; for(var i=0;i<temp.length;i++){ if(temp[i].name == name){ matches.push(temp[i]); } } return matches; }; } </script>
In theory, this should work, but it might need adjusting, if there is only 1 item with the name, and that item, has a length property (e.g. a form, a select list, a radio button or checkbox set.) If you find the perfect solution, please advise.
Once Upon A Time: Every Web based application has to start somewhere, but I'm going to jump in to a very specific spot.
Every Web based application has forms, likely lots of forms, and each of those forms has buttons, often at least a few.
Buttons are the perfect UI component. Just looking at them it is obvious what to do with them , and design wise they provide the perfect constraints to apply actions to a form.
Buttons usually have words that depict exactly what they are for , they display a pointer cursor when you mouseover them, and they can even be displayed in a disabled state , indicating that a particular action is not available at this time.
As a developer, you have the choice to "roll-your-own" fancy buttons by using images and/or css, but the basic input type="button", does all the work for you.
...
So if they are so perfect, why devote an article to them? ...well, they are great, but there are drawbacks as well.
So its day 2 or 25 or 457 of your web application's life. You've built a pile of forms and pages to interact with your software, and everything is great. In fact, if you take a minute to ponder, those buttons you have, certainly add up... well into the hundreds now, and you add more with every update to the application.
You used the element designed for this task, the <input type="button".../>. Straight "out-of-the-box" they had everything you needed. You could submit forms, execute JavaScript, enable, disable, even change the text on the button, or the value it submitted.
Then one day, things took a bit of a nose dive. Users started to complain that the buttons looked ugly, if they were wordy, distorting as if melting at the sides. Welcome to the world of bugs. This bug, is the famous Windows XP Button bug (bug 101), which under most circumstances, causes buttons with 18 or more characters to start stretching oddly. There are some minor tweaks you can make, to try and fix a bit of the stretching, but they aren't perfect, and they will still eventually fail.
So, depressed and frustrated, you check your specs at the W3C and realize all is not lost, there is a <button>Click Me</button> element that might just save the day!
Shattered Dreams:
After building some super sexy button elements, you figure you have it licked! Not only do these buttons look like buttons, but you can add images, spans of text, line breaks, you name it! Awesome!
Everything is great, until you submit that first form.
What on earth is all that garbage HTML when I submit my form? Welcome to (bug 341).
So, using the button element won't solve your problem, and in fact, you can't even use it in your application because one browser "Broke The Web" ~TM. It's too bad, because beyond the animated GIF bug for buttons (reference), the button element would be the perfect control for great looking Web 2.0 applications.
Like many 12 step programs, you've reached level 1. Admitting defeat. Try as hard as you can to follow the specs and use the proper elements, you have to concede that you may need to do some hacking, or break the rules.
You also start getting a lot more emails from users complaining that their auto-completion works fine on other web sites, and applications, but it isn't working on yours? After gathering the info, it turns out that only your IE users are affected.
Strange? Auto-complete is a feature of the browser, and you don't specifically go out of your way to block it anywhere in your application. Turns out, that Auto-complete was implemented in a buggy manner in IE (bug 137) and now your application suffers because of it. At least there is a hackable workaround for this issue.
It's the afternoon now, and you're keen to implement a new section in your application. The new section does some neat stuff with AJAX calls to refresh parts of the page with new data, and executes some server-side validation to improve usability. As part of this process, some of the options in some dropdowns need to be disabled.
Everything works fine in Firefox, Safari, and Opera... but before you commit your new code, you test it in IE... What? there's no JavaScript error, but the options do not dynamically get disabled/enabled as needed! You've inadvertently discovered that IE doesn't support disabled options (bug 293) and you struggle to figure out a realistic workaround. Ugh!
In the ideal world, each and every browser would support these properly, and development would be a breeze... but alas, that is not the case.
For each method listed below, I'll link to the various bugs in terms of their implementation.
getElementById( id )
What seems like the most simplistic method available, yet also one of the most powerful, is unfortunately broken. (bug 152) describes how Internet Explorer, will return an element, if it matches by the id attribute as designed, but will also return a match based on the name attribute. It will also disregard your case-sensitive searches and return elements with IDs with non-matching case (bug 154).
createElement( type )
Another super simple, but super useful method, is again plagued with issues. The correct syntax is:
var myDiv = document.createElement( 'div' ); //or var myHeader = document.createElement( 'h2' ); //or var myTextBox = document.createElement( 'input' );
Well, lets say you are building up some form elements on-the-fly (very common in today's Web 2.0 world). Say you want to add a hidden field named "showOption" that you will pre-populate with the value "messages", just before the form is submitted to take the user directly to a certain screen.
The code would look something like this: development would be a breeze... but alas, that is not the case.
var hiddenOption = document.createElement( 'input' ); hiddenOption.setAttribute('name', 'showOption'); hiddenOption.setAttribute('value', 'messages'); hiddenOption.setAttribute('type', 'hidden'); var myForm = document.forms[0]; document.appendChild(hiddenOption, myForm); myForm.submit();
So as long as you have a form, this should work! Well, not in Internet Explorer!
As it turns out, in (bug 235) Internet Explorer, you can't set the name attribute on an Element... any Element! To overcome this, there is a hack, which explains why the createElement method is broken (bug 124) in IE. To make the above code snippet work in IE, you need to do this:
var hiddenOption = document.createElement( '<input name="showOption">' ); hiddenOption.setAttribute('type', 'hidden'); hiddenOption.setAttribute('value', 'messages'); var myForm = document.forms[0]; document.appendChild(hiddenOption, myForm); myForm.submit();
Did you spot the changes?
Change#1.) The Element we create is a string that is the HTML tag, with the name attribute. This is not only quite ugly (mixing tags in strings), but also completely against the spec! document.createElement Spec Reference.
Change#2.) We moved the "type" attribute up to be the first attribute set. The reason for this, is that in IE you can't change the type attribute (bug 237) after the node is added to the DOM, and the default type is always "text". In this code snippet, it didn't matter, but if we had added this to the DOM, before setting the type, we would have been stuck.
Issue: #137 Affects: IE5, IE5.5, IE6, IE7, IE8 Beta 1, IE8 Beta 2, IE8 PR1, IE8 RC1 Description: When a form is submitted, by any method other that an input button of type="submit", the data in the form is NOT stored for future use in AutoComplete.
Example: calling document.forms['foo'].submit(); from JavaScript will not save the form contents for future use.
Known Workarounds: According to this KB article KB:329156, explicitly calling this function, before calling .submit(); will store the data in the AutoComplete history.
Example Workaround Code:
function fixSubmit(formObj){ window.external.AutoCompleteSaveForm(formObj); formObj.submit(); }
Related Issues: The workaround for this bug, could be directly incorporated into the .submit() method for all forms on a page, by prototyping a .submit() wrapper on the HTMLFormElement object, however due to bug 186, this is not possible.
Feb. 7,2009 - Added a new Tag called Broken By Design. It is applied to all reported bugs that the browser vendor has indicated that they have no intention of fixing this bug any time soon and is therefore broken "By Design".
Feb. 7,2009 - Updated as many bug reports as possible for Internet Explorer 8 (IE8) to reflect the status of IE8 RC1 since according to the IE Blog the RTM release is coming soon. If you want to know, click to see what has been fixed?
Drag/Right-Click and save to your Bookmarks
View generated source of a page in IE View Source
Show Rendering Mode for IE6/7 Render Mode
Show Rendering Mode for IE8 IE8 Render Mode
Show how many style tags a page has # style tags