/* * Copyright (C) 2010 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "BaseDateAndTimeInputType.h" #include "DateComponents.h" #include "HTMLInputElement.h" #include "HTMLNames.h" #include "KeyboardEvent.h" #include #include #include #include #include #include namespace WebCore { using namespace HTMLNames; using namespace std; static const double msecPerMinute = 60 * 1000; static const double msecPerSecond = 1000; double BaseDateAndTimeInputType::valueAsDate() const { return parseToDouble(element()->value(), DateComponents::invalidMilliseconds()); } void BaseDateAndTimeInputType::setValueAsDate(double value, ExceptionCode&) const { element()->setValue(serialize(value)); } double BaseDateAndTimeInputType::valueAsNumber() const { return parseToDouble(element()->value(), numeric_limits::quiet_NaN()); } void BaseDateAndTimeInputType::setValueAsNumber(double newValue, ExceptionCode&) const { element()->setValue(serialize(newValue)); } bool BaseDateAndTimeInputType::typeMismatchFor(const String& value) const { return !value.isEmpty() && !parseToDateComponents(value, 0); } bool BaseDateAndTimeInputType::typeMismatch() const { return typeMismatchFor(element()->value()); } bool BaseDateAndTimeInputType::rangeUnderflow(const String& value) const { const double nan = numeric_limits::quiet_NaN(); double doubleValue = parseToDouble(value, nan); return isfinite(doubleValue) && doubleValue < minimum(); } bool BaseDateAndTimeInputType::rangeOverflow(const String& value) const { const double nan = numeric_limits::quiet_NaN(); double doubleValue = parseToDouble(value, nan); return isfinite(doubleValue) && doubleValue > maximum(); } bool BaseDateAndTimeInputType::supportsRangeLimitation() const { return true; } double BaseDateAndTimeInputType::defaultValueForStepUp() const { double ms = currentTimeMS(); double utcOffset = calculateUTCOffset(); double dstOffset = calculateDSTOffset(ms, utcOffset); int offset = static_cast((utcOffset + dstOffset) / msPerMinute); return ms + (offset * msPerMinute); } bool BaseDateAndTimeInputType::stepMismatch(const String& value, double step) const { const double nan = numeric_limits::quiet_NaN(); double doubleValue = parseToDouble(value, nan); doubleValue = fabs(doubleValue - stepBase()); if (!isfinite(doubleValue)) return false; ASSERT(round(doubleValue) == doubleValue); ASSERT(round(step) == step); return fmod(doubleValue, step); } double BaseDateAndTimeInputType::stepBase() const { return parseToDouble(element()->fastGetAttribute(minAttr), defaultStepBase()); } void BaseDateAndTimeInputType::handleKeydownEvent(KeyboardEvent* event) { handleKeydownEventForSpinButton(event); if (!event->defaultHandled()) TextFieldInputType::handleKeydownEvent(event); } void BaseDateAndTimeInputType::handleWheelEvent(WheelEvent* event) { handleWheelEventForSpinButton(event); } double BaseDateAndTimeInputType::parseToDouble(const String& src, double defaultValue) const { DateComponents date; if (!parseToDateComponents(src, &date)) return defaultValue; double msec = date.millisecondsSinceEpoch(); ASSERT(isfinite(msec)); return msec; } bool BaseDateAndTimeInputType::parseToDateComponents(const String& source, DateComponents* out) const { if (source.isEmpty()) return false; DateComponents ignoredResult; if (!out) out = &ignoredResult; return parseToDateComponentsInternal(source.characters(), source.length(), out); } String BaseDateAndTimeInputType::serialize(double value) const { if (!isfinite(value)) return String(); DateComponents date; if (!setMillisecondToDateComponents(value, &date)) return String(); double step; if (!element()->getAllowedValueStep(&step)) return date.toString(); if (!fmod(step, msecPerMinute)) return date.toString(DateComponents::None); if (!fmod(step, msecPerSecond)) return date.toString(DateComponents::Second); return date.toString(DateComponents::Millisecond); } bool BaseDateAndTimeInputType::hasSpinButton() { return true; } } // namespace WebCore