This source file includes following definitions.
- isValidColorString
- create
- countUsage
- isColorControl
- formControlType
- supportsRequired
- fallbackValue
- sanitizeValue
- valueAsColor
- createShadowSubtree
- setValue
- handleDOMActivateEvent
- closePopupView
- shouldRespectListAttribute
- typeMismatchFor
- didChooseColor
- didEndChooser
- endColorChooser
- updateView
- shadowColorSwatch
- elementRectRelativeToRootView
- currentColor
- shouldShowSuggestions
- suggestions
#include "config.h"
#include "core/html/forms/ColorInputType.h"
#include "CSSPropertyNames.h"
#include "InputTypeNames.h"
#include "RuntimeEnabledFeatures.h"
#include "bindings/v8/ExceptionStatePlaceholder.h"
#include "bindings/v8/ScriptController.h"
#include "core/events/MouseEvent.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/html/HTMLDataListElement.h"
#include "core/html/HTMLDivElement.h"
#include "core/html/HTMLInputElement.h"
#include "core/html/HTMLOptionElement.h"
#include "core/page/Chrome.h"
#include "core/rendering/RenderView.h"
#include "platform/UserGestureIndicator.h"
#include "platform/graphics/Color.h"
#include "wtf/PassOwnPtr.h"
#include "wtf/text/WTFString.h"
namespace WebCore {
using namespace HTMLNames;
static const unsigned maxSuggestions = 1000;
static const unsigned maxSuggestionLabelLength = 1000;
static bool isValidColorString(const String& value)
{
if (value.isEmpty())
return false;
if (value[0] != '#')
return false;
if (value.length() != 7)
return false;
Color color;
return color.setFromString(value) && !color.hasAlpha();
}
PassRefPtr<InputType> ColorInputType::create(HTMLInputElement& element)
{
return adoptRef(new ColorInputType(element));
}
ColorInputType::~ColorInputType()
{
endColorChooser();
}
void ColorInputType::countUsage()
{
countUsageIfVisible(UseCounter::InputTypeColor);
}
bool ColorInputType::isColorControl() const
{
return true;
}
const AtomicString& ColorInputType::formControlType() const
{
return InputTypeNames::color;
}
bool ColorInputType::supportsRequired() const
{
return false;
}
String ColorInputType::fallbackValue() const
{
return String("#000000");
}
String ColorInputType::sanitizeValue(const String& proposedValue) const
{
if (!isValidColorString(proposedValue))
return fallbackValue();
return proposedValue.lower();
}
Color ColorInputType::valueAsColor() const
{
Color color;
bool success = color.setFromString(element().value());
ASSERT_UNUSED(success, success);
return color;
}
void ColorInputType::createShadowSubtree()
{
ASSERT(element().shadow());
Document& document = element().document();
RefPtr<HTMLDivElement> wrapperElement = HTMLDivElement::create(document);
wrapperElement->setShadowPseudoId(AtomicString("-webkit-color-swatch-wrapper", AtomicString::ConstructFromLiteral));
RefPtr<HTMLDivElement> colorSwatch = HTMLDivElement::create(document);
colorSwatch->setShadowPseudoId(AtomicString("-webkit-color-swatch", AtomicString::ConstructFromLiteral));
wrapperElement->appendChild(colorSwatch.release());
element().userAgentShadowRoot()->appendChild(wrapperElement.release());
element().updateView();
}
void ColorInputType::setValue(const String& value, bool valueChanged, TextFieldEventBehavior eventBehavior)
{
InputType::setValue(value, valueChanged, eventBehavior);
if (!valueChanged)
return;
element().updateView();
if (m_chooser)
m_chooser->setSelectedColor(valueAsColor());
}
void ColorInputType::handleDOMActivateEvent(Event* event)
{
if (element().isDisabledFormControl() || !element().renderer())
return;
if (!UserGestureIndicator::processingUserGesture())
return;
Chrome* chrome = this->chrome();
if (chrome && !m_chooser)
m_chooser = chrome->createColorChooser(this, valueAsColor());
event->setDefaultHandled();
}
void ColorInputType::closePopupView()
{
endColorChooser();
}
bool ColorInputType::shouldRespectListAttribute()
{
return true;
}
bool ColorInputType::typeMismatchFor(const String& value) const
{
return !isValidColorString(value);
}
void ColorInputType::didChooseColor(const Color& color)
{
if (element().isDisabledFormControl() || color == valueAsColor())
return;
element().setValueFromRenderer(color.serialized());
element().updateView();
element().dispatchFormControlChangeEvent();
}
void ColorInputType::didEndChooser()
{
m_chooser.clear();
}
void ColorInputType::endColorChooser()
{
if (m_chooser)
m_chooser->endChooser();
}
void ColorInputType::updateView()
{
HTMLElement* colorSwatch = shadowColorSwatch();
if (!colorSwatch)
return;
colorSwatch->setInlineStyleProperty(CSSPropertyBackgroundColor, element().value());
}
HTMLElement* ColorInputType::shadowColorSwatch() const
{
ShadowRoot* shadow = element().userAgentShadowRoot();
return shadow ? toHTMLElement(shadow->firstChild()->firstChild()) : 0;
}
IntRect ColorInputType::elementRectRelativeToRootView() const
{
return element().document().view()->contentsToRootView(element().pixelSnappedBoundingBox());
}
Color ColorInputType::currentColor()
{
return valueAsColor();
}
bool ColorInputType::shouldShowSuggestions() const
{
return element().fastHasAttribute(listAttr);
}
Vector<ColorSuggestion> ColorInputType::suggestions() const
{
Vector<ColorSuggestion> suggestions;
HTMLDataListElement* dataList = element().dataList();
if (dataList) {
RefPtr<HTMLCollection> options = dataList->options();
for (unsigned i = 0; HTMLOptionElement* option = toHTMLOptionElement(options->item(i)); i++) {
if (!element().isValidValue(option->value()))
continue;
Color color;
if (!color.setFromString(option->value()))
continue;
ColorSuggestion suggestion(color, option->label().left(maxSuggestionLabelLength));
suggestions.append(suggestion);
if (suggestions.size() >= maxSuggestions)
break;
}
}
return suggestions;
}
}