📄 html_formimpl.cpp
字号:
assert(false);
return 0;
}
void HTMLInputElementImpl::attach()
{
if (!m_inited) {
if (!m_haveType)
setType(getAttribute(ATTR_TYPE));
// FIXME: This needs to be dynamic, doesn't it, since someone could set this
// after attachment?
DOMString val = getAttribute(ATTR_VALUE);
if ((uint) m_type <= ISINDEX && !val.isEmpty()) {
// remove newline stuff..
QString nvalue;
for (unsigned int i = 0; i < val.length(); ++i)
if (val[i] >= ' ')
nvalue += val[i];
if (val.length() != nvalue.length())
setAttribute(ATTR_VALUE, nvalue);
}
m_defaultChecked = (!getAttribute(ATTR_CHECKED).isNull());
m_inited = true;
}
// Disallow the width attribute on inputs other than HIDDEN and IMAGE.
// Dumb Web sites will try to set the width as an attribute on form controls that aren't
// images or hidden.
if (hasMappedAttributes() && m_type != HIDDEN && m_type != IMAGE && !getAttribute(ATTR_WIDTH).isEmpty()) {
int excCode;
removeAttribute(ATTR_WIDTH, excCode);
}
HTMLGenericFormElementImpl::attach();
if (m_type == IMAGE) {
if (!m_imageLoader)
m_imageLoader = new HTMLImageLoader(this);
m_imageLoader->updateFromElement();
if (renderer()) {
RenderImage* imageObj = static_cast<RenderImage*>(renderer());
imageObj->setImage(m_imageLoader->image());
}
}
#if APPLE_CHANGES
// note we don't deal with calling passwordFieldRemoved() on detach, because the timing
// was such that it cleared our state too early
if (m_type == PASSWORD)
getDocument()->passwordFieldAdded();
#endif
}
void HTMLInputElementImpl::detach()
{
HTMLGenericFormElementImpl::detach();
m_valueMatchesRenderer = false;
}
DOMString HTMLInputElementImpl::altText() const
{
// http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen
// also heavily discussed by Hixie on bugzilla
// note this is intentionally different to HTMLImageElementImpl::altText()
DOMString alt = getAttribute( ATTR_ALT );
// fall back to title attribute
if ( alt.isNull() )
alt = getAttribute( ATTR_TITLE );
if ( alt.isNull() )
alt = getAttribute( ATTR_VALUE );
if ( alt.isEmpty() )
#if APPLE_CHANGES
alt = inputElementAltText();
#else
alt = i18n( "Submit" );
#endif
return alt;
}
bool HTMLInputElementImpl::isSuccessfulSubmitButton() const
{
// HTML spec says that buttons must have names
// to be considered successful. However, other browsers
// do not impose this constraint. Therefore, we behave
// differently and can use different buttons than the
// author intended.
// Was: (m_type == SUBMIT && !name().isEmpty())
return !m_disabled && (m_type == IMAGE || m_type == SUBMIT);
}
bool HTMLInputElementImpl::isActivatedSubmit() const
{
return m_activeSubmit;
}
void HTMLInputElementImpl::setActivatedSubmit(bool flag)
{
m_activeSubmit = flag;
}
bool HTMLInputElementImpl::appendFormData(FormDataList &encoding, bool multipart)
{
// image generates its own names
if (name().isEmpty() && m_type != IMAGE) return false;
switch (m_type) {
case HIDDEN:
case TEXT:
#if APPLE_CHANGES
case SEARCH:
case RANGE:
#endif
case PASSWORD:
// always successful
encoding.appendData(name(), value());
return true;
case CHECKBOX:
case RADIO:
if (checked()) {
encoding.appendData(name(), value());
return true;
}
break;
case BUTTON:
case RESET:
// those buttons are never successful
return false;
case IMAGE:
if (m_activeSubmit)
{
encoding.appendData(name().isEmpty() ? QString::fromLatin1("x") : (name().string() + ".x"), clickX());
encoding.appendData(name().isEmpty() ? QString::fromLatin1("y") : (name().string() + ".y"), clickY());
if (!name().isEmpty() && !value().isEmpty())
encoding.appendData(name(), value());
return true;
}
break;
case SUBMIT:
if (m_activeSubmit)
{
QString enc_str = valueWithDefault().string();
if (!enc_str.isEmpty()) {
encoding.appendData(name(), enc_str);
return true;
}
}
break;
case FILE:
{
// can't submit file on GET
// don't submit if display: none or display: hidden
if(!multipart || !renderer() || renderer()->style()->visibility() != khtml::VISIBLE)
return false;
// if no filename at all is entered, return successful, however empty
// null would be more logical but netscape posts an empty file. argh.
if (value().isEmpty()) {
encoding.appendData(name(), QString(""));
return true;
}
#if APPLE_CHANGES
encoding.appendFile(name(), value());
return true;
#else
KURL fileurl("file:///");
fileurl.setPath(value().string());
KIO::UDSEntry filestat;
if (!KIO::NetAccess::stat(fileurl, filestat)) {
KMessageBox::sorry(0L, i18n("Error fetching file for submission:\n%1").arg(KIO::NetAccess::lastErrorString()));
return false;
}
KFileItem fileitem(filestat, fileurl, true, false);
if (fileitem.isDir()) {
return false;
}
QString local;
if ( KIO::NetAccess::download(fileurl, local) )
{
QFile file(local);
if (file.open(IO_ReadOnly))
{
QCString filearray(file.size()+1);
int readbytes = file.readBlock( filearray.data(), file.size());
if ( readbytes >= 0 )
filearray[readbytes] = '\0';
file.close();
encoding.appendData(name(), filearray);
KIO::NetAccess::removeTempFile( local );
return true;
}
return false;
}
else {
KMessageBox::sorry(0L, i18n("Error fetching file for submission:\n%1").arg(KIO::NetAccess::lastErrorString()));
return false;
}
break;
#endif
}
case ISINDEX:
encoding.appendData(name(), value());
return true;
}
return false;
}
void HTMLInputElementImpl::reset()
{
if (storesValueSeparateFromAttribute())
setValue(DOMString());
setChecked(m_defaultChecked);
m_useDefaultChecked = true;
}
void HTMLInputElementImpl::setChecked(bool _checked)
{
if (checked() == _checked) return;
if (m_form && m_type == RADIO && _checked && !name().isEmpty())
m_form->radioClicked(this);
m_useDefaultChecked = false;
m_checked = _checked;
setChanged();
}
DOMString HTMLInputElementImpl::value() const
{
DOMString value = m_value;
// It's important *not* to fall back to the value attribute for file inputs,
// because that would allow a malicious web page to upload files by setting the
// value attribute in markup.
if (value.isNull() && m_type != FILE)
value = getAttribute(ATTR_VALUE);
// If no attribute exists, then just use "on" or "" based off the checked() state of the control.
if (value.isNull() && (m_type == CHECKBOX || m_type == RADIO))
return DOMString(checked() ? "on" : "");
return value;
}
DOMString HTMLInputElementImpl::valueWithDefault() const
{
DOMString v = value();
if (v.isEmpty()) {
switch (m_type) {
case RESET:
#if APPLE_CHANGES
v = resetButtonDefaultLabel();
#else
v = i18n("Reset");
#endif
break;
case SUBMIT:
#if APPLE_CHANGES
v = submitButtonDefaultLabel();
#else
v = i18n("Submit");
#endif
break;
case BUTTON:
case CHECKBOX:
case FILE:
case HIDDEN:
case IMAGE:
case ISINDEX:
case PASSWORD:
case RADIO:
#if APPLE_CHANGES
case RANGE:
case SEARCH:
#endif
case TEXT:
break;
}
}
return v;
}
void HTMLInputElementImpl::setValue(const DOMString &value)
{
if (m_type == FILE) return;
if (storesValueSeparateFromAttribute()) {
m_value = value;
setChanged();
} else {
setAttribute(ATTR_VALUE, value);
}
m_valueMatchesRenderer = false;
}
void HTMLInputElementImpl::setValueFromRenderer(const DOMString &value)
{
m_value = value;
m_valueMatchesRenderer = true;
// Fire the "input" DOM event.
dispatchHTMLEvent(EventImpl::INPUT_EVENT, true, false);
}
bool HTMLInputElementImpl::storesValueSeparateFromAttribute() const
{
switch (m_type) {
case BUTTON:
case CHECKBOX:
case FILE:
case HIDDEN:
case IMAGE:
case RADIO:
#if APPLE_CHANGES
case RANGE:
#endif
case RESET:
case SUBMIT:
return false;
case ISINDEX:
case PASSWORD:
#if APPLE_CHANGES
case SEARCH:
#endif
case TEXT:
return true;
}
return false;
}
void HTMLInputElementImpl::blur()
{
if(getDocument()->focusNode() == this)
getDocument()->setFocusNode(0);
}
void HTMLInputElementImpl::focus()
{
getDocument()->setFocusNode(this);
}
void HTMLInputElementImpl::defaultEventHandler(EventImpl *evt)
{
if (evt->isMouseEvent() &&
( evt->id() == EventImpl::KHTML_CLICK_EVENT || evt->id() == EventImpl::KHTML_DBLCLICK_EVENT ) &&
m_type == IMAGE
&& m_render) {
// record the mouse position for when we get the DOMActivate event
MouseEventImpl *me = static_cast<MouseEventImpl*>(evt);
int offsetX, offsetY;
m_render->absolutePosition(offsetX,offsetY);
xPos = me->clientX()-offsetX;
yPos = me->clientY()-offsetY;
me->setDefaultHandled();
}
// 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. Javacsript code wishing to activate the element
// must dispatch a DOMActivate event - a click event will not do the job.
if ((evt->id() == EventImpl::DOMACTIVATE_EVENT) &&
(m_type == IMAGE || m_type == SUBMIT || m_type == RESET)){
if (!m_form)
return;
if (m_type == RESET) {
m_form->reset();
}
else {
m_activeSubmit = true;
if (!m_form->prepareSubmit()) {
xPos = 0;
yPos = 0;
}
m_activeSubmit = false;
}
}
#if NOKIA_CHANGES
// Use key press event here since sending simulated mouse events
// on key down blocks the proper sending of the key press event.
if (evt->id() == EventImpl::KEYPRESS_EVENT && evt->isKeyboardEvent()) {
DOMString key = static_cast<KeyboardEventImpl *>(evt)->keyIdentifier();
switch (m_type) {
case CHECKBOX:
case RADIO:
case PASSWORD:
case TEXT:
if (m_render && static_cast<RenderWidget*>(m_render)->widget())
static_cast<RenderWidget*>(m_render)->widget()->activate();
evt->setDefaultHandled();
break;
case BUTTON:
case FILE:
case IMAGE:
case RESET:
case SUBMIT:
// Simulate mouse click for enter or spacebar for these types of elements.
// The AppKit already does this for spacebar for some, but not all, of them.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -