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/TimeInputType.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 timeDefaultStep = 60; 51 static const int timeDefaultStepBase = 0; 52 static const int timeStepScaleFactor = 1000; 53 54 TimeInputType::TimeInputType(HTMLInputElement& element) 55 : BaseTimeInputType(element) 56 { 57 } 58 59 PassRefPtrWillBeRawPtr<InputType> TimeInputType::create(HTMLInputElement& element) 60 { 61 return adoptRefWillBeNoop(new TimeInputType(element)); 62 } 63 64 void TimeInputType::countUsage() 65 { 66 countUsageIfVisible(UseCounter::InputTypeTime); 67 } 68 69 const AtomicString& TimeInputType::formControlType() const 70 { 71 return InputTypeNames::time; 72 } 73 74 Decimal TimeInputType::defaultValueForStepUp() const 75 { 76 DateComponents date; 77 date.setMillisecondsSinceMidnight(convertToLocalTime(currentTimeMS())); 78 double milliseconds = date.millisecondsSinceEpoch(); 79 ASSERT(std::isfinite(milliseconds)); 80 return Decimal::fromDouble(milliseconds); 81 } 82 83 StepRange TimeInputType::createStepRange(AnyStepHandling anyStepHandling) const 84 { 85 DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (timeDefaultStep, timeDefaultStepBase, timeStepScaleFactor, StepRange::ScaledStepValueShouldBeInteger)); 86 87 return InputType::createStepRange(anyStepHandling, timeDefaultStepBase, Decimal::fromDouble(DateComponents::minimumTime()), Decimal::fromDouble(DateComponents::maximumTime()), stepDescription); 88 } 89 90 bool TimeInputType::parseToDateComponentsInternal(const String& string, DateComponents* out) const 91 { 92 ASSERT(out); 93 unsigned end; 94 return out->parseTime(string, 0, end) && end == string.length(); 95 } 96 97 bool TimeInputType::setMillisecondToDateComponents(double value, DateComponents* date) const 98 { 99 ASSERT(date); 100 return date->setMillisecondsSinceMidnight(value); 101 } 102 103 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 104 105 String TimeInputType::localizeValue(const String& proposedValue) const 106 { 107 DateComponents date; 108 if (!parseToDateComponents(proposedValue, &date)) 109 return proposedValue; 110 111 Locale::FormatType formatType = shouldHaveSecondField(date) ? Locale::FormatTypeMedium : Locale::FormatTypeShort; 112 113 String localized = element().locale().formatDateTime(date, formatType); 114 return localized.isEmpty() ? proposedValue : localized; 115 } 116 117 String TimeInputType::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const 118 { 119 if (!dateTimeFieldsState.hasHour() || !dateTimeFieldsState.hasMinute() || !dateTimeFieldsState.hasAMPM()) 120 return emptyString(); 121 if (dateTimeFieldsState.hasMillisecond() && dateTimeFieldsState.millisecond()) { 122 return String::format("%02u:%02u:%02u.%03u", 123 dateTimeFieldsState.hour23(), 124 dateTimeFieldsState.minute(), 125 dateTimeFieldsState.hasSecond() ? dateTimeFieldsState.second() : 0, 126 dateTimeFieldsState.millisecond()); 127 } 128 if (dateTimeFieldsState.hasSecond() && dateTimeFieldsState.second()) { 129 return String::format("%02u:%02u:%02u", 130 dateTimeFieldsState.hour23(), 131 dateTimeFieldsState.minute(), 132 dateTimeFieldsState.second()); 133 } 134 return String::format("%02u:%02u", dateTimeFieldsState.hour23(), dateTimeFieldsState.minute()); 135 } 136 137 void TimeInputType::setupLayoutParameters(DateTimeEditElement::LayoutParameters& layoutParameters, const DateComponents& date) const 138 { 139 if (shouldHaveSecondField(date)) { 140 layoutParameters.dateTimeFormat = layoutParameters.locale.timeFormat(); 141 layoutParameters.fallbackDateTimeFormat = "HH:mm:ss"; 142 } else { 143 layoutParameters.dateTimeFormat = layoutParameters.locale.shortTimeFormat(); 144 layoutParameters.fallbackDateTimeFormat = "HH:mm"; 145 } 146 if (!parseToDateComponents(element().fastGetAttribute(minAttr), &layoutParameters.minimum)) 147 layoutParameters.minimum = DateComponents(); 148 if (!parseToDateComponents(element().fastGetAttribute(maxAttr), &layoutParameters.maximum)) 149 layoutParameters.maximum = DateComponents(); 150 } 151 152 bool TimeInputType::isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const 153 { 154 return hasHour && hasMinute && hasAMPM; 155 } 156 #endif 157 158 } // namespace blink 159