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