mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 598833 part 12. Add dom::Element::UpdateState and use it in various places where elements update their own state. r=smaug,sdwilsh,mounir
This commit is contained in:
parent
9e1fe05fd3
commit
0cc4f9cbde
@ -85,11 +85,16 @@ enum {
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class Link;
|
||||
|
||||
class Element : public nsIContent
|
||||
{
|
||||
public:
|
||||
#ifdef MOZILLA_INTERNAL_API
|
||||
Element(already_AddRefed<nsINodeInfo> aNodeInfo) : nsIContent(aNodeInfo) {}
|
||||
Element(already_AddRefed<nsINodeInfo> aNodeInfo) :
|
||||
nsIContent(aNodeInfo),
|
||||
mState(NS_EVENT_STATE_MOZ_READONLY)
|
||||
{}
|
||||
#endif // MOZILLA_INTERNAL_API
|
||||
|
||||
/**
|
||||
@ -97,7 +102,9 @@ public:
|
||||
* the possible bits that could be set here.
|
||||
*/
|
||||
nsEventStates State() const {
|
||||
return IntrinsicState() | mState;
|
||||
// mState is maintained by having whoever might have changed it
|
||||
// call UpdateState() or one of the other mState mutators.
|
||||
return mState;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,6 +118,18 @@ public:
|
||||
*/
|
||||
virtual void RequestLinkStateUpdate();
|
||||
|
||||
/**
|
||||
* Ask this element to update its state. If aNotify is false, then
|
||||
* state change notifications will not be dispatched; in that
|
||||
* situation it is the caller's responsibility to dispatch them.
|
||||
*
|
||||
* In general, aNotify should only be false if we're guaranteed that
|
||||
* the element can't have a frame no matter what its style is
|
||||
* (e.g. if we're in the middle of adding it to the document or
|
||||
* removing it from the document).
|
||||
*/
|
||||
void UpdateState(bool aNotify);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Method to get the _intrinsic_ content state of this element. This is the
|
||||
@ -125,6 +144,26 @@ protected:
|
||||
*/
|
||||
void UpdateLinkState(nsEventStates aState);
|
||||
|
||||
/**
|
||||
* Method to add state bits. This should be called from subclass
|
||||
* constructors to set up our event state correctly at construction
|
||||
* time and other places where we don't want to notify a state
|
||||
* change.
|
||||
*/
|
||||
void AddStatesSilently(nsEventStates aStates) {
|
||||
mState |= aStates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to remove state bits. This should be called from subclass
|
||||
* constructors to set up our event state correctly at construction
|
||||
* time and other places where we don't want to notify a state
|
||||
* change.
|
||||
*/
|
||||
void RemoveStatesSilently(nsEventStates aStates) {
|
||||
mState &= ~aStates;
|
||||
}
|
||||
|
||||
private:
|
||||
// Need to allow the ESM, nsGlobalWindow, and the focus manager to
|
||||
// set our state
|
||||
@ -132,6 +171,9 @@ private:
|
||||
friend class ::nsGlobalWindow;
|
||||
friend class ::nsFocusManager;
|
||||
|
||||
// Also need to allow Link to call UpdateLinkState.
|
||||
friend class Link;
|
||||
|
||||
void NotifyStateChange(nsEventStates aStates);
|
||||
|
||||
// Methods for the ESM to manage state bits. These will handle
|
||||
@ -140,13 +182,13 @@ private:
|
||||
void AddStates(nsEventStates aStates) {
|
||||
NS_PRECONDITION(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
|
||||
"Should only be adding ESM-managed states here");
|
||||
mState |= aStates;
|
||||
AddStatesSilently(aStates);
|
||||
NotifyStateChange(aStates);
|
||||
}
|
||||
void RemoveStates(nsEventStates aStates) {
|
||||
NS_PRECONDITION(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
|
||||
"Should only be removing ESM-managed states here");
|
||||
mState &= ~aStates;
|
||||
RemoveStatesSilently(aStates);
|
||||
NotifyStateChange(aStates);
|
||||
}
|
||||
|
||||
|
@ -76,8 +76,8 @@ enum nsLinkState {
|
||||
|
||||
// IID for the nsIContent interface
|
||||
#define NS_ICONTENT_IID \
|
||||
{ 0xba1c9e22, 0x4b73, 0x42ae, \
|
||||
{ 0xb6, 0x45, 0xa7, 0x83, 0xd0, 0x7e, 0xee, 0x2c } }
|
||||
{ 0x860ee35b, 0xe505, 0x438f, \
|
||||
{ 0xa7, 0x7b, 0x65, 0xb9, 0xf5, 0x0b, 0xe5, 0x29 } }
|
||||
|
||||
/**
|
||||
* A node of content in a document's content model. This interface
|
||||
@ -856,9 +856,10 @@ public:
|
||||
/**
|
||||
* Should be called when the node can become editable or when it can stop
|
||||
* being editable (for example when its contentEditable attribute changes,
|
||||
* when it is moved into an editable parent, ...).
|
||||
* when it is moved into an editable parent, ...). If aNotify is true and
|
||||
* the node is an element, this will notify the state change.
|
||||
*/
|
||||
virtual void UpdateEditableState();
|
||||
virtual void UpdateEditableState(PRBool aNotify);
|
||||
|
||||
/**
|
||||
* Destroy this node and its children. Ideally this shouldn't be needed
|
||||
|
@ -85,25 +85,18 @@ Link::SetLinkState(nsLinkState aState)
|
||||
NS_ASSERTION(mLinkState != aState,
|
||||
"Setting state to the currently set state!");
|
||||
|
||||
// Remember our old link state for when we notify.
|
||||
nsEventStates oldLinkState = LinkState();
|
||||
|
||||
// Set our current state as appropriate.
|
||||
mLinkState = aState;
|
||||
|
||||
// Per IHistory interface documentation, we are no longer registered.
|
||||
mRegistered = false;
|
||||
|
||||
// Notify the document that our visited state has changed.
|
||||
Element *element = mElement;
|
||||
nsIDocument *doc = element->GetCurrentDoc();
|
||||
NS_ASSERTION(doc, "Registered but we have no document?!");
|
||||
nsEventStates newLinkState = LinkState();
|
||||
NS_ASSERTION(newLinkState == NS_EVENT_STATE_VISITED ||
|
||||
newLinkState == NS_EVENT_STATE_UNVISITED,
|
||||
"Unexpected state obtained from LinkState()!");
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(element, oldLinkState ^ newLinkState);
|
||||
NS_ABORT_IF_FALSE(LinkState() == NS_EVENT_STATE_VISITED ||
|
||||
LinkState() == NS_EVENT_STATE_UNVISITED,
|
||||
"Unexpected state obtained from LinkState()!");
|
||||
|
||||
// Tell the element to update its visited state
|
||||
mElement->UpdateState(true);
|
||||
}
|
||||
|
||||
nsEventStates
|
||||
@ -484,15 +477,16 @@ Link::ResetLinkState(bool aNotify)
|
||||
// Get rid of our cached URI.
|
||||
mCachedURI = nsnull;
|
||||
|
||||
// If aNotify is true, notify both of the visited-related states. We have
|
||||
// to do that, because we might be racing with a response from history and
|
||||
// hence need to make sure that we get restyled whether we were visited or
|
||||
// not before. In particular, we need to make sure that our LinkState() is
|
||||
// called so that we'll start a new history query as needed.
|
||||
if (aNotify && doc) {
|
||||
nsEventStates changedState = NS_EVENT_STATE_VISITED ^ NS_EVENT_STATE_UNVISITED;
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(element, changedState);
|
||||
// We have to be very careful here: if aNotify is false we do NOT
|
||||
// want to call UpdateState, because that will call into LinkState()
|
||||
// and try to start off loads, etc. But ResetLinkState is called
|
||||
// with aNotify false when things are in inconsistent states, so
|
||||
// we'll get confused in that situation. Instead, just silently
|
||||
// update the link state on mElement.
|
||||
if (aNotify) {
|
||||
mElement->UpdateState(aNotify);
|
||||
} else {
|
||||
mElement->UpdateLinkState(nsEventStates());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,9 @@ public:
|
||||
nsGenConImageContent(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsXMLElement(aNodeInfo)
|
||||
{
|
||||
// nsImageLoadingContent starts out broken, so we start out
|
||||
// suppressed to match it.
|
||||
AddStatesSilently(NS_EVENT_STATE_SUPPRESSED);
|
||||
}
|
||||
|
||||
nsresult Init(imgIRequest* aImageRequest)
|
||||
|
@ -535,7 +535,7 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
|
||||
nsNodeUtils::ParentChainChanged(this);
|
||||
|
||||
UpdateEditableState();
|
||||
UpdateEditableState(PR_FALSE);
|
||||
|
||||
NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
|
||||
NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
|
||||
|
@ -819,13 +819,59 @@ Element::UpdateLinkState(nsEventStates aState)
|
||||
}
|
||||
|
||||
void
|
||||
nsIContent::UpdateEditableState()
|
||||
Element::UpdateState(bool aNotify)
|
||||
{
|
||||
nsEventStates oldState = mState;
|
||||
mState = IntrinsicState() | (oldState & ESM_MANAGED_STATES);
|
||||
if (aNotify) {
|
||||
nsEventStates changedStates = oldState ^ mState;
|
||||
if (!changedStates.IsEmpty()) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, changedStates);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsIContent::UpdateEditableState(PRBool aNotify)
|
||||
{
|
||||
// Guaranteed to be non-element content
|
||||
NS_ASSERTION(!IsElement(), "What happened here?");
|
||||
nsIContent *parent = GetParent();
|
||||
|
||||
SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericElement::UpdateEditableState(PRBool aNotify)
|
||||
{
|
||||
nsIContent *parent = GetParent();
|
||||
|
||||
PRBool oldEditable = IsEditable();
|
||||
SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
|
||||
PRBool newEditable = IsEditable();
|
||||
if (oldEditable != newEditable) {
|
||||
if (aNotify) {
|
||||
UpdateState(aNotify);
|
||||
} else {
|
||||
// Avoid calling UpdateState in this very common case, because
|
||||
// this gets called for pretty much every single element on
|
||||
// insertion into the document and UpdateState can be slow for
|
||||
// some kinds of elements even when not notifying.
|
||||
if (oldEditable) {
|
||||
RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
|
||||
AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
|
||||
} else {
|
||||
RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
|
||||
AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsIContent::FindFirstNonNativeAnonymous() const
|
||||
{
|
||||
@ -3034,7 +3080,7 @@ nsGenericElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
}
|
||||
}
|
||||
|
||||
UpdateEditableState();
|
||||
UpdateEditableState(PR_FALSE);
|
||||
|
||||
// Now recurse into our kids
|
||||
for (nsIContent* child = GetFirstChild(); child;
|
||||
@ -4668,13 +4714,6 @@ nsGenericElement::SetAttrAndNotify(PRInt32 aNamespaceID,
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
|
||||
|
||||
// When notifying, make sure to keep track of states whose value
|
||||
// depends solely on the value of an attribute.
|
||||
nsEventStates stateMask;
|
||||
if (aNotify) {
|
||||
stateMask = IntrinsicState();
|
||||
}
|
||||
|
||||
nsMutationGuard::DidMutate();
|
||||
|
||||
if (aNamespaceID == kNameSpaceID_None) {
|
||||
@ -4706,11 +4745,9 @@ nsGenericElement::SetAttrAndNotify(PRInt32 aNamespaceID,
|
||||
}
|
||||
}
|
||||
|
||||
UpdateState(aNotify);
|
||||
|
||||
if (aNotify) {
|
||||
stateMask ^= IntrinsicState();
|
||||
if (document && !stateMask.IsEmpty()) {
|
||||
document->ContentStateChanged(this, stateMask);
|
||||
}
|
||||
nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType);
|
||||
}
|
||||
|
||||
@ -4904,13 +4941,6 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
nsIDOMMutationEvent::REMOVAL);
|
||||
}
|
||||
|
||||
// When notifying, make sure to keep track of states whose value
|
||||
// depends solely on the value of an attribute.
|
||||
nsEventStates stateMask;
|
||||
if (aNotify) {
|
||||
stateMask = IntrinsicState();
|
||||
}
|
||||
|
||||
PRBool hasMutationListeners = aNotify &&
|
||||
nsContentUtils::HasMutationListeners(this,
|
||||
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
||||
@ -4950,11 +4980,9 @@ nsGenericElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
}
|
||||
}
|
||||
|
||||
UpdateState(aNotify);
|
||||
|
||||
if (aNotify) {
|
||||
stateMask ^= IntrinsicState();
|
||||
if (document && !stateMask.IsEmpty()) {
|
||||
document->ContentStateChanged(this, stateMask);
|
||||
}
|
||||
nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
|
||||
nsIDOMMutationEvent::REMOVAL);
|
||||
}
|
||||
@ -5085,7 +5113,7 @@ nsGenericElement::List(FILE* out, PRInt32 aIndent,
|
||||
|
||||
ListAttributes(out);
|
||||
|
||||
fprintf(out, " intrinsicstate=[%llx]", IntrinsicState().GetInternalValue());
|
||||
fprintf(out, " state=[%llx]", State().GetInternalValue());
|
||||
fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
|
||||
fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
|
||||
fprintf(out, " refcount=%d<", mRefCnt.get());
|
||||
|
@ -355,6 +355,8 @@ public:
|
||||
}
|
||||
|
||||
// nsIContent interface methods
|
||||
virtual void UpdateEditableState(PRBool aNotify);
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers);
|
||||
|
@ -794,8 +794,6 @@ nsImageLoadingContent::UpdateImageState(PRBool aNotify)
|
||||
return;
|
||||
}
|
||||
|
||||
nsEventStates oldState = ImageState();
|
||||
|
||||
mLoading = mBroken = mUserDisabled = mSuppressed = PR_FALSE;
|
||||
|
||||
// If we were blocked by server-based content policy, we claim to be
|
||||
@ -818,17 +816,8 @@ nsImageLoadingContent::UpdateImageState(PRBool aNotify)
|
||||
}
|
||||
}
|
||||
|
||||
if (aNotify) {
|
||||
nsIDocument* doc = thisContent->GetCurrentDoc();
|
||||
if (doc) {
|
||||
NS_ASSERTION(thisContent->IsInDoc(), "Something is confused");
|
||||
nsEventStates changedBits = oldState ^ ImageState();
|
||||
if (!changedBits.IsEmpty()) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(thisContent, changedBits);
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(thisContent->IsElement(), "Not an element?");
|
||||
thisContent->AsElement()->UpdateState(aNotify);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -337,9 +337,7 @@ class AutoNotifier {
|
||||
mOldState = aContent->ObjectState();
|
||||
}
|
||||
~AutoNotifier() {
|
||||
if (mNotify) {
|
||||
mContent->NotifyStateChanged(mOldType, mOldState, PR_FALSE);
|
||||
}
|
||||
mContent->NotifyStateChanged(mOldType, mOldState, PR_FALSE, mNotify);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -350,7 +348,7 @@ class AutoNotifier {
|
||||
void Notify() {
|
||||
NS_ASSERTION(mNotify, "Should not notify when notify=false");
|
||||
|
||||
mContent->NotifyStateChanged(mOldType, mOldState, PR_TRUE);
|
||||
mContent->NotifyStateChanged(mOldType, mOldState, PR_TRUE, PR_TRUE);
|
||||
mOldType = mContent->Type();
|
||||
mOldState = mContent->ObjectState();
|
||||
}
|
||||
@ -1639,7 +1637,9 @@ nsObjectLoadingContent::UnloadContent()
|
||||
|
||||
void
|
||||
nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
|
||||
nsEventStates aOldState, PRBool aSync)
|
||||
nsEventStates aOldState,
|
||||
PRBool aSync,
|
||||
PRBool aNotify)
|
||||
{
|
||||
LOG(("OBJLC [%p]: Notifying about state change: (%u, %llx) -> (%u, %llx) (sync=%i)\n",
|
||||
this, aOldType, aOldState.GetInternalValue(), mType,
|
||||
@ -1649,6 +1649,18 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
NS_ASSERTION(thisContent, "must be a content");
|
||||
|
||||
NS_ASSERTION(thisContent->IsElement(), "Not an element?");
|
||||
|
||||
// Unfortunately, we do some state changes without notifying
|
||||
// (e.g. in Fallback when canceling image requests), so we have to
|
||||
// manually notify object state changes.
|
||||
thisContent->AsElement()->UpdateState(false);
|
||||
|
||||
if (!aNotify) {
|
||||
// We're done here
|
||||
return;
|
||||
}
|
||||
|
||||
nsIDocument* doc = thisContent->GetCurrentDoc();
|
||||
if (!doc) {
|
||||
return; // Nothing to do
|
||||
@ -1666,8 +1678,7 @@ nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
|
||||
doc->ContentStateChanged(thisContent, changedBits);
|
||||
}
|
||||
if (aSync) {
|
||||
// Make sure that frames are actually constructed, and do it after
|
||||
// EndUpdate was called.
|
||||
// Make sure that frames are actually constructed immediately.
|
||||
doc->FlushPendingNotifications(Flush_Frames);
|
||||
}
|
||||
} else if (aOldType != mType) {
|
||||
|
@ -256,9 +256,10 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
*
|
||||
* @param aSync If a synchronous frame construction is required. If false,
|
||||
* the construction may either be sync or async.
|
||||
* @param aNotify if false, only need to update the state of our element.
|
||||
*/
|
||||
void NotifyStateChanged(ObjectType aOldType, nsEventStates aOldState,
|
||||
PRBool aSync);
|
||||
PRBool aSync, PRBool aNotify);
|
||||
|
||||
/**
|
||||
* Fires the "Plugin not found" event. This function doesn't do any checks
|
||||
|
@ -939,17 +939,16 @@ nsGenericHTMLElement::InNavQuirksMode(nsIDocument* aDoc)
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLElement::UpdateEditableState()
|
||||
nsGenericHTMLElement::UpdateEditableState(PRBool aNotify)
|
||||
{
|
||||
// XXX Should we do this only when in a document?
|
||||
ContentEditableTristate value = GetContentEditableValue();
|
||||
if (value != eInherit) {
|
||||
SetEditableFlag(!!value);
|
||||
|
||||
DoSetEditableFlag(!!value, aNotify);
|
||||
return;
|
||||
}
|
||||
|
||||
nsStyledElement::UpdateEditableState();
|
||||
nsStyledElement::UpdateEditableState(aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -1713,27 +1712,26 @@ nsGenericHTMLElement::MapCommonAttributesInto(const nsMappedAttributes* aAttribu
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLFormElement::UpdateEditableFormControlState()
|
||||
nsGenericHTMLFormElement::UpdateEditableFormControlState(PRBool aNotify)
|
||||
{
|
||||
// nsCSSFrameConstructor::MaybeConstructLazily is based on the logic of this
|
||||
// function, so should be kept in sync with that.
|
||||
|
||||
ContentEditableTristate value = GetContentEditableValue();
|
||||
if (value != eInherit) {
|
||||
SetEditableFlag(!!value);
|
||||
|
||||
DoSetEditableFlag(!!value, aNotify);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIContent *parent = GetParent();
|
||||
|
||||
if (parent && parent->HasFlag(NODE_IS_EDITABLE)) {
|
||||
SetEditableFlag(PR_TRUE);
|
||||
DoSetEditableFlag(PR_TRUE, aNotify);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsTextControl(PR_FALSE)) {
|
||||
SetEditableFlag(PR_FALSE);
|
||||
DoSetEditableFlag(PR_FALSE, aNotify);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1741,7 +1739,7 @@ nsGenericHTMLFormElement::UpdateEditableFormControlState()
|
||||
PRBool roState;
|
||||
GetBoolAttr(nsGkAtoms::readonly, &roState);
|
||||
|
||||
SetEditableFlag(!roState);
|
||||
DoSetEditableFlag(!roState, aNotify);
|
||||
}
|
||||
|
||||
|
||||
@ -2410,6 +2408,9 @@ nsGenericHTMLFormElement::nsGenericHTMLFormElement(already_AddRefed<nsINodeInfo>
|
||||
, mForm(nsnull)
|
||||
, mFieldSet(nsnull)
|
||||
{
|
||||
// We should add the NS_EVENT_STATE_ENABLED bit here as needed, but
|
||||
// that depends on our type, which is not initialized yet. So we
|
||||
// have to do this in subclasses.
|
||||
}
|
||||
|
||||
nsGenericHTMLFormElement::~nsGenericHTMLFormElement()
|
||||
@ -2564,7 +2565,7 @@ nsGenericHTMLFormElement::BindToTree(nsIDocument* aDocument,
|
||||
}
|
||||
|
||||
// Set parent fieldset which should be used for the disabled state.
|
||||
UpdateFieldSet();
|
||||
UpdateFieldSet(PR_FALSE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2589,6 +2590,11 @@ nsGenericHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
UnsetFlags(MAYBE_ORPHAN_FORM_ELEMENT);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mForm) {
|
||||
// Our novalidate state might have changed
|
||||
UpdateState(false);
|
||||
}
|
||||
}
|
||||
|
||||
// We have to remove the form id observer if there was one.
|
||||
@ -2601,7 +2607,7 @@ nsGenericHTMLFormElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
|
||||
|
||||
// The element might not have a fieldset anymore.
|
||||
UpdateFieldSet();
|
||||
UpdateFieldSet(PR_FALSE);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -2622,8 +2628,6 @@ nsGenericHTMLFormElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
}
|
||||
|
||||
if (mForm && aName == nsGkAtoms::type) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp);
|
||||
|
||||
if (!tmp.IsEmpty()) {
|
||||
@ -2642,10 +2646,8 @@ nsGenericHTMLFormElement::BeforeSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
// control anymore. Go ahead and notify on that change, though we might
|
||||
// end up readding and becoming the default control again in
|
||||
// AfterSetAttr.
|
||||
if (doc && aNotify) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_DEFAULT);
|
||||
}
|
||||
// FIXME: Bug 656197
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
if (aName == nsGkAtoms::form) {
|
||||
@ -2679,7 +2681,6 @@ nsGenericHTMLFormElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
}
|
||||
|
||||
if (mForm && aName == nsGkAtoms::type) {
|
||||
nsIDocument* doc = GetDocument();
|
||||
nsAutoString tmp;
|
||||
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp);
|
||||
@ -2700,9 +2701,7 @@ nsGenericHTMLFormElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
// Go ahead and notify on that change.
|
||||
// Note: no need to notify on CanBeDisabled(), since type attr
|
||||
// changes can't affect that.
|
||||
if (doc && aNotify) {
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_DEFAULT);
|
||||
}
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
if (aName == nsGkAtoms::form) {
|
||||
@ -2913,19 +2912,13 @@ nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
|
||||
NS_PRECONDITION(!aBindToTree || !aFormIdElement,
|
||||
"aFormIdElement shouldn't be set if aBindToTree is true!");
|
||||
|
||||
PRBool needStateUpdate = PR_FALSE;
|
||||
if (!aBindToTree) {
|
||||
PRBool wasDefaultSubmit = mForm && mForm->IsDefaultSubmitElement(this);
|
||||
needStateUpdate = mForm && mForm->IsDefaultSubmitElement(this);
|
||||
ClearForm(PR_TRUE);
|
||||
if (wasDefaultSubmit) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool hadForm = mForm;
|
||||
nsHTMLFormElement *oldForm = mForm;
|
||||
|
||||
if (!mForm) {
|
||||
// If @form is set, we have to use that to find the form.
|
||||
@ -2972,7 +2965,7 @@ nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
|
||||
SetFlags(ADDED_TO_FORM);
|
||||
|
||||
// Notify only if we just found this mForm.
|
||||
mForm->AddElement(this, true, !hadForm);
|
||||
mForm->AddElement(this, true, oldForm == nsnull);
|
||||
|
||||
if (!nameVal.IsEmpty()) {
|
||||
mForm->AddElementToTable(this, nameVal);
|
||||
@ -2982,10 +2975,14 @@ nsGenericHTMLFormElement::UpdateFormOwner(bool aBindToTree,
|
||||
mForm->AddElementToTable(this, idVal);
|
||||
}
|
||||
}
|
||||
|
||||
if (mForm != oldForm || needStateUpdate) {
|
||||
UpdateState(true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLFormElement::UpdateFieldSet()
|
||||
nsGenericHTMLFormElement::UpdateFieldSet(PRBool aNotify)
|
||||
{
|
||||
nsIContent* parent = nsnull;
|
||||
nsIContent* prev = nsnull;
|
||||
@ -2997,11 +2994,19 @@ nsGenericHTMLFormElement::UpdateFieldSet()
|
||||
static_cast<nsHTMLFieldSetElement*>(parent);
|
||||
|
||||
if (!prev || fieldset->GetFirstLegend() != prev) {
|
||||
if (mFieldSet == fieldset) {
|
||||
// We already have the right fieldset;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mFieldSet) {
|
||||
static_cast<nsHTMLFieldSetElement*>(mFieldSet)->RemoveElement(this);
|
||||
}
|
||||
mFieldSet = fieldset;
|
||||
fieldset->AddElement(this);
|
||||
|
||||
// The disabled state may have changed
|
||||
FieldSetDisabledChanged(aNotify);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -3010,24 +3015,16 @@ nsGenericHTMLFormElement::UpdateFieldSet()
|
||||
// No fieldset found.
|
||||
if (mFieldSet) {
|
||||
static_cast<nsHTMLFieldSetElement*>(mFieldSet)->RemoveElement(this);
|
||||
mFieldSet = nsnull;
|
||||
// The disabled state may have changed
|
||||
FieldSetDisabledChanged(aNotify);
|
||||
}
|
||||
mFieldSet = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericHTMLFormElement::FieldSetDisabledChanged(nsEventStates aStates, PRBool aNotify)
|
||||
nsGenericHTMLFormElement::FieldSetDisabledChanged(PRBool aNotify)
|
||||
{
|
||||
if (!aNotify) {
|
||||
return;
|
||||
}
|
||||
|
||||
aStates |= NS_EVENT_STATE_DISABLED | NS_EVENT_STATE_ENABLED;
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, aStates);
|
||||
}
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@ -3556,20 +3553,13 @@ MakeContentDescendantsEditable(nsIContent *aContent, nsIDocument *aDocument)
|
||||
// that. For elements, we need to send a ContentStateChanged
|
||||
// notification.
|
||||
if (!aContent->IsElement()) {
|
||||
aContent->UpdateEditableState();
|
||||
aContent->UpdateEditableState(PR_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
Element *element = aContent->AsElement();
|
||||
nsEventStates stateBefore = element->State();
|
||||
|
||||
element->UpdateEditableState();
|
||||
|
||||
if (aDocument && stateBefore != element->State()) {
|
||||
aDocument->ContentStateChanged(element,
|
||||
NS_EVENT_STATE_MOZ_READONLY |
|
||||
NS_EVENT_STATE_MOZ_READWRITE);
|
||||
}
|
||||
element->UpdateEditableState(PR_TRUE);
|
||||
|
||||
for (nsIContent *child = aContent->GetFirstChild();
|
||||
child;
|
||||
|
@ -199,7 +199,13 @@ public:
|
||||
// HTML element methods
|
||||
void Compact() { mAttrsAndChildren.Compact(); }
|
||||
|
||||
virtual void UpdateEditableState();
|
||||
virtual void UpdateEditableState(PRBool aNotify);
|
||||
|
||||
// Helper for setting our editable flag and notifying
|
||||
void DoSetEditableFlag(PRBool aEditable, bool aNotify) {
|
||||
SetEditableFlag(aEditable);
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
@ -870,22 +876,18 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback is called by a fieldest on all it's elements whenever it's
|
||||
* disabled attribute is changed so the element knows it's disabled state
|
||||
* This callback is called by a fieldest on all its elements whenever its
|
||||
* disabled attribute is changed so the element knows its disabled state
|
||||
* might have changed.
|
||||
*
|
||||
* @param aStates States for which a change should be notified.
|
||||
* @note Classes redefining this method should not call ContentStatesChanged
|
||||
* but they should pass aStates instead.
|
||||
* @note Classes redefining this method should not do any content
|
||||
* state updates themselves but should just make sure to call into
|
||||
* nsGenericHTMLFormElement::FieldSetDisabledChanged.
|
||||
*/
|
||||
virtual void FieldSetDisabledChanged(nsEventStates aStates, PRBool aNotify);
|
||||
virtual void FieldSetDisabledChanged(PRBool aNotify);
|
||||
|
||||
void FieldSetFirstLegendChanged(PRBool aNotify) {
|
||||
UpdateFieldSet();
|
||||
|
||||
// The disabled state may have change because the element might not be in
|
||||
// the first legend anymore.
|
||||
FieldSetDisabledChanged(nsEventStates(), aNotify);
|
||||
UpdateFieldSet(aNotify);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -916,7 +918,7 @@ protected:
|
||||
virtual nsresult AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify);
|
||||
|
||||
void UpdateEditableFormControlState();
|
||||
void UpdateEditableFormControlState(PRBool aNotify);
|
||||
|
||||
/**
|
||||
* This method will update the form owner, using @form or looking to a parent.
|
||||
@ -934,7 +936,7 @@ protected:
|
||||
/**
|
||||
* This method will update mFieldset and set it to the first fieldset parent.
|
||||
*/
|
||||
void UpdateFieldSet();
|
||||
void UpdateFieldSet(PRBool aNotify);
|
||||
|
||||
/**
|
||||
* Add a form id observer which will observe when the element with the id in
|
||||
|
@ -134,6 +134,12 @@ public:
|
||||
virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
|
||||
virtual nsresult PostHandleEvent(nsEventChainPostVisitor& aVisitor);
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers);
|
||||
virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
|
||||
PRBool aNullParent = PR_TRUE);
|
||||
|
||||
virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
|
||||
virtual void DoneCreatingElement();
|
||||
virtual nsXPCClassInfo* GetClassInfo();
|
||||
@ -167,6 +173,9 @@ nsHTMLButtonElement::nsHTMLButtonElement(already_AddRefed<nsINodeInfo> aNodeInfo
|
||||
{
|
||||
// <button> is always barred from constraint validation.
|
||||
SetBarredFromConstraintValidation(PR_TRUE);
|
||||
|
||||
// Set up our default state: enabled
|
||||
AddStatesSilently(NS_EVENT_STATE_ENABLED);
|
||||
}
|
||||
|
||||
nsHTMLButtonElement::~nsHTMLButtonElement()
|
||||
@ -486,6 +495,31 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLButtonElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers)
|
||||
{
|
||||
nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
|
||||
aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Update our state; we may now be the default submit element
|
||||
UpdateState(false);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLButtonElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
{
|
||||
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
|
||||
|
||||
// Update our state; we may no longer be the default submit element
|
||||
UpdateState(false);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLButtonElement::GetDefaultValue(nsAString& aDefaultValue)
|
||||
{
|
||||
@ -574,22 +608,13 @@ nsresult
|
||||
nsHTMLButtonElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify)
|
||||
{
|
||||
nsEventStates states;
|
||||
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
if (aName == nsGkAtoms::type) {
|
||||
if (!aValue) {
|
||||
mType = kButtonDefaultType->value;
|
||||
}
|
||||
|
||||
states |= NS_EVENT_STATE_MOZ_SUBMITINVALID;
|
||||
}
|
||||
|
||||
if (aNotify && !states.IsEmpty()) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
doc->ContentStateChanged(this, states);
|
||||
}
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,9 @@ nsHTMLFieldSetElement::nsHTMLFieldSetElement(already_AddRefed<nsINodeInfo> aNode
|
||||
{
|
||||
// <fieldset> is always barred from constraint validation.
|
||||
SetBarredFromConstraintValidation(PR_TRUE);
|
||||
|
||||
// We start out enabled
|
||||
AddStatesSilently(NS_EVENT_STATE_ENABLED);
|
||||
}
|
||||
|
||||
nsHTMLFieldSetElement::~nsHTMLFieldSetElement()
|
||||
@ -127,7 +130,7 @@ nsHTMLFieldSetElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
PRUint32 length = mElements->Length(PR_TRUE);
|
||||
for (PRUint32 i=0; i<length; ++i) {
|
||||
static_cast<nsGenericHTMLFormElement*>(mElements->GetNodeAt(i))
|
||||
->FieldSetDisabledChanged(nsEventStates(), aNotify);
|
||||
->FieldSetDisabledChanged(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,21 +382,14 @@ nsHTMLFormElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
if (aName == nsGkAtoms::novalidate && aNameSpaceID == kNameSpaceID_None) {
|
||||
// Update all form elements states because they might be [no longer]
|
||||
// affected by :-moz-ui-valid or :-moz-ui-invalid.
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
for (PRUint32 i = 0, length = mControls->mElements.Length();
|
||||
i < length; ++i) {
|
||||
doc->ContentStateChanged(mControls->mElements[i],
|
||||
NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID);
|
||||
}
|
||||
for (PRUint32 i = 0, length = mControls->mElements.Length();
|
||||
i < length; ++i) {
|
||||
mControls->mElements[i]->UpdateState(true);
|
||||
}
|
||||
|
||||
for (PRUint32 i = 0, length = mControls->mNotInElements.Length();
|
||||
i < length; ++i) {
|
||||
doc->ContentStateChanged(mControls->mNotInElements[i],
|
||||
NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID);
|
||||
}
|
||||
for (PRUint32 i = 0, length = mControls->mNotInElements.Length();
|
||||
i < length; ++i) {
|
||||
mControls->mNotInElements[i]->UpdateState(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -505,8 +498,7 @@ CollectOrphans(nsINode* aRemovalRoot, nsTArray<nsGenericHTMLFormElement*> aArray
|
||||
#endif
|
||||
)
|
||||
{
|
||||
// Prepare document update batch.
|
||||
nsIDocument* doc = aArray.IsEmpty() ? nsnull : aArray[0]->GetCurrentDoc();
|
||||
// Put a script blocker around all the notifications we're about to do.
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
|
||||
// Walk backwards so that if we remove elements we can just keep iterating
|
||||
@ -527,20 +519,8 @@ CollectOrphans(nsINode* aRemovalRoot, nsTArray<nsGenericHTMLFormElement*> aArray
|
||||
if (!nsContentUtils::ContentIsDescendantOf(node, aRemovalRoot)) {
|
||||
node->ClearForm(PR_TRUE);
|
||||
|
||||
// When a form control loses its form owner, :-moz-ui-invalid and
|
||||
// :-moz-ui-valid might not apply any more.
|
||||
nsEventStates states = NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
|
||||
// In addition, submit controls shouldn't have
|
||||
// NS_EVENT_STATE_MOZ_SUBMITINVALID applying if they do not have a form.
|
||||
if (node->IsSubmitControl()) {
|
||||
states |= NS_EVENT_STATE_MOZ_SUBMITINVALID;
|
||||
}
|
||||
|
||||
if (doc) {
|
||||
doc->ContentStateChanged(node, states);
|
||||
}
|
||||
// When a form control loses its form owner, its state can change.
|
||||
node->UpdateState(true);
|
||||
#ifdef DEBUG
|
||||
removed = PR_TRUE;
|
||||
#endif
|
||||
@ -1203,7 +1183,7 @@ nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
// unless it replaces what's in the slot. If it _does_ replace what's in
|
||||
// the slot, it becomes the default submit if either the default submit is
|
||||
// what's in the slot or the child is earlier than the default submit.
|
||||
nsIFormControl* oldDefaultSubmit = mDefaultSubmitElement;
|
||||
nsGenericHTMLFormElement* oldDefaultSubmit = mDefaultSubmitElement;
|
||||
if (!*firstSubmitSlot ||
|
||||
(!lastElement &&
|
||||
CompareFormControlPosition(aChild, *firstSubmitSlot, this) < 0)) {
|
||||
@ -1226,16 +1206,9 @@ nsHTMLFormElement::AddElement(nsGenericHTMLFormElement* aChild,
|
||||
|
||||
// Notify that the state of the previous default submit element has changed
|
||||
// if the element which is the default submit element has changed. The new
|
||||
// default submit element is responsible for its own ContentStateChanged
|
||||
// call.
|
||||
if (aNotify && oldDefaultSubmit &&
|
||||
oldDefaultSubmit != mDefaultSubmitElement) {
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
nsCOMPtr<nsIContent> oldElement(do_QueryInterface(oldDefaultSubmit));
|
||||
document->ContentStateChanged(oldElement, NS_EVENT_STATE_DEFAULT);
|
||||
}
|
||||
// default submit element is responsible for its own state update.
|
||||
if (oldDefaultSubmit && oldDefaultSubmit != mDefaultSubmitElement) {
|
||||
oldDefaultSubmit->UpdateState(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1368,12 +1341,7 @@ nsHTMLFormElement::HandleDefaultSubmitRemoval()
|
||||
|
||||
// Notify about change if needed.
|
||||
if (mDefaultSubmitElement) {
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
document->ContentStateChanged(mDefaultSubmitElement,
|
||||
NS_EVENT_STATE_DEFAULT);
|
||||
}
|
||||
mDefaultSubmitElement->UpdateState(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1742,40 +1710,33 @@ nsHTMLFormElement::CheckValidFormSubmission()
|
||||
if (!mEverTriedInvalidSubmit) {
|
||||
mEverTriedInvalidSubmit = true;
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
/*
|
||||
* We are going to call ContentStateChanged assuming elements want to
|
||||
* be notified because we can't know.
|
||||
* Submissions shouldn't happen during parsing so it _should_ be safe.
|
||||
*/
|
||||
/*
|
||||
* We are going to call update states assuming elements want to
|
||||
* be notified because we can't know.
|
||||
* Submissions shouldn't happen during parsing so it _should_ be safe.
|
||||
*/
|
||||
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
|
||||
for (PRUint32 i = 0, length = mControls->mElements.Length();
|
||||
i < length; ++i) {
|
||||
// Input elements can trigger a form submission and we want to
|
||||
// update the style in that case.
|
||||
if (mControls->mElements[i]->IsHTML(nsGkAtoms::input) &&
|
||||
nsContentUtils::IsFocusedContent(mControls->mElements[i])) {
|
||||
static_cast<nsHTMLInputElement*>(mControls->mElements[i])
|
||||
->UpdateValidityUIBits(true);
|
||||
}
|
||||
|
||||
doc->ContentStateChanged(mControls->mElements[i],
|
||||
NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID);
|
||||
for (PRUint32 i = 0, length = mControls->mElements.Length();
|
||||
i < length; ++i) {
|
||||
// Input elements can trigger a form submission and we want to
|
||||
// update the style in that case.
|
||||
if (mControls->mElements[i]->IsHTML(nsGkAtoms::input) &&
|
||||
nsContentUtils::IsFocusedContent(mControls->mElements[i])) {
|
||||
static_cast<nsHTMLInputElement*>(mControls->mElements[i])
|
||||
->UpdateValidityUIBits(true);
|
||||
}
|
||||
|
||||
// Because of backward compatibility, <input type='image'> is not in
|
||||
// elements but can be invalid.
|
||||
// TODO: should probably be removed when bug 606491 will be fixed.
|
||||
for (PRUint32 i = 0, length = mControls->mNotInElements.Length();
|
||||
i < length; ++i) {
|
||||
doc->ContentStateChanged(mControls->mNotInElements[i],
|
||||
NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID);
|
||||
}
|
||||
mControls->mElements[i]->UpdateState(true);
|
||||
}
|
||||
|
||||
// Because of backward compatibility, <input type='image'> is not in
|
||||
// elements but can be invalid.
|
||||
// TODO: should probably be removed when bug 606491 will be fixed.
|
||||
for (PRUint32 i = 0, length = mControls->mNotInElements.Length();
|
||||
i < length; ++i) {
|
||||
mControls->mNotInElements[i]->UpdateState(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1823,13 +1784,8 @@ nsHTMLFormElement::UpdateValidity(PRBool aElementValidity)
|
||||
return;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We are going to call ContentStateChanged assuming submit controls want to
|
||||
* We are going to update states assuming submit controls want to
|
||||
* be notified because we can't know.
|
||||
* UpdateValidity shouldn't be called so much during parsing so it _should_
|
||||
* be safe.
|
||||
@ -1841,8 +1797,7 @@ nsHTMLFormElement::UpdateValidity(PRBool aElementValidity)
|
||||
for (PRUint32 i = 0, length = mControls->mElements.Length();
|
||||
i < length; ++i) {
|
||||
if (mControls->mElements[i]->IsSubmitControl()) {
|
||||
doc->ContentStateChanged(mControls->mElements[i],
|
||||
NS_EVENT_STATE_MOZ_SUBMITINVALID);
|
||||
mControls->mElements[i]->UpdateState(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1851,8 +1806,7 @@ nsHTMLFormElement::UpdateValidity(PRBool aElementValidity)
|
||||
PRUint32 length = mControls->mNotInElements.Length();
|
||||
for (PRUint32 i = 0; i < length; ++i) {
|
||||
if (mControls->mNotInElements[i]->IsSubmitControl()) {
|
||||
doc->ContentStateChanged(mControls->mNotInElements[i],
|
||||
NS_EVENT_STATE_MOZ_SUBMITINVALID);
|
||||
mControls->mNotInElements[i]->UpdateState(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -180,6 +180,8 @@ NS_NewHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||
nsHTMLImageElement::nsHTMLImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
{
|
||||
// We start out broken
|
||||
AddStatesSilently(NS_EVENT_STATE_BROKEN);
|
||||
}
|
||||
|
||||
nsHTMLImageElement::~nsHTMLImageElement()
|
||||
@ -506,7 +508,10 @@ nsHTMLImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
|
||||
// FIXME: Bug 660963 it would be nice if we could just have
|
||||
// ClearBrokenState update our state and do it fast...
|
||||
ClearBrokenState();
|
||||
RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
|
||||
// If loading is temporarily disabled, don't even launch MaybeLoadImage.
|
||||
// Otherwise MaybeLoadImage may run later when someone has reenabled
|
||||
// loading.
|
||||
|
@ -631,6 +631,15 @@ nsHTMLInputElement::nsHTMLInputElement(already_AddRefed<nsINodeInfo> aNodeInfo,
|
||||
|
||||
if (!gUploadLastDir)
|
||||
nsHTMLInputElement::InitUploadLastDir();
|
||||
|
||||
// Set up our default state. By default we're enabled (since we're
|
||||
// a control type that can be disabled but not actually disabled
|
||||
// right now), optional, and valid. We are NOT readwrite by default
|
||||
// until someone calls UpdateEditableState on us, apparently! Also
|
||||
// by default we don't have to show validity UI and so forth.
|
||||
AddStatesSilently(NS_EVENT_STATE_ENABLED |
|
||||
NS_EVENT_STATE_OPTIONAL |
|
||||
NS_EVENT_STATE_VALID);
|
||||
}
|
||||
|
||||
nsHTMLInputElement::~nsHTMLInputElement()
|
||||
@ -800,9 +809,6 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue,
|
||||
PRBool aNotify)
|
||||
{
|
||||
// States changes that have to be passed to ContentStateChanged().
|
||||
nsEventStates states;
|
||||
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
//
|
||||
// When name or type changes, radio should be added to radio group.
|
||||
@ -815,8 +821,6 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
(mForm || !(GET_BOOLBIT(mBitField, BF_PARSER_CREATING)))) {
|
||||
AddedToRadioGroup();
|
||||
UpdateValueMissingValidityStateForRadio(false);
|
||||
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_REQUIRED | NS_EVENT_STATE_OPTIONAL;
|
||||
}
|
||||
|
||||
// If @value is changed and BF_VALUE_CHANGED is false, @value is the value
|
||||
@ -883,30 +887,6 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
LoadImage(src, PR_FALSE, aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
// Changing type affects the applicability of some states. Just notify
|
||||
// on them all now, just in case. Note that we can't rely on the
|
||||
// notifications LoadImage or CancelImageRequests might have sent, because
|
||||
// those didn't include all the possibly-changed states in the mask. We
|
||||
// have to do this here because we just updated mType, so the code in
|
||||
// nsGenericElement::SetAttrAndNotify didn't see the new states.
|
||||
states |= NS_EVENT_STATE_CHECKED |
|
||||
NS_EVENT_STATE_DEFAULT |
|
||||
NS_EVENT_STATE_BROKEN |
|
||||
NS_EVENT_STATE_USERDISABLED |
|
||||
NS_EVENT_STATE_SUPPRESSED |
|
||||
NS_EVENT_STATE_LOADING |
|
||||
NS_EVENT_STATE_MOZ_READONLY |
|
||||
NS_EVENT_STATE_MOZ_READWRITE |
|
||||
NS_EVENT_STATE_REQUIRED |
|
||||
NS_EVENT_STATE_OPTIONAL |
|
||||
NS_EVENT_STATE_VALID |
|
||||
NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID |
|
||||
NS_EVENT_STATE_INDETERMINATE |
|
||||
NS_EVENT_STATE_MOZ_PLACEHOLDER |
|
||||
NS_EVENT_STATE_MOZ_SUBMITINVALID;
|
||||
}
|
||||
|
||||
if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) {
|
||||
@ -929,34 +909,14 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
|
||||
UpdateBarredFromConstraintValidation();
|
||||
}
|
||||
|
||||
states |= NS_EVENT_STATE_REQUIRED | NS_EVENT_STATE_OPTIONAL |
|
||||
NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
} else if (MaxLengthApplies() && aName == nsGkAtoms::maxlength) {
|
||||
UpdateTooLongValidityState();
|
||||
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
} else if (aName == nsGkAtoms::pattern) {
|
||||
UpdatePatternMismatchValidityState();
|
||||
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
}
|
||||
|
||||
if (aNotify) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
|
||||
if (aName == nsGkAtoms::type) {
|
||||
UpdateEditableState();
|
||||
} else if (IsSingleLineTextControl(PR_FALSE) && aName == nsGkAtoms::readonly) {
|
||||
UpdateEditableState();
|
||||
states |= NS_EVENT_STATE_MOZ_READONLY | NS_EVENT_STATE_MOZ_READWRITE;
|
||||
}
|
||||
|
||||
if (doc && !states.IsEmpty()) {
|
||||
doc->ContentStateChanged(this, states);
|
||||
}
|
||||
}
|
||||
UpdateEditableState(aNotify);
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
|
||||
@ -1023,12 +983,7 @@ nsHTMLInputElement::SetIndeterminateInternal(PRBool aValue,
|
||||
frame->InvalidateFrameSubtree();
|
||||
}
|
||||
|
||||
// Notify the document so it can update :indeterminate pseudoclass rules
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
document->ContentStateChanged(this, NS_EVENT_STATE_INDETERMINATE);
|
||||
}
|
||||
UpdateState(true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1441,11 +1396,7 @@ nsHTMLInputElement::SetValueInternal(const nsAString& aValue,
|
||||
|
||||
if (PlaceholderApplies() &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_MOZ_PLACEHOLDER);
|
||||
}
|
||||
UpdateState(true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -1480,12 +1431,7 @@ nsHTMLInputElement::SetValueChanged(PRBool aValueChanged)
|
||||
}
|
||||
|
||||
if (valueChangedBefore != aValueChanged) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID);
|
||||
}
|
||||
UpdateState(true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -1529,13 +1475,7 @@ nsHTMLInputElement::SetCheckedChangedInternal(PRBool aCheckedChanged)
|
||||
// This method can't be called when we are not authorized to notify
|
||||
// so we do not need a aNotify parameter.
|
||||
if (checkedChangedBefore != aCheckedChanged) {
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
document->ContentStateChanged(this,
|
||||
NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID);
|
||||
}
|
||||
UpdateState(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1729,17 +1669,11 @@ nsHTMLInputElement::SetCheckedInternal(PRBool aChecked, PRBool aNotify)
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAllValidityStates(aNotify);
|
||||
|
||||
// Notify the document that the CSS :checked pseudoclass for this element
|
||||
// has changed state.
|
||||
if (aNotify) {
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
document->ContentStateChanged(this, NS_EVENT_STATE_CHECKED);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAllValidityStates(aNotify);
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -2057,30 +1991,10 @@ nsHTMLInputElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
|
||||
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
|
||||
aVisitor.mEvent->message == NS_BLUR_CONTENT) {
|
||||
nsEventStates states;
|
||||
|
||||
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT) {
|
||||
UpdateValidityUIBits(true);
|
||||
UpdateValidityUIBits(aVisitor.mEvent->message == NS_FOCUS_CONTENT);
|
||||
|
||||
// We don't have to update NS_EVENT_STATE_MOZ_UI_INVALID nor
|
||||
// NS_EVENT_STATE_MOZ_UI_VALID given that the states should not change.
|
||||
} else { // NS_BLUR_CONTENT
|
||||
UpdateValidityUIBits(false);
|
||||
states |= NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
}
|
||||
|
||||
if (PlaceholderApplies() &&
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
|
||||
// TODO: checking if the value is empty could be a good idea but we do not
|
||||
// have a simple way to do that, see bug 585100
|
||||
states |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, states);
|
||||
}
|
||||
UpdateState(true);
|
||||
}
|
||||
|
||||
// ignore the activate event fired by the "Browse..." button
|
||||
@ -2455,7 +2369,10 @@ nsHTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
// Our base URI may have changed; claim that our URI changed, and the
|
||||
// nsImageLoadingContent will decide whether a new image load is warranted.
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
|
||||
// FIXME: Bug 660963 it would be nice if we could just have
|
||||
// ClearBrokenState update our state and do it fast...
|
||||
ClearBrokenState();
|
||||
RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
|
||||
nsContentUtils::AddScriptRunner(
|
||||
NS_NewRunnableMethod(this, &nsHTMLInputElement::MaybeLoadImage));
|
||||
}
|
||||
@ -2476,6 +2393,9 @@ nsHTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
// (call done before).
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
// And now make sure our state is up to date
|
||||
UpdateState(false);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -2498,6 +2418,9 @@ nsHTMLInputElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
UpdateValueMissingValidityState();
|
||||
// We might be no longer disabled because of parent chain changed.
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
// And now make sure our state is up to date
|
||||
UpdateState(false);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3654,14 +3577,7 @@ nsHTMLInputElement::SetCustomValidity(const nsAString& aError)
|
||||
{
|
||||
nsIConstraintValidation::SetCustomValidity(aError);
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID);
|
||||
}
|
||||
UpdateState(true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3872,15 +3788,8 @@ nsHTMLInputElement::UpdateAllValidityStates(PRBool aNotify)
|
||||
UpdateTypeMismatchValidityState();
|
||||
UpdatePatternMismatchValidityState();
|
||||
|
||||
if (validBefore != IsValid() && aNotify) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this,
|
||||
NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID);
|
||||
}
|
||||
if (validBefore != IsValid()) {
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4173,26 +4082,20 @@ nsHTMLInputElement::OnValueChanged(PRBool aNotify)
|
||||
|
||||
// :-moz-placeholder pseudo-class may change when the value changes.
|
||||
// However, we don't want to waste cycles if the state doesn't apply.
|
||||
if (aNotify && PlaceholderApplies()
|
||||
if (PlaceholderApplies()
|
||||
&& HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)
|
||||
&& !nsContentUtils::IsFocusedContent((nsIContent*)(this))) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_MOZ_PLACEHOLDER);
|
||||
}
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLInputElement::FieldSetDisabledChanged(nsEventStates aStates, PRBool aNotify)
|
||||
nsHTMLInputElement::FieldSetDisabledChanged(PRBool aNotify)
|
||||
{
|
||||
UpdateValueMissingValidityState();
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
aStates |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
nsGenericHTMLFormElement::FieldSetDisabledChanged(aStates, aNotify);
|
||||
nsGenericHTMLFormElement::FieldSetDisabledChanged(aNotify);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
|
@ -161,7 +161,7 @@ public:
|
||||
virtual PRBool RestoreState(nsPresState* aState);
|
||||
virtual PRBool AllowDrop();
|
||||
|
||||
virtual void FieldSetDisabledChanged(nsEventStates aStates, PRBool aNotify);
|
||||
virtual void FieldSetDisabledChanged(PRBool aNotify);
|
||||
|
||||
// nsIContent
|
||||
virtual PRBool IsHTMLFocusable(PRBool aWithMouse, PRBool *aIsFocusable, PRInt32 *aTabIndex);
|
||||
@ -239,9 +239,9 @@ public:
|
||||
|
||||
NS_IMETHOD FireAsyncClickHandler();
|
||||
|
||||
virtual void UpdateEditableState()
|
||||
virtual void UpdateEditableState(PRBool aNotify)
|
||||
{
|
||||
return UpdateEditableFormControlState();
|
||||
return UpdateEditableFormControlState(aNotify);
|
||||
}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLInputElement,
|
||||
|
@ -163,6 +163,9 @@ nsHTMLObjectElement::nsHTMLObjectElement(already_AddRefed<nsINodeInfo> aNodeInfo
|
||||
|
||||
// <object> is always barred from constraint validation.
|
||||
SetBarredFromConstraintValidation(PR_TRUE);
|
||||
|
||||
// By default we're in the loading state
|
||||
AddStatesSilently(NS_EVENT_STATE_LOADING);
|
||||
}
|
||||
|
||||
nsHTMLObjectElement::~nsHTMLObjectElement()
|
||||
|
@ -101,6 +101,8 @@ NS_IMPL_NS_NEW_HTML_ELEMENT(OptGroup)
|
||||
nsHTMLOptGroupElement::nsHTMLOptGroupElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLElement(aNodeInfo)
|
||||
{
|
||||
// We start off enabled
|
||||
AddStatesSilently(NS_EVENT_STATE_ENABLED);
|
||||
}
|
||||
|
||||
nsHTMLOptGroupElement::~nsHTMLOptGroupElement()
|
||||
|
@ -120,6 +120,8 @@ nsHTMLOptionElement::nsHTMLOptionElement(already_AddRefed<nsINodeInfo> aNodeInfo
|
||||
mIsSelected(PR_FALSE),
|
||||
mIsInSetDefaultSelected(PR_FALSE)
|
||||
{
|
||||
// We start off enabled
|
||||
AddStatesSilently(NS_EVENT_STATE_ENABLED);
|
||||
}
|
||||
|
||||
nsHTMLOptionElement::~nsHTMLOptionElement()
|
||||
@ -169,14 +171,10 @@ nsHTMLOptionElement::SetSelectedInternal(PRBool aValue, PRBool aNotify)
|
||||
mSelectedChanged = PR_TRUE;
|
||||
mIsSelected = aValue;
|
||||
|
||||
// When mIsInSetDefaultSelected is true, the notification will be handled by
|
||||
// When mIsInSetDefaultSelected is true, the state change will be handled by
|
||||
// SetAttr/UnsetAttr.
|
||||
if (aNotify && !mIsInSetDefaultSelected) {
|
||||
nsIDocument* document = GetCurrentDoc();
|
||||
if (document) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
document->ContentStateChanged(this, NS_EVENT_STATE_CHECKED);
|
||||
}
|
||||
if (!mIsInSetDefaultSelected) {
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,6 +86,10 @@ public:
|
||||
|
||||
nsEventStates IntrinsicState() const;
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers);
|
||||
|
||||
// This function is called when a callback function from nsIMutationObserver
|
||||
// has to be used to update the defaultValue attribute.
|
||||
void DescendantsChanged();
|
||||
@ -120,6 +124,9 @@ nsHTMLOutputElement::nsHTMLOutputElement(already_AddRefed<nsINodeInfo> aNodeInfo
|
||||
, mValueModeFlag(eModeDefault)
|
||||
{
|
||||
AddMutationObserver(this);
|
||||
|
||||
// We start out valid and ui-valid (since we have no form).
|
||||
AddStatesSilently(NS_EVENT_STATE_VALID | NS_EVENT_STATE_MOZ_UI_VALID);
|
||||
}
|
||||
|
||||
nsHTMLOutputElement::~nsHTMLOutputElement()
|
||||
@ -157,14 +164,7 @@ nsHTMLOutputElement::SetCustomValidity(const nsAString& aError)
|
||||
{
|
||||
nsIConstraintValidation::SetCustomValidity(aError);
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID);
|
||||
}
|
||||
UpdateState(true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -222,6 +222,26 @@ nsHTMLOutputElement::IntrinsicState() const
|
||||
return states;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLOutputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
nsIContent* aBindingParent,
|
||||
PRBool aCompileEventHandlers)
|
||||
{
|
||||
nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
|
||||
aBindingParent,
|
||||
aCompileEventHandlers);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Unfortunately, we can actually end up having to change our state
|
||||
// as a result of being bound to a tree even from the parser: we
|
||||
// might end up a in a novalidate form, and unlike other form
|
||||
// controls that on its own is enough to make change ui-valid state.
|
||||
// So just go ahead and update our state now.
|
||||
UpdateState(false);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLOutputElement::GetForm(nsIDOMHTMLFormElement** aForm)
|
||||
{
|
||||
|
@ -102,6 +102,8 @@ NS_IMPL_NS_NEW_HTML_ELEMENT(Progress)
|
||||
nsHTMLProgressElement::nsHTMLProgressElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsGenericHTMLFormElement(aNodeInfo)
|
||||
{
|
||||
// We start out indeterminate
|
||||
AddStatesSilently(NS_EVENT_STATE_INDETERMINATE);
|
||||
}
|
||||
|
||||
nsHTMLProgressElement::~nsHTMLProgressElement()
|
||||
|
@ -156,6 +156,11 @@ nsHTMLSelectElement::nsHTMLSelectElement(already_AddRefed<nsINodeInfo> aNodeInfo
|
||||
|
||||
// DoneAddingChildren() will be called later if it's from the parser,
|
||||
// otherwise it is
|
||||
|
||||
// Set up our default state: enabled, optional, and valid.
|
||||
AddStatesSilently(NS_EVENT_STATE_ENABLED |
|
||||
NS_EVENT_STATE_OPTIONAL |
|
||||
NS_EVENT_STATE_VALID);
|
||||
}
|
||||
|
||||
nsHTMLSelectElement::~nsHTMLSelectElement()
|
||||
@ -203,14 +208,7 @@ nsHTMLSelectElement::SetCustomValidity(const nsAString& aError)
|
||||
{
|
||||
nsIConstraintValidation::SetCustomValidity(aError);
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID);
|
||||
}
|
||||
UpdateState(true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -355,16 +353,7 @@ nsHTMLSelectElement::RemoveOptionsFromList(nsIContent* aOptions,
|
||||
// option.
|
||||
UpdateValueMissingValidityState();
|
||||
|
||||
if (aNotify) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_VALID |
|
||||
NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID);
|
||||
}
|
||||
}
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
@ -888,16 +877,7 @@ nsHTMLSelectElement::OnOptionSelected(nsISelectControlFrame* aSelectFrame,
|
||||
}
|
||||
|
||||
UpdateValueMissingValidityState();
|
||||
if (aNotify) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_VALID |
|
||||
NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID);
|
||||
}
|
||||
}
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1321,16 +1301,7 @@ nsHTMLSelectElement::SelectSomething(PRBool aNotify)
|
||||
NS_ENSURE_SUCCESS(rv, PR_FALSE);
|
||||
|
||||
UpdateValueMissingValidityState();
|
||||
if (aNotify) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_VALID |
|
||||
NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID);
|
||||
}
|
||||
}
|
||||
UpdateState(aNotify);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -1351,8 +1322,13 @@ nsHTMLSelectElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
|
||||
// If there is a disabled fieldset in the parent chain, the element is now
|
||||
// barred from constraint validation.
|
||||
// XXXbz is this still needed now that fieldset changes always call
|
||||
// FieldSetDisabledChanged?
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
// And now make sure our state is up to date
|
||||
UpdateState(false);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1362,7 +1338,12 @@ nsHTMLSelectElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
|
||||
|
||||
// We might be no longer disabled because our parent chain changed.
|
||||
// XXXbz is this still needed now that fieldset changes always call
|
||||
// FieldSetDisabledChanged?
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
// And now make sure our state is up to date
|
||||
UpdateState(false);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -1382,26 +1363,14 @@ nsresult
|
||||
nsHTMLSelectElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify)
|
||||
{
|
||||
nsEventStates states;
|
||||
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
if (aName == nsGkAtoms::disabled) {
|
||||
UpdateBarredFromConstraintValidation();
|
||||
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
} else if (aName == nsGkAtoms::required) {
|
||||
UpdateValueMissingValidityState();
|
||||
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
if (aNotify && !states.IsEmpty()) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, states);
|
||||
}
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
|
||||
@ -1470,6 +1439,9 @@ nsHTMLSelectElement::DoneAddingChildren(PRBool aHaveNotified)
|
||||
// with an empty value. We have to make sure the select element updates it's
|
||||
// validity state to take this into account.
|
||||
UpdateValueMissingValidityState();
|
||||
|
||||
// And now make sure we update our content state too
|
||||
UpdateState(aHaveNotified);
|
||||
}
|
||||
|
||||
mDefaultSelectionSet = PR_TRUE;
|
||||
@ -1573,12 +1545,7 @@ nsHTMLSelectElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
mCanShowInvalidUI = PR_TRUE;
|
||||
mCanShowValidUI = PR_TRUE;
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID);
|
||||
}
|
||||
UpdateState(true);
|
||||
}
|
||||
|
||||
return nsGenericHTMLFormElement::PostHandleEvent(aVisitor);
|
||||
@ -2287,13 +2254,11 @@ nsHTMLSelectElement::UpdateBarredFromConstraintValidation()
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLSelectElement::FieldSetDisabledChanged(nsEventStates aStates, PRBool aNotify)
|
||||
nsHTMLSelectElement::FieldSetDisabledChanged(PRBool aNotify)
|
||||
{
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
aStates |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
nsGenericHTMLFormElement::FieldSetDisabledChanged(aStates, aNotify);
|
||||
nsGenericHTMLFormElement::FieldSetDisabledChanged(aNotify);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2306,13 +2271,8 @@ nsHTMLSelectElement::SetSelectionChanged(PRBool aValue, PRBool aNotify)
|
||||
PRBool previousSelectionChangedValue = mSelectionHasChanged;
|
||||
mSelectionHasChanged = aValue;
|
||||
|
||||
if (aNotify && mSelectionHasChanged != previousSelectionChangedValue) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_MOZ_UI_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID);
|
||||
}
|
||||
if (mSelectionHasChanged != previousSelectionChangedValue) {
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,7 +289,7 @@ public:
|
||||
NS_IMETHOD SaveState();
|
||||
virtual PRBool RestoreState(nsPresState* aState);
|
||||
|
||||
virtual void FieldSetDisabledChanged(nsEventStates aStates, PRBool aNotify);
|
||||
virtual void FieldSetDisabledChanged(PRBool aNotify);
|
||||
|
||||
nsEventStates IntrinsicState() const;
|
||||
|
||||
|
@ -180,6 +180,9 @@ nsHTMLSharedObjectElement::nsHTMLSharedObjectElement(already_AddRefed<nsINodeInf
|
||||
{
|
||||
RegisterFreezableElement();
|
||||
SetIsNetworkCreated(aFromParser == FROM_PARSER_NETWORK);
|
||||
|
||||
// By default we're in the loading state
|
||||
AddStatesSilently(NS_EVENT_STATE_LOADING);
|
||||
}
|
||||
|
||||
nsHTMLSharedObjectElement::~nsHTMLSharedObjectElement()
|
||||
|
@ -134,7 +134,7 @@ public:
|
||||
NS_IMETHOD SaveState();
|
||||
virtual PRBool RestoreState(nsPresState* aState);
|
||||
|
||||
virtual void FieldSetDisabledChanged(nsEventStates aStates, PRBool aNotify);
|
||||
virtual void FieldSetDisabledChanged(PRBool aNotify);
|
||||
|
||||
virtual nsEventStates IntrinsicState() const;
|
||||
|
||||
@ -204,9 +204,9 @@ public:
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
|
||||
virtual void UpdateEditableState()
|
||||
virtual void UpdateEditableState(PRBool aNotify)
|
||||
{
|
||||
return UpdateEditableFormControlState();
|
||||
return UpdateEditableFormControlState(aNotify);
|
||||
}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsHTMLTextAreaElement,
|
||||
@ -321,6 +321,15 @@ nsHTMLTextAreaElement::nsHTMLTextAreaElement(already_AddRefed<nsINodeInfo> aNode
|
||||
mState(new nsTextEditorState(this))
|
||||
{
|
||||
AddMutationObserver(this);
|
||||
|
||||
// Set up our default state. By default we're enabled (since we're
|
||||
// a control type that can be disabled but not actually disabled
|
||||
// right now), optional, and valid. We are NOT readwrite by default
|
||||
// until someone calls UpdateEditableState on us, apparently! Also
|
||||
// by default we don't have to show validity UI and so forth.
|
||||
AddStatesSilently(NS_EVENT_STATE_ENABLED |
|
||||
NS_EVENT_STATE_OPTIONAL |
|
||||
NS_EVENT_STATE_VALID);
|
||||
}
|
||||
|
||||
|
||||
@ -587,18 +596,7 @@ nsHTMLTextAreaElement::SetValueChanged(PRBool aValueChanged)
|
||||
}
|
||||
|
||||
if (mValueChanged != previousValue) {
|
||||
nsEventStates states = NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
|
||||
states |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, states);
|
||||
}
|
||||
UpdateState(true);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -747,8 +745,6 @@ nsHTMLTextAreaElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
|
||||
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT ||
|
||||
aVisitor.mEvent->message == NS_BLUR_CONTENT) {
|
||||
nsEventStates states;
|
||||
|
||||
if (aVisitor.mEvent->message == NS_FOCUS_CONTENT) {
|
||||
// If the invalid UI is shown, we should show it while focusing (and
|
||||
// update). Otherwise, we should not.
|
||||
@ -757,26 +753,12 @@ nsHTMLTextAreaElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
||||
// If neither invalid UI nor valid UI is shown, we shouldn't show the valid
|
||||
// UI while typing.
|
||||
mCanShowValidUI = ShouldShowValidityUI();
|
||||
|
||||
// We don't have to update NS_EVENT_STATE_MOZ_UI_INVALID nor
|
||||
// NS_EVENT_STATE_MOZ_UI_VALID given that the states should not change.
|
||||
} else { // NS_BLUR_CONTENT
|
||||
mCanShowInvalidUI = PR_TRUE;
|
||||
mCanShowValidUI = PR_TRUE;
|
||||
states |= NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
}
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
|
||||
// TODO: checking if the value is empty could be a good idea but we do not
|
||||
// have a simple way to do that, see bug 585100
|
||||
states |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
|
||||
}
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, states);
|
||||
}
|
||||
UpdateState(true);
|
||||
}
|
||||
|
||||
// Reset the flag for other content besides this text field
|
||||
@ -1116,6 +1098,9 @@ nsHTMLTextAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
UpdateValueMissingValidityState();
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
// And now make sure our state is up to date
|
||||
UpdateState(false);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1127,6 +1112,9 @@ nsHTMLTextAreaElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
|
||||
// We might be no longer disabled because of parent chain changed.
|
||||
UpdateValueMissingValidityState();
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
// And now make sure our state is up to date
|
||||
UpdateState(false);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -1194,8 +1182,6 @@ nsresult
|
||||
nsHTMLTextAreaElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify)
|
||||
{
|
||||
nsEventStates states;
|
||||
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
|
||||
aName == nsGkAtoms::readonly) {
|
||||
@ -1205,28 +1191,14 @@ nsHTMLTextAreaElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
||||
if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
|
||||
UpdateBarredFromConstraintValidation();
|
||||
}
|
||||
|
||||
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID |
|
||||
NS_EVENT_STATE_MOZ_SUBMITINVALID;
|
||||
} else if (aName == nsGkAtoms::maxlength) {
|
||||
UpdateTooLongValidityState();
|
||||
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
}
|
||||
|
||||
if (aNotify) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
|
||||
if (aName == nsGkAtoms::readonly) {
|
||||
UpdateEditableState();
|
||||
states |= NS_EVENT_STATE_MOZ_READONLY | NS_EVENT_STATE_MOZ_READWRITE;
|
||||
}
|
||||
|
||||
if (doc && !states.IsEmpty()) {
|
||||
doc->ContentStateChanged(this, states);
|
||||
}
|
||||
if (aName == nsGkAtoms::readonly) {
|
||||
UpdateEditableState(aNotify);
|
||||
}
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName, aValue,
|
||||
@ -1269,14 +1241,7 @@ nsHTMLTextAreaElement::SetCustomValidity(const nsAString& aError)
|
||||
{
|
||||
nsIConstraintValidation::SetCustomValidity(aError);
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID);
|
||||
}
|
||||
UpdateState(true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1487,36 +1452,19 @@ nsHTMLTextAreaElement::OnValueChanged(PRBool aNotify)
|
||||
UpdateTooLongValidityState();
|
||||
UpdateValueMissingValidityState();
|
||||
|
||||
if (aNotify) {
|
||||
nsEventStates states;
|
||||
if (validBefore != IsValid()) {
|
||||
states |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
}
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)
|
||||
&& !nsContentUtils::IsFocusedContent((nsIContent*)(this))) {
|
||||
states |= NS_EVENT_STATE_MOZ_PLACEHOLDER;
|
||||
}
|
||||
|
||||
if (!states.IsEmpty()) {
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, states);
|
||||
}
|
||||
}
|
||||
if (validBefore != IsValid() ||
|
||||
(HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)
|
||||
&& !nsContentUtils::IsFocusedContent((nsIContent*)(this)))) {
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsHTMLTextAreaElement::FieldSetDisabledChanged(nsEventStates aStates, PRBool aNotify)
|
||||
nsHTMLTextAreaElement::FieldSetDisabledChanged(PRBool aNotify)
|
||||
{
|
||||
UpdateValueMissingValidityState();
|
||||
UpdateBarredFromConstraintValidation();
|
||||
|
||||
aStates |= NS_EVENT_STATE_VALID | NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID | NS_EVENT_STATE_MOZ_UI_INVALID;
|
||||
nsGenericHTMLFormElement::FieldSetDisabledChanged(aStates, aNotify);
|
||||
nsGenericHTMLFormElement::FieldSetDisabledChanged(aNotify);
|
||||
}
|
||||
|
||||
|
@ -83,13 +83,7 @@ nsRadioSetValueMissingState::Visit(nsIFormControl* aRadio)
|
||||
input->SetValidityState(nsIConstraintValidation::VALIDITY_STATE_VALUE_MISSING,
|
||||
mValidity);
|
||||
|
||||
nsIDocument* doc = input->GetCurrentDoc();
|
||||
if (mNotify && doc) {
|
||||
doc->ContentStateChanged(input, NS_EVENT_STATE_VALID |
|
||||
NS_EVENT_STATE_INVALID |
|
||||
NS_EVENT_STATE_MOZ_UI_VALID |
|
||||
NS_EVENT_STATE_MOZ_UI_INVALID);
|
||||
}
|
||||
input->UpdateState(true);
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ function checkNotSufferingFromBeingMissing(element, doNotApply)
|
||||
if (element.type != 'radio' && element.type != 'checkbox') {
|
||||
is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
|
||||
doNotApply ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)",
|
||||
"The pseudo-class is not correctly applied");
|
||||
"The pseudo-class is not correctly applied to " + element.localName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2732,10 +2732,9 @@ NotifyEditableStateChange(nsINode *aNode, nsIDocument *aDocument,
|
||||
PRUint32 i, n = aNode->GetChildCount();
|
||||
for (i = 0; i < n; ++i) {
|
||||
nsIContent *child = aNode->GetChildAt(i);
|
||||
if (child->HasFlag(NODE_IS_EDITABLE) != aEditable) {
|
||||
aDocument->ContentStateChanged(child,
|
||||
NS_EVENT_STATE_MOZ_READONLY |
|
||||
NS_EVENT_STATE_MOZ_READWRITE);
|
||||
if (child->HasFlag(NODE_IS_EDITABLE) != aEditable &&
|
||||
child->IsElement()) {
|
||||
child->AsElement()->UpdateState(true);
|
||||
}
|
||||
NotifyEditableStateChange(child, aDocument, aEditable);
|
||||
}
|
||||
|
@ -463,10 +463,5 @@ nsMathMLElement::SetIncrementScriptLevel(PRBool aIncrementScriptLevel,
|
||||
|
||||
NS_ASSERTION(aNotify, "We always notify!");
|
||||
|
||||
nsIDocument* doc = GetCurrentDoc();
|
||||
if (!doc)
|
||||
return;
|
||||
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL);
|
||||
UpdateState(true);
|
||||
}
|
||||
|
@ -5377,6 +5377,8 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGFEImageElementBase)
|
||||
nsSVGFEImageElement::nsSVGFEImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsSVGFEImageElementBase(aNodeInfo)
|
||||
{
|
||||
// We start out broken
|
||||
AddStatesSilently(NS_EVENT_STATE_BROKEN);
|
||||
}
|
||||
|
||||
nsSVGFEImageElement::~nsSVGFEImageElement()
|
||||
@ -5466,7 +5468,10 @@ nsSVGFEImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
|
||||
// FIXME: Bug 660963 it would be nice if we could just have
|
||||
// ClearBrokenState update our state and do it fast...
|
||||
ClearBrokenState();
|
||||
RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
|
||||
nsContentUtils::AddScriptRunner(
|
||||
NS_NewRunnableMethod(this, &nsSVGFEImageElement::MaybeLoadSVGImage));
|
||||
}
|
||||
|
@ -84,6 +84,8 @@ NS_INTERFACE_MAP_END_INHERITING(nsSVGImageElementBase)
|
||||
nsSVGImageElement::nsSVGImageElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
: nsSVGImageElementBase(aNodeInfo)
|
||||
{
|
||||
// We start out broken
|
||||
AddStatesSilently(NS_EVENT_STATE_BROKEN);
|
||||
}
|
||||
|
||||
nsSVGImageElement::~nsSVGImageElement()
|
||||
@ -207,7 +209,10 @@ nsSVGImageElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
|
||||
// FIXME: Bug 660963 it would be nice if we could just have
|
||||
// ClearBrokenState update our state and do it fast...
|
||||
ClearBrokenState();
|
||||
RemoveStatesSilently(NS_EVENT_STATE_BROKEN);
|
||||
nsContentUtils::AddScriptRunner(
|
||||
NS_NewRunnableMethod(this, &nsSVGImageElement::MaybeLoadSVGImage));
|
||||
}
|
||||
|
@ -914,8 +914,7 @@ nsXTFElementWrapper::SetIntrinsicState(nsEventStates::InternalType aNewState)
|
||||
"Both READONLY and READWRITE are being set. Yikes!!!");
|
||||
|
||||
mIntrinsicState = newStates;
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
doc->ContentStateChanged(this, bits);
|
||||
UpdateState(true);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -245,6 +245,12 @@ nsXULElement::nsXULElement(already_AddRefed<nsINodeInfo> aNodeInfo)
|
||||
mBindingParent(nsnull)
|
||||
{
|
||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumElements);
|
||||
|
||||
// We may be READWRITE by default; check.
|
||||
if (IsReadWriteTextElement()) {
|
||||
AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
|
||||
RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
|
||||
}
|
||||
}
|
||||
|
||||
nsXULElement::nsXULSlots::nsXULSlots()
|
||||
@ -892,6 +898,16 @@ nsXULElement::MaybeAddPopupListener(nsIAtom* aLocalName)
|
||||
//
|
||||
// nsIContent interface
|
||||
//
|
||||
void
|
||||
nsXULElement::UpdateEditableState(PRBool aNotify)
|
||||
{
|
||||
// Don't call through to nsGenericElement here because the things
|
||||
// it does don't work for cases when we're an editable control.
|
||||
nsIContent *parent = GetParent();
|
||||
|
||||
SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULElement::BindToTree(nsIDocument* aDocument,
|
||||
@ -1362,12 +1378,7 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
|
||||
nsAutoString oldValue;
|
||||
GetAttr(aNameSpaceID, aName, oldValue);
|
||||
|
||||
// When notifying, make sure to keep track of states whose value
|
||||
// depends solely on the value of an attribute.
|
||||
nsEventStates stateMask;
|
||||
if (aNotify) {
|
||||
stateMask = IntrinsicState();
|
||||
|
||||
nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName,
|
||||
nsIDOMMutationEvent::REMOVAL);
|
||||
}
|
||||
@ -1467,11 +1478,9 @@ nsXULElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotify)
|
||||
|
||||
}
|
||||
|
||||
UpdateState(aNotify);
|
||||
|
||||
if (aNotify) {
|
||||
stateMask ^= IntrinsicState();
|
||||
if (doc && !stateMask.IsEmpty()) {
|
||||
doc->ContentStateChanged(this, stateMask);
|
||||
}
|
||||
nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
|
||||
nsIDOMMutationEvent::REMOVAL);
|
||||
}
|
||||
@ -2248,10 +2257,7 @@ nsXULElement::IntrinsicState() const
|
||||
{
|
||||
nsEventStates state = nsStyledElement::IntrinsicState();
|
||||
|
||||
const nsIAtom* tag = Tag();
|
||||
if (GetNameSpaceID() == kNameSpaceID_XUL &&
|
||||
(tag == nsGkAtoms::textbox || tag == nsGkAtoms::textarea) &&
|
||||
!HasAttr(kNameSpaceID_None, nsGkAtoms::readonly)) {
|
||||
if (IsReadWriteTextElement()) {
|
||||
state |= NS_EVENT_STATE_MOZ_READWRITE;
|
||||
state &= ~NS_EVENT_STATE_MOZ_READONLY;
|
||||
}
|
||||
|
@ -651,6 +651,8 @@ protected:
|
||||
virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
|
||||
const nsAString* aValue, PRBool aNotify);
|
||||
|
||||
virtual void UpdateEditableState(PRBool aNotify);
|
||||
|
||||
virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
|
||||
nsIAtom* aAttribute,
|
||||
const nsAString& aValue,
|
||||
@ -708,6 +710,15 @@ protected:
|
||||
PRBool aIsScriptable);
|
||||
|
||||
friend class nsScriptEventHandlerOwnerTearoff;
|
||||
|
||||
bool IsReadWriteTextElement() const
|
||||
{
|
||||
const nsIAtom* tag = Tag();
|
||||
return
|
||||
GetNameSpaceID() == kNameSpaceID_XUL &&
|
||||
(tag == nsGkAtoms::textbox || tag == nsGkAtoms::textarea) &&
|
||||
!HasAttr(kNameSpaceID_None, nsGkAtoms::readonly);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // nsXULElement_h__
|
||||
|
@ -66,6 +66,7 @@
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
nsIFrame*
|
||||
NS_NewHTMLVideoFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
@ -101,7 +102,8 @@ nsVideoFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||
nsnull,
|
||||
kNameSpaceID_XHTML);
|
||||
NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
|
||||
mPosterImage = NS_NewHTMLImageElement(nodeInfo.forget());
|
||||
Element* element = NS_NewHTMLImageElement(nodeInfo.forget());
|
||||
mPosterImage = element;
|
||||
NS_ENSURE_TRUE(mPosterImage, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// Push a null JSContext on the stack so that code that runs
|
||||
@ -118,6 +120,8 @@ nsVideoFrame::CreateAnonymousContent(nsTArray<ContentInfo>& aElements)
|
||||
NS_ENSURE_TRUE(imgContent, NS_ERROR_FAILURE);
|
||||
|
||||
imgContent->ForceImageState(PR_TRUE, 0);
|
||||
// And now have it update its internal state
|
||||
element->UpdateState(false);
|
||||
|
||||
nsresult res = UpdatePosterSource(PR_FALSE);
|
||||
NS_ENSURE_SUCCESS(res,res);
|
||||
|
Loading…
Reference in New Issue
Block a user