Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/dom/html/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 10 kB image not shown  

Quellcode-Bibliothek HTMLFieldSetElement.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "mozilla/BasicEvents.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/Maybe.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/dom/CustomElementRegistry.h"
#include "mozilla/dom/HTMLFieldSetElement.h"
#include "mozilla/dom/HTMLFieldSetElementBinding.h"
#include "nsContentList.h"
#include "nsQueryObject.h"

NS_IMPL_NS_NEW_HTML_ELEMENT(FieldSet)

namespace mozilla::dom {

HTMLFieldSetElement::HTMLFieldSetElement(
    already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
    : nsGenericHTMLFormControlElement(std::move(aNodeInfo),
                                      FormControlType::Fieldset),
      mElements(nullptr),
      mFirstLegend(nullptr),
      mInvalidElementsCount(0) {
  // <fieldset> is always barred from constraint validation.
  SetBarredFromConstraintValidation(true);

  // We start out enabled and valid.
  AddStatesSilently(ElementState::ENABLED | ElementState::VALID);
}

HTMLFieldSetElement::~HTMLFieldSetElement() {
  uint32_t length = mDependentElements.Length();
  for (uint32_t i = 0; i < length; ++i) {
    mDependentElements[i]->ForgetFieldSet(this);
  }
}

NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLFieldSetElement,
                                   nsGenericHTMLFormControlElement, mValidity,
                                   mElements)

NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLFieldSetElement,
                                             nsGenericHTMLFormControlElement,
                                             nsIConstraintValidation)

NS_IMPL_ELEMENT_CLONE(HTMLFieldSetElement)

bool HTMLFieldSetElement::IsDisabledForEvents(WidgetEvent* aEvent) {
  if (StaticPrefs::dom_forms_fieldset_disable_only_descendants_enabled()) {
    return false;
  }
  return IsElementDisabledForEvents(aEvent, nullptr);
}

// nsIContent
void HTMLFieldSetElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
  // Do not process any DOM events if the element is disabled.
  aVisitor.mCanHandle = false;
  if (IsDisabledForEvents(aVisitor.mEvent)) {
    return;
  }

  nsGenericHTMLFormControlElement::GetEventTargetParent(aVisitor);
}

void HTMLFieldSetElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                       const nsAttrValue* aValue,
                                       const nsAttrValue* aOldValue,
                                       nsIPrincipal* aSubjectPrincipal,
                                       bool aNotify) {
  if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled) {
    // This *has* to be called *before* calling FieldSetDisabledChanged on our
    // controls, as they may depend on our disabled state.
    UpdateDisabledState(aNotify);
  }

  return nsGenericHTMLFormControlElement::AfterSetAttr(
      aNameSpaceID, aName, aValue, aOldValue, aSubjectPrincipal, aNotify);
}

void HTMLFieldSetElement::GetType(nsAString& aType) const {
  aType.AssignLiteral("fieldset");
}

/* static */
bool HTMLFieldSetElement::MatchListedElements(Element* aElement,
                                              int32_t aNamespaceID,
                                              nsAtom* aAtom, void* aData) {
  return nsIFormControl::FromNodeOrNull(aElement) != nullptr;
}

nsIHTMLCollection* HTMLFieldSetElement::Elements() {
  if (!mElements) {
    mElements =
        new nsContentList(this, MatchListedElements, nullptr, nullptr, true);
  }

  return mElements;
}

// nsIFormControl

nsresult HTMLFieldSetElement::Reset() { return NS_OK; }

void HTMLFieldSetElement::InsertChildBefore(nsIContent* aChild,
                                            nsIContent* aBeforeThis,
                                            bool aNotify, ErrorResult& aRv) {
  bool firstLegendHasChanged = false;

  if (aChild->IsHTMLElement(nsGkAtoms::legend)) {
    if (!mFirstLegend) {
      mFirstLegend = aChild;
      // We do not want to notify the first time mFirstElement is set.
    } else {
      // If mFirstLegend is before aIndex, we do not change it.
      // Otherwise, mFirstLegend is now aChild.
      const Maybe<uint32_t> indexOfRef =
          aBeforeThis ? ComputeIndexOf(aBeforeThis) : Some(GetChildCount());
      const Maybe<uint32_t> indexOfFirstLegend = ComputeIndexOf(mFirstLegend);
      if ((indexOfRef.isSome() && indexOfFirstLegend.isSome() &&
           *indexOfRef <= *indexOfFirstLegend) ||
          // XXX Keep the odd traditional behavior for now.
          indexOfRef.isNothing()) {
        mFirstLegend = aChild;
        firstLegendHasChanged = true;
      }
    }
  }

  nsGenericHTMLFormControlElement::InsertChildBefore(aChild, aBeforeThis,
                                                     aNotify, aRv);
  if (aRv.Failed()) {
    return;
  }

  if (firstLegendHasChanged) {
    NotifyElementsForFirstLegendChange(aNotify);
  }
}

void HTMLFieldSetElement::RemoveChildNode(nsIContent* aKid, bool aNotify,
                                          const BatchRemovalState* aState) {
  bool firstLegendHasChanged = false;

  if (mFirstLegend && aKid == mFirstLegend) {
    // If we are removing the first legend we have to found another one.
    nsIContent* child = mFirstLegend->GetNextSibling();
    mFirstLegend = nullptr;
    firstLegendHasChanged = true;

    for (; child; child = child->GetNextSibling()) {
      if (child->IsHTMLElement(nsGkAtoms::legend)) {
        mFirstLegend = child;
        break;
      }
    }
  }

  nsGenericHTMLFormControlElement::RemoveChildNode(aKid, aNotify, aState);

  if (firstLegendHasChanged) {
    NotifyElementsForFirstLegendChange(aNotify);
  }
}

void HTMLFieldSetElement::AddElement(nsGenericHTMLFormElement* aElement) {
  mDependentElements.AppendElement(aElement);

  // If the element that we are adding aElement is a fieldset, then all the
  // invalid elements in aElement are also invalid elements of this.
  HTMLFieldSetElement* fieldSet = FromNode(aElement);
  if (fieldSet) {
    for (int32_t i = 0; i < fieldSet->mInvalidElementsCount; i++) {
      UpdateValidity(false);
    }
    return;
  }

  // If the element is a form-associated custom element, adding element might be
  // caused by FACE upgrade which won't trigger mutation observer, so mark
  // mElements dirty manually here.
  CustomElementData* data = aElement->GetCustomElementData();
  if (data && data->IsFormAssociated() && mElements) {
    mElements->SetDirty();
  }

  // We need to update the validity of the fieldset.
  nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aElement);
  if (cvElmt && cvElmt->IsCandidateForConstraintValidation() &&
      !cvElmt->IsValid()) {
    UpdateValidity(false);
  }

#if DEBUG
  int32_t debugInvalidElementsCount = 0;
  for (uint32_t i = 0; i < mDependentElements.Length(); i++) {
    HTMLFieldSetElement* fieldSet = FromNode(mDependentElements[i]);
    if (fieldSet) {
      debugInvalidElementsCount += fieldSet->mInvalidElementsCount;
      continue;
    }
    nsCOMPtr<nsIConstraintValidation> cvElmt =
        do_QueryObject(mDependentElements[i]);
    if (cvElmt && cvElmt->IsCandidateForConstraintValidation() &&
        !(cvElmt->IsValid())) {
      debugInvalidElementsCount += 1;
    }
  }
  MOZ_ASSERT(debugInvalidElementsCount == mInvalidElementsCount);
#endif
}

void HTMLFieldSetElement::RemoveElement(nsGenericHTMLFormElement* aElement) {
  mDependentElements.RemoveElement(aElement);

  // If the element that we are removing aElement is a fieldset, then all the
  // invalid elements in aElement are also removed from this.
  HTMLFieldSetElement* fieldSet = FromNode(aElement);
  if (fieldSet) {
    for (int32_t i = 0; i < fieldSet->mInvalidElementsCount; i++) {
      UpdateValidity(true);
    }
    return;
  }

  // We need to update the validity of the fieldset.
  nsCOMPtr<nsIConstraintValidation> cvElmt = do_QueryObject(aElement);
  if (cvElmt && cvElmt->IsCandidateForConstraintValidation() &&
      !cvElmt->IsValid()) {
    UpdateValidity(true);
  }

#if DEBUG
  int32_t debugInvalidElementsCount = 0;
  for (uint32_t i = 0; i < mDependentElements.Length(); i++) {
    HTMLFieldSetElement* fieldSet = FromNode(mDependentElements[i]);
    if (fieldSet) {
      debugInvalidElementsCount += fieldSet->mInvalidElementsCount;
      continue;
    }
    nsCOMPtr<nsIConstraintValidation> cvElmt =
        do_QueryObject(mDependentElements[i]);
    if (cvElmt && cvElmt->IsCandidateForConstraintValidation() &&
        !(cvElmt->IsValid())) {
      debugInvalidElementsCount += 1;
    }
  }
  MOZ_ASSERT(debugInvalidElementsCount == mInvalidElementsCount);
#endif
}

void HTMLFieldSetElement::UpdateDisabledState(bool aNotify) {
  nsGenericHTMLFormControlElement::UpdateDisabledState(aNotify);

  for (nsGenericHTMLFormElement* element : mDependentElements) {
    element->FieldSetDisabledChanged(aNotify);
  }
}

void HTMLFieldSetElement::NotifyElementsForFirstLegendChange(bool aNotify) {
  /**
   * NOTE: this could be optimized if only call when the fieldset is currently
   * disabled.
   * This should also make sure that mElements is set when we happen to be here.
   * However, this method shouldn't be called very often in normal use cases.
   */

  if (!mElements) {
    mElements =
        new nsContentList(this, MatchListedElements, nullptr, nullptr, true);
  }

  uint32_t length = mElements->Length(true);
  for (uint32_t i = 0; i < length; ++i) {
    static_cast<nsGenericHTMLFormElement*>(mElements->Item(i))
        ->FieldSetFirstLegendChanged(aNotify);
  }
}

void HTMLFieldSetElement::UpdateValidity(bool aElementValidity) {
  if (aElementValidity) {
    --mInvalidElementsCount;
  } else {
    ++mInvalidElementsCount;
  }

  MOZ_ASSERT(mInvalidElementsCount >= 0);

  // The fieldset validity has just changed if:
  // - there are no more invalid elements ;
  // - or there is one invalid elmement and an element just became invalid.
  if (!mInvalidElementsCount ||
      (mInvalidElementsCount == 1 && !aElementValidity)) {
    AutoStateChangeNotifier notifier(*thistrue);
    RemoveStatesSilently(ElementState::VALID | ElementState::INVALID);
    AddStatesSilently(mInvalidElementsCount ? ElementState::INVALID
                                            : ElementState::VALID);
  }

  // We should propagate the change to the fieldset parent chain.
  if (mFieldSet) {
    mFieldSet->UpdateValidity(aElementValidity);
  }
}

JSObject* HTMLFieldSetElement::WrapNode(JSContext* aCx,
                                        JS::Handle<JSObject*> aGivenProto) {
  return HTMLFieldSetElement_Binding::Wrap(aCx, this, aGivenProto);
}

}  // namespace mozilla::dom

84%


¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.1Bemerkung:  (vorverarbeitet)  ¤

*Bot Zugriff






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.