4 SVG Renderer for PlotKit
8 Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
9 For use under the BSD license. <http://www.liquidx.net/plotkit>
12 // -------------------------------------------------------------------------
13 // NOTES: - If you use XHTML1.1 strict, then you must include each MochiKit
15 // - For IE support, you must include the AdobeSVG object hack.
16 // See tests/svg.html
for details
.
17 // -------------------------------------------------------------------------
18 // -------------------------------------------------------------------------
19 // Check required components
20 // -------------------------------------------------------------------------
23 if (typeof(PlotKit
.Layout
) == 'undefined')
29 throw "PlotKit depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.Layout"
33 // ---------------------------------------------------------------------------
35 // ---------------------------------------------------------------------------
37 PlotKit
.SVGRenderer
= function(element
, layout
, options
) {
38 if (arguments
.length
> 0)
39 this.__init__(element
, layout
, options
);
42 PlotKit
.SVGRenderer
.NAME
= "PlotKit.SVGRenderer";
43 PlotKit
.SVGRenderer
.VERSION
= PlotKit
.VERSION
;
45 PlotKit
.SVGRenderer
.__repr__
= function() {
46 return "[" + this.NAME
+ " " + this.VERSION
+ "]";
49 PlotKit
.SVGRenderer
.toString
= function() {
50 return this.__repr__();
53 PlotKit
.SVGRenderer
.SVGNS
= 'http://www.w3.org/2000/svg';
55 PlotKit
.SVGRenderer
.prototype.__init__
= function(element
, layout
, options
) {
56 var isNil
= MochiKit
.Base
.isUndefinedOrNull
;
60 "drawBackground": true,
61 "backgroundColor": Color
.whiteColor(),
62 "padding": {left
: 30, right
: 30, top
: 5, bottom
: 10},
63 "colorScheme": PlotKit
.Base
.palette(PlotKit
.Base
.baseColors()[1]),
64 "strokeColor": Color
.whiteColor(),
65 "strokeColorTransform": "asStrokeColor",
71 "axisLineColor": Color
.blackColor(),
74 "axisLabelColor": Color
.blackColor(),
75 "axisLabelFont": "Arial",
76 "axisLabelFontSize": 9,
78 "axisLabelUseDiv": true,
83 MochiKit
.Base
.update(this.options
, options
? options
: {});
85 this.element
= MochiKit
.DOM
.getElement(element
);
86 this.container
= this.element
.parentNode
;
87 this.height
= parseInt(this.element
.getAttribute("height"));
88 this.width
= parseInt(this.element
.getAttribute("width"));
89 this.document
= document
;
90 this.root
= this.element
;
93 // - if an exception is thrown, then no Adobe SVG Plugin support.
95 this.document
= this.element
.getSVGDocument();
96 this.root
= isNil(this.document
.documentElement
) ? this.element
: this.document
.documentElement
;
101 this.element
.style
.zIndex
= 1;
103 if (isNil(this.element
))
104 throw "SVGRenderer() - passed SVG object is not found";
106 if (isNil(this.container
) || this.container
.nodeName
.toLowerCase() != "div")
107 throw "SVGRenderer() - No DIV's around the SVG.";
110 this.xlabels
= new Array();
111 this.ylabels
= new Array();
113 // initialise some meta structures in SVG
114 this.defs
= this.createSVGElement("defs");
117 x
: this.options
.padding
.left
,
118 y
: this.options
.padding
.top
,
119 w
: this.width
- this.options
.padding
.left
- this.options
.padding
.right
,
120 h
: this.height
- this.options
.padding
.top
- this.options
.padding
.bottom
123 MochiKit
.DOM
.updateNodeAttributes(this.container
,
124 {"style":{ "position": "relative", "width": this.width
+ "px"}});
130 PlotKit
.SVGRenderer
.prototype.render
= function() {
131 if (this.options
.drawBackground
)
132 this._renderBackground();
134 if (this.layout
.style
== "bar") {
135 this._renderBarChart();
136 this._renderBarAxis();
138 else if (this.layout
.style
== "pie") {
139 this._renderPieChart();
140 this._renderPieAxis();
142 else if (this.layout
.style
== "line") {
143 this._renderLineChart();
144 this._renderLineAxis();
148 PlotKit
.SVGRenderer
.prototype._renderBarOrLine
= function(data
, plotFunc
, startFunc
, endFunc
) {
150 var colorCount
= this.options
.colorScheme
.length
;
151 var colorScheme
= this.options
.colorScheme
;
152 var setNames
= MochiKit
.Base
.keys(this.layout
.datasets
);
153 var setCount
= setNames
.length
;
155 for (var i
= 0; i
< setCount
; i
++) {
156 var setName
= setNames
[i
];
157 var attrs
= new Array();
158 var color
= colorScheme
[i
%colorCount
];
160 if (this.options
.shouldFill
)
161 attrs
["fill"] = color
.toRGBString();
163 attrs
["fill"] = "none";
165 if (this.options
.shouldStroke
&&
166 (this.options
.strokeColor
|| this.options
.strokeColorTransform
)) {
167 if (this.options
.strokeColor
)
168 attrs
["stroke"] = this.options
.strokeColor
.toRGBString();
169 else if (this.options
.strokeColorTransform
)
170 attrs
["stroke"] = color
[this.options
.strokeColorTransform
]().toRGBString();
171 attrs
["strokeWidth"] = this.options
.strokeWidth
;
177 var forEachFunc
= function(obj
) {
178 if (obj
.name
== setName
)
179 plotFunc(attrs
, obj
);
182 MochiKit
.Iter
.forEach(data
, bind(forEachFunc
, this));
188 PlotKit
.SVGRenderer
.prototype._renderBarChart
= function() {
189 var bind
= MochiKit
.Base
.bind
;
191 var drawRect
= function(attrs
, bar
) {
192 var x
= this.area
.w
* bar
.x
+ this.area
.x
;
193 var y
= this.area
.h
* bar
.y
+ this.area
.y
;
194 var w
= this.area
.w
* bar
.w
;
195 var h
= this.area
.h
* bar
.h
;
196 this._drawRect(x
, y
, w
, h
, attrs
);
198 this._renderBarOrLine(this.layout
.bars
, bind(drawRect
, this));
201 PlotKit
.SVGRenderer
.prototype._renderLineChart
= function() {
202 var bind
= MochiKit
.Base
.bind
;
204 var addPoint
= function(attrs
, point
) {
205 this._tempPointsBuffer
+= (this.area
.w
* point
.x
+ this.area
.x
) + "," +
206 (this.area
.h
* point
.y
+ this.area
.y
) + " ";
209 var startLine
= function(attrs
) {
210 this._tempPointsBuffer
= "";
211 this._tempPointsBuffer
+= (this.area
.x
) + "," + (this.area
.y
+this.area
.h
) + " ";
214 var endLine
= function(attrs
) {
215 this._tempPointsBuffer
+= (this.area
.w
+ this.area
.x
) + "," +(this.area
.h
+ this.area
.y
);
216 attrs
["points"] = this._tempPointsBuffer
;
217 var elem
= this.createSVGElement("polygon", attrs
);
218 this.root
.appendChild(elem
);
221 this._renderBarOrLine(this.layout
.points
,
222 bind(addPoint
, this),
223 bind(startLine
, this),
224 bind(endLine
, this));
228 PlotKit
.SVGRenderer
.prototype._renderPieChart
= function() {
229 var colorCount
= this.options
.colorScheme
.length
;
230 var slices
= this.layout
.slices
;
232 var centerx
= this.area
.x
+ this.area
.w
* 0.5;
233 var centery
= this.area
.y
+ this.area
.h
* 0.5;
234 var radius
= Math
.min(this.area
.w
* this.options
.pieRadius
,
235 this.area
.h
* this.options
.pieRadius
);
237 // NOTE NOTE!! Canvas Tag draws the circle clockwise from the y = 0, x = 1
238 // so we have to subtract 90 degrees to make it start at y = 1, x = 0
240 // workaround if we only have 1 slice of 100%
241 if (slices
.length
== 1 && (Math
.abs(slices
[0].startAngle
) - Math
.abs(slices
[0].endAngle
) < 0.1)) {
242 var attrs
= {"cx": centerx
, "cy": centery
, "r": radius
};
243 var color
= this.options
.colorScheme
[0];
244 if (this.options
.shouldFill
)
245 attrs
["fill"] = color
.toRGBString();
247 attrs
["fill"] = "none";
249 if (this.options
.shouldStroke
&&
250 (this.options
.strokeColor
|| this.options
.strokeColorTransform
)) {
251 if (this.options
.strokeColor
)
252 attrs
["stroke"] = this.options
.strokeColor
.toRGBString();
253 else if (this.options
.strokeColorTransform
)
254 attrs
["stroke"] = color
[this.options
.strokeColorTransform
]().toRGBString();
255 attrs
["style"] = "stroke-width: " + this.options
.strokeWidth
;
258 this.root
.appendChild(this.createSVGElement("circle", attrs
));
262 for (var i
= 0; i
< slices
.length
; i
++) {
263 var attrs
= new Array();
264 var color
= this.options
.colorScheme
[i
%colorCount
];
265 if (this.options
.shouldFill
)
266 attrs
["fill"] = color
.toRGBString();
268 attrs
["fill"] = "none";
270 if (this.options
.shouldStroke
&&
271 (this.options
.strokeColor
|| this.options
.strokeColorTransform
)) {
272 if (this.options
.strokeColor
)
273 attrs
["stroke"] = this.options
.strokeColor
.toRGBString();
274 else if (this.options
.strokeColorTransform
)
275 attrs
["stroke"] = color
[this.options
.strokeColorTransform
]().toRGBString();
276 attrs
["style"] = "stroke-width:" + this.options
.strokeWidth
;
280 if (Math
.abs(slices
[i
].endAngle
- slices
[i
].startAngle
) > Math
.PI
)
282 var x1
= Math
.cos(slices
[i
].startAngle
- Math
.PI
/2) * radius
;
283 var y1
= Math
.sin(slices
[i
].startAngle
- Math
.PI
/2) * radius
;
284 var x2
= Math
.cos(slices
[i
].endAngle
- Math
.PI
/2) * radius
;
285 var y2
= Math
.sin(slices
[i
].endAngle
- Math
.PI
/2) * radius
;
289 var pathString
= "M" + centerx
+ "," + centery
+ " ";
290 pathString
+= "l" + x1
+ "," + y1
+ " ";
291 pathString
+= "a" + radius
+ "," + radius
+ " 0 " + largearc
+ ",1 " + rx
+ "," + ry
+ " z";
293 attrs
["d"] = pathString
;
295 var elem
= this.createSVGElement("path", attrs
);
296 this.root
.appendChild(elem
);
300 PlotKit
.SVGRenderer
.prototype._renderBarAxis
= function() {
304 PlotKit
.SVGRenderer
.prototype._renderLineAxis
= function() {
309 PlotKit
.SVGRenderer
.prototype._renderAxis
= function() {
311 if (!this.options
.drawXAxis
&& !this.options
.drawYAxis
)
314 var labelStyle
= {"style":
315 {"position": "absolute",
316 "textAlign": "center",
317 "fontSize": this.options
.axisLabelFontSize
+ "px",
319 "color": this.options
.axisLabelColor
.toRGBString(),
320 "width": this.options
.axisLabelWidth
+ "px",
327 "stroke": this.options
.axisLineColor
.toRGBString(),
328 "strokeWidth": this.options
.axisLineWidth
332 if (this.options
.drawYAxis
) {
333 if (this.layout
.yticks
) {
334 var drawTick
= function(tick
) {
336 var y
= this.area
.y
+ tick
[0] * this.area
.h
;
337 this._drawLine(x
, y
, x
- 3, y
, lineAttrs
);
339 if (this.options
.axisLabelUseDiv
) {
340 var label
= DIV(labelStyle
, tick
[1]);
341 label
.style
.top
= (y
- this.options
.axisLabelFontSize
) + "px";
342 label
.style
.left
= (x
- this.options
.padding
.left
+ this.options
.axisTickSize
) + "px";
343 label
.style
.textAlign
= "left";
344 label
.style
.width
= (this.options
.padding
.left
- 3) + "px";
345 MochiKit
.DOM
.appendChildNodes(this.container
, label
);
346 this.ylabels
.push(label
);
351 x
: (x
- this.options
.padding
.left
+ 3),
352 width
: (this.options
.padding
.left
- this.options
.axisTickSize
) + "px",
353 height
: (this.options
.axisLabelFontSize
+ 3) + "px",
355 fontSize
: this.options
.axisLabelFontSize
+ "px",
356 fill
: this.options
.axisLabelColor
.toRGBString()
359 /* we can do clipping just like DIVs
360 http://www.xml.com/pub/a/2004/06/02/svgtype.html */
362 var mask = this.createSVGElement("mask", {id: "mask" + tick[0]});
363 var maskShape = this.createSVGElement("rect",
365 x: (x - this.options.padding.left + 3),
366 width: (this.options.padding.left - this.options.axisTickSize) + "px",
367 height: (this.options.axisLabelFontSize + 3) + "px",
368 style: {"fill": "#ffffff", "stroke": "#000000"}});
369 mask.appendChild(maskShape);
370 this.defs.appendChild(mask);
372 attrs["filter"] = "url(#mask" + tick[0] + ")";
375 var label
= this.createSVGElement("text", attrs
);
376 label
.appendChild(this.document
.createTextNode(tick
[1]));
377 this.root
.appendChild(label
);
381 MochiKit
.Iter
.forEach(this.layout
.yticks
, bind(drawTick
, this));
384 this._drawLine(this.area
.x
, this.area
.y
, this.area
.x
, this.area
.y
+ this.area
.h
, lineAttrs
);
387 if (this.options
.drawXAxis
) {
388 if (this.layout
.xticks
) {
389 var drawTick
= function(tick
) {
390 var x
= this.area
.x
+ tick
[0] * this.area
.w
;
391 var y
= this.area
.y
+ this.area
.h
;
392 this._drawLine(x
, y
, x
, y
+ this.options
.axisTickSize
, lineAttrs
);
394 if (this.options
.axisLabelUseDiv
) {
395 var label
= DIV(labelStyle
, tick
[1]);
396 label
.style
.top
= (y
+ this.options
.axisTickSize
) + "px";
397 label
.style
.left
= (x
- this.options
.axisLabelWidth
/2) + "px";
398 label
.style
.textAlign
= "center";
399 label
.style
.width
= this.options
.axisLabelWidth
+ "px";
400 MochiKit
.DOM
.appendChildNodes(this.container
, label
);
401 this.xlabels
.push(label
);
405 y
: (y
+ this.options
.axisTickSize
+ this.options
.axisLabelFontSize
),
407 width
: this.options
.axisLabelWidth
+ "px",
408 height
: (this.options
.axisLabelFontSize
+ 3) + "px",
410 fontSize
: this.options
.axisLabelFontSize
+ "px",
411 fill
: this.options
.axisLabelColor
.toRGBString(),
414 var label
= this.createSVGElement("text", attrs
);
415 label
.appendChild(this.document
.createTextNode(tick
[1]));
416 this.root
.appendChild(label
);
420 MochiKit
.Iter
.forEach(this.layout
.xticks
, bind(drawTick
, this));
423 this._drawLine(this.area
.x
, this.area
.y
+ this.area
.h
, this.area
.x
+ this.area
.w
, this.area
.y
+ this.area
.h
, lineAttrs
)
427 PlotKit
.SVGRenderer
.prototype._renderPieAxis
= function() {
429 if (this.layout
.xticks
) {
430 // make a lookup dict for x->slice values
431 var lookup
= new Array();
432 for (var i
= 0; i
< this.layout
.slices
.length
; i
++) {
433 lookup
[this.layout
.slices
[i
].xval
] = this.layout
.slices
[i
];
436 var centerx
= this.area
.x
+ this.area
.w
* 0.5;
437 var centery
= this.area
.y
+ this.area
.h
* 0.5;
438 var radius
= Math
.min(this.area
.w
* this.options
.pieRadius
+ 10,
439 this.area
.h
* this.options
.pieRadius
+ 10);
440 var labelWidth
= this.options
.axisLabelWidth
;
442 for (var i
= 0; i
< this.layout
.xticks
.length
; i
++) {
443 var slice
= lookup
[this.layout
.xticks
[i
][0]];
444 if (MochiKit
.Base
.isUndefinedOrNull(slice
))
448 var angle
= (slice
.startAngle
+ slice
.endAngle
)/2;
449 // normalize the angle
450 var normalisedAngle
= angle
;
451 if (normalisedAngle
> Math
.PI
* 2)
452 normalisedAngle
= normalisedAngle
- Math
.PI
* 2;
453 else if (normalisedAngle
< 0)
454 normalisedAngle
= normalisedAngle
+ Math
.PI
* 2;
456 var labelx
= centerx
+ Math
.sin(normalisedAngle
) * (radius
+ 10);
457 var labely
= centery
- Math
.cos(normalisedAngle
) * (radius
+ 10);
460 "position": "absolute",
462 "width": labelWidth
+ "px",
463 "fontSize": this.options
.axisLabelFontSize
+ "px",
464 "overflow": "hidden",
465 "color": this.options
.axisLabelColor
.toHexString()
469 "width": labelWidth
+ "px",
470 "fontSize": this.options
.axisLabelFontSize
+ "px",
471 "height": (this.options
.axisLabelFontSize
+ 3) + "px",
472 "fill": this.options
.axisLabelColor
.toRGBString()
475 if (normalisedAngle
<= Math
.PI
* 0.5) {
476 // text on top and align left
477 MochiKit
.Base
.update(attrib
, {
478 'textAlign': 'left', 'verticalAlign': 'top',
479 'left': labelx
+ 'px',
480 'top': (labely
- this.options
.axisLabelFontSize
) + "px"
482 MochiKit
.Base
.update(svgattrib
, {
484 "y" :(labely
- this.options
.axisLabelFontSize
),
488 else if ((normalisedAngle
> Math
.PI
* 0.5) && (normalisedAngle
<= Math
.PI
)) {
489 // text on bottom and align left
490 MochiKit
.Base
.update(attrib
, {
491 'textAlign': 'left', 'verticalAlign': 'bottom',
492 'left': labelx
+ 'px',
495 MochiKit
.Base
.update(svgattrib
, {
496 'textAnchor': 'left',
501 else if ((normalisedAngle
> Math
.PI
) && (normalisedAngle
<= Math
.PI
*1.5)) {
502 // text on bottom and align right
503 MochiKit
.Base
.update(attrib
, {
504 'textAlign': 'right', 'verticalAlign': 'bottom',
505 'left': labelx
+ 'px',
508 MochiKit
.Base
.update(svgattrib
, {
509 'textAnchor': 'right',
510 'x': labelx
- labelWidth
,
515 // text on top and align right
516 MochiKit
.Base
.update(attrib
, {
517 'textAlign': 'left', 'verticalAlign': 'bottom',
518 'left': labelx
+ 'px',
521 MochiKit
.Base
.update(svgattrib
, {
522 'textAnchor': 'left',
523 'x': labelx
- labelWidth
,
524 'y': labely
- this.options
.axisLabelFontSize
528 if (this.options
.axisLabelUseDiv
) {
529 var label
= DIV({'style': attrib
}, this.layout
.xticks
[i
][1]);
530 this.xlabels
.push(label
);
531 MochiKit
.DOM
.appendChildNodes(this.container
, label
);
534 var label
= this.createSVGElement("text", svgattrib
);
535 label
.appendChild(this.document
.createTextNode(this.layout
.xticks
[i
][1]))
536 this.root
.appendChild(label
);
543 PlotKit
.SVGRenderer
.prototype._renderBackground
= function() {
544 var opts
= {"stroke": "none",
545 "fill": this.options
.backgroundColor
.toRGBString()
547 this._drawRect(0, 0, this.width
, this.height
, opts
);
550 PlotKit
.SVGRenderer
.prototype._drawRect
= function(x
, y
, w
, h
, moreattrs
) {
551 var attrs
= {x
: x
+ "px", y
: y
+ "px", width
: w
+ "px", height
: h
+ "px"};
553 MochiKit
.Base
.update(attrs
, moreattrs
);
555 var elem
= this.createSVGElement("rect", attrs
);
556 this.root
.appendChild(elem
);
559 PlotKit
.SVGRenderer
.prototype._drawLine
= function(x1
, y1
, x2
, y2
, moreattrs
) {
560 var attrs
= {x1
: x1
+ "px", y1
: y1
+ "px", x2
: x2
+ "px", y2
: y2
+ "px"};
562 MochiKit
.Base
.update(attrs
, moreattrs
);
564 var elem
= this.createSVGElement("line", attrs
);
565 this.root
.appendChild(elem
);
568 PlotKit
.SVGRenderer
.prototype.clear
= function() {
569 while(this.element
.firstChild
) {
570 this.element
.removeChild(this.element
.firstChild
);
573 if (this.options
.axisLabelUseDiv
) {
574 for (var i
= 0; i
< this.xlabels
.length
; i
++) {
575 MochiKit
.DOM
.removeElement(this.xlabels
[i
]);
577 for (var i
= 0; i
< this.ylabels
.length
; i
++) {
578 MochiKit
.DOM
.removeElement(this.ylabels
[i
]);
581 this.xlabels
= new Array();
582 this.ylabels
= new Array();
586 PlotKit
.SVGRenderer
.prototype.createSVGElement
= function(name
, attrs
) {
587 var isNil
= MochiKit
.Base
.isUndefinedOrNull
;
589 var doc
= isNil(this.document
) ? document
: this.document
;
592 elem
= doc
.createElementNS(PlotKit
.SVGRenderer
.SVGNS
, name
);
595 elem
= doc
.createElement(name
);
596 elem
.setAttribute("xmlns", PlotKit
.SVGRenderer
.SVGNS
);
600 MochiKit
.DOM
.updateNodeAttributes(elem
, attrs
);
602 // TODO: we don't completely emulate the MochiKit.DOM.createElement
603 // as we don't care about nodes contained. We really should though.
610 PlotKit
.SVGRenderer
.SVG
= function(attrs
) {
611 // we have to do things differently for IE+AdobeSVG.
612 // My guess this works (via trial and error) is that we need to
613 // have an SVG object in order to use SVGDocument.createElementNS
614 // but IE doesn't allow us to that.
616 var ie
= navigator
.appVersion
.match(/MSIE (\d\.\d)/);
617 var opera
= (navigator
.userAgent
.toLowerCase().indexOf("opera") != -1);
618 if (ie
&& (ie
[1] >= 6) && (!opera
)) {
619 var width
= attrs
["width"] ? attrs
["width"] : "100";
620 var height
= attrs
["height"] ? attrs
["height"] : "100";
621 var eid
= attrs
["id"] ? attrs
["id"] : "notunique";
623 var html
= '<svg:svg width="' + width
+ '" height="' + height
+ '" ';
624 html
+= 'id="' + eid
+ '" version="1.1" baseProfile="full" />';
626 var canvas
= document
.createElement(html
);
628 // create embedded SVG inside SVG.
629 var group
= canvas
.getSVGDocument().createElementNS(PlotKit
.SVGRenderer
.SVGNS
, "svg");
630 group
.setAttribute("width", width
);
631 group
.setAttribute("height", height
);
632 canvas
.getSVGDocument().appendChild(group
);
637 return PlotKit
.SVGRenderer
.prototype.createSVGElement("svg", attrs
);
641 PlotKit
.SVGRenderer
.isSupported
= function() {
642 var isOpera
= (navigator
.userAgent
.toLowerCase().indexOf("opera") != -1);
643 var ieVersion
= navigator
.appVersion
.match(/MSIE (\d\.\d)/);
644 var safariVersion
= navigator
.userAgent
.match(/AppleWebKit\/(\d
+)/);
645 var operaVersion
= navigator
.userAgent
.match(/Opera\/(\d
*\.\d
*)/);
646 var mozillaVersion
= navigator
.userAgent
.match(/rv:(\d*\.\d*).*Gecko/);
647 var svgFeature
= "http://www.w3.org/TR/SVG11/feature#SVG";
649 if (ieVersion
&& (ieVersion
[1] >= 6) && !isOpera
) {
650 return document
.implementation
.hasFeature(svgFeature
,"1.1");
652 var dummysvg = document.createElement('<svg:svg width="1" height="1" baseProfile="full" version="1.1" id="dummy">');
654 dummysvg.getSVGDocument();
665 /* support not really there yet. no text and paths are buggy
666 if (safariVersion && (safariVersion[1] > 419))
670 if (operaVersion
&& (operaVersion
[1] > 8.9))
673 if (mozillaVersion
&& (mozillaVersion
> 1.7))
679 // Namespace Iniitialisation
682 PlotKit
.SVG
.SVGRenderer
= PlotKit
.SVGRenderer
;
684 PlotKit
.SVG
.EXPORT
= [
688 PlotKit
.SVG
.EXPORT_OK
= [
692 PlotKit
.SVG
.__new__
= function() {
693 var m
= MochiKit
.Base
;
695 m
.nameFunctions(this);
698 ":common": this.EXPORT
,
699 ":all": m
.concat(this.EXPORT
, this.EXPORT_OK
)
703 PlotKit
.SVG
.__new__();
704 MochiKit
.Base
._exportSymbols(this, PlotKit
.SVG
);