2 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@kde.org>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
24 #include "SVGScriptElement.h"
26 #include "Attribute.h"
29 #include "EventNames.h"
30 #include "HTMLNames.h"
31 #include "SVGAnimatedStaticPropertyTearOff.h"
32 #include "SVGElementInstance.h"
34 #include "ScriptEventListener.h"
38 // Animated property definitions
39 DEFINE_ANIMATED_STRING(SVGScriptElement, XLinkNames::hrefAttr, Href, href)
40 DEFINE_ANIMATED_BOOLEAN(SVGScriptElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
42 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGScriptElement)
43 REGISTER_LOCAL_ANIMATED_PROPERTY(href)
44 REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
45 END_REGISTER_ANIMATED_PROPERTIES
47 inline SVGScriptElement::SVGScriptElement(const QualifiedName& tagName, Document* document, bool wasInsertedByParser, bool alreadyStarted)
48 : SVGElement(tagName, document)
49 , ScriptElement(this, wasInsertedByParser, alreadyStarted)
51 ASSERT(hasTagName(SVGNames::scriptTag));
52 registerAnimatedPropertiesForSVGScriptElement();
55 PassRefPtr<SVGScriptElement> SVGScriptElement::create(const QualifiedName& tagName, Document* document, bool insertedByParser)
57 return adoptRef(new SVGScriptElement(tagName, document, insertedByParser, false));
60 bool SVGScriptElement::isSupportedAttribute(const QualifiedName& attrName)
62 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
63 if (supportedAttributes.isEmpty()) {
64 SVGURIReference::addSupportedAttributes(supportedAttributes);
65 SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
66 supportedAttributes.add(SVGNames::typeAttr);
67 supportedAttributes.add(HTMLNames::onerrorAttr);
69 return supportedAttributes.contains(attrName);
72 void SVGScriptElement::parseMappedAttribute(Attribute* attr)
74 if (!isSupportedAttribute(attr->name())) {
75 SVGElement::parseMappedAttribute(attr);
79 if (attr->name() == SVGNames::typeAttr) {
80 setType(attr->value());
84 if (attr->name() == HTMLNames::onerrorAttr) {
85 setAttributeEventListener(eventNames().errorEvent, createAttributeEventListener(this, attr));
89 if (SVGURIReference::parseMappedAttribute(attr))
91 if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
97 void SVGScriptElement::svgAttributeChanged(const QualifiedName& attrName)
99 if (!isSupportedAttribute(attrName)) {
100 SVGElement::svgAttributeChanged(attrName);
104 SVGElementInstance::InvalidationGuard invalidationGuard(this);
106 if (attrName == SVGNames::typeAttr || attrName == HTMLNames::onerrorAttr)
109 if (SVGURIReference::isKnownAttribute(attrName)) {
110 handleSourceAttribute(href());
114 if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
115 // Handle dynamic updates of the 'externalResourcesRequired' attribute. Only possible case: changing from 'true' to 'false'
116 // causes an immediate dispatch of the SVGLoad event. If the attribute value was 'false' before inserting the script element
117 // in the document, the SVGLoad event has already been dispatched.
118 if (!externalResourcesRequiredBaseValue() && !haveFiredLoadEvent() && !isParserInserted()) {
119 setHaveFiredLoadEvent(true);
120 ASSERT(haveLoadedRequiredResources());
122 sendSVGLoadEventIfPossible();
127 ASSERT_NOT_REACHED();
130 void SVGScriptElement::insertedIntoDocument()
132 SVGElement::insertedIntoDocument();
133 ScriptElement::insertedIntoDocument();
135 if (isParserInserted())
138 // Eventually send SVGLoad event now for the dynamically inserted script element
139 if (!externalResourcesRequiredBaseValue()) {
140 setHaveFiredLoadEvent(true);
141 sendSVGLoadEventIfPossible();
145 void SVGScriptElement::removedFromDocument()
147 SVGElement::removedFromDocument();
148 ScriptElement::removedFromDocument();
151 void SVGScriptElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
153 ScriptElement::childrenChanged();
154 SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
157 bool SVGScriptElement::isURLAttribute(Attribute* attr) const
159 return attr->name() == sourceAttributeValue();
162 void SVGScriptElement::finishParsingChildren()
164 SVGElement::finishParsingChildren();
166 // A SVGLoad event has been fired by SVGElement::finishParsingChildren.
167 if (!externalResourcesRequiredBaseValue())
168 setHaveFiredLoadEvent(true);
171 String SVGScriptElement::type() const
176 void SVGScriptElement::setType(const String& type)
181 void SVGScriptElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
183 SVGElement::addSubresourceAttributeURLs(urls);
185 addSubresourceURL(urls, document()->completeURL(href()));
188 bool SVGScriptElement::haveLoadedRequiredResources()
190 return !externalResourcesRequiredBaseValue() || haveFiredLoadEvent();
193 String SVGScriptElement::sourceAttributeValue() const
198 String SVGScriptElement::charsetAttributeValue() const
203 String SVGScriptElement::typeAttributeValue() const
208 String SVGScriptElement::languageAttributeValue() const
213 String SVGScriptElement::forAttributeValue() const
218 String SVGScriptElement::eventAttributeValue() const
223 bool SVGScriptElement::asyncAttributeValue() const
228 bool SVGScriptElement::deferAttributeValue() const
233 bool SVGScriptElement::hasSourceAttribute() const
235 return hasAttribute(XLinkNames::hrefAttr);
238 void SVGScriptElement::dispatchLoadEvent()
240 bool externalResourcesRequired = externalResourcesRequiredBaseValue();
242 if (isParserInserted())
243 ASSERT(externalResourcesRequired != haveFiredLoadEvent());
244 else if (haveFiredLoadEvent()) {
245 // If we've already fired an load event and externalResourcesRequired is set to 'true'
246 // externalResourcesRequired has been modified while loading the <script>. Don't dispatch twice.
247 if (externalResourcesRequired)
251 // HTML and SVG differ completly in the 'onload' event handling of <script> elements.
252 // HTML fires the 'load' event after it sucessfully loaded a remote resource, otherwhise an error event.
253 // SVG fires the SVGLoad event immediately after parsing the <script> element, if externalResourcesRequired
254 // is set to 'false', otherwhise it dispatches the 'SVGLoad' event just after loading the remote resource.
255 if (externalResourcesRequired) {
256 ASSERT(!haveFiredLoadEvent());
258 // Dispatch SVGLoad event
259 setHaveFiredLoadEvent(true);
260 ASSERT(haveLoadedRequiredResources());
262 sendSVGLoadEventIfPossible();
266 PassRefPtr<Element> SVGScriptElement::cloneElementWithoutAttributesAndChildren()
268 return adoptRef(new SVGScriptElement(tagQName(), document(), false, alreadyStarted()));
273 #endif // ENABLE(SVG)