Prettier buttons
[scpubgit/stemmaweb.git] / root / js / jquery.svgdom.js
1 /* http://keith-wood.name/svg.html\r
2    SVG/jQuery DOM compatibility for jQuery v1.4.3.\r
3    Written by Keith Wood (kbwood{at}iinet.com.au) April 2009.\r
4    Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and \r
5    MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. \r
6    Please attribute the author if you use it. */\r
7 \r
8 (function($) { // Hide scope, no $ conflict\r
9 \r
10 /* Support adding class names to SVG nodes. */\r
11 $.fn.addClass = function(origAddClass) {\r
12         return function(classNames) {\r
13                 classNames = classNames || '';\r
14                 return this.each(function() {\r
15                         if (isSVGElem(this)) {\r
16                                 var node = this;\r
17                                 $.each(classNames.split(/\s+/), function(i, className) {\r
18                                         var classes = (node.className ? node.className.baseVal : node.getAttribute('class'));\r
19                                         if ($.inArray(className, classes.split(/\s+/)) == -1) {\r
20                                                 classes += (classes ? ' ' : '') + className;\r
21                                                 (node.className ? node.className.baseVal = classes :\r
22                                                         node.setAttribute('class',  classes));\r
23                                         }\r
24                                 });\r
25                         }\r
26                         else {\r
27                                 origAddClass.apply($(this), [classNames]);\r
28                         }\r
29                 });\r
30         };\r
31 }($.fn.addClass);\r
32 \r
33 /* Support removing class names from SVG nodes. */\r
34 $.fn.removeClass = function(origRemoveClass) {\r
35         return function(classNames) {\r
36                 classNames = classNames || '';\r
37                 return this.each(function() {\r
38                         if (isSVGElem(this)) {\r
39                                 var node = this;\r
40                                 $.each(classNames.split(/\s+/), function(i, className) {\r
41                                         var classes = (node.className ? node.className.baseVal : node.getAttribute('class'));\r
42                                         classes = $.grep(classes.split(/\s+/), function(n, i) { return n != className; }).\r
43                                                 join(' ');\r
44                                         (node.className ? node.className.baseVal = classes :\r
45                                                 node.setAttribute('class', classes));\r
46                                 });\r
47                         }\r
48                         else {\r
49                                 origRemoveClass.apply($(this), [classNames]);\r
50                         }\r
51                 });\r
52         };\r
53 }($.fn.removeClass);\r
54 \r
55 /* Support toggling class names on SVG nodes. */\r
56 $.fn.toggleClass = function(origToggleClass) {\r
57         return function(className, state) {\r
58                 return this.each(function() {\r
59                         if (isSVGElem(this)) {\r
60                                 if (typeof state !== 'boolean') {\r
61                                         state = !$(this).hasClass(className);\r
62                                 }\r
63                                 $(this)[(state ? 'add' : 'remove') + 'Class'](className);\r
64                         }\r
65                         else {\r
66                                 origToggleClass.apply($(this), [className, state]);\r
67                         }\r
68                 });\r
69         };\r
70 }($.fn.toggleClass);\r
71 \r
72 /* Support checking class names on SVG nodes. */\r
73 $.fn.hasClass = function(origHasClass) {\r
74         return function(className) {\r
75                 className = className || '';\r
76                 var found = false;\r
77                 this.each(function() {\r
78                         if (isSVGElem(this)) {\r
79                                 var classes = (this.className ? this.className.baseVal :\r
80                                         this.getAttribute('class')).split(/\s+/);\r
81                                 found = ($.inArray(className, classes) > -1);\r
82                         }\r
83                         else {\r
84                                 found = (origHasClass.apply($(this), [className]));\r
85                         }\r
86                         return !found;\r
87                 });\r
88                 return found;\r
89         };\r
90 }($.fn.hasClass);\r
91 \r
92 /* Support attributes on SVG nodes. */\r
93 $.fn.attr = function(origAttr) {\r
94         return function(name, value, type) {\r
95                 if (typeof name === 'string' && value === undefined) {\r
96                         var val = origAttr.apply(this, [name, value, type]);\r
97                         if (val && val.baseVal && val.baseVal.numberOfItems != null) { // Transform\r
98                                 value = '';\r
99                                 val = val.baseVal;\r
100                                 for (var i = 0; i < val.numberOfItems; i++) {\r
101                                         var item = val.getItem(i);\r
102                                         switch (item.type) {\r
103                                                 case 1: value += ' matrix(' + item.matrix.a + ',' + item.matrix.b + ',' +\r
104                                                                         item.matrix.c + ',' + item.matrix.d + ',' +\r
105                                                                         item.matrix.e + ',' + item.matrix.f + ')';\r
106                                                                 break;\r
107                                                 case 2: value += ' translate(' + item.matrix.e + ',' + item.matrix.f + ')'; break;\r
108                                                 case 3: value += ' scale(' + item.matrix.a + ',' + item.matrix.d + ')'; break;\r
109                                                 case 4: value += ' rotate(' + item.angle + ')'; break; // Doesn't handle new origin\r
110                                                 case 5: value += ' skewX(' + item.angle + ')'; break;\r
111                                                 case 6: value += ' skewY(' + item.angle + ')'; break;\r
112                                         }\r
113                                 }\r
114                                 val = value.substring(1);\r
115                         }\r
116                         return (val && val.baseVal ? val.baseVal.valueAsString : val);\r
117                 }\r
118                 var options = name;\r
119                 if (typeof name === 'string') {\r
120                         options = {};\r
121                         options[name] = value;\r
122                 }\r
123                 return this.each(function() {\r
124                         if (isSVGElem(this)) {\r
125                                 for (var n in options) {\r
126                                         var val = ($.isFunction(options[n]) ? options[n]() : options[n]);\r
127                                         (type ? this.style[n] = val : this.setAttribute(n, val));\r
128                                 }\r
129                         }\r
130                         else {\r
131                                 origAttr.apply($(this), [name, value, type]);\r
132                         }\r
133                 });\r
134         };\r
135 }($.fn.attr);\r
136 \r
137 /* Support removing attributes on SVG nodes. */\r
138 $.fn.removeAttr = function(origRemoveAttr) {\r
139         return function(name) {\r
140                 return this.each(function() {\r
141                         if (isSVGElem(this)) {\r
142                                 (this[name] && this[name].baseVal ? this[name].baseVal.value = '' :\r
143                                         this.setAttribute(name, ''));\r
144                         }\r
145                         else {\r
146                                 origRemoveAttr.apply($(this), [name]);\r
147                         }\r
148                 });\r
149         };\r
150 }($.fn.removeAttr);\r
151 \r
152 /* Determine if any nodes are SVG nodes. */\r
153 function anySVG(checkSet) {\r
154         for (var i = 0; i < checkSet.length; i++) {\r
155                 if (checkSet[i].nodeType == 1 && checkSet[i].namespaceURI == $.svg.svgNS) {\r
156                         return true;\r
157                 }\r
158         }\r
159         return false;\r
160 }\r
161 \r
162 /* Update Sizzle selectors. */\r
163 \r
164 $.expr.relative['+'] = function(origRelativeNext) {\r
165         return function(checkSet, part, isXML) {\r
166                 origRelativeNext(checkSet, part, isXML || anySVG(checkSet));\r
167         };\r
168 }($.expr.relative['+']);\r
169 \r
170 $.expr.relative['>'] = function(origRelativeChild) {\r
171         return function(checkSet, part, isXML) {\r
172                 origRelativeChild(checkSet, part, isXML || anySVG(checkSet));\r
173         };\r
174 }($.expr.relative['>']);\r
175 \r
176 $.expr.relative[''] = function(origRelativeDescendant) {\r
177         return function(checkSet, part, isXML) {\r
178                 origRelativeDescendant(checkSet, part, isXML || anySVG(checkSet));\r
179         };\r
180 }($.expr.relative['']);\r
181 \r
182 $.expr.relative['~'] = function(origRelativeSiblings) {\r
183         return function(checkSet, part, isXML) {\r
184                 origRelativeSiblings(checkSet, part, isXML || anySVG(checkSet));\r
185         };\r
186 }($.expr.relative['~']);\r
187 \r
188 $.expr.find.ID = function(origFindId) {\r
189         return function(match, context, isXML) {\r
190                 return (isSVGElem(context) ?\r
191                         [context.ownerDocument.getElementById(match[1])] :\r
192                         origFindId(match, context, isXML));\r
193         };\r
194 }($.expr.find.ID);\r
195 \r
196 var div = document.createElement('div');\r
197 div.appendChild(document.createComment(''));\r
198 if (div.getElementsByTagName('*').length > 0) { // Make sure no comments are found\r
199         $.expr.find.TAG = function(match, context) {\r
200                 var results = context.getElementsByTagName(match[1]);\r
201                 if (match[1] === '*') { // Filter out possible comments\r
202                         var tmp = [];\r
203                         for (var i = 0; results[i] || results.item(i); i++) {\r
204                                 if ((results[i] || results.item(i)).nodeType === 1) {\r
205                                         tmp.push(results[i] || results.item(i));\r
206                                 }\r
207                         }\r
208                         results = tmp;\r
209                 }\r
210                 return results;\r
211         };\r
212 }\r
213 \r
214 $.expr.preFilter.CLASS = function(match, curLoop, inplace, result, not, isXML) {\r
215         match = ' ' + match[1].replace(/\\/g, '') + ' ';\r
216         if (isXML) {\r
217                 return match;\r
218         }\r
219         for (var i = 0, elem = {}; elem != null; i++) {\r
220                 elem = curLoop[i];\r
221                 if (!elem) {\r
222                         try {\r
223                                 elem = curLoop.item(i);\r
224                         }\r
225                         catch (e) {\r
226                                 // Ignore\r
227                         }\r
228                 }\r
229                 if (elem) {\r
230                         var className = (!isSVGElem(elem) ? elem.className :\r
231                                 (elem.className ? elem.className.baseVal : '') || elem.getAttribute('class'));\r
232                         if (not ^ (className && (' ' + className + ' ').indexOf(match) > -1)) {\r
233                                 if (!inplace)\r
234                                         result.push(elem);\r
235                         }\r
236                         else if (inplace) {\r
237                                 curLoop[i] = false;\r
238                         }\r
239                 }\r
240         }\r
241         return false;\r
242 };\r
243 \r
244 $.expr.filter.CLASS = function(elem, match) {\r
245         var className = (!isSVGElem(elem) ? elem.className :\r
246                 (elem.className ? elem.className.baseVal : elem.getAttribute('class')));\r
247         return (' ' + className + ' ').indexOf(match) > -1;\r
248 };\r
249 \r
250 $.expr.filter.ATTR = function(origFilterAttr) {\r
251         return function(elem, match) {\r
252                 var handler = null;\r
253                 if (isSVGElem(elem)) {\r
254                         handler = match[1];\r
255                         $.expr.attrHandle[handler] = function(elem){\r
256                                 var attr = elem.getAttribute(handler);\r
257                                 return attr && attr.baseVal || attr;\r
258                         };\r
259                 }\r
260                 var filter = origFilterAttr(elem, match);\r
261                 if (handler) {\r
262                         $.expr.attrHandle[handler] = null;\r
263                 }\r
264                 return filter;\r
265         };\r
266 }($.expr.filter.ATTR);\r
267 \r
268 /*\r
269         Change Sizzle initialisation (line 1425) in jQuery v1.3.2 base code...\r
270         \r
271         if ( toString.call(checkSet) === "[object Array]" ) {\r
272                 if ( !prune ) {\r
273                         results.push.apply( results, checkSet );\r
274                 } else if ( context.nodeType === 1 ) {\r
275                         for ( var i = 0; checkSet[i] != null; i++ ) {\r
276                                 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && contains(context, checkSet[i])) ) {\r
277                                         results.push( set[i] || set.item(i) ); // Here\r
278                                 }\r
279                         }\r
280                 } else {\r
281                         for ( var i = 0; checkSet[i] != null; i++ ) {\r
282                                 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {\r
283                                         results.push( set[i] || set.item(i) ); // Here\r
284                                 }\r
285                         }\r
286                 }\r
287         }\r
288         \r
289         Change fallback makeArray (line 2076) implementation in jQuery Sizzle...\r
290         \r
291                         if ( typeof array.length === "number" ) {\r
292                                 for ( var i = 0, l = array.length; i < l; i++ ) {\r
293                                         ret.push( array[i] || array.item(i) ); // Here\r
294                                 }\r
295                         }\r
296 */\r
297 \r
298 /*\r
299         Events management requires changes to jQuery v1.3.2 base code...\r
300 \r
301         In $.event.add (line 2437)...\r
302         \r
303                                 if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem, data, namespaces) === false ) {\r
304                                         // Bind the global event handler to the element\r
305                                         try { // Here\r
306                                                 elem.addEventListener(type, handle, false);\r
307                                         }\r
308                                         catch(e) {\r
309                                                 if (elem.attachEvent)\r
310                                                         elem.attachEvent("on" + type, handle);\r
311                                         }\r
312                                 }\r
313 \r
314         In $.event.remove (line 2521)...\r
315         \r
316                                                         if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem, namespaces) === false ) {\r
317                                                                 try { // Here\r
318                                                                         elem.removeEventListener(type, jQuery.data(elem, "handle"), false);\r
319                                                                 }\r
320                                                                 catch (e) {\r
321                                                                         if (elem.detachEvent)\r
322                                                                                 elem.detachEvent("on" + type, jQuery.data(elem, "handle"));\r
323                                                                 }\r
324                                                         }\r
325 */\r
326 \r
327 /* Does this node belong to SVG? */\r
328 function isSVGElem(node) {\r
329         return (node.nodeType == 1 && node.namespaceURI == $.svg.svgNS);\r
330 }\r
331 \r
332 })(jQuery);\r