Пример #1
0
void InputElement::updateValueIfNeeded(InputElementData& data)
{
    String oldValue = data.value();
    String newValue = data.inputElement()->constrainValue(oldValue);
    if (newValue != oldValue)
        data.inputElement()->setValue(newValue);
}
Пример #2
0
void InputElement::parseSizeAttribute(InputElementData& data, MappedAttribute* attribute)
{
    data.setSize(attribute->isNull() ? InputElement::s_defaultSize : attribute->value().toInt());

    if (RenderObject* renderer = data.element()->renderer())
        renderer->setNeedsLayoutAndPrefWidthsRecalc();
}
Пример #3
0
void InputElement::aboutToUnload(InputElementData& data, Document* document)
{
    if (!data.inputElement()->isTextField() || !data.element()->focused() || !document->frame())
        return;

    document->frame()->textFieldDidEndEditing(data.element());
}
Пример #4
0
void InputElement::updateSelectionRange(InputElementData& data, int start, int end)
{
    if (!data.inputElement()->isTextField())
        return;

    if (RenderTextControl* renderer = toRenderTextControl(data.element()->renderer()))
        renderer->setSelectionRange(start, end);
}
Пример #5
0
void InputElement::dispatchFocusEvent(InputElementData& data, Document* document)
{
    if (!data.inputElement()->isTextField())
        return;

    updatePlaceholderVisibility(data, document);

    if (data.inputElement()->isPasswordField() && document->frame())
        document->setUseSecureKeyboardEntryWhenActive(true);
}
Пример #6
0
String InputElement::validateInputMask(InputElementData& data, String& inputMask)
{
    inputMask.replace("\\\\", "\\");

    bool isValid = true;
    bool hasWildcard = false;
    unsigned escapeCharCount = 0;
    unsigned maskLength = inputMask.length();
    UChar formatCode;
    for (unsigned i = 0; i < maskLength; ++i) {
        formatCode = inputMask[i];
        if (formatCodes().find(formatCode) == -1) {
            if (formatCode == '*' || (isASCIIDigit(formatCode) && formatCode != '0')) {
                // Validate codes which ends with '*f' or 'nf'
                formatCode = inputMask[++i];
                if ((i + 1 != maskLength) || formatCodes().find(formatCode) == -1) {
                    isValid = false;
                    break;
                }
                hasWildcard = true;
            } else if (formatCode == '\\') {
                // skip over the next mask character
                ++i;
                ++escapeCharCount;
            } else {
                isValid = false;
                break;
            }
        }
    }

    if (!isValid)
        return String();
    // calculate the number of characters allowed to be entered by input mask
    unsigned allowedLength = maskLength;
    if (escapeCharCount)
        allowedLength -= escapeCharCount;

    if (hasWildcard) {
        formatCode = inputMask[maskLength - 2];
        if (formatCode == '*')
            allowedLength = data.maxInputCharsAllowed();
        else {
            unsigned leftLen = String(&formatCode).toInt();
            allowedLength = leftLen + allowedLength - 2;
        }
    }

    if (allowedLength < data.maxInputCharsAllowed())
        data.setMaxInputCharsAllowed(allowedLength);

    return inputMask;
}
Пример #7
0
String InputElement::sanitizeValueForTextField(const InputElement* inputElement, const String& proposedValue)
{
#if ENABLE(WCSS)
    InputElementData data = const_cast<InputElement*>(inputElement)->data();
    if (!isConformToInputMask(data, proposedValue)) {
        if (isConformToInputMask(data, data.value()))
            return data.value();
        return String();
    }
#endif
    return replaceEOLAndLimitLength(inputElement, proposedValue, s_maximumLength);
}
Пример #8
0
void InputElement::updateFocusAppearance(InputElementData& data, Document* document, bool restorePreviousSelection)
{
    ASSERT(data.inputElement()->isTextField());

    if (!restorePreviousSelection || data.cachedSelectionStart() == -1)
        data.inputElement()->select();
    else
        // Restore the cached selection.
        updateSelectionRange(data, data.cachedSelectionStart(), data.cachedSelectionEnd());

    if (document && document->frame())
        document->frame()->revealSelection();
}
Пример #9
0
void InputElement::parseMaxLengthAttribute(InputElementData& data, InputElement* inputElement, Element* element, Attribute* attribute)
{
    int maxLength = attribute->isNull() ? InputElement::s_maximumLength : attribute->value().toInt();
    if (maxLength <= 0 || maxLength > InputElement::s_maximumLength)
        maxLength = InputElement::s_maximumLength;

    int oldMaxLength = data.maxLength();
    data.setMaxLength(maxLength);

    if (oldMaxLength != maxLength)
        updateValueIfNeeded(data, inputElement);

    element->setNeedsStyleRecalc();
}
Пример #10
0
void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, Document* document, Event* event)
{
    ASSERT(event->isBeforeTextInsertedEvent());

    // Make sure that the text to be inserted will not violate the maxLength.
    int oldLength = numGraphemeClusters(data.inputElement()->value().impl());
    ASSERT(oldLength <= data.maxLength());
    int selectionLength = numGraphemeClusters(plainText(document->frame()->selection()->selection().toNormalizedRange().get()).impl());
    ASSERT(oldLength >= selectionLength);
    int maxNewLength = data.maxLength() - (oldLength - selectionLength);

    // Truncate the inserted text to avoid violating the maxLength and other constraints.
    BeforeTextInsertedEvent* textEvent = static_cast<BeforeTextInsertedEvent*>(event);
    textEvent->setText(constrainValue(data, textEvent->text(), maxNewLength));
}
Пример #11
0
void InputElement::dispatchBlurEvent(InputElementData& data, Document* document)
{
    if (!data.inputElement()->isTextField())
        return;

    Frame* frame = document->frame();
    if (!frame)
        return;

    updatePlaceholderVisibility(data, document);

    if (data.inputElement()->isPasswordField())
        document->setUseSecureKeyboardEntryWhenActive(false);

    frame->textFieldDidEndEditing(data.element());
}
Пример #12
0
void InputElement::updateValueIfNeeded(InputElementData& data, InputElement* inputElement)
{
    String oldValue = data.value();
    String newValue = inputElement->sanitizeValue(oldValue);
    if (newValue != oldValue)
        inputElement->setValue(newValue);
}
Пример #13
0
String InputElement::constrainValue(const InputElementData& data, const String& proposedValue, int maxLength)
{
    String string = proposedValue;
    if (!data.inputElement()->isTextField())
        return string;
        
    string.replace("\r\n", " ");
    string.replace('\r', ' ');
    string.replace('\n', ' ');
    
    StringImpl* s = string.impl();
    int newLength = numCharactersInGraphemeClusters(s, maxLength);
    for (int i = 0; i < newLength; ++i) {
        const UChar& current = (*s)[i];
        if (current < ' ' && current != '\t') {
            newLength = i;
            break;
        }
    }

    if (newLength < static_cast<int>(string.length()))
        return string.left(newLength);

    return string;
}
Пример #14
0
void InputElement::setValueFromRenderer(InputElementData& data, InputElement* inputElement, Element* element, const String& value)
{
    // Renderer and our event handler are responsible for sanitizing values.
    ASSERT_UNUSED(inputElement, value == inputElement->sanitizeValue(value) || inputElement->sanitizeValue(value).isEmpty());

    // Workaround for bug where trailing \n is included in the result of textContent.
    // The assert macro above may also be simplified to:  value == constrainValue(value)
    // http://bugs.webkit.org/show_bug.cgi?id=9661
    if (value == "\n")
        data.setValue("");
    else
        data.setValue(value);

    element->setFormControlValueMatchesRenderer(true);

    element->dispatchEvent(Event::create(eventNames().inputEvent, true, false));
    notifyFormStateChanged(element);
}
Пример #15
0
void InputElement::notifyFormStateChanged(InputElementData& data, Document* document)
{
    Frame* frame = document->frame();
    if (!frame)
        return;

    if (Page* page = frame->page())
        page->chrome()->client()->formStateDidChange(data.element());
}
Пример #16
0
bool InputElement::isConformToInputMask(const InputElementData& data, UChar inChar, unsigned cursorPosition)
{
    String inputFormatMask = data.inputFormatMask();

    if (inputFormatMask.isEmpty() || inputFormatMask == "*M" || inputFormatMask == "*m")
        return true;

    if (cursorPosition >= data.maxInputCharsAllowed())
        return false;

    unsigned maskIndex = cursorPositionToMaskIndex(inputFormatMask, cursorPosition);
    bool ok = true;
    UChar mask = inputFormatMask[maskIndex];
    // Match the inputed character with input mask
    switch (mask) {
    case 'A':
        ok = !isASCIIDigit(inChar) && !isASCIILower(inChar) && isASCIIPrintable(inChar);
        break;
    case 'a':
        ok = !isASCIIDigit(inChar) && !isASCIIUpper(inChar) && isASCIIPrintable(inChar);
        break;
    case 'N':
        ok = isASCIIDigit(inChar);
        break;
    case 'n':
        ok = !isASCIIAlpha(inChar) && isASCIIPrintable(inChar);
        break;
    case 'X':
        ok = !isASCIILower(inChar) && isASCIIPrintable(inChar);
        break;
    case 'x':
        ok = !isASCIIUpper(inChar) && isASCIIPrintable(inChar);
        break;
    case 'M':
    case 'm':
        ok = isASCIIPrintable(inChar);
        break;
    default:
        ok = (mask == inChar);
        break;
    }

    return ok;
}
Пример #17
0
void InputElement::updatePlaceholderVisibility(InputElementData& data, Document* document, bool placeholderValueChanged)
{
    ASSERT(data.inputElement()->isTextField());

    bool oldPlaceholderShouldBeVisible = data.placeholderShouldBeVisible();
    Element* element = data.element();

    data.setPlaceholderShouldBeVisible(data.inputElement()->value().isEmpty() 
                                       && document->focusedNode() != element
                                       && !data.inputElement()->placeholder().isEmpty());

    if ((oldPlaceholderShouldBeVisible != data.placeholderShouldBeVisible() || placeholderValueChanged) && element->renderer())
        static_cast<RenderTextControlSingleLine*>(element->renderer())->updatePlaceholderVisibility();
}
Пример #18
0
void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputElement* inputElement, Element* element, Event* event)
{
    ASSERT(event->isBeforeTextInsertedEvent());
    // Make sure that the text to be inserted will not violate the maxLength.

    // We use RenderTextControlSingleLine::text() instead of InputElement::value()
    // because they can be mismatched by sanitizeValue() in
    // RenderTextControlSingleLine::subtreeHasChanged() in some cases.
    unsigned oldLength = numGraphemeClusters(toRenderTextControlSingleLine(element->renderer())->text());

    // selectionLength represents the selection length of this text field to be
    // removed by this insertion.
    // If the text field has no focus, we don't need to take account of the
    // selection length. The selection is the source of text drag-and-drop in
    // that case, and nothing in the text field will be removed.
    unsigned selectionLength = element->focused() ? numGraphemeClusters(plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get())) : 0;
    ASSERT(oldLength >= selectionLength);

    // Selected characters will be removed by the next text event.
    unsigned baseLength = oldLength - selectionLength;
    unsigned maxLength = static_cast<unsigned>(inputElement->supportsMaxLength() ? data.maxLength() : s_maximumLength); // maxLength() can never be negative.
    unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0;

    // Truncate the inserted text to avoid violating the maxLength and other constraints.
    BeforeTextInsertedEvent* textEvent = static_cast<BeforeTextInsertedEvent*>(event);
#if ENABLE(WCSS)
    RefPtr<Range> range = element->document()->frame()->selection()->selection().toNormalizedRange();
    String candidateString = toRenderTextControlSingleLine(element->renderer())->text();
    if (selectionLength)
        candidateString.replace(range->startOffset(), range->endOffset(), textEvent->text());
    else
        candidateString.insert(textEvent->text(), range->startOffset());
    if (!isConformToInputMask(inputElement->data(), candidateString)) {
        textEvent->setText("");
        return;
      }
#endif
    textEvent->setText(sanitizeUserInputValue(inputElement, textEvent->text(), appendableLength));
}
Пример #19
0
void InputElement::setValueFromRenderer(InputElementData& data, Document* document, const String& value)
{
    // Renderer and our event handler are responsible for constraining values.
    ASSERT(value == data.inputElement()->constrainValue(value) || data.inputElement()->constrainValue(value).isEmpty());

    if (data.inputElement()->isTextField())
        updatePlaceholderVisibility(data, document);

    // Workaround for bug where trailing \n is included in the result of textContent.
    // The assert macro above may also be simplified to:  value == constrainValue(value)
    // http://bugs.webkit.org/show_bug.cgi?id=9661
    if (value == "\n")
        data.setValue("");
    else
        data.setValue(value);

    Element* element = data.element();
    element->setFormControlValueMatchesRenderer(true);

    // Fire the "input" DOM event
    element->dispatchEvent(eventNames().inputEvent, true, false);
    notifyFormStateChanged(data, document);
}