15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010 Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 Apple Inc. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
3306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/html/forms/RangeInputType.h"
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "bindings/core/v8/ExceptionStatePlaceholder.h"
365d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/HTMLNames.h"
375d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)#include "core/InputTypeNames.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/accessibility/AXObjectCache.h"
3906f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/KeyboardEvent.h"
4006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/MouseEvent.h"
4106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/ScopedEventQueue.h"
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/Touch.h"
4306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/events/TouchEvent.h"
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/dom/TouchList.h"
45e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)#include "core/dom/shadow/ShadowRoot.h"
4693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "core/html/HTMLDataListElement.h"
479e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)#include "core/html/HTMLDataListOptionsCollection.h"
4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLDivElement.h"
4953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/HTMLInputElement.h"
5093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "core/html/HTMLOptionElement.h"
5106f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include "core/html/forms/StepRange.h"
5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/parser/HTMLParserIdioms.h"
53e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)#include "core/html/shadow/ShadowElementNames.h"
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/html/shadow/SliderThumbElement.h"
5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/RenderSlider.h"
561e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/PlatformMouseEvent.h"
5793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/MathExtras.h"
5893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/NonCopyingSort.h"
5993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)#include "wtf/PassOwnPtr.h"
6006f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)#include <limits>
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
62c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)using namespace HTMLNames;
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int rangeDefaultMinimum = 0;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int rangeDefaultMaximum = 100;
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int rangeDefaultStep = 1;
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int rangeDefaultStepBase = 0;
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int rangeStepScaleFactor = 1;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static Decimal ensureMaximum(const Decimal& proposedValue, const Decimal& minimum, const Decimal& fallbackValue)
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return proposedValue >= minimum ? proposedValue : std::max(minimum, fallbackValue);
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
77323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)PassRefPtrWillBeRawPtr<InputType> RangeInputType::create(HTMLInputElement& element)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
79323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    return adoptRefWillBeNoop(new RangeInputType(element));
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
82bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)RangeInputType::RangeInputType(HTMLInputElement& element)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : InputType(element)
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_tickMarkValuesDirty(true)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
88e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)void RangeInputType::countUsage()
89926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
90f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    countUsageIfVisible(UseCounter::InputTypeRange);
91926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
92926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const AtomicString& RangeInputType::formControlType() const
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
9551b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    return InputTypeNames::range;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)double RangeInputType::valueAsDouble() const
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
100bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return parseToDoubleForNumberType(element().value());
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void RangeInputType::setValueAsDouble(double newValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
10509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    setValueAsDecimal(Decimal::fromDouble(newValue), eventBehavior, exceptionState);
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RangeInputType::typeMismatchFor(const String& value) const
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    return !value.isEmpty() && !std::isfinite(parseToDoubleForNumberType(value));
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RangeInputType::supportsRequired() const
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)StepRange RangeInputType::createStepRange(AnyStepHandling anyStepHandling) const
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (rangeDefaultStep, rangeDefaultStepBase, rangeStepScaleFactor));
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
12209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    const Decimal stepBase = findStepBase(rangeDefaultStepBase);
123bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    const Decimal minimum = parseToNumber(element().fastGetAttribute(minAttr), rangeDefaultMinimum);
124bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    const Decimal maximum = ensureMaximum(parseToNumber(element().fastGetAttribute(maxAttr), rangeDefaultMaximum), minimum, rangeDefaultMaximum);
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
126bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element().fastGetAttribute(stepAttr));
12709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return StepRange(stepBase, minimum, maximum, step, stepDescription);
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RangeInputType::isSteppable() const
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RangeInputType::handleMouseDownEvent(MouseEvent* event)
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
137bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (element().isDisabledOrReadOnly())
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Node* targetNode = event->target()->toNode();
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (event->button() != LeftButton || !targetNode)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
143bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    ASSERT(element().shadow());
144bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (targetNode != element() && !targetNode->isDescendantOf(element().userAgentShadowRoot()))
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
146e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    SliderThumbElement* thumb = sliderThumbElement();
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (targetNode == thumb)
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    thumb->dragFrom(event->absoluteLocation());
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RangeInputType::handleTouchEvent(TouchEvent* event)
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
154bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (element().isDisabledOrReadOnly())
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1571e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    if (event->type() == EventTypeNames::touchend) {
1586f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        element().dispatchFormControlChangeEvent();
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        event->setDefaultHandled();
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TouchList* touches = event->targetTouches();
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (touches->length() == 1) {
165e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        sliderThumbElement()->setPositionFromPoint(touches->item(0)->absoluteLocation());
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        event->setDefaultHandled();
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RangeInputType::hasTouchEventHandler() const
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RangeInputType::handleKeydownEvent(KeyboardEvent* event)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
177bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (element().isDisabledOrReadOnly())
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const String& key = event->keyIdentifier();
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
182bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    const Decimal current = parseToNumberOrNaN(element().value());
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(current.isFinite());
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StepRange stepRange(createStepRange(RejectAny));
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: We can't use stepUp() for the step value "any". So, we increase
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // or decrease the value by 1/100 of the value range. Is it reasonable?
190bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    const Decimal step = equalIgnoringCase(element().fastGetAttribute(stepAttr), "any") ? (stepRange.maximum() - stepRange.minimum()) / 100 : stepRange.step();
1915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)    const Decimal bigStep = std::max((stepRange.maximum() - stepRange.minimum()) / 10, step);
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isVertical = false;
194bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (element().renderer()) {
195bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        ControlPart part = element().renderer()->style()->appearance();
196d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        isVertical = part == SliderVerticalPart;
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal newValue;
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (key == "Up")
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newValue = current + step;
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (key == "Down")
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newValue = current - step;
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (key == "Left")
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newValue = isVertical ? current + step : current - step;
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (key == "Right")
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newValue = isVertical ? current - step : current + step;
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (key == "PageUp")
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newValue = current + bigStep;
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (key == "PageDown")
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newValue = current - bigStep;
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (key == "Home")
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newValue = isVertical ? stepRange.maximum() : stepRange.minimum();
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else if (key == "End")
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newValue = isVertical ? stepRange.minimum() : stepRange.maximum();
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return; // Did not match any key binding.
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newValue = stepRange.clampValue(newValue);
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (newValue != current) {
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EventQueueScope scope;
223d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        TextFieldEventBehavior eventBehavior = DispatchInputAndChangeEvent;
2241fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch        setValueAsDecimal(newValue, eventBehavior, IGNORE_EXCEPTION);
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
226bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        if (AXObjectCache* cache = element().document().existingAXObjectCache())
227bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)            cache->postNotification(&element(), AXObjectCache::AXValueChanged, true);
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    event->setDefaultHandled();
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RangeInputType::createShadowSubtree()
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
235bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    ASSERT(element().shadow());
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
237bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    Document& document = element().document();
238d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    RefPtrWillBeRawPtr<HTMLDivElement> track = HTMLDivElement::create(document);
23909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    track->setShadowPseudoId(AtomicString("-webkit-slider-runnable-track", AtomicString::ConstructFromLiteral));
240e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    track->setAttribute(idAttr, ShadowElementNames::sliderTrack());
241e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    track->appendChild(SliderThumbElement::create(document));
242323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)    RefPtrWillBeRawPtr<HTMLElement> container = SliderContainerElement::create(document);
243e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    container->appendChild(track.release());
244bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    element().userAgentShadowRoot()->appendChild(container.release());
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
247591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochRenderObject* RangeInputType::createRenderer(RenderStyle*) const
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
249bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return new RenderSlider(&element());
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Decimal RangeInputType::parseToNumber(const String& src, const Decimal& defaultValue) const
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return parseToDecimalForNumberType(src, defaultValue);
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String RangeInputType::serialize(const Decimal& value) const
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!value.isFinite())
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return String();
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return serializeForNumberType(value);
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: Could share this with BaseClickableWithKeyInputType and BaseCheckableInputType if we had a common base class.
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RangeInputType::accessKeyAction(bool sendMouseEvents)
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InputType::accessKeyAction(sendMouseEvents);
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
269bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    element().dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
272e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)void RangeInputType::sanitizeValueInResponseToMinOrMaxAttributeChange()
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
274bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    if (element().hasDirtyValue())
275bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)        element().setValue(element().value());
276521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)
277e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    sliderThumbElement()->setPositionFromValue();
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RangeInputType::setValue(const String& value, bool valueChanged, TextFieldEventBehavior eventBehavior)
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InputType::setValue(value, valueChanged, eventBehavior);
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!valueChanged)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
287e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    sliderThumbElement()->setPositionFromValue();
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String RangeInputType::fallbackValue() const
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return serializeForNumberType(createStepRange(RejectAny).defaultValue());
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)String RangeInputType::sanitizeValue(const String& proposedValue) const
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    StepRange stepRange(createStepRange(RejectAny));
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const Decimal proposedNumericValue = parseToNumber(proposedValue, stepRange.defaultValue());
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return serializeForNumberType(stepRange.clampValue(proposedNumericValue));
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
302a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void RangeInputType::disabledAttributeChanged()
303a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
304a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    if (element().isDisabledFormControl())
305a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        sliderThumbElement()->stopDragging();
306a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
307a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RangeInputType::shouldRespectListAttribute()
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
310d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return true;
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
313e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)inline SliderThumbElement* RangeInputType::sliderThumbElement() const
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
315bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return toSliderThumbElement(element().userAgentShadowRoot()->getElementById(ShadowElementNames::sliderThumb()));
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
318e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)inline Element* RangeInputType::sliderTrackElement() const
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
320bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    return element().userAgentShadowRoot()->getElementById(ShadowElementNames::sliderTrack());
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RangeInputType::listAttributeTargetChanged()
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_tickMarkValuesDirty = true;
326e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)    Element* sliderTrackElement = this->sliderTrackElement();
327926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    if (sliderTrackElement->renderer())
3285d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        sliderTrackElement->renderer()->setNeedsLayoutAndFullPaintInvalidation();
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static bool decimalCompare(const Decimal& a, const Decimal& b)
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return a < b;
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RangeInputType::updateTickMarkValues()
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_tickMarkValuesDirty)
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_tickMarkValues.clear();
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_tickMarkValuesDirty = false;
342bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles)    HTMLDataListElement* dataList = element().dataList();
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!dataList)
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
3459e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)    RefPtrWillBeRawPtr<HTMLDataListOptionsCollection> options = dataList->options();
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_tickMarkValues.reserveCapacity(options->length());
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < options->length(); ++i) {
3489e12abdf8c3a23d52091ea54ebb6a04d327f9300Torne (Richard Coles)        HTMLOptionElement* optionElement = options->item(i);
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        String optionValue = optionElement->value();
35009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (!this->element().isValidValue(optionValue))
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        m_tickMarkValues.append(parseToNumber(optionValue, Decimal::nan()));
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_tickMarkValues.shrinkToFit();
3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    nonCopyingSort(m_tickMarkValues.begin(), m_tickMarkValues.end(), decimalCompare);
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Decimal RangeInputType::findClosestTickMarkValue(const Decimal& value)
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateTickMarkValues();
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_tickMarkValues.size())
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return Decimal::nan();
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t left = 0;
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t right = m_tickMarkValues.size();
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    size_t middle;
3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (true) {
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(left <= right);
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        middle = left + (right - left) / 2;
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!middle)
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (middle == m_tickMarkValues.size() - 1 && m_tickMarkValues[middle] < value) {
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            middle++;
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_tickMarkValues[middle - 1] <= value && m_tickMarkValues[middle] >= value)
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (m_tickMarkValues[middle] < value)
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            left = middle;
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            right = middle;
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const Decimal closestLeft = middle ? m_tickMarkValues[middle - 1] : Decimal::infinity(Decimal::Negative);
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const Decimal closestRight = middle != m_tickMarkValues.size() ? m_tickMarkValues[middle] : Decimal::infinity(Decimal::Positive);
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (closestRight - value < value - closestLeft)
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return closestRight;
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return closestLeft;
3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
391c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
392