void DateTimeNumericFieldElement::stepUp() { int newValue = roundUp(m_hasValue ? m_value + 1 : defaultValueForStepUp()); if (!m_range.isInRange(newValue)) newValue = roundUp(m_range.minimum); m_typeAheadBuffer.clear(); setValueAsInteger(newValue, DispatchEvent); }
void DateTimeNumericFieldElement::stepUp() { if (m_hasValue) setValueAsInteger(m_value == m_range.maximum ? m_range.minimum : clampValue(m_value + 1), DispatchEvent); else setValueAsInteger(defaultValueForStepUp(), DispatchEvent); }
void InputType::stepUpFromRenderer(int n) { // The differences from stepUp()/stepDown(): // // Difference 1: the current value // If the current value is not a number, including empty, the current value is assumed as 0. // * If 0 is in-range, and matches to step value // - The value should be the +step if n > 0 // - The value should be the -step if n < 0 // If -step or +step is out of range, new value should be 0. // * If 0 is smaller than the minimum value // - The value should be the minimum value for any n // * If 0 is larger than the maximum value // - The value should be the maximum value for any n // * If 0 is in-range, but not matched to step value // - The value should be the larger matched value nearest to 0 if n > 0 // e.g. <input type=number min=-100 step=3> -> 2 // - The value should be the smaler matched value nearest to 0 if n < 0 // e.g. <input type=number min=-100 step=3> -> -1 // As for date/datetime-local/month/time/week types, the current value is assumed as "the current local date/time". // As for datetime type, the current value is assumed as "the current date/time in UTC". // If the current value is smaller than the minimum value: // - The value should be the minimum value if n > 0 // - Nothing should happen if n < 0 // If the current value is larger than the maximum value: // - The value should be the maximum value if n < 0 // - Nothing should happen if n > 0 // // Difference 2: clamping steps // If the current value is not matched to step value: // - The value should be the larger matched value nearest to 0 if n > 0 // e.g. <input type=number value=3 min=-100 step=3> -> 5 // - The value should be the smaler matched value nearest to 0 if n < 0 // e.g. <input type=number value=3 min=-100 step=3> -> 2 // // n is assumed as -n if step < 0. ASSERT(isSteppable()); if (!isSteppable()) return; ASSERT(n); if (!n) return; StepRange stepRange(createStepRange(AnyIsDefaultStep)); // FIXME: Not any changes after stepping, even if it is an invalid value, may be better. // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "foo") if (!stepRange.hasStep()) return; EventQueueScope scope; const Decimal step = stepRange.step(); int sign; if (step > 0) sign = n; else if (step < 0) sign = -n; else sign = 0; String currentStringValue = element().value(); Decimal current = parseToNumberOrNaN(currentStringValue); if (!current.isFinite()) { current = defaultValueForStepUp(); const Decimal nextDiff = step * n; if (current < stepRange.minimum() - nextDiff) current = stepRange.minimum() - nextDiff; if (current > stepRange.maximum() - nextDiff) current = stepRange.maximum() - nextDiff; setValueAsDecimal(current, DispatchNoEvent, IGNORE_EXCEPTION); } if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > stepRange.maximum())) setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchInputAndChangeEvent, IGNORE_EXCEPTION); else { if (stepMismatch(element().value())) { ASSERT(!step.isZero()); const Decimal base = stepRange.stepBase(); Decimal newValue; if (sign < 0) newValue = base + ((current - base) / step).floor() * step; else if (sign > 0) newValue = base + ((current - base) / step).ceiling() * step; else newValue = current; if (newValue < stepRange.minimum()) newValue = stepRange.minimum(); if (newValue > stepRange.maximum()) newValue = stepRange.maximum(); setValueAsDecimal(newValue, n == 1 || n == -1 ? DispatchInputAndChangeEvent : DispatchNoEvent, IGNORE_EXCEPTION); if (n > 1) applyStep(n - 1, AnyIsDefaultStep, DispatchInputAndChangeEvent, IGNORE_EXCEPTION); else if (n < -1) applyStep(n + 1, AnyIsDefaultStep, DispatchInputAndChangeEvent, IGNORE_EXCEPTION); } else applyStep(n, AnyIsDefaultStep, DispatchInputAndChangeEvent, IGNORE_EXCEPTION); } }
void InputType::stepUpFromLayoutObject(int n) { // The only difference from stepUp()/stepDown() is the extra treatment // of the current value before applying the step: // // If the current value is not a number, including empty, the current value is assumed as 0. // * If 0 is in-range, and matches to step value // - The value should be the +step if n > 0 // - The value should be the -step if n < 0 // If -step or +step is out of range, new value should be 0. // * If 0 is smaller than the minimum value // - The value should be the minimum value for any n // * If 0 is larger than the maximum value // - The value should be the maximum value for any n // * If 0 is in-range, but not matched to step value // - The value should be the larger matched value nearest to 0 if n > 0 // e.g. <input type=number min=-100 step=3> -> 2 // - The value should be the smaler matched value nearest to 0 if n < 0 // e.g. <input type=number min=-100 step=3> -> -1 // As for date/datetime-local/month/time/week types, the current value is assumed as "the current local date/time". // As for datetime type, the current value is assumed as "the current date/time in UTC". // If the current value is smaller than the minimum value: // - The value should be the minimum value if n > 0 // - Nothing should happen if n < 0 // If the current value is larger than the maximum value: // - The value should be the maximum value if n < 0 // - Nothing should happen if n > 0 // // n is assumed as -n if step < 0. DCHECK(isSteppable()); if (!isSteppable()) return; DCHECK(n); if (!n) return; StepRange stepRange(createStepRange(AnyIsDefaultStep)); // FIXME: Not any changes after stepping, even if it is an invalid value, may be better. // (e.g. Stepping-up for <input type="number" value="foo" step="any" /> => "foo") if (!stepRange.hasStep()) return; EventQueueScope scope; const Decimal step = stepRange.step(); int sign; if (step > 0) sign = n; else if (step < 0) sign = -n; else sign = 0; Decimal current = parseToNumberOrNaN(element().value()); if (!current.isFinite()) { current = defaultValueForStepUp(); const Decimal nextDiff = step * n; if (current < stepRange.minimum() - nextDiff) current = stepRange.minimum() - nextDiff; if (current > stepRange.maximum() - nextDiff) current = stepRange.maximum() - nextDiff; setValueAsDecimal(current, DispatchNoEvent, IGNORE_EXCEPTION); } if ((sign > 0 && current < stepRange.minimum()) || (sign < 0 && current > stepRange.maximum())) { setValueAsDecimal(sign > 0 ? stepRange.minimum() : stepRange.maximum(), DispatchChangeEvent, IGNORE_EXCEPTION); return; } if ((sign > 0 && current >= stepRange.maximum()) || (sign < 0 && current <= stepRange.minimum())) return; applyStep(current, n, AnyIsDefaultStep, DispatchChangeEvent, IGNORE_EXCEPTION); }