339
340static bool decimalCompare(const Decimal& a, const Decimal& b)
341{
342 return a < b;
343}
344
345void RangeInputType::updateTickMarkValues()
346{
347 if (!m_tickMarkValuesDirty)
348 return;
349 m_tickMarkValues.clear();
350 m_tickMarkValuesDirty = false;
351 HTMLDataListElement* dataList = element()->dataList();
352 if (!dataList)
353 return;
354 RefPtr<HTMLCollection> options = dataList->options();
355 m_tickMarkValues.reserveCapacity(options->length());
356 StepRange stepRange(createStepRange(RejectAny));
357 for (unsigned i = 0; i < options->length(); ++i) {
358 Node* node = options->item(i);
359 HTMLOptionElement* optionElement = toHTMLOptionElement(node);
360 String optionValue = optionElement->value();
361 if (!element()->isValidValue(optionValue))
362 continue;
363 m_tickMarkValues.append(parseToNumber(optionValue, stepRange.defaultValue()));
364 }
365 m_tickMarkValues.shrinkToFit();
366 nonCopyingSort(m_tickMarkValues.begin(), m_tickMarkValues.end(), decimalCompare);
367}
368
369Decimal RangeInputType::findClosestTickMarkValue(const Decimal& value)
370{
371 updateTickMarkValues();
372 if (!m_tickMarkValues.size())
373 return Decimal::nan();
374
375 size_t left = 0;
376 size_t right = m_tickMarkValues.size();
377 size_t middle;
378 while (true) {
379 ASSERT(left <= right);
380 middle = left + (right - left) / 2;
381 if (!middle)
382 break;
383 if (middle == m_tickMarkValues.size() - 1 && m_tickMarkValues[middle] < value) {
384 middle++;
385 break;
386 }
387 if (m_tickMarkValues[middle - 1] <= value && m_tickMarkValues[middle] >= value)
388 break;
389
390 if (m_tickMarkValues[middle] < value)
391 left = middle;
392 else
393 right = middle;
394 }
395 const Decimal closestLeft = middle ? m_tickMarkValues[middle - 1] : Decimal::infinity(Decimal::Negative);
396 const Decimal closestRight = middle != m_tickMarkValues.size() ? m_tickMarkValues[middle] : Decimal::infinity(Decimal::Positive);
397 if (closestRight - value < value - closestLeft)
398 return closestRight;
399 return closestLeft;
400}