📄 htmlinputelement.cpp
字号:
String enc_str = valueWithDefault(); encoding.appendData(name(), enc_str); return true; } break; case FILE: { // Can't submit file on GET. if (!multipart) return false; // If no filename at all is entered, return successful but empty. // Null would be more logical, but Netscape posts an empty file. Argh. unsigned numFiles = m_fileList->length(); if (!numFiles) { encoding.appendFile(name(), File::create("")); return true; } for (unsigned i = 0; i < numFiles; ++i) encoding.appendFile(name(), m_fileList->item(i)); return true; } } return false;}void HTMLInputElement::reset(){ if (storesValueSeparateFromAttribute()) setValue(String()); setChecked(m_defaultChecked); m_useDefaultChecked = true;}void HTMLInputElement::setChecked(bool nowChecked, bool sendChangeEvent){ if (checked() == nowChecked) return; checkedRadioButtons(this).removeButton(this); m_useDefaultChecked = false; m_checked = nowChecked; setChanged(); checkedRadioButtons(this).addButton(this); if (renderer() && renderer()->style()->hasAppearance()) theme()->stateChanged(renderer(), CheckedState); // Only send a change event for items in the document (avoid firing during // parsing) and don't send a change event for a radio button that's getting // unchecked to match other browsers. DOM is not a useful standard for this // because it says only to fire change events at "lose focus" time, which is // definitely wrong in practice for these types of elements. if (sendChangeEvent && inDocument() && (inputType() != RADIO || nowChecked)) onChange();}void HTMLInputElement::setIndeterminate(bool _indeterminate){ // Only checkboxes honor indeterminate. if (inputType() != CHECKBOX || indeterminate() == _indeterminate) return; m_indeterminate = _indeterminate; setChanged(); if (renderer() && renderer()->style()->hasAppearance()) theme()->stateChanged(renderer(), CheckedState);}int HTMLInputElement::size() const{ return m_data.size();}void HTMLInputElement::copyNonAttributeProperties(const Element* source){ const HTMLInputElement* sourceElement = static_cast<const HTMLInputElement*>(source); m_data.setValue(sourceElement->m_data.value()); m_checked = sourceElement->m_checked; m_indeterminate = sourceElement->m_indeterminate; HTMLFormControlElementWithState::copyNonAttributeProperties(source);}String HTMLInputElement::value() const{ // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control // but we don't want to break existing websites, who may be relying on being able to get the file name as a value. if (inputType() == FILE) { if (!m_fileList->isEmpty()) return m_fileList->item(0)->fileName(); return String(); } String value = m_data.value(); if (value.isNull()) { value = constrainValue(getAttribute(valueAttr)); // If no attribute exists, then just use "on" or "" based off the checked() state of the control. if (value.isNull() && (inputType() == CHECKBOX || inputType() == RADIO)) return checked() ? "on" : ""; } return value;}String HTMLInputElement::valueWithDefault() const{ String v = value(); if (v.isNull()) { switch (inputType()) { case BUTTON: case CHECKBOX: case FILE: case HIDDEN: case IMAGE: case ISINDEX: case PASSWORD: case RADIO: case RANGE: case SEARCH: case TEXT: break; case RESET: v = resetButtonDefaultLabel(); break; case SUBMIT: v = submitButtonDefaultLabel(); break; } } return v;}void HTMLInputElement::setValue(const String& value){ // For security reasons, we don't allow setting the filename, but we do allow clearing it. // The HTML5 spec (as of the 10/24/08 working draft) says that the value attribute isn't applicable to the file upload control // but we don't want to break existing websites, who may be relying on this method to clear things. if (inputType() == FILE && !value.isEmpty()) return; if (isTextField()) InputElement::updatePlaceholderVisibility(m_data, document()); setValueMatchesRenderer(false); if (storesValueSeparateFromAttribute()) { if (inputType() == FILE) m_fileList->clear(); else { m_data.setValue(constrainValue(value)); if (isTextField() && inDocument()) document()->updateRendering(); } if (renderer()) renderer()->updateFromElement(); setChanged(); } else setAttribute(valueAttr, constrainValue(value)); if (isTextField()) { unsigned max = m_data.value().length(); if (document()->focusedNode() == this) InputElement::updateSelectionRange(m_data, max, max); else cacheSelection(max, max); } InputElement::notifyFormStateChanged(m_data, document());}String HTMLInputElement::placeholderValue() const{ return getAttribute(placeholderAttr).string();}bool HTMLInputElement::searchEventsShouldBeDispatched() const{ return hasAttribute(incrementalAttr);}void HTMLInputElement::setValueFromRenderer(const String& value){ // File upload controls will always use setFileListFromRenderer. ASSERT(inputType() != FILE); InputElement::setValueFromRenderer(m_data, document(), value);}void HTMLInputElement::setFileListFromRenderer(const Vector<String>& paths){ m_fileList->clear(); int size = paths.size(); for (int i = 0; i < size; i++) m_fileList->append(File::create(paths[i])); setValueMatchesRenderer(); InputElement::notifyFormStateChanged(m_data, document());}bool HTMLInputElement::storesValueSeparateFromAttribute() const{ switch (inputType()) { case BUTTON: case CHECKBOX: case HIDDEN: case IMAGE: case RADIO: case RESET: case SUBMIT: return false; case FILE: case ISINDEX: case PASSWORD: case RANGE: case SEARCH: case TEXT: return true; } return false;}void* HTMLInputElement::preDispatchEventHandler(Event *evt){ // preventDefault or "return false" are used to reverse the automatic checking/selection we do here. // This result gives us enough info to perform the "undo" in postDispatch of the action we take here. void* result = 0; if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent() && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { if (inputType() == CHECKBOX) { // As a way to store the state, we return 0 if we were unchecked, 1 if we were checked, and 2 for // indeterminate. if (indeterminate()) { result = (void*)0x2; setIndeterminate(false); } else { if (checked()) result = (void*)0x1; setChecked(!checked(), true); } } else { // For radio buttons, store the current selected radio object. // We really want radio groups to end up in sane states, i.e., to have something checked. // Therefore if nothing is currently selected, we won't allow this action to be "undone", since // we want some object in the radio group to actually get selected. HTMLInputElement* currRadio = checkedRadioButtons(this).checkedButtonForGroup(name()); if (currRadio) { // We have a radio button selected that is not us. Cache it in our result field and ref it so // that it can't be destroyed. currRadio->ref(); result = currRadio; } setChecked(true, true); } } return result;}void HTMLInputElement::postDispatchEventHandler(Event *evt, void* data){ if ((inputType() == CHECKBOX || inputType() == RADIO) && evt->isMouseEvent() && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { if (inputType() == CHECKBOX) { // Reverse the checking we did in preDispatch. if (evt->defaultPrevented() || evt->defaultHandled()) { if (data == (void*)0x2) setIndeterminate(true); else setChecked(data); } } else if (data) { HTMLInputElement* input = static_cast<HTMLInputElement*>(data); if (evt->defaultPrevented() || evt->defaultHandled()) { // Restore the original selected radio button if possible. // Make sure it is still a radio button and only do the restoration if it still // belongs to our group. if (input->form() == form() && input->inputType() == RADIO && input->name() == name()) { // Ok, the old radio button is still in our form and in our group and is still a // radio button, so it's safe to restore selection to it. input->setChecked(true); } } input->deref(); } // Left clicks on radio buttons and check boxes already performed default actions in preDispatchEventHandler(). evt->setDefaultHandled(); }}void HTMLInputElement::defaultEventHandler(Event* evt){ bool clickDefaultFormButton = false; if (isTextField() && evt->type() == eventNames().textInputEvent && evt->isTextEvent() && static_cast<TextEvent*>(evt)->data() == "\n") clickDefaultFormButton = true; if (inputType() == IMAGE && evt->isMouseEvent() && evt->type() == eventNames().clickEvent) { // record the mouse position for when we get the DOMActivate event MouseEvent* me = static_cast<MouseEvent*>(evt); // FIXME: We could just call offsetX() and offsetY() on the event, // but that's currently broken, so for now do the computation here. if (me->isSimulated() || !renderer()) { m_xPos = 0; m_yPos = 0; } else { // FIXME: This doesn't work correctly with transforms. IntPoint absOffset = roundedIntPoint(renderer()->localToAbsolute()); m_xPos = me->pageX() - absOffset.x(); m_yPos = me->pageY() - absOffset.y(); } } if (isTextField() && evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent() && focused() && document()->frame() && document()->frame()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) { evt->setDefaultHandled(); return; } if (inputType() == RADIO && evt->isMouseEvent() && evt->type() == eventNames().clickEvent && static_cast<MouseEvent*>(evt)->button() == LeftButton) { evt->setDefaultHandled(); return; } // Let the key handling done in Node take precedence over the event handling here for editable text fields if (!clickDefaultFormButton) { HTMLFormControlElementWithState::defaultEventHandler(evt); if (evt->defaultHandled()) return; } // DOMActivate events cause the input to be "activated" - in the case of image and submit inputs, this means // actually submitting the form. For reset inputs, the form is reset. These events are sent when the user clicks // on the element, or presses enter while it is the active element. JavaScript code wishing to activate the element // must dispatch a DOMActivate event - a click event will not do the job. if (evt->type() == eventNames().DOMActivateEvent && !disabled()) { if (inputType() == IMAGE || inputType() == SUBMIT || inputType() == RESET) { if (!form()) return; if (inputType() == RESET) form()->reset(); else { m_activeSubmit = true; // FIXME: Would be cleaner to get m_xPos and m_yPos out of the underlying mouse // event (if any) here instead of relying on the variables set above when // processing the click event. Even better, appendFormData could pass the // event in, and then we could get rid of m_xPos and m_yPos altogether! if (!form()->prepareSubmit(evt)) { m_xPos = 0; m_yPos = 0; } m_activeSubmit = false; } } else if (inputType() == FILE && renderer()) static_cast<RenderFileUploadControl*>(renderer())->click(); } // Use key press event here since sending simulated mouse events // on key down blocks the proper sending of the key press event. if (evt->type() == eventNames().keypressEvent && evt->isKeyboardEvent()) { bool clickElement = false; int charCode = static_cast<KeyboardEvent*>(evt)->charCode(); if (charCode == '\r') { switch (inputType()) { case CHECKBOX: case HIDDEN: case ISINDEX: case PASSWORD: case RANGE: case SEARCH: case TEXT: // Simulate mouse click on the default form button for enter for these types of elements. clickDefaultFormButton = true; break; case BUTTON: case FILE: case IMAGE: case RESET: case SUBMIT: // Simulate mouse click for enter for these types of elements. clickElement = true; break; case RADIO: break; // Don't do anything for enter on a radio button.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -