Search code examples
javascriptjquerydomattributes

Inconsistency in jQuery's attribute manipulation


$('<option selected="selected">something</option>')
.removeAttr('selected')
.wrap('<p></p>').parent().html();

results in

<option>something</option>

which is expected. But if I put back the 'selected' attribute after removing it (or to an <option> tag without 'selected' attribute), I get the same output.

$('<option selected="selected">something</option>')
.removeAttr('selected')
.attr('selected', 'selected')
.wrap('<p></p>').parent().html();

Why is this happening?


Solution

  • There are two selecteds, the selected attribute and the selected property.

    The HTML selected="selected" attribute sets the initial state of the JavaScript selected boolean property, but after that, like all form field state, they are independent.

    If you select the option by clicking on it in the select box, it doesn't add an HTML selected="selected" attribute to the HTMLOptionElement DOM node, so you won't see that reflected in the innerHTML/html() of the element. Instead it just sets the underlying form contents as reflected by the option.selected property.

    IE before version 8 doesn't even allow you to set the HTML selected attribute, because setAttribute is broken there. If you try, it'll actually set the selected boolean property.

    attr() in jQuery is a kind of hybrid of attribute and property access which tries to sweep these problems under the rug. But the upshot is calling attr('selected') is effectively the same as using the boolean selected property.