Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 2010 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "BaseDateAndTimeInputType.h"
     33 
     34 #include "DateComponents.h"
     35 #include "HTMLInputElement.h"
     36 #include "HTMLNames.h"
     37 #include "KeyboardEvent.h"
     38 #include <limits>
     39 #include <wtf/CurrentTime.h>
     40 #include <wtf/DateMath.h>
     41 #include <wtf/MathExtras.h>
     42 #include <wtf/PassOwnPtr.h>
     43 #include <wtf/text/WTFString.h>
     44 
     45 namespace WebCore {
     46 
     47 using namespace HTMLNames;
     48 using namespace std;
     49 
     50 static const double msecPerMinute = 60 * 1000;
     51 static const double msecPerSecond = 1000;
     52 
     53 double BaseDateAndTimeInputType::valueAsDate() const
     54 {
     55     return parseToDouble(element()->value(), DateComponents::invalidMilliseconds());
     56 }
     57 
     58 void BaseDateAndTimeInputType::setValueAsDate(double value, ExceptionCode&) const
     59 {
     60     element()->setValue(serialize(value));
     61 }
     62 
     63 double BaseDateAndTimeInputType::valueAsNumber() const
     64 {
     65     return parseToDouble(element()->value(), numeric_limits<double>::quiet_NaN());
     66 }
     67 
     68 void BaseDateAndTimeInputType::setValueAsNumber(double newValue, ExceptionCode&) const
     69 {
     70     element()->setValue(serialize(newValue));
     71 }
     72 
     73 bool BaseDateAndTimeInputType::typeMismatchFor(const String& value) const
     74 {
     75     return !value.isEmpty() && !parseToDateComponents(value, 0);
     76 }
     77 
     78 bool BaseDateAndTimeInputType::typeMismatch() const
     79 {
     80     return typeMismatchFor(element()->value());
     81 }
     82 
     83 bool BaseDateAndTimeInputType::rangeUnderflow(const String& value) const
     84 {
     85     const double nan = numeric_limits<double>::quiet_NaN();
     86     double doubleValue = parseToDouble(value, nan);
     87     return isfinite(doubleValue) && doubleValue < minimum();
     88 }
     89 
     90 bool BaseDateAndTimeInputType::rangeOverflow(const String& value) const
     91 {
     92     const double nan = numeric_limits<double>::quiet_NaN();
     93     double doubleValue = parseToDouble(value, nan);
     94     return isfinite(doubleValue) && doubleValue > maximum();
     95 }
     96 
     97 bool BaseDateAndTimeInputType::supportsRangeLimitation() const
     98 {
     99     return true;
    100 }
    101 
    102 double BaseDateAndTimeInputType::defaultValueForStepUp() const
    103 {
    104     double ms = currentTimeMS();
    105     double utcOffset = calculateUTCOffset();
    106     double dstOffset = calculateDSTOffset(ms, utcOffset);
    107     int offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute);
    108     return ms + (offset * msPerMinute);
    109 }
    110 
    111 bool BaseDateAndTimeInputType::stepMismatch(const String& value, double step) const
    112 {
    113     const double nan = numeric_limits<double>::quiet_NaN();
    114     double doubleValue = parseToDouble(value, nan);
    115     doubleValue = fabs(doubleValue - stepBase());
    116     if (!isfinite(doubleValue))
    117         return false;
    118     ASSERT(round(doubleValue) == doubleValue);
    119     ASSERT(round(step) == step);
    120     return fmod(doubleValue, step);
    121 }
    122 
    123 double BaseDateAndTimeInputType::stepBase() const
    124 {
    125     return parseToDouble(element()->fastGetAttribute(minAttr), defaultStepBase());
    126 }
    127 
    128 void BaseDateAndTimeInputType::handleKeydownEvent(KeyboardEvent* event)
    129 {
    130     handleKeydownEventForSpinButton(event);
    131     if (!event->defaultHandled())
    132         TextFieldInputType::handleKeydownEvent(event);
    133 }
    134 
    135 void BaseDateAndTimeInputType::handleWheelEvent(WheelEvent* event)
    136 {
    137     handleWheelEventForSpinButton(event);
    138 }
    139 
    140 double BaseDateAndTimeInputType::parseToDouble(const String& src, double defaultValue) const
    141 {
    142     DateComponents date;
    143     if (!parseToDateComponents(src, &date))
    144         return defaultValue;
    145     double msec = date.millisecondsSinceEpoch();
    146     ASSERT(isfinite(msec));
    147     return msec;
    148 }
    149 
    150 bool BaseDateAndTimeInputType::parseToDateComponents(const String& source, DateComponents* out) const
    151 {
    152     if (source.isEmpty())
    153         return false;
    154     DateComponents ignoredResult;
    155     if (!out)
    156         out = &ignoredResult;
    157     return parseToDateComponentsInternal(source.characters(), source.length(), out);
    158 }
    159 
    160 String BaseDateAndTimeInputType::serialize(double value) const
    161 {
    162     if (!isfinite(value))
    163         return String();
    164     DateComponents date;
    165     if (!setMillisecondToDateComponents(value, &date))
    166         return String();
    167     double step;
    168     if (!element()->getAllowedValueStep(&step))
    169         return date.toString();
    170     if (!fmod(step, msecPerMinute))
    171         return date.toString(DateComponents::None);
    172     if (!fmod(step, msecPerSecond))
    173         return date.toString(DateComponents::Second);
    174     return date.toString(DateComponents::Millisecond);
    175 }
    176 
    177 bool BaseDateAndTimeInputType::hasSpinButton()
    178 {
    179     return true;
    180 }
    181 
    182 } // namespace WebCore
    183