Home | History | Annotate | Download | only in forms
      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 "core/html/forms/MonthInputType.h"
     33 
     34 #include "core/HTMLNames.h"
     35 #include "core/InputTypeNames.h"
     36 #include "core/html/HTMLInputElement.h"
     37 #include "core/html/forms/DateTimeFieldsState.h"
     38 #include "platform/DateComponents.h"
     39 #include "platform/text/PlatformLocale.h"
     40 #include "wtf/CurrentTime.h"
     41 #include "wtf/DateMath.h"
     42 #include "wtf/MathExtras.h"
     43 #include "wtf/PassOwnPtr.h"
     44 #include "wtf/text/WTFString.h"
     45 
     46 namespace blink {
     47 
     48 using namespace HTMLNames;
     49 
     50 static const int monthDefaultStep = 1;
     51 static const int monthDefaultStepBase = 0;
     52 static const int monthStepScaleFactor = 1;
     53 
     54 PassRefPtrWillBeRawPtr<InputType> MonthInputType::create(HTMLInputElement& element)
     55 {
     56     return adoptRefWillBeNoop(new MonthInputType(element));
     57 }
     58 
     59 void MonthInputType::countUsage()
     60 {
     61     countUsageIfVisible(UseCounter::InputTypeMonth);
     62 }
     63 
     64 const AtomicString& MonthInputType::formControlType() const
     65 {
     66     return InputTypeNames::month;
     67 }
     68 
     69 double MonthInputType::valueAsDate() const
     70 {
     71     DateComponents date;
     72     if (!parseToDateComponents(element().value(), &date))
     73         return DateComponents::invalidMilliseconds();
     74     double msec = date.millisecondsSinceEpoch();
     75     ASSERT(std::isfinite(msec));
     76     return msec;
     77 }
     78 
     79 String MonthInputType::serializeWithMilliseconds(double value) const
     80 {
     81     DateComponents date;
     82     if (!date.setMillisecondsSinceEpochForMonth(value))
     83         return String();
     84     return serializeWithComponents(date);
     85 }
     86 
     87 Decimal MonthInputType::defaultValueForStepUp() const
     88 {
     89     DateComponents date;
     90     date.setMillisecondsSinceEpochForMonth(convertToLocalTime(currentTimeMS()));
     91     double months = date.monthsSinceEpoch();
     92     ASSERT(std::isfinite(months));
     93     return Decimal::fromDouble(months);
     94 }
     95 
     96 StepRange MonthInputType::createStepRange(AnyStepHandling anyStepHandling) const
     97 {
     98     DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (monthDefaultStep, monthDefaultStepBase, monthStepScaleFactor, StepRange::ParsedStepValueShouldBeInteger));
     99 
    100     return InputType::createStepRange(anyStepHandling, Decimal::fromDouble(monthDefaultStepBase), Decimal::fromDouble(DateComponents::minimumMonth()), Decimal::fromDouble(DateComponents::maximumMonth()), stepDescription);
    101 }
    102 
    103 Decimal MonthInputType::parseToNumber(const String& src, const Decimal& defaultValue) const
    104 {
    105     DateComponents date;
    106     if (!parseToDateComponents(src, &date))
    107         return defaultValue;
    108     double months = date.monthsSinceEpoch();
    109     ASSERT(std::isfinite(months));
    110     return Decimal::fromDouble(months);
    111 }
    112 
    113 bool MonthInputType::parseToDateComponentsInternal(const String& string, DateComponents* out) const
    114 {
    115     ASSERT(out);
    116     unsigned end;
    117     return out->parseMonth(string, 0, end) && end == string.length();
    118 }
    119 
    120 bool MonthInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
    121 {
    122     ASSERT(date);
    123     return date->setMonthsSinceEpoch(value);
    124 }
    125 
    126 bool MonthInputType::canSetSuggestedValue()
    127 {
    128     return true;
    129 }
    130 
    131 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
    132 String MonthInputType::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const
    133 {
    134     if (!dateTimeFieldsState.hasMonth() || !dateTimeFieldsState.hasYear())
    135         return emptyString();
    136     return String::format("%04u-%02u", dateTimeFieldsState.year(), dateTimeFieldsState.month());
    137 }
    138 
    139 void MonthInputType::setupLayoutParameters(DateTimeEditElement::LayoutParameters& layoutParameters, const DateComponents& date) const
    140 {
    141     layoutParameters.dateTimeFormat = layoutParameters.locale.monthFormat();
    142     layoutParameters.fallbackDateTimeFormat = "yyyy-MM";
    143     if (!parseToDateComponents(element().fastGetAttribute(minAttr), &layoutParameters.minimum))
    144         layoutParameters.minimum = DateComponents();
    145     if (!parseToDateComponents(element().fastGetAttribute(maxAttr), &layoutParameters.maximum))
    146         layoutParameters.maximum = DateComponents();
    147     layoutParameters.placeholderForMonth = "--";
    148     layoutParameters.placeholderForYear = "----";
    149 }
    150 
    151 bool MonthInputType::isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const
    152 {
    153     return hasYear && hasMonth;
    154 }
    155 #endif
    156 } // namespace blink
    157