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

Closed
gibson042 opened this Issue Jul 11, 2016 · 0 comments

Projects

None yet

1 participant

@gibson042
Member

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;
@gibson042 gibson042 added a commit to gibson042/sizzle that referenced this issue Jul 30, 2016
@gibson042 gibson042 Selector: Properly implement :enabled/:disabled for select contents
SemVer patch
Fixes gh-382
Ref jquery/jquery#3224
Ref 7999a01
5ff208b
@gibson042 gibson042 closed this in 4f19ae6 Aug 8, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment