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 WebCore { 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 double current = currentTimeMS(); 77 double utcOffset = calculateUTCOffset(); 78 double dstOffset = calculateDSTOffset(current, utcOffset); 79 int offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute); 80 current += offset * msPerMinute; 81 82 DateComponents date; 83 date.setMillisecondsSinceMidnight(current); 84 double milliseconds = date.millisecondsSinceEpoch(); 85 ASSERT(std::isfinite(milliseconds)); 86 return Decimal::fromDouble(milliseconds); 87 } 88 89 StepRange TimeInputType::createStepRange(AnyStepHandling anyStepHandling) const 90 { 91 DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (timeDefaultStep, timeDefaultStepBase, timeStepScaleFactor, StepRange::ScaledStepValueShouldBeInteger)); 92 93 return InputType::createStepRange(anyStepHandling, timeDefaultStepBase, Decimal::fromDouble(DateComponents::minimumTime()), Decimal::fromDouble(DateComponents::maximumTime()), stepDescription); 94 } 95 96 bool TimeInputType::parseToDateComponentsInternal(const String& string, DateComponents* out) const 97 { 98 ASSERT(out); 99 unsigned end; 100 return out->parseTime(string, 0, end) && end == string.length(); 101 } 102 103 bool TimeInputType::setMillisecondToDateComponents(double value, DateComponents* date) const 104 { 105 ASSERT(date); 106 return date->setMillisecondsSinceMidnight(value); 107 } 108 109 bool TimeInputType::isTimeField() const 110 { 111 return true; 112 } 113 114 #if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 115 116 String TimeInputType::localizeValue(const String& proposedValue) const 117 { 118 DateComponents date; 119 if (!parseToDateComponents(proposedValue, &date)) 120 return proposedValue; 121 122 Locale::FormatType formatType = shouldHaveSecondField(date) ? Locale::FormatTypeMedium : Locale::FormatTypeShort; 123 124 String localized = element().locale().formatDateTime(date, formatType); 125 return localized.isEmpty() ? proposedValue : localized; 126 } 127 128 String TimeInputType::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const 129 { 130 if (!dateTimeFieldsState.hasHour() || !dateTimeFieldsState.hasMinute() || !dateTimeFieldsState.hasAMPM()) 131 return emptyString(); 132 if (dateTimeFieldsState.hasMillisecond() && dateTimeFieldsState.millisecond()) { 133 return String::format("%02u:%02u:%02u.%03u", 134 dateTimeFieldsState.hour23(), 135 dateTimeFieldsState.minute(), 136 dateTimeFieldsState.hasSecond() ? dateTimeFieldsState.second() : 0, 137 dateTimeFieldsState.millisecond()); 138 } 139 if (dateTimeFieldsState.hasSecond() && dateTimeFieldsState.second()) { 140 return String::format("%02u:%02u:%02u", 141 dateTimeFieldsState.hour23(), 142 dateTimeFieldsState.minute(), 143 dateTimeFieldsState.second()); 144 } 145 return String::format("%02u:%02u", dateTimeFieldsState.hour23(), dateTimeFieldsState.minute()); 146 } 147 148 void TimeInputType::setupLayoutParameters(DateTimeEditElement::LayoutParameters& layoutParameters, const DateComponents& date) const 149 { 150 if (shouldHaveSecondField(date)) { 151 layoutParameters.dateTimeFormat = layoutParameters.locale.timeFormat(); 152 layoutParameters.fallbackDateTimeFormat = "HH:mm:ss"; 153 } else { 154 layoutParameters.dateTimeFormat = layoutParameters.locale.shortTimeFormat(); 155 layoutParameters.fallbackDateTimeFormat = "HH:mm"; 156 } 157 if (!parseToDateComponents(element().fastGetAttribute(minAttr), &layoutParameters.minimum)) 158 layoutParameters.minimum = DateComponents(); 159 if (!parseToDateComponents(element().fastGetAttribute(maxAttr), &layoutParameters.maximum)) 160 layoutParameters.maximum = DateComponents(); 161 } 162 163 bool TimeInputType::isValidFormat(bool hasYear, bool hasMonth, bool hasWeek, bool hasDay, bool hasAMPM, bool hasHour, bool hasMinute, bool hasSecond) const 164 { 165 return hasHour && hasMinute && hasAMPM; 166 } 167 #endif 168 169 } // namespace WebCore 170