• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2      Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  
4      This file is part of the KDE project
5  
6      This library is free software; you can redistribute it and/or
7      modify it under the terms of the GNU Library General Public
8      License as published by the Free Software Foundation; either
9      version 2 of the License, or (at your option) any later version.
10  
11      This library is distributed in the hope that it will be useful,
12      but WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14      Library General Public License for more details.
15  
16      You should have received a copy of the GNU Library General Public License
17      along with this library; see the file COPYING.LIB.  If not, write to
18      the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19      Boston, MA 02110-1301, USA.
20  */
21  
22  #include "config.h"
23  
24  #if ENABLE(SVG)
25  #include "SVGElementInstance.h"
26  
27  #include "ContainerNodeAlgorithms.h"
28  #include "Document.h"
29  #include "Event.h"
30  #include "EventException.h"
31  #include "EventListener.h"
32  #include "EventNames.h"
33  #include "FrameView.h"
34  #include "SVGElementInstanceList.h"
35  #include "SVGUseElement.h"
36  
37  #include <wtf/RefCountedLeakCounter.h>
38  
39  #if USE(JSC)
40  #include "GCController.h"
41  #endif
42  
43  namespace WebCore {
44  
45  #ifndef NDEBUG
46  static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance");
47  #endif
48  
SVGElementInstance(SVGUseElement * useElement,SVGElement * originalElement)49  SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, SVGElement* originalElement)
50      : m_needsUpdate(false)
51      , m_useElement(useElement)
52      , m_element(originalElement)
53      , m_previousSibling(0)
54      , m_nextSibling(0)
55      , m_firstChild(0)
56      , m_lastChild(0)
57  {
58      ASSERT(m_useElement);
59      ASSERT(m_element);
60  
61      // Register as instance for passed element.
62      m_element->mapInstanceToElement(this);
63  
64  #ifndef NDEBUG
65      instanceCounter.increment();
66  #endif
67  }
68  
~SVGElementInstance()69  SVGElementInstance::~SVGElementInstance()
70  {
71  #ifndef NDEBUG
72      instanceCounter.decrement();
73  #endif
74  
75      // Deregister as instance for passed element.
76      m_element->removeInstanceMapping(this);
77  
78      removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this);
79  }
80  
childNodes()81  PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes()
82  {
83      return SVGElementInstanceList::create(this);
84  }
85  
setShadowTreeElement(SVGElement * element)86  void SVGElementInstance::setShadowTreeElement(SVGElement* element)
87  {
88      ASSERT(element);
89      m_shadowTreeElement = element;
90  }
91  
forgetWrapper()92  void SVGElementInstance::forgetWrapper()
93  {
94  #if USE(JSC)
95      // FIXME: This is fragile, as discussed with Sam. Need to find a better solution.
96      // Think about the case where JS explicitely holds "var root = useElement.instanceRoot;".
97      // We still have to recreate this wrapper somehow. The gc collection below, won't catch it.
98  
99      // If the use shadow tree has been rebuilt, just the JSSVGElementInstance objects
100      // are still holding RefPtrs of SVGElementInstance objects, which prevent us to
101      // be deleted (and the shadow tree is not destructed as well). Force JS GC.
102      gcController().garbageCollectNow();
103  #endif
104  }
105  
appendChild(PassRefPtr<SVGElementInstance> child)106  void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child)
107  {
108      appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this);
109  }
110  
invalidateAllInstancesOfElement(SVGElement * element)111  void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element)
112  {
113      if (!element)
114          return;
115  
116      HashSet<SVGElementInstance*> set = element->instancesForElement();
117      if (set.isEmpty())
118          return;
119  
120      // Find all use elements referencing the instances - ask them _once_ to rebuild.
121      HashSet<SVGElementInstance*>::const_iterator it = set.begin();
122      const HashSet<SVGElementInstance*>::const_iterator end = set.end();
123  
124      for (; it != end; ++it)
125          (*it)->setNeedsUpdate(true);
126  }
127  
setNeedsUpdate(bool value)128  void SVGElementInstance::setNeedsUpdate(bool value)
129  {
130      m_needsUpdate = value;
131  
132      if (m_needsUpdate)
133          correspondingUseElement()->setNeedsStyleRecalc();
134  }
135  
scriptExecutionContext() const136  ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const
137  {
138      if (SVGElement* element = correspondingElement())
139          return element->document();
140      return 0;
141  }
142  
addEventListener(const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)143  void SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture)
144  {
145      if (SVGElement* element = correspondingElement())
146          element->addEventListener(eventType, listener, useCapture);
147  }
148  
removeEventListener(const AtomicString & eventType,EventListener * listener,bool useCapture)149  void SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture)
150  {
151      if (SVGElement* element = correspondingElement())
152          element->removeEventListener(eventType, listener, useCapture);
153  }
154  
dispatchEvent(PassRefPtr<Event> e,ExceptionCode & ec)155  bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec)
156  {
157      RefPtr<Event> evt(e);
158      ASSERT(!eventDispatchForbidden());
159      if (!evt || evt->type().isEmpty()) {
160          ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
161          return false;
162      }
163  
164      // The event has to be dispatched to the shadowTreeElement(), not the correspondingElement()!
165      SVGElement* element = shadowTreeElement();
166      if (!element)
167          return false;
168  
169      evt->setTarget(this);
170  
171      RefPtr<FrameView> view = element->document()->view();
172      return element->dispatchGenericEvent(evt.release());
173  }
174  
onabort() const175  EventListener* SVGElementInstance::onabort() const
176  {
177      return correspondingElement()->getAttributeEventListener(eventNames().abortEvent);
178  }
179  
setOnabort(PassRefPtr<EventListener> eventListener)180  void SVGElementInstance::setOnabort(PassRefPtr<EventListener> eventListener)
181  {
182      correspondingElement()->setAttributeEventListener(eventNames().abortEvent, eventListener);
183  }
184  
onblur() const185  EventListener* SVGElementInstance::onblur() const
186  {
187      return correspondingElement()->getAttributeEventListener(eventNames().blurEvent);
188  }
189  
setOnblur(PassRefPtr<EventListener> eventListener)190  void SVGElementInstance::setOnblur(PassRefPtr<EventListener> eventListener)
191  {
192      correspondingElement()->setAttributeEventListener(eventNames().blurEvent, eventListener);
193  }
194  
onchange() const195  EventListener* SVGElementInstance::onchange() const
196  {
197      return correspondingElement()->getAttributeEventListener(eventNames().changeEvent);
198  }
199  
setOnchange(PassRefPtr<EventListener> eventListener)200  void SVGElementInstance::setOnchange(PassRefPtr<EventListener> eventListener)
201  {
202      correspondingElement()->setAttributeEventListener(eventNames().changeEvent, eventListener);
203  }
204  
onclick() const205  EventListener* SVGElementInstance::onclick() const
206  {
207      return correspondingElement()->getAttributeEventListener(eventNames().clickEvent);
208  }
209  
setOnclick(PassRefPtr<EventListener> eventListener)210  void SVGElementInstance::setOnclick(PassRefPtr<EventListener> eventListener)
211  {
212      correspondingElement()->setAttributeEventListener(eventNames().clickEvent, eventListener);
213  }
214  
oncontextmenu() const215  EventListener* SVGElementInstance::oncontextmenu() const
216  {
217      return correspondingElement()->getAttributeEventListener(eventNames().contextmenuEvent);
218  }
219  
setOncontextmenu(PassRefPtr<EventListener> eventListener)220  void SVGElementInstance::setOncontextmenu(PassRefPtr<EventListener> eventListener)
221  {
222      correspondingElement()->setAttributeEventListener(eventNames().contextmenuEvent, eventListener);
223  }
224  
ondblclick() const225  EventListener* SVGElementInstance::ondblclick() const
226  {
227      return correspondingElement()->getAttributeEventListener(eventNames().dblclickEvent);
228  }
229  
setOndblclick(PassRefPtr<EventListener> eventListener)230  void SVGElementInstance::setOndblclick(PassRefPtr<EventListener> eventListener)
231  {
232      correspondingElement()->setAttributeEventListener(eventNames().dblclickEvent, eventListener);
233  }
234  
onerror() const235  EventListener* SVGElementInstance::onerror() const
236  {
237      return correspondingElement()->getAttributeEventListener(eventNames().errorEvent);
238  }
239  
setOnerror(PassRefPtr<EventListener> eventListener)240  void SVGElementInstance::setOnerror(PassRefPtr<EventListener> eventListener)
241  {
242      correspondingElement()->setAttributeEventListener(eventNames().errorEvent, eventListener);
243  }
244  
onfocus() const245  EventListener* SVGElementInstance::onfocus() const
246  {
247      return correspondingElement()->getAttributeEventListener(eventNames().focusEvent);
248  }
249  
setOnfocus(PassRefPtr<EventListener> eventListener)250  void SVGElementInstance::setOnfocus(PassRefPtr<EventListener> eventListener)
251  {
252      correspondingElement()->setAttributeEventListener(eventNames().focusEvent, eventListener);
253  }
254  
oninput() const255  EventListener* SVGElementInstance::oninput() const
256  {
257      return correspondingElement()->getAttributeEventListener(eventNames().inputEvent);
258  }
259  
setOninput(PassRefPtr<EventListener> eventListener)260  void SVGElementInstance::setOninput(PassRefPtr<EventListener> eventListener)
261  {
262      correspondingElement()->setAttributeEventListener(eventNames().inputEvent, eventListener);
263  }
264  
onkeydown() const265  EventListener* SVGElementInstance::onkeydown() const
266  {
267      return correspondingElement()->getAttributeEventListener(eventNames().keydownEvent);
268  }
269  
setOnkeydown(PassRefPtr<EventListener> eventListener)270  void SVGElementInstance::setOnkeydown(PassRefPtr<EventListener> eventListener)
271  {
272      correspondingElement()->setAttributeEventListener(eventNames().keydownEvent, eventListener);
273  }
274  
onkeypress() const275  EventListener* SVGElementInstance::onkeypress() const
276  {
277      return correspondingElement()->getAttributeEventListener(eventNames().keypressEvent);
278  }
279  
setOnkeypress(PassRefPtr<EventListener> eventListener)280  void SVGElementInstance::setOnkeypress(PassRefPtr<EventListener> eventListener)
281  {
282      correspondingElement()->setAttributeEventListener(eventNames().keypressEvent, eventListener);
283  }
284  
onkeyup() const285  EventListener* SVGElementInstance::onkeyup() const
286  {
287      return correspondingElement()->getAttributeEventListener(eventNames().keyupEvent);
288  }
289  
setOnkeyup(PassRefPtr<EventListener> eventListener)290  void SVGElementInstance::setOnkeyup(PassRefPtr<EventListener> eventListener)
291  {
292      correspondingElement()->setAttributeEventListener(eventNames().keyupEvent, eventListener);
293  }
294  
onload() const295  EventListener* SVGElementInstance::onload() const
296  {
297      return correspondingElement()->getAttributeEventListener(eventNames().loadEvent);
298  }
299  
setOnload(PassRefPtr<EventListener> eventListener)300  void SVGElementInstance::setOnload(PassRefPtr<EventListener> eventListener)
301  {
302      correspondingElement()->setAttributeEventListener(eventNames().loadEvent, eventListener);
303  }
304  
onmousedown() const305  EventListener* SVGElementInstance::onmousedown() const
306  {
307      return correspondingElement()->getAttributeEventListener(eventNames().mousedownEvent);
308  }
309  
setOnmousedown(PassRefPtr<EventListener> eventListener)310  void SVGElementInstance::setOnmousedown(PassRefPtr<EventListener> eventListener)
311  {
312      correspondingElement()->setAttributeEventListener(eventNames().mousedownEvent, eventListener);
313  }
314  
onmousemove() const315  EventListener* SVGElementInstance::onmousemove() const
316  {
317      return correspondingElement()->getAttributeEventListener(eventNames().mousemoveEvent);
318  }
319  
setOnmousemove(PassRefPtr<EventListener> eventListener)320  void SVGElementInstance::setOnmousemove(PassRefPtr<EventListener> eventListener)
321  {
322      correspondingElement()->setAttributeEventListener(eventNames().mousemoveEvent, eventListener);
323  }
324  
onmouseout() const325  EventListener* SVGElementInstance::onmouseout() const
326  {
327      return correspondingElement()->getAttributeEventListener(eventNames().mouseoutEvent);
328  }
329  
setOnmouseout(PassRefPtr<EventListener> eventListener)330  void SVGElementInstance::setOnmouseout(PassRefPtr<EventListener> eventListener)
331  {
332      correspondingElement()->setAttributeEventListener(eventNames().mouseoutEvent, eventListener);
333  }
334  
onmouseover() const335  EventListener* SVGElementInstance::onmouseover() const
336  {
337      return correspondingElement()->getAttributeEventListener(eventNames().mouseoverEvent);
338  }
339  
setOnmouseover(PassRefPtr<EventListener> eventListener)340  void SVGElementInstance::setOnmouseover(PassRefPtr<EventListener> eventListener)
341  {
342      correspondingElement()->setAttributeEventListener(eventNames().mouseoverEvent, eventListener);
343  }
344  
onmouseup() const345  EventListener* SVGElementInstance::onmouseup() const
346  {
347      return correspondingElement()->getAttributeEventListener(eventNames().mouseupEvent);
348  }
349  
setOnmouseup(PassRefPtr<EventListener> eventListener)350  void SVGElementInstance::setOnmouseup(PassRefPtr<EventListener> eventListener)
351  {
352      correspondingElement()->setAttributeEventListener(eventNames().mouseupEvent, eventListener);
353  }
354  
onmousewheel() const355  EventListener* SVGElementInstance::onmousewheel() const
356  {
357      return correspondingElement()->getAttributeEventListener(eventNames().mousewheelEvent);
358  }
359  
setOnmousewheel(PassRefPtr<EventListener> eventListener)360  void SVGElementInstance::setOnmousewheel(PassRefPtr<EventListener> eventListener)
361  {
362      correspondingElement()->setAttributeEventListener(eventNames().mousewheelEvent, eventListener);
363  }
364  
onbeforecut() const365  EventListener* SVGElementInstance::onbeforecut() const
366  {
367      return correspondingElement()->getAttributeEventListener(eventNames().beforecutEvent);
368  }
369  
setOnbeforecut(PassRefPtr<EventListener> eventListener)370  void SVGElementInstance::setOnbeforecut(PassRefPtr<EventListener> eventListener)
371  {
372      correspondingElement()->setAttributeEventListener(eventNames().beforecutEvent, eventListener);
373  }
374  
oncut() const375  EventListener* SVGElementInstance::oncut() const
376  {
377      return correspondingElement()->getAttributeEventListener(eventNames().cutEvent);
378  }
379  
setOncut(PassRefPtr<EventListener> eventListener)380  void SVGElementInstance::setOncut(PassRefPtr<EventListener> eventListener)
381  {
382      correspondingElement()->setAttributeEventListener(eventNames().cutEvent, eventListener);
383  }
384  
onbeforecopy() const385  EventListener* SVGElementInstance::onbeforecopy() const
386  {
387      return correspondingElement()->getAttributeEventListener(eventNames().beforecopyEvent);
388  }
389  
setOnbeforecopy(PassRefPtr<EventListener> eventListener)390  void SVGElementInstance::setOnbeforecopy(PassRefPtr<EventListener> eventListener)
391  {
392      correspondingElement()->setAttributeEventListener(eventNames().beforecopyEvent, eventListener);
393  }
394  
oncopy() const395  EventListener* SVGElementInstance::oncopy() const
396  {
397      return correspondingElement()->getAttributeEventListener(eventNames().copyEvent);
398  }
399  
setOncopy(PassRefPtr<EventListener> eventListener)400  void SVGElementInstance::setOncopy(PassRefPtr<EventListener> eventListener)
401  {
402      correspondingElement()->setAttributeEventListener(eventNames().copyEvent, eventListener);
403  }
404  
onbeforepaste() const405  EventListener* SVGElementInstance::onbeforepaste() const
406  {
407      return correspondingElement()->getAttributeEventListener(eventNames().beforepasteEvent);
408  }
409  
setOnbeforepaste(PassRefPtr<EventListener> eventListener)410  void SVGElementInstance::setOnbeforepaste(PassRefPtr<EventListener> eventListener)
411  {
412      correspondingElement()->setAttributeEventListener(eventNames().beforepasteEvent, eventListener);
413  }
414  
onpaste() const415  EventListener* SVGElementInstance::onpaste() const
416  {
417      return correspondingElement()->getAttributeEventListener(eventNames().pasteEvent);
418  }
419  
setOnpaste(PassRefPtr<EventListener> eventListener)420  void SVGElementInstance::setOnpaste(PassRefPtr<EventListener> eventListener)
421  {
422      correspondingElement()->setAttributeEventListener(eventNames().pasteEvent, eventListener);
423  }
424  
ondragenter() const425  EventListener* SVGElementInstance::ondragenter() const
426  {
427      return correspondingElement()->getAttributeEventListener(eventNames().dragenterEvent);
428  }
429  
setOndragenter(PassRefPtr<EventListener> eventListener)430  void SVGElementInstance::setOndragenter(PassRefPtr<EventListener> eventListener)
431  {
432      correspondingElement()->setAttributeEventListener(eventNames().dragenterEvent, eventListener);
433  }
434  
ondragover() const435  EventListener* SVGElementInstance::ondragover() const
436  {
437      return correspondingElement()->getAttributeEventListener(eventNames().dragoverEvent);
438  }
439  
setOndragover(PassRefPtr<EventListener> eventListener)440  void SVGElementInstance::setOndragover(PassRefPtr<EventListener> eventListener)
441  {
442      correspondingElement()->setAttributeEventListener(eventNames().dragoverEvent, eventListener);
443  }
444  
ondragleave() const445  EventListener* SVGElementInstance::ondragleave() const
446  {
447      return correspondingElement()->getAttributeEventListener(eventNames().dragleaveEvent);
448  }
449  
setOndragleave(PassRefPtr<EventListener> eventListener)450  void SVGElementInstance::setOndragleave(PassRefPtr<EventListener> eventListener)
451  {
452      correspondingElement()->setAttributeEventListener(eventNames().dragleaveEvent, eventListener);
453  }
454  
ondrop() const455  EventListener* SVGElementInstance::ondrop() const
456  {
457      return correspondingElement()->getAttributeEventListener(eventNames().dropEvent);
458  }
459  
setOndrop(PassRefPtr<EventListener> eventListener)460  void SVGElementInstance::setOndrop(PassRefPtr<EventListener> eventListener)
461  {
462      correspondingElement()->setAttributeEventListener(eventNames().dropEvent, eventListener);
463  }
464  
ondragstart() const465  EventListener* SVGElementInstance::ondragstart() const
466  {
467      return correspondingElement()->getAttributeEventListener(eventNames().dragstartEvent);
468  }
469  
setOndragstart(PassRefPtr<EventListener> eventListener)470  void SVGElementInstance::setOndragstart(PassRefPtr<EventListener> eventListener)
471  {
472      correspondingElement()->setAttributeEventListener(eventNames().dragstartEvent, eventListener);
473  }
474  
ondrag() const475  EventListener* SVGElementInstance::ondrag() const
476  {
477      return correspondingElement()->getAttributeEventListener(eventNames().dragEvent);
478  }
479  
setOndrag(PassRefPtr<EventListener> eventListener)480  void SVGElementInstance::setOndrag(PassRefPtr<EventListener> eventListener)
481  {
482      correspondingElement()->setAttributeEventListener(eventNames().dragEvent, eventListener);
483  }
484  
ondragend() const485  EventListener* SVGElementInstance::ondragend() const
486  {
487      return correspondingElement()->getAttributeEventListener(eventNames().dragendEvent);
488  }
489  
setOndragend(PassRefPtr<EventListener> eventListener)490  void SVGElementInstance::setOndragend(PassRefPtr<EventListener> eventListener)
491  {
492      correspondingElement()->setAttributeEventListener(eventNames().dragendEvent, eventListener);
493  }
494  
onreset() const495  EventListener* SVGElementInstance::onreset() const
496  {
497      return correspondingElement()->getAttributeEventListener(eventNames().resetEvent);
498  }
499  
setOnreset(PassRefPtr<EventListener> eventListener)500  void SVGElementInstance::setOnreset(PassRefPtr<EventListener> eventListener)
501  {
502      correspondingElement()->setAttributeEventListener(eventNames().resetEvent, eventListener);
503  }
504  
onresize() const505  EventListener* SVGElementInstance::onresize() const
506  {
507      return correspondingElement()->getAttributeEventListener(eventNames().resizeEvent);
508  }
509  
setOnresize(PassRefPtr<EventListener> eventListener)510  void SVGElementInstance::setOnresize(PassRefPtr<EventListener> eventListener)
511  {
512      correspondingElement()->setAttributeEventListener(eventNames().resizeEvent, eventListener);
513  }
514  
onscroll() const515  EventListener* SVGElementInstance::onscroll() const
516  {
517      return correspondingElement()->getAttributeEventListener(eventNames().scrollEvent);
518  }
519  
setOnscroll(PassRefPtr<EventListener> eventListener)520  void SVGElementInstance::setOnscroll(PassRefPtr<EventListener> eventListener)
521  {
522      correspondingElement()->setAttributeEventListener(eventNames().scrollEvent, eventListener);
523  }
524  
onsearch() const525  EventListener* SVGElementInstance::onsearch() const
526  {
527      return correspondingElement()->getAttributeEventListener(eventNames().searchEvent);
528  }
529  
setOnsearch(PassRefPtr<EventListener> eventListener)530  void SVGElementInstance::setOnsearch(PassRefPtr<EventListener> eventListener)
531  {
532      correspondingElement()->setAttributeEventListener(eventNames().searchEvent, eventListener);
533  }
534  
onselect() const535  EventListener* SVGElementInstance::onselect() const
536  {
537      return correspondingElement()->getAttributeEventListener(eventNames().selectEvent);
538  }
539  
setOnselect(PassRefPtr<EventListener> eventListener)540  void SVGElementInstance::setOnselect(PassRefPtr<EventListener> eventListener)
541  {
542      correspondingElement()->setAttributeEventListener(eventNames().selectEvent, eventListener);
543  }
544  
onselectstart() const545  EventListener* SVGElementInstance::onselectstart() const
546  {
547      return correspondingElement()->getAttributeEventListener(eventNames().selectstartEvent);
548  }
549  
setOnselectstart(PassRefPtr<EventListener> eventListener)550  void SVGElementInstance::setOnselectstart(PassRefPtr<EventListener> eventListener)
551  {
552      correspondingElement()->setAttributeEventListener(eventNames().selectstartEvent, eventListener);
553  }
554  
onsubmit() const555  EventListener* SVGElementInstance::onsubmit() const
556  {
557      return correspondingElement()->getAttributeEventListener(eventNames().submitEvent);
558  }
559  
setOnsubmit(PassRefPtr<EventListener> eventListener)560  void SVGElementInstance::setOnsubmit(PassRefPtr<EventListener> eventListener)
561  {
562      correspondingElement()->setAttributeEventListener(eventNames().submitEvent, eventListener);
563  }
564  
onunload() const565  EventListener* SVGElementInstance::onunload() const
566  {
567      return correspondingElement()->getAttributeEventListener(eventNames().unloadEvent);
568  }
569  
setOnunload(PassRefPtr<EventListener> eventListener)570  void SVGElementInstance::setOnunload(PassRefPtr<EventListener> eventListener)
571  {
572      correspondingElement()->setAttributeEventListener(eventNames().unloadEvent, eventListener);
573  }
574  
575  }
576  
577  #endif // ENABLE(SVG)
578