Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

InnerHTML/outerHTML in IE doesn't reflect checkbox state except in quirks mode

I am currently battling an IE JavaScript/DOM bug (what fun) and it has truly stumped me. The code in question copies some checkboxes into a form and needs to maintain their checked state. Problem is, IE (specifically IE8, though I'm guessing others as well) doesn't want to do that.

I've narrowed down the bug itself to a very small test case. Basically, things work correctly without a DOCTYPE on the page but they are broken when a DOCTYPE is present. I would have expected the opposite, but who knows with IE.


Following are the simplest possible test cases. For each of them: open the page in IE, toggle the checkbox, then click "TEST".

Does not produce the bug:

<input type="checkbox" id="broken">
<button id="break">TEST</button>
<script>
 document.getElementById('break').onclick = function() {
  alert(document.getElementById('broken').outerHTML);
 };
</script>

Link

Produces the bug:

<!DOCTYPE html>
<input type="checkbox" id="broken">
<button id="break">TEST</button>
<script>
 document.getElementById('break').onclick = function() {
  alert(document.getElementById('broken').outerHTML);
 };
</script>

Link

The bug occurs on valid pages (with <html>, <head>, <body>, etc) and whether or not the input is inside a form. In the "broken" case, outerHTML always reflects what was present on page load (if I have the input checked by default then it always alerts code with CHECKED, even if I uncheck it first). Things happen the same way if I wrap the input and use innerHTML. On the actual site I am using jQuery's .clone() method to do the copying; .clone() uses .outerHTML internally and that's how I narrowed this down.


My question is this: is there a way around this short of manually building new HTML myself? And does anyone have any idea WHY this happens in the first place (other than "IE SUX LOLZ")?

like image 661
Matt Kantor Avatar asked Jun 22 '10 21:06

Matt Kantor


2 Answers

There are problems in general with innerHTML and form properties. Not just in IE ((its worse in FF, it will NEVER update the checked property in innerHTML))...

You can try this to work around the issue in the linked question:

document.getElementById('break').onclick = function() {
  var broken = document.getElementById('broken');
  if (broken.checked) broken.setAttribute('checked','checked');
  else broken.removeAttribute('checked');
  alert(broken.outerHTML);
};
like image 198
gnarf Avatar answered Nov 14 '22 23:11

gnarf


I ended up writing a wrapper for .clone() based off gnarf's answer:

$.fn.inputClone = function(events) {
    this.each(function() {
        this.attr('value', this.value);

        if(this.checked) this.setAttribute('checked', 'checked');
        else this.removeAttribute('checked');

        if(this.selected) this.setAttribute('selected', 'selected');
        else this.removeAttribute('selected');
    });
    return this.clone(events);
};

It's not very general-purpose (e.g. it won't work if you try to clone elements containing inputs), but for this case it seems to do the trick.

like image 33
Matt Kantor Avatar answered Nov 14 '22 22:11

Matt Kantor