[SCM] WebKit Debian packaging branch, webkit-1.3, updated. upstream/1.3.7-4207-g178b198
tkent at chromium.org
tkent at chromium.org
Sun Feb 20 22:56:30 UTC 2011
The following commit has been merged in the webkit-1.3 branch:
commit c31a097e4cdd29b029ba312dc716ca327a852a49
Author: tkent at chromium.org <tkent at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Fri Jan 14 06:21:51 2011 +0000
Implement form validation message UI
https://bugs.webkit.org/show_bug.cgi?id=48980
Reviewed by Dimitri Glazkov.
* Add four internal pseudo selectors:
- -webkit-validation-bubble
- -webkit-validation-bubble-message
- -webkit-validation-bubble-top-outer-arrow
- -webkit-validation-bubble-top-inner-arrow
* Implement ValidationMessage functions
Show the message for <the number of characters> / 20.0 seconds.
No new tests because the feature is disabled by default for now and the
new behavior is strongly timing-dependent.
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::canShareStyleWithElement):
Do not share a style with elements with different shadowPseudoId().
* css/html.css: Define appearance for the internal selectors.
(::-webkit-validation-bubble):
(::-webkit-validation-bubble-message):
(::-webkit-validation-bubble-top-outer-arrow):
(::-webkit-validation-bubble-top-inner-arrow):
* dom/Node.cpp:
(WebCore::Node::createRendererIfNeeded):
Allow to add shadow renderers even if canHaveChildren() returns false.
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::detach):
Remove m_validationMessage immediately because we can't use
hideVisibleValidationMessage(), which calls a ValidationMessage function later.
(WebCore::HTMLFormControlElement::updateVisibleValidationMessage):
- Don't create ValidationMessage if the message is empty.
- Remove the check for message equality.
(WebCore::HTMLFormControlElement::hideVisibleValidationMessage):
Don't remove m_validationMessage immediately. We shouldn't make the
element needsLayout() state in this context.
* html/ValidationMessage.cpp:
(WebCore::ValidationMessage::~ValidationMessage):
hideMessage() -> deleteBubbleTree() renaming.
(WebCore::ValidationMessage::setMessage): Implemented.
(WebCore::ValidationMessage::setMessageDOMAndStartTimer):
Added. This updates the validation message and starts the timer to hide it.
(WebCore::ElementWithPseudoId):
Added to help implementations of styled shadow nodes.
(WebCore::ValidationMessage::buildBubbleTree): Added.
(WebCore::ValidationMessage::requestToHideMessage): Added.
(WebCore::ValidationMessage::deleteBubbleTree):
Renamed from hideMessage(), and implemented.
* html/ValidationMessage.h: Add declarations.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75770 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 1967f9b..66e7741 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,57 @@
+2011-01-13 Kent Tamura <tkent at chromium.org>
+
+ Reviewed by Dimitri Glazkov.
+
+ Implement form validation message UI
+ https://bugs.webkit.org/show_bug.cgi?id=48980
+
+ * Add four internal pseudo selectors:
+ - -webkit-validation-bubble
+ - -webkit-validation-bubble-message
+ - -webkit-validation-bubble-top-outer-arrow
+ - -webkit-validation-bubble-top-inner-arrow
+
+ * Implement ValidationMessage functions
+ Show the message for <the number of characters> / 20.0 seconds.
+
+ No new tests because the feature is disabled by default for now and the
+ new behavior is strongly timing-dependent.
+
+ * css/CSSStyleSelector.cpp:
+ (WebCore::CSSStyleSelector::canShareStyleWithElement):
+ Do not share a style with elements with different shadowPseudoId().
+ * css/html.css: Define appearance for the internal selectors.
+ (::-webkit-validation-bubble):
+ (::-webkit-validation-bubble-message):
+ (::-webkit-validation-bubble-top-outer-arrow):
+ (::-webkit-validation-bubble-top-inner-arrow):
+ * dom/Node.cpp:
+ (WebCore::Node::createRendererIfNeeded):
+ Allow to add shadow renderers even if canHaveChildren() returns false.
+ * html/HTMLFormControlElement.cpp:
+ (WebCore::HTMLFormControlElement::detach):
+ Remove m_validationMessage immediately because we can't use
+ hideVisibleValidationMessage(), which calls a ValidationMessage function later.
+ (WebCore::HTMLFormControlElement::updateVisibleValidationMessage):
+ - Don't create ValidationMessage if the message is empty.
+ - Remove the check for message equality.
+ (WebCore::HTMLFormControlElement::hideVisibleValidationMessage):
+ Don't remove m_validationMessage immediately. We shouldn't make the
+ element needsLayout() state in this context.
+ * html/ValidationMessage.cpp:
+ (WebCore::ValidationMessage::~ValidationMessage):
+ hideMessage() -> deleteBubbleTree() renaming.
+ (WebCore::ValidationMessage::setMessage): Implemented.
+ (WebCore::ValidationMessage::setMessageDOMAndStartTimer):
+ Added. This updates the validation message and starts the timer to hide it.
+ (WebCore::ElementWithPseudoId):
+ Added to help implementations of styled shadow nodes.
+ (WebCore::ValidationMessage::buildBubbleTree): Added.
+ (WebCore::ValidationMessage::requestToHideMessage): Added.
+ (WebCore::ValidationMessage::deleteBubbleTree):
+ Renamed from hideMessage(), and implemented.
+ * html/ValidationMessage.h: Add declarations.
+
2011-01-13 Dan Bernstein <mitz at apple.com>
Reviewed by Alexey Proskuryakov.
diff --git a/Source/WebCore/css/CSSStyleSelector.cpp b/Source/WebCore/css/CSSStyleSelector.cpp
index 6363ca9..b9f9bab 100644
--- a/Source/WebCore/css/CSSStyleSelector.cpp
+++ b/Source/WebCore/css/CSSStyleSelector.cpp
@@ -981,6 +981,7 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n) const
(s->hovered() == m_element->hovered()) &&
(s->active() == m_element->active()) &&
(s->focused() == m_element->focused()) &&
+ (s->shadowPseudoId() == m_element->shadowPseudoId()) &&
(s != s->document()->cssTarget() && m_element != m_element->document()->cssTarget()) &&
(s->fastGetAttribute(typeAttr) == m_element->fastGetAttribute(typeAttr)) &&
(s->fastGetAttribute(XMLNames::langAttr) == m_element->fastGetAttribute(XMLNames::langAttr)) &&
diff --git a/Source/WebCore/css/html.css b/Source/WebCore/css/html.css
index fb3a2c8..d5b3a19 100644
--- a/Source/WebCore/css/html.css
+++ b/Source/WebCore/css/html.css
@@ -553,6 +553,59 @@ output {
display: inline;
}
+/* form validation message bubble */
+
+::-webkit-validation-bubble {
+ display: block;
+ z-index: 2147483647;
+ position: absolute;
+ opacity: 0.9;
+ line-height: 0;
+ -webkit-transition: opacity 05.5s ease;
+}
+
+::-webkit-validation-bubble-message {
+ display: block;
+ font: message-box;
+ min-width: 50px;
+ max-width: 200px;
+ border: solid 2px black;
+ background: -webkit-gradient(linear, left top, left bottom, from(#fbf9f9), to(#f0e4e4));
+ padding: 8px;
+ -webkit-border-radius: 8px;
+ -webkit-box-shadow: 4px 4px 4px rgba(204,204,204,0.7);
+ line-height: normal;
+}
+
+::-webkit-validation-bubble-top-outer-arrow {
+ display: inline-block;
+ position: relative;
+ left: 14px;
+ height: 0;
+ width: 0;
+ border-style: solid;
+ border-width: 14px;
+ border-bottom-color: black;
+ border-right-color: transparent;
+ border-top-width: 0;
+ border-left-width: 0;
+}
+
+::-webkit-validation-bubble-top-inner-arrow {
+ display: inline-block;
+ height: 0;
+ width: 0;
+ border-style: solid;
+ border-width: 10px; /* <border box width of outer-arrow> - <message border width> * 2 */
+ border-bottom-color: #fbf9f9;
+ border-right-color: transparent;
+ border-top-width: 0;
+ border-left-width: 0;
+ position: relative;
+ top: 2px; /* <message border width> */
+ left: 2px; /* <outer-arrow position> + <message border width> - <border box width of outer-arrow> */
+}
+
/* meter */
meter {
diff --git a/Source/WebCore/dom/Node.cpp b/Source/WebCore/dom/Node.cpp
index 7837707..08a9a47 100644
--- a/Source/WebCore/dom/Node.cpp
+++ b/Source/WebCore/dom/Node.cpp
@@ -1380,8 +1380,10 @@ void Node::createRendererIfNeeded()
document()->setFullScreenRenderer(fullscreenRenderer);
}
#endif
-
- if (parentRenderer && parentRenderer->canHaveChildren() && parent->childShouldCreateRenderer(this)) {
+
+ // FIXME: Ignoreing canHaveChildren() in a case of isShadowRoot() might be wrong.
+ // See https://bugs.webkit.org/show_bug.cgi?id=52423
+ if (parentRenderer && (parentRenderer->canHaveChildren() || isShadowRoot()) && parent->childShouldCreateRenderer(this)) {
RefPtr<RenderStyle> style = styleForRenderer();
if (rendererIsNeeded(style.get())) {
if (RenderObject* r = createRenderer(document()->renderArena(), style.get())) {
diff --git a/Source/WebCore/html/HTMLFormControlElement.cpp b/Source/WebCore/html/HTMLFormControlElement.cpp
index 714311e..b3ad7c8 100644
--- a/Source/WebCore/html/HTMLFormControlElement.cpp
+++ b/Source/WebCore/html/HTMLFormControlElement.cpp
@@ -80,7 +80,7 @@ HTMLFormControlElement::~HTMLFormControlElement()
void HTMLFormControlElement::detach()
{
- hideVisibleValidationMessage();
+ m_validationMessage = 0;
HTMLElement::detach();
}
@@ -310,18 +310,24 @@ void HTMLFormControlElement::updateVisibleValidationMessage()
message.append(title);
}
}
+ if (message.isEmpty()) {
+ hideVisibleValidationMessage();
+ return;
+ }
if (!m_validationMessage) {
m_validationMessage = ValidationMessage::create(this);
m_validationMessage->setMessage(message);
- } else if (message.isEmpty())
- hideVisibleValidationMessage();
- else if (m_validationMessage->message() != message)
+ } else {
+ // Call setMessage() even if m_validationMesage->message() == message
+ // because the existing message might be to be hidden.
m_validationMessage->setMessage(message);
+ }
}
void HTMLFormControlElement::hideVisibleValidationMessage()
{
- m_validationMessage = 0;
+ if (m_validationMessage)
+ m_validationMessage->requestToHideMessage();
}
String HTMLFormControlElement::visibleValidationMessage() const
diff --git a/Source/WebCore/html/ValidationMessage.cpp b/Source/WebCore/html/ValidationMessage.cpp
index 4418235..2c441c7 100644
--- a/Source/WebCore/html/ValidationMessage.cpp
+++ b/Source/WebCore/html/ValidationMessage.cpp
@@ -31,10 +31,18 @@
#include "config.h"
#include "ValidationMessage.h"
+#include "CSSStyleSelector.h"
+#include "FormAssociatedElement.h"
+#include "HTMLBRElement.h"
+#include "HTMLNames.h"
+#include "RenderObject.h"
+#include "Text.h"
#include <wtf/PassOwnPtr.h>
namespace WebCore {
+using namespace HTMLNames;
+
ALWAYS_INLINE ValidationMessage::ValidationMessage(FormAssociatedElement* element)
: m_element(element)
{
@@ -42,7 +50,7 @@ ALWAYS_INLINE ValidationMessage::ValidationMessage(FormAssociatedElement* elemen
ValidationMessage::~ValidationMessage()
{
- hideMessage();
+ deleteBubbleTree();
}
PassOwnPtr<ValidationMessage> ValidationMessage::create(FormAssociatedElement* element)
@@ -52,18 +60,105 @@ PassOwnPtr<ValidationMessage> ValidationMessage::create(FormAssociatedElement* e
void ValidationMessage::setMessage(const String& message)
{
- // FIXME: Construct validation message UI if m_message is empty.
-
+ // Don't modify the DOM tree in this context.
+ // If so, an assertion in Node::isFocusable() fails.
+ ASSERT(!message.isEmpty());
m_message = message;
+ if (!m_bubble)
+ m_timer.set(new Timer<ValidationMessage>(this, &ValidationMessage::buildBubbleTree));
+ else
+ m_timer.set(new Timer<ValidationMessage>(this, &ValidationMessage::setMessageDOMAndStartTimer));
+ m_timer->startOneShot(0);
+}
+
+void ValidationMessage::setMessageDOMAndStartTimer(Timer<ValidationMessage>*)
+{
+ ASSERT(m_bubbleMessage);
+ m_bubbleMessage->removeAllChildren();
+ Vector<String> lines;
+ m_message.split('\n', lines);
+ Document* doc = m_bubbleMessage->document();
+ ExceptionCode ec = 0;
+ for (unsigned i = 0; i < lines.size(); ++i) {
+ if (i) {
+ m_bubbleMessage->appendChild(HTMLBRElement::create(doc), ec);
+ m_bubbleMessage->appendChild(Text::create(doc, lines[i]), ec);
+ } else {
+ RefPtr<HTMLElement> bold = HTMLElement::create(bTag, doc);
+ bold->setInnerText(lines[i], ec);
+ m_bubbleMessage->appendChild(bold.release(), ec);
+ }
+ }
- m_timer.set(new Timer<ValidationMessage>(this, &ValidationMessage::hideMessage));
- m_timer->startOneShot(6.0); // FIXME: should be <message length> * something.
+ m_timer.set(new Timer<ValidationMessage>(this, &ValidationMessage::deleteBubbleTree));
+ m_timer->startOneShot(max(5.0, m_message.length() / 20.0));
}
-void ValidationMessage::hideMessage(Timer<ValidationMessage>*)
+class ElementWithPseudoId : public HTMLElement {
+public:
+ static PassRefPtr<HTMLElement> create(Document* doc, const AtomicString& pseudoName)
+ {
+ return adoptRef(new ElementWithPseudoId(doc, pseudoName));
+ }
+
+protected:
+ ElementWithPseudoId(Document* doc, const AtomicString& pseudoName)
+ : HTMLElement(divTag, doc)
+ , m_pseudoName(pseudoName) { };
+ virtual AtomicString shadowPseudoId() const { return m_pseudoName; }
+
+private:
+ AtomicString m_pseudoName;
+};
+
+void ValidationMessage::buildBubbleTree(Timer<ValidationMessage>*)
{
- // FIXME: Implement.
+ HTMLElement* host = toHTMLElement(m_element);
+ Document* doc = host->document();
+ m_bubble = ElementWithPseudoId::create(doc, "-webkit-validation-bubble");
+ ExceptionCode ec = 0;
+ // FIXME: We need a way to host multiple shadow roots in a single node, or
+ // to inherit an existing shadow tree.
+ if (host->shadowRoot())
+ host->shadowRoot()->appendChild(m_bubble.get(), ec);
+ else {
+ host->setShadowRoot(m_bubble);
+ // FIXME: The following attach() should be unnecessary.
+ m_bubble->attach();
+ }
+
+ m_bubble->appendChild(ElementWithPseudoId::create(doc, "-webkit-validation-bubble-top-outer-arrow"), ec);
+ m_bubble->appendChild(ElementWithPseudoId::create(doc, "-webkit-validation-bubble-top-inner-arrow"), ec);
+ m_bubbleMessage = ElementWithPseudoId::create(doc, "-webkit-validation-bubble-message");
+ m_bubble->appendChild(m_bubbleMessage, ec);
+ setMessageDOMAndStartTimer();
+
+ // FIXME: Use transition to show the bubble.
+
+ // We don't need to adjust the bubble location. The default position is enough.
+}
+
+void ValidationMessage::requestToHideMessage()
+{
+ // We must not modify the DOM tree in this context by the same reason as setMessage().
+ m_timer.set(new Timer<ValidationMessage>(this, &ValidationMessage::deleteBubbleTree));
+ m_timer->startOneShot(0);
+}
+
+void ValidationMessage::deleteBubbleTree(Timer<ValidationMessage>*)
+{
+ if (m_bubble) {
+ m_bubbleMessage = 0;
+ HTMLElement* host = toHTMLElement(m_element);
+ if (m_bubble->isShadowRoot())
+ host->setShadowRoot(0);
+ else {
+ ExceptionCode ec;
+ host->shadowRoot()->removeChild(m_bubble.get(), ec);
+ }
+ m_bubble = 0;
+ }
m_message = String();
}
diff --git a/Source/WebCore/html/ValidationMessage.h b/Source/WebCore/html/ValidationMessage.h
index d78e3f3..5fa1f96 100644
--- a/Source/WebCore/html/ValidationMessage.h
+++ b/Source/WebCore/html/ValidationMessage.h
@@ -34,11 +34,13 @@
#include "Timer.h"
#include <wtf/Noncopyable.h>
#include <wtf/OwnPtr.h>
+#include <wtf/RefPtr.h>
#include <wtf/text/WTFString.h>
namespace WebCore {
class FormAssociatedElement;
+class HTMLElement;
class ValidationMessage : public Noncopyable {
public:
@@ -46,14 +48,19 @@ public:
~ValidationMessage();
String message() const { return m_message; }
void setMessage(const String&);
+ void requestToHideMessage();
private:
ValidationMessage(FormAssociatedElement*);
- void hideMessage(Timer<ValidationMessage>* = 0);
+ void setMessageDOMAndStartTimer(Timer<ValidationMessage>* = 0);
+ void buildBubbleTree(Timer<ValidationMessage>*);
+ void deleteBubbleTree(Timer<ValidationMessage>* = 0);
FormAssociatedElement* m_element;
String m_message;
OwnPtr<Timer<ValidationMessage> > m_timer;
+ RefPtr<HTMLElement> m_bubble;
+ RefPtr<HTMLElement> m_bubbleMessage;
};
} // namespace WebCore
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list