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 "HTMLNames.h" 35#include "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 46namespace WebCore { 47 48using namespace HTMLNames; 49 50static const int timeDefaultStep = 60; 51static const int timeDefaultStepBase = 0; 52static const int timeStepScaleFactor = 1000; 53 54TimeInputType::TimeInputType(HTMLInputElement& element) 55 : BaseTimeInputType(element) 56{ 57} 58 59PassRefPtr<InputType> TimeInputType::create(HTMLInputElement& element) 60{ 61 return adoptRef(new TimeInputType(element)); 62} 63 64void TimeInputType::countUsage() 65{ 66 countUsageIfVisible(UseCounter::InputTypeTime); 67} 68 69const AtomicString& TimeInputType::formControlType() const 70{ 71 return InputTypeNames::time; 72} 73 74Decimal 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 89StepRange 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, 0, Decimal::fromDouble(DateComponents::minimumTime()), Decimal::fromDouble(DateComponents::maximumTime()), stepDescription); 94} 95 96bool 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 103bool TimeInputType::setMillisecondToDateComponents(double value, DateComponents* date) const 104{ 105 ASSERT(date); 106 return date->setMillisecondsSinceMidnight(value); 107} 108 109bool TimeInputType::isTimeField() const 110{ 111 return true; 112} 113 114#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) 115 116String 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 128String 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 148void 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 163bool 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