Search code examples
javascriptjqueryinternet-explorer-9

JavaScript Failing in IE9 Randomly / FORM Tag Containing DIV Closing Prematurely in IE9


The general gist of the problem is that random commands seem to not work in IE9, or only work occasionally. Commands that work on other pages just fine.

I've excluded some things I didn't need so now there are only two javascripts on the page. One is jQuery 2.0.3, and the other is the pages main action script:

$(function()
    {
    $("#lib").addClass("this_page");

    $(".output").each(convert_values);

    $("form .input_class").keyup(convert_values);
    $("form .input_class").change(convert_values);
    $(".swap").click(function($e)
        {
        var $form = $(this).closest("form");        
        var $input_value = $form.find(".input_units").val();
        var $output_value = $form.find(".output_units").val();
        $form.find(".input_units").val($output_value);
        $form.find(".output_units").val($input_value).change();
        $e.preventDefault();
        });
    });


function convert_values()
    {
    var $form = $(this).parent();
    var $input = $form.find(".input").val();
    $form.find(".input").removeClass("input_error");
    var $input_units = $form.find(".input_units").val();
    var $output_units = $form.find(".output_units").val();
    var $result = 0;

    if ($input == "") { $input = "0"; }

    console.log("data-type='"+$form.attr("data-type")+"'");
    if ( $form.attr("data-type") == "temp" )
        {
        switch ( String($input_units) + String($output_units) )
            {
            case "fc":
                $result = (Number($input) - 32) * (5/9); break;
            case "fk":
                $result = ((Number($input) - 32) * (5/9)) + 273.15; break;
            case "cf":
                $result = (Number($input) * 1.8) + 32; break;
            case "ck":
                $result = Number($input) + 273.15; break;
            case "kc":
                $result = Number($input) - 273.15; break;
            case "kf":
                $result = ((Number($input) - 273.15) * 1.8) + 32; break;
            default:
                $result = $input;
            }
        }
    else
        {
        console.log("("+$input+" / "+$output_units+") * "+$input_units);
        $result = (Number($input) / Number($output_units)) * Number($input_units);
        }

    if (isNaN($result))
        {
        //play_a_sound("snd_fail");
        $form.find(".input").addClass("input_error");
        $result = "Input Error";        
        }

    $form.find(".output").val($result);
    }

The results of this are very strange. My convert_values( ) function is called several times at page load, and it seems to work fine. But then when you call it by clicking on selects after page load, it doesn't work.

More specifically,

var $input = $form.find(".input").val();
var $input_units = $form.find(".input_units").val();
var $output_units = $form.find(".output_units").val();

These three lines work several times just after the script loads. But later on in the script, $output_units is undefined when the function is called. This one function and event handler are used to process several different individual HTML forms, which is why there are no specific IDs, only classes and $(this) based identifiers. But why would 2 of those commands work, but not the third? Why would it work sometimes, but not the rest of the time.

Also, potentially BEFORE that even happens, there's this check:

if ( $form.attr("data-type") == "temp" )

Most of the forms do not have this attribute. And processing goes normally. But halfway down the page, one form DOES have this attribute. But IE9 still returns "undefined" from this. IE9 DOES support HTML5 data- attributes, so theres no obvious reason why this isn't working.

Based on what I am currently logging to the console, you can see when those first three values are working properly, and when one of them cuts out and does not work. And that same debug logging also shows you when IE9 misses the data-type="temp" attribute, because you end up with strings in your math, due to program flow not being redirected for this special case.

So random, perfectly valid commands seem to be failing, for no reason. But the behavior is 100% repeatable. In this current state of things, I am getting no relevant errors in the JS console in IE9. It's like something in my code is causing IE9 to go haywire but I have no idea what it is.

The web page in question is here: http://www.whatsmyip.org/lib/unit-converter/

The javascript file for that page is here: http://www.whatsmyip.org/js/tools/lib/unit-converter.js

Each converter on the page is it's own FORM tag, the "Temperature" form is the one with the data-type attribute that seems to be unreadable for IE9. After it fails to read that, it seems that THEN it also starts being unable to read $form.find(".output_units").val(); though it can read this fine before.

As much as I hate all IE, I'm not ready to abandon IE9 yet. I have lots of scripts on almost every page on my site, but this is the only issue I'm having. All other pages work great. I do lots of beta testing in virtual machines.


Solution

  • P tags cannot contain block level items. My original HTML contains lots of FORMs like this:

    <p>
    <form>
          blahblah
          <div>Divider</div>
          dfasdfasdf
    </form>
    

    Even though FORM is a block tag, this code is valid because P's are self closing tags, so the FORM closes the P. However in IE9 specifically, this setup causes the FORM tag to go into what I will call "function-like-shit-mode", where any block item inside the FORM will close the FORM, and then the P.

    This bug, in my specific code, was causing half of my form elements to be rendered outside of the FORM. This was only clear when I started messing around with CSS of all things. Threw a border around my forms and look at that, only half of the form's elements are inside the border!

    The result of all of this, is that my Javascript couldn't find all of the values it needed, because I find SELECTs by searching for specific classes inside of FORMs. Now the extra odd thing is that it would properly process most of the forms onLoad, but after that fail. As if the FORMs were rendering correctly for a second, then "snapping" back to the buggy version, excluding half of the items.

    So in conclusion, I deleted the P tag in front of each of my FORM tags, and now IE9 is functionally totally normally. My FORMs can now contains DIVs without any issues.