Skip to content

:enabled and :disabled don't consider an option's containing optgroup #382

@gibson042

Description

@gibson042

Ref jquery/jquery#3224
Ref 7999a01

Include citations to:

Also note that :enabled and :disabled can only match elements from exactly the same set, which includes three that aren't listed form-associated elements and don't have form IDL attributes: <optgroup>, <option>, and <menuitem>. All three have label IDL attributes (as do the non-disableable <menu> and <track>), but none of them need to consider ancestor fieldsets (although <option> does need to consider parent <optgroup>).

The bottom line is that boolean disabled is a good indicator, excepting two special cases where an element can match :disabled instead of :enabled despite having .disabled === false:

  • <option> (the only element having both label and form IDL attributes) with a disabled parent <optgroup> (which also has label)
  • an element with both form IDL attribute and a disabled fieldset ancestor whose legend is not also an ancestor

It is interesting to observe that special processing is required if and only if disabled is false and form exists. I think the resulting logic will look like

// Only certain elements can match :enabled or :disabled
// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled

// Check for inherited disabledness on relevant non-disabled elements:
// * listed form-associated elements
//   https://html.spec.whatwg.org/multipage/forms.html#category-listed
// * option elements
//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
return "form" in elem && elem.disabled === false ?

    // Support: IE 6 - 11
    // Use the shortcut property, which already covers inheritance
    elem.isDisabled === disabled ||
    elem.isDisabled !== !disabled && ("label" in elem ?

        // Option elements defer to a parent optgroup if present
        (elem.parentNode && "label" in elem.parentNode ?
            elem.parentNode.disabled === disabled :
            elem.disabled === disabled) :

        // All others defer to ancestor fieldsets if present
        disabledAncestor( elem ) === disabled
    ) :

    // Check other disableable elements for direct disabledness
    // Some victims get caught in our net (label, legend, menu, track),
    // but they shouldn't have the property anyway.
    "form" in elem && elem.disabled === disabled ||
    "label" in elem && elem.disabled === disabled;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions