This source file includes following definitions.
- isEmpty
- isRequired
- checkedButton
- m_requiredCount
- create
- isValid
- setCheckedButton
- add
- updateCheckedState
- requiredAttributeChanged
- remove
- setNeedsValidityCheckForAllButtons
- contains
- addButton
- updateCheckedState
- requiredAttributeChanged
- checkedButtonForGroup
- isInRequiredGroup
- removeButton
#include "config.h"
#include "core/html/forms/RadioButtonGroupScope.h"
#include "core/html/HTMLInputElement.h"
#include "wtf/HashSet.h"
namespace WebCore {
class RadioButtonGroup {
WTF_MAKE_FAST_ALLOCATED;
public:
static PassOwnPtr<RadioButtonGroup> create();
bool isEmpty() const { return m_members.isEmpty(); }
bool isRequired() const { return m_requiredCount; }
HTMLInputElement* checkedButton() const { return m_checkedButton; }
void add(HTMLInputElement*);
void updateCheckedState(HTMLInputElement*);
void requiredAttributeChanged(HTMLInputElement*);
void remove(HTMLInputElement*);
bool contains(HTMLInputElement*) const;
private:
RadioButtonGroup();
void setNeedsValidityCheckForAllButtons();
bool isValid() const;
void setCheckedButton(HTMLInputElement*);
HashSet<HTMLInputElement*> m_members;
HTMLInputElement* m_checkedButton;
size_t m_requiredCount;
};
RadioButtonGroup::RadioButtonGroup()
: m_checkedButton(0)
, m_requiredCount(0)
{
}
PassOwnPtr<RadioButtonGroup> RadioButtonGroup::create()
{
return adoptPtr(new RadioButtonGroup);
}
inline bool RadioButtonGroup::isValid() const
{
return !isRequired() || m_checkedButton;
}
void RadioButtonGroup::setCheckedButton(HTMLInputElement* button)
{
HTMLInputElement* oldCheckedButton = m_checkedButton;
if (oldCheckedButton == button)
return;
m_checkedButton = button;
if (oldCheckedButton)
oldCheckedButton->setChecked(false);
}
void RadioButtonGroup::add(HTMLInputElement* button)
{
ASSERT(button->isRadioButton());
if (!m_members.add(button).isNewEntry)
return;
bool groupWasValid = isValid();
if (button->isRequired())
++m_requiredCount;
if (button->checked())
setCheckedButton(button);
bool groupIsValid = isValid();
if (groupWasValid != groupIsValid) {
setNeedsValidityCheckForAllButtons();
} else if (!groupIsValid) {
button->setNeedsValidityCheck();
}
}
void RadioButtonGroup::updateCheckedState(HTMLInputElement* button)
{
ASSERT(button->isRadioButton());
ASSERT(m_members.contains(button));
bool wasValid = isValid();
if (button->checked()) {
setCheckedButton(button);
} else {
if (m_checkedButton == button)
m_checkedButton = 0;
}
if (wasValid != isValid())
setNeedsValidityCheckForAllButtons();
}
void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button)
{
ASSERT(button->isRadioButton());
ASSERT(m_members.contains(button));
bool wasValid = isValid();
if (button->isRequired()) {
++m_requiredCount;
} else {
ASSERT(m_requiredCount);
--m_requiredCount;
}
if (wasValid != isValid())
setNeedsValidityCheckForAllButtons();
}
void RadioButtonGroup::remove(HTMLInputElement* button)
{
ASSERT(button->isRadioButton());
HashSet<HTMLInputElement*>::iterator it = m_members.find(button);
if (it == m_members.end())
return;
bool wasValid = isValid();
m_members.remove(it);
if (button->isRequired()) {
ASSERT(m_requiredCount);
--m_requiredCount;
}
if (m_checkedButton == button)
m_checkedButton = 0;
if (m_members.isEmpty()) {
ASSERT(!m_requiredCount);
ASSERT(!m_checkedButton);
} else if (wasValid != isValid()) {
setNeedsValidityCheckForAllButtons();
}
if (!wasValid) {
button->setNeedsValidityCheck();
}
}
void RadioButtonGroup::setNeedsValidityCheckForAllButtons()
{
typedef HashSet<HTMLInputElement*>::const_iterator Iterator;
Iterator end = m_members.end();
for (Iterator it = m_members.begin(); it != end; ++it) {
HTMLInputElement* button = *it;
ASSERT(button->isRadioButton());
button->setNeedsValidityCheck();
}
}
bool RadioButtonGroup::contains(HTMLInputElement* button) const
{
return m_members.contains(button);
}
RadioButtonGroupScope::RadioButtonGroupScope()
{
}
RadioButtonGroupScope::~RadioButtonGroupScope()
{
}
void RadioButtonGroupScope::addButton(HTMLInputElement* element)
{
ASSERT(element->isRadioButton());
if (element->name().isEmpty())
return;
if (!m_nameToGroupMap)
m_nameToGroupMap = adoptPtr(new NameToGroupMap);
OwnPtr<RadioButtonGroup>& group = m_nameToGroupMap->add(element->name(), PassOwnPtr<RadioButtonGroup>()).storedValue->value;
if (!group)
group = RadioButtonGroup::create();
group->add(element);
}
void RadioButtonGroupScope::updateCheckedState(HTMLInputElement* element)
{
ASSERT(element->isRadioButton());
if (element->name().isEmpty())
return;
ASSERT(m_nameToGroupMap);
if (!m_nameToGroupMap)
return;
RadioButtonGroup* group = m_nameToGroupMap->get(element->name());
ASSERT(group);
group->updateCheckedState(element);
}
void RadioButtonGroupScope::requiredAttributeChanged(HTMLInputElement* element)
{
ASSERT(element->isRadioButton());
if (element->name().isEmpty())
return;
ASSERT(m_nameToGroupMap);
if (!m_nameToGroupMap)
return;
RadioButtonGroup* group = m_nameToGroupMap->get(element->name());
ASSERT(group);
group->requiredAttributeChanged(element);
}
HTMLInputElement* RadioButtonGroupScope::checkedButtonForGroup(const AtomicString& name) const
{
if (!m_nameToGroupMap)
return 0;
RadioButtonGroup* group = m_nameToGroupMap->get(name);
return group ? group->checkedButton() : 0;
}
bool RadioButtonGroupScope::isInRequiredGroup(HTMLInputElement* element) const
{
ASSERT(element->isRadioButton());
if (element->name().isEmpty())
return false;
if (!m_nameToGroupMap)
return false;
RadioButtonGroup* group = m_nameToGroupMap->get(element->name());
return group && group->isRequired() && group->contains(element);
}
void RadioButtonGroupScope::removeButton(HTMLInputElement* element)
{
ASSERT(element->isRadioButton());
if (element->name().isEmpty())
return;
if (!m_nameToGroupMap)
return;
RadioButtonGroup* group = m_nameToGroupMap->get(element->name());
if (!group)
return;
group->remove(element);
if (group->isEmpty()) {
ASSERT(!group->isRequired());
ASSERT_WITH_SECURITY_IMPLICATION(!group->checkedButton());
}
}
}