void SliderThumbElement::setPositionFromPoint(const IntPoint& point) { HTMLInputElement* input = hostInput(); ASSERT(input); if (!input->renderer() || !renderer()) return; IntPoint offset = roundedIntPoint(input->renderer()->absoluteToLocal(point, false, true)); RenderStyle* sliderStyle = input->renderer()->style(); bool isVertical = sliderStyle->appearance() == SliderVerticalPart || sliderStyle->appearance() == MediaVolumeSliderPart; int trackSize; int position; int currentPosition; if (isVertical) { trackSize = input->renderBox()->contentHeight() - renderBox()->height(); position = offset.y() - renderBox()->height() / 2; currentPosition = renderBox()->y() - input->renderBox()->contentBoxRect().y(); } else { trackSize = input->renderBox()->contentWidth() - renderBox()->width(); position = offset.x() - renderBox()->width() / 2; currentPosition = renderBox()->x() - input->renderBox()->contentBoxRect().x(); } position = max(0, min(position, trackSize)); if (position == currentPosition) return; StepRange range(input); double fraction = static_cast<double>(position) / trackSize; if (isVertical) fraction = 1 - fraction; double value = range.clampValue(range.valueFromProportion(fraction)); // FIXME: This is no longer being set from renderer. Consider updating the method name. input->setValueFromRenderer(serializeForNumberType(value)); renderer()->setNeedsLayout(true); input->dispatchFormControlChangeEvent(); }
void RenderSlider::setValueForPosition(int position) { if (!m_thumb || !m_thumb->renderer()) return; HTMLInputElement* element = static_cast<HTMLInputElement*>(node()); // Calculate the new value based on the position, and send it to the element. StepRange range(element); double fraction = static_cast<double>(position) / trackSize(); if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) fraction = 1 - fraction; double value = range.clampValue(range.valueFromProportion(fraction)); element->setValueFromRenderer(serializeForNumberType(value)); // Also update the position if appropriate. if (position != currentPosition()) { setNeedsLayout(true); // FIXME: It seems like this could send extra change events if the same value is set // multiple times with no layout in between. element->dispatchFormControlChangeEvent(); } }
String NumberInputType::serialize(const Decimal& value) const { if (!value.isFinite()) return String(); return serializeForNumberType(value); }
String RangeInputType::sanitizeValue(const String& proposedValue) const { StepRange stepRange(createStepRange(RejectAny)); const Decimal proposedNumericValue = parseToNumber(proposedValue, stepRange.defaultValue()); return serializeForNumberType(stepRange.clampValue(proposedNumericValue)); }
String RangeInputType::fallbackValue() const { return serializeForNumberType(createStepRange(RejectAny).defaultValue()); }
void NumberInputType::setValueAsDecimal(const Decimal& newValue, TextFieldEventBehavior eventBehavior, ExceptionState& exceptionState) const { element().setValue(serializeForNumberType(newValue), eventBehavior); }
void SliderThumbElement::setPositionFromPoint(const LayoutPoint& point) { HTMLInputElement* input(hostInput()); Element* trackElement = input->userAgentShadowRoot()->getElementById( ShadowElementNames::sliderTrack()); if (!input->layoutObject() || !layoutBox() || !trackElement->layoutBox()) return; LayoutPoint offset = LayoutPoint( input->layoutObject()->absoluteToLocal(FloatPoint(point), UseTransforms)); bool isVertical = hasVerticalAppearance(input); bool isLeftToRightDirection = layoutBox()->style()->isLeftToRightDirection(); LayoutUnit trackSize; LayoutUnit position; LayoutUnit currentPosition; // We need to calculate currentPosition from absolute points becaue the // layoutObject for this node is usually on a layer and layoutBox()->x() and // y() are unusable. // FIXME: This should probably respect transforms. LayoutPoint absoluteThumbOrigin = layoutBox()->absoluteBoundingBoxRectIgnoringTransforms().location(); LayoutPoint absoluteSliderContentOrigin = LayoutPoint(input->layoutObject()->localToAbsolute()); IntRect trackBoundingBox = trackElement->layoutObject()->absoluteBoundingBoxRectIgnoringTransforms(); IntRect inputBoundingBox = input->layoutObject()->absoluteBoundingBoxRectIgnoringTransforms(); if (isVertical) { trackSize = trackElement->layoutBox()->contentHeight() - layoutBox()->size().height(); position = offset.y() - layoutBox()->size().height() / 2 - trackBoundingBox.y() + inputBoundingBox.y() - layoutBox()->marginBottom(); currentPosition = absoluteThumbOrigin.y() - absoluteSliderContentOrigin.y(); } else { trackSize = trackElement->layoutBox()->contentWidth() - layoutBox()->size().width(); position = offset.x() - layoutBox()->size().width() / 2 - trackBoundingBox.x() + inputBoundingBox.x(); position -= isLeftToRightDirection ? layoutBox()->marginLeft() : layoutBox()->marginRight(); currentPosition = absoluteThumbOrigin.x() - absoluteSliderContentOrigin.x(); } position = std::min(position, trackSize).clampNegativeToZero(); const Decimal ratio = Decimal::fromDouble(static_cast<double>(position) / trackSize); const Decimal fraction = isVertical || !isLeftToRightDirection ? Decimal(1) - ratio : ratio; StepRange stepRange(input->createStepRange(RejectAny)); Decimal value = stepRange.clampValue(stepRange.valueFromProportion(fraction)); Decimal closest = input->findClosestTickMarkValue(value); if (closest.isFinite()) { double closestFraction = stepRange.proportionFromValue(closest).toDouble(); double closestRatio = isVertical || !isLeftToRightDirection ? 1.0 - closestFraction : closestFraction; LayoutUnit closestPosition(trackSize * closestRatio); const LayoutUnit snappingThreshold(5); if ((closestPosition - position).abs() <= snappingThreshold) value = closest; } String valueString = serializeForNumberType(value); if (valueString == input->value()) return; // FIXME: This is no longer being set from renderer. Consider updating the // method name. input->setValueFromRenderer(valueString); if (layoutObject()) layoutObject()->setNeedsLayoutAndFullPaintInvalidation( LayoutInvalidationReason::SliderValueChanged); }
String NumberInputType::serialize(double value) const { if (!isfinite(value)) return String(); return serializeForNumberType(value); }